Skip to content

Commit 81ddf32

Browse files
authored
Implement PolicyCatalogAdapter (#1438)
1 parent 037cf38 commit 81ddf32

File tree

14 files changed

+941
-8
lines changed

14 files changed

+941
-8
lines changed

integration-tests/src/main/java/org/apache/polaris/service/it/env/PolarisClient.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ public GenericTableApi genericTableApi(ClientCredentials credentials) {
116116
client, endpoints, obtainToken(credentials), endpoints.catalogApiEndpoint());
117117
}
118118

119+
public PolicyApi policyApi(PrincipalWithCredentials principal) {
120+
return new PolicyApi(client, endpoints, obtainToken(principal), endpoints.catalogApiEndpoint());
121+
}
122+
123+
public PolicyApi policyApi(ClientCredentials credentials) {
124+
return new PolicyApi(
125+
client, endpoints, obtainToken(credentials), endpoints.catalogApiEndpoint());
126+
}
127+
119128
/**
120129
* Requests an access token from the Polaris server for the client ID/secret pair that is part of
121130
* the given principal data object.
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
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.polaris.service.it.env;
20+
21+
import jakarta.ws.rs.client.Client;
22+
import jakarta.ws.rs.client.Entity;
23+
import jakarta.ws.rs.core.Response;
24+
import java.net.URI;
25+
import java.util.HashMap;
26+
import java.util.List;
27+
import java.util.Map;
28+
import org.apache.iceberg.catalog.Namespace;
29+
import org.apache.iceberg.rest.RESTUtil;
30+
import org.apache.polaris.core.policy.PolicyType;
31+
import org.apache.polaris.service.types.ApplicablePolicy;
32+
import org.apache.polaris.service.types.AttachPolicyRequest;
33+
import org.apache.polaris.service.types.CreatePolicyRequest;
34+
import org.apache.polaris.service.types.DetachPolicyRequest;
35+
import org.apache.polaris.service.types.GetApplicablePoliciesResponse;
36+
import org.apache.polaris.service.types.ListPoliciesResponse;
37+
import org.apache.polaris.service.types.LoadPolicyResponse;
38+
import org.apache.polaris.service.types.Policy;
39+
import org.apache.polaris.service.types.PolicyAttachmentTarget;
40+
import org.apache.polaris.service.types.PolicyIdentifier;
41+
import org.apache.polaris.service.types.UpdatePolicyRequest;
42+
import org.assertj.core.api.Assertions;
43+
44+
public class PolicyApi extends RestApi {
45+
PolicyApi(Client client, PolarisApiEndpoints endpoints, String authToken, URI uri) {
46+
super(client, endpoints, authToken, uri);
47+
}
48+
49+
public void purge(String catalog, Namespace ns) {
50+
listPolicies(catalog, ns).forEach(t -> dropPolicy(catalog, t));
51+
}
52+
53+
public List<PolicyIdentifier> listPolicies(String catalog, Namespace namespace) {
54+
return listPolicies(catalog, namespace, null);
55+
}
56+
57+
public List<PolicyIdentifier> listPolicies(String catalog, Namespace namespace, PolicyType type) {
58+
String ns = RESTUtil.encodeNamespace(namespace);
59+
Map<String, String> queryParams = new HashMap<>();
60+
if (type != null) {
61+
queryParams.put("policyType", type.getName());
62+
}
63+
try (Response res =
64+
request(
65+
"polaris/v1/{cat}/namespaces/{ns}/policies",
66+
Map.of("cat", catalog, "ns", ns),
67+
queryParams)
68+
.get()) {
69+
Assertions.assertThat(res.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
70+
return res.readEntity(ListPoliciesResponse.class).getIdentifiers().stream().toList();
71+
}
72+
}
73+
74+
public void dropPolicy(String catalog, PolicyIdentifier policyIdentifier) {
75+
String ns = RESTUtil.encodeNamespace(policyIdentifier.getNamespace());
76+
try (Response res =
77+
request(
78+
"polaris/v1/{cat}/namespaces/{ns}/policies/{policy}",
79+
Map.of("cat", catalog, "ns", ns, "policy", policyIdentifier.getName()))
80+
.delete()) {
81+
Assertions.assertThat(res.getStatus()).isEqualTo(Response.Status.NO_CONTENT.getStatusCode());
82+
}
83+
}
84+
85+
public Policy loadPolicy(String catalog, PolicyIdentifier policyIdentifier) {
86+
String ns = RESTUtil.encodeNamespace(policyIdentifier.getNamespace());
87+
try (Response res =
88+
request(
89+
"polaris/v1/{cat}/namespaces/{ns}/policies/{policy}",
90+
Map.of("cat", catalog, "ns", ns, "policy", policyIdentifier.getName()))
91+
.get()) {
92+
Assertions.assertThat(res.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
93+
return res.readEntity(LoadPolicyResponse.class).getPolicy();
94+
}
95+
}
96+
97+
public Policy createPolicy(
98+
String catalog,
99+
PolicyIdentifier policyIdentifier,
100+
PolicyType policyType,
101+
String content,
102+
String description) {
103+
String ns = RESTUtil.encodeNamespace(policyIdentifier.getNamespace());
104+
CreatePolicyRequest request =
105+
CreatePolicyRequest.builder()
106+
.setType(policyType.getName())
107+
.setName(policyIdentifier.getName())
108+
.setDescription(description)
109+
.setContent(content)
110+
.build();
111+
try (Response res =
112+
request("polaris/v1/{cat}/namespaces/{ns}/policies", Map.of("cat", catalog, "ns", ns))
113+
.post(Entity.json(request))) {
114+
Assertions.assertThat(res.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
115+
return res.readEntity(LoadPolicyResponse.class).getPolicy();
116+
}
117+
}
118+
119+
public Policy updatePolicy(
120+
String catalog,
121+
PolicyIdentifier policyIdentifier,
122+
String newContent,
123+
String newDescription,
124+
int currentPolicyVersion) {
125+
String ns = RESTUtil.encodeNamespace(policyIdentifier.getNamespace());
126+
UpdatePolicyRequest request =
127+
UpdatePolicyRequest.builder()
128+
.setContent(newContent)
129+
.setDescription(newDescription)
130+
.setCurrentPolicyVersion(currentPolicyVersion)
131+
.build();
132+
try (Response res =
133+
request(
134+
"polaris/v1/{cat}/namespaces/{ns}/policies/{policy}",
135+
Map.of("cat", catalog, "ns", ns, "policy", policyIdentifier.getName()))
136+
.put(Entity.json(request))) {
137+
Assertions.assertThat(res.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
138+
return res.readEntity(LoadPolicyResponse.class).getPolicy();
139+
}
140+
}
141+
142+
public void attachPolicy(
143+
String catalog,
144+
PolicyIdentifier policyIdentifier,
145+
PolicyAttachmentTarget target,
146+
Map<String, String> parameters) {
147+
String ns = RESTUtil.encodeNamespace(policyIdentifier.getNamespace());
148+
AttachPolicyRequest request =
149+
AttachPolicyRequest.builder().setTarget(target).setParameters(parameters).build();
150+
try (Response res =
151+
request(
152+
"polaris/v1/{cat}/namespaces/{ns}/policies/{policy}/mappings",
153+
Map.of("cat", catalog, "ns", ns, "policy", policyIdentifier.getName()))
154+
.put(Entity.json(request))) {
155+
Assertions.assertThat(res.getStatus()).isEqualTo(Response.Status.NO_CONTENT.getStatusCode());
156+
}
157+
}
158+
159+
public void detachPolicy(
160+
String catalog, PolicyIdentifier policyIdentifier, PolicyAttachmentTarget target) {
161+
String ns = RESTUtil.encodeNamespace(policyIdentifier.getNamespace());
162+
DetachPolicyRequest request = DetachPolicyRequest.builder().setTarget(target).build();
163+
try (Response res =
164+
request(
165+
"polaris/v1/{cat}/namespaces/{ns}/policies/{policy}/mappings",
166+
Map.of("cat", catalog, "ns", ns, "policy", policyIdentifier.getName()))
167+
.post(Entity.json(request))) {
168+
Assertions.assertThat(res.getStatus()).isEqualTo(Response.Status.NO_CONTENT.getStatusCode());
169+
}
170+
}
171+
172+
public List<ApplicablePolicy> getApplicablePolicies(
173+
String catalog, Namespace namespace, String targetName, PolicyType policyType) {
174+
String ns = namespace != null ? RESTUtil.encodeNamespace(namespace) : null;
175+
Map<String, String> queryParams = new HashMap<>();
176+
if (ns != null) {
177+
queryParams.put("namespace", ns);
178+
}
179+
if (targetName != null) {
180+
queryParams.put("target-name", targetName);
181+
}
182+
if (policyType != null) {
183+
queryParams.put("policyType", policyType.getName());
184+
}
185+
186+
try (Response res =
187+
request("polaris/v1/{cat}/applicable-policies", Map.of("cat", catalog), queryParams)
188+
.get()) {
189+
Assertions.assertThat(res.getStatus()).isEqualTo(Response.Status.OK.getStatusCode());
190+
return res.readEntity(GetApplicablePoliciesResponse.class).getApplicablePolicies().stream()
191+
.toList();
192+
}
193+
}
194+
}

0 commit comments

Comments
 (0)