From 4f3fe21aa98a196ef1ddd62e1ac84a6c2e4c13cf Mon Sep 17 00:00:00 2001 From: jh7358 Date: Wed, 16 Oct 2019 11:51:46 -0400 Subject: Generate notifications when policies change Updated existing PAP code to make use of new notification classes. Change-Id: I4637ad92ac4f432f215cfc837e672c75074d88b5 Issue-ID: POLICY-1841 Signed-off-by: Jim Hahn --- .../org/onap/policy/pap/main/PapConstants.java | 2 + .../policy/pap/main/comm/PdpModifyRequestMap.java | 15 ++- .../org/onap/policy/pap/main/comm/PdpRequests.java | 14 ++- .../onap/policy/pap/main/comm/msgdata/Request.java | 8 ++ .../policy/pap/main/comm/msgdata/RequestImpl.java | 10 +- .../pap/main/comm/msgdata/StateChangeReq.java | 3 +- .../policy/pap/main/comm/msgdata/UpdateReq.java | 14 ++- .../main/parameters/PdpModifyRequestMapParams.java | 24 ++++- .../policy/pap/main/parameters/RequestParams.java | 9 +- .../main/rest/depundep/PdpGroupDeleteProvider.java | 11 ++- .../main/rest/depundep/PdpGroupDeployProvider.java | 68 ++++++++++++-- .../pap/main/rest/depundep/ProviderBase.java | 37 +++++--- .../policy/pap/main/rest/depundep/SessionData.java | 102 +++++++++++++++++++++ .../policy/pap/main/startstop/PapActivator.java | 24 ++++- .../policy/pap/main/comm/CommonRequestBase.java | 11 ++- .../pap/main/comm/PdpModifyRequestMapTest.java | 3 + .../onap/policy/pap/main/comm/PdpRequestsTest.java | 3 +- .../pap/main/comm/msgdata/RequestImplTest.java | 2 +- .../pap/main/comm/msgdata/UpdateReqTest.java | 24 +++++ .../parameters/TestPdpModifyRequestMapParams.java | 32 ++++++- .../pap/main/parameters/TestRequestParams.java | 13 +-- .../pap/main/rest/depundep/ProviderSuper.java | 5 + .../rest/depundep/TestPdpGroupDeleteProvider.java | 31 +++++-- .../rest/depundep/TestPdpGroupDeployProvider.java | 70 +++++++++++++- .../pap/main/rest/depundep/TestProviderBase.java | 34 ++++++- .../pap/main/rest/depundep/TestSessionData.java | 73 +++++++++++++++ .../pap/main/startstop/TestPapActivator.java | 6 ++ .../test/resources/e2e/PapConfigParameters.json | 4 + .../resources/parameters/PapConfigParameters.json | 4 + .../parameters/PapConfigParametersStd.json | 4 + .../simpleDeploy/createGroupsDelPolicy.json | 43 +++++++++ .../simpleDeploy/daoPolicyListDelPolicy.json | 10 ++ 32 files changed, 632 insertions(+), 81 deletions(-) create mode 100644 main/src/test/resources/simpleDeploy/createGroupsDelPolicy.json create mode 100644 main/src/test/resources/simpleDeploy/daoPolicyListDelPolicy.json (limited to 'main') diff --git a/main/src/main/java/org/onap/policy/pap/main/PapConstants.java b/main/src/main/java/org/onap/policy/pap/main/PapConstants.java index 3fc36f35..b8b199e6 100644 --- a/main/src/main/java/org/onap/policy/pap/main/PapConstants.java +++ b/main/src/main/java/org/onap/policy/pap/main/PapConstants.java @@ -31,10 +31,12 @@ public class PapConstants { public static final String REG_PDP_MODIFY_LOCK = "lock:pdp"; public static final String REG_PDP_MODIFY_MAP = "object:pdp/modify/map"; public static final String REG_PDP_TRACKER = "object:pdp/tracker"; + public static final String REG_POLICY_NOTIFIER = "object:policy/notifier"; public static final String REG_PAP_DAO_FACTORY = "object:pap/dao/factory"; // topic names public static final String TOPIC_POLICY_PDP_PAP = "POLICY-PDP-PAP"; + public static final String TOPIC_POLICY_NOTIFICATION = "POLICY-NOTIFICATION"; private PapConstants() { super(); diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/PdpModifyRequestMap.java b/main/src/main/java/org/onap/policy/pap/main/comm/PdpModifyRequestMap.java index 3f0b5c11..f058da32 100644 --- a/main/src/main/java/org/onap/policy/pap/main/comm/PdpModifyRequestMap.java +++ b/main/src/main/java/org/onap/policy/pap/main/comm/PdpModifyRequestMap.java @@ -41,6 +41,7 @@ import org.onap.policy.pap.main.comm.msgdata.Request; import org.onap.policy.pap.main.comm.msgdata.RequestListener; import org.onap.policy.pap.main.comm.msgdata.StateChangeReq; import org.onap.policy.pap.main.comm.msgdata.UpdateReq; +import org.onap.policy.pap.main.notification.PolicyNotifier; import org.onap.policy.pap.main.parameters.PdpModifyRequestMapParams; import org.onap.policy.pap.main.parameters.RequestParams; import org.slf4j.Logger; @@ -74,6 +75,11 @@ public class PdpModifyRequestMap { */ private final PolicyModelsProviderFactoryWrapper daoFactory; + /** + * Used to notify when policy updates completes. + */ + private final PolicyNotifier policyNotifier; + /** * Constructs the object. @@ -88,6 +94,7 @@ public class PdpModifyRequestMap { this.params = params; this.modifyLock = params.getModifyLock(); this.daoFactory = params.getDaoFactory(); + this.policyNotifier = params.getPolicyNotifier(); } /** @@ -150,7 +157,7 @@ public class PdpModifyRequestMap { .setMaxRetryCount(params.getParams().getUpdateParameters().getMaxRetryCount()) .setTimers(params.getUpdateTimers()) .setModifyLock(params.getModifyLock()) - .setPublisher(params.getPublisher()) + .setPdpPublisher(params.getPdpPublisher()) .setResponseDispatcher(params.getResponseDispatcher()); // @formatter:on @@ -179,7 +186,7 @@ public class PdpModifyRequestMap { .setMaxRetryCount(params.getParams().getStateChangeParameters().getMaxRetryCount()) .setTimers(params.getStateChangeTimers()) .setModifyLock(params.getModifyLock()) - .setPublisher(params.getPublisher()) + .setPdpPublisher(params.getPdpPublisher()) .setResponseDispatcher(params.getResponseDispatcher()); // @formatter:on @@ -299,7 +306,7 @@ public class PdpModifyRequestMap { * @return a new set of requests */ protected PdpRequests makePdpRequests(String pdpName) { - return new PdpRequests(pdpName); + return new PdpRequests(pdpName, policyNotifier); } /** @@ -359,6 +366,8 @@ public class PdpModifyRequestMap { */ private void disablePdp(PdpRequests requests) { + policyNotifier.removePdp(requests.getPdpName()); + // remove the requests from the map if (!pdp2requests.remove(requests.getPdpName(), requests)) { // don't have the info we need to disable it diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/PdpRequests.java b/main/src/main/java/org/onap/policy/pap/main/comm/PdpRequests.java index 5863b2cb..4e1e9233 100644 --- a/main/src/main/java/org/onap/policy/pap/main/comm/PdpRequests.java +++ b/main/src/main/java/org/onap/policy/pap/main/comm/PdpRequests.java @@ -23,6 +23,7 @@ package org.onap.policy.pap.main.comm; import lombok.Getter; import org.onap.policy.models.pdp.concepts.PdpMessage; import org.onap.policy.pap.main.comm.msgdata.Request; +import org.onap.policy.pap.main.notification.PolicyNotifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +45,12 @@ public class PdpRequests { @Getter private final String pdpName; + /** + * Notifier for policy update completions. + */ + @Getter + private final PolicyNotifier notifier; + /** * Index of request currently being published. */ @@ -60,8 +67,9 @@ public class PdpRequests { * * @param pdpName name of the PDP with which the requests are associated */ - public PdpRequests(String pdpName) { + public PdpRequests(String pdpName, PolicyNotifier notifier) { this.pdpName = pdpName; + this.notifier = notifier; } /** @@ -71,6 +79,8 @@ public class PdpRequests { */ public void addSingleton(Request request) { + request.setNotifier(notifier); + if (request.getMessage().getName() == null) { throw new IllegalArgumentException("unexpected broadcast for " + pdpName); } @@ -86,7 +96,7 @@ public class PdpRequests { singletons[priority] = request; // stop publishing anything of a lower priority - QueueToken token = stopPublishingLowerPriority(priority); + final QueueToken token = stopPublishingLowerPriority(priority); // start publishing if nothing of higher priority if (higherPrioritySingleton(priority)) { diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/Request.java b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/Request.java index 1f69dcb5..62aea789 100644 --- a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/Request.java +++ b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/Request.java @@ -23,6 +23,7 @@ package org.onap.policy.pap.main.comm.msgdata; import org.onap.policy.models.pdp.concepts.PdpMessage; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.pap.main.comm.QueueToken; +import org.onap.policy.pap.main.notification.PolicyNotifier; /** * Request data, whose message may be changed at any point, possibly triggering a restart @@ -60,6 +61,13 @@ public interface Request { */ public void setListener(RequestListener listener); + /** + * Sets the notifier to track responses to the request. + * + * @param notifier notifier used to publish notifications + */ + public void setNotifier(PolicyNotifier notifier); + /** * Determines if this request is currently being published. * diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/RequestImpl.java b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/RequestImpl.java index 1945b32d..a110ef44 100644 --- a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/RequestImpl.java +++ b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/RequestImpl.java @@ -30,6 +30,7 @@ import org.onap.policy.models.pdp.concepts.PdpMessage; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.pap.main.comm.QueueToken; import org.onap.policy.pap.main.comm.TimerManager; +import org.onap.policy.pap.main.notification.PolicyNotifier; import org.onap.policy.pap.main.parameters.RequestParams; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,6 +64,13 @@ public abstract class RequestImpl implements Request { @Setter private RequestListener listener; + /** + * Notifier for policy update completions. + */ + @Getter + @Setter + private PolicyNotifier notifier; + /** * Current retry count. */ @@ -217,7 +225,7 @@ public abstract class RequestImpl implements Request { // couldn't take the other's place - add our own token to the queue token = new QueueToken<>(message); - params.getPublisher().enqueue(token); + params.getPdpPublisher().enqueue(token); } /** diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/StateChangeReq.java b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/StateChangeReq.java index e38cb0fd..40acd3ad 100644 --- a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/StateChangeReq.java +++ b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/StateChangeReq.java @@ -20,7 +20,6 @@ package org.onap.policy.pap.main.comm.msgdata; -import org.onap.policy.models.pdp.concepts.PdpMessage; import org.onap.policy.models.pdp.concepts.PdpStateChange; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.pap.main.parameters.RequestParams; @@ -39,7 +38,7 @@ public class StateChangeReq extends RequestImpl { * * @throws IllegalArgumentException if a required parameter is not set */ - public StateChangeReq(RequestParams params, String name, PdpMessage message) { + public StateChangeReq(RequestParams params, String name, PdpStateChange message) { super(params, name, message); } diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java index 8efdb7ca..6b04e726 100644 --- a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java +++ b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java @@ -26,7 +26,6 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; -import org.onap.policy.models.pdp.concepts.PdpMessage; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.models.pdp.concepts.PdpUpdate; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; @@ -48,7 +47,7 @@ public class UpdateReq extends RequestImpl { * * @throws IllegalArgumentException if a required parameter is not set */ - public UpdateReq(RequestParams params, String name, PdpMessage message) { + public UpdateReq(RequestParams params, String name, PdpUpdate message) { super(params, name, message); } @@ -61,10 +60,15 @@ public class UpdateReq extends RequestImpl { public String checkResponse(PdpStatus response) { String reason = super.checkResponse(response); if (reason != null) { + // response isn't for this PDP - don't generate notifications return reason; } + Set actualSet = new HashSet<>(alwaysList(response.getPolicies())); + getNotifier().processResponse(getName(), actualSet); + PdpUpdate message = getMessage(); + if (!StringUtils.equals(message.getPdpGroup(), response.getPdpGroup())) { return "group does not match"; } @@ -74,11 +78,11 @@ public class UpdateReq extends RequestImpl { } // see if the policies match - Set set1 = new HashSet<>(alwaysList(response.getPolicies())); - Set set2 = new HashSet<>(alwaysList(message.getPolicies()).stream() + + Set expectedSet = new HashSet<>(alwaysList(message.getPolicies()).stream() .map(ToscaPolicy::getIdentifier).collect(Collectors.toSet())); - if (!set1.equals(set2)) { + if (!actualSet.equals(expectedSet)) { return "policies do not match"; } diff --git a/main/src/main/java/org/onap/policy/pap/main/parameters/PdpModifyRequestMapParams.java b/main/src/main/java/org/onap/policy/pap/main/parameters/PdpModifyRequestMapParams.java index 2f74bf3d..9a3e7a45 100644 --- a/main/src/main/java/org/onap/policy/pap/main/parameters/PdpModifyRequestMapParams.java +++ b/main/src/main/java/org/onap/policy/pap/main/parameters/PdpModifyRequestMapParams.java @@ -22,10 +22,12 @@ package org.onap.policy.pap.main.parameters; import lombok.Getter; import org.onap.policy.common.endpoints.listeners.RequestIdDispatcher; +import org.onap.policy.models.pdp.concepts.PdpMessage; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper; import org.onap.policy.pap.main.comm.Publisher; import org.onap.policy.pap.main.comm.TimerManager; +import org.onap.policy.pap.main.notification.PolicyNotifier; /** @@ -33,13 +35,14 @@ import org.onap.policy.pap.main.comm.TimerManager; */ @Getter public class PdpModifyRequestMapParams { - private Publisher publisher; + private Publisher pdpPublisher; private RequestIdDispatcher responseDispatcher; private Object modifyLock; private PdpParameters params; private TimerManager updateTimers; private TimerManager stateChangeTimers; private PolicyModelsProviderFactoryWrapper daoFactory; + private PolicyNotifier policyNotifier; public PdpModifyRequestMapParams setParams(PdpParameters params) { this.params = params; @@ -61,8 +64,13 @@ public class PdpModifyRequestMapParams { return this; } - public PdpModifyRequestMapParams setPublisher(Publisher publisher) { - this.publisher = publisher; + public PdpModifyRequestMapParams setPolicyNotifier(PolicyNotifier policyNotifier) { + this.policyNotifier = policyNotifier; + return this; + } + + public PdpModifyRequestMapParams setPdpPublisher(Publisher pdpPublisher) { + this.pdpPublisher = pdpPublisher; return this; } @@ -80,7 +88,7 @@ public class PdpModifyRequestMapParams { * Validates the parameters. */ public void validate() { - if (publisher == null) { + if (pdpPublisher == null) { throw new IllegalArgumentException("missing publisher"); } @@ -103,5 +111,13 @@ public class PdpModifyRequestMapParams { if (stateChangeTimers == null) { throw new IllegalArgumentException("missing stateChangeTimers"); } + + if (daoFactory == null) { + throw new IllegalArgumentException("missing DAO factory"); + } + + if (policyNotifier == null) { + throw new IllegalArgumentException("missing policy notifier"); + } } } diff --git a/main/src/main/java/org/onap/policy/pap/main/parameters/RequestParams.java b/main/src/main/java/org/onap/policy/pap/main/parameters/RequestParams.java index b9083864..57d4ddaa 100644 --- a/main/src/main/java/org/onap/policy/pap/main/parameters/RequestParams.java +++ b/main/src/main/java/org/onap/policy/pap/main/parameters/RequestParams.java @@ -22,6 +22,7 @@ package org.onap.policy.pap.main.parameters; import lombok.Getter; import org.onap.policy.common.endpoints.listeners.RequestIdDispatcher; +import org.onap.policy.models.pdp.concepts.PdpMessage; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.pap.main.comm.Publisher; import org.onap.policy.pap.main.comm.TimerManager; @@ -32,15 +33,15 @@ import org.onap.policy.pap.main.comm.TimerManager; */ @Getter public class RequestParams { - private Publisher publisher; + private Publisher pdpPublisher; private RequestIdDispatcher responseDispatcher; private Object modifyLock; private TimerManager timers; private int maxRetryCount; - public RequestParams setPublisher(Publisher publisher) { - this.publisher = publisher; + public RequestParams setPdpPublisher(Publisher publisher) { + this.pdpPublisher = publisher; return this; } @@ -68,7 +69,7 @@ public class RequestParams { * Validates the parameters. */ public void validate() { - if (publisher == null) { + if (pdpPublisher == null) { throw new IllegalArgumentException("missing publisher"); } 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 0ca32451..09ad862b 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 @@ -21,12 +21,13 @@ package org.onap.policy.pap.main.rest.depundep; import java.util.Iterator; -import java.util.function.BiFunction; +import java.util.Set; import java.util.function.Predicate; +import java.util.stream.Collectors; import javax.ws.rs.core.Response.Status; import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.pdp.concepts.Pdp; 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; @@ -122,7 +123,7 @@ public class PdpGroupDeleteProvider extends ProviderBase { * Returns a function that will remove the desired policy from a subgroup. */ @Override - protected BiFunction makeUpdater(ToscaPolicy policy, + protected Updater makeUpdater(SessionData data, ToscaPolicy policy, ToscaPolicyIdentifierOptVersion desiredIdent) { // construct a matcher based on whether or not the version was specified @@ -142,6 +143,8 @@ public class PdpGroupDeleteProvider extends ProviderBase { // return a function that will remove the policy from the subgroup return (group, subgroup) -> { + Set pdps = subgroup.getPdpInstances().stream().map(Pdp::getInstanceId).collect(Collectors.toSet()); + boolean result = false; Iterator iter = subgroup.getPolicies().iterator(); @@ -153,6 +156,8 @@ public class PdpGroupDeleteProvider extends ProviderBase { iter.remove(); logger.info("remove policy {} {} from subgroup {} {} count={}", ident.getName(), ident.getVersion(), group.getName(), subgroup.getPdpType(), subgroup.getPolicies().size()); + + data.trackUndeploy(ident, pdps); } } 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 bc3148ef..1e00528e 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 @@ -28,8 +28,8 @@ 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 java.util.stream.Collectors; import javax.ws.rs.core.Response.Status; import org.onap.policy.common.parameters.BeanValidationResult; import org.onap.policy.common.parameters.ObjectValidationResult; @@ -269,8 +269,9 @@ public class PdpGroupDeployProvider extends ProviderBase { * @param dbgroup the group, as it appears within the DB * @param group the group being updated * @return {@code true} if a subgroup was removed, {@code false} otherwise + * @throws PfModelException if an error occurred */ - private boolean notifyPdpsDelSubGroups(SessionData data, PdpGroup dbgroup, PdpGroup group) { + private boolean notifyPdpsDelSubGroups(SessionData data, PdpGroup dbgroup, PdpGroup group) throws PfModelException { boolean updated = false; // subgroups, as they appear within the updated group @@ -284,6 +285,7 @@ public class PdpGroupDeployProvider extends ProviderBase { // this subgroup no longer appears - notify its PDPs updated = true; notifyPdpsDelSubGroup(data, subgrp); + trackPdpsDelSubGroup(data, subgrp); } } @@ -313,11 +315,27 @@ public class PdpGroupDeployProvider extends ProviderBase { } } + /** + * Tracks PDP responses when their subgroup is removed. + * + * @param data session data + * @param subgrp subgroup that is being removed + * @throws PfModelException if an error occurred + */ + private void trackPdpsDelSubGroup(SessionData data, PdpSubGroup subgrp) throws PfModelException { + Set pdps = subgrp.getPdpInstances().stream().map(Pdp::getInstanceId).collect(Collectors.toSet()); + + for (ToscaPolicyIdentifier policyId : subgrp.getPolicies()) { + data.trackUndeploy(policyId, pdps); + } + } + /** * Adds a new subgroup. * * @param data session data - * @param subgrp the subgroup to be added, updated to fully qualified versions upon return + * @param subgrp the subgroup to be added, updated to fully qualified versions upon + * return * @return the validation result * @throws PfModelException if an error occurred */ @@ -339,7 +357,8 @@ public class PdpGroupDeployProvider extends ProviderBase { * @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, updated to fully qualified versions upon return + * @param subgrp the subgroup to be updated, updated to fully qualified versions upon + * return * @param container container for additional validation results * @return {@code true} if the subgroup content was changed, {@code false} if there * were no changes @@ -356,7 +375,7 @@ public class PdpGroupDeployProvider extends ProviderBase { /* * first, apply the changes about which the PDPs care */ - boolean updated = updateList(dbsub.getPolicies(), subgrp.getPolicies(), dbsub::setPolicies); + boolean updated = updatePolicies(data, dbsub, subgrp); // publish any changes to the PDPs if (updated) { @@ -373,12 +392,40 @@ public class PdpGroupDeployProvider extends ProviderBase { dbsub::setDesiredInstanceCount) || updated; } + private boolean updatePolicies(SessionData data, PdpSubGroup dbsub, PdpSubGroup subgrp) throws PfModelException { + Set undeployed = new HashSet<>(dbsub.getPolicies()); + undeployed.removeAll(subgrp.getPolicies()); + + Set deployed = new HashSet<>(subgrp.getPolicies()); + deployed.removeAll(dbsub.getPolicies()); + + if (deployed.isEmpty() && undeployed.isEmpty()) { + // lists are identical + return false; + } + + + Set pdps = subgrp.getPdpInstances().stream().map(Pdp::getInstanceId).collect(Collectors.toSet()); + + for (ToscaPolicyIdentifier policyId : deployed) { + data.trackDeploy(policyId, pdps); + } + + for (ToscaPolicyIdentifier policyId : undeployed) { + data.trackUndeploy(policyId, pdps); + } + + dbsub.setPolicies(new ArrayList<>(subgrp.getPolicies())); + return true; + } + /** * Performs additional validations of a subgroup. * * @param data session data * @param dbsub the subgroup, from the DB - * @param subgrp the subgroup to be validated, updated to fully qualified versions upon return + * @param subgrp the subgroup to be validated, updated to fully qualified versions + * upon return * @param container container for additional validation results * @return {@code true} if the subgroup is valid, {@code false} otherwise * @throws PfModelException if an error occurred @@ -455,7 +502,8 @@ public class PdpGroupDeployProvider extends ProviderBase { private ValidationResult validatePolicies(SessionData data, PdpSubGroup dbsub, PdpSubGroup subgrp) throws PfModelException { - // build a map of the DB data, from policy name to (fully qualified) policy version + // build a map of the DB data, from policy name to (fully qualified) policy + // version Map dbname2vers = new HashMap<>(); if (dbsub != null) { dbsub.getPolicies().forEach(ident -> dbname2vers.put(ident.getName(), ident.getVersion())); @@ -557,7 +605,7 @@ public class PdpGroupDeployProvider extends ProviderBase { * Adds a policy to a subgroup, if it isn't there already. */ @Override - protected BiFunction makeUpdater(ToscaPolicy policy, + protected Updater makeUpdater(SessionData data, ToscaPolicy policy, ToscaPolicyIdentifierOptVersion requestedIdent) { ToscaPolicyIdentifier desiredIdent = policy.getIdentifier(); @@ -586,6 +634,10 @@ public class PdpGroupDeployProvider extends ProviderBase { logger.info("add policy {} {} to subgroup {} {} count={}", desiredIdent.getName(), desiredIdent.getVersion(), group.getName(), subgroup.getPdpType(), subgroup.getPolicies().size()); + + Set pdps = subgroup.getPdpInstances().stream().map(Pdp::getInstanceId).collect(Collectors.toSet()); + data.trackDeploy(desiredIdent, pdps); + return true; }; } 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 70ccd7ab..fd8edf17 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 @@ -21,17 +21,13 @@ package org.onap.policy.pap.main.rest.depundep; import java.util.Collection; -import java.util.Collections; -import java.util.function.BiFunction; import java.util.stream.Collectors; import javax.ws.rs.core.Response.Status; -import org.apache.commons.lang3.tuple.Pair; import org.onap.policy.common.utils.services.Registry; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; 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; @@ -41,6 +37,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifi import org.onap.policy.pap.main.PapConstants; import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper; import org.onap.policy.pap.main.comm.PdpModifyRequestMap; +import org.onap.policy.pap.main.notification.PolicyNotifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,6 +66,11 @@ public abstract class ProviderBase { */ private final PdpModifyRequestMap requestMap; + /** + * Generates policy notifications based on responses from PDPs. + */ + private final PolicyNotifier notifier; + /** * Factory for PAP DAO. */ @@ -82,6 +84,7 @@ public abstract class ProviderBase { this.updateLock = Registry.get(PapConstants.REG_PDP_MODIFY_LOCK, Object.class); this.requestMap = Registry.get(PapConstants.REG_PDP_MODIFY_MAP, PdpModifyRequestMap.class); this.daoFactory = Registry.get(PapConstants.REG_PAP_DAO_FACTORY, PolicyModelsProviderFactoryWrapper.class); + this.notifier = Registry.get(PapConstants.REG_POLICY_NOTIFIER, PolicyNotifier.class); } /** @@ -94,19 +97,16 @@ public abstract class ProviderBase { protected void process(T request, BiConsumerWithEx processor) throws PfModelException { synchronized (updateLock) { - // list of requests to be published to the PDPs - Collection> requests = Collections.emptyList(); + SessionData data; try (PolicyModelsProvider dao = daoFactory.create()) { - SessionData data = new SessionData(dao); + data = new SessionData(dao); processor.accept(data, request); // make all of the DB updates data.updateDb(); - requests = data.getPdpRequests(); - } catch (PfModelException | PfModelRuntimeException e) { logger.warn(DEPLOY_FAILED, e); throw e; @@ -116,9 +116,12 @@ public abstract class ProviderBase { throw new PfModelException(Status.INTERNAL_SERVER_ERROR, "request failed", e); } + // track responses for notification purposes + data.getDeployData().forEach(notifier::addDeploymentData); + data.getUndeployData().forEach(notifier::addUndeploymentData); // publish the requests - requests.forEach(pair -> requestMap.addRequest(pair.getLeft(), pair.getRight())); + data.getPdpRequests().forEach(pair -> requestMap.addRequest(pair.getLeft(), pair.getRight())); } } @@ -140,7 +143,7 @@ public abstract class ProviderBase { + desiredPolicy.getName() + " " + desiredPolicy.getVersion()); } - BiFunction updater = makeUpdater(policy, desiredPolicy); + Updater updater = makeUpdater(data, policy, desiredPolicy); for (PdpGroup group : groups) { upgradeGroup(data, group, updater); @@ -152,11 +155,12 @@ public abstract class ProviderBase { * {@code true} if the subgroup was updated, {@code false} if no update was * necessary/appropriate. * + * @param data session data * @param policy policy to be added to or removed from each subgroup * @param desiredPolicy request policy * @return a function to update a subgroup */ - protected abstract BiFunction makeUpdater(ToscaPolicy policy, + protected abstract Updater makeUpdater(SessionData data, ToscaPolicy policy, ToscaPolicyIdentifierOptVersion desiredPolicy); /** @@ -180,9 +184,9 @@ public abstract class ProviderBase { * @param data session data * @param group the original group, to be updated * @param updater function to update a group - * @throws PfModelRuntimeException if an error occurred + * @throws PfModelException if an error occurred */ - private void upgradeGroup(SessionData data, PdpGroup group, BiFunction updater) { + private void upgradeGroup(SessionData data, PdpGroup group, Updater updater) throws PfModelException { boolean updated = false; @@ -275,4 +279,9 @@ public abstract class ProviderBase { */ void accept(F firstArg, S secondArg) throws PfModelException; } + + @FunctionalInterface + public static interface Updater { + boolean apply(PdpGroup group, PdpSubGroup subgroup) throws PfModelException; + } } 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 437d7a11..5b2a8eea 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 @@ -23,8 +23,10 @@ package org.onap.policy.pap.main.rest.depundep; import java.util.Collection; 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.regex.Pattern; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; @@ -38,9 +40,11 @@ import org.onap.policy.models.provider.PolicyModelsProvider; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyFilter.ToscaPolicyFilterBuilder; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifierOptVersion; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; +import org.onap.policy.pap.main.notification.PolicyPdpNotificationData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -88,6 +92,18 @@ public class SessionData { */ private final Map typeCache = new HashMap<>(); + /** + * Policies to be deployed. This is just used to build up the data, which is then + * passed to the notifier once the update is "committed". + */ + private final Map deploy = new HashMap<>(); + + /** + * Policies to be undeployed. This is just used to build up the data, which is then + * passed to the notifier once the update is "committed". + */ + private final Map undeploy = new HashMap<>(); + /** * Constructs the object. @@ -402,4 +418,90 @@ public class SessionData { logger.info("deleting DB group {}", group.getName()); dao.deletePdpGroup(group.getName()); } + + /** + * Adds policy deployment data. + * + * @param policyId ID of the policy being deployed + * @param pdps PDPs to which the policy is being deployed + * @throws PfModelException if an error occurred + */ + protected void trackDeploy(ToscaPolicyIdentifier policyId, Collection pdps) throws PfModelException { + trackDeploy(policyId, new HashSet<>(pdps)); + } + + /** + * Adds policy deployment data. + * + * @param policyId ID of the policy being deployed + * @param pdps PDPs to which the policy is being deployed + * @throws PfModelException if an error occurred + */ + protected void trackDeploy(ToscaPolicyIdentifier policyId, Set pdps) throws PfModelException { + addData(policyId, pdps, deploy, undeploy); + } + + /** + * Adds policy undeployment data. + * + * @param policyId ID of the policy being undeployed + * @param pdps PDPs to which the policy is being undeployed + * @throws PfModelException if an error occurred + */ + protected void trackUndeploy(ToscaPolicyIdentifier policyId, Collection pdps) throws PfModelException { + trackUndeploy(policyId, new HashSet<>(pdps)); + } + + /** + * Adds policy undeployment data. + * + * @param policyId ID of the policy being undeployed + * @param pdps PDPs to which the policy is being undeployed + * @throws PfModelException if an error occurred + */ + protected void trackUndeploy(ToscaPolicyIdentifier policyId, Set pdps) throws PfModelException { + addData(policyId, pdps, undeploy, deploy); + } + + /** + * Adds policy deployment/undeployment data. + * + * @param policyId ID of the policy being deployed/undeployed + * @param pdps PDPs to which the policy is being deployed/undeployed + * @param addMap map to which it should be added + * @param removeMap map from which it should be removed + * @throws PfModelException if an error occurred + */ + private void addData(ToscaPolicyIdentifier policyId, Set pdps, + Map addMap, + Map removeMap) throws PfModelException { + + PolicyPdpNotificationData removeData = removeMap.get(policyId); + if (removeData != null) { + removeData.removeAll(pdps); + } + + ToscaPolicyIdentifierOptVersion optid = new ToscaPolicyIdentifierOptVersion(policyId); + ToscaPolicyTypeIdentifier policyType = getPolicy(optid).getTypeIdentifier(); + + addMap.computeIfAbsent(policyId, key -> new PolicyPdpNotificationData(policyId, policyType)).addAll(pdps); + } + + /** + * Gets the policies to be deployed. + * + * @return the policies to be deployed + */ + public Collection getDeployData() { + return deploy.values(); + } + + /** + * Gets the policies to be undeployed. + * + * @return the policies to be undeployed + */ + public Collection getUndeployData() { + return undeploy.values(); + } } diff --git a/main/src/main/java/org/onap/policy/pap/main/startstop/PapActivator.java b/main/src/main/java/org/onap/policy/pap/main/startstop/PapActivator.java index d119044f..8d2fd3ea 100644 --- a/main/src/main/java/org/onap/policy/pap/main/startstop/PapActivator.java +++ b/main/src/main/java/org/onap/policy/pap/main/startstop/PapActivator.java @@ -31,6 +31,8 @@ import org.onap.policy.common.endpoints.listeners.RequestIdDispatcher; import org.onap.policy.common.parameters.ParameterService; import org.onap.policy.common.utils.services.Registry; import org.onap.policy.common.utils.services.ServiceManagerContainer; +import org.onap.policy.models.pap.concepts.PolicyNotification; +import org.onap.policy.models.pdp.concepts.PdpMessage; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.models.pdp.enums.PdpMessageType; import org.onap.policy.pap.main.PapConstants; @@ -41,6 +43,7 @@ import org.onap.policy.pap.main.comm.PdpModifyRequestMap; import org.onap.policy.pap.main.comm.PdpTracker; import org.onap.policy.pap.main.comm.Publisher; import org.onap.policy.pap.main.comm.TimerManager; +import org.onap.policy.pap.main.notification.PolicyNotifier; import org.onap.policy.pap.main.parameters.PapParameterGroup; import org.onap.policy.pap.main.parameters.PdpModifyRequestMapParams; import org.onap.policy.pap.main.parameters.PdpParameters; @@ -112,13 +115,15 @@ public class PapActivator extends ServiceManagerContainer { final Object pdpUpdateLock = new Object(); final PdpParameters pdpParams = papParameterGroup.getPdpParameters(); - final AtomicReference pdpPub = new AtomicReference<>(); + final AtomicReference> pdpPub = new AtomicReference<>(); + final AtomicReference> notifyPub = new AtomicReference<>(); final AtomicReference pdpUpdTimers = new AtomicReference<>(); final AtomicReference pdpStChgTimers = new AtomicReference<>(); final AtomicReference heartBeatTimers = new AtomicReference<>(); final AtomicReference daoFactory = new AtomicReference<>(); final AtomicReference requestMap = new AtomicReference<>(); final AtomicReference restServer = new AtomicReference<>(); + final AtomicReference notifier = new AtomicReference<>(); // @formatter:off addAction("PAP parameters", @@ -156,11 +161,23 @@ public class PapActivator extends ServiceManagerContainer { addAction("PDP publisher", () -> { - pdpPub.set(new Publisher(PapConstants.TOPIC_POLICY_PDP_PAP)); + pdpPub.set(new Publisher<>(PapConstants.TOPIC_POLICY_PDP_PAP)); startThread(pdpPub.get()); }, () -> pdpPub.get().stop()); + addAction("Policy Notification publisher", + () -> { + notifyPub.set(new Publisher<>(PapConstants.TOPIC_POLICY_NOTIFICATION)); + startThread(notifyPub.get()); + notifier.set(new PolicyNotifier(notifyPub.get())); + }, + () -> notifyPub.get().stop()); + + addAction("Policy Notifier", + () -> Registry.register(PapConstants.REG_POLICY_NOTIFIER, notifier.get()), + () -> Registry.unregister(PapConstants.REG_POLICY_NOTIFIER)); + addAction("PDP heart beat timers", () -> { long maxWaitHeartBeatMs = MAX_MISSED_HEARTBEATS * pdpParams.getHeartBeatMs(); @@ -194,7 +211,8 @@ public class PapActivator extends ServiceManagerContainer { .setDaoFactory(daoFactory.get()) .setModifyLock(pdpUpdateLock) .setParams(pdpParams) - .setPublisher(pdpPub.get()) + .setPolicyNotifier(notifier.get()) + .setPdpPublisher(pdpPub.get()) .setResponseDispatcher(reqIdDispatcher) .setStateChangeTimers(pdpStChgTimers.get()) .setUpdateTimers(pdpUpdTimers.get()))); diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/CommonRequestBase.java b/main/src/test/java/org/onap/policy/pap/main/comm/CommonRequestBase.java index 0337161e..f10abdda 100644 --- a/main/src/test/java/org/onap/policy/pap/main/comm/CommonRequestBase.java +++ b/main/src/test/java/org/onap/policy/pap/main/comm/CommonRequestBase.java @@ -49,6 +49,7 @@ import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper; import org.onap.policy.pap.main.comm.msgdata.RequestListener; import org.onap.policy.pap.main.comm.msgdata.StateChangeReq; import org.onap.policy.pap.main.comm.msgdata.UpdateReq; +import org.onap.policy.pap.main.notification.PolicyNotifier; import org.onap.policy.pap.main.parameters.PdpModifyRequestMapParams; import org.onap.policy.pap.main.parameters.PdpParameters; import org.onap.policy.pap.main.parameters.PdpStateChangeParameters; @@ -70,6 +71,7 @@ public class CommonRequestBase { protected static final int RETRIES = 1; protected Publisher publisher; + protected PolicyNotifier notifier; protected RequestIdDispatcher dispatcher; protected Object lock; protected TimerManager timers; @@ -90,6 +92,7 @@ public class CommonRequestBase { @SuppressWarnings("unchecked") public void setUp() throws Exception { publisher = mock(Publisher.class); + notifier = mock(PolicyNotifier.class); dispatcher = mock(RequestIdDispatcher.class); lock = new Object(); timers = mock(TimerManager.class); @@ -121,12 +124,12 @@ public class CommonRequestBase { when(updateParams.getMaxRetryCount()).thenReturn(RETRIES); when(pdpParams.getUpdateParameters()).thenReturn(updateParams); - reqParams = new RequestParams().setMaxRetryCount(RETRIES).setModifyLock(lock).setPublisher(publisher) + reqParams = new RequestParams().setMaxRetryCount(RETRIES).setModifyLock(lock).setPdpPublisher(publisher) .setResponseDispatcher(dispatcher).setTimers(timers); - mapParams = new PdpModifyRequestMapParams().setModifyLock(lock).setPublisher(publisher) - .setResponseDispatcher(dispatcher).setDaoFactory(daoFactory).setUpdateTimers(timers) - .setStateChangeTimers(timers).setParams(pdpParams); + mapParams = new PdpModifyRequestMapParams().setModifyLock(lock).setPdpPublisher(publisher) + .setPolicyNotifier(notifier).setResponseDispatcher(dispatcher).setDaoFactory(daoFactory) + .setUpdateTimers(timers).setStateChangeTimers(timers).setParams(pdpParams); } /** diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/PdpModifyRequestMapTest.java b/main/src/test/java/org/onap/policy/pap/main/comm/PdpModifyRequestMapTest.java index 92f5c5f3..d0bc200f 100644 --- a/main/src/test/java/org/onap/policy/pap/main/comm/PdpModifyRequestMapTest.java +++ b/main/src/test/java/org/onap/policy/pap/main/comm/PdpModifyRequestMapTest.java @@ -305,6 +305,9 @@ public class PdpModifyRequestMapTest extends CommonRequestBase { // should have stopped publishing verify(requests).stopPublishing(); + // should have generated a notification + verify(notifier).removePdp(PDP1); + // should have published a new update PdpMessage msg2 = getSingletons(3).get(1).getMessage(); assertNotNull(msg2); diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/PdpRequestsTest.java b/main/src/test/java/org/onap/policy/pap/main/comm/PdpRequestsTest.java index 1bf73225..ccb13fea 100644 --- a/main/src/test/java/org/onap/policy/pap/main/comm/PdpRequestsTest.java +++ b/main/src/test/java/org/onap/policy/pap/main/comm/PdpRequestsTest.java @@ -50,7 +50,7 @@ public class PdpRequestsTest extends CommonRequestBase { update = makeUpdateReq(PDP1, MY_GROUP, MY_SUBGROUP); change = makeStateChangeReq(PDP1, MY_STATE); - data = new PdpRequests(PDP1); + data = new PdpRequests(PDP1, notifier); } @Test @@ -62,6 +62,7 @@ public class PdpRequestsTest extends CommonRequestBase { public void testAddSingleton() { data.addSingleton(update); + verify(update).setNotifier(notifier); verify(update).startPublishing(any()); } diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/RequestImplTest.java b/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/RequestImplTest.java index 3d90fcbb..e47f8792 100644 --- a/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/RequestImplTest.java +++ b/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/RequestImplTest.java @@ -383,7 +383,7 @@ public class RequestImplTest extends CommonRequestBase { @Test public void testResetRetryCount_testBumpRetryCount() { - req = new MyRequest(new RequestParams().setMaxRetryCount(2).setModifyLock(lock).setPublisher(publisher) + req = new MyRequest(new RequestParams().setMaxRetryCount(2).setModifyLock(lock).setPdpPublisher(publisher) .setResponseDispatcher(dispatcher).setTimers(timers), MY_REQ_NAME, msg); req.setListener(listener); diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateReqTest.java b/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateReqTest.java index a7987701..80ed0fb1 100644 --- a/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateReqTest.java +++ b/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateReqTest.java @@ -25,9 +25,13 @@ import static org.junit.Assert.assertFalse; 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; +import static org.mockito.Mockito.verify; import java.util.ArrayList; import java.util.Arrays; +import java.util.Set; import java.util.stream.Collectors; import org.junit.Before; import org.junit.Test; @@ -45,6 +49,7 @@ public class UpdateReqTest extends CommonRequestBase { /** * Sets up. + * * @throws Exception if an error occurs */ @Before @@ -62,6 +67,7 @@ public class UpdateReqTest extends CommonRequestBase { update.getPolicies().stream().map(ToscaPolicy::getIdentifier).collect(Collectors.toList())); data = new UpdateReq(reqParams, MY_REQ_NAME, update); + data.setNotifier(notifier); } @Test @@ -73,6 +79,7 @@ public class UpdateReqTest extends CommonRequestBase { @Test public void testCheckResponse() { assertNull(data.checkResponse(response)); + verifyResponse(); // both policy lists null update.setPolicies(null); @@ -85,6 +92,7 @@ public class UpdateReqTest extends CommonRequestBase { response.setName(null); assertEquals("null PDP name", data.checkResponse(response)); + verifyNoResponse(); } @Test @@ -92,6 +100,7 @@ public class UpdateReqTest extends CommonRequestBase { update.setName(null); assertEquals(null, data.checkResponse(response)); + verifyResponse(); } @Test @@ -99,6 +108,7 @@ public class UpdateReqTest extends CommonRequestBase { response.setPdpGroup(DIFFERENT); assertEquals("group does not match", data.checkResponse(response)); + verifyResponse(); } @Test @@ -106,6 +116,7 @@ public class UpdateReqTest extends CommonRequestBase { response.setPdpSubgroup(DIFFERENT); assertEquals("subgroup does not match", data.checkResponse(response)); + verifyResponse(); } @Test @@ -116,6 +127,7 @@ public class UpdateReqTest extends CommonRequestBase { response.setPolicies(policies.stream().map(ToscaPolicy::getIdentifier).collect(Collectors.toList())); assertEquals("policies do not match", data.checkResponse(response)); + verifyResponse(); } @Test @@ -123,6 +135,7 @@ public class UpdateReqTest extends CommonRequestBase { update.setPolicies(null); assertEquals("policies do not match", data.checkResponse(response)); + verifyResponse(); } @Test @@ -130,6 +143,7 @@ public class UpdateReqTest extends CommonRequestBase { response.setPolicies(null); assertEquals("policies do not match", data.checkResponse(response)); + verifyResponse(); } @Test @@ -222,6 +236,16 @@ public class UpdateReqTest extends CommonRequestBase { assertTrue(data.getPriority() > new StateChangeReq(reqParams, MY_REQ_NAME, new PdpStateChange()).getPriority()); } + @SuppressWarnings("unchecked") + private void verifyResponse() { + verify(notifier).processResponse(any(), any(Set.class)); + } + + @SuppressWarnings("unchecked") + private void verifyNoResponse() { + verify(notifier, never()).processResponse(any(), any(Set.class)); + } + /** * Makes an update message. * diff --git a/main/src/test/java/org/onap/policy/pap/main/parameters/TestPdpModifyRequestMapParams.java b/main/src/test/java/org/onap/policy/pap/main/parameters/TestPdpModifyRequestMapParams.java index b9dde727..629cf24c 100644 --- a/main/src/test/java/org/onap/policy/pap/main/parameters/TestPdpModifyRequestMapParams.java +++ b/main/src/test/java/org/onap/policy/pap/main/parameters/TestPdpModifyRequestMapParams.java @@ -27,18 +27,23 @@ import static org.mockito.Mockito.mock; import org.junit.Before; import org.junit.Test; import org.onap.policy.common.endpoints.listeners.RequestIdDispatcher; +import org.onap.policy.models.pdp.concepts.PdpMessage; import org.onap.policy.models.pdp.concepts.PdpStatus; +import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper; import org.onap.policy.pap.main.comm.Publisher; import org.onap.policy.pap.main.comm.TimerManager; +import org.onap.policy.pap.main.notification.PolicyNotifier; public class TestPdpModifyRequestMapParams { private PdpModifyRequestMapParams params; - private Publisher pub; + private Publisher pub; private RequestIdDispatcher disp; private Object lock; private PdpParameters pdpParams; private TimerManager updTimers; private TimerManager stateTimers; + private PolicyModelsProviderFactoryWrapper dao; + private PolicyNotifier notifier; /** * Sets up the objects and creates an empty {@link #params}. @@ -52,19 +57,24 @@ public class TestPdpModifyRequestMapParams { pdpParams = mock(PdpParameters.class); updTimers = mock(TimerManager.class); stateTimers = mock(TimerManager.class); + dao = mock(PolicyModelsProviderFactoryWrapper.class); + notifier = mock(PolicyNotifier.class); - params = new PdpModifyRequestMapParams().setModifyLock(lock).setPublisher(pub).setResponseDispatcher(disp) - .setParams(pdpParams).setStateChangeTimers(stateTimers).setUpdateTimers(updTimers); + params = new PdpModifyRequestMapParams().setModifyLock(lock).setPdpPublisher(pub).setResponseDispatcher(disp) + .setParams(pdpParams).setStateChangeTimers(stateTimers).setUpdateTimers(updTimers) + .setDaoFactory(dao).setPolicyNotifier(notifier); } @Test public void testGettersSetters() { - assertSame(pub, params.getPublisher()); + assertSame(pub, params.getPdpPublisher()); assertSame(disp, params.getResponseDispatcher()); assertSame(lock, params.getModifyLock()); assertSame(pdpParams, params.getParams()); assertSame(updTimers, params.getUpdateTimers()); assertSame(stateTimers, params.getStateChangeTimers()); + assertSame(dao, params.getDaoFactory()); + assertSame(notifier, params.getPolicyNotifier()); } @Test @@ -75,7 +85,7 @@ public class TestPdpModifyRequestMapParams { @Test public void testValidate_MissingPublisher() { - assertThatIllegalArgumentException().isThrownBy(() -> params.setPublisher(null).validate()) + assertThatIllegalArgumentException().isThrownBy(() -> params.setPdpPublisher(null).validate()) .withMessageContaining("publisher"); } @@ -108,4 +118,16 @@ public class TestPdpModifyRequestMapParams { assertThatIllegalArgumentException().isThrownBy(() -> params.setUpdateTimers(null).validate()) .withMessageContaining("update"); } + + @Test + public void testValidate_MissingDaoFactory() { + assertThatIllegalArgumentException().isThrownBy(() -> params.setDaoFactory(null).validate()) + .withMessageContaining("DAO"); + } + + @Test + public void testValidate_MissingNotifier() { + assertThatIllegalArgumentException().isThrownBy(() -> params.setPolicyNotifier(null).validate()) + .withMessageContaining("notifier"); + } } diff --git a/main/src/test/java/org/onap/policy/pap/main/parameters/TestRequestParams.java b/main/src/test/java/org/onap/policy/pap/main/parameters/TestRequestParams.java index b4855e74..7c5a3954 100644 --- a/main/src/test/java/org/onap/policy/pap/main/parameters/TestRequestParams.java +++ b/main/src/test/java/org/onap/policy/pap/main/parameters/TestRequestParams.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.mock; import org.junit.Before; import org.junit.Test; import org.onap.policy.common.endpoints.listeners.RequestIdDispatcher; +import org.onap.policy.models.pdp.concepts.PdpMessage; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.pap.main.comm.Publisher; import org.onap.policy.pap.main.comm.TimerManager; @@ -36,7 +37,7 @@ public class TestRequestParams { private static final int RETRIES = 1; private RequestParams params; - private Publisher pub; + private Publisher pub; private RequestIdDispatcher disp; private Object lock; private TimerManager timers; @@ -52,15 +53,15 @@ public class TestRequestParams { lock = new Object(); timers = mock(TimerManager.class); - params = new RequestParams().setModifyLock(lock).setPublisher(pub).setResponseDispatcher(disp).setTimers(timers) - .setMaxRetryCount(RETRIES); + params = new RequestParams().setModifyLock(lock).setPdpPublisher(pub).setResponseDispatcher(disp) + .setTimers(timers).setMaxRetryCount(RETRIES); } @Test public void testGettersSetters() { - assertSame(params, params.setModifyLock(lock).setPublisher(pub).setResponseDispatcher(disp)); + assertSame(params, params.setModifyLock(lock).setPdpPublisher(pub).setResponseDispatcher(disp)); - assertSame(pub, params.getPublisher()); + assertSame(pub, params.getPdpPublisher()); assertSame(disp, params.getResponseDispatcher()); assertSame(lock, params.getModifyLock()); assertSame(timers, params.getTimers()); @@ -87,7 +88,7 @@ public class TestRequestParams { @Test public void testValidate_MissingPublisher() { - assertThatIllegalArgumentException().isThrownBy(() -> params.setPublisher(null).validate()) + assertThatIllegalArgumentException().isThrownBy(() -> params.setPdpPublisher(null).validate()) .withMessageContaining("publisher"); } 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 2fca6848..3f29fb56 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 @@ -52,6 +52,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; import org.onap.policy.pap.main.PapConstants; import org.onap.policy.pap.main.PolicyModelsProviderFactoryWrapper; import org.onap.policy.pap.main.comm.PdpModifyRequestMap; +import org.onap.policy.pap.main.notification.PolicyNotifier; /** * Super class for TestPdpGroupDeployProviderXxx classes. @@ -62,6 +63,9 @@ public class ProviderSuper { @Mock protected PolicyModelsProvider dao; + @Mock + protected PolicyNotifier notifier; + /** * Used to capture input to dao.updatePdpGroups() and dao.createPdpGroups(). @@ -103,6 +107,7 @@ public class ProviderSuper { Registry.register(PapConstants.REG_PDP_MODIFY_LOCK, lockit); Registry.register(PapConstants.REG_PDP_MODIFY_MAP, reqmap); Registry.register(PapConstants.REG_PAP_DAO_FACTORY, daofact); + Registry.register(PapConstants.REG_POLICY_NOTIFIER, notifier); } protected void assertGroup(List groups, String name) { 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 a577e07b..cac16808 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 @@ -26,8 +26,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; 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; @@ -35,11 +35,14 @@ import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.List; -import java.util.function.BiFunction; +import java.util.Set; import javax.ws.rs.core.Response.Status; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; import org.onap.policy.common.utils.services.Registry; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.pdp.concepts.PdpGroup; @@ -48,17 +51,23 @@ import org.onap.policy.models.pdp.concepts.PdpUpdate; import org.onap.policy.models.pdp.enums.PdpState; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifierOptVersion; +import org.onap.policy.pap.main.rest.depundep.ProviderBase.Updater; public class TestPdpGroupDeleteProvider extends ProviderSuper { private static final String EXPECTED_EXCEPTION = "expected exception"; private static final String GROUP1_NAME = "groupA"; - private MyProvider prov; + @Mock private SessionData session; + + @Captor + private ArgumentCaptor> pdpCaptor; + + private MyProvider prov; private ToscaPolicyIdentifierOptVersion optIdent; private ToscaPolicyIdentifierOptVersion fullIdent; private ToscaPolicyIdentifier ident; - private BiFunction updater; + private Updater updater; @AfterClass @@ -76,14 +85,13 @@ public class TestPdpGroupDeleteProvider extends ProviderSuper { super.setUp(); - session = mock(SessionData.class); ident = policy1.getIdentifier(); optIdent = new ToscaPolicyIdentifierOptVersion(ident.getName(), null); fullIdent = new ToscaPolicyIdentifierOptVersion(ident.getName(), ident.getVersion()); prov = new MyProvider(); - updater = prov.makeUpdater(policy1, fullIdent); + updater = prov.makeUpdater(session, policy1, fullIdent); } @Test @@ -215,7 +223,7 @@ public class TestPdpGroupDeleteProvider extends ProviderSuper { } @Test - public void testMakeUpdater_WithVersion() { + public void testMakeUpdater_WithVersion() throws PfModelException { /* * this group has two matching policies and one policy with a different name. */ @@ -230,10 +238,13 @@ public class TestPdpGroupDeleteProvider extends ProviderSuper { // identified policy should have been removed assertEquals(origSize - 1, subgroup.getPolicies().size()); assertFalse(subgroup.getPolicies().contains(ident)); + + verify(session).trackUndeploy(eq(ident), pdpCaptor.capture()); + assertEquals("[pdpA]", pdpCaptor.getValue().toString()); } @Test - public void testMakeUpdater_NullVersion() { + public void testMakeUpdater_NullVersion() throws PfModelException { /* * this group has two matching policies and one policy with a different name. */ @@ -243,7 +254,7 @@ public class TestPdpGroupDeleteProvider extends ProviderSuper { int origSize = subgroup.getPolicies().size(); // invoke updater - matching the name, but with a null (i.e., wild-card) version - updater = prov.makeUpdater(policy1, optIdent); + updater = prov.makeUpdater(session, policy1, optIdent); assertTrue(updater.apply(group, subgroup)); // identified policy should have been removed @@ -252,7 +263,7 @@ public class TestPdpGroupDeleteProvider extends ProviderSuper { } @Test - public void testMakeUpdater_NotFound() { + public void testMakeUpdater_NotFound() throws PfModelException { /* * this group has one policy with a different name and one with a different * version, but not the policy of interest. 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 90ea1658..c2d368ad 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 @@ -35,11 +35,13 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.TreeMap; +import java.util.TreeSet; import java.util.stream.Collectors; import javax.ws.rs.core.Response.Status; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.onap.policy.common.utils.services.Registry; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; @@ -53,6 +55,7 @@ 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; +import org.onap.policy.pap.main.notification.PolicyPdpNotificationData; public class TestPdpGroupDeployProvider extends ProviderSuper { private static final String EXPECTED_EXCEPTION = "expected exception"; @@ -279,6 +282,14 @@ public class TestPdpGroupDeployProvider extends ProviderSuper { assertEquals(newgrp.toString(), dbgroup.toString()); + // no deployment notifications + verify(notifier, never()).addDeploymentData(any()); + + // should have notified of deleted subgroup's policies/PDPs + ArgumentCaptor captor = ArgumentCaptor.forClass(PolicyPdpNotificationData.class); + verify(notifier).addUndeploymentData(captor.capture()); + assertDeploymentData(captor, policy1.getIdentifier(), "[pdpB, pdpD]"); + // this requires a PDP UPDATE message List pdpUpdates = getUpdateRequests(2); assertEquals(2, pdpUpdates.size()); @@ -540,16 +551,23 @@ public class TestPdpGroupDeployProvider extends ProviderSuper { @Test public void testUpdateSubGroup_Policies() throws Exception { - PdpGroups groups = loadPdpGroups("createGroups.json"); + PdpGroups groups = loadPdpGroups("createGroupsDelPolicy.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)); + + // delete second policy + subgrp.setPolicies(subgrp.getPolicies().subList(0, 1)); + + // add new policy + ToscaPolicyIdentifier policyId2 = new ToscaPolicyIdentifier(POLICY2_NAME, POLICY1_VERSION); + subgrp.getPolicies().add(policyId2); when(dao.getFilteredPolicyList(any())).thenReturn(loadPolicies("createGroupNewPolicy.json")) .thenReturn(loadPolicies("daoPolicyList.json")) + .thenReturn(loadPolicies("daoPolicyListDelPolicy.json")) .thenReturn(loadPolicies("createGroupNewPolicy.json")); prov.createOrUpdateGroups(groups); @@ -559,10 +577,42 @@ public class TestPdpGroupDeployProvider extends ProviderSuper { assertEquals(newgrp.toString(), group.toString()); + // should have notified of added policy/PDPs + ArgumentCaptor captor = ArgumentCaptor.forClass(PolicyPdpNotificationData.class); + verify(notifier).addDeploymentData(captor.capture()); + assertDeploymentData(captor, policyId2, "[pdpA]"); + + // should have notified of deleted policy/PDPs + captor = ArgumentCaptor.forClass(PolicyPdpNotificationData.class); + verify(notifier).addUndeploymentData(captor.capture()); + assertDeploymentData(captor, new ToscaPolicyIdentifier("ToBeDeleted", POLICY1_VERSION), "[pdpA]"); + // this requires a PDP UPDATE message assertGroupUpdate(group, subgrp); } + @Test + public void testUpdateSubGroup_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)); + + prov.createOrUpdateGroups(groups); + + Collections.sort(newgrp.getPdpSubgroups().get(0).getPolicies()); + Collections.sort(group.getPdpSubgroups().get(0).getPolicies()); + + assertEquals(newgrp.toString(), group.toString()); + + // no notifications + verify(notifier, never()).addDeploymentData(any()); + verify(notifier, never()).addUndeploymentData(any()); + + // no group updates + assertNoGroupAction(); + } + @Test public void testUpdateSubGroup_PolicyVersionMismatch() throws Exception { PdpGroups groups = loadPdpGroups("createGroups.json"); @@ -662,6 +712,14 @@ public class TestPdpGroupDeployProvider extends ProviderSuper { List requests = getUpdateRequests(2); assertUpdate(requests, GROUP1_NAME, PDP2_TYPE, PDP2); assertUpdate(requests, GROUP1_NAME, PDP4_TYPE, PDP4); + + // should have notified of added policy/PDPs + ArgumentCaptor captor = ArgumentCaptor.forClass(PolicyPdpNotificationData.class); + verify(notifier).addDeploymentData(captor.capture()); + assertDeploymentData(captor, policy1.getIdentifier(), "[pdpB, pdpD]"); + + // no undeployment notifications + verify(notifier, never()).addUndeploymentData(any()); } @Test @@ -741,6 +799,14 @@ public class TestPdpGroupDeployProvider extends ProviderSuper { assertEquals(Arrays.asList(group), updates); } + private void assertDeploymentData(ArgumentCaptor captor, ToscaPolicyIdentifier policyId, + String expectedPdps) { + PolicyPdpNotificationData data = captor.getValue(); + assertEquals(policyId, data.getPolicyId()); + assertEquals(policy1.getTypeIdentifier(), data.getPolicyType()); + assertEquals(expectedPdps, new TreeSet<>(data.getPdps()).toString()); + } + /** * Loads a standard request. * diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestProviderBase.java b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestProviderBase.java index 3a91363f..9370a7bd 100644 --- a/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestProviderBase.java +++ b/main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestProviderBase.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -34,20 +35,22 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Queue; -import java.util.function.BiFunction; +import java.util.TreeSet; import javax.ws.rs.core.Response.Status; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.onap.policy.common.utils.services.Registry; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.pap.concepts.PdpDeployPolicies; import org.onap.policy.models.pdp.concepts.PdpGroup; -import org.onap.policy.models.pdp.concepts.PdpSubGroup; 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.ToscaPolicyIdentifierOptVersion; +import org.onap.policy.pap.main.notification.PolicyPdpNotificationData; import org.powermock.reflect.Whitebox; public class TestProviderBase extends ProviderSuper { @@ -103,6 +106,24 @@ public class TestProviderBase extends ProviderSuper { assertGroup(getGroupUpdates(), GROUP1_NAME); assertUpdate(getUpdateRequests(1), GROUP1_NAME, PDP1_TYPE, PDP1); + + ArgumentCaptor captor = ArgumentCaptor.forClass(PolicyPdpNotificationData.class); + verify(notifier, times(2)).addDeploymentData(captor.capture()); + assertNotifier(captor, PDP1, PDP3); + + captor = ArgumentCaptor.forClass(PolicyPdpNotificationData.class); + verify(notifier, times(2)).addUndeploymentData(captor.capture()); + assertNotifier(captor, PDP2, PDP4); + } + + private void assertNotifier(ArgumentCaptor captor, String firstPdp, String secondPdp) { + assertEquals(1, captor.getAllValues().get(0).getPdps().size()); + assertEquals(1, captor.getAllValues().get(1).getPdps().size()); + + // ensure the order by using a TreeSet + TreeSet pdps = new TreeSet<>(captor.getAllValues().get(0).getPdps()); + pdps.addAll(captor.getAllValues().get(1).getPdps()); + assertEquals("[" + firstPdp + ", " + secondPdp + "]", pdps.toString()); } @Test @@ -345,13 +366,20 @@ public class TestProviderBase extends ProviderSuper { } @Override - protected BiFunction makeUpdater(ToscaPolicy policy, + protected Updater makeUpdater(SessionData data, ToscaPolicy policy, ToscaPolicyIdentifierOptVersion desiredPolicy) { return (group, subgroup) -> { if (shouldUpdate.remove()) { // queue indicated that the update should succeed subgroup.getPolicies().add(policy.getIdentifier()); + + data.trackDeploy(policy.getIdentifier(), Collections.singleton(PDP1)); + data.trackUndeploy(policy.getIdentifier(), Collections.singleton(PDP2)); + + ToscaPolicyIdentifier ident2 = new ToscaPolicyIdentifier(POLICY1_NAME, "9.9.9"); + data.trackDeploy(ident2, Collections.singleton(PDP3)); + data.trackUndeploy(ident2, Collections.singleton(PDP4)); return true; } else { 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 d7d9b677..4d353a6e 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 @@ -41,6 +41,8 @@ import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.TreeSet; +import java.util.function.Supplier; import javax.ws.rs.core.Response.Status; import org.apache.commons.lang3.tuple.Pair; import org.junit.Before; @@ -52,9 +54,11 @@ 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.ToscaPolicyFilter; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifierOptVersion; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier; +import org.onap.policy.pap.main.notification.PolicyPdpNotificationData; public class TestSessionData extends ProviderSuper { private static final String GROUP_NAME = "groupA"; @@ -533,6 +537,70 @@ public class TestSessionData extends ProviderSuper { verify(dao).deletePdpGroup(group1.getName()); } + @Test + public void testTrackDeploy() throws PfModelException { + testTrack(session::getDeployData, session::getUndeployData, session::trackDeploy); + } + + /** + * Tests trackDeploy() when there is something in the undeployed list. + * + * @throws PfModelException if an error occurs + */ + @Test + public void testTrackDeployRemoveUndeploy() throws PfModelException { + testTrack(session::getDeployData, session::getUndeployData, session::trackUndeploy, session::trackDeploy); + } + + @Test + public void testTrackUndeploy() throws PfModelException { + testTrack(session::getUndeployData, session::getDeployData, session::trackUndeploy); + } + + /** + * Tests trackUndeploy() when there is something in the deployed list. + * + * @throws PfModelException if an error occurs + */ + @Test + public void testTrackUndeployRemoveUndeploy() throws PfModelException { + testTrack(session::getUndeployData, session::getDeployData, session::trackDeploy, session::trackUndeploy); + } + + protected void testTrack(Supplier> expected, + Supplier> unexpected, TrackEx... trackFuncs) + throws PfModelException { + + ToscaPolicy policy = makePolicy(POLICY_NAME, POLICY_VERSION); + policy.setType(POLICY_TYPE); + policy.setTypeVersion(POLICY_TYPE_VERSION); + + when(dao.getFilteredPolicyList(any())).thenReturn(Arrays.asList(policy)); + + ToscaPolicyIdentifier policyId = new ToscaPolicyIdentifier(POLICY_NAME, POLICY_VERSION); + List pdps = Arrays.asList(PDP1, PDP2); + + for (TrackEx trackFunc : trackFuncs) { + trackFunc.accept(policyId, pdps); + } + + // "unexpected" list should be empty of any PDPs + Collection dataList = unexpected.get(); + assertTrue(dataList.size() <= 1); + if (!dataList.isEmpty()) { + PolicyPdpNotificationData data = dataList.iterator().next(); + assertTrue(data.getPdps().isEmpty()); + } + + dataList = expected.get(); + assertEquals(1, dataList.size()); + + PolicyPdpNotificationData data = dataList.iterator().next(); + assertEquals(policyId, data.getPolicyId()); + assertEquals(type, data.getPolicyType()); + assertEquals("[pdp_1, pdp_2]", new TreeSet<>(data.getPdps()).toString()); + } + private PdpUpdate makeUpdate(String pdpName) { PdpUpdate update = new PdpUpdate(); @@ -586,4 +654,9 @@ public class TestSessionData extends ProviderSuper { private String getName(Pair pair) { return (pair.getKey() != null ? pair.getKey().getName() : pair.getValue().getName()); } + + @FunctionalInterface + private static interface TrackEx { + public void accept(ToscaPolicyIdentifier policyId, Collection pdps) throws PfModelException; + } } diff --git a/main/src/test/java/org/onap/policy/pap/main/startstop/TestPapActivator.java b/main/src/test/java/org/onap/policy/pap/main/startstop/TestPapActivator.java index 13c06098..19668b31 100644 --- a/main/src/test/java/org/onap/policy/pap/main/startstop/TestPapActivator.java +++ b/main/src/test/java/org/onap/policy/pap/main/startstop/TestPapActivator.java @@ -36,6 +36,8 @@ import org.onap.policy.common.utils.services.Registry; import org.onap.policy.pap.main.PapConstants; import org.onap.policy.pap.main.PolicyPapException; import org.onap.policy.pap.main.comm.PdpModifyRequestMap; +import org.onap.policy.pap.main.comm.PdpTracker; +import org.onap.policy.pap.main.notification.PolicyNotifier; import org.onap.policy.pap.main.parameters.CommonTestData; import org.onap.policy.pap.main.parameters.PapParameterGroup; import org.onap.policy.pap.main.parameters.PapParameterHandler; @@ -92,6 +94,8 @@ public class TestPapActivator { assertNotNull(Registry.get(PapConstants.REG_PDP_MODIFY_LOCK, Object.class)); assertNotNull(Registry.get(PapConstants.REG_STATISTICS_MANAGER, PapStatisticsManager.class)); assertNotNull(Registry.get(PapConstants.REG_PDP_MODIFY_MAP, PdpModifyRequestMap.class)); + assertNotNull(Registry.get(PapConstants.REG_PDP_TRACKER, PdpTracker.class)); + assertNotNull(Registry.get(PapConstants.REG_POLICY_NOTIFIER, PolicyNotifier.class)); // repeat - should throw an exception assertThatIllegalStateException().isThrownBy(() -> activator.start()); @@ -109,6 +113,8 @@ public class TestPapActivator { assertNull(Registry.getOrDefault(PapConstants.REG_PDP_MODIFY_LOCK, Object.class, null)); assertNull(Registry.getOrDefault(PapConstants.REG_STATISTICS_MANAGER, PapStatisticsManager.class, null)); assertNull(Registry.getOrDefault(PapConstants.REG_PDP_MODIFY_MAP, PdpModifyRequestMap.class, null)); + assertNull(Registry.getOrDefault(PapConstants.REG_PDP_TRACKER, PdpTracker.class, null)); + assertNull(Registry.getOrDefault(PapConstants.REG_POLICY_NOTIFIER, PolicyNotifier.class, null)); // repeat - should throw an exception assertThatIllegalStateException().isThrownBy(() -> activator.stop()); diff --git a/main/src/test/resources/e2e/PapConfigParameters.json b/main/src/test/resources/e2e/PapConfigParameters.json index 0c86e8fe..17507bdb 100644 --- a/main/src/test/resources/e2e/PapConfigParameters.json +++ b/main/src/test/resources/e2e/PapConfigParameters.json @@ -37,6 +37,10 @@ "topic" : "POLICY-PDP-PAP", "servers" : [ "message-router" ], "topicCommInfrastructure" : "noop" + },{ + "topic" : "POLICY-NOTIFICATION", + "servers" : [ "message-router" ], + "topicCommInfrastructure" : "noop" }] } } diff --git a/main/src/test/resources/parameters/PapConfigParameters.json b/main/src/test/resources/parameters/PapConfigParameters.json index f3dc775c..11315029 100644 --- a/main/src/test/resources/parameters/PapConfigParameters.json +++ b/main/src/test/resources/parameters/PapConfigParameters.json @@ -37,6 +37,10 @@ "topic" : "POLICY-PDP-PAP", "servers" : [ "message-router" ], "topicCommInfrastructure" : "noop" + },{ + "topic" : "POLICY-NOTIFICATION", + "servers" : [ "message-router" ], + "topicCommInfrastructure" : "noop" }] } } diff --git a/main/src/test/resources/parameters/PapConfigParametersStd.json b/main/src/test/resources/parameters/PapConfigParametersStd.json index 309bdb0d..828c1a44 100644 --- a/main/src/test/resources/parameters/PapConfigParametersStd.json +++ b/main/src/test/resources/parameters/PapConfigParametersStd.json @@ -37,6 +37,10 @@ "topic" : "POLICY-PDP-PAP", "servers" : [ "message-router" ], "topicCommInfrastructure" : "noop" + },{ + "topic" : "POLICY-NOTIFICATION", + "servers" : [ "message-router" ], + "topicCommInfrastructure" : "noop" }] } } diff --git a/main/src/test/resources/simpleDeploy/createGroupsDelPolicy.json b/main/src/test/resources/simpleDeploy/createGroupsDelPolicy.json new file mode 100644 index 00000000..8972997a --- /dev/null +++ b/main/src/test/resources/simpleDeploy/createGroupsDelPolicy.json @@ -0,0 +1,43 @@ +{ + "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" + }, + { + "name": "ToBeDeleted", + "version": "1.2.3" + } + ] + } + ] + } + ] +} diff --git a/main/src/test/resources/simpleDeploy/daoPolicyListDelPolicy.json b/main/src/test/resources/simpleDeploy/daoPolicyListDelPolicy.json new file mode 100644 index 00000000..155912c7 --- /dev/null +++ b/main/src/test/resources/simpleDeploy/daoPolicyListDelPolicy.json @@ -0,0 +1,10 @@ +{ + "policies": [ + { + "name": "ToBeDeleted", + "version": "1.2.3", + "type": "typeA", + "type_version": "100.2.3" + } + ] +} -- cgit 1.2.3-korg