jerryshao commented on code in PR #7821: URL: https://github.com/apache/gravitino/pull/7821#discussion_r2258704636
########## common/src/main/java/org/apache/gravitino/dto/policy/PolicyDTO.java: ########## @@ -0,0 +1,298 @@ +/* + * 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.gravitino.dto.policy; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.google.common.base.Preconditions; +import java.util.Collections; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import lombok.ToString; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.dto.AuditDTO; +import org.apache.gravitino.policy.Policy; + +/** Represents a Policy Data Transfer Object (DTO). */ +@ToString +public class PolicyDTO implements Policy { + + @JsonProperty("name") + private String name; + + @JsonProperty("comment") + private String comment; + + @JsonProperty("policyType") + private String policyType; + + @JsonProperty("enabled") + private boolean enabled; + + @JsonProperty("exclusive") + private boolean exclusive; + + @JsonProperty("inheritable") + private boolean inheritable; + + @JsonProperty("supportedObjectTypes") + private Set<MetadataObject.Type> supportedObjectTypes = Collections.emptySet(); + + @JsonProperty("content") + @JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXTERNAL_PROPERTY, + property = "policyType", + defaultImpl = PolicyContentDTO.CustomContentDTO.class) + @JsonSubTypes({ + // add mappings for built-in types here + // For example: @JsonSubTypes.Type(value = DataCompactionContent.class, name = + // "system_data_compaction") + }) Review Comment: Does it work as we don't have built-in policy for now? ########## common/src/main/java/org/apache/gravitino/dto/policy/PolicyContentDTO.java: ########## @@ -0,0 +1,67 @@ +/* + * 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.gravitino.dto.policy; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.apache.gravitino.policy.PolicyContent; + +/** Represents a Policy Content Data Transfer Object (DTO). */ +public interface PolicyContentDTO extends PolicyContent { + + /** Represents a custom policy content DTO. */ + @EqualsAndHashCode + @ToString + @Builder(setterPrefix = "with") + @AllArgsConstructor Review Comment: Do we need this `@AllArgsConstructor`? I don't think we need this since we already have a builder. ########## common/src/main/java/org/apache/gravitino/dto/requests/PolicyUpdateRequest.java: ########## @@ -0,0 +1,175 @@ +/* + * 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.gravitino.dto.requests; + +import static org.apache.gravitino.dto.util.DTOConverters.fromDTO; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.google.common.base.Preconditions; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import org.apache.commons.lang3.StringUtils; +import org.apache.gravitino.dto.policy.PolicyContentDTO; +import org.apache.gravitino.policy.PolicyChange; +import org.apache.gravitino.rest.RESTRequest; + +/** Represents a request to update a policy. */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY) +@JsonSubTypes({ + @JsonSubTypes.Type(value = PolicyUpdateRequest.RenamePolicyRequest.class, name = "rename"), + @JsonSubTypes.Type( + value = PolicyUpdateRequest.UpdatePolicyCommentRequest.class, + name = "updateComment"), + @JsonSubTypes.Type( + value = PolicyUpdateRequest.UpdatePolicyContentRequest.class, + name = "updateContent") +}) +public interface PolicyUpdateRequest extends RESTRequest { Review Comment: Can you also add a test to verify the polymorphism of the `PolicyUpdateRequest`. ########## common/src/main/java/org/apache/gravitino/dto/requests/PolicyCreateRequest.java: ########## @@ -0,0 +1,170 @@ +/* + * 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.gravitino.dto.requests; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.google.common.base.Preconditions; +import java.util.Set; +import javax.annotation.Nullable; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import org.apache.commons.lang3.StringUtils; +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.dto.policy.PolicyContentDTO; +import org.apache.gravitino.policy.Policy; +import org.apache.gravitino.rest.RESTRequest; + +/** Represents a request to create a policy. */ +@Getter +@EqualsAndHashCode +@ToString +public class PolicyCreateRequest implements RESTRequest { + + @JsonProperty("name") + private final String name; + + @JsonProperty("comment") + @Nullable + private final String comment; + + @JsonProperty("policyType") + private final String policyType; + + @JsonProperty(value = "enabled", defaultValue = "true") + private final Boolean enabled; + + @JsonProperty("content") + @JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXTERNAL_PROPERTY, + property = "policyType", + defaultImpl = PolicyContentDTO.CustomContentDTO.class) + @JsonSubTypes({ + // add mappings for built-in types here + // For example: @JsonSubTypes.Type(value = DataCompactionContent.class, name = + // "system_data_compaction") + }) Review Comment: Can you please add the test to verify the polymorphism of the `PolicyContent`. ########## server/src/main/java/org/apache/gravitino/server/web/rest/PolicyOperations.java: ########## @@ -0,0 +1,273 @@ +/* + * 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.gravitino.server.web.rest; + +import static org.apache.gravitino.dto.util.DTOConverters.fromDTO; + +import com.codahale.metrics.annotation.ResponseMetered; +import com.codahale.metrics.annotation.Timed; +import java.util.Arrays; +import java.util.Optional; +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.PATCH; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.gravitino.dto.policy.PolicyDTO; +import org.apache.gravitino.dto.requests.PolicyCreateRequest; +import org.apache.gravitino.dto.requests.PolicySetRequest; +import org.apache.gravitino.dto.requests.PolicyUpdateRequest; +import org.apache.gravitino.dto.requests.PolicyUpdatesRequest; +import org.apache.gravitino.dto.responses.BaseResponse; +import org.apache.gravitino.dto.responses.DropResponse; +import org.apache.gravitino.dto.responses.NameListResponse; +import org.apache.gravitino.dto.responses.PolicyListResponse; +import org.apache.gravitino.dto.responses.PolicyResponse; +import org.apache.gravitino.dto.util.DTOConverters; +import org.apache.gravitino.metrics.MetricNames; +import org.apache.gravitino.policy.Policy; +import org.apache.gravitino.policy.PolicyChange; +import org.apache.gravitino.policy.PolicyDispatcher; +import org.apache.gravitino.server.web.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Path("metalakes/{metalake}/policies") +public class PolicyOperations { + + private static final Logger LOG = LoggerFactory.getLogger(PolicyOperations.class); + + private final PolicyDispatcher policyDispatcher; + + @Context private HttpServletRequest httpRequest; + + @Inject + public PolicyOperations(PolicyDispatcher policyDispatcher) { + this.policyDispatcher = policyDispatcher; + } + + @GET + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "list-policies." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "list-policies", absolute = true) + public Response listPolicies( + @PathParam("metalake") String metalake, + @QueryParam("details") @DefaultValue("false") boolean verbose) { + LOG.info( + "Received list policy {} request for metalake: {}", verbose ? "infos" : "names", metalake); + + try { + return Utils.doAs( + httpRequest, + () -> { + if (verbose) { + Policy[] policies = policyDispatcher.listPolicyInfos(metalake); + PolicyDTO[] policyDTOs; + if (ArrayUtils.isEmpty(policies)) { + policyDTOs = new PolicyDTO[0]; + } else { + policyDTOs = + Arrays.stream(policies) + .map(p -> DTOConverters.toDTO(p, Optional.empty())) + .toArray(PolicyDTO[]::new); + } + + LOG.info("List {} policies info under metalake: {}", policyDTOs.length, metalake); + return Utils.ok(new PolicyListResponse(policyDTOs)); + + } else { + String[] policyNames = policyDispatcher.listPolicies(metalake); + policyNames = policyNames == null ? new String[0] : policyNames; + + LOG.info("List {} policies under metalake: {}", policyNames.length, metalake); + return Utils.ok(new NameListResponse(policyNames)); + } + }); + } catch (Exception e) { + return ExceptionHandlers.handlePolicyException(OperationType.LIST, "", metalake, e); + } + } + + @POST + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "create-policy." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "create-policy", absolute = true) + public Response createPolicy( + @PathParam("metalake") String metalake, PolicyCreateRequest request) { + LOG.info("Received create policy request under metalake: {}", metalake); + + try { + return Utils.doAs( + httpRequest, + () -> { + request.validate(); + Policy policy = + Policy.BuiltInType.fromPolicyType(request.getPolicyType()) + == Policy.BuiltInType.CUSTOM + ? policyDispatcher.createPolicy( + metalake, + request.getName(), + request.getPolicyType(), + request.getComment(), + request.getEnabled(), + request.getExclusive(), + request.getInheritable(), + request.getSupportedObjectTypes(), + fromDTO(request.getPolicyContent())) + : policyDispatcher.createPolicy( + metalake, + request.getName(), + request.getPolicyType(), + request.getComment(), + request.getEnabled(), + fromDTO(request.getPolicyContent())); + + LOG.info("Created policy: {} under metalake: {}", policy.name(), metalake); + return Utils.ok(new PolicyResponse(DTOConverters.toDTO(policy, Optional.empty()))); + }); + } catch (Exception e) { + return ExceptionHandlers.handlePolicyException( + OperationType.CREATE, request.getName(), metalake, e); + } + } + + @GET + @Path("{policy}") + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "get-policy." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "get-policy", absolute = true) + public Response getPolicy( + @PathParam("metalake") String metalake, @PathParam("policy") String name) { + LOG.info("Received get policy request for policy: {} under metalake: {}", name, metalake); + + try { + return Utils.doAs( + httpRequest, + () -> { + Policy policy = policyDispatcher.getPolicy(metalake, name); + LOG.info("Get policy: {} under metalake: {}", name, metalake); + return Utils.ok(new PolicyResponse(DTOConverters.toDTO(policy, Optional.empty()))); + }); + } catch (Exception e) { + return ExceptionHandlers.handlePolicyException(OperationType.GET, name, metalake, e); + } + } + + @PUT + @Path("{policy}") + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "alter-policy." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "alter-policy", absolute = true) + public Response alterPolicy( + @PathParam("metalake") String metalake, + @PathParam("policy") String name, + PolicyUpdatesRequest request) { + LOG.info("Received alter policy request for policy: {} under metalake: {}", name, metalake); + + try { + return Utils.doAs( + httpRequest, + () -> { + request.validate(); + + PolicyChange[] changes = + request.getUpdates().stream() + .map(PolicyUpdateRequest::policyChange) + .toArray(PolicyChange[]::new); + Policy policy = policyDispatcher.alterPolicy(metalake, name, changes); + + LOG.info("Altered policy: {} under metalake: {}", name, metalake); + return Utils.ok(new PolicyResponse(DTOConverters.toDTO(policy, Optional.empty()))); + }); + } catch (Exception e) { + return ExceptionHandlers.handlePolicyException(OperationType.ALTER, name, metalake, e); + } + } + + @PATCH + @Path("{policy}") + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "set-policy." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "set-policy", absolute = true) + public Response alterPolicy( + @PathParam("metalake") String metalake, + @PathParam("policy") String name, + PolicySetRequest request) { + LOG.info("Received set policy request for policy: {} under metalake: {}", name, metalake); + + try { + return Utils.doAs( + httpRequest, + () -> { + if (request.isEnable()) { + policyDispatcher.enablePolicy(metalake, name); + } else { + policyDispatcher.disablePolicy(metalake, name); + } + + Response response = Utils.ok(new BaseResponse()); + LOG.info( + "Successfully {} policy: {} under metalake: {}", + request.isEnable() ? "enabled" : "disabled", + name, + metalake); + return response; + }); + } catch (Exception e) { + return ExceptionHandlers.handlePolicyException(OperationType.ENABLE, name, metalake, e); + } + } + + @DELETE + @Path("{policy}") + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "delete-policy." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "delete-policy", absolute = true) + public Response deletePolicy( + @PathParam("metalake") String metalake, @PathParam("policy") String name) { + LOG.info("Received delete policy request for policy: {} under metalake: {}", name, metalake); + + try { + return Utils.doAs( + httpRequest, + () -> { + boolean deleted = policyDispatcher.deletePolicy(metalake, name); + if (!deleted) { + LOG.warn("Failed to delete policy {} under metalake {}", name, metalake); Review Comment: It is actually "Not found", not "Failed to delete", right? ########## server/src/main/java/org/apache/gravitino/server/web/rest/PolicyOperations.java: ########## @@ -0,0 +1,273 @@ +/* + * 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.gravitino.server.web.rest; + +import static org.apache.gravitino.dto.util.DTOConverters.fromDTO; + +import com.codahale.metrics.annotation.ResponseMetered; +import com.codahale.metrics.annotation.Timed; +import java.util.Arrays; +import java.util.Optional; +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.PATCH; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.gravitino.dto.policy.PolicyDTO; +import org.apache.gravitino.dto.requests.PolicyCreateRequest; +import org.apache.gravitino.dto.requests.PolicySetRequest; +import org.apache.gravitino.dto.requests.PolicyUpdateRequest; +import org.apache.gravitino.dto.requests.PolicyUpdatesRequest; +import org.apache.gravitino.dto.responses.BaseResponse; +import org.apache.gravitino.dto.responses.DropResponse; +import org.apache.gravitino.dto.responses.NameListResponse; +import org.apache.gravitino.dto.responses.PolicyListResponse; +import org.apache.gravitino.dto.responses.PolicyResponse; +import org.apache.gravitino.dto.util.DTOConverters; +import org.apache.gravitino.metrics.MetricNames; +import org.apache.gravitino.policy.Policy; +import org.apache.gravitino.policy.PolicyChange; +import org.apache.gravitino.policy.PolicyDispatcher; +import org.apache.gravitino.server.web.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Path("metalakes/{metalake}/policies") +public class PolicyOperations { + + private static final Logger LOG = LoggerFactory.getLogger(PolicyOperations.class); + + private final PolicyDispatcher policyDispatcher; + + @Context private HttpServletRequest httpRequest; + + @Inject + public PolicyOperations(PolicyDispatcher policyDispatcher) { + this.policyDispatcher = policyDispatcher; + } + + @GET + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "list-policies." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "list-policies", absolute = true) + public Response listPolicies( + @PathParam("metalake") String metalake, + @QueryParam("details") @DefaultValue("false") boolean verbose) { + LOG.info( + "Received list policy {} request for metalake: {}", verbose ? "infos" : "names", metalake); + + try { + return Utils.doAs( + httpRequest, + () -> { + if (verbose) { + Policy[] policies = policyDispatcher.listPolicyInfos(metalake); + PolicyDTO[] policyDTOs; + if (ArrayUtils.isEmpty(policies)) { + policyDTOs = new PolicyDTO[0]; + } else { + policyDTOs = + Arrays.stream(policies) + .map(p -> DTOConverters.toDTO(p, Optional.empty())) + .toArray(PolicyDTO[]::new); + } + + LOG.info("List {} policies info under metalake: {}", policyDTOs.length, metalake); + return Utils.ok(new PolicyListResponse(policyDTOs)); + + } else { + String[] policyNames = policyDispatcher.listPolicies(metalake); + policyNames = policyNames == null ? new String[0] : policyNames; + + LOG.info("List {} policies under metalake: {}", policyNames.length, metalake); + return Utils.ok(new NameListResponse(policyNames)); + } + }); + } catch (Exception e) { + return ExceptionHandlers.handlePolicyException(OperationType.LIST, "", metalake, e); + } + } + + @POST + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "create-policy." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "create-policy", absolute = true) + public Response createPolicy( + @PathParam("metalake") String metalake, PolicyCreateRequest request) { + LOG.info("Received create policy request under metalake: {}", metalake); + + try { + return Utils.doAs( + httpRequest, + () -> { + request.validate(); + Policy policy = + Policy.BuiltInType.fromPolicyType(request.getPolicyType()) + == Policy.BuiltInType.CUSTOM + ? policyDispatcher.createPolicy( + metalake, + request.getName(), + request.getPolicyType(), + request.getComment(), + request.getEnabled(), + request.getExclusive(), + request.getInheritable(), + request.getSupportedObjectTypes(), + fromDTO(request.getPolicyContent())) + : policyDispatcher.createPolicy( + metalake, + request.getName(), + request.getPolicyType(), + request.getComment(), + request.getEnabled(), + fromDTO(request.getPolicyContent())); + + LOG.info("Created policy: {} under metalake: {}", policy.name(), metalake); + return Utils.ok(new PolicyResponse(DTOConverters.toDTO(policy, Optional.empty()))); + }); + } catch (Exception e) { + return ExceptionHandlers.handlePolicyException( + OperationType.CREATE, request.getName(), metalake, e); + } + } + + @GET + @Path("{policy}") + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "get-policy." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "get-policy", absolute = true) + public Response getPolicy( + @PathParam("metalake") String metalake, @PathParam("policy") String name) { + LOG.info("Received get policy request for policy: {} under metalake: {}", name, metalake); + + try { + return Utils.doAs( + httpRequest, + () -> { + Policy policy = policyDispatcher.getPolicy(metalake, name); + LOG.info("Get policy: {} under metalake: {}", name, metalake); + return Utils.ok(new PolicyResponse(DTOConverters.toDTO(policy, Optional.empty()))); + }); + } catch (Exception e) { + return ExceptionHandlers.handlePolicyException(OperationType.GET, name, metalake, e); + } + } + + @PUT + @Path("{policy}") + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "alter-policy." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "alter-policy", absolute = true) + public Response alterPolicy( + @PathParam("metalake") String metalake, + @PathParam("policy") String name, + PolicyUpdatesRequest request) { + LOG.info("Received alter policy request for policy: {} under metalake: {}", name, metalake); + + try { + return Utils.doAs( + httpRequest, + () -> { + request.validate(); + + PolicyChange[] changes = + request.getUpdates().stream() + .map(PolicyUpdateRequest::policyChange) + .toArray(PolicyChange[]::new); + Policy policy = policyDispatcher.alterPolicy(metalake, name, changes); + + LOG.info("Altered policy: {} under metalake: {}", name, metalake); + return Utils.ok(new PolicyResponse(DTOConverters.toDTO(policy, Optional.empty()))); + }); + } catch (Exception e) { + return ExceptionHandlers.handlePolicyException(OperationType.ALTER, name, metalake, e); + } + } + + @PATCH + @Path("{policy}") + @Produces("application/vnd.gravitino.v1+json") + @Timed(name = "set-policy." + MetricNames.HTTP_PROCESS_DURATION, absolute = true) + @ResponseMetered(name = "set-policy", absolute = true) + public Response alterPolicy( Review Comment: Maybe you should use a different method name to differentiate. ########## common/src/main/java/org/apache/gravitino/dto/requests/PolicyUpdateRequest.java: ########## @@ -0,0 +1,175 @@ +/* + * 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.gravitino.dto.requests; + +import static org.apache.gravitino.dto.util.DTOConverters.fromDTO; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.google.common.base.Preconditions; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import org.apache.commons.lang3.StringUtils; +import org.apache.gravitino.dto.policy.PolicyContentDTO; +import org.apache.gravitino.policy.PolicyChange; +import org.apache.gravitino.rest.RESTRequest; + +/** Represents a request to update a policy. */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY) +@JsonSubTypes({ + @JsonSubTypes.Type(value = PolicyUpdateRequest.RenamePolicyRequest.class, name = "rename"), + @JsonSubTypes.Type( + value = PolicyUpdateRequest.UpdatePolicyCommentRequest.class, + name = "updateComment"), + @JsonSubTypes.Type( + value = PolicyUpdateRequest.UpdatePolicyContentRequest.class, + name = "updateContent") +}) +public interface PolicyUpdateRequest extends RESTRequest { + + /** + * Returns the policy change. + * + * @return the policy change. + */ + PolicyChange policyChange(); + + /** The policy update request for renaming a policy. */ + @EqualsAndHashCode + @Getter + @ToString + class RenamePolicyRequest implements PolicyUpdateRequest { + + @JsonProperty("newName") + private final String newName; + + /** + * Creates a new RenamePolicyRequest. + * + * @param newName The new name of the policy. + */ + public RenamePolicyRequest(String newName) { + this.newName = newName; + } + + /** This is the constructor that is used by Jackson deserializer */ + public RenamePolicyRequest() { Review Comment: Make all the jackson default constructor private, also using `this(xxx, xxx...)` to replace the code. ########## common/src/main/java/org/apache/gravitino/dto/requests/PolicyCreateRequest.java: ########## @@ -0,0 +1,170 @@ +/* + * 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.gravitino.dto.requests; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.google.common.base.Preconditions; +import java.util.Set; +import javax.annotation.Nullable; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; +import org.apache.commons.lang3.StringUtils; +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.dto.policy.PolicyContentDTO; +import org.apache.gravitino.policy.Policy; +import org.apache.gravitino.rest.RESTRequest; + +/** Represents a request to create a policy. */ +@Getter +@EqualsAndHashCode +@ToString +public class PolicyCreateRequest implements RESTRequest { + + @JsonProperty("name") + private final String name; + + @JsonProperty("comment") + @Nullable + private final String comment; + + @JsonProperty("policyType") + private final String policyType; + + @JsonProperty(value = "enabled", defaultValue = "true") + private final Boolean enabled; + + @JsonProperty("content") + @JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.EXTERNAL_PROPERTY, + property = "policyType", + defaultImpl = PolicyContentDTO.CustomContentDTO.class) + @JsonSubTypes({ + // add mappings for built-in types here + // For example: @JsonSubTypes.Type(value = DataCompactionContent.class, name = + // "system_data_compaction") + }) + private final PolicyContentDTO policyContent; + + @JsonProperty("exclusive") + private final Boolean exclusive; + + @JsonProperty("inheritable") + private final Boolean inheritable; + + @JsonProperty("supportedObjectTypes") + private final Set<MetadataObject.Type> supportedObjectTypes; + + /** + * Creates a new PolicyCreateRequest. + * + * @param name The name of the policy. + * @param comment The comment of the policy. + * @param type The type of the policy. + * @param enabled Whether the policy is enabled. + * @param exclusive Whether the policy is exclusive. + * @param inheritable Whether the policy is inheritable. + * @param supportedObjectTypes The set of metadata object types that the policy can be applied to. + * @param content The content of the policy. + */ + public PolicyCreateRequest( + String name, + String type, + String comment, + boolean enabled, + boolean exclusive, + boolean inheritable, + Set<MetadataObject.Type> supportedObjectTypes, + PolicyContentDTO content) { + this.name = name; + this.policyType = type; + this.comment = comment; + this.enabled = enabled; + this.exclusive = exclusive; + this.inheritable = inheritable; + this.supportedObjectTypes = supportedObjectTypes; + this.policyContent = content; + } + + /** This is the constructor that is used by Jackson deserializer */ + private PolicyCreateRequest() { + this.name = null; + this.policyType = null; + this.comment = null; + this.enabled = null; + this.exclusive = null; + this.inheritable = null; + this.supportedObjectTypes = null; + this.policyContent = null; + } Review Comment: Using `this(xxx, xxx...)`. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
