Skip to content

Commit d2ecece

Browse files
committed
Merge branch 'main' of github.com:apache/polaris into generic-federation
2 parents 4feb77b + 9e6226a commit d2ecece

File tree

37 files changed

+524
-104
lines changed

37 files changed

+524
-104
lines changed

helm/polaris/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ A Helm chart for Apache Polaris (incubating).
4848

4949
### Optional
5050

51-
When using EclipseLink backed metastore a custom `persistence.xml` is required, a Kubernetes Secret must be created for it. Below is a sample command:
51+
When using a custom `persistence.xml`, a Kubernetes Secret must be created for it. Below is a sample command:
5252
```bash
5353
kubectl create secret generic polaris-secret -n polaris --from-file=persistence.xml
5454
```
@@ -67,7 +67,7 @@ helm unittest helm/polaris
6767
The below instructions assume Kind and Helm are installed.
6868

6969
Simply run the `run.sh` script from the Polaris repo root, making sure to specify the
70-
`--eclipse-link-deps` if using EclipseLink backed metastore, option:
70+
`--eclipse-link-deps` option:
7171

7272
```bash
7373
./run.sh
@@ -186,8 +186,8 @@ kubectl delete namespace polaris
186186

187187
## Values
188188

189-
Key | Type | Default | Description |
190-
|-----|------|-----|-------------|
189+
| Key | Type | Default | Description |
190+
|-----|------|---------|-------------|
191191
| advancedConfig | object | `{}` | Advanced configuration. You can pass here any valid Polaris or Quarkus configuration property. Any property that is defined here takes precedence over all the other configuration values generated by this chart. Properties can be passed "flattened" or as nested YAML objects (see examples below). Note: values should be strings; avoid using numbers, booleans, or other types. |
192192
| affinity | object | `{}` | Affinity and anti-affinity for polaris pods. See https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity. |
193193
| authentication | object | `{"authenticator":{"type":"default"},"tokenBroker":{"maxTokenGeneration":"PT1H","secret":{"name":null,"privateKey":"private.pem","publicKey":"public.pem","secretKey":"secret"},"type":"rsa-key-pair"},"tokenService":{"type":"default"}}` | Polaris authentication configuration. |
@@ -343,4 +343,4 @@ kubectl delete namespace polaris
343343
| tracing.attributes | object | `{}` | Resource attributes to identify the polaris service among other tracing sources. See https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/#service. If left empty, traces will be attached to a service named "Apache Polaris"; to change this, provide a service.name attribute here. |
344344
| tracing.enabled | bool | `false` | Specifies whether tracing for the polaris server should be enabled. |
345345
| tracing.endpoint | string | `"http://otlp-collector:4317"` | The collector endpoint URL to connect to (required). The endpoint URL must have either the http:// or the https:// scheme. The collector must talk the OpenTelemetry protocol (OTLP) and the port must be its gRPC port (by default 4317). See https://quarkus.io/guides/opentelemetry for more information. |
346-
| tracing.sample | string | `"1.0d"` | Which requests should be sampled. Valid values are: "all", "none", or a ratio between 0.0 and "1.0d" (inclusive). E.g. "0.5d" means that 50% of the requests will be sampled. Note: avoid entering numbers here, always prefer a string representation of the ratio. |
346+
| tracing.sample | string | `"1.0d"` | Which requests should be sampled. Valid values are: "all", "none", or a ratio between 0.0 and "1.0d" (inclusive). E.g. "0.5d" means that 50% of the requests will be sampled. Note: avoid entering numbers here, always prefer a string representation of the ratio. |

helm/polaris/templates/configmap.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ data:
3636
{{- $_ = set $map "polaris.realm-context.realms" (join "," .Values.realmContext.realms) -}}
3737
3838
{{- /* Features */ -}}
39-
{{- range $k, $v := .Values.features.defaults -}}
40-
{{- $_ = set $map (printf "polaris.features.defaults.\"%s\"" $k) (toJson $v) -}}
39+
{{- range $k, $v := .Values.features -}}
40+
{{- $_ = set $map (printf "polaris.features.\"%s\"" $k) (toJson $v) -}}
4141
{{- end -}}
4242
{{- range $realm, $overrides := .Values.features.realmOverrides -}}
4343
{{- range $k, $v := $overrides -}}
44-
{{- $_ = set $map (printf "polaris.config.realm-overrides.\"%s\".\"%s\"" $realm $k) (toJson $v) -}}
44+
{{- $_ = set $map (printf "polaris.features.realm-overrides.\"%s\".\"%s\"" $realm $k) (toJson $v) -}}
4545
{{- end -}}
4646
{{- end -}}
4747

helm/polaris/tests/configmap_test.yaml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,18 @@ tests:
8989
- it: should configure features
9090
set:
9191
features:
92-
defaults:
93-
feature1: true
94-
feature2: 42
92+
feature1: true
93+
feature2: 42
9594
realmOverrides:
9695
realm1:
9796
feature1: false
9897
realm2:
9998
feature2: 43
10099
asserts:
101-
- matchRegex: { path: 'data["application.properties"]', pattern: "polaris.features.defaults.\"feature1\"=true" }
102-
- matchRegex: { path: 'data["application.properties"]', pattern: "polaris.features.defaults.\"feature2\"=42" }
103-
- matchRegex: { path: 'data["application.properties"]', pattern: "polaris.config.realm-overrides.\"realm1\".\"feature1\"=false" }
104-
- matchRegex: { path: 'data["application.properties"]', pattern: "polaris.config.realm-overrides.\"realm2\".\"feature2\"=43" }
100+
- matchRegex: { path: 'data["application.properties"]', pattern: "polaris.features.\"feature1\"=true" }
101+
- matchRegex: { path: 'data["application.properties"]', pattern: "polaris.features.\"feature2\"=42" }
102+
- matchRegex: { path: 'data["application.properties"]', pattern: "polaris.features.realm-overrides.\"realm1\".\"feature1\"=false" }
103+
- matchRegex: { path: 'data["application.properties"]', pattern: "polaris.features.realm-overrides.\"realm2\".\"feature2\"=43" }
105104

106105
- it: should configure persistence
107106
set:

polaris-core/src/main/java/org/apache/polaris/core/config/BehaviorChangeConfiguration.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,12 @@
3333
public class BehaviorChangeConfiguration<T> extends PolarisConfiguration<T> {
3434

3535
protected BehaviorChangeConfiguration(
36-
String key, String description, T defaultValue, Optional<String> catalogConfig) {
37-
super(key, description, defaultValue, catalogConfig);
36+
String key,
37+
String description,
38+
T defaultValue,
39+
Optional<String> catalogConfig,
40+
Optional<String> catalogConfigUnsafe) {
41+
super(key, description, defaultValue, catalogConfig, catalogConfigUnsafe);
3842
}
3943

4044
public static final BehaviorChangeConfiguration<Boolean> VALIDATE_VIEW_LOCATION_OVERLAP =

polaris-core/src/main/java/org/apache/polaris/core/config/FeatureConfiguration.java

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@
3434
*/
3535
public class FeatureConfiguration<T> extends PolarisConfiguration<T> {
3636
protected FeatureConfiguration(
37-
String key, String description, T defaultValue, Optional<String> catalogConfig) {
38-
super(key, description, defaultValue, catalogConfig);
37+
String key,
38+
String description,
39+
T defaultValue,
40+
Optional<String> catalogConfig,
41+
Optional<String> catalogConfigUnsafe) {
42+
super(key, description, defaultValue, catalogConfig, catalogConfigUnsafe);
3943
}
4044

4145
/**
@@ -82,7 +86,8 @@ public static void enforceFeatureEnabledOrThrow(
8286
public static final FeatureConfiguration<Boolean> ALLOW_TABLE_LOCATION_OVERLAP =
8387
PolarisConfiguration.<Boolean>builder()
8488
.key("ALLOW_TABLE_LOCATION_OVERLAP")
85-
.catalogConfig("allow.overlapping.table.location")
89+
.catalogConfig("polaris.config.allow.overlapping.table.location")
90+
.catalogConfigUnsafe("allow.overlapping.table.location")
8691
.description(
8792
"If set to true, allow one table's location to reside within another table's location. "
8893
+ "This is only enforced within a given namespace.")
@@ -116,15 +121,17 @@ public static void enforceFeatureEnabledOrThrow(
116121
public static final FeatureConfiguration<Boolean> ALLOW_UNSTRUCTURED_TABLE_LOCATION =
117122
PolarisConfiguration.<Boolean>builder()
118123
.key("ALLOW_UNSTRUCTURED_TABLE_LOCATION")
119-
.catalogConfig("allow.unstructured.table.location")
124+
.catalogConfig("polaris.config.allow.unstructured.table.location")
125+
.catalogConfigUnsafe("allow.unstructured.table.location")
120126
.description("If set to true, allows unstructured table locations.")
121127
.defaultValue(false)
122128
.buildFeatureConfiguration();
123129

124130
public static final FeatureConfiguration<Boolean> ALLOW_EXTERNAL_TABLE_LOCATION =
125131
PolarisConfiguration.<Boolean>builder()
126132
.key("ALLOW_EXTERNAL_TABLE_LOCATION")
127-
.catalogConfig("allow.external.table.location")
133+
.catalogConfig("polaris.config.allow.external.table.location")
134+
.catalogConfigUnsafe("allow.external.table.location")
128135
.description(
129136
"If set to true, allows tables to have external locations outside the default structure.")
130137
.defaultValue(false)
@@ -133,15 +140,17 @@ public static void enforceFeatureEnabledOrThrow(
133140
public static final FeatureConfiguration<Boolean> ALLOW_EXTERNAL_CATALOG_CREDENTIAL_VENDING =
134141
PolarisConfiguration.<Boolean>builder()
135142
.key("ALLOW_EXTERNAL_CATALOG_CREDENTIAL_VENDING")
136-
.catalogConfig("enable.credential.vending")
143+
.catalogConfig("polaris.config.enable.credential.vending")
144+
.catalogConfigUnsafe("enable.credential.vending")
137145
.description("If set to true, allow credential vending for external catalogs.")
138146
.defaultValue(true)
139147
.buildFeatureConfiguration();
140148

141149
public static final FeatureConfiguration<List<String>> SUPPORTED_CATALOG_STORAGE_TYPES =
142150
PolarisConfiguration.<List<String>>builder()
143151
.key("SUPPORTED_CATALOG_STORAGE_TYPES")
144-
.catalogConfig("supported.storage.types")
152+
.catalogConfig("polaris.config.supported.storage.types")
153+
.catalogConfigUnsafe("supported.storage.types")
145154
.description("The list of supported storage types for a catalog")
146155
.defaultValue(
147156
List.of(
@@ -154,23 +163,26 @@ public static void enforceFeatureEnabledOrThrow(
154163
public static final FeatureConfiguration<Boolean> CLEANUP_ON_NAMESPACE_DROP =
155164
PolarisConfiguration.<Boolean>builder()
156165
.key("CLEANUP_ON_NAMESPACE_DROP")
157-
.catalogConfig("cleanup.on.namespace.drop")
166+
.catalogConfig("polaris.config.cleanup.on.namespace.drop")
167+
.catalogConfigUnsafe("cleanup.on.namespace.drop")
158168
.description("If set to true, clean up data when a namespace is dropped")
159169
.defaultValue(false)
160170
.buildFeatureConfiguration();
161171

162172
public static final FeatureConfiguration<Boolean> CLEANUP_ON_CATALOG_DROP =
163173
PolarisConfiguration.<Boolean>builder()
164174
.key("CLEANUP_ON_CATALOG_DROP")
165-
.catalogConfig("cleanup.on.catalog.drop")
175+
.catalogConfig("polaris.config.cleanup.on.catalog.drop")
176+
.catalogConfigUnsafe("cleanup.on.catalog.drop")
166177
.description("If set to true, clean up data when a catalog is dropped")
167178
.defaultValue(false)
168179
.buildFeatureConfiguration();
169180

170181
public static final FeatureConfiguration<Boolean> DROP_WITH_PURGE_ENABLED =
171182
PolarisConfiguration.<Boolean>builder()
172183
.key("DROP_WITH_PURGE_ENABLED")
173-
.catalogConfig("drop-with-purge.enabled")
184+
.catalogConfig("polaris.config.drop-with-purge.enabled")
185+
.catalogConfigUnsafe("drop-with-purge.enabled")
174186
.description(
175187
"If set to true, allows tables to be dropped with the purge parameter set to true.")
176188
.defaultValue(true)

polaris-core/src/main/java/org/apache/polaris/core/config/PolarisConfiguration.java

Lines changed: 103 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,81 @@
2121
import java.util.ArrayList;
2222
import java.util.List;
2323
import java.util.Optional;
24+
import java.util.function.Function;
25+
import java.util.stream.Collectors;
26+
import java.util.stream.Stream;
2427
import org.apache.polaris.core.context.CallContext;
2528
import org.slf4j.Logger;
2629
import org.slf4j.LoggerFactory;
2730

2831
/**
29-
* An ABC for Polaris configurations that alter the service's behavior
32+
* An ABC for Polaris configurations that alter the service's behavior TODO: deprecate unsafe
33+
* catalog configs and remove related code
3034
*
3135
* @param <T> The type of the configuration
3236
*/
3337
public abstract class PolarisConfiguration<T> {
3438

3539
private static final Logger LOGGER = LoggerFactory.getLogger(PolarisConfiguration.class);
3640

41+
private static final List<PolarisConfiguration<?>> allConfigurations = new ArrayList<>();
42+
3743
public final String key;
3844
public final String description;
3945
public final T defaultValue;
4046
private final Optional<String> catalogConfigImpl;
47+
private final Optional<String> catalogConfigUnsafeImpl;
4148
private final Class<T> typ;
4249

50+
/** catalog configs are expected to start with this prefix */
51+
private static final String SAFE_CATALOG_CONFIG_PREFIX = "polaris.config.";
52+
53+
/**
54+
* Helper method for building `allConfigurations` and checking for duplicate use of keys across
55+
* configs.
56+
*/
57+
private static void registerConfiguration(PolarisConfiguration<?> configuration) {
58+
for (PolarisConfiguration<?> existingConfiguration : allConfigurations) {
59+
if (existingConfiguration.key.equals(configuration.key)) {
60+
throw new IllegalArgumentException(
61+
String.format("Config '%s' is already in use", configuration.key));
62+
} else {
63+
var configs =
64+
Stream.of(
65+
configuration.catalogConfigImpl,
66+
configuration.catalogConfigUnsafeImpl,
67+
existingConfiguration.catalogConfigImpl,
68+
existingConfiguration.catalogConfigUnsafeImpl)
69+
.flatMap(Optional::stream)
70+
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
71+
for (var entry : configs.entrySet()) {
72+
if (entry.getValue() > 1) {
73+
throw new IllegalArgumentException(
74+
String.format("Catalog config %s is already in use", entry.getKey()));
75+
}
76+
}
77+
}
78+
}
79+
allConfigurations.add(configuration);
80+
}
81+
82+
/** Returns a list of all PolarisConfigurations that have been registered */
83+
public static List<PolarisConfiguration<?>> getAllConfigurations() {
84+
return List.copyOf(allConfigurations);
85+
}
86+
4387
@SuppressWarnings("unchecked")
4488
protected PolarisConfiguration(
45-
String key, String description, T defaultValue, Optional<String> catalogConfig) {
89+
String key,
90+
String description,
91+
T defaultValue,
92+
Optional<String> catalogConfig,
93+
Optional<String> catalogConfigUnsafe) {
4694
this.key = key;
4795
this.description = description;
4896
this.defaultValue = defaultValue;
4997
this.catalogConfigImpl = catalogConfig;
98+
this.catalogConfigUnsafeImpl = catalogConfigUnsafe;
5099
this.typ = (Class<T>) defaultValue.getClass();
51100
}
52101

@@ -61,6 +110,17 @@ public String catalogConfig() {
61110
"Attempted to read a catalog config key from a configuration that doesn't have one."));
62111
}
63112

113+
public boolean hasCatalogConfigUnsafe() {
114+
return catalogConfigUnsafeImpl.isPresent();
115+
}
116+
117+
public String catalogConfigUnsafe() {
118+
return catalogConfigUnsafeImpl.orElseThrow(
119+
() ->
120+
new IllegalStateException(
121+
"Attempted to read an unsafe catalog config key from a configuration that doesn't have one."));
122+
}
123+
64124
T cast(Object value) {
65125
return this.typ.cast(value);
66126
}
@@ -70,6 +130,7 @@ public static class Builder<T> {
70130
private String description;
71131
private T defaultValue;
72132
private Optional<String> catalogConfig = Optional.empty();
133+
private Optional<String> catalogConfigUnsafe = Optional.empty();
73134

74135
public Builder<T> key(String key) {
75136
this.key = key;
@@ -93,26 +154,58 @@ public Builder<T> defaultValue(T defaultValue) {
93154
}
94155

95156
public Builder<T> catalogConfig(String catalogConfig) {
157+
if (!catalogConfig.startsWith(SAFE_CATALOG_CONFIG_PREFIX)) {
158+
throw new IllegalArgumentException(
159+
"Catalog configs are expected to start with " + SAFE_CATALOG_CONFIG_PREFIX);
160+
}
96161
this.catalogConfig = Optional.of(catalogConfig);
97162
return this;
98163
}
99164

100-
public FeatureConfiguration<T> buildFeatureConfiguration() {
101-
if (key == null || description == null || defaultValue == null) {
102-
throw new IllegalArgumentException("key, description, and defaultValue are required");
165+
/**
166+
* Used to support backwards compatability before there were reserved properties. Usage of this
167+
* method should be removed over time.
168+
*/
169+
@Deprecated
170+
public Builder<T> catalogConfigUnsafe(String catalogConfig) {
171+
LOGGER.info("catalogConfigUnsafe is deprecated! Use catalogConfig() instead.");
172+
if (catalogConfig.startsWith(SAFE_CATALOG_CONFIG_PREFIX)) {
173+
throw new IllegalArgumentException(
174+
"Unsafe catalog configs are not expected to start with " + SAFE_CATALOG_CONFIG_PREFIX);
103175
}
104-
return new FeatureConfiguration<>(key, description, defaultValue, catalogConfig);
176+
this.catalogConfigUnsafe = Optional.of(catalogConfig);
177+
return this;
105178
}
106179

107-
public BehaviorChangeConfiguration<T> buildBehaviorChangeConfiguration() {
180+
private void validateOrThrow() {
108181
if (key == null || description == null || defaultValue == null) {
109182
throw new IllegalArgumentException("key, description, and defaultValue are required");
110183
}
111-
if (catalogConfig.isPresent()) {
184+
if (key.contains(".")) {
185+
throw new IllegalArgumentException("key cannot contain `.`");
186+
}
187+
}
188+
189+
public FeatureConfiguration<T> buildFeatureConfiguration() {
190+
validateOrThrow();
191+
FeatureConfiguration<T> config =
192+
new FeatureConfiguration<>(
193+
key, description, defaultValue, catalogConfig, catalogConfigUnsafe);
194+
PolarisConfiguration.registerConfiguration(config);
195+
return config;
196+
}
197+
198+
public BehaviorChangeConfiguration<T> buildBehaviorChangeConfiguration() {
199+
validateOrThrow();
200+
if (catalogConfig.isPresent() || catalogConfigUnsafe.isPresent()) {
112201
throw new IllegalArgumentException(
113-
"catalogConfig is not valid for behavior change configs");
202+
"catalog configs are not valid for behavior change configs");
114203
}
115-
return new BehaviorChangeConfiguration<>(key, description, defaultValue, catalogConfig);
204+
BehaviorChangeConfiguration<T> config =
205+
new BehaviorChangeConfiguration<>(
206+
key, description, defaultValue, catalogConfig, catalogConfigUnsafe);
207+
PolarisConfiguration.registerConfiguration(config);
208+
return config;
116209
}
117210
}
118211

0 commit comments

Comments
 (0)