diff options
Diffstat (limited to 'main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java')
-rw-r--r-- | main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java | 307 |
1 files changed, 296 insertions, 11 deletions
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java index eef14388..cb2d1e34 100644 --- a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java +++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java @@ -20,10 +20,22 @@ package org.onap.policy.pap.main.rest.depundep; +import com.att.aft.dme2.internal.apache.commons.lang.ObjectUtils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.function.BiFunction; +import java.util.function.Consumer; import javax.ws.rs.core.Response; import org.apache.commons.lang3.tuple.Pair; +import org.onap.policy.common.parameters.BeanValidationResult; +import org.onap.policy.common.parameters.ObjectValidationResult; +import org.onap.policy.common.parameters.ValidationResult; +import org.onap.policy.common.parameters.ValidationStatus; import org.onap.policy.common.utils.services.Registry; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.pap.concepts.PdpDeployPolicies; @@ -31,7 +43,7 @@ import org.onap.policy.models.pap.concepts.PdpGroupDeployResponse; import org.onap.policy.models.pdp.concepts.PdpGroup; import org.onap.policy.models.pdp.concepts.PdpGroups; import org.onap.policy.models.pdp.concepts.PdpSubGroup; -import org.onap.policy.models.pdp.concepts.PdpUpdate; +import org.onap.policy.models.pdp.enums.PdpState; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifierOptVersion; @@ -61,28 +73,297 @@ public class PdpGroupDeployProvider extends ProviderBase<PdpGroupDeployResponse> } /** - * Deploys or updates PDP groups. + * Creates or updates PDP groups. * - * @param groups PDP group configurations + * @param groups PDP group configurations to be created or updated * @return a pair containing the status and the response */ - public Pair<Response.Status, PdpGroupDeployResponse> deployGroup(PdpGroups groups) { - return process(groups, this::deployGroups); + public Pair<Response.Status, PdpGroupDeployResponse> createOrUpdateGroups(PdpGroups groups) { + ValidationResult result = groups.validatePapRest(); + + if (!result.isValid()) { + String msg = result.getResult().trim(); + logger.warn(msg); + return Pair.of(Response.Status.INTERNAL_SERVER_ERROR, makeResponse(msg)); + } + + return process(groups, this::createOrUpdate); } /** - * Deploys or updates PDP groups. + * Creates or updates PDP groups. This is the method that does the actual work. * * @param data session data * @param groups PDP group configurations - * @return a list of requests that should be sent to configure the PDPs */ - private List<PdpUpdate> deployGroups(SessionData data, PdpGroups groups) { - throw new PolicyPapRuntimeException("not implemented yet"); + private void createOrUpdate(SessionData data, PdpGroups groups) { + BeanValidationResult result = new BeanValidationResult("groups", groups); + + for (PdpGroup group : groups.getGroups()) { + PdpGroup dbgroup = data.getGroup(group.getName()); + + if (dbgroup == null) { + result.addResult(addGroup(data, group)); + + } else { + result.addResult(updateGroup(data, dbgroup, group)); + } + } + + if (!result.isValid()) { + throw new PolicyPapRuntimeException(result.getResult().trim()); + } + } + + /** + * Adds a new group. + * + * @param data session data + * @param group the group to be added + * @return the validation result + */ + private ValidationResult addGroup(SessionData data, PdpGroup group) { + BeanValidationResult result = new BeanValidationResult(group.getName(), group); + + validateGroupOnly(group, result); + if (!result.isValid()) { + return result; + } + + // default to active + if (group.getPdpGroupState() == null) { + group.setPdpGroupState(PdpState.ACTIVE); + } + + for (PdpSubGroup subgrp : group.getPdpSubgroups()) { + result.addResult(addSubGroup(data, subgrp)); + } + + if (result.isValid()) { + data.create(group); + } + + return result; + } + + /** + * Performs additional validations of a group, but does not examine the subgroups. + * + * @param group the group to be validated + * @param result the validation result + */ + private void validateGroupOnly(PdpGroup group, BeanValidationResult result) { + if (group.getPdpGroupState() == null) { + return; + } + + switch (group.getPdpGroupState()) { + case ACTIVE: + case PASSIVE: + break; + + default: + result.addResult(new ObjectValidationResult("pdpGroupState", group.getPdpGroupState(), + ValidationStatus.INVALID, "must be null, ACTIVE, or PASSIVE")); + break; + } + } + + /** + * Updates an existing group. + * + * @param data session data + * @param dbgroup the group, as it appears within the DB + * @param group the group to be added + * @return the validation result + */ + private ValidationResult updateGroup(SessionData data, PdpGroup dbgroup, PdpGroup group) { + BeanValidationResult result = new BeanValidationResult(group.getName(), group); + + if (!ObjectUtils.equals(dbgroup.getProperties(), group.getProperties())) { + result.addResult(new ObjectValidationResult("properties", "", ValidationStatus.INVALID, + "cannot change properties")); + } + + // create a map of existing subgroups + Map<String, PdpSubGroup> type2sub = new HashMap<>(); + dbgroup.getPdpSubgroups().forEach(subgrp -> type2sub.put(subgrp.getPdpType(), subgrp)); + + boolean updated = updateField(dbgroup.getDescription(), group.getDescription(), dbgroup::setDescription); + + for (PdpSubGroup subgrp : group.getPdpSubgroups()) { + PdpSubGroup dbsub = type2sub.get(subgrp.getPdpType()); + BeanValidationResult subResult = new BeanValidationResult(subgrp.getPdpType(), subgrp); + + if (dbsub == null) { + updated = true; + subResult.addResult(addSubGroup(data, subgrp)); + dbgroup.getPdpSubgroups().add(subgrp); + + } else { + updated = updateSubGroup(data, group, dbsub, subgrp, subResult) || updated; + } + + result.addResult(subResult); + } + + if (result.isValid() && updated) { + data.update(group); + } + + return result; + } + + /** + * Updates a field, if the new value is different than the old value. + * + * @param oldValue old value + * @param newValue new value + * @param setter function to set the field to the new value + * @return {@code true} if the field was updated, {@code false} if it already matched + * the new value + */ + private <T> boolean updateField(T oldValue, T newValue, Consumer<T> setter) { + if (oldValue == newValue) { + return false; + } + + if (oldValue != null && oldValue.equals(newValue)) { + return false; + } + + setter.accept(newValue); + return true; + } + + /** + * Adds a new subgroup. + * + * @param data session data + * @param subgrp the subgroup to be added + * @return the validation result + */ + private ValidationResult addSubGroup(SessionData data, PdpSubGroup subgrp) { + subgrp.setCurrentInstanceCount(0); + subgrp.setPdpInstances(Collections.emptyList()); + + BeanValidationResult result = new BeanValidationResult(subgrp.getPdpType(), subgrp); + + result.addResult(validatePolicies(data, subgrp)); + + return result; } /** - * Deploys or updates PDP policies. + * Updates an existing subgroup. + * + * @param data session data + * @param dbgroup the group, from the DB, containing the subgroup + * @param dbsub the subgroup, from the DB + * @param subgrp the subgroup to be updated + * @param container container for additional validation results + * @return {@code true} if the subgroup content was changed, {@code false} if there + * were no changes + */ + private boolean updateSubGroup(SessionData data, PdpGroup dbgroup, PdpSubGroup dbsub, PdpSubGroup subgrp, + BeanValidationResult container) { + + // perform additional validations first + if (!validateSubGroup(data, dbsub, subgrp, container)) { + return false; + } + + /* + * first, apply the changes about which the PDPs care + */ + boolean updated = updateList(dbsub.getPolicies(), subgrp.getPolicies(), dbsub::setPolicies); + + // publish any changes to the PDPs + if (updated) { + makeUpdates(data, dbgroup, dbsub); + } + + /* + * now make any remaining changes + */ + updated = updateList(dbsub.getSupportedPolicyTypes(), subgrp.getSupportedPolicyTypes(), + dbsub::setSupportedPolicyTypes) || updated; + + return updateField(dbsub.getDesiredInstanceCount(), subgrp.getDesiredInstanceCount(), + dbsub::setDesiredInstanceCount) || updated; + } + + /** + * Performs additional validations of a subgroup. + * + * @param data session data + * @param dbsub the subgroup, from the DB + * @param subgrp the subgroup to be validated + * @param container container for additional validation results + * @return {@code true} if the subgroup is valid, {@code false} otherwise + */ + private boolean validateSubGroup(SessionData data, PdpSubGroup dbsub, PdpSubGroup subgrp, + BeanValidationResult container) { + + BeanValidationResult result = new BeanValidationResult(subgrp.getPdpType(), subgrp); + + if (!ObjectUtils.equals(dbsub.getProperties(), subgrp.getProperties())) { + result.addResult(new ObjectValidationResult("properties", "", ValidationStatus.INVALID, + "cannot change properties")); + } + + result.addResult(validatePolicies(data, subgrp)); + container.addResult(result); + + return result.isValid(); + } + + /** + * Updates a DB list with items from a new list. + * + * @param dblist the list from the DB + * @param newList the new list + * @param setter function to set the new list + * @return {@code true} if the list changed, {@code false} if the lists were the same + */ + private <T> boolean updateList(List<T> dblist, List<T> newList, Consumer<List<T>> setter) { + + Set<T> dbTypes = new HashSet<T>(dblist); + Set<T> newTypes = new HashSet<T>(newList); + + if (dbTypes.equals(newTypes)) { + return false; + } + + setter.accept(new ArrayList<>(newTypes)); + + return true; + } + + /** + * Performs additional validations of the policies within a subgroup. + * + * @param data session data + * @param subgrp the subgroup to be validated + * @param result the validation result + */ + private ValidationResult validatePolicies(SessionData data, PdpSubGroup subgrp) { + BeanValidationResult result = new BeanValidationResult(subgrp.getPdpType(), subgrp); + + for (ToscaPolicyIdentifier ident : subgrp.getPolicies()) { + ToscaPolicy policy = data.getPolicy(ident); + + if (!subgrp.getSupportedPolicyTypes().contains(policy.getTypeIdentifier())) { + result.addResult(new ObjectValidationResult("policy", ident, ValidationStatus.INVALID, + "not a supported policy for the subgroup")); + } + } + + return result; + } + + /** + * Deploys or updates PDP policies using the simple API. * * @param policies PDP policies * @return a pair containing the status and the response @@ -92,7 +373,8 @@ public class PdpGroupDeployProvider extends ProviderBase<PdpGroupDeployResponse> } /** - * Deploys or updates PDP policies using the simple API. + * Deploys or updates PDP policies using the simple API. This is the method that does + * the actual work. * * @param data session data * @param extPolicies external PDP policies @@ -118,6 +400,9 @@ public class PdpGroupDeployProvider extends ProviderBase<PdpGroupDeployResponse> } } + /** + * Adds a policy to a subgroup, if it isn't there already. + */ @Override protected BiFunction<PdpGroup, PdpSubGroup, Boolean> makeUpdater(ToscaPolicy policy) { ToscaPolicyIdentifier desiredIdent = policy.getIdentifier(); |