aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2019-04-12 10:00:05 -0400
committerJim Hahn <jrh3@att.com>2019-04-13 20:21:36 -0400
commitd641bd5f3c4f6333e56ea85d95abb3dc124d4f4b (patch)
treeb62566d613d90db4d03a87431c300f741dccfd81 /main
parentfb057952d747a91139bce6e259b775bf57fc158f (diff)
Support group-oriented REST API
Added code to support PDP group create/update & delete REST API calls. The create/update request can also be used to deploy/undeploy policies. It is assumed that the create/update request specifies a valid list of supported policy types for each subgroup (i.e., PDP type). Updated due to elimination of "version" from group in policy/models. Added/updated junits. Change-Id: I1916d9b17dfd5f12129c6f6a2fcf54e706662c10 Issue-ID: POLICY-1542 Signed-off-by: Jim Hahn <jrh3@att.com>
Diffstat (limited to 'main')
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/GroupData.java49
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeleteControllerV1.java46
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeleteProvider.java54
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployControllerV1.java2
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java307
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/ProviderBase.java35
-rw-r--r--main/src/main/java/org/onap/policy/pap/main/rest/depundep/SessionData.java133
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/ProviderSuper.java50
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestGroupData.java25
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeleteControllerV1.java26
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeleteProvider.java65
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployProvider.java412
-rw-r--r--main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestSessionData.java235
-rw-r--r--main/src/test/resources/simpleDeploy/createGroupNewPolicy.json10
-rw-r--r--main/src/test/resources/simpleDeploy/createGroups.json39
-rw-r--r--main/src/test/resources/simpleDeploy/createGroupsNewSub.json56
-rw-r--r--main/src/test/resources/simpleDeploy/deleteGroup.json29
-rw-r--r--main/src/test/resources/simpleDeploy/group1.json3
-rw-r--r--main/src/test/resources/simpleDeploy/group2.json3
-rw-r--r--main/src/test/resources/simpleDeploy/group3.json3
-rw-r--r--main/src/test/resources/simpleDeploy/group4.json3
-rw-r--r--main/src/test/resources/simpleDeploy/group5.json3
22 files changed, 1418 insertions, 170 deletions
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/GroupData.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/GroupData.java
index 25a886bd..f97107f7 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/GroupData.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/GroupData.java
@@ -24,26 +24,58 @@ import lombok.Getter;
import org.onap.policy.models.pdp.concepts.PdpGroup;
/**
- * PdpGroup data, which includes the old group, that's in the DB, and possibly a new
- * group, that must be added to the DB.
+ * PdpGroup data, only the latest copy of the group is retained.
*/
-@Getter
public class GroupData {
+ @Getter
private PdpGroup group;
+ private enum State {
+ UNCHANGED, CREATED, UPDATED
+ }
+
/**
- * {@code True} if the group has been updated, {@code false} otherwise.
+ * State of the group.
*/
- private boolean updated = false;
+ private State state;
/**
- * Constructs the object.
+ * Constructs the object, for an existing group.
*
* @param group the group that is in the DB
*/
public GroupData(PdpGroup group) {
+ this(group, false);
+ }
+
+ /**
+ * Constructs the object.
+ *
+ * @param group the group that is in, or to be added to, the DB
+ * @param isNew {@code true} if this is a new group, {@code false} otherwise
+ */
+ public GroupData(PdpGroup group, boolean isNew) {
this.group = group;
+ this.state = (isNew ? State.CREATED : State.UNCHANGED);
+ }
+
+ /**
+ * Determines if the group is new.
+ *
+ * @return {@code true} if the group is new, {@code false} otherwise
+ */
+ public boolean isNew() {
+ return (state == State.CREATED);
+ }
+
+ /**
+ * Determines if the group has been updated.
+ *
+ * @return {@code true} if the group has been updated, {@code false} otherwise
+ */
+ public boolean isUpdated() {
+ return (state == State.UPDATED);
}
/**
@@ -57,7 +89,10 @@ public class GroupData {
"expected group " + this.group.getName() + ", but received " + newGroup.getName());
}
- this.updated = true;
this.group = newGroup;
+
+ if (state == State.UNCHANGED) {
+ state = State.UPDATED;
+ }
}
}
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeleteControllerV1.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeleteControllerV1.java
index ca638f3e..08781857 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeleteControllerV1.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeleteControllerV1.java
@@ -82,51 +82,7 @@ public class PdpGroupDeleteControllerV1 extends PapRestControllerV1 {
public Response deleteGroup(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
@ApiParam(value = "PDP Group Name", required = true) @PathParam("name") String groupName) {
- Pair<Status, PdpGroupDeleteResponse> pair = provider.deleteGroup(groupName, null);
-
- return addLoggingHeaders(addVersionControlHeaders(Response.status(pair.getLeft())), requestId)
- .entity(pair.getRight()).build();
- }
-
- /**
- * Deletes a particular version of a PDP group.
- *
- * @param requestId request ID used in ONAP logging
- * @param groupName name of the PDP group to be deleted
- * @param version version to be deleted
- * @return a response
- */
- // @formatter:off
- @DELETE
- @Path("pdps/groups/{name}/versions/{version}")
- @ApiOperation(value = "Delete version of a PDP Group",
- notes = "Deletes a version of PDP Group, returning optional error details",
- response = PdpGroupDeleteResponse.class,
- tags = {"Policy Administration (PAP) API"},
- authorizations = @Authorization(value = AUTHORIZATION_TYPE),
- responseHeaders = {
- @ResponseHeader(name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
- response = String.class),
- @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
- response = String.class),
- @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
- response = String.class),
- @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
- response = UUID.class)},
- extensions = {@Extension(name = EXTENSION_NAME,
- properties = {@ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
- @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)})})
- @ApiResponses(value = {@ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
- @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
- @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)})
- // @formatter:on
-
- public Response deleteGroupVersion(
- @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
- @ApiParam(value = "PDP Group Name", required = true) @PathParam("name") String groupName,
- @ApiParam(value = "PDP Group Version", required = true) @PathParam("version") String version) {
-
- Pair<Status, PdpGroupDeleteResponse> pair = provider.deleteGroup(groupName, version);
+ Pair<Status, PdpGroupDeleteResponse> pair = provider.deleteGroup(groupName);
return addLoggingHeaders(addVersionControlHeaders(Response.status(pair.getLeft())), requestId)
.entity(pair.getRight()).build();
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeleteProvider.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeleteProvider.java
index 6457efae..7d47b3e2 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeleteProvider.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeleteProvider.java
@@ -27,6 +27,7 @@ import org.onap.policy.models.base.PfModelException;
import org.onap.policy.models.pap.concepts.PdpGroupDeleteResponse;
import org.onap.policy.models.pdp.concepts.PdpGroup;
import org.onap.policy.models.pdp.concepts.PdpSubGroup;
+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;
@@ -52,47 +53,73 @@ public class PdpGroupDeleteProvider extends ProviderBase<PdpGroupDeleteResponse>
* Deletes a PDP group.
*
* @param groupName name of the PDP group to be deleted
- * @param version group version to delete; may be {@code null} if the group has only
- * one version
* @return a pair containing the status and the response
*/
- public Pair<Response.Status, PdpGroupDeleteResponse> deleteGroup(String groupName, String version) {
+ public Pair<Response.Status, PdpGroupDeleteResponse> deleteGroup(String groupName) {
- PdpGroupDeleteResponse resp = new PdpGroupDeleteResponse();
- resp.setErrorDetails("not implemented yet");
+ return process(groupName, this::deleteGroup);
+ }
+
+ /**
+ * Deletes a PDP group.
+ *
+ * @param data session data
+ * @param groupName name of the PDP group to be deleted
+ */
+ private void deleteGroup(SessionData data, String groupName) {
+ try {
+ PdpGroup group = data.getGroup(groupName);
+ if (group == null) {
+ throw new PolicyPapRuntimeException("group not found");
+ }
+
+ if (group.getPdpGroupState() == PdpState.ACTIVE) {
+ throw new PolicyPapRuntimeException("group is still " + PdpState.ACTIVE);
+ }
- return Pair.of(Response.Status.INTERNAL_SERVER_ERROR, resp);
+ data.deleteGroupFromDb(group);
+
+ } catch (PfModelException e) {
+ // no need to log the error here, as it will be logged by the invoker
+ logger.warn("failed to delete group: {}", groupName);
+ throw new PolicyPapRuntimeException(DB_ERROR_MSG, e);
+
+ } catch (RuntimeException e) {
+ // no need to log the error here, as it will be logged by the invoker
+ logger.warn("failed to delete group: {}", groupName);
+ throw e;
+ }
}
/**
- * Deletes a PDP policy.
+ * Undeploys a policy.
*
* @param policyIdent identifier of the policy to be undeployed
* @return a pair containing the status and the response
*/
public Pair<Response.Status, PdpGroupDeleteResponse> undeploy(ToscaPolicyIdentifierOptVersion policyIdent) {
- return process(policyIdent, this::deletePolicy);
+ return process(policyIdent, this::undeployPolicy);
}
/**
- * Deletes a policy from its groups.
+ * Undeploys a policy from its groups.
*
* @param data session data
* @param ident identifier of the policy to be deleted
*/
- private void deletePolicy(SessionData data, ToscaPolicyIdentifierOptVersion ident) {
+ private void undeployPolicy(SessionData data, ToscaPolicyIdentifierOptVersion ident) {
try {
processPolicy(data, ident);
} catch (PfModelException e) {
// no need to log the error here, as it will be logged by the invoker
- logger.warn("failed to deploy policy: {}", ident);
+ logger.warn("failed to undeploy policy: {}", ident);
throw new PolicyPapRuntimeException(DB_ERROR_MSG, e);
} catch (RuntimeException e) {
// no need to log the error here, as it will be logged by the invoker
- logger.warn("failed to deploy policy: {}", ident);
+ logger.warn("failed to undeploy policy: {}", ident);
throw e;
}
}
@@ -104,6 +131,9 @@ public class PdpGroupDeleteProvider extends ProviderBase<PdpGroupDeleteResponse>
return resp;
}
+ /**
+ * Returns a function that will remove the specified policy from a subgroup.
+ */
@Override
protected BiFunction<PdpGroup, PdpSubGroup, Boolean> makeUpdater(ToscaPolicy policy) {
ToscaPolicyIdentifier desiredIdent = policy.getIdentifier();
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployControllerV1.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployControllerV1.java
index 6d4dc7ed..bdec3562 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployControllerV1.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployControllerV1.java
@@ -82,7 +82,7 @@ public class PdpGroupDeployControllerV1 extends PapRestControllerV1 {
public Response deployGroup(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
@ApiParam(value = "List of PDP Group Configuration", required = true) PdpGroups groups) {
- Pair<Status, PdpGroupDeployResponse> pair = provider.deployGroup(groups);
+ Pair<Status, PdpGroupDeployResponse> pair = provider.createOrUpdateGroups(groups);
return addLoggingHeaders(addVersionControlHeaders(Response.status(pair.getLeft())), requestId)
.entity(pair.getRight()).build();
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();
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/ProviderBase.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/ProviderBase.java
index d3519197..5e0fb71a 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/ProviderBase.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/ProviderBase.java
@@ -32,6 +32,7 @@ import org.onap.policy.models.base.PfModelException;
import org.onap.policy.models.pap.concepts.SimpleResponse;
import org.onap.policy.models.pdp.concepts.Pdp;
import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
import org.onap.policy.models.pdp.concepts.PdpSubGroup;
import org.onap.policy.models.pdp.concepts.PdpUpdate;
import org.onap.policy.models.provider.PolicyModelsProvider;
@@ -59,7 +60,6 @@ import org.slf4j.LoggerFactory;
*/
public abstract class ProviderBase<R extends SimpleResponse> {
private static final String DEPLOY_FAILED = "failed to deploy/undeploy policies";
-
public static final String DB_ERROR_MSG = "DB error";
private static final Logger logger = LoggerFactory.getLogger(ProviderBase.class);
@@ -100,7 +100,7 @@ public abstract class ProviderBase<R extends SimpleResponse> {
synchronized (updateLock) {
// list of requests to be published to the PDPs
- Collection<PdpUpdate> requests = Collections.emptyList();
+ Collection<Pair<PdpUpdate, PdpStateChange>> requests = Collections.emptyList();
try (PolicyModelsProvider dao = daoFactory.create()) {
@@ -110,7 +110,7 @@ public abstract class ProviderBase<R extends SimpleResponse> {
// make all of the DB updates
data.updateDb();
- requests = data.getPdpUpdates();
+ requests = data.getPdpRequests();
} catch (PfModelException e) {
logger.warn(DEPLOY_FAILED, e);
@@ -127,7 +127,7 @@ public abstract class ProviderBase<R extends SimpleResponse> {
// publish the requests
- requests.forEach(requestMap::addRequest);
+ requests.forEach(pair -> requestMap.addRequest(pair.getLeft(), pair.getRight()));
}
return Pair.of(Response.Status.OK, makeResponse(null));
@@ -236,13 +236,7 @@ public abstract class ProviderBase<R extends SimpleResponse> {
updated = true;
- /*
- * generate an UPDATE for each PDP instance. Since the group is active, we
- * assume that the PDP is, too, thus no need for a STATE-CHANGE.
- */
- for (Pdp pdpInstance : subgroup.getPdpInstances()) {
- data.addUpdate(makeUpdate(data, group, subgroup, pdpInstance));
- }
+ makeUpdates(data, group, subgroup);
}
@@ -253,19 +247,32 @@ public abstract class ProviderBase<R extends SimpleResponse> {
}
/**
+ * Makes UPDATE messages for each PDP in a subgroup.
+ *
+ * @param data session data
+ * @param group group containing the subgroup
+ * @param subgroup subgroup whose PDPs should receive messages
+ */
+ protected void makeUpdates(SessionData data, PdpGroup group, PdpSubGroup subgroup) {
+ for (Pdp pdp : subgroup.getPdpInstances()) {
+ data.addUpdate(makeUpdate(data, group, subgroup, pdp));
+ }
+ }
+
+ /**
* Makes an UPDATE message for a particular PDP.
*
* @param data session data
* @param group group to which the PDP should belong
* @param subgroup subgroup to which the PDP should belong
- * @param pdpInstance identifies the PDP of interest
+ * @param pdp the PDP of interest
* @return a new UPDATE message
*/
- private PdpUpdate makeUpdate(SessionData data, PdpGroup group, PdpSubGroup subgroup, Pdp pdpInstance) {
+ private PdpUpdate makeUpdate(SessionData data, PdpGroup group, PdpSubGroup subgroup, Pdp pdp) {
PdpUpdate update = new PdpUpdate();
- update.setName(pdpInstance.getInstanceId());
+ update.setName(pdp.getInstanceId());
update.setDescription(group.getDescription());
update.setPdpGroup(group.getName());
update.setPdpSubgroup(subgroup.getPdpType());
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/SessionData.java b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/SessionData.java
index 6b42b19b..0537c80b 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/depundep/SessionData.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/depundep/SessionData.java
@@ -26,9 +26,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import org.apache.commons.lang3.tuple.Pair;
import org.onap.policy.models.base.PfModelException;
import org.onap.policy.models.pdp.concepts.PdpGroup;
import org.onap.policy.models.pdp.concepts.PdpGroupFilter;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
import org.onap.policy.models.pdp.concepts.PdpUpdate;
import org.onap.policy.models.pdp.enums.PdpState;
import org.onap.policy.models.provider.PolicyModelsProvider;
@@ -57,9 +59,9 @@ public class SessionData {
private final Map<ToscaPolicyTypeIdentifier, List<GroupData>> type2groups = new HashMap<>();
/**
- * Maps a PDP name to its most recently generated update request.
+ * Maps a PDP name to its most recently generated update and state-change requests.
*/
- private final Map<String, PdpUpdate> pdpUpdates = new HashMap<>();
+ private final Map<String, Pair<PdpUpdate, PdpStateChange>> pdpRequests = new HashMap<>();
/**
* Maps a policy's identifier to the policy.
@@ -96,17 +98,11 @@ public class SessionData {
try {
List<ToscaPolicy> lst = dao.getPolicyList(ident.getName(), ident.getVersion());
-
if (lst.isEmpty()) {
throw new PolicyPapRuntimeException(
"cannot find policy: " + ident.getName() + " " + ident.getVersion());
}
- if (lst.size() > 1) {
- throw new PolicyPapRuntimeException(
- "too many policies match: " + ident.getName() + " " + ident.getVersion());
- }
-
return lst.get(0);
} catch (PfModelException e) {
@@ -117,22 +113,67 @@ public class SessionData {
}
/**
+ * Adds an update and state-change to the sets, replacing any previous entries for the
+ * given PDP.
+ *
+ * @param update the update to be added
+ * @param change the state-change to be added
+ */
+ public void addRequests(PdpUpdate update, PdpStateChange change) {
+ if (!update.getName().equals(change.getName())) {
+ throw new IllegalArgumentException("PDP name mismatch " + update.getName() + ", " + change.getName());
+ }
+
+ pdpRequests.put(update.getName(), Pair.of(update, change));
+ }
+
+ /**
* Adds an update to the set of updates, replacing any previous entry for the given
* PDP.
*
* @param update the update to be added
*/
public void addUpdate(PdpUpdate update) {
- pdpUpdates.put(update.getName(), update);
+ pdpRequests.compute(update.getName(), (name, data) -> Pair.of(update, (data == null ? null : data.getRight())));
}
/**
- * Gets the accumulated UPDATE requests.
+ * Adds a state-change to the set of state-change requests, replacing any previous entry for the given
+ * PDP.
*
- * @return the UPDATE requests
+ * @param change the state-change to be added
*/
- public Collection<PdpUpdate> getPdpUpdates() {
- return pdpUpdates.values();
+ public void addStateChange(PdpStateChange change) {
+ pdpRequests.compute(change.getName(), (name, data) -> Pair.of((data == null ? null : data.getLeft()), change));
+ }
+
+ /**
+ * Gets the accumulated PDP requests.
+ *
+ * @return the PDP requests
+ */
+ public Collection<Pair<PdpUpdate, PdpStateChange>> getPdpRequests() {
+ return pdpRequests.values();
+ }
+
+ /**
+ * Gets the accumulated PDP update requests.
+ *
+ * @return the PDP requests
+ */
+ public List<PdpUpdate> getPdpUpdates() {
+ return pdpRequests.values().stream().filter(req -> req.getLeft() != null).map(Pair::getLeft)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Gets the accumulated PDP state-change requests.
+ *
+ * @return the PDP requests
+ */
+ public List<PdpStateChange> getPdpStateChanges() {
+ return pdpRequests.values().stream().filter(req -> req.getRight() != null).map(Pair::getRight)
+ .collect(Collectors.toList());
}
/**
@@ -163,6 +204,19 @@ public class SessionData {
}
/**
+ * Creates a group.
+ *
+ * @param newGroup the new group
+ */
+ public void create(PdpGroup newGroup) {
+ String name = newGroup.getName();
+
+ if (groupCache.put(name, new GroupData(newGroup, true)) != null) {
+ throw new IllegalStateException("group already cached: " + name);
+ }
+ }
+
+ /**
* Updates a group.
*
* @param newGroup the updated group
@@ -178,6 +232,34 @@ public class SessionData {
}
/**
+ * Gets the group by the given name.
+ *
+ * @param name name of the group to get
+ * @return the group, or {@code null} if it does not exist
+ * @throws PolicyPapRuntimeException if an error occurs
+ */
+ public PdpGroup getGroup(String name) {
+
+ GroupData data = groupCache.computeIfAbsent(name, key -> {
+
+ try {
+ List<PdpGroup> lst = dao.getPdpGroups(key);
+ if (lst.isEmpty()) {
+ return null;
+ }
+
+ return new GroupData(lst.get(0));
+
+ } catch (PfModelException e) {
+ throw new PolicyPapRuntimeException("cannot get group: " + name, e);
+ }
+
+ });
+
+ return (data == null ? null : data.getGroup());
+ }
+
+ /**
* Gets the active groups supporting the given policy.
*
* @param type desired policy type
@@ -225,13 +307,28 @@ public class SessionData {
* @throws PfModelException if an error occurs
*/
public void updateDb() throws PfModelException {
- List<GroupData> updatedGroups =
+ // create new groups
+ List<GroupData> created = groupCache.values().stream().filter(GroupData::isNew).collect(Collectors.toList());
+ if (!created.isEmpty()) {
+ dao.createPdpGroups(created.stream().map(GroupData::getGroup).collect(Collectors.toList()));
+ }
+
+ // update existing groups
+ List<GroupData> updated =
groupCache.values().stream().filter(GroupData::isUpdated).collect(Collectors.toList());
- if (updatedGroups.isEmpty()) {
- return;
+ if (!updated.isEmpty()) {
+ dao.updatePdpGroups(updated.stream().map(GroupData::getGroup).collect(Collectors.toList()));
}
+ }
- // update the groups
- dao.updatePdpGroups(updatedGroups.stream().map(GroupData::getGroup).collect(Collectors.toList()));
+ /**
+ * Deletes a group from the DB, immediately (i.e., without caching the request to be
+ * executed later).
+ *
+ * @param group the group to be deleted
+ * @throws PfModelException if an error occurs
+ */
+ public void deleteGroupFromDb(PdpGroup group) throws PfModelException {
+ dao.deletePdpGroup(group.getName());
}
}
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/ProviderSuper.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/ProviderSuper.java
index 65b1234f..256d3af0 100644
--- a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/ProviderSuper.java
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/ProviderSuper.java
@@ -1,4 +1,4 @@
-/*
+/*-
* ============LICENSE_START=======================================================
* ONAP PAP
* ================================================================================
@@ -31,6 +31,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
import org.junit.Before;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
@@ -43,6 +44,7 @@ import org.onap.policy.common.utils.resources.ResourceUtils;
import org.onap.policy.common.utils.services.Registry;
import org.onap.policy.models.pdp.concepts.PdpGroup;
import org.onap.policy.models.pdp.concepts.PdpGroups;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
import org.onap.policy.models.pdp.concepts.PdpUpdate;
import org.onap.policy.models.provider.PolicyModelsProvider;
import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
@@ -61,7 +63,7 @@ public class ProviderSuper {
/**
- * Used to capture input to dao.updatePdpGroups().
+ * Used to capture input to dao.updatePdpGroups() and dao.createPdpGroups().
*/
@Captor
private ArgumentCaptor<List<PdpGroup>> updateCaptor;
@@ -118,7 +120,19 @@ public class ProviderSuper {
}
/**
- * Gets the input to the method.
+ * Gets the input to the create() method.
+ *
+ * @return the input that was passed to the dao.updatePdpGroups() method
+ * @throws Exception if an error occurred
+ */
+ protected List<PdpGroup> getGroupCreates() throws Exception {
+ verify(dao).createPdpGroups(updateCaptor.capture());
+
+ return copyList(updateCaptor.getValue());
+ }
+
+ /**
+ * Gets the input to the update() method.
*
* @return the input that was passed to the dao.updatePdpGroups() method
* @throws Exception if an error occurred
@@ -130,6 +144,20 @@ public class ProviderSuper {
}
/**
+ * Gets the state-changes that were added to the request map.
+ *
+ * @param count the number of times the method is expected to have been called
+ * @return the state-changes that were added to the request map
+ */
+ protected List<PdpStateChange> getStateChangeRequests(int count) {
+ ArgumentCaptor<PdpStateChange> captor = ArgumentCaptor.forClass(PdpStateChange.class);
+
+ verify(reqmap, times(count)).addRequest(any(), captor.capture());
+
+ return captor.getAllValues().stream().filter(req -> req != null).collect(Collectors.toList());
+ }
+
+ /**
* Gets the updates that were added to the request map.
*
* @param count the number of times the method is expected to have been called
@@ -138,9 +166,9 @@ public class ProviderSuper {
protected List<PdpUpdate> getUpdateRequests(int count) {
ArgumentCaptor<PdpUpdate> captor = ArgumentCaptor.forClass(PdpUpdate.class);
- verify(reqmap, times(count)).addRequest(captor.capture());
+ verify(reqmap, times(count)).addRequest(captor.capture(), any());
- return new ArrayList<>(captor.getAllValues());
+ return captor.getAllValues().stream().filter(req -> req != null).collect(Collectors.toList());
}
/**
@@ -162,7 +190,17 @@ public class ProviderSuper {
* @return a list of groups
*/
protected List<PdpGroup> loadGroups(String fileName) {
- return loadFile(fileName, PdpGroups.class).getGroups();
+ return loadPdpGroups(fileName).getGroups();
+ }
+
+ /**
+ * Loads a PdpGroups.
+ *
+ * @param fileName name of the file from which to load
+ * @return a PdpGroups
+ */
+ protected PdpGroups loadPdpGroups(String fileName) {
+ return loadFile(fileName, PdpGroups.class);
}
/**
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestGroupData.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestGroupData.java
index 8313d193..0c14aa2f 100644
--- a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestGroupData.java
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestGroupData.java
@@ -50,19 +50,42 @@ public class TestGroupData {
}
@Test
- public void test() {
+ public void testNew() {
+ data = new GroupData(oldGroup, true);
+ assertSame(oldGroup, data.getGroup());
+
+ assertTrue(data.isNew());
+ assertFalse(data.isUpdated());
+
+ data.update(newGroup);
+ assertTrue(data.isNew());
+ assertFalse(data.isUpdated());
+ assertSame(newGroup, data.getGroup());
+
+ // repeat with a new group
+ newGroup = new PdpGroup(oldGroup);
+ data.update(newGroup);
+ assertTrue(data.isNew());
+ assertFalse(data.isUpdated());
+ assertSame(newGroup, data.getGroup());
+ }
+
+ @Test
+ public void testUpdateOnly() {
assertFalse(data.isUpdated());
assertSame(oldGroup, data.getGroup());
data.update(newGroup);
assertTrue(data.isUpdated());
+ assertFalse(data.isNew());
assertSame(newGroup, data.getGroup());
// repeat
newGroup = new PdpGroup(oldGroup);
data.update(newGroup);
assertTrue(data.isUpdated());
+ assertFalse(data.isNew());
assertSame(newGroup, data.getGroup());
// incorrect name
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeleteControllerV1.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeleteControllerV1.java
index c3928789..458ca9e7 100644
--- a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeleteControllerV1.java
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeleteControllerV1.java
@@ -31,14 +31,13 @@ import org.onap.policy.pap.main.rest.CommonPapRestServer;
public class TestPdpGroupDeleteControllerV1 extends CommonPapRestServer {
- private static final String NOT_IMPLEMENTED_YET = "not implemented yet";
+ private static final String GROUP_NOT_FOUND = "group not found";
private static final String DELETE_GROUP_ENDPOINT = "pdps/groups";
private static final String DELETE_POLICIES_ENDPOINT = "pdps/policies";
@Test
public void testSwagger() throws Exception {
super.testSwagger(DELETE_GROUP_ENDPOINT + "/{name}");
- super.testSwagger(DELETE_GROUP_ENDPOINT + "/{name}/versions/{version}");
super.testSwagger(DELETE_POLICIES_ENDPOINT + "/{name}");
super.testSwagger(DELETE_POLICIES_ENDPOINT + "/{name}/versions/{version}");
@@ -52,31 +51,12 @@ public class TestPdpGroupDeleteControllerV1 extends CommonPapRestServer {
Response rawresp = invocationBuilder.delete();
PdpGroupDeleteResponse resp = rawresp.readEntity(PdpGroupDeleteResponse.class);
assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rawresp.getStatus());
- assertEquals(NOT_IMPLEMENTED_YET, resp.getErrorDetails());
+ assertEquals(GROUP_NOT_FOUND, resp.getErrorDetails());
rawresp = invocationBuilder.delete();
resp = rawresp.readEntity(PdpGroupDeleteResponse.class);
assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rawresp.getStatus());
- assertEquals(NOT_IMPLEMENTED_YET, resp.getErrorDetails());
-
- // verify it fails when no authorization info is included
- checkUnauthRequest(uri, req -> req.delete());
- }
-
- @Test
- public void testDeleteGroupVersion() throws Exception {
- String uri = DELETE_GROUP_ENDPOINT + "/my-name/versions/1.2.3";
-
- Invocation.Builder invocationBuilder = sendRequest(uri);
- Response rawresp = invocationBuilder.delete();
- PdpGroupDeleteResponse resp = rawresp.readEntity(PdpGroupDeleteResponse.class);
- assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rawresp.getStatus());
- assertEquals(NOT_IMPLEMENTED_YET, resp.getErrorDetails());
-
- rawresp = invocationBuilder.delete();
- resp = rawresp.readEntity(PdpGroupDeleteResponse.class);
- assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), rawresp.getStatus());
- assertEquals(NOT_IMPLEMENTED_YET, resp.getErrorDetails());
+ assertEquals(GROUP_NOT_FOUND, resp.getErrorDetails());
// verify it fails when no authorization info is included
checkUnauthRequest(uri, req -> req.delete());
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeleteProvider.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeleteProvider.java
index dbb7951e..c0b08644 100644
--- a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeleteProvider.java
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeleteProvider.java
@@ -1,4 +1,4 @@
-/*
+/*-
* ============LICENSE_START=======================================================
* ONAP PAP
* ================================================================================
@@ -29,7 +29,9 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
@@ -57,7 +59,6 @@ public class TestPdpGroupDeleteProvider extends ProviderSuper {
private static final String POLICY1_NAME = "policyA";
private static final String POLICY1_VERSION = "1.2.3";
private static final String GROUP1_NAME = "groupA";
- private static final String GROUP1_VERSION = "200.2.3";
private MyProvider prov;
private SessionData session;
@@ -91,10 +92,62 @@ public class TestPdpGroupDeleteProvider extends ProviderSuper {
}
@Test
- public void testDeleteGroup() {
- Pair<Status, PdpGroupDeleteResponse> pair = prov.deleteGroup(GROUP1_NAME, GROUP1_VERSION);
- assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
- assertEquals("not implemented yet", pair.getRight().getErrorDetails());
+ public void testDeleteGroup_Inctive() throws Exception {
+ PdpGroup group = loadGroup("deleteGroup.json");
+
+ when(session.getGroup(GROUP1_NAME)).thenReturn(group);
+
+ prov.deleteGroup(GROUP1_NAME);
+
+ verify(session).deleteGroupFromDb(group);
+
+ // should be no PDP requests
+ verify(session, never()).addRequests(any(), any());
+ }
+
+ @Test
+ public void testDeleteGroup_Active() throws Exception {
+ PdpGroup group = loadGroup("deleteGroup.json");
+
+ group.setPdpGroupState(PdpState.ACTIVE);
+
+ when(session.getGroup(GROUP1_NAME)).thenReturn(group);
+
+ assertThatThrownBy(() -> prov.deleteGroup(GROUP1_NAME)).isInstanceOf(PolicyPapRuntimeException.class)
+ .hasMessage("group is still ACTIVE");
+ }
+
+ @Test
+ public void testDeleteGroup_NotFound() throws Exception {
+ assertThatThrownBy(() -> prov.deleteGroup(GROUP1_NAME)).isInstanceOf(PolicyPapRuntimeException.class)
+ .hasMessage("group not found");
+ }
+
+ @Test
+ public void testDeleteGroup_Inactive() throws Exception {
+ PdpGroup group = loadGroup("deleteGroup.json");
+
+ when(session.getGroup(GROUP1_NAME)).thenReturn(group);
+
+ prov.deleteGroup(GROUP1_NAME);
+
+ verify(session).deleteGroupFromDb(group);
+
+ // should done no requests for the PDPs
+ verify(session, never()).addRequests(any(), any());
+ }
+
+ @Test
+ public void testDeleteGroup_DaoEx() throws Exception {
+ PdpGroup group = loadGroup("deleteGroup.json");
+
+ when(session.getGroup(GROUP1_NAME)).thenReturn(group);
+
+ PfModelException ex = new PfModelException(Status.BAD_REQUEST, EXPECTED_EXCEPTION);
+ doThrow(ex).when(session).deleteGroupFromDb(group);
+
+ assertThatThrownBy(() -> prov.deleteGroup(GROUP1_NAME)).isInstanceOf(PolicyPapRuntimeException.class)
+ .hasMessage(ProviderBase.DB_ERROR_MSG);
}
@Test
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployProvider.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployProvider.java
index 8ca205cd..cad73d92 100644
--- a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployProvider.java
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployProvider.java
@@ -22,6 +22,7 @@ package org.onap.policy.pap.main.rest.depundep;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
@@ -29,7 +30,12 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.onap.policy.pap.main.rest.depundep.ProviderBase.DB_ERROR_MSG;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
+import java.util.TreeMap;
+import java.util.stream.Collectors;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.AfterClass;
@@ -39,14 +45,21 @@ import org.onap.policy.common.utils.services.Registry;
import org.onap.policy.models.base.PfModelException;
import org.onap.policy.models.pap.concepts.PdpDeployPolicies;
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.ToscaPolicyTypeIdentifier;
public class TestPdpGroupDeployProvider extends ProviderSuper {
private static final String EXPECTED_EXCEPTION = "expected exception";
private static final Object REQUEST_FAILED_MSG = "request failed";
private static final String POLICY1_NAME = "policyA";
+ private static final String POLICY2_NAME = "policyB";
private static final String POLICY1_VERSION = "1.2.3";
private static final String GROUP1_NAME = "groupA";
private static final String PDP1_TYPE = "pdpTypeA";
@@ -79,10 +92,365 @@ public class TestPdpGroupDeployProvider extends ProviderSuper {
}
@Test
- public void testDeployGroup() {
- Pair<Status, PdpGroupDeployResponse> pair = prov.deployGroup(new PdpGroups());
+ public void testCreateOrUpdateGroups() throws Exception {
+ Pair<Status, PdpGroupDeployResponse> pair = prov.createOrUpdateGroups(loadPdpGroups("emptyGroups.json"));
+ assertEquals(Status.OK, pair.getLeft());
+ assertNull(pair.getRight().getErrorDetails());
+
+ // no groups, so no action should have been taken
+ assertNoGroupAction();
+ }
+
+ @Test
+ public void testCreateOrUpdateGroups_InvalidRequest() throws Exception {
+ Pair<Status, PdpGroupDeployResponse> pair = prov.createOrUpdateGroups(new PdpGroups());
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertTrue(pair.getRight().getErrorDetails().contains("is null"));
+
+ assertNoGroupAction();
+ }
+
+ @Test
+ public void testCreateOrUpdate_Invalid() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ groups.getGroups().get(0).setPdpGroupState(PdpState.TERMINATED);
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.createOrUpdateGroups(groups);
assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
- assertEquals("not implemented yet", pair.getRight().getErrorDetails());
+ assertTrue(pair.getRight().getErrorDetails().contains("pdpGroupState"));
+
+ assertNoGroupAction();
+ }
+
+ @Test
+ public void testAddGroup() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup group = groups.getGroups().get(0);
+ group.setPdpGroupState(PdpState.PASSIVE);
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ // should not have updated the state
+ assertEquals(PdpState.PASSIVE, group.getPdpGroupState());
+
+ assertSame(group, getGroupCreates().get(0));
+ }
+
+ @Test
+ public void testAddGroup_Invalid() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ groups.getGroups().get(0).setPdpGroupState(PdpState.TERMINATED);
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.createOrUpdateGroups(groups);
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertTrue(pair.getRight().getErrorDetails().contains("pdpGroupState"));
+
+ assertNoGroupAction();
+ }
+
+ @Test
+ public void testAddGroup_InvalidSubGroup() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+
+ // policy won't match supported type
+ groups.getGroups().get(0).getPdpSubgroups().get(0).getSupportedPolicyTypes().get(0).setVersion("99.99.99");
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.createOrUpdateGroups(groups);
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertTrue(pair.getRight().getErrorDetails().contains("supported policy"));
+
+ assertNoGroupAction();
+ }
+
+ @Test
+ public void testValidateGroupOnly_NullState() {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ groups.getGroups().get(0).setPdpGroupState(null);
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+ }
+
+ @Test
+ public void testValidateGroupOnly_Active() {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ groups.getGroups().get(0).setPdpGroupState(PdpState.ACTIVE);
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+ }
+
+ @Test
+ public void testValidateGroupOnly_Passive() {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ groups.getGroups().get(0).setPdpGroupState(PdpState.PASSIVE);
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+ }
+
+ @Test
+ public void testValidateGroupOnly_Invalid() {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ groups.getGroups().get(0).setPdpGroupState(PdpState.TERMINATED);
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.createOrUpdateGroups(groups);
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertTrue(pair.getRight().getErrorDetails().contains("pdpGroupState"));
+ }
+
+ @Test
+ public void testUpdateGroup() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+
+ // DB group = new group
+ PdpGroup group = new PdpGroup(groups.getGroups().get(0));
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ assertNoGroupAction();
+ }
+
+ @Test
+ public void testUpdateGroup_PropertiesChanged() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+
+ PdpGroup group = new PdpGroup(groups.getGroups().get(0));
+ group.setProperties(new TreeMap<>());
+
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.createOrUpdateGroups(groups);
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertTrue(pair.getRight().getErrorDetails().contains("properties"));
+
+ assertNoGroupAction();
+ }
+
+ @Test
+ public void testUpdateGroup_NewDescription() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ group.setDescription("old description");
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ assertGroupUpdateOnly(group);
+
+ assertEquals(group.getDescription(), "my description");
+ assertEquals(newgrp.toString(), group.toString());
+ }
+
+ @Test
+ public void testUpdateGroup_NewSubGroup() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroupsNewSub.json");
+ PdpGroup group = loadPdpGroups("createGroups.json").getGroups().get(0);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ PdpGroup newgrp = groups.getGroups().get(0);
+ assertEquals(newgrp.toString(), group.toString());
+ assertGroupUpdateOnly(group);
+ }
+
+ @Test
+ public void testUpdateGroup_UpdatedSubGroup() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ // something different in this subgroup
+ group.getPdpSubgroups().get(0).setDesiredInstanceCount(10);
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ assertEquals(newgrp.toString(), group.toString());
+ assertGroupUpdateOnly(group);
+ }
+
+ @Test
+ public void testUpdateGroup_MultipleChanges() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ PdpSubGroup subgrp = newgrp.getPdpSubgroups().get(0);
+ subgrp.setDesiredInstanceCount(30);
+ subgrp.getPolicies().add(new ToscaPolicyIdentifier(POLICY2_NAME, POLICY1_VERSION));
+ subgrp.getSupportedPolicyTypes().add(new ToscaPolicyTypeIdentifier("typeX", "9.8.7"));
+
+ when(dao.getPolicyList(POLICY2_NAME, POLICY1_VERSION)).thenReturn(loadPolicies("createGroupNewPolicy.json"));
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ Collections.sort(newgrp.getPdpSubgroups().get(0).getPolicies());
+ Collections.sort(group.getPdpSubgroups().get(0).getPolicies());
+
+ assertEquals(newgrp.toString(), group.toString());
+
+ // this requires a PDP UPDATE message
+ assertGroupUpdate(group, subgrp);
+ }
+
+ @Test
+ public void testUpdateField_Unchanged() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ assertNoGroupAction();
+ }
+
+ @Test
+ public void testUpdateField_WasNull() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ group.setDescription(null);
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ assertEquals(newgrp.toString(), group.toString());
+ assertGroupUpdateOnly(group);
+ }
+
+ @Test
+ public void testUpdateField_NowNull() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ newgrp.setDescription(null);
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ assertEquals(newgrp.toString(), group.toString());
+ assertGroupUpdateOnly(group);
+ }
+
+ @Test
+ public void testUpdateField_Changed() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ newgrp.setDescription(group.getDescription() + "-changed");
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ assertEquals(newgrp.toString(), group.toString());
+ assertGroupUpdateOnly(group);
+ }
+
+ @Test
+ public void testAddSubGroup() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroupsNewSub.json");
+ PdpGroup group = loadPdpGroups("createGroups.json").getGroups().get(0);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ PdpGroup newgrp = groups.getGroups().get(0);
+
+ PdpSubGroup newsub = newgrp.getPdpSubgroups().get(1);
+ newsub.setCurrentInstanceCount(0);
+ newsub.setPdpInstances(new ArrayList<>(0));
+
+ assertEquals(newgrp.toString(), group.toString());
+ assertGroupUpdateOnly(group);
+ }
+
+ @Test
+ public void testUpdateSubGroup_Invalid() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ // change properties
+ newgrp.getPdpSubgroups().get(0).setProperties(new TreeMap<>());
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.createOrUpdateGroups(groups);
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertTrue(pair.getRight().getErrorDetails().contains("properties"));
+
+ assertNoGroupAction();
+ }
+
+ @Test
+ public void testUpdateSubGroup_SupportedPolicies() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ newgrp.getPdpSubgroups().get(0).getSupportedPolicyTypes().add(new ToscaPolicyTypeIdentifier("typeX", "9.8.7"));
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ assertEquals(newgrp.toString(), group.toString());
+ assertGroupUpdateOnly(group);
+ }
+
+ @Test
+ public void testUpdateSubGroup_DesiredCount() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ newgrp.getPdpSubgroups().get(0).setDesiredInstanceCount(20);
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ assertEquals(newgrp.toString(), group.toString());
+ assertGroupUpdateOnly(group);
+ }
+
+ @Test
+ public void testUpdateSubGroup_Policies() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ PdpSubGroup subgrp = newgrp.getPdpSubgroups().get(0);
+ subgrp.getPolicies().add(new ToscaPolicyIdentifier(POLICY2_NAME, POLICY1_VERSION));
+
+ when(dao.getPolicyList(POLICY2_NAME, POLICY1_VERSION)).thenReturn(loadPolicies("createGroupNewPolicy.json"));
+
+ assertEquals(Status.OK, prov.createOrUpdateGroups(groups).getLeft());
+
+ Collections.sort(newgrp.getPdpSubgroups().get(0).getPolicies());
+ Collections.sort(group.getPdpSubgroups().get(0).getPolicies());
+
+ assertEquals(newgrp.toString(), group.toString());
+
+ // this requires a PDP UPDATE message
+ assertGroupUpdate(group, subgrp);
+ }
+
+ @Test
+ public void testValidateSubGroup_PropertiesMismatch() throws Exception {
+ PdpGroups groups = loadPdpGroups("createGroups.json");
+ PdpGroup newgrp = groups.getGroups().get(0);
+ PdpGroup group = new PdpGroup(newgrp);
+ when(dao.getPdpGroups(group.getName())).thenReturn(Arrays.asList(group));
+
+ newgrp.setProperties(new TreeMap<>());
+
+ Pair<Status, PdpGroupDeployResponse> pair = prov.createOrUpdateGroups(groups);
+ assertEquals(Status.INTERNAL_SERVER_ERROR, pair.getLeft());
+ assertTrue(pair.getRight().getErrorDetails().contains("properties"));
+
+ assertNoGroupAction();
}
@Test
@@ -180,6 +548,44 @@ public class TestPdpGroupDeployProvider extends ProviderSuper {
assertTrue(update.getPolicies().contains(policy1));
}
+ private void assertNoGroupAction() throws Exception {
+ verify(dao, never()).createPdpGroups(any());
+ verify(dao, never()).updatePdpGroups(any());
+ verify(reqmap, never()).addRequest(any(), any());
+ }
+
+ private void assertGroupUpdate(PdpGroup group, PdpSubGroup subgrp) throws Exception {
+ verify(dao, never()).createPdpGroups(any());
+
+ assertEquals(0, getStateChangeRequests(1).size());
+
+ List<PdpUpdate> pdpUpdates = getUpdateRequests(1);
+ assertEquals(1, pdpUpdates.size());
+
+ PdpUpdate pdpUpdate = pdpUpdates.get(0);
+ assertEquals("pdpA", pdpUpdate.getName());
+ assertEquals(group.getName(), pdpUpdate.getPdpGroup());
+
+ assertEquals(subgrp.getPdpType(), pdpUpdate.getPdpSubgroup());
+
+ List<ToscaPolicyIdentifier> pdpPolicies =
+ pdpUpdate.getPolicies().stream().map(ToscaPolicy::getIdentifier).collect(Collectors.toList());
+ Collections.sort(pdpPolicies);
+
+ assertEquals(subgrp.getPolicies().toString(), pdpPolicies.toString());
+
+ List<PdpGroup> updates = getGroupUpdates();
+ assertEquals(Arrays.asList(group), updates);
+ }
+
+ private void assertGroupUpdateOnly(PdpGroup group) throws Exception {
+ verify(dao, never()).createPdpGroups(any());
+ verify(reqmap, never()).addRequest(any(), any());
+
+ List<PdpGroup> updates = getGroupUpdates();
+ assertEquals(Arrays.asList(group), updates);
+ }
+
/**
* Loads a standard request.
*
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestSessionData.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestSessionData.java
index fd351c89..2eac4324 100644
--- a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestSessionData.java
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestSessionData.java
@@ -20,9 +20,11 @@
package org.onap.policy.pap.main.rest.depundep;
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
@@ -35,20 +37,23 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Iterator;
import java.util.List;
import javax.ws.rs.core.Response.Status;
+import org.apache.commons.lang3.tuple.Pair;
import org.junit.Before;
import org.junit.Test;
import org.onap.policy.models.base.PfModelException;
import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpStateChange;
import org.onap.policy.models.pdp.concepts.PdpUpdate;
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.ToscaPolicyTypeIdentifier;
+import org.onap.policy.pap.main.PolicyPapRuntimeException;
public class TestSessionData extends ProviderSuper {
private static final String GROUP_NAME = "groupA";
- private static final String GROUP_NAME2 = "groupB";
private static final String PDP1 = "pdp_1";
private static final String PDP2 = "pdp_2";
private static final String PDP3 = "pdp_3";
@@ -58,6 +63,7 @@ public class TestSessionData extends ProviderSuper {
private static final String POLICY_VERSION2 = POLICY_VERSION_PREFIX + "4";
private static final String POLICY_TYPE = "myType";
private static final String POLICY_TYPE_VERSION = "10.20.30";
+ private static final String EXPECTED_EXCEPTION = "expected exception";
private SessionData session;
private ToscaPolicyIdentifier ident;
@@ -78,8 +84,8 @@ public class TestSessionData extends ProviderSuper {
ident = new ToscaPolicyIdentifier(POLICY_NAME, POLICY_VERSION);
type = new ToscaPolicyTypeIdentifier(POLICY_TYPE, POLICY_TYPE_VERSION);
type2 = new ToscaPolicyTypeIdentifier(POLICY_TYPE, POLICY_TYPE_VERSION + "0");
- group1 = makeGroup(GROUP_NAME);
- group2 = makeGroup(GROUP_NAME2);
+ group1 = loadGroup("group1.json");
+ group2 = loadGroup("group2.json");
session = new SessionData(dao);
}
@@ -116,14 +122,6 @@ public class TestSessionData extends ProviderSuper {
}
@Test
- public void testGetPolicy_TooMany() throws Exception {
- ToscaPolicy policy = new ToscaPolicy();
- when(dao.getPolicyList(any(), any())).thenReturn(Arrays.asList(policy, policy));
-
- assertThatThrownBy(() -> session.getPolicy(ident)).hasMessage("too many policies match: myPolicy 1.2.3");
- }
-
- @Test
public void testGetPolicy_DaoEx() throws Exception {
PfModelException ex = new PfModelException(Status.INTERNAL_SERVER_ERROR, "expected exception");
when(dao.getPolicyList(any(), any())).thenThrow(ex);
@@ -132,6 +130,71 @@ public class TestSessionData extends ProviderSuper {
}
@Test
+ public void testAddRequests_testGetPdpStateChanges_testGetPdpUpdates() {
+ // pre-load with a update and state-change for other PDPs
+ PdpUpdate update2 = makeUpdate(PDP2);
+ session.addUpdate(update2);
+
+ PdpStateChange change3 = makeStateChange(PDP3);
+ session.addStateChange(change3);
+
+ // add requests
+ PdpUpdate update = makeUpdate(PDP1);
+ PdpStateChange change = makeStateChange(PDP1);
+ session.addRequests(update, change);
+ verifyRequests(update, update2, change, change3);
+
+ /*
+ * repeat with a new pair
+ */
+ update = makeUpdate(PDP1);
+ change = makeStateChange(PDP1);
+ session.addRequests(update, change);
+ verifyRequests(update, update2, change, change3);
+
+ // just make an update this time
+ update = makeUpdate(PDP1);
+ session.addUpdate(update);
+ verifyRequests(update, update2, change, change3);
+ }
+
+ private void verifyRequests(PdpUpdate update, PdpUpdate update2, PdpStateChange change, PdpStateChange change3) {
+ List<Pair<PdpUpdate, PdpStateChange>> requests = sort(session.getPdpRequests(), this::compare);
+ assertEquals(3, requests.size());
+
+ System.out.println(requests);
+ System.out.println(update);
+
+ Iterator<Pair<PdpUpdate, PdpStateChange>> reqiter = requests.iterator();
+ Pair<PdpUpdate, PdpStateChange> pair = reqiter.next();
+ assertSame(update, pair.getLeft());
+ assertSame(change, pair.getRight());
+
+ pair = reqiter.next();
+ assertSame(update2, pair.getLeft());
+ assertSame(null, pair.getRight());
+
+ pair = reqiter.next();
+ assertSame(null, pair.getLeft());
+ assertSame(change3, pair.getRight());
+
+ // verify individual lists
+ List<PdpUpdate> updates = Arrays.asList(update, update2);
+ assertEquals(sort(updates, this::compare), sort(session.getPdpUpdates(), this::compare));
+
+ List<PdpStateChange> changes = Arrays.asList(change, change3);
+ assertEquals(sort(changes, this::compare), sort(session.getPdpStateChanges(), this::compare));
+ }
+
+ @Test
+ public void testAddRequests_MismatchedNames() {
+ PdpUpdate update = makeUpdate(PDP1);
+ PdpStateChange change = makeStateChange(PDP2);
+ assertThatIllegalArgumentException().isThrownBy(() -> session.addRequests(update, change))
+ .withMessage("PDP name mismatch pdp_1, pdp_2");
+ }
+
+ @Test
public void testAddUpdate_testGetPdpUpdates() {
// several different updates, but one duplicate
PdpUpdate update1 = makeUpdate(PDP1);
@@ -143,17 +206,40 @@ public class TestSessionData extends ProviderSuper {
PdpUpdate update3 = makeUpdate(PDP3);
session.addUpdate(update3);
- List<PdpUpdate> lst = sort(session.getPdpUpdates(), this::compare);
+ List<PdpUpdate> lst = sort(getUpdateRequests(), this::compare);
assertEquals(Arrays.asList(update1, update2, update3).toString(), lst.toString());
// overwrite one
update2 = makeUpdate(PDP2);
session.addUpdate(update2);
- lst = sort(session.getPdpUpdates(), this::compare);
+ lst = sort(getUpdateRequests(), this::compare);
assertEquals(Arrays.asList(update1, update2, update3).toString(), lst.toString());
}
+ @Test
+ public void testAddStateChange_testGetPdpStateChanges() {
+ // several different changes, but one duplicate
+ PdpStateChange change1 = makeStateChange(PDP1);
+ session.addStateChange(change1);
+
+ PdpStateChange change2 = makeStateChange(PDP2);
+ session.addStateChange(change2);
+
+ PdpStateChange change3 = makeStateChange(PDP3);
+ session.addStateChange(change3);
+
+ List<PdpStateChange> lst = sort(getStateChangeRequests(), this::compare);
+ assertEquals(Arrays.asList(change1, change2, change3).toString(), lst.toString());
+
+ // overwrite one
+ change2 = makeStateChange(PDP2);
+ session.addStateChange(change2);
+
+ lst = sort(getStateChangeRequests(), this::compare);
+ assertEquals(Arrays.asList(change1, change2, change3).toString(), lst.toString());
+ }
+
private ToscaPolicy makePolicy(String name, String version) {
ToscaPolicy policy = new ToscaPolicy();
@@ -183,12 +269,19 @@ public class TestSessionData extends ProviderSuper {
assertThatThrownBy(() -> session.getPolicyMaxVersion(POLICY_NAME)).hasMessage("cannot find policy: myPolicy");
}
- private PdpGroup makeGroup(String name) {
- PdpGroup group = new PdpGroup();
-
- group.setName(name);
-
- return group;
+ @Test
+ public void testCreate() throws Exception {
+ session.create(group1);
+ assertSame(group1, session.getGroup(group1.getName()));
+
+ // can add another
+ session.create(group2);
+ assertSame(group1, session.getGroup(group1.getName()));
+ assertSame(group2, session.getGroup(group2.getName()));
+
+ // cannot overwrite
+ assertThatIllegalStateException().isThrownBy(() -> session.create(group1))
+ .withMessage("group already cached: groupA");
}
@Test
@@ -229,6 +322,48 @@ public class TestSessionData extends ProviderSuper {
}
@Test
+ public void testGetGroup() throws Exception {
+ when(dao.getPdpGroups(GROUP_NAME)).thenReturn(Arrays.asList(group1));
+
+ assertSame(group1, session.getGroup(GROUP_NAME));
+ verify(dao).getPdpGroups(any());
+
+ // repeat
+ assertSame(group1, session.getGroup(GROUP_NAME));
+
+ // should not access dao again
+ verify(dao, times(1)).getPdpGroups(any());
+ }
+
+ @Test
+ public void testGetGroup_NotFound() throws Exception {
+ when(dao.getPdpGroups(GROUP_NAME)).thenReturn(Collections.emptyList());
+
+ assertNull(session.getGroup(GROUP_NAME));
+ verify(dao).getPdpGroups(any());
+
+ // repeat
+ assertNull(session.getGroup(GROUP_NAME));
+
+ // SHOULD access dao again
+ verify(dao, times(2)).getPdpGroups(GROUP_NAME);
+
+ // find it this time
+ when(dao.getPdpGroups(GROUP_NAME)).thenReturn(Arrays.asList(group1));
+ assertSame(group1, session.getGroup(GROUP_NAME));
+ verify(dao, times(3)).getPdpGroups(GROUP_NAME);
+ }
+
+ @Test
+ public void testGetGroup_DaoEx() throws Exception {
+ PfModelException ex = new PfModelException(Status.BAD_REQUEST, EXPECTED_EXCEPTION);
+ when(dao.getPdpGroups(GROUP_NAME)).thenThrow(ex);
+
+ assertThatThrownBy(() -> session.getGroup(GROUP_NAME)).isInstanceOf(PolicyPapRuntimeException.class)
+ .hasCause(ex);
+ }
+
+ @Test
public void testGetActivePdpGroupsByPolicyType() throws Exception {
List<PdpGroup> groups = Arrays.asList(group1, group2);
when(dao.getFilteredPdpGroups(any())).thenReturn(groups);
@@ -263,10 +398,17 @@ public class TestSessionData extends ProviderSuper {
@Test
public void testUpdateDb() throws Exception {
// force the groups into the cache
- PdpGroup group3 = makeGroup("groupC");
+ PdpGroup group3 = loadGroup("group3.json");
when(dao.getFilteredPdpGroups(any())).thenReturn(Arrays.asList(group1, group2, group3));
session.getActivePdpGroupsByPolicyType(type);
+ // create groups 4 & 5
+ PdpGroup group4 = loadGroup("group4.json");
+ session.create(group4);
+
+ PdpGroup group5 = loadGroup("group5.json");
+ session.create(group5);
+
// update group 1
when(dao.getFilteredPdpGroups(any())).thenReturn(Arrays.asList(group1));
PdpGroup newgrp1 = new PdpGroup(group1);
@@ -281,13 +423,25 @@ public class TestSessionData extends ProviderSuper {
PdpGroup newgrp3 = new PdpGroup(group3);
session.update(newgrp3);
+ // update group 5
+ when(dao.getFilteredPdpGroups(any())).thenReturn(Arrays.asList(group5));
+ PdpGroup newgrp5 = new PdpGroup(group5);
+ session.update(newgrp5);
+
// push the changes to the DB
session.updateDb();
+ // expect one create for groups 4 & 5 (group5 replaced by newgrp5)
+ List<PdpGroup> creates = getGroupCreates();
+ assertEquals(2, creates.size());
+ assertSame(group4, creates.get(0));
+ assertSame(newgrp5, creates.get(1));
+
// expect one update for groups 1 & 3
- List<PdpGroup> changes = getGroupUpdates();
- assertSame(newgrp1, changes.get(0));
- assertSame(newgrp3, changes.get(1));
+ List<PdpGroup> updates = getGroupUpdates();
+ assertEquals(2, updates.size());
+ assertSame(newgrp1, updates.get(0));
+ assertSame(newgrp3, updates.get(1));
}
@Test
@@ -301,6 +455,13 @@ public class TestSessionData extends ProviderSuper {
verify(dao, never()).updatePdpGroups(any());
}
+ @Test
+ public void testDeleteGroupFromDb() throws Exception {
+ session.deleteGroupFromDb(group1);
+
+ verify(dao).deletePdpGroup(group1.getName());
+ }
+
private PdpUpdate makeUpdate(String pdpName) {
PdpUpdate update = new PdpUpdate();
@@ -309,6 +470,22 @@ public class TestSessionData extends ProviderSuper {
return update;
}
+ private PdpStateChange makeStateChange(String pdpName) {
+ PdpStateChange change = new PdpStateChange();
+
+ change.setName(pdpName);
+
+ return change;
+ }
+
+ private List<PdpUpdate> getUpdateRequests() {
+ return session.getPdpUpdates();
+ }
+
+ private List<PdpStateChange> getStateChangeRequests() {
+ return session.getPdpStateChanges();
+ }
+
private <T> List<T> sort(Collection<T> collection, Comparator<T> comparator) {
List<T> lst = new ArrayList<>(collection);
Collections.sort(lst, comparator);
@@ -316,7 +493,19 @@ public class TestSessionData extends ProviderSuper {
return lst;
}
+ private int compare(Pair<PdpUpdate, PdpStateChange> left, Pair<PdpUpdate, PdpStateChange> right) {
+ return getName(left).compareTo(getName(right));
+ }
+
private int compare(PdpUpdate left, PdpUpdate right) {
return left.getName().compareTo(right.getName());
}
+
+ private int compare(PdpStateChange left, PdpStateChange right) {
+ return left.getName().compareTo(right.getName());
+ }
+
+ private String getName(Pair<PdpUpdate, PdpStateChange> pair) {
+ return (pair.getKey() != null ? pair.getKey().getName() : pair.getValue().getName());
+ }
}
diff --git a/main/src/test/resources/simpleDeploy/createGroupNewPolicy.json b/main/src/test/resources/simpleDeploy/createGroupNewPolicy.json
new file mode 100644
index 00000000..285db315
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/createGroupNewPolicy.json
@@ -0,0 +1,10 @@
+{
+ "policies": [
+ {
+ "name": "policyB",
+ "version": "1.2.3",
+ "type": "typeA",
+ "typeVersion": "100.2.3"
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/createGroups.json b/main/src/test/resources/simpleDeploy/createGroups.json
new file mode 100644
index 00000000..59c4eb87
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/createGroups.json
@@ -0,0 +1,39 @@
+{
+ "groups": [
+ {
+ "name": "groupA",
+ "version": "200.2.3",
+ "description": "my description",
+ "pdpGroupState": "ACTIVE",
+ "properties": {
+ "hello": "world"
+ },
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "desiredInstanceCount": 1,
+ "properties": {
+ "abc": "def"
+ },
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpA"
+ }
+ ],
+ "policies": [
+ {
+ "name": "policyA",
+ "version": "1.2.3"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/createGroupsNewSub.json b/main/src/test/resources/simpleDeploy/createGroupsNewSub.json
new file mode 100644
index 00000000..033ced8c
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/createGroupsNewSub.json
@@ -0,0 +1,56 @@
+{
+ "groups": [
+ {
+ "name": "groupA",
+ "version": "200.2.3",
+ "description": "my description",
+ "pdpGroupState": "ACTIVE",
+ "properties": {
+ "hello": "world"
+ },
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "desiredInstanceCount": 1,
+ "properties": {
+ "abc": "def"
+ },
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpA"
+ }
+ ],
+ "policies": [
+ {
+ "name": "policyA",
+ "version": "1.2.3"
+ }
+ ]
+ },
+ {
+ "pdpType": "pdpTypeB",
+ "desiredInstanceCount": 1,
+ "currentInstanceCount": 22,
+ "supportedPolicyTypes": [
+ {
+ "name": "typeA",
+ "version": "100.2.3"
+ }
+ ],
+ "pdpInstances": [
+ {
+ "instanceId": "pdpB"
+ }
+ ],
+ "policies": []
+ }
+ ]
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/deleteGroup.json b/main/src/test/resources/simpleDeploy/deleteGroup.json
new file mode 100644
index 00000000..6def3510
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/deleteGroup.json
@@ -0,0 +1,29 @@
+{
+ "name": "groupA",
+ "pdpGroupState": "PASSIVE",
+ "pdpSubgroups": [
+ {
+ "pdpType": "pdpTypeA",
+ "pdpInstances": [
+ {
+ "instanceId": "pdpA_1"
+ },
+ {
+ "instanceId": "pdpA_2"
+ }
+ ]
+ },
+ {
+ "pdpType": "pdpTypeB",
+ "pdpInstances": []
+ },
+ {
+ "pdpType": "pdpTypeC",
+ "pdpInstances": [
+ {
+ "instanceId": "pdpC_1"
+ }
+ ]
+ }
+ ]
+}
diff --git a/main/src/test/resources/simpleDeploy/group1.json b/main/src/test/resources/simpleDeploy/group1.json
new file mode 100644
index 00000000..8df853c1
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/group1.json
@@ -0,0 +1,3 @@
+{
+ "name": "groupA"
+}
diff --git a/main/src/test/resources/simpleDeploy/group2.json b/main/src/test/resources/simpleDeploy/group2.json
new file mode 100644
index 00000000..fca12ad0
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/group2.json
@@ -0,0 +1,3 @@
+{
+ "name": "groupB"
+}
diff --git a/main/src/test/resources/simpleDeploy/group3.json b/main/src/test/resources/simpleDeploy/group3.json
new file mode 100644
index 00000000..4a6ac2d6
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/group3.json
@@ -0,0 +1,3 @@
+{
+ "name": "groupC"
+}
diff --git a/main/src/test/resources/simpleDeploy/group4.json b/main/src/test/resources/simpleDeploy/group4.json
new file mode 100644
index 00000000..c73ab0ac
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/group4.json
@@ -0,0 +1,3 @@
+{
+ "name": "groupD"
+}
diff --git a/main/src/test/resources/simpleDeploy/group5.json b/main/src/test/resources/simpleDeploy/group5.json
new file mode 100644
index 00000000..4bd56272
--- /dev/null
+++ b/main/src/test/resources/simpleDeploy/group5.json
@@ -0,0 +1,3 @@
+{
+ "name": "groupE"
+}