This is an automated email from the ASF dual-hosted git repository.
yufei pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/main by this push:
new 226774b0 Core: Add policy content and validator for more maintenance
policies (#1261)
226774b0 is described below
commit 226774b04d9a0de697856d20277f62c53496d4ea
Author: Yufei Gu <[email protected]>
AuthorDate: Thu Mar 27 13:08:02 2025 -0700
Core: Add policy content and validator for more maintenance policies (#1261)
---
.../core/policy/{ => content}/PolicyContent.java | 2 +-
.../PolicyContentUtil.java} | 4 +-
.../StrictBooleanDeserializer.java | 3 +-
.../maintenance/BaseMaintenancePolicyContent.java} | 46 ++----
.../maintenance}/DataCompactionPolicyContent.java | 63 ++-----
.../MetadataCompactionPolicyContent.java | 54 ++++++
.../OrphanFileRemovalPolicyContent.java | 84 ++++++++++
.../SnapshotRetentionPolicyContent.java | 54 ++++++
.../core/policy/validator/PolicyValidators.java | 26 ++-
.../BaseMaintenancePolicyValidator.java} | 11 +-
.../system/orphan-file-removal/2025-02-03.json | 2 +-
.../core/policy/MaintenancePolicyContentTest.java | 181 +++++++++++++++++++++
.../polaris/core/policy/PolicyValidatorsTest.java | 132 +++++++++++++++
.../validator/DataCompactionPolicyContentTest.java | 97 -----------
.../DataCompactionPolicyValidatorTest.java | 88 ----------
.../policy/validator/PolicyValidatorsTest.java | 65 --------
16 files changed, 561 insertions(+), 351 deletions(-)
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/policy/PolicyContent.java
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/PolicyContent.java
similarity index 94%
rename from
polaris-core/src/main/java/org/apache/polaris/core/policy/PolicyContent.java
rename to
polaris-core/src/main/java/org/apache/polaris/core/policy/content/PolicyContent.java
index a1e82f7b..21186f6c 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/policy/PolicyContent.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/PolicyContent.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.polaris.core.policy;
+package org.apache.polaris.core.policy.content;
/** A marker interface for policy content */
public interface PolicyContent {}
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/PolicyValidatorUtil.java
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/PolicyContentUtil.java
similarity index 94%
rename from
polaris-core/src/main/java/org/apache/polaris/core/policy/validator/PolicyValidatorUtil.java
rename to
polaris-core/src/main/java/org/apache/polaris/core/policy/content/PolicyContentUtil.java
index a08cdfd7..2ba025a6 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/PolicyValidatorUtil.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/PolicyContentUtil.java
@@ -16,12 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.polaris.core.policy.validator;
+package org.apache.polaris.core.policy.content;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
-public class PolicyValidatorUtil {
+public class PolicyContentUtil {
public static final ObjectMapper MAPPER = configureMapper();
private static ObjectMapper configureMapper() {
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/StrictBooleanDeserializer.java
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/StrictBooleanDeserializer.java
similarity index 92%
rename from
polaris-core/src/main/java/org/apache/polaris/core/policy/validator/StrictBooleanDeserializer.java
rename to
polaris-core/src/main/java/org/apache/polaris/core/policy/content/StrictBooleanDeserializer.java
index f6da87e7..3c54d10d 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/StrictBooleanDeserializer.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/StrictBooleanDeserializer.java
@@ -16,12 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.polaris.core.policy.validator;
+package org.apache.polaris.core.policy.content;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
+import org.apache.polaris.core.policy.validator.InvalidPolicyException;
public class StrictBooleanDeserializer extends JsonDeserializer<Boolean> {
@Override
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/datacompaction/DataCompactionPolicyContent.java
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java
similarity index 57%
copy from
polaris-core/src/main/java/org/apache/polaris/core/policy/validator/datacompaction/DataCompactionPolicyContent.java
copy to
polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java
index efdd158b..a825e87b 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/datacompaction/DataCompactionPolicyContent.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.polaris.core.policy.validator.datacompaction;
+package org.apache.polaris.core.policy.content.maintenance;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -24,15 +24,11 @@ import
com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.Strings;
import java.util.Map;
import java.util.Set;
-import org.apache.polaris.core.policy.PolicyContent;
+import org.apache.polaris.core.policy.content.PolicyContent;
+import org.apache.polaris.core.policy.content.StrictBooleanDeserializer;
import org.apache.polaris.core.policy.validator.InvalidPolicyException;
-import org.apache.polaris.core.policy.validator.PolicyValidatorUtil;
-import org.apache.polaris.core.policy.validator.StrictBooleanDeserializer;
-
-public class DataCompactionPolicyContent implements PolicyContent {
- private static final String DEFAULT_POLICY_SCHEMA_VERSION = "2025-02-03";
- private static final Set<String> POLICY_SCHEMA_VERSIONS =
Set.of(DEFAULT_POLICY_SCHEMA_VERSION);
+public abstract class BaseMaintenancePolicyContent implements PolicyContent {
@JsonDeserialize(using = StrictBooleanDeserializer.class)
private Boolean enable;
@@ -40,7 +36,7 @@ public class DataCompactionPolicyContent implements
PolicyContent {
private Map<String, String> config;
@JsonCreator
- public DataCompactionPolicyContent(
+ public BaseMaintenancePolicyContent(
@JsonProperty(value = "enable", required = true) boolean enable) {
this.enable = enable;
}
@@ -69,29 +65,21 @@ public class DataCompactionPolicyContent implements
PolicyContent {
this.config = config;
}
- public static DataCompactionPolicyContent fromString(String content) {
- if (Strings.isNullOrEmpty(content)) {
- throw new InvalidPolicyException("Policy is empty");
+ static void validateVersion(
+ String content,
+ BaseMaintenancePolicyContent policy,
+ String defaultVersion,
+ Set<String> allVersions) {
+ if (policy == null) {
+ throw new InvalidPolicyException("Invalid policy: " + content);
}
- try {
- DataCompactionPolicyContent policy =
- PolicyValidatorUtil.MAPPER.readValue(content,
DataCompactionPolicyContent.class);
- if (policy == null) {
- throw new InvalidPolicyException("Invalid policy");
- }
-
- if (Strings.isNullOrEmpty(policy.getVersion())) {
- policy.setVersion(DEFAULT_POLICY_SCHEMA_VERSION);
- }
-
- if (!POLICY_SCHEMA_VERSIONS.contains(policy.getVersion())) {
- throw new InvalidPolicyException("Invalid policy version: " +
policy.getVersion());
- }
+ if (Strings.isNullOrEmpty(policy.getVersion())) {
+ policy.setVersion(defaultVersion);
+ }
- return policy;
- } catch (Exception e) {
- throw new InvalidPolicyException(e);
+ if (!allVersions.contains(policy.getVersion())) {
+ throw new InvalidPolicyException("Invalid policy version: " +
policy.getVersion());
}
}
}
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/datacompaction/DataCompactionPolicyContent.java
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java
similarity index 51%
rename from
polaris-core/src/main/java/org/apache/polaris/core/policy/validator/datacompaction/DataCompactionPolicyContent.java
rename to
polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java
index efdd158b..a5a4012c 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/datacompaction/DataCompactionPolicyContent.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java
@@ -16,57 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.polaris.core.policy.validator.datacompaction;
+package org.apache.polaris.core.policy.content.maintenance;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.Strings;
-import java.util.Map;
import java.util.Set;
-import org.apache.polaris.core.policy.PolicyContent;
+import org.apache.polaris.core.policy.content.PolicyContentUtil;
import org.apache.polaris.core.policy.validator.InvalidPolicyException;
-import org.apache.polaris.core.policy.validator.PolicyValidatorUtil;
-import org.apache.polaris.core.policy.validator.StrictBooleanDeserializer;
-public class DataCompactionPolicyContent implements PolicyContent {
+public class DataCompactionPolicyContent extends BaseMaintenancePolicyContent {
private static final String DEFAULT_POLICY_SCHEMA_VERSION = "2025-02-03";
private static final Set<String> POLICY_SCHEMA_VERSIONS =
Set.of(DEFAULT_POLICY_SCHEMA_VERSION);
- @JsonDeserialize(using = StrictBooleanDeserializer.class)
- private Boolean enable;
-
- private String version;
- private Map<String, String> config;
-
@JsonCreator
public DataCompactionPolicyContent(
@JsonProperty(value = "enable", required = true) boolean enable) {
- this.enable = enable;
- }
-
- public String getVersion() {
- return version;
- }
-
- public void setVersion(String version) {
- this.version = version;
- }
-
- public Boolean enabled() {
- return enable;
- }
-
- public void setEnabled(Boolean enable) {
- this.enable = enable;
- }
-
- public Map<String, String> getConfig() {
- return config;
- }
-
- public void setConfig(Map<String, String> config) {
- this.config = config;
+ super(enable);
}
public static DataCompactionPolicyContent fromString(String content) {
@@ -74,24 +40,15 @@ public class DataCompactionPolicyContent implements
PolicyContent {
throw new InvalidPolicyException("Policy is empty");
}
+ DataCompactionPolicyContent policy;
try {
- DataCompactionPolicyContent policy =
- PolicyValidatorUtil.MAPPER.readValue(content,
DataCompactionPolicyContent.class);
- if (policy == null) {
- throw new InvalidPolicyException("Invalid policy");
- }
-
- if (Strings.isNullOrEmpty(policy.getVersion())) {
- policy.setVersion(DEFAULT_POLICY_SCHEMA_VERSION);
- }
-
- if (!POLICY_SCHEMA_VERSIONS.contains(policy.getVersion())) {
- throw new InvalidPolicyException("Invalid policy version: " +
policy.getVersion());
- }
-
- return policy;
+ policy = PolicyContentUtil.MAPPER.readValue(content,
DataCompactionPolicyContent.class);
} catch (Exception e) {
throw new InvalidPolicyException(e);
}
+
+ validateVersion(content, policy, DEFAULT_POLICY_SCHEMA_VERSION,
POLICY_SCHEMA_VERSIONS);
+
+ return policy;
}
}
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/MetadataCompactionPolicyContent.java
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/MetadataCompactionPolicyContent.java
new file mode 100644
index 00000000..a22ca2d5
--- /dev/null
+++
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/MetadataCompactionPolicyContent.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.core.policy.content.maintenance;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Strings;
+import java.util.Set;
+import org.apache.polaris.core.policy.content.PolicyContentUtil;
+import org.apache.polaris.core.policy.validator.InvalidPolicyException;
+
+public class MetadataCompactionPolicyContent extends
BaseMaintenancePolicyContent {
+ private static final String DEFAULT_POLICY_SCHEMA_VERSION = "2025-02-03";
+ private static final Set<String> POLICY_SCHEMA_VERSIONS =
Set.of(DEFAULT_POLICY_SCHEMA_VERSION);
+
+ @JsonCreator
+ public MetadataCompactionPolicyContent(
+ @JsonProperty(value = "enable", required = true) boolean enable) {
+ super(enable);
+ }
+
+ public static MetadataCompactionPolicyContent fromString(String content) {
+ if (Strings.isNullOrEmpty(content)) {
+ throw new InvalidPolicyException("Policy is empty");
+ }
+
+ MetadataCompactionPolicyContent policy;
+ try {
+ policy = PolicyContentUtil.MAPPER.readValue(content,
MetadataCompactionPolicyContent.class);
+ } catch (Exception e) {
+ throw new InvalidPolicyException(e);
+ }
+
+ validateVersion(content, policy, DEFAULT_POLICY_SCHEMA_VERSION,
POLICY_SCHEMA_VERSIONS);
+
+ return policy;
+ }
+}
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/OrphanFileRemovalPolicyContent.java
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/OrphanFileRemovalPolicyContent.java
new file mode 100644
index 00000000..0adf0ed5
--- /dev/null
+++
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/OrphanFileRemovalPolicyContent.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.core.policy.content.maintenance;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Strings;
+import java.util.List;
+import java.util.Set;
+import org.apache.polaris.core.policy.content.PolicyContentUtil;
+import org.apache.polaris.core.policy.validator.InvalidPolicyException;
+
+public class OrphanFileRemovalPolicyContent extends
BaseMaintenancePolicyContent {
+ private static final String DEFAULT_POLICY_SCHEMA_VERSION = "2025-02-03";
+ private static final Set<String> POLICY_SCHEMA_VERSIONS =
Set.of(DEFAULT_POLICY_SCHEMA_VERSION);
+
+ @JsonProperty(value = "max_orphan_file_age_in_days")
+ private int maxOrphanFileAgeInDays;
+
+ private List<String> locations;
+
+ @JsonCreator
+ public OrphanFileRemovalPolicyContent(
+ @JsonProperty(value = "enable", required = true) boolean enable) {
+ super(enable);
+ }
+
+ public int getMaxOrphanFileAgeInDays() {
+ return maxOrphanFileAgeInDays;
+ }
+
+ public void setMaxOrphanFileAgeInDays(int maxOrphanFileAgeInDays) {
+ this.maxOrphanFileAgeInDays = maxOrphanFileAgeInDays;
+ }
+
+ public List<String> getLocations() {
+ return locations;
+ }
+
+ public void setLocations(List<String> locations) {
+ this.locations = locations;
+ }
+
+ public static OrphanFileRemovalPolicyContent fromString(String content) {
+ if (Strings.isNullOrEmpty(content)) {
+ throw new InvalidPolicyException("Policy is empty");
+ }
+
+ OrphanFileRemovalPolicyContent policy;
+ try {
+ policy = PolicyContentUtil.MAPPER.readValue(content,
OrphanFileRemovalPolicyContent.class);
+ } catch (Exception e) {
+ throw new InvalidPolicyException(e);
+ }
+
+ validateVersion(content, policy, DEFAULT_POLICY_SCHEMA_VERSION,
POLICY_SCHEMA_VERSIONS);
+
+ int maxAge = policy.getMaxOrphanFileAgeInDays();
+ if (maxAge < 0) {
+ throw new InvalidPolicyException(
+ "Invalid max_orphan_file_age_in_days: "
+ + maxAge
+ + ". It must be greater than or equal to 0");
+ }
+
+ return policy;
+ }
+}
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/SnapshotRetentionPolicyContent.java
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/SnapshotRetentionPolicyContent.java
new file mode 100644
index 00000000..ecb3e3d6
--- /dev/null
+++
b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/SnapshotRetentionPolicyContent.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.core.policy.content.maintenance;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Strings;
+import java.util.Set;
+import org.apache.polaris.core.policy.content.PolicyContentUtil;
+import org.apache.polaris.core.policy.validator.InvalidPolicyException;
+
+public class SnapshotRetentionPolicyContent extends
BaseMaintenancePolicyContent {
+ private static final String DEFAULT_POLICY_SCHEMA_VERSION = "2025-02-03";
+ private static final Set<String> POLICY_SCHEMA_VERSIONS =
Set.of(DEFAULT_POLICY_SCHEMA_VERSION);
+
+ @JsonCreator
+ public SnapshotRetentionPolicyContent(
+ @JsonProperty(value = "enable", required = true) boolean enable) {
+ super(enable);
+ }
+
+ public static SnapshotRetentionPolicyContent fromString(String content) {
+ if (Strings.isNullOrEmpty(content)) {
+ throw new InvalidPolicyException("Policy is empty");
+ }
+
+ SnapshotRetentionPolicyContent policy;
+ try {
+ policy = PolicyContentUtil.MAPPER.readValue(content,
SnapshotRetentionPolicyContent.class);
+ } catch (Exception e) {
+ throw new InvalidPolicyException(e);
+ }
+
+ validateVersion(content, policy, DEFAULT_POLICY_SCHEMA_VERSION,
POLICY_SCHEMA_VERSIONS);
+
+ return policy;
+ }
+}
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/PolicyValidators.java
b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/PolicyValidators.java
index ed37f127..3ccb2f6d 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/PolicyValidators.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/PolicyValidators.java
@@ -22,7 +22,11 @@ import com.google.common.base.Preconditions;
import org.apache.polaris.core.entity.PolarisEntity;
import org.apache.polaris.core.policy.PolicyEntity;
import org.apache.polaris.core.policy.PredefinedPolicyTypes;
-import
org.apache.polaris.core.policy.validator.datacompaction.DataCompactionPolicyValidator;
+import
org.apache.polaris.core.policy.content.maintenance.DataCompactionPolicyContent;
+import
org.apache.polaris.core.policy.content.maintenance.MetadataCompactionPolicyContent;
+import
org.apache.polaris.core.policy.content.maintenance.OrphanFileRemovalPolicyContent;
+import
org.apache.polaris.core.policy.content.maintenance.SnapshotRetentionPolicyContent;
+import
org.apache.polaris.core.policy.validator.maintenance.BaseMaintenancePolicyValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,15 +54,19 @@ public class PolicyValidators {
switch (type) {
case DATA_COMPACTION:
- DataCompactionPolicyValidator.INSTANCE.validate(policy.getContent());
+ DataCompactionPolicyContent.fromString(policy.getContent());
break;
-
- // To support additional policy types in the future, add cases here.
case METADATA_COMPACTION:
+ MetadataCompactionPolicyContent.fromString(policy.getContent());
+ break;
case SNAPSHOT_RETENTION:
+ SnapshotRetentionPolicyContent.fromString(policy.getContent());
+ break;
case ORPHAN_FILE_REMOVAL:
+ OrphanFileRemovalPolicyContent.fromString(policy.getContent());
+ break;
default:
- throw new InvalidPolicyException("Unsupported policy type: " +
type.getName());
+ throw new IllegalArgumentException("Unsupported policy type: " +
type.getName());
}
LOGGER.info("Policy validated successfully: {}", type.getName());
@@ -79,14 +87,16 @@ public class PolicyValidators {
Preconditions.checkArgument(
policyType != null, "Unknown policy type: " +
policy.getPolicyTypeCode());
+ var entityType = targetEntity.getType();
+ var entitySubType = targetEntity.getSubType();
+
switch (policyType) {
case DATA_COMPACTION:
- return DataCompactionPolicyValidator.INSTANCE.canAttach(
- targetEntity.getType(), targetEntity.getSubType());
- // To support additional policy types in the future, add cases here.
case METADATA_COMPACTION:
case SNAPSHOT_RETENTION:
case ORPHAN_FILE_REMOVAL:
+ return BaseMaintenancePolicyValidator.INSTANCE.canAttach(entityType,
entitySubType);
+
default:
LOGGER.warn("Attachment not supported for policy type: {}",
policyType.getName());
return false;
diff --git
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/datacompaction/DataCompactionPolicyValidator.java
b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java
similarity index 86%
rename from
polaris-core/src/main/java/org/apache/polaris/core/policy/validator/datacompaction/DataCompactionPolicyValidator.java
rename to
polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java
index 344c72d9..86308f55 100644
---
a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/datacompaction/DataCompactionPolicyValidator.java
+++
b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.polaris.core.policy.validator.datacompaction;
+package org.apache.polaris.core.policy.validator.maintenance;
import static org.apache.polaris.core.entity.PolarisEntityType.CATALOG;
import static org.apache.polaris.core.entity.PolarisEntityType.NAMESPACE;
@@ -28,16 +28,15 @@ import org.apache.polaris.core.entity.PolarisEntityType;
import org.apache.polaris.core.policy.validator.InvalidPolicyException;
import org.apache.polaris.core.policy.validator.PolicyValidator;
-public class DataCompactionPolicyValidator implements PolicyValidator {
- public static final DataCompactionPolicyValidator INSTANCE = new
DataCompactionPolicyValidator();
+public class BaseMaintenancePolicyValidator implements PolicyValidator {
+ public static final BaseMaintenancePolicyValidator INSTANCE =
+ new BaseMaintenancePolicyValidator();
private static final Set<PolarisEntityType> ATTACHABLE_ENTITY_TYPES =
Set.of(CATALOG, NAMESPACE, TABLE_LIKE);
@Override
- public void validate(String content) throws InvalidPolicyException {
- DataCompactionPolicyContent.fromString(content);
- }
+ public void validate(String content) throws InvalidPolicyException {}
@Override
public boolean canAttach(PolarisEntityType entityType, PolarisEntitySubType
entitySubType) {
diff --git
a/polaris-core/src/main/resources/schemas/policies/system/orphan-file-removal/2025-02-03.json
b/polaris-core/src/main/resources/schemas/policies/system/orphan-file-removal/2025-02-03.json
index 19f35dec..f7b00d1e 100644
---
a/polaris-core/src/main/resources/schemas/policies/system/orphan-file-removal/2025-02-03.json
+++
b/polaris-core/src/main/resources/schemas/policies/system/orphan-file-removal/2025-02-03.json
@@ -40,7 +40,7 @@
"version": "2025-02-03",
"enable": true,
"max_orphan_file_age_in_days": 30,
- "location": "s3://my-bucket/my-table-location",
+ "locations": ["s3://my-bucket/my-table-location"],
"config": {
"prefix_mismatch_mode": "ignore",
"key1": "value1"
diff --git
a/polaris-core/src/test/java/org/apache/polaris/core/policy/MaintenancePolicyContentTest.java
b/polaris-core/src/test/java/org/apache/polaris/core/policy/MaintenancePolicyContentTest.java
new file mode 100644
index 00000000..1b5972a0
--- /dev/null
+++
b/polaris-core/src/test/java/org/apache/polaris/core/policy/MaintenancePolicyContentTest.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.core.policy;
+
+import static
org.apache.polaris.core.policy.content.maintenance.OrphanFileRemovalPolicyContent.fromString;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.function.Function;
+import java.util.stream.Stream;
+import
org.apache.polaris.core.policy.content.maintenance.BaseMaintenancePolicyContent;
+import
org.apache.polaris.core.policy.content.maintenance.DataCompactionPolicyContent;
+import
org.apache.polaris.core.policy.content.maintenance.MetadataCompactionPolicyContent;
+import
org.apache.polaris.core.policy.content.maintenance.OrphanFileRemovalPolicyContent;
+import
org.apache.polaris.core.policy.content.maintenance.SnapshotRetentionPolicyContent;
+import org.apache.polaris.core.policy.validator.InvalidPolicyException;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public class MaintenancePolicyContentTest {
+ static Stream<Arguments> policyTypes() {
+ return Stream.of(
+ Arguments.of(PredefinedPolicyTypes.DATA_COMPACTION),
+ Arguments.of(PredefinedPolicyTypes.METADATA_COMPACTION),
+ Arguments.of(PredefinedPolicyTypes.ORPHAN_FILE_REMOVAL),
+ Arguments.of(PredefinedPolicyTypes.METADATA_COMPACTION));
+ }
+
+ Function<String, BaseMaintenancePolicyContent>
getParser(PredefinedPolicyTypes policyType) {
+ switch (policyType) {
+ case DATA_COMPACTION:
+ return DataCompactionPolicyContent::fromString;
+ case METADATA_COMPACTION:
+ return MetadataCompactionPolicyContent::fromString;
+ case ORPHAN_FILE_REMOVAL:
+ return OrphanFileRemovalPolicyContent::fromString;
+ case SNAPSHOT_RETENTION:
+ return SnapshotRetentionPolicyContent::fromString;
+ default:
+ throw new IllegalArgumentException("Unknown policy type: " +
policyType);
+ }
+ }
+
+ @ParameterizedTest
+ @MethodSource("policyTypes")
+ public void testValidPolicyContent(PredefinedPolicyTypes policyType) {
+ var parser = getParser(policyType);
+
+ assertThat(parser.apply("{\"enable\": false}").enabled()).isFalse();
+ assertThat(parser.apply("{\"enable\": true}").enabled()).isTrue();
+
+ var validJson = "{\"version\":\"2025-02-03\", \"enable\": true}";
+ assertThat(parser.apply(validJson).getVersion()).isEqualTo("2025-02-03");
+
+ validJson = "{\"enable\": true, \"config\": {\"key1\": \"value1\",
\"key2\": true}}";
+
assertThat(parser.apply(validJson).getConfig().get("key1")).isEqualTo("value1");
+ }
+
+ @ParameterizedTest
+ @MethodSource("policyTypes")
+ void testIsValidEmptyString(PredefinedPolicyTypes policyTypes) {
+ var parser = getParser(policyTypes);
+ assertThatThrownBy(() -> parser.apply(""))
+ .as("Validating empty string should throw InvalidPolicyException")
+ .isInstanceOf(InvalidPolicyException.class)
+ .hasMessageContaining("Policy is empty");
+ }
+
+ @ParameterizedTest
+ @MethodSource("policyTypes")
+ void testIsValidJSONLiteralNull(PredefinedPolicyTypes policyTypes) {
+ var parser = getParser(policyTypes);
+ assertThatThrownBy(() -> parser.apply("null"))
+ .isInstanceOf(InvalidPolicyException.class)
+ .hasMessageContaining("Invalid policy: null");
+ }
+
+ @ParameterizedTest
+ @MethodSource("policyTypes")
+ void testIsValidEmptyJson(PredefinedPolicyTypes policyTypes) {
+ var parser = getParser(policyTypes);
+ assertThatThrownBy(() -> parser.apply("{}"))
+ .as("Validating empty JSON '{}' should throw InvalidPolicyException")
+ .isInstanceOf(InvalidPolicyException.class)
+ .hasMessageContaining("Invalid policy");
+ }
+
+ @ParameterizedTest
+ @MethodSource("policyTypes")
+ void testIsValidInvalidVersionFormat(PredefinedPolicyTypes policyTypes) {
+ var parser = getParser(policyTypes);
+ String invalidPolicy = "{\"enable\": true, \"version\": \"fdafds\"}";
+ assertThatThrownBy(() -> parser.apply(invalidPolicy))
+ .as("Validating policy with invalid version format should throw
InvalidPolicyException")
+ .isInstanceOf(InvalidPolicyException.class);
+ }
+
+ @ParameterizedTest
+ @MethodSource("policyTypes")
+ void testIsValidInvalidKeyInPolicy(PredefinedPolicyTypes policyTypes) {
+ var parser = getParser(policyTypes);
+ String invalidPolicy = "{\"version\":\"2025-02-03\", \"enable\": true,
\"invalid_key\": 12342}";
+ assertThatThrownBy(() -> parser.apply(invalidPolicy))
+ .as("Validating policy with an unknown key should throw
InvalidPolicyException")
+ .isInstanceOf(InvalidPolicyException.class)
+ .hasMessageContaining("Invalid policy");
+ }
+
+ @ParameterizedTest
+ @MethodSource("policyTypes")
+ void testIsValidUnrecognizedToken(PredefinedPolicyTypes policyTypes) {
+ var parser = getParser(policyTypes);
+ var invalidPolicy = "{\"enable\": invalidToken}";
+ assertThatThrownBy(() -> parser.apply(invalidPolicy))
+ .isInstanceOf(InvalidPolicyException.class)
+ .hasMessageContaining("Invalid policy");
+ }
+
+ @ParameterizedTest
+ @MethodSource("policyTypes")
+ void testIsValidNullValue(PredefinedPolicyTypes policyTypes) {
+ var parser = getParser(policyTypes);
+ var invalidPolicy = "{\"enable\": null}";
+ assertThatThrownBy(() -> parser.apply(invalidPolicy))
+ .isInstanceOf(InvalidPolicyException.class)
+ .hasMessageContaining("Invalid policy");
+ }
+
+ @ParameterizedTest
+ @MethodSource("policyTypes")
+ void testIsValidWrongString(PredefinedPolicyTypes policyTypes) {
+ var parser = getParser(policyTypes);
+ var invalidPolicy = "{\"enable\": \"invalid\"}";
+ assertThatThrownBy(() -> parser.apply(invalidPolicy))
+ .isInstanceOf(InvalidPolicyException.class)
+ .hasMessageContaining("Invalid policy");
+ }
+
+ @Test
+ public void testValidOrphanFileRemovalPolicyContent() {
+ assertThat(
+ fromString("{\"enable\": true, \"max_orphan_file_age_in_days\":
3}")
+ .getMaxOrphanFileAgeInDays())
+ .isEqualTo(3);
+ assertThat(
+ fromString(
+ "{\"enable\": true, \"max_orphan_file_age_in_days\": 3,
\"locations\": ["
+ + " \"s3://my-bucket/ns/my_table/\","
+ + " \"s3://my-bucket/ns/my_table/my-data/\","
+ + " \"s3://my-bucket/ns/my_table/my-metadata\""
+ + " ]}")
+ .getLocations()
+ .get(0))
+ .isEqualTo("s3://my-bucket/ns/my_table/");
+ }
+
+ @Test
+ public void testInvalidOrphanFileRemovalPolicyContent() {
+ assertThatThrownBy(() -> fromString("{\"enable\": true,
\"max_orphan_file_age_in_days\": -3}"))
+ .isInstanceOf(InvalidPolicyException.class)
+ .hasMessageContaining("Invalid max_orphan_file_age_in_days");
+ }
+}
diff --git
a/polaris-core/src/test/java/org/apache/polaris/core/policy/PolicyValidatorsTest.java
b/polaris-core/src/test/java/org/apache/polaris/core/policy/PolicyValidatorsTest.java
new file mode 100644
index 00000000..04435ba7
--- /dev/null
+++
b/polaris-core/src/test/java/org/apache/polaris/core/policy/PolicyValidatorsTest.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.polaris.core.policy;
+
+import static
org.apache.polaris.core.entity.PolarisEntitySubType.ICEBERG_TABLE;
+import static org.apache.polaris.core.entity.PolarisEntitySubType.ICEBERG_VIEW;
+import static
org.apache.polaris.core.policy.PredefinedPolicyTypes.DATA_COMPACTION;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.polaris.core.entity.CatalogEntity;
+import org.apache.polaris.core.entity.NamespaceEntity;
+import org.apache.polaris.core.entity.PrincipalEntity;
+import org.apache.polaris.core.entity.table.IcebergTableLikeEntity;
+import org.apache.polaris.core.policy.validator.InvalidPolicyException;
+import org.apache.polaris.core.policy.validator.PolicyValidators;
+import org.junit.jupiter.api.Test;
+
+public class PolicyValidatorsTest {
+ Namespace ns = Namespace.of("NS1");
+ TableIdentifier tableIdentifier = TableIdentifier.of(ns, "table1");
+ PolicyEntity policyEntity = new PolicyEntity.Builder(ns, "pn",
DATA_COMPACTION).build();
+
+ @Test
+ public void testInvalidPolicy() {
+ var policyEntity =
+ new PolicyEntity.Builder(ns, "testPolicy", DATA_COMPACTION)
+ .setContent("InvalidContent")
+ .setPolicyVersion(0)
+ .build();
+ assertThatThrownBy(() -> PolicyValidators.validate(policyEntity))
+ .as("Validating empty JSON '{}' should throw InvalidPolicyException")
+ .isInstanceOf(InvalidPolicyException.class)
+ .hasMessageContaining("Invalid policy");
+ }
+
+ @Test
+ public void testUnsupportedPolicyType() {
+ var newPolicyType =
+ new PolicyType() {
+ @Override
+ public int getCode() {
+ return Integer.MAX_VALUE;
+ }
+
+ @Override
+ public String getName() {
+ return "";
+ }
+
+ @Override
+ public boolean isInheritable() {
+ return false;
+ }
+ };
+
+ var policyEntity = new PolicyEntity.Builder(ns, "testPolicy",
newPolicyType).build();
+
+ assertThatThrownBy(() -> PolicyValidators.validate(policyEntity))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessageContaining("Unknown policy type:");
+ }
+
+ @Test
+ public void testValidPolicy() {
+ var policyEntity =
+ new PolicyEntity.Builder(ns, "testPolicy", DATA_COMPACTION)
+ .setContent("{\"enable\": false}")
+ .setPolicyVersion(0)
+ .build();
+ PolicyValidators.validate(policyEntity);
+ }
+
+ @Test
+ public void testCanAttachReturnsTrueForCatalogType() {
+ var targetEntity = new CatalogEntity.Builder().build();
+ var result = PolicyValidators.canAttach(policyEntity, targetEntity);
+ assertThat(result).isTrue().as("Expected canAttach() to return true for
CATALOG type");
+ }
+
+ @Test
+ public void testCanAttachReturnsTrueForNamespaceType() {
+ var targetEntity = new NamespaceEntity.Builder(ns).build();
+ var result = PolicyValidators.canAttach(policyEntity, targetEntity);
+ assertThat(result).isTrue().as("Expected canAttach() to return true for
CATALOG type");
+ }
+
+ @Test
+ public void testCanAttachReturnsTrueForIcebergTableLikeWithTableSubtype() {
+ var targetEntity =
+ new IcebergTableLikeEntity.Builder(tableIdentifier,
"").setSubType(ICEBERG_TABLE).build();
+ var result = PolicyValidators.canAttach(policyEntity, targetEntity);
+ assertThat(result)
+ .isTrue()
+ .as("Expected canAttach() to return true for ICEBERG_TABLE_LIKE with
TABLE subtype");
+ }
+
+ @Test
+ public void
testCanAttachReturnsFalseForIcebergTableLikeWithNonTableSubtype() {
+ var targetEntity =
+ new IcebergTableLikeEntity.Builder(tableIdentifier,
"").setSubType(ICEBERG_VIEW).build();
+ var result = PolicyValidators.canAttach(policyEntity, targetEntity);
+ assertThat(result)
+ .isFalse()
+ .as("Expected canAttach() to return false for ICEBERG_TABLE_LIKE with
non-TABLE subtype");
+ }
+
+ @Test
+ public void testCanAttachReturnsFalseForUnattachableType() {
+ var targetEntity = new PrincipalEntity.Builder().build();
+ var result = PolicyValidators.canAttach(policyEntity, targetEntity);
+ assertThat(result).isFalse().as("Expected canAttach() to return false for
null");
+ }
+}
diff --git
a/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/DataCompactionPolicyContentTest.java
b/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/DataCompactionPolicyContentTest.java
deleted file mode 100644
index 3d70fbee..00000000
---
a/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/DataCompactionPolicyContentTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.core.policy.validator;
-
-import static
org.apache.polaris.core.policy.validator.datacompaction.DataCompactionPolicyContent.fromString;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import org.junit.jupiter.api.Test;
-
-public class DataCompactionPolicyContentTest {
- @Test
- public void testValidPolicies() {
- assertThat(fromString("{\"enable\": false}").enabled()).isFalse();
- assertThat(fromString("{\"enable\": true}").enabled()).isTrue();
-
- var validJson = "{\"version\":\"2025-02-03\", \"enable\": true}";
- assertThat(fromString(validJson).getVersion()).isEqualTo("2025-02-03");
-
- validJson = "{\"enable\": true, \"config\": {\"key1\": \"value1\",
\"key2\": true}}";
-
assertThat(fromString(validJson).getConfig().get("key1")).isEqualTo("value1");
- }
-
- @Test
- void testIsValidEmptyString() {
- assertThatThrownBy(() -> fromString(""))
- .as("Validating empty string should throw InvalidPolicyException")
- .isInstanceOf(InvalidPolicyException.class)
- .hasMessageContaining("Policy is empty");
- }
-
- @Test
- void testIsValidEmptyJson() {
- assertThatThrownBy(() -> fromString("{}"))
- .as("Validating empty JSON '{}' should throw InvalidPolicyException")
- .isInstanceOf(InvalidPolicyException.class)
- .hasMessageContaining("Invalid policy");
- }
-
- @Test
- void testIsValidInvalidVersionFormat() {
- String invalidPolicy1 = "{\"enable\": true, \"version\": \"fdafds\"}";
- assertThatThrownBy(() -> fromString(invalidPolicy1))
- .as("Validating policy with invalid version format should throw
InvalidPolicyException")
- .isInstanceOf(InvalidPolicyException.class);
- }
-
- @Test
- void testIsValidInvalidKeyInPolicy() {
- String invalidPolicy2 =
- "{\"version\":\"2025-02-03\", \"enable\": true, \"invalid_key\":
12342}";
- assertThatThrownBy(() -> fromString(invalidPolicy2))
- .as("Validating policy with an unknown key should throw
InvalidPolicyException")
- .isInstanceOf(InvalidPolicyException.class)
- .hasMessageContaining("Invalid policy");
- }
-
- @Test
- void testIsValidUnrecognizedToken() {
- var invalidPolicy = "{\"enable\": invalidToken}";
- assertThatThrownBy(() -> fromString(invalidPolicy))
- .isInstanceOf(InvalidPolicyException.class)
- .hasMessageContaining("Invalid policy");
- }
-
- @Test
- void testIsValidNullValue() {
- var invalidPolicy = "{\"enable\": null}";
- assertThatThrownBy(() -> fromString(invalidPolicy))
- .isInstanceOf(InvalidPolicyException.class)
- .hasMessageContaining("Invalid policy");
- }
-
- @Test
- void testIsValidWrongString() {
- var invalidPolicy = "{\"enable\": \"invalid\"}";
- assertThatThrownBy(() -> fromString(invalidPolicy))
- .isInstanceOf(InvalidPolicyException.class)
- .hasMessageContaining("Invalid policy");
- }
-}
diff --git
a/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/DataCompactionPolicyValidatorTest.java
b/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/DataCompactionPolicyValidatorTest.java
deleted file mode 100644
index 18205763..00000000
---
a/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/DataCompactionPolicyValidatorTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.core.policy.validator;
-
-import static org.apache.polaris.core.entity.PolarisEntitySubType.ANY_SUBTYPE;
-import static
org.apache.polaris.core.entity.PolarisEntitySubType.ICEBERG_TABLE;
-import static org.apache.polaris.core.entity.PolarisEntitySubType.ICEBERG_VIEW;
-import static org.apache.polaris.core.entity.PolarisEntityType.CATALOG;
-import static org.apache.polaris.core.entity.PolarisEntityType.NAMESPACE;
-import static org.apache.polaris.core.entity.PolarisEntityType.PRINCIPAL;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import org.apache.polaris.core.entity.PolarisEntityType;
-import
org.apache.polaris.core.policy.validator.datacompaction.DataCompactionPolicyValidator;
-import org.junit.jupiter.api.Test;
-
-public class DataCompactionPolicyValidatorTest {
- private final DataCompactionPolicyValidator validator = new
DataCompactionPolicyValidator();
-
- @Test
- public void testValidPolicies() {
- var validJson = "{\"version\":\"2025-02-03\", \"enable\": true}";
- validator.validate(validJson);
-
- assertThatThrownBy(() -> validator.validate(""))
- .as("Validating empty string should throw InvalidPolicyException")
- .isInstanceOf(InvalidPolicyException.class)
- .hasMessageContaining("Policy is empty");
- }
-
- @Test
- public void testCanAttachReturnsTrueForCatalogType() {
- var result = validator.canAttach(CATALOG, ANY_SUBTYPE); // using any valid
subtype
- assertThat(result).isTrue().as("Expected canAttach() to return true for
CATALOG type");
- }
-
- @Test
- public void testCanAttachReturnsTrueForNamespaceType() {
- var result = validator.canAttach(NAMESPACE, ANY_SUBTYPE); // using any
valid subtype
- assertThat(result).isTrue().as("Expected canAttach() to return true for
CATALOG type");
- }
-
- @Test
- public void testCanAttachReturnsTrueForIcebergTableLikeWithTableSubtype() {
- var result = validator.canAttach(PolarisEntityType.TABLE_LIKE,
ICEBERG_TABLE);
- assertThat(result)
- .isTrue()
- .as("Expected canAttach() to return true for ICEBERG_TABLE_LIKE with
TABLE subtype");
- }
-
- @Test
- public void
testCanAttachReturnsFalseForIcebergTableLikeWithNonTableSubtype() {
- // For ICEBERG_TABLE_LIKE, any subtype other than TABLE should return
false.
- boolean result = validator.canAttach(PolarisEntityType.TABLE_LIKE,
ICEBERG_VIEW);
- assertThat(result)
- .isFalse()
- .as("Expected canAttach() to return false for ICEBERG_TABLE_LIKE with
non-TABLE subtype");
- }
-
- @Test
- public void testCanAttachReturnsFalseForNull() {
- var result = validator.canAttach(null, null); // using any valid subtype
- assertThat(result).isFalse().as("Expected canAttach() to return false for
null");
- }
-
- @Test
- public void testCanAttachReturnsFalseForUnattachableType() {
- var result = validator.canAttach(PRINCIPAL, null); // using any valid
subtype
- assertThat(result).isFalse().as("Expected canAttach() to return false for
null");
- }
-}
diff --git
a/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/PolicyValidatorsTest.java
b/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/PolicyValidatorsTest.java
deleted file mode 100644
index 24d122a1..00000000
---
a/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/PolicyValidatorsTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.polaris.core.policy.validator;
-
-import static
org.apache.polaris.core.policy.PredefinedPolicyTypes.DATA_COMPACTION;
-import static
org.apache.polaris.core.policy.PredefinedPolicyTypes.METADATA_COMPACTION;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import org.apache.iceberg.catalog.Namespace;
-import org.apache.polaris.core.policy.PolicyEntity;
-import org.junit.jupiter.api.Test;
-
-public class PolicyValidatorsTest {
- @Test
- public void testInvalidPolicy() {
- var policyEntity =
- new PolicyEntity.Builder(Namespace.of("NS1"), "testPolicy",
DATA_COMPACTION)
- .setContent("InvalidContent")
- .setPolicyVersion(0)
- .build();
- assertThatThrownBy(() -> PolicyValidators.validate(policyEntity))
- .as("Validating empty JSON '{}' should throw InvalidPolicyException")
- .isInstanceOf(InvalidPolicyException.class)
- .hasMessageContaining("Invalid policy");
- }
-
- @Test
- public void testUnsupportedPolicyType() {
- var policyEntity =
- new PolicyEntity.Builder(Namespace.of("NS1"), "testPolicy",
METADATA_COMPACTION)
- .setContent("InvalidContent")
- .setPolicyVersion(0)
- .build();
-
- assertThatThrownBy(() -> PolicyValidators.validate(policyEntity))
- .isInstanceOf(InvalidPolicyException.class)
- .hasMessageContaining("Unsupported policy type");
- }
-
- @Test
- public void testValidPolicy() {
- var policyEntity =
- new PolicyEntity.Builder(Namespace.of("NS1"), "testPolicy",
DATA_COMPACTION)
- .setContent("{\"enable\": false}")
- .setPolicyVersion(0)
- .build();
- PolicyValidators.validate(policyEntity);
- }
-}