Support delta policy lists in xacml-pdp 22/121522/3
authorJim Hahn <jrh3@att.com>
Mon, 24 May 2021 17:13:07 +0000 (13:13 -0400)
committerJim Hahn <jrh3@att.com>
Tue, 25 May 2021 13:45:44 +0000 (09:45 -0400)
Updated xacml-pdp to use the deploy & undeploy lists in the PDP-UPDATE
message.
Added more code coverage to the junit test class.
Per review:
- added logging for unexpected cases

Issue-ID: POLICY-3188
Change-Id: I0f899abcd497f7eb711d4df358e455fd2d50e904
Signed-off-by: Jim Hahn <jrh3@att.com>
main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java
main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisherTest.java

index 7806fea..39af6fd 100644 (file)
 
 package org.onap.policy.pdpx.main.comm;
 
-import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
 import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient;
 import org.onap.policy.models.pdp.concepts.PdpStatus;
 import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
 import org.onap.policy.pdp.xacml.application.common.XacmlPolicyUtils;
@@ -63,15 +66,22 @@ public class XacmlPdpUpdatePublisher {
      */
     public void handlePdpUpdate(PdpUpdate message) {
 
-        Set<ToscaPolicy> incomingPolicies =
-                new HashSet<>(message.getPolicies() == null ? Collections.emptyList() : message.getPolicies());
-        Set<ToscaPolicy> deployedPolicies =
-                new HashSet<>(appManager.getToscaPolicies().keySet());
+        // current data
+        Map<ToscaConceptIdentifier, ToscaPolicy> deployedPolicies = policyToMap(appManager.getToscaPolicies().keySet());
 
-        // Undeploy a policy
-        // if incoming policies do not contain the deployed policy then remove it from PDP
-        for (ToscaPolicy policy : deployedPolicies) {
-            if (!incomingPolicies.contains(policy)) {
+        // incoming data
+        Map<ToscaConceptIdentifier, ToscaPolicy> toBeDeployedPolicies = policyToMap(message.getPoliciesToBeDeployed());
+        List<ToscaConceptIdentifier> toBeUndeployedIds =
+                        Optional.ofNullable(message.getPoliciesToBeUndeployed()).orElse(Collections.emptyList());
+
+        // Undeploy policies
+        for (ToscaConceptIdentifier policyId: toBeUndeployedIds) {
+            ToscaPolicy policy = deployedPolicies.get(policyId);
+            if (policy == null) {
+                LOGGER.warn("attempt to undeploy policy that has not been previously deployed: {}", policyId);
+            } else if (toBeDeployedPolicies.containsKey(policyId)) {
+                LOGGER.warn("not undeploying policy, as it also appears in the deployment list: {}", policyId);
+            } else {
                 appManager.removeUndeployedPolicy(policy);
             }
         }
@@ -79,8 +89,8 @@ public class XacmlPdpUpdatePublisher {
         var errorMessage = new StringBuilder();
         // Deploy a policy
         // if deployed policies do not contain the incoming policy load it
-        for (ToscaPolicy policy : incomingPolicies) {
-            if (!deployedPolicies.contains(policy)) {
+        for (ToscaPolicy policy : toBeDeployedPolicies.values()) {
+            if (!deployedPolicies.containsKey(policy.getIdentifier())) {
                 try {
                     appManager.loadDeployedPolicy(policy);
                 } catch (XacmlApplicationException e) {
@@ -91,9 +101,6 @@ public class XacmlPdpUpdatePublisher {
                 }
             }
         }
-        // Return current deployed policies
-        message.setPolicies(new ArrayList<>(appManager.getToscaPolicies().keySet()));
-        LOGGER.debug("Returning current deployed policies: {} ", message.getPolicies());
 
         // update the policy count statistic
         var stats = XacmlPdpStatisticsManager.getCurrent();
@@ -101,7 +108,18 @@ public class XacmlPdpUpdatePublisher {
             stats.setTotalPolicyCount(appManager.getPolicyCount());
         }
 
-        sendPdpUpdate(state.updateInternalState(message, errorMessage.toString()));
+        PdpStatus status = state.updateInternalState(message, errorMessage.toString());
+        LOGGER.debug("Returning current deployed policies: {} ", status.getPolicies());
+
+        sendPdpUpdate(status);
+    }
+
+    private Map<ToscaConceptIdentifier, ToscaPolicy> policyToMap(Collection<ToscaPolicy> policies) {
+        if (policies == null) {
+            return Collections.emptyMap();
+        }
+
+        return policies.stream().collect(Collectors.toMap(ToscaPolicy::getIdentifier, policy -> policy));
     }
 
     private void sendPdpUpdate(PdpStatus status) {
@@ -110,5 +128,4 @@ public class XacmlPdpUpdatePublisher {
             LOGGER.error("failed to send to topic sink {}", client.getTopic());
         }
     }
-
 }
index a4cee50..1edaab3 100644 (file)
@@ -28,7 +28,6 @@ import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -40,6 +39,7 @@ import org.mockito.junit.MockitoJUnitRunner;
 import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient;
 import org.onap.policy.models.pdp.concepts.PdpStatus;
 import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
@@ -54,7 +54,7 @@ import org.onap.policy.pdpx.main.rest.XacmlPdpStatisticsManager;
 @RunWith(MockitoJUnitRunner.class)
 public class XacmlPdpUpdatePublisherTest {
 
-    private static final int NEW_COUNT = 4;
+    private static final int NEW_COUNT = 5;
 
     @Mock
     private TopicSinkClient client;
@@ -80,6 +80,9 @@ public class XacmlPdpUpdatePublisherTest {
     @Mock
     private ToscaPolicy deployed4;
 
+    @Mock
+    private ToscaPolicy deployed5;
+
     @Mock
     private ToscaPolicy added1;
 
@@ -106,19 +109,39 @@ public class XacmlPdpUpdatePublisherTest {
      */
     @Before
     public void setUp() {
+        ToscaConceptIdentifier deployedId1 = new ToscaConceptIdentifier("deployed-1", "1.0.0");
+        ToscaConceptIdentifier deployedId2 = new ToscaConceptIdentifier("deployed-2", "1.0.0");
+        ToscaConceptIdentifier deployedId4 = new ToscaConceptIdentifier("deployed-4", "1.0.0");
+        ToscaConceptIdentifier deployedId5 = new ToscaConceptIdentifier("deployed-5", "1.0.0");
+        ToscaConceptIdentifier addedId1 = new ToscaConceptIdentifier("added-1", "1.0.0");
+        ToscaConceptIdentifier addedId2 = new ToscaConceptIdentifier("added-2", "1.0.0");
+
+        when(deployed1.getIdentifier()).thenReturn(deployedId1);
+        when(deployed2.getIdentifier()).thenReturn(deployedId2);
+        when(deployed3.getIdentifier()).thenReturn(new ToscaConceptIdentifier("deployed-3", "1.0.0"));
+        when(deployed4.getIdentifier()).thenReturn(deployedId4);
+        when(deployed5.getIdentifier()).thenReturn(deployedId5);
+        when(added1.getIdentifier()).thenReturn(addedId1);
+        when(added2.getIdentifier()).thenReturn(addedId2);
+        when(failPolicy1.getIdentifier()).thenReturn(new ToscaConceptIdentifier("failPolicy-1", "1.0.0"));
+        when(failPolicy2.getIdentifier()).thenReturn(new ToscaConceptIdentifier("failPolicy-2", "1.0.0"));
+
         Map<ToscaPolicy, XacmlApplicationServiceProvider> deployedPolicies = new HashMap<>();
         deployedPolicies.put(deployed1, null);
         deployedPolicies.put(deployed2, null);
         deployedPolicies.put(deployed3, null);
         deployedPolicies.put(deployed4, null);
+        deployedPolicies.put(deployed5, null);
         when(appmgr.getToscaPolicies()).thenReturn(deployedPolicies);
 
-        // update includes two overlaps
-        List<ToscaPolicy> updatePolicies = Arrays.asList(added1, deployed2, deployed3, added2);
-        when(update.getPolicies()).thenReturn(updatePolicies);
+        // update includes one overlap with existing and one overlap between the two
+        when(update.getPoliciesToBeDeployed()).thenReturn(List.of(added1, deployed2, deployed5, added2));
+        when(update.getPoliciesToBeUndeployed()).thenReturn(List.of(addedId1, deployedId1, deployedId5, deployedId4));
 
-        List<ToscaPolicy> failureUpdatePolicies = Arrays.asList(added1, deployed2, deployed3, failPolicy1, failPolicy2);
-        when(failurePdpUpdate.getPolicies()).thenReturn(failureUpdatePolicies);
+        when(failurePdpUpdate.getPoliciesToBeDeployed())
+                        .thenReturn(List.of(added1, deployed2, deployed5, failPolicy1, failPolicy2));
+        when(failurePdpUpdate.getPoliciesToBeUndeployed())
+                        .thenReturn(List.of(addedId1, deployedId1, deployedId5, deployedId4));
 
         when(appmgr.getPolicyCount()).thenReturn(NEW_COUNT);
 
@@ -144,17 +167,57 @@ public class XacmlPdpUpdatePublisherTest {
         verify(appmgr).loadDeployedPolicy(added1);
         verify(appmgr).loadDeployedPolicy(added2);
 
-        // two untouched
+        // three untouched
         verify(appmgr, never()).removeUndeployedPolicy(deployed2);
         verify(appmgr, never()).removeUndeployedPolicy(deployed3);
+        verify(appmgr, never()).removeUndeployedPolicy(deployed5);
         verify(appmgr, never()).loadDeployedPolicy(deployed2);
         verify(appmgr, never()).loadDeployedPolicy(deployed3);
+        verify(appmgr, never()).loadDeployedPolicy(deployed5);
 
         assertEquals(NEW_COUNT, statmgr.getTotalPoliciesCount());
 
         verify(client).send(status);
     }
 
+    @Test
+    public void testHandlePdpUpdate_Deploy() throws XacmlApplicationException {
+        when(update.getPoliciesToBeUndeployed()).thenReturn(null);
+
+        publisher.handlePdpUpdate(update);
+
+        // none removed
+        verify(appmgr, never()).removeUndeployedPolicy(any());
+
+        // two added
+        verify(appmgr).loadDeployedPolicy(added1);
+        verify(appmgr).loadDeployedPolicy(added2);
+
+        // three untouched
+        verify(appmgr, never()).loadDeployedPolicy(deployed2);
+        verify(appmgr, never()).loadDeployedPolicy(deployed3);
+        verify(appmgr, never()).loadDeployedPolicy(deployed5);
+    }
+
+    @Test
+    public void testHandlePdpUpdate_Undeploy() throws XacmlApplicationException {
+        when(update.getPoliciesToBeDeployed()).thenReturn(null);
+
+        publisher.handlePdpUpdate(update);
+
+        // three removed
+        verify(appmgr).removeUndeployedPolicy(deployed1);
+        verify(appmgr).removeUndeployedPolicy(deployed4);
+        verify(appmgr).removeUndeployedPolicy(deployed5);
+
+        // none added
+        verify(appmgr, never()).loadDeployedPolicy(any());
+
+        // two untouched
+        verify(appmgr, never()).removeUndeployedPolicy(deployed2);
+        verify(appmgr, never()).removeUndeployedPolicy(deployed3);
+    }
+
     @Test
     public void testHandlePdpUpdate_LoadPolicyFailed() throws XacmlApplicationException {
         // Set loadPolicy to fail
@@ -167,7 +230,8 @@ public class XacmlPdpUpdatePublisherTest {
         verify(appmgr).removeUndeployedPolicy(deployed1);
         verify(appmgr).removeUndeployedPolicy(deployed4);
 
-        verify(failurePdpUpdate).setPolicies(any());
+        // one untouched
+        verify(appmgr, never()).removeUndeployedPolicy(deployed5);
 
         verify(state).updateInternalState(any(), startsWith("Failed to load policy"));
         verify(client).send(status);
@@ -175,15 +239,13 @@ public class XacmlPdpUpdatePublisherTest {
 
     @Test
     public void testHandlePdpUpdate_NullPolicies() throws XacmlApplicationException {
-        when(update.getPolicies()).thenReturn(null);
+        when(update.getPoliciesToBeDeployed()).thenReturn(null);
+        when(update.getPoliciesToBeUndeployed()).thenReturn(null);
 
         publisher.handlePdpUpdate(update);
 
-        // all removed
-        verify(appmgr).removeUndeployedPolicy(deployed1);
-        verify(appmgr).removeUndeployedPolicy(deployed2);
-        verify(appmgr).removeUndeployedPolicy(deployed3);
-        verify(appmgr).removeUndeployedPolicy(deployed4);
+        // none removed
+        verify(appmgr, never()).removeUndeployedPolicy(any());
 
         // none added
         verify(appmgr, never()).loadDeployedPolicy(any());