Undeploy policies when subgroup is deleted 92/89292/3
authorJim Hahn <jrh3@att.com>
Tue, 4 Jun 2019 21:27:31 +0000 (17:27 -0400)
committerJim Hahn <jrh3@att.com>
Tue, 4 Jun 2019 22:06:49 +0000 (18:06 -0400)
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 <jrh3@att.com>
main/src/main/java/org/onap/policy/pap/main/rest/depundep/PdpGroupDeployProvider.java
main/src/test/java/org/onap/policy/pap/main/rest/depundep/TestPdpGroupDeployProvider.java
main/src/test/resources/simpleDeploy/createGroupsDelSub.json [new file with mode: 0644]

index 1fd99be..01b4161 100644 (file)
@@ -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 <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 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<String, PdpSubGroup> 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<String> 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 <T> boolean updateField(T oldValue, T newValue, Consumer<T> 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);
+        }
     }
 
     /**
index 8166417..6d193fe 100644 (file)
@@ -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<PdpGroup> 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<PdpUpdate> 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<PdpStateChange> 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 (file)
index 0000000..cba308e
--- /dev/null
@@ -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"
+                        }
+                    ]
+                }
+            ]
+        }
+    ]
+}