Skip to content

Commit f94fbd8

Browse files
committed
GCS: Allow no-auth for testing purposes
Although there is no "official" Google Cloud Storage emulator available yet, there is [one available](https://github.com/oittaa/gcp-storage-emulator) that allows at least some basic testing. To use an emulator, the client needs to be configured to use no authentication, otherwise it will fallback to "automatic credential detection".
1 parent 6902571 commit f94fbd8

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

gcp/src/main/java/org/apache/iceberg/gcp/GCPProperties.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
*/
1919
package org.apache.iceberg.gcp;
2020

21+
import com.google.api.client.util.Preconditions;
2122
import java.io.Serializable;
2223
import java.util.Date;
2324
import java.util.Map;
2425
import java.util.Optional;
2526
import org.apache.iceberg.util.PropertyUtil;
2627

2728
public class GCPProperties implements Serializable {
29+
2830
// Service Options
2931
public static final String GCS_PROJECT_ID = "gcs.project-id";
3032
public static final String GCS_CLIENT_LIB_TOKEN = "gcs.client-lib-token";
@@ -40,6 +42,8 @@ public class GCPProperties implements Serializable {
4042

4143
public static final String GCS_OAUTH2_TOKEN = "gcs.oauth2.token";
4244
public static final String GCS_OAUTH2_TOKEN_EXPIRES_AT = "gcs.oauth2.token-expires-at";
45+
// Boolean to explicitly configure "no authentication" for testing purposes using a GCS emulator
46+
public static final String GCS_NO_AUTH = "gcs.no-auth";
4347

4448
/** Configure the batch size used when deleting multiple files from a given GCS bucket */
4549
public static final String GCS_DELETE_BATCH_SIZE = "gcs.delete.batch-size";
@@ -60,6 +64,7 @@ public class GCPProperties implements Serializable {
6064
private Integer gcsChannelReadChunkSize;
6165
private Integer gcsChannelWriteChunkSize;
6266

67+
private boolean gcsNoAuth;
6368
private String gcsOAuth2Token;
6469
private Date gcsOAuth2TokenExpiresAt;
6570

@@ -90,6 +95,10 @@ public GCPProperties(Map<String, String> properties) {
9095
gcsOAuth2TokenExpiresAt =
9196
new Date(Long.parseLong(properties.get(GCS_OAUTH2_TOKEN_EXPIRES_AT)));
9297
}
98+
gcsNoAuth = Boolean.parseBoolean(properties.getOrDefault(GCS_NO_AUTH, "false"));
99+
Preconditions.checkState(
100+
!(gcsOAuth2Token != null && gcsNoAuth),
101+
"Must not configure " + GCS_NO_AUTH + " and " + GCS_OAUTH2_TOKEN);
93102

94103
gcsDeleteBatchSize =
95104
PropertyUtil.propertyAsInt(
@@ -132,6 +141,10 @@ public Optional<String> oauth2Token() {
132141
return Optional.ofNullable(gcsOAuth2Token);
133142
}
134143

144+
public boolean noAuth() {
145+
return gcsNoAuth;
146+
}
147+
135148
public Optional<Date> oauth2TokenExpiresAt() {
136149
return Optional.ofNullable(gcsOAuth2TokenExpiresAt);
137150
}

gcp/src/main/java/org/apache/iceberg/gcp/gcs/GCSFileIO.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import com.google.auth.oauth2.AccessToken;
2222
import com.google.auth.oauth2.OAuth2Credentials;
23+
import com.google.cloud.NoCredentials;
2324
import com.google.cloud.storage.Blob;
2425
import com.google.cloud.storage.BlobId;
2526
import com.google.cloud.storage.Storage;
@@ -55,6 +56,7 @@
5556
* Overview</a>
5657
*/
5758
public class GCSFileIO implements DelegateFileIO {
59+
5860
private static final Logger LOG = LoggerFactory.getLogger(GCSFileIO.class);
5961
private static final String DEFAULT_METRICS_IMPL =
6062
"org.apache.iceberg.hadoop.HadoopMetricsContext";
@@ -141,10 +143,18 @@ public void initialize(Map<String, String> props) {
141143
gcpProperties.clientLibToken().ifPresent(builder::setClientLibToken);
142144
gcpProperties.serviceHost().ifPresent(builder::setHost);
143145

146+
// Google Cloud APIs default to automatically detect the credentials to use, which is
147+
// in most cases the convenient way, especially in GCP.
148+
// See javadoc of com.google.auth.oauth2.GoogleCredentials.getApplicationDefault().
149+
if (gcpProperties.noAuth()) {
150+
// Explicitly allow "no credentials" for testing purposes.
151+
builder.setCredentials(NoCredentials.getInstance());
152+
}
144153
gcpProperties
145154
.oauth2Token()
146155
.ifPresent(
147156
token -> {
157+
// Explicitly configure an OAuth token.
148158
AccessToken accessToken =
149159
new AccessToken(token, gcpProperties.oauth2TokenExpiresAt().orElse(null));
150160
builder.setCredentials(OAuth2Credentials.create(accessToken));

0 commit comments

Comments
 (0)