From 8f1cc3035fcee119f22141f60dfeb6776b6f96e5 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Mon, 24 May 2021 13:13:07 -0400 Subject: Support delta policy lists in xacml-pdp 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 --- .../pdpx/main/comm/XacmlPdpUpdatePublisher.java | 53 ++++++++----- .../main/comm/XacmlPdpUpdatePublisherTest.java | 92 ++++++++++++++++++---- 2 files changed, 112 insertions(+), 33 deletions(-) (limited to 'main/src') diff --git a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java index 7806fead..39af6fd6 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java @@ -20,13 +20,16 @@ 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 incomingPolicies = - new HashSet<>(message.getPolicies() == null ? Collections.emptyList() : message.getPolicies()); - Set deployedPolicies = - new HashSet<>(appManager.getToscaPolicies().keySet()); + // current data + Map 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 toBeDeployedPolicies = policyToMap(message.getPoliciesToBeDeployed()); + List 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 policyToMap(Collection 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()); } } - } diff --git a/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisherTest.java b/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisherTest.java index a4cee50a..1edaab34 100644 --- a/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisherTest.java +++ b/main/src/test/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisherTest.java @@ -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 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 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 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()); -- cgit 1.2.3-korg