Skip to content

Commit 4e57b84

Browse files
committed
Add gcs.auth-type configuration
This makes it easier to add new GCS authentication types in the future. The commit also deprecate `gcs.use-access-token`
1 parent 99b40f8 commit 4e57b84

File tree

4 files changed

+135
-34
lines changed

4 files changed

+135
-34
lines changed

docs/src/main/sphinx/object-storage/file-system-gcs.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,15 @@ Cloud Storage:
7070
- Description
7171
* - `gcs.use-access-token`
7272
- Flag to set usage of a client-provided OAuth 2.0 token to access Google
73-
Cloud Storage. Defaults to `false`.
73+
Cloud Storage. Defaults to `false`, deprecated to use `gcs.auth-type` instead.
74+
* - `gcs.auth-type`
75+
- Authentication type to use for Google Cloud Storage access. Default to `DEFAULT`.
76+
Supported values are:
77+
* `DEFAULT`: loads credentials from the environment. Either `gcs.json-key` or
78+
`gcs.json-key-file-path` can be set in addition to override the default
79+
credentials provider.
80+
* `ACCESS_TOKEN`: usage of client-provided OAuth 2.0 token to access Google
81+
Cloud Storage.
7482
* - `gcs.json-key`
7583
- Your Google Cloud service account key in JSON format. Not to be set together
7684
with `gcs.json-key-file-path`.
@@ -103,7 +111,7 @@ Cloud Storage, make the following edits to your catalog configuration:
103111
- Native property
104112
- Notes
105113
* - `hive.gcs.use-access-token`
106-
- `gcs.use-access-token`
114+
- `gcs.auth-type`
107115
-
108116
* - `hive.gcs.json-key-file-path`
109117
- `gcs.json-key-file-path`

lib/trino-filesystem-gcs/src/main/java/io/trino/filesystem/gcs/GcsFileSystemConfig.java

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,17 @@
2929
import java.util.Optional;
3030
import java.util.concurrent.TimeUnit;
3131

32+
import static com.google.common.base.Preconditions.checkArgument;
3233
import static io.airlift.units.DataSize.Unit.MEGABYTE;
3334

3435
public class GcsFileSystemConfig
3536
{
37+
public enum AuthType
38+
{
39+
ACCESS_TOKEN,
40+
DEFAULT;
41+
}
42+
3643
private DataSize readBlockSize = DataSize.of(2, MEGABYTE);
3744
private DataSize writeBlockSize = DataSize.of(16, MEGABYTE);
3845
private int pageSize = 100;
@@ -41,7 +48,8 @@ public class GcsFileSystemConfig
4148
private String projectId;
4249
private Optional<String> endpoint = Optional.empty();
4350

44-
private boolean useGcsAccessToken;
51+
private Optional<Boolean> useGcsAccessToken = Optional.empty();
52+
private AuthType authType;
4553
private String jsonKey;
4654
private String jsonKeyFilePath;
4755
private int maxRetries = 20;
@@ -134,15 +142,38 @@ public GcsFileSystemConfig setEndpoint(Optional<String> endpoint)
134142
return this;
135143
}
136144

145+
@NotNull
146+
public AuthType getAuthType()
147+
{
148+
return Optional.ofNullable(authType).orElse(AuthType.DEFAULT);
149+
}
150+
151+
@Config("gcs.auth-type")
152+
public GcsFileSystemConfig setAuthType(AuthType authType)
153+
{
154+
checkArgument(useGcsAccessToken.isEmpty(), "Cannot set both gcs.use-access-token and gcs.auth-type");
155+
this.authType = authType;
156+
return this;
157+
}
158+
159+
@Deprecated
137160
public boolean isUseGcsAccessToken()
138161
{
139-
return useGcsAccessToken;
162+
return useGcsAccessToken.orElse(false);
140163
}
141164

165+
@Deprecated
142166
@Config("gcs.use-access-token")
143167
public GcsFileSystemConfig setUseGcsAccessToken(boolean useGcsAccessToken)
144168
{
145-
this.useGcsAccessToken = useGcsAccessToken;
169+
checkArgument(authType == null, "Cannot set both gcs.use-access-token and gcs.auth-type");
170+
this.useGcsAccessToken = Optional.of(useGcsAccessToken);
171+
if (useGcsAccessToken) {
172+
this.authType = AuthType.ACCESS_TOKEN;
173+
}
174+
else {
175+
this.authType = AuthType.DEFAULT;
176+
}
146177
return this;
147178
}
148179

@@ -268,10 +299,10 @@ public boolean isRetryDelayValid()
268299
return minBackoffDelay.compareTo(maxBackoffDelay) <= 0;
269300
}
270301

271-
@AssertTrue(message = "Either gcs.use-access-token or gcs.json-key or gcs.json-key-file-path must be set")
302+
@AssertTrue(message = "Either gcs.auth-type or gcs.json-key or gcs.json-key-file-path must be set")
272303
public boolean isAuthMethodValid()
273304
{
274-
if (useGcsAccessToken) {
305+
if (authType == AuthType.ACCESS_TOKEN) {
275306
return jsonKey == null && jsonKeyFilePath == null;
276307
}
277308

lib/trino-filesystem-gcs/src/main/java/io/trino/filesystem/gcs/GcsFileSystemModule.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
import com.google.inject.Scopes;
1818
import io.airlift.configuration.AbstractConfigurationAwareModule;
1919

20-
import static io.airlift.configuration.ConditionalModule.conditionalModule;
2120
import static io.airlift.configuration.ConfigBinder.configBinder;
21+
import static io.airlift.configuration.SwitchModule.switchModule;
2222

2323
public class GcsFileSystemModule
2424
extends AbstractConfigurationAwareModule
@@ -30,10 +30,12 @@ protected void setup(Binder binder)
3030
binder.bind(GcsStorageFactory.class).in(Scopes.SINGLETON);
3131
binder.bind(GcsFileSystemFactory.class).in(Scopes.SINGLETON);
3232

33-
install(conditionalModule(
33+
install(switchModule(
3434
GcsFileSystemConfig.class,
35-
GcsFileSystemConfig::isUseGcsAccessToken,
36-
_ -> binder.bind(GcsAuth.class).to(GcsAccessTokenAuth.class).in(Scopes.SINGLETON),
37-
_ -> binder.bind(GcsAuth.class).to(GcsDefaultAuth.class).in(Scopes.SINGLETON)));
35+
GcsFileSystemConfig::getAuthType,
36+
type -> switch (type) {
37+
case ACCESS_TOKEN -> _ -> binder.bind(GcsAuth.class).to(GcsAccessTokenAuth.class).in(Scopes.SINGLETON);
38+
case DEFAULT -> _ -> binder.bind(GcsAuth.class).to(GcsDefaultAuth.class).in(Scopes.SINGLETON);
39+
}));
3840
}
3941
}

lib/trino-filesystem-gcs/src/test/java/io/trino/filesystem/gcs/TestGcsFileSystemConfig.java

Lines changed: 82 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.google.common.collect.ImmutableMap;
1717
import io.airlift.units.DataSize;
1818
import io.airlift.units.Duration;
19+
import io.trino.filesystem.gcs.GcsFileSystemConfig.AuthType;
1920
import jakarta.validation.constraints.AssertTrue;
2021
import org.junit.jupiter.api.Test;
2122

@@ -30,32 +31,74 @@
3031
import static io.airlift.units.DataSize.Unit.MEGABYTE;
3132
import static java.util.concurrent.TimeUnit.MILLISECONDS;
3233
import static java.util.concurrent.TimeUnit.SECONDS;
34+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
3335

3436
public class TestGcsFileSystemConfig
3537
{
3638
@Test
3739
void testDefaults()
3840
{
39-
assertRecordedDefaults(recordDefaults(GcsFileSystemConfig.class)
40-
.setReadBlockSize(DataSize.of(2, MEGABYTE))
41-
.setWriteBlockSize(DataSize.of(16, MEGABYTE))
42-
.setPageSize(100)
43-
.setBatchSize(100)
44-
.setProjectId(null)
45-
.setEndpoint(Optional.empty())
46-
.setUseGcsAccessToken(false)
47-
.setJsonKey(null)
48-
.setJsonKeyFilePath(null)
49-
.setMaxRetries(20)
50-
.setBackoffScaleFactor(3.0)
51-
.setMaxRetryTime(new Duration(25, SECONDS))
52-
.setMinBackoffDelay(new Duration(10, MILLISECONDS))
53-
.setMaxBackoffDelay(new Duration(2000, MILLISECONDS))
54-
.setApplicationId("Trino"));
41+
assertThatThrownBy(
42+
() -> assertRecordedDefaults(recordDefaults(GcsFileSystemConfig.class)
43+
.setReadBlockSize(DataSize.of(2, MEGABYTE))
44+
.setWriteBlockSize(DataSize.of(16, MEGABYTE))
45+
.setPageSize(100)
46+
.setBatchSize(100)
47+
.setProjectId(null)
48+
.setEndpoint(Optional.empty())
49+
.setAuthType(null)
50+
.setJsonKey(null)
51+
.setJsonKeyFilePath(null)
52+
.setMaxRetries(20)
53+
.setBackoffScaleFactor(3.0)
54+
.setMaxRetryTime(new Duration(25, SECONDS))
55+
.setMinBackoffDelay(new Duration(10, MILLISECONDS))
56+
.setMaxBackoffDelay(new Duration(2000, MILLISECONDS))
57+
.setApplicationId("Trino")))
58+
.isInstanceOf(AssertionError.class)
59+
// use-access-token is not deprecated and isn't allowed to be set with auth-type
60+
.hasMessage("Untested attributes: [UseGcsAccessToken]");
5561
}
5662

5763
@Test
5864
void testExplicitPropertyMappings()
65+
{
66+
Map<String, String> properties = ImmutableMap.<String, String>builder()
67+
.put("gcs.read-block-size", "51MB")
68+
.put("gcs.write-block-size", "52MB")
69+
.put("gcs.page-size", "10")
70+
.put("gcs.batch-size", "11")
71+
.put("gcs.project-id", "project")
72+
.put("gcs.endpoint", "http://custom.dns.org:8000")
73+
.put("gcs.auth-type", "access_token")
74+
.put("gcs.client.max-retries", "10")
75+
.put("gcs.client.backoff-scale-factor", "4.0")
76+
.put("gcs.client.max-retry-time", "10s")
77+
.put("gcs.client.min-backoff-delay", "20ms")
78+
.put("gcs.client.max-backoff-delay", "20ms")
79+
.put("gcs.application-id", "application id")
80+
.buildOrThrow();
81+
82+
GcsFileSystemConfig expected = new GcsFileSystemConfig()
83+
.setReadBlockSize(DataSize.of(51, MEGABYTE))
84+
.setWriteBlockSize(DataSize.of(52, MEGABYTE))
85+
.setPageSize(10)
86+
.setBatchSize(11)
87+
.setProjectId("project")
88+
.setEndpoint(Optional.of("http://custom.dns.org:8000"))
89+
.setAuthType(AuthType.ACCESS_TOKEN)
90+
.setMaxRetries(10)
91+
.setBackoffScaleFactor(4.0)
92+
.setMaxRetryTime(new Duration(10, SECONDS))
93+
.setMinBackoffDelay(new Duration(20, MILLISECONDS))
94+
.setMaxBackoffDelay(new Duration(20, MILLISECONDS))
95+
.setApplicationId("application id");
96+
assertFullMapping(properties, expected, Set.of("gcs.json-key", "gcs.json-key-file-path", "gcs.use-access-token"));
97+
}
98+
99+
// backwards compatibility test, remove if use-access-token is removed
100+
@Test
101+
void testExplicitPropertyMappingsWithDeprecatedUseAccessToken()
59102
{
60103
Map<String, String> properties = ImmutableMap.<String, String>builder()
61104
.put("gcs.read-block-size", "51MB")
@@ -87,34 +130,51 @@ void testExplicitPropertyMappings()
87130
.setMinBackoffDelay(new Duration(20, MILLISECONDS))
88131
.setMaxBackoffDelay(new Duration(20, MILLISECONDS))
89132
.setApplicationId("application id");
90-
assertFullMapping(properties, expected, Set.of("gcs.json-key", "gcs.json-key-file-path"));
133+
assertFullMapping(properties, expected, Set.of("gcs.json-key", "gcs.json-key-file-path", "gcs.auth-type"));
134+
}
135+
136+
@Test
137+
void testSetUseGcsAccessTokenWithAuthType()
138+
{
139+
assertThatThrownBy(() -> new GcsFileSystemConfig().setAuthType(AuthType.ACCESS_TOKEN).setUseGcsAccessToken(true))
140+
.isInstanceOf(IllegalArgumentException.class)
141+
.hasMessage("Cannot set both gcs.use-access-token and gcs.auth-type");
142+
assertThatThrownBy(() -> new GcsFileSystemConfig().setAuthType(AuthType.DEFAULT).setUseGcsAccessToken(false))
143+
.isInstanceOf(IllegalArgumentException.class)
144+
.hasMessage("Cannot set both gcs.use-access-token and gcs.auth-type");
145+
assertThatThrownBy(() -> new GcsFileSystemConfig().setUseGcsAccessToken(true).setAuthType(AuthType.ACCESS_TOKEN))
146+
.isInstanceOf(IllegalArgumentException.class)
147+
.hasMessage("Cannot set both gcs.use-access-token and gcs.auth-type");
148+
assertThatThrownBy(() -> new GcsFileSystemConfig().setUseGcsAccessToken(true).setAuthType(AuthType.DEFAULT))
149+
.isInstanceOf(IllegalArgumentException.class)
150+
.hasMessage("Cannot set both gcs.use-access-token and gcs.auth-type");
91151
}
92152

93153
@Test
94154
public void testValidation()
95155
{
96156
assertFailsValidation(
97157
new GcsFileSystemConfig()
98-
.setUseGcsAccessToken(true)
158+
.setAuthType(AuthType.ACCESS_TOKEN)
99159
.setJsonKey("{}}"),
100160
"authMethodValid",
101-
"Either gcs.use-access-token or gcs.json-key or gcs.json-key-file-path must be set",
161+
"Either gcs.auth-type or gcs.json-key or gcs.json-key-file-path must be set",
102162
AssertTrue.class);
103163

104164
assertFailsValidation(
105165
new GcsFileSystemConfig()
106-
.setUseGcsAccessToken(true)
166+
.setAuthType(AuthType.ACCESS_TOKEN)
107167
.setJsonKeyFilePath("/dev/null"),
108168
"authMethodValid",
109-
"Either gcs.use-access-token or gcs.json-key or gcs.json-key-file-path must be set",
169+
"Either gcs.auth-type or gcs.json-key or gcs.json-key-file-path must be set",
110170
AssertTrue.class);
111171

112172
assertFailsValidation(
113173
new GcsFileSystemConfig()
114174
.setJsonKey("{}")
115175
.setJsonKeyFilePath("/dev/null"),
116176
"authMethodValid",
117-
"Either gcs.use-access-token or gcs.json-key or gcs.json-key-file-path must be set",
177+
"Either gcs.auth-type or gcs.json-key or gcs.json-key-file-path must be set",
118178
AssertTrue.class);
119179

120180
assertFailsValidation(

0 commit comments

Comments
 (0)