From 23b2730941fff26082de9e8a308e1a29758c96a5 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Tue, 4 Jun 2019 17:27:31 -0400 Subject: Undeploy policies when subgroup is deleted When a subgroup is deleted via the PDP Group create/update API, any PDPs in the subgroup should have all of its policies undeployed. In the process, refactored addOrUpdateSubGroups() out of updateGroup(). Change-Id: I0750802bfb133a655e38493a868744b512ca3fb4 Issue-ID: POLICY-1803 Signed-off-by: Jim Hahn --- .../main/rest/depundep/PdpGroupDeployProvider.java | 112 +++++++++++++++++---- .../rest/depundep/TestPdpGroupDeployProvider.java | 48 +++++++++ .../resources/simpleDeploy/createGroupsDelSub.json | 64 ++++++++++++ 3 files changed, 205 insertions(+), 19 deletions(-) create mode 100644 main/src/test/resources/simpleDeploy/createGroupsDelSub.json 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 1fd99be9..01b41613 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 @@ -39,9 +39,12 @@ 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.Pdp; 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.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; @@ -186,11 +189,57 @@ public class PdpGroupDeployProvider extends ProviderBase { "cannot change properties")); } + boolean updated = updateField(dbgroup.getDescription(), group.getDescription(), dbgroup::setDescription); + updated = notifyPdpsDelSubGroups(data, dbgroup, group) || updated; + updated = addOrUpdateSubGroups(data, dbgroup, group, result) || updated; + + 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 boolean updateField(T oldValue, T newValue, Consumer setter) { + if (oldValue == newValue) { + return false; + } + + if (oldValue != null && oldValue.equals(newValue)) { + return false; + } + + setter.accept(newValue); + return true; + } + + /** + * Adds or updates subgroups within the group. + * + * @param data session data + * @param dbgroup the group, as it appears within the DB + * @param group the group to be added + * @param result the validation result + * @return {@code true} if the DB group was modified, {@code false} otherwise + * @throws PfModelException if an error occurred + */ + private boolean addOrUpdateSubGroups(SessionData data, PdpGroup dbgroup, PdpGroup group, + BeanValidationResult result) throws PfModelException { + // create a map of existing subgroups Map type2sub = new HashMap<>(); dbgroup.getPdpSubgroups().forEach(subgrp -> type2sub.put(subgrp.getPdpType(), subgrp)); - boolean updated = updateField(dbgroup.getDescription(), group.getDescription(), dbgroup::setDescription); + boolean updated = false; for (PdpSubGroup subgrp : group.getPdpSubgroups()) { PdpSubGroup dbsub = type2sub.get(subgrp.getPdpType()); @@ -208,33 +257,58 @@ public class PdpGroupDeployProvider extends ProviderBase { result.addResult(subResult); } - if (result.isValid() && updated) { - data.update(group); + return updated; + } + + /** + * Notifies any PDPs whose subgroups are being removed. + * + * @param data session data + * @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 + */ + private boolean notifyPdpsDelSubGroups(SessionData data, PdpGroup dbgroup, PdpGroup group) { + boolean updated = false; + + // subgroups, as they appear within the updated group + Set subgroups = new HashSet<>(); + group.getPdpSubgroups().forEach(subgrp -> subgroups.add(subgrp.getPdpType())); + + // loop through subgroups as they appear within the DB + for (PdpSubGroup subgrp : dbgroup.getPdpSubgroups()) { + + if (!subgroups.contains(subgrp.getPdpType())) { + // this subgroup no longer appears - notify its PDPs + updated = true; + notifyPdpsDelSubGroup(data, subgrp); + } } - return result; + return updated; } /** - * Updates a field, if the new value is different than the old value. + * Notifies the PDPs that their subgroup is being removed. * - * @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 + * @param data session data + * @param subgrp subgroup that is being removed */ - private boolean updateField(T oldValue, T newValue, Consumer setter) { - if (oldValue == newValue) { - return false; - } + private void notifyPdpsDelSubGroup(SessionData data, PdpSubGroup subgrp) { + for (Pdp pdp : subgrp.getPdpInstances()) { + String name = pdp.getInstanceId(); - if (oldValue != null && oldValue.equals(newValue)) { - return false; - } + // make it passive + PdpStateChange change = new PdpStateChange(); + change.setName(name); + change.setState(PdpState.PASSIVE); - setter.accept(newValue); - return true; + // remove it from subgroup and undeploy all policies + PdpUpdate update = new PdpUpdate(); + update.setName(name); + + data.addRequests(update, change); + } } /** 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 81664176..6d193fef 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.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.junit.Assert.assertTrue; import static org.mockito.Matchers.any; @@ -45,6 +46,7 @@ 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.PdpGroups; +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.pdp.enums.PdpState; @@ -256,6 +258,52 @@ public class TestPdpGroupDeployProvider extends ProviderSuper { assertGroupUpdateOnly(group); } + @Test + public void testUpdateGroup_notifyPdpsDelSubGroups() throws Exception { + PdpGroup dbgroup = new PdpGroup(loadPdpGroups("createGroupsDelSub.json").getGroups().get(0)); + when(dao.getPdpGroups(dbgroup.getName())).thenReturn(Arrays.asList(dbgroup)); + + PdpGroups groups = loadPdpGroups("createGroups.json"); + + prov.createOrUpdateGroups(groups); + + // verify that DB group was updated + List updates = getGroupUpdates(); + assertEquals(1, updates.size()); + dbgroup = updates.get(0); + + PdpGroup newgrp = groups.getGroups().get(0); + + Collections.sort(newgrp.getPdpSubgroups().get(0).getPolicies()); + Collections.sort(dbgroup.getPdpSubgroups().get(0).getPolicies()); + + assertEquals(newgrp.toString(), dbgroup.toString()); + + // this requires a PDP UPDATE message + List pdpUpdates = getUpdateRequests(2); + assertEquals(2, pdpUpdates.size()); + + PdpUpdate pdpUpdate = pdpUpdates.get(0); + assertEquals(PDP2, pdpUpdate.getName()); + assertNull(pdpUpdate.getPdpGroup()); + + pdpUpdate = pdpUpdates.get(1); + assertEquals(PDP4, pdpUpdate.getName()); + assertNull(pdpUpdate.getPdpGroup()); + + // it also requires a PDP STATE-CHANGE message + List changes = getStateChangeRequests(2); + assertEquals(2, changes.size()); + + PdpStateChange change = changes.get(0); + assertEquals(PDP2, change.getName()); + assertEquals(PdpState.PASSIVE, change.getState()); + + change = changes.get(1); + assertEquals(PDP4, change.getName()); + assertEquals(PdpState.PASSIVE, change.getState()); + } + @Test public void testUpdateGroup_MultipleChanges() throws Exception { PdpGroups groups = loadPdpGroups("createGroups.json"); diff --git a/main/src/test/resources/simpleDeploy/createGroupsDelSub.json b/main/src/test/resources/simpleDeploy/createGroupsDelSub.json new file mode 100644 index 00000000..cba308ec --- /dev/null +++ b/main/src/test/resources/simpleDeploy/createGroupsDelSub.json @@ -0,0 +1,64 @@ +{ + "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" + }, + { + "instanceId": "pdpD" + } + ], + "policies": [ + { + "name": "policyA", + "version": "1.2.3" + } + ] + } + ] + } + ] +} -- cgit 1.2.3-korg