Skip to content

Commit 8dc9eac

Browse files
authored
Core: Add credentials to loadTable / loadView responses (#11173)
1 parent 44233fa commit 8dc9eac

File tree

9 files changed

+555
-2
lines changed

9 files changed

+555
-2
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.iceberg.rest.credentials;
20+
21+
import java.util.Map;
22+
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
23+
import org.immutables.value.Value;
24+
25+
@Value.Immutable
26+
public interface Credential {
27+
String prefix();
28+
29+
Map<String, String> config();
30+
31+
@Value.Check
32+
default void validate() {
33+
Preconditions.checkArgument(!prefix().isEmpty(), "Invalid prefix: must be non-empty");
34+
Preconditions.checkArgument(!config().isEmpty(), "Invalid config: must be non-empty");
35+
}
36+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.iceberg.rest.credentials;
20+
21+
import com.fasterxml.jackson.core.JsonGenerator;
22+
import com.fasterxml.jackson.databind.JsonNode;
23+
import java.io.IOException;
24+
import java.util.Map;
25+
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
26+
import org.apache.iceberg.util.JsonUtil;
27+
28+
public class CredentialParser {
29+
private static final String PREFIX = "prefix";
30+
private static final String CONFIG = "config";
31+
32+
private CredentialParser() {}
33+
34+
public static String toJson(Credential credential) {
35+
return toJson(credential, false);
36+
}
37+
38+
public static String toJson(Credential credential, boolean pretty) {
39+
return JsonUtil.generate(gen -> toJson(credential, gen), pretty);
40+
}
41+
42+
public static void toJson(Credential credential, JsonGenerator gen) throws IOException {
43+
Preconditions.checkArgument(null != credential, "Invalid credential: null");
44+
45+
gen.writeStartObject();
46+
47+
gen.writeStringField(PREFIX, credential.prefix());
48+
JsonUtil.writeStringMap(CONFIG, credential.config(), gen);
49+
50+
gen.writeEndObject();
51+
}
52+
53+
public static Credential fromJson(String json) {
54+
return JsonUtil.parse(json, CredentialParser::fromJson);
55+
}
56+
57+
public static Credential fromJson(JsonNode json) {
58+
Preconditions.checkArgument(null != json, "Cannot parse credential from null object");
59+
String prefix = JsonUtil.getString(PREFIX, json);
60+
Map<String, String> config = JsonUtil.getStringMap(CONFIG, json);
61+
return ImmutableCredential.builder().prefix(prefix).config(config).build();
62+
}
63+
}

core/src/main/java/org/apache/iceberg/rest/responses/LoadTableResponse.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@
1818
*/
1919
package org.apache.iceberg.rest.responses;
2020

21+
import java.util.List;
2122
import java.util.Map;
2223
import org.apache.iceberg.TableMetadata;
2324
import org.apache.iceberg.relocated.com.google.common.base.MoreObjects;
2425
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
26+
import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
2527
import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
28+
import org.apache.iceberg.relocated.com.google.common.collect.Lists;
2629
import org.apache.iceberg.relocated.com.google.common.collect.Maps;
2730
import org.apache.iceberg.rest.RESTResponse;
31+
import org.apache.iceberg.rest.credentials.Credential;
2832

2933
/**
3034
* A REST response that is used when a table is successfully loaded.
@@ -40,16 +44,21 @@ public class LoadTableResponse implements RESTResponse {
4044
private TableMetadata metadata;
4145
private Map<String, String> config;
4246
private TableMetadata metadataWithLocation;
47+
private List<Credential> credentials;
4348

4449
public LoadTableResponse() {
4550
// Required for Jackson deserialization
4651
}
4752

4853
private LoadTableResponse(
49-
String metadataLocation, TableMetadata metadata, Map<String, String> config) {
54+
String metadataLocation,
55+
TableMetadata metadata,
56+
Map<String, String> config,
57+
List<Credential> credentials) {
5058
this.metadataLocation = metadataLocation;
5159
this.metadata = metadata;
5260
this.config = config;
61+
this.credentials = credentials;
5362
}
5463

5564
@Override
@@ -74,6 +83,10 @@ public Map<String, String> config() {
7483
return config != null ? config : ImmutableMap.of();
7584
}
7685

86+
public List<Credential> credentials() {
87+
return credentials != null ? credentials : ImmutableList.of();
88+
}
89+
7790
@Override
7891
public String toString() {
7992
return MoreObjects.toStringHelper(this)
@@ -91,6 +104,7 @@ public static class Builder {
91104
private String metadataLocation;
92105
private TableMetadata metadata;
93106
private final Map<String, String> config = Maps.newHashMap();
107+
private final List<Credential> credentials = Lists.newArrayList();
94108

95109
private Builder() {}
96110

@@ -110,9 +124,19 @@ public Builder addAllConfig(Map<String, String> properties) {
110124
return this;
111125
}
112126

127+
public Builder addCredential(Credential credential) {
128+
credentials.add(credential);
129+
return this;
130+
}
131+
132+
public Builder addAllCredentials(List<Credential> credentialsToAdd) {
133+
credentials.addAll(credentialsToAdd);
134+
return this;
135+
}
136+
113137
public LoadTableResponse build() {
114138
Preconditions.checkNotNull(metadata, "Invalid metadata: null");
115-
return new LoadTableResponse(metadataLocation, metadata, config);
139+
return new LoadTableResponse(metadataLocation, metadata, config, credentials);
116140
}
117141
}
118142
}

core/src/main/java/org/apache/iceberg/rest/responses/LoadTableResponseParser.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@
2424
import org.apache.iceberg.TableMetadata;
2525
import org.apache.iceberg.TableMetadataParser;
2626
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
27+
import org.apache.iceberg.rest.credentials.Credential;
28+
import org.apache.iceberg.rest.credentials.CredentialParser;
2729
import org.apache.iceberg.util.JsonUtil;
2830

2931
public class LoadTableResponseParser {
3032

3133
private static final String METADATA_LOCATION = "metadata-location";
3234
private static final String METADATA = "metadata";
3335
private static final String CONFIG = "config";
36+
private static final String STORAGE_CREDENTIALS = "storage-credentials";
3437

3538
private LoadTableResponseParser() {}
3639

@@ -58,6 +61,15 @@ public static void toJson(LoadTableResponse response, JsonGenerator gen) throws
5861
JsonUtil.writeStringMap(CONFIG, response.config(), gen);
5962
}
6063

64+
if (!response.credentials().isEmpty()) {
65+
gen.writeArrayFieldStart(STORAGE_CREDENTIALS);
66+
for (Credential credential : response.credentials()) {
67+
CredentialParser.toJson(credential, gen);
68+
}
69+
70+
gen.writeEndArray();
71+
}
72+
6173
gen.writeEndObject();
6274
}
6375

@@ -85,6 +97,16 @@ public static LoadTableResponse fromJson(JsonNode json) {
8597
builder.addAllConfig(JsonUtil.getStringMap(CONFIG, json));
8698
}
8799

100+
if (json.hasNonNull(STORAGE_CREDENTIALS)) {
101+
JsonNode credentials = JsonUtil.get(STORAGE_CREDENTIALS, json);
102+
Preconditions.checkArgument(
103+
credentials.isArray(), "Cannot parse credentials from non-array: %s", credentials);
104+
105+
for (JsonNode credential : credentials) {
106+
builder.addCredential(CredentialParser.fromJson(credential));
107+
}
108+
}
109+
88110
return builder.build();
89111
}
90112
}

core/src/main/java/org/apache/iceberg/rest/responses/LoadViewResponse.java

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

21+
import java.util.List;
2122
import java.util.Map;
23+
import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
2224
import org.apache.iceberg.rest.RESTResponse;
25+
import org.apache.iceberg.rest.credentials.Credential;
2326
import org.apache.iceberg.view.ViewMetadata;
2427
import org.immutables.value.Value;
2528

@@ -31,6 +34,11 @@ public interface LoadViewResponse extends RESTResponse {
3134

3235
Map<String, String> config();
3336

37+
@Value.Default
38+
default List<Credential> credentials() {
39+
return ImmutableList.of();
40+
}
41+
3442
@Override
3543
default void validate() {
3644
// nothing to validate as it's not possible to create an invalid instance

core/src/main/java/org/apache/iceberg/rest/responses/LoadViewResponseParser.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import com.fasterxml.jackson.databind.JsonNode;
2323
import java.io.IOException;
2424
import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
25+
import org.apache.iceberg.rest.credentials.Credential;
26+
import org.apache.iceberg.rest.credentials.CredentialParser;
2527
import org.apache.iceberg.util.JsonUtil;
2628
import org.apache.iceberg.view.ViewMetadata;
2729
import org.apache.iceberg.view.ViewMetadataParser;
@@ -31,6 +33,7 @@ public class LoadViewResponseParser {
3133
private static final String METADATA_LOCATION = "metadata-location";
3234
private static final String METADATA = "metadata";
3335
private static final String CONFIG = "config";
36+
private static final String STORAGE_CREDENTIALS = "storage-credentials";
3437

3538
private LoadViewResponseParser() {}
3639

@@ -56,6 +59,15 @@ public static void toJson(LoadViewResponse response, JsonGenerator gen) throws I
5659
JsonUtil.writeStringMap(CONFIG, response.config(), gen);
5760
}
5861

62+
if (!response.credentials().isEmpty()) {
63+
gen.writeArrayFieldStart(STORAGE_CREDENTIALS);
64+
for (Credential credential : response.credentials()) {
65+
CredentialParser.toJson(credential, gen);
66+
}
67+
68+
gen.writeEndArray();
69+
}
70+
5971
gen.writeEndObject();
6072
}
6173

@@ -80,6 +92,16 @@ public static LoadViewResponse fromJson(JsonNode json) {
8092
builder.config(JsonUtil.getStringMap(CONFIG, json));
8193
}
8294

95+
if (json.hasNonNull(STORAGE_CREDENTIALS)) {
96+
JsonNode credentials = JsonUtil.get(STORAGE_CREDENTIALS, json);
97+
Preconditions.checkArgument(
98+
credentials.isArray(), "Cannot parse credentials from non-array: %s", credentials);
99+
100+
for (JsonNode credential : credentials) {
101+
builder.addCredentials(CredentialParser.fromJson(credential));
102+
}
103+
}
104+
83105
return builder.build();
84106
}
85107
}

0 commit comments

Comments
 (0)