From ec57f4a4407356f04a5d24da6c7ac240f091319c Mon Sep 17 00:00:00 2001 From: Yufei Gu Date: Wed, 26 Mar 2025 14:38:13 -0700 Subject: [PATCH 1/5] Add Policy contents and validators --- .../policy/{ => content}/PolicyContent.java | 2 +- .../PolicyContentUtil.java} | 4 +- .../StrictBooleanDeserializer.java | 3 +- .../BaseMaintenancePolicyContent.java | 64 ++++++++++++ .../DataCompactionPolicyContent.java | 10 +- .../MetadataCompactionPolicyContent.java | 63 ++++++++++++ .../OrphanFileRemovalPolicyContent.java | 73 ++++++++++++++ .../SnapshotRetentionPolicyContent.java | 63 ++++++++++++ .../policy/validator/PolicyValidators.java | 26 +++-- .../BaseMaintenancePolicyValidator.java} | 16 +-- .../DataCompactionPolicyValidator.java | 31 ++++++ .../MetadataCompactionPolicyValidator.java | 32 ++++++ .../OrphanFileRemovalPolicyValidator.java | 32 ++++++ .../SnapshotRetentionPolicyValidator.java | 32 ++++++ .../DataCompactionPolicyContentTest.java | 2 +- .../DataCompactionPolicyValidatorTest.java | 88 ----------------- .../MetadataCompactionPolicyContentTest.java | 97 +++++++++++++++++++ .../validator/PolicyValidatorsTest.java | 83 ++++++++++++++-- 18 files changed, 596 insertions(+), 125 deletions(-) rename polaris-core/src/main/java/org/apache/polaris/core/policy/{ => content}/PolicyContent.java (94%) rename polaris-core/src/main/java/org/apache/polaris/core/policy/{validator/PolicyValidatorUtil.java => content/PolicyContentUtil.java} (94%) rename polaris-core/src/main/java/org/apache/polaris/core/policy/{validator => content}/StrictBooleanDeserializer.java (92%) create mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java rename polaris-core/src/main/java/org/apache/polaris/core/policy/{validator/datacompaction => content/maintenance}/DataCompactionPolicyContent.java (88%) create mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/MetadataCompactionPolicyContent.java create mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/OrphanFileRemovalPolicyContent.java create mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/SnapshotRetentionPolicyContent.java rename polaris-core/src/main/java/org/apache/polaris/core/policy/validator/{datacompaction/DataCompactionPolicyValidator.java => maintenance/BaseMaintenancePolicyValidator.java} (79%) create mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/DataCompactionPolicyValidator.java create mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/MetadataCompactionPolicyValidator.java create mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/OrphanFileRemovalPolicyValidator.java create mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/SnapshotRetentionPolicyValidator.java delete mode 100644 polaris-core/src/test/java/org/apache/polaris/core/policy/validator/DataCompactionPolicyValidatorTest.java create mode 100644 polaris-core/src/test/java/org/apache/polaris/core/policy/validator/MetadataCompactionPolicyContentTest.java 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 a1e82f7b6a..21186f6c70 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 a08cdfd7e7..2ba025a663 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 f6da87e702..3c54d10d1d 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 { @Override diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java new file mode 100644 index 0000000000..b8a84c553b --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java @@ -0,0 +1,64 @@ +/* + * 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.fasterxml.jackson.databind.annotation.JsonDeserialize; +import java.util.Map; +import org.apache.polaris.core.policy.content.PolicyContent; +import org.apache.polaris.core.policy.content.StrictBooleanDeserializer; + +public class BaseMaintenancePolicyContent implements PolicyContent { + @JsonDeserialize(using = StrictBooleanDeserializer.class) + private Boolean enable; + + private String version; + private Map config; + + @JsonCreator + public BaseMaintenancePolicyContent( + @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 getConfig() { + return config; + } + + public void setConfig(Map config) { + this.config = config; + } +} 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 88% 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 efdd158b5d..f96d313273 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,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,10 +24,10 @@ 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.PolicyContentUtil; +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"; @@ -76,7 +76,7 @@ public static DataCompactionPolicyContent fromString(String content) { try { DataCompactionPolicyContent policy = - PolicyValidatorUtil.MAPPER.readValue(content, DataCompactionPolicyContent.class); + PolicyContentUtil.MAPPER.readValue(content, DataCompactionPolicyContent.class); if (policy == null) { throw new InvalidPolicyException("Invalid 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 0000000000..8929cd44ff --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/MetadataCompactionPolicyContent.java @@ -0,0 +1,63 @@ +/* + * 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 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"); + } + + try { + MetadataCompactionPolicyContent policy = + PolicyContentUtil.MAPPER.readValue(content, MetadataCompactionPolicyContent.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; + } catch (Exception e) { + throw new InvalidPolicyException(e); + } + } +} 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 0000000000..e7925bdbf1 --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/OrphanFileRemovalPolicyContent.java @@ -0,0 +1,73 @@ +/* + * 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 OrphanFileRemovalPolicyContent extends BaseMaintenancePolicyContent { + private static final String DEFAULT_POLICY_SCHEMA_VERSION = "2025-02-03"; + private static final Set POLICY_SCHEMA_VERSIONS = Set.of(DEFAULT_POLICY_SCHEMA_VERSION); + + private int maxOrphanFileAgeInDays; + + @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 static OrphanFileRemovalPolicyContent fromString(String content) { + if (Strings.isNullOrEmpty(content)) { + throw new InvalidPolicyException("Policy is empty"); + } + + try { + OrphanFileRemovalPolicyContent policy = + PolicyContentUtil.MAPPER.readValue(content, OrphanFileRemovalPolicyContent.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; + } catch (Exception e) { + throw new InvalidPolicyException(e); + } + } +} 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 0000000000..f477873a83 --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/SnapshotRetentionPolicyContent.java @@ -0,0 +1,63 @@ +/* + * 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 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"); + } + + try { + SnapshotRetentionPolicyContent policy = + PolicyContentUtil.MAPPER.readValue(content, SnapshotRetentionPolicyContent.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; + } catch (Exception e) { + throw new InvalidPolicyException(e); + } + } +} 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 ed37f12792..fb27b3cb12 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,10 @@ 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.validator.maintenance.DataCompactionPolicyValidator; +import org.apache.polaris.core.policy.validator.maintenance.MetadataCompactionPolicyValidator; +import org.apache.polaris.core.policy.validator.maintenance.OrphanFileRemovalPolicyValidator; +import org.apache.polaris.core.policy.validator.maintenance.SnapshotRetentionPolicyValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,13 +55,17 @@ public static void validate(PolicyEntity policy) { case DATA_COMPACTION: DataCompactionPolicyValidator.INSTANCE.validate(policy.getContent()); break; - - // To support additional policy types in the future, add cases here. case METADATA_COMPACTION: + MetadataCompactionPolicyValidator.INSTANCE.validate(policy.getContent()); + break; case SNAPSHOT_RETENTION: + SnapshotRetentionPolicyValidator.INSTANCE.validate(policy.getContent()); + break; case ORPHAN_FILE_REMOVAL: + OrphanFileRemovalPolicyValidator.INSTANCE.validate(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 +86,19 @@ public static boolean canAttach(PolicyEntity policy, PolarisEntity targetEntity) 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. + return DataCompactionPolicyValidator.INSTANCE.canAttach(entityType, entitySubType); case METADATA_COMPACTION: + return MetadataCompactionPolicyValidator.INSTANCE.canAttach(entityType, entitySubType); case SNAPSHOT_RETENTION: + return SnapshotRetentionPolicyValidator.INSTANCE.canAttach(entityType, entitySubType); case ORPHAN_FILE_REMOVAL: + return OrphanFileRemovalPolicyValidator.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 79% 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 344c72d909..efecc3dfa3 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; @@ -25,31 +25,23 @@ import java.util.Set; import org.apache.polaris.core.entity.PolarisEntitySubType; 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 abstract class BaseMaintenancePolicyValidator implements PolicyValidator { private static final Set ATTACHABLE_ENTITY_TYPES = Set.of(CATALOG, NAMESPACE, TABLE_LIKE); - @Override - public void validate(String content) throws InvalidPolicyException { - DataCompactionPolicyContent.fromString(content); - } - @Override public boolean canAttach(PolarisEntityType entityType, PolarisEntitySubType entitySubType) { if (entityType == null) { return false; } - if (!ATTACHABLE_ENTITY_TYPES.contains(entityType)) { + if (entityType == TABLE_LIKE && entitySubType != PolarisEntitySubType.ICEBERG_TABLE) { return false; } - if (entityType == TABLE_LIKE && entitySubType != PolarisEntitySubType.ICEBERG_TABLE) { + if (!ATTACHABLE_ENTITY_TYPES.contains(entityType)) { return false; } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/DataCompactionPolicyValidator.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/DataCompactionPolicyValidator.java new file mode 100644 index 0000000000..8c68e4e790 --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/DataCompactionPolicyValidator.java @@ -0,0 +1,31 @@ +/* + * 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.maintenance; + +import org.apache.polaris.core.policy.content.maintenance.DataCompactionPolicyContent; +import org.apache.polaris.core.policy.validator.InvalidPolicyException; + +public class DataCompactionPolicyValidator extends BaseMaintenancePolicyValidator { + public static final DataCompactionPolicyValidator INSTANCE = new DataCompactionPolicyValidator(); + + @Override + public void validate(String content) throws InvalidPolicyException { + DataCompactionPolicyContent.fromString(content); + } +} diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/MetadataCompactionPolicyValidator.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/MetadataCompactionPolicyValidator.java new file mode 100644 index 0000000000..49ad0d3b6b --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/MetadataCompactionPolicyValidator.java @@ -0,0 +1,32 @@ +/* + * 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.maintenance; + +import org.apache.polaris.core.policy.content.maintenance.MetadataCompactionPolicyContent; +import org.apache.polaris.core.policy.validator.InvalidPolicyException; + +public class MetadataCompactionPolicyValidator extends BaseMaintenancePolicyValidator { + public static final MetadataCompactionPolicyValidator INSTANCE = + new MetadataCompactionPolicyValidator(); + + @Override + public void validate(String content) throws InvalidPolicyException { + MetadataCompactionPolicyContent.fromString(content); + } +} diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/OrphanFileRemovalPolicyValidator.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/OrphanFileRemovalPolicyValidator.java new file mode 100644 index 0000000000..342544d82e --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/OrphanFileRemovalPolicyValidator.java @@ -0,0 +1,32 @@ +/* + * 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.maintenance; + +import org.apache.polaris.core.policy.content.maintenance.OrphanFileRemovalPolicyContent; +import org.apache.polaris.core.policy.validator.InvalidPolicyException; + +public class OrphanFileRemovalPolicyValidator extends BaseMaintenancePolicyValidator { + public static final OrphanFileRemovalPolicyValidator INSTANCE = + new OrphanFileRemovalPolicyValidator(); + + @Override + public void validate(String content) throws InvalidPolicyException { + OrphanFileRemovalPolicyContent.fromString(content); + } +} diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/SnapshotRetentionPolicyValidator.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/SnapshotRetentionPolicyValidator.java new file mode 100644 index 0000000000..ce0645a49e --- /dev/null +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/SnapshotRetentionPolicyValidator.java @@ -0,0 +1,32 @@ +/* + * 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.maintenance; + +import org.apache.polaris.core.policy.content.maintenance.SnapshotRetentionPolicyContent; +import org.apache.polaris.core.policy.validator.InvalidPolicyException; + +public class SnapshotRetentionPolicyValidator extends BaseMaintenancePolicyValidator { + public static final SnapshotRetentionPolicyValidator INSTANCE = + new SnapshotRetentionPolicyValidator(); + + @Override + public void validate(String content) throws InvalidPolicyException { + SnapshotRetentionPolicyContent.fromString(content); + } +} 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 index 3d70fbeeff..ad30fb8931 100644 --- 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 @@ -18,7 +18,7 @@ */ package org.apache.polaris.core.policy.validator; -import static org.apache.polaris.core.policy.validator.datacompaction.DataCompactionPolicyContent.fromString; +import static org.apache.polaris.core.policy.content.maintenance.DataCompactionPolicyContent.fromString; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; 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 18205763fa..0000000000 --- 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/MetadataCompactionPolicyContentTest.java b/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/MetadataCompactionPolicyContentTest.java new file mode 100644 index 0000000000..72a8d6c522 --- /dev/null +++ b/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/MetadataCompactionPolicyContentTest.java @@ -0,0 +1,97 @@ +/* + * 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.content.maintenance.MetadataCompactionPolicyContent.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 MetadataCompactionPolicyContentTest { + @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/PolicyValidatorsTest.java b/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/PolicyValidatorsTest.java index 24d122a119..42bd5963b0 100644 --- 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 @@ -18,12 +18,20 @@ */ package org.apache.polaris.core.policy.validator; +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.apache.polaris.core.policy.PredefinedPolicyTypes.METADATA_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.IcebergTableLikeEntity; +import org.apache.polaris.core.entity.NamespaceEntity; +import org.apache.polaris.core.entity.PrincipalEntity; import org.apache.polaris.core.policy.PolicyEntity; +import org.apache.polaris.core.policy.PolicyType; import org.junit.jupiter.api.Test; public class PolicyValidatorsTest { @@ -42,15 +50,29 @@ public void testInvalidPolicy() { @Test public void testUnsupportedPolicyType() { - var policyEntity = - new PolicyEntity.Builder(Namespace.of("NS1"), "testPolicy", METADATA_COMPACTION) - .setContent("InvalidContent") - .setPolicyVersion(0) - .build(); + 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(InvalidPolicyException.class) - .hasMessageContaining("Unsupported policy type"); + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Unknown policy type:"); } @Test @@ -62,4 +84,49 @@ public void testValidPolicy() { .build(); PolicyValidators.validate(policyEntity); } + + Namespace ns = Namespace.of("NS1"); + TableIdentifier tableIdentifier = TableIdentifier.of(ns, "table1"); + PolicyEntity policyEntity = new PolicyEntity.Builder(ns, "pn", DATA_COMPACTION).build(); + + @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"); + } } From c301c44475aff82d882542c0f7c7b0c232606a9c Mon Sep 17 00:00:00 2001 From: Yufei Gu Date: Wed, 26 Mar 2025 15:41:55 -0700 Subject: [PATCH 2/5] Add Policy contents and validators --- .../BaseMaintenancePolicyContent.java | 2 +- .../DataCompactionPolicyContent.java | 38 +--- .../OrphanFileRemovalPolicyContent.java | 12 ++ .../orphan-file-removal/2025-02-03.json | 2 +- .../policy/MaintenancePolicyContentTest.java | 165 ++++++++++++++++++ .../{validator => }/PolicyValidatorsTest.java | 20 +-- .../DataCompactionPolicyContentTest.java | 97 ---------- .../MetadataCompactionPolicyContentTest.java | 97 ---------- 8 files changed, 191 insertions(+), 242 deletions(-) create mode 100644 polaris-core/src/test/java/org/apache/polaris/core/policy/MaintenancePolicyContentTest.java rename polaris-core/src/test/java/org/apache/polaris/core/policy/{validator => }/PolicyValidatorsTest.java (92%) delete mode 100644 polaris-core/src/test/java/org/apache/polaris/core/policy/validator/DataCompactionPolicyContentTest.java delete mode 100644 polaris-core/src/test/java/org/apache/polaris/core/policy/validator/MetadataCompactionPolicyContentTest.java diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java index b8a84c553b..2d989d7be5 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java @@ -25,7 +25,7 @@ import org.apache.polaris.core.policy.content.PolicyContent; import org.apache.polaris.core.policy.content.StrictBooleanDeserializer; -public class BaseMaintenancePolicyContent implements PolicyContent { +public abstract class BaseMaintenancePolicyContent implements PolicyContent { @JsonDeserialize(using = StrictBooleanDeserializer.class) private Boolean enable; diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java index f96d313273..6441299229 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java @@ -20,53 +20,19 @@ 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.content.PolicyContent; import org.apache.polaris.core.policy.content.PolicyContentUtil; -import org.apache.polaris.core.policy.content.StrictBooleanDeserializer; import org.apache.polaris.core.policy.validator.InvalidPolicyException; -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 POLICY_SCHEMA_VERSIONS = Set.of(DEFAULT_POLICY_SCHEMA_VERSION); - @JsonDeserialize(using = StrictBooleanDeserializer.class) - private Boolean enable; - - private String version; - private Map 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 getConfig() { - return config; - } - - public void setConfig(Map config) { - this.config = config; + super(enable); } public static DataCompactionPolicyContent fromString(String content) { 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 index e7925bdbf1..aeae79ae46 100644 --- 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 @@ -21,6 +21,7 @@ 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; @@ -29,8 +30,11 @@ public class OrphanFileRemovalPolicyContent extends BaseMaintenancePolicyContent private static final String DEFAULT_POLICY_SCHEMA_VERSION = "2025-02-03"; private static final Set POLICY_SCHEMA_VERSIONS = Set.of(DEFAULT_POLICY_SCHEMA_VERSION); + @JsonProperty(value = "max_orphan_file_age_in_days") private int maxOrphanFileAgeInDays; + private List locations; + @JsonCreator public OrphanFileRemovalPolicyContent( @JsonProperty(value = "enable", required = true) boolean enable) { @@ -45,6 +49,14 @@ public void setMaxOrphanFileAgeInDays(int maxOrphanFileAgeInDays) { this.maxOrphanFileAgeInDays = maxOrphanFileAgeInDays; } + public List getLocations() { + return locations; + } + + public void setLocations(List locations) { + this.locations = locations; + } + public static OrphanFileRemovalPolicyContent fromString(String content) { if (Strings.isNullOrEmpty(content)) { throw new InvalidPolicyException("Policy is empty"); 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 19f35deca3..c7c14e67a6 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", + "location": ["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 0000000000..ab26377a5a --- /dev/null +++ b/polaris-core/src/test/java/org/apache/polaris/core/policy/MaintenancePolicyContentTest.java @@ -0,0 +1,165 @@ +/* + * 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 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 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 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/"); + } +} 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/PolicyValidatorsTest.java similarity index 92% rename from polaris-core/src/test/java/org/apache/polaris/core/policy/validator/PolicyValidatorsTest.java rename to polaris-core/src/test/java/org/apache/polaris/core/policy/PolicyValidatorsTest.java index 42bd5963b0..04435ba734 100644 --- 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/PolicyValidatorsTest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.polaris.core.policy.validator; +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; @@ -27,18 +27,22 @@ 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.IcebergTableLikeEntity; import org.apache.polaris.core.entity.NamespaceEntity; import org.apache.polaris.core.entity.PrincipalEntity; -import org.apache.polaris.core.policy.PolicyEntity; -import org.apache.polaris.core.policy.PolicyType; +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(Namespace.of("NS1"), "testPolicy", DATA_COMPACTION) + new PolicyEntity.Builder(ns, "testPolicy", DATA_COMPACTION) .setContent("InvalidContent") .setPolicyVersion(0) .build(); @@ -78,17 +82,13 @@ public boolean isInheritable() { @Test public void testValidPolicy() { var policyEntity = - new PolicyEntity.Builder(Namespace.of("NS1"), "testPolicy", DATA_COMPACTION) + new PolicyEntity.Builder(ns, "testPolicy", DATA_COMPACTION) .setContent("{\"enable\": false}") .setPolicyVersion(0) .build(); PolicyValidators.validate(policyEntity); } - Namespace ns = Namespace.of("NS1"); - TableIdentifier tableIdentifier = TableIdentifier.of(ns, "table1"); - PolicyEntity policyEntity = new PolicyEntity.Builder(ns, "pn", DATA_COMPACTION).build(); - @Test public void testCanAttachReturnsTrueForCatalogType() { var targetEntity = new CatalogEntity.Builder().build(); 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 ad30fb8931..0000000000 --- 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.content.maintenance.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/MetadataCompactionPolicyContentTest.java b/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/MetadataCompactionPolicyContentTest.java deleted file mode 100644 index 72a8d6c522..0000000000 --- a/polaris-core/src/test/java/org/apache/polaris/core/policy/validator/MetadataCompactionPolicyContentTest.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.content.maintenance.MetadataCompactionPolicyContent.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 MetadataCompactionPolicyContentTest { - @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"); - } -} From 128efe20e83f6a4918483e634323bb8c84ff7300 Mon Sep 17 00:00:00 2001 From: Yufei Gu Date: Wed, 26 Mar 2025 15:49:27 -0700 Subject: [PATCH 3/5] Minor fix --- .../schemas/policies/system/orphan-file-removal/2025-02-03.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c7c14e67a6..f7b00d1e4e 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" From 20f3aa20c88f8d7e45a1d6a823deae0ab6c83833 Mon Sep 17 00:00:00 2001 From: Yufei Gu Date: Wed, 26 Mar 2025 17:43:04 -0700 Subject: [PATCH 4/5] Resolve comments --- .../DataCompactionPolicyContent.java | 29 ++++++++------- .../MetadataCompactionPolicyContent.java | 29 ++++++++------- .../OrphanFileRemovalPolicyContent.java | 37 ++++++++++++------- .../SnapshotRetentionPolicyContent.java | 29 ++++++++------- .../BaseMaintenancePolicyValidator.java | 4 +- .../policy/MaintenancePolicyContentTest.java | 16 ++++++++ 6 files changed, 86 insertions(+), 58 deletions(-) diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java index 6441299229..6ca58a72f4 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java @@ -40,24 +40,25 @@ public static DataCompactionPolicyContent fromString(String content) { throw new InvalidPolicyException("Policy is empty"); } + DataCompactionPolicyContent policy; try { - DataCompactionPolicyContent policy = - PolicyContentUtil.MAPPER.readValue(content, DataCompactionPolicyContent.class); - if (policy == null) { - throw new InvalidPolicyException("Invalid policy"); - } + policy = PolicyContentUtil.MAPPER.readValue(content, DataCompactionPolicyContent.class); + } catch (Exception e) { + throw new InvalidPolicyException(e); + } - if (Strings.isNullOrEmpty(policy.getVersion())) { - policy.setVersion(DEFAULT_POLICY_SCHEMA_VERSION); - } + if (policy == null) { + throw new InvalidPolicyException("Invalid policy: " + content); + } - if (!POLICY_SCHEMA_VERSIONS.contains(policy.getVersion())) { - throw new InvalidPolicyException("Invalid policy version: " + policy.getVersion()); - } + if (Strings.isNullOrEmpty(policy.getVersion())) { + policy.setVersion(DEFAULT_POLICY_SCHEMA_VERSION); + } - return policy; - } catch (Exception e) { - throw new InvalidPolicyException(e); + if (!POLICY_SCHEMA_VERSIONS.contains(policy.getVersion())) { + throw new InvalidPolicyException("Invalid policy version: " + policy.getVersion()); } + + 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 index 8929cd44ff..15f8570fa9 100644 --- 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 @@ -40,24 +40,25 @@ public static MetadataCompactionPolicyContent fromString(String content) { throw new InvalidPolicyException("Policy is empty"); } + MetadataCompactionPolicyContent policy; try { - MetadataCompactionPolicyContent policy = - PolicyContentUtil.MAPPER.readValue(content, MetadataCompactionPolicyContent.class); - if (policy == null) { - throw new InvalidPolicyException("Invalid policy"); - } + policy = PolicyContentUtil.MAPPER.readValue(content, MetadataCompactionPolicyContent.class); + } catch (Exception e) { + throw new InvalidPolicyException(e); + } - if (Strings.isNullOrEmpty(policy.getVersion())) { - policy.setVersion(DEFAULT_POLICY_SCHEMA_VERSION); - } + if (policy == null) { + throw new InvalidPolicyException("Invalid policy: " + content); + } - if (!POLICY_SCHEMA_VERSIONS.contains(policy.getVersion())) { - throw new InvalidPolicyException("Invalid policy version: " + policy.getVersion()); - } + if (Strings.isNullOrEmpty(policy.getVersion())) { + policy.setVersion(DEFAULT_POLICY_SCHEMA_VERSION); + } - return policy; - } catch (Exception e) { - throw new InvalidPolicyException(e); + if (!POLICY_SCHEMA_VERSIONS.contains(policy.getVersion())) { + throw new InvalidPolicyException("Invalid policy version: " + policy.getVersion()); } + + 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 index aeae79ae46..98f9c5aff4 100644 --- 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 @@ -62,24 +62,33 @@ public static OrphanFileRemovalPolicyContent fromString(String content) { throw new InvalidPolicyException("Policy is empty"); } + OrphanFileRemovalPolicyContent policy; try { - OrphanFileRemovalPolicyContent policy = - PolicyContentUtil.MAPPER.readValue(content, OrphanFileRemovalPolicyContent.class); - if (policy == null) { - throw new InvalidPolicyException("Invalid policy"); - } + policy = PolicyContentUtil.MAPPER.readValue(content, OrphanFileRemovalPolicyContent.class); + } catch (Exception e) { + throw new InvalidPolicyException(e); + } + + if (policy == null) { + throw new InvalidPolicyException("Invalid policy: " + content); + } - if (Strings.isNullOrEmpty(policy.getVersion())) { - policy.setVersion(DEFAULT_POLICY_SCHEMA_VERSION); - } + 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 (!POLICY_SCHEMA_VERSIONS.contains(policy.getVersion())) { + throw new InvalidPolicyException("Invalid policy version: " + policy.getVersion()); + } - return policy; - } catch (Exception e) { - throw new InvalidPolicyException(e); + 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 index f477873a83..2bdbbcd352 100644 --- 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 @@ -40,24 +40,25 @@ public static SnapshotRetentionPolicyContent fromString(String content) { throw new InvalidPolicyException("Policy is empty"); } + SnapshotRetentionPolicyContent policy; try { - SnapshotRetentionPolicyContent policy = - PolicyContentUtil.MAPPER.readValue(content, SnapshotRetentionPolicyContent.class); - if (policy == null) { - throw new InvalidPolicyException("Invalid policy"); - } + policy = PolicyContentUtil.MAPPER.readValue(content, SnapshotRetentionPolicyContent.class); + } catch (Exception e) { + throw new InvalidPolicyException(e); + } - if (Strings.isNullOrEmpty(policy.getVersion())) { - policy.setVersion(DEFAULT_POLICY_SCHEMA_VERSION); - } + if (policy == null) { + throw new InvalidPolicyException("Invalid policy: " + content); + } - if (!POLICY_SCHEMA_VERSIONS.contains(policy.getVersion())) { - throw new InvalidPolicyException("Invalid policy version: " + policy.getVersion()); - } + if (Strings.isNullOrEmpty(policy.getVersion())) { + policy.setVersion(DEFAULT_POLICY_SCHEMA_VERSION); + } - return policy; - } catch (Exception e) { - throw new InvalidPolicyException(e); + if (!POLICY_SCHEMA_VERSIONS.contains(policy.getVersion())) { + throw new InvalidPolicyException("Invalid policy version: " + policy.getVersion()); } + + return policy; } } diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java index efecc3dfa3..8e6116ae28 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java @@ -37,11 +37,11 @@ public boolean canAttach(PolarisEntityType entityType, PolarisEntitySubType enti return false; } - if (entityType == TABLE_LIKE && entitySubType != PolarisEntitySubType.ICEBERG_TABLE) { + if (!ATTACHABLE_ENTITY_TYPES.contains(entityType)) { return false; } - if (!ATTACHABLE_ENTITY_TYPES.contains(entityType)) { + if (entityType == TABLE_LIKE && entitySubType != PolarisEntitySubType.ICEBERG_TABLE) { return false; } 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 index ab26377a5a..1b5972a05f 100644 --- 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 @@ -84,6 +84,15 @@ void testIsValidEmptyString(PredefinedPolicyTypes policyTypes) { .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) { @@ -162,4 +171,11 @@ public void testValidOrphanFileRemovalPolicyContent() { .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"); + } } From 482d9337360bde75f53c2c8e90367e5a8a91fb78 Mon Sep 17 00:00:00 2001 From: Yufei Gu Date: Thu, 27 Mar 2025 11:53:45 -0700 Subject: [PATCH 5/5] Resolve comments --- .../BaseMaintenancePolicyContent.java | 21 ++++++++++++ .../DataCompactionPolicyContent.java | 12 +------ .../MetadataCompactionPolicyContent.java | 12 +------ .../OrphanFileRemovalPolicyContent.java | 12 +------ .../SnapshotRetentionPolicyContent.java | 12 +------ .../policy/validator/PolicyValidators.java | 22 ++++++------- .../BaseMaintenancePolicyValidator.java | 9 +++++- .../DataCompactionPolicyValidator.java | 31 ------------------ .../MetadataCompactionPolicyValidator.java | 32 ------------------- .../OrphanFileRemovalPolicyValidator.java | 32 ------------------- .../SnapshotRetentionPolicyValidator.java | 32 ------------------- 11 files changed, 43 insertions(+), 184 deletions(-) delete mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/DataCompactionPolicyValidator.java delete mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/MetadataCompactionPolicyValidator.java delete mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/OrphanFileRemovalPolicyValidator.java delete mode 100644 polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/SnapshotRetentionPolicyValidator.java diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java index 2d989d7be5..a825e87ba3 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/BaseMaintenancePolicyContent.java @@ -21,9 +21,12 @@ 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.content.PolicyContent; import org.apache.polaris.core.policy.content.StrictBooleanDeserializer; +import org.apache.polaris.core.policy.validator.InvalidPolicyException; public abstract class BaseMaintenancePolicyContent implements PolicyContent { @JsonDeserialize(using = StrictBooleanDeserializer.class) @@ -61,4 +64,22 @@ public Map getConfig() { public void setConfig(Map config) { this.config = config; } + + static void validateVersion( + String content, + BaseMaintenancePolicyContent policy, + String defaultVersion, + Set allVersions) { + if (policy == null) { + throw new InvalidPolicyException("Invalid policy: " + content); + } + + if (Strings.isNullOrEmpty(policy.getVersion())) { + policy.setVersion(defaultVersion); + } + + 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/content/maintenance/DataCompactionPolicyContent.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java index 6ca58a72f4..a5a4012c49 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/content/maintenance/DataCompactionPolicyContent.java @@ -47,17 +47,7 @@ public static DataCompactionPolicyContent fromString(String content) { throw new InvalidPolicyException(e); } - if (policy == null) { - throw new InvalidPolicyException("Invalid policy: " + content); - } - - 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()); - } + 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 index 15f8570fa9..a22ca2d527 100644 --- 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 @@ -47,17 +47,7 @@ public static MetadataCompactionPolicyContent fromString(String content) { throw new InvalidPolicyException(e); } - if (policy == null) { - throw new InvalidPolicyException("Invalid policy: " + content); - } - - 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()); - } + 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 index 98f9c5aff4..0adf0ed505 100644 --- 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 @@ -69,17 +69,7 @@ public static OrphanFileRemovalPolicyContent fromString(String content) { throw new InvalidPolicyException(e); } - if (policy == null) { - throw new InvalidPolicyException("Invalid policy: " + content); - } - - 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()); - } + validateVersion(content, policy, DEFAULT_POLICY_SCHEMA_VERSION, POLICY_SCHEMA_VERSIONS); int maxAge = policy.getMaxOrphanFileAgeInDays(); if (maxAge < 0) { 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 index 2bdbbcd352..ecb3e3d6c2 100644 --- 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 @@ -47,17 +47,7 @@ public static SnapshotRetentionPolicyContent fromString(String content) { throw new InvalidPolicyException(e); } - if (policy == null) { - throw new InvalidPolicyException("Invalid policy: " + content); - } - - 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()); - } + 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 fb27b3cb12..3ccb2f6d2e 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,10 +22,11 @@ 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.maintenance.DataCompactionPolicyValidator; -import org.apache.polaris.core.policy.validator.maintenance.MetadataCompactionPolicyValidator; -import org.apache.polaris.core.policy.validator.maintenance.OrphanFileRemovalPolicyValidator; -import org.apache.polaris.core.policy.validator.maintenance.SnapshotRetentionPolicyValidator; +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; @@ -53,16 +54,16 @@ public static void validate(PolicyEntity policy) { switch (type) { case DATA_COMPACTION: - DataCompactionPolicyValidator.INSTANCE.validate(policy.getContent()); + DataCompactionPolicyContent.fromString(policy.getContent()); break; case METADATA_COMPACTION: - MetadataCompactionPolicyValidator.INSTANCE.validate(policy.getContent()); + MetadataCompactionPolicyContent.fromString(policy.getContent()); break; case SNAPSHOT_RETENTION: - SnapshotRetentionPolicyValidator.INSTANCE.validate(policy.getContent()); + SnapshotRetentionPolicyContent.fromString(policy.getContent()); break; case ORPHAN_FILE_REMOVAL: - OrphanFileRemovalPolicyValidator.INSTANCE.validate(policy.getContent()); + OrphanFileRemovalPolicyContent.fromString(policy.getContent()); break; default: throw new IllegalArgumentException("Unsupported policy type: " + type.getName()); @@ -91,13 +92,10 @@ public static boolean canAttach(PolicyEntity policy, PolarisEntity targetEntity) switch (policyType) { case DATA_COMPACTION: - return DataCompactionPolicyValidator.INSTANCE.canAttach(entityType, entitySubType); case METADATA_COMPACTION: - return MetadataCompactionPolicyValidator.INSTANCE.canAttach(entityType, entitySubType); case SNAPSHOT_RETENTION: - return SnapshotRetentionPolicyValidator.INSTANCE.canAttach(entityType, entitySubType); case ORPHAN_FILE_REMOVAL: - return OrphanFileRemovalPolicyValidator.INSTANCE.canAttach(entityType, entitySubType); + return BaseMaintenancePolicyValidator.INSTANCE.canAttach(entityType, entitySubType); default: LOGGER.warn("Attachment not supported for policy type: {}", policyType.getName()); diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java index 8e6116ae28..86308f5559 100644 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java +++ b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/BaseMaintenancePolicyValidator.java @@ -25,12 +25,19 @@ import java.util.Set; import org.apache.polaris.core.entity.PolarisEntitySubType; import org.apache.polaris.core.entity.PolarisEntityType; +import org.apache.polaris.core.policy.validator.InvalidPolicyException; import org.apache.polaris.core.policy.validator.PolicyValidator; -public abstract class BaseMaintenancePolicyValidator implements PolicyValidator { +public class BaseMaintenancePolicyValidator implements PolicyValidator { + public static final BaseMaintenancePolicyValidator INSTANCE = + new BaseMaintenancePolicyValidator(); + private static final Set ATTACHABLE_ENTITY_TYPES = Set.of(CATALOG, NAMESPACE, TABLE_LIKE); + @Override + public void validate(String content) throws InvalidPolicyException {} + @Override public boolean canAttach(PolarisEntityType entityType, PolarisEntitySubType entitySubType) { if (entityType == null) { diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/DataCompactionPolicyValidator.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/DataCompactionPolicyValidator.java deleted file mode 100644 index 8c68e4e790..0000000000 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/DataCompactionPolicyValidator.java +++ /dev/null @@ -1,31 +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.maintenance; - -import org.apache.polaris.core.policy.content.maintenance.DataCompactionPolicyContent; -import org.apache.polaris.core.policy.validator.InvalidPolicyException; - -public class DataCompactionPolicyValidator extends BaseMaintenancePolicyValidator { - public static final DataCompactionPolicyValidator INSTANCE = new DataCompactionPolicyValidator(); - - @Override - public void validate(String content) throws InvalidPolicyException { - DataCompactionPolicyContent.fromString(content); - } -} diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/MetadataCompactionPolicyValidator.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/MetadataCompactionPolicyValidator.java deleted file mode 100644 index 49ad0d3b6b..0000000000 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/MetadataCompactionPolicyValidator.java +++ /dev/null @@ -1,32 +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.maintenance; - -import org.apache.polaris.core.policy.content.maintenance.MetadataCompactionPolicyContent; -import org.apache.polaris.core.policy.validator.InvalidPolicyException; - -public class MetadataCompactionPolicyValidator extends BaseMaintenancePolicyValidator { - public static final MetadataCompactionPolicyValidator INSTANCE = - new MetadataCompactionPolicyValidator(); - - @Override - public void validate(String content) throws InvalidPolicyException { - MetadataCompactionPolicyContent.fromString(content); - } -} diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/OrphanFileRemovalPolicyValidator.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/OrphanFileRemovalPolicyValidator.java deleted file mode 100644 index 342544d82e..0000000000 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/OrphanFileRemovalPolicyValidator.java +++ /dev/null @@ -1,32 +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.maintenance; - -import org.apache.polaris.core.policy.content.maintenance.OrphanFileRemovalPolicyContent; -import org.apache.polaris.core.policy.validator.InvalidPolicyException; - -public class OrphanFileRemovalPolicyValidator extends BaseMaintenancePolicyValidator { - public static final OrphanFileRemovalPolicyValidator INSTANCE = - new OrphanFileRemovalPolicyValidator(); - - @Override - public void validate(String content) throws InvalidPolicyException { - OrphanFileRemovalPolicyContent.fromString(content); - } -} diff --git a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/SnapshotRetentionPolicyValidator.java b/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/SnapshotRetentionPolicyValidator.java deleted file mode 100644 index ce0645a49e..0000000000 --- a/polaris-core/src/main/java/org/apache/polaris/core/policy/validator/maintenance/SnapshotRetentionPolicyValidator.java +++ /dev/null @@ -1,32 +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.maintenance; - -import org.apache.polaris.core.policy.content.maintenance.SnapshotRetentionPolicyContent; -import org.apache.polaris.core.policy.validator.InvalidPolicyException; - -public class SnapshotRetentionPolicyValidator extends BaseMaintenancePolicyValidator { - public static final SnapshotRetentionPolicyValidator INSTANCE = - new SnapshotRetentionPolicyValidator(); - - @Override - public void validate(String content) throws InvalidPolicyException { - SnapshotRetentionPolicyContent.fromString(content); - } -}