Merge "Fix UNDEPLOY transition in policyParticipant in ACM"
diff --git a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/client/PolicyApiHttpClient.java b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/client/PolicyApiHttpClient.java
index a86576e..bf1d24a 100644
--- a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/client/PolicyApiHttpClient.java
+++ b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/client/PolicyApiHttpClient.java
@@ -1,6 +1,6 @@
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2021 Nordix Foundation.
+ * Copyright (C) 2021,2023 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.onap.policy.clamp.acm.participant.policy.main.parameters.ParticipantPolicyParameters;
-import org.onap.policy.models.base.PfModelException;
import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
import org.springframework.stereotype.Component;
@@ -47,9 +46,8 @@
*
* @param toscaServiceTemplate the whole ToscaServiceTemplate
* @return Response
- * @throws PfModelException on errors creating the policy type
*/
- public Response createPolicyType(ToscaServiceTemplate toscaServiceTemplate) throws PfModelException {
+ public Response createPolicyType(ToscaServiceTemplate toscaServiceTemplate) {
return executePost(POLICY_URI + "policytypes", Entity.entity(toscaServiceTemplate, MediaType.APPLICATION_JSON));
}
diff --git a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java
index 0b03e23..3e74019 100644
--- a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java
+++ b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandler.java
@@ -22,9 +22,13 @@
package org.onap.policy.clamp.acm.participant.policy.main.handler;
+import java.util.ArrayList;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import java.util.UUID;
+import javax.ws.rs.core.Response.Status;
+import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.apache.http.HttpStatus;
import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
@@ -35,9 +39,9 @@
import org.onap.policy.clamp.models.acm.concepts.DeployState;
import org.onap.policy.clamp.models.acm.concepts.LockState;
import org.onap.policy.models.base.PfModelException;
-import org.onap.policy.models.base.PfModelRuntimeException;
import org.onap.policy.models.pdp.concepts.DeploymentSubGroup;
-import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@@ -46,11 +50,12 @@
* This class handles implementation of automationCompositionElement updates.
*/
@Component
+@RequiredArgsConstructor
public class AutomationCompositionElementHandler implements AutomationCompositionElementListener {
private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionElementHandler.class);
- private final Map<String, String> policyTypeMap = new LinkedHashMap<>();
- private final Map<String, String> policyMap = new LinkedHashMap<>();
+
+ private final Map<UUID, ToscaServiceTemplate> serviceTemplateMap = new LinkedHashMap<>();
private final PolicyApiHttpClient apiHttpClient;
private final PolicyPapHttpClient papHttpClient;
@@ -59,53 +64,48 @@
private ParticipantIntermediaryApi intermediaryApi;
/**
- * constructor.
- *
- * @param apiHttpClient the Policy Api Http Client
- * @param papHttpClient the Policy Pap Http Client
- */
- public AutomationCompositionElementHandler(PolicyApiHttpClient apiHttpClient, PolicyPapHttpClient papHttpClient) {
- this.papHttpClient = papHttpClient;
- this.apiHttpClient = apiHttpClient;
- }
-
- /**
* Callback method to handle a automation composition element state change.
*
* @param automationCompositionId the ID of the automation composition
* @param automationCompositionElementId the ID of the automation composition element
*/
@Override
- public void undeploy(UUID automationCompositionId, UUID automationCompositionElementId) {
- try {
- undeployPolicies(automationCompositionElementId);
- deletePolicyData(automationCompositionId, automationCompositionElementId);
+ public void undeploy(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException {
+ var automationCompositionDefinition = serviceTemplateMap.get(automationCompositionElementId);
+ if (automationCompositionDefinition == null) {
+ LOGGER.debug("No policies to undeploy to {}", automationCompositionElementId);
intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
automationCompositionElementId, DeployState.UNDEPLOYED, LockState.NONE);
- } catch (PfModelRuntimeException e) {
- LOGGER.error("Undeploying/Deleting policy failed {}", automationCompositionElementId, e);
+ return;
}
+ var policyList = getPolicyList(automationCompositionDefinition);
+ undeployPolicies(policyList, automationCompositionElementId);
+ var policyTypeList = getPolicyTypeList(automationCompositionDefinition);
+ deletePolicyData(policyTypeList, policyList);
+ serviceTemplateMap.remove(automationCompositionElementId);
+ intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
+ automationCompositionElementId, DeployState.UNDEPLOYED, LockState.NONE);
}
- private void deletePolicyData(UUID automationCompositionId, UUID automationCompositionElementId) {
+ private void deletePolicyData(List<ToscaConceptIdentifier> policyTypeList,
+ List<ToscaConceptIdentifier> policyList) {
// Delete all policies of this automationComposition from policy framework
- for (var policy : policyMap.entrySet()) {
- apiHttpClient.deletePolicy(policy.getKey(), policy.getValue());
+ for (var policy : policyList) {
+ apiHttpClient.deletePolicy(policy.getName(), policy.getVersion());
}
- policyMap.clear();
// Delete all policy types of this automation composition from policy framework
- for (var policyType : policyTypeMap.entrySet()) {
- apiHttpClient.deletePolicyType(policyType.getKey(), policyType.getValue());
+ for (var policyType : policyTypeList) {
+ apiHttpClient.deletePolicyType(policyType.getName(), policyType.getVersion());
}
- policyTypeMap.clear();
}
- private void deployPolicies(UUID automationCompositionId, UUID automationCompositionElementId) {
+ private void deployPolicies(List<ToscaConceptIdentifier> policyList, UUID automationCompositionId,
+ UUID automationCompositionElementId) throws PfModelException {
var deployFailure = false;
// Deploy all policies of this automationComposition from Policy Framework
- if (!policyMap.entrySet().isEmpty()) {
- for (var policy : policyMap.entrySet()) {
- var deployPolicyResp = papHttpClient.handlePolicyDeployOrUndeploy(policy.getKey(), policy.getValue(),
+ if (!policyList.isEmpty()) {
+ for (var policy : policyList) {
+ var deployPolicyResp = papHttpClient.handlePolicyDeployOrUndeploy(policy.getName(), policy.getVersion(),
DeploymentSubGroup.Action.POST).getStatus();
if (deployPolicyResp != HttpStatus.SC_ACCEPTED) {
deployFailure = true;
@@ -119,14 +119,16 @@
// Update the AC element state
intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
automationCompositionElementId, DeployState.DEPLOYED, LockState.LOCKED);
+ } else {
+ throw new PfModelException(Status.BAD_REQUEST, "Deploy of Policy failed.");
}
}
- private void undeployPolicies(UUID automationCompositionElementId) {
+ private void undeployPolicies(List<ToscaConceptIdentifier> policyList, UUID automationCompositionElementId) {
// Undeploy all policies of this automation composition from Policy Framework
- if (!policyMap.entrySet().isEmpty()) {
- for (var policy : policyMap.entrySet()) {
- papHttpClient.handlePolicyDeployOrUndeploy(policy.getKey(), policy.getValue(),
+ if (!policyList.isEmpty()) {
+ for (var policy : policyList) {
+ papHttpClient.handlePolicyDeployOrUndeploy(policy.getName(), policy.getVersion(),
DeploymentSubGroup.Action.DELETE);
}
LOGGER.debug("Undeployed policies from {} successfully", automationCompositionElementId);
@@ -150,32 +152,53 @@
var createPolicyResp = HttpStatus.SC_OK;
var automationCompositionDefinition = element.getToscaServiceTemplateFragment();
- if (automationCompositionDefinition.getToscaTopologyTemplate() != null) {
- if (automationCompositionDefinition.getPolicyTypes() != null) {
- for (var policyType : automationCompositionDefinition.getPolicyTypes().values()) {
- policyTypeMap.put(policyType.getName(), policyType.getVersion());
- }
- LOGGER.info("Found Policy Types in automation composition definition: {} , Creating Policy Types",
- automationCompositionDefinition.getName());
- createPolicyTypeResp = apiHttpClient.createPolicyType(automationCompositionDefinition).getStatus();
- }
- if (automationCompositionDefinition.getToscaTopologyTemplate().getPolicies() != null) {
- for (var gotPolicyMap : automationCompositionDefinition.getToscaTopologyTemplate().getPolicies()) {
- for (ToscaPolicy policy : gotPolicyMap.values()) {
- policyMap.put(policy.getName(), policy.getVersion());
- }
- }
- LOGGER.info("Found Policies in automation composition definition: {} , Creating Policies",
- automationCompositionDefinition.getName());
- createPolicyResp = apiHttpClient.createPolicy(automationCompositionDefinition).getStatus();
- }
- if (createPolicyTypeResp == HttpStatus.SC_OK && createPolicyResp == HttpStatus.SC_OK) {
- LOGGER.info("PolicyTypes/Policies for the automation composition element : {} are created "
- + "successfully", element.getId());
- deployPolicies(automationCompositionId, element.getId());
- } else {
- LOGGER.error("Creation of PolicyTypes/Policies failed. Policies will not be deployed.");
+ if (automationCompositionDefinition.getToscaTopologyTemplate() == null) {
+ throw new PfModelException(Status.BAD_REQUEST, "ToscaTopologyTemplate not defined");
+ }
+ serviceTemplateMap.put(element.getId(), automationCompositionDefinition);
+ if (automationCompositionDefinition.getPolicyTypes() != null) {
+ LOGGER.info("Found Policy Types in automation composition definition: {} , Creating Policy Types",
+ automationCompositionDefinition.getName());
+ createPolicyTypeResp = apiHttpClient.createPolicyType(automationCompositionDefinition).getStatus();
+ }
+ if (automationCompositionDefinition.getToscaTopologyTemplate().getPolicies() != null) {
+ LOGGER.info("Found Policies in automation composition definition: {} , Creating Policies",
+ automationCompositionDefinition.getName());
+ createPolicyResp = apiHttpClient.createPolicy(automationCompositionDefinition).getStatus();
+ }
+ if (createPolicyTypeResp == HttpStatus.SC_OK && createPolicyResp == HttpStatus.SC_OK) {
+ LOGGER.info(
+ "PolicyTypes/Policies for the automation composition element : {} are created " + "successfully",
+ element.getId());
+ var policyList = getPolicyList(automationCompositionDefinition);
+ deployPolicies(policyList, automationCompositionId, element.getId());
+ } else {
+ throw new PfModelException(Status.BAD_REQUEST,
+ "Creation of PolicyTypes/Policies failed. Policies will not be deployed.");
+ }
+ }
+
+ private List<ToscaConceptIdentifier> getPolicyTypeList(ToscaServiceTemplate serviceTemplate) {
+ List<ToscaConceptIdentifier> policyTypeList = new ArrayList<>();
+ if (serviceTemplate.getPolicyTypes() != null) {
+ for (var policyType : serviceTemplate.getPolicyTypes().values()) {
+ policyTypeList.add(policyType.getKey().asIdentifier());
}
}
+
+ return policyTypeList;
+ }
+
+ private List<ToscaConceptIdentifier> getPolicyList(ToscaServiceTemplate serviceTemplate) {
+ List<ToscaConceptIdentifier> policyList = new ArrayList<>();
+ if (serviceTemplate.getToscaTopologyTemplate().getPolicies() != null) {
+ for (var gotPolicyMap : serviceTemplate.getToscaTopologyTemplate().getPolicies()) {
+ for (var policy : gotPolicyMap.values()) {
+ policyList.add(policy.getKey().asIdentifier());
+ }
+ }
+ }
+
+ return policyList;
}
}
diff --git a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java
index e0b4a69..47c2799 100644
--- a/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java
+++ b/participant/participant-impl/participant-impl-policy/src/test/java/org/onap/policy/clamp/acm/participant/policy/main/handler/AutomationCompositionElementHandlerTest.java
@@ -20,20 +20,23 @@
package org.onap.policy.clamp.acm.participant.policy.main.handler;
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ws.rs.core.Response;
import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
import org.onap.policy.clamp.acm.participant.policy.client.PolicyApiHttpClient;
import org.onap.policy.clamp.acm.participant.policy.client.PolicyPapHttpClient;
import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
+import org.onap.policy.clamp.models.acm.concepts.DeployState;
+import org.onap.policy.clamp.models.acm.concepts.LockState;
import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
import org.onap.policy.models.base.PfModelException;
import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
@@ -50,21 +53,16 @@
public static final UUID AC_ID = UUID.randomUUID();
private static final ToscaConceptIdentifier DEFINITION = new ToscaConceptIdentifier(ID_NAME, ID_VERSION);
- private PolicyApiHttpClient api = Mockito.mock(PolicyApiHttpClient.class);
- private PolicyPapHttpClient pap = Mockito.mock(PolicyPapHttpClient.class);
-
@Test
- void testHandlerDoesNotThrowExceptions() {
- var handler = getTestingHandler();
-
- assertDoesNotThrow(() -> handler.undeploy(AC_ID, automationCompositionElementId));
- }
-
- private AutomationCompositionElementHandler getTestingHandler() {
- var handler = new AutomationCompositionElementHandler(api, pap);
- var intermediaryApi = Mockito.mock(ParticipantIntermediaryApi.class);
+ void testHandlerUndeploy() throws PfModelException {
+ var handler = new AutomationCompositionElementHandler(mock(PolicyApiHttpClient.class),
+ mock(PolicyPapHttpClient.class));
+ var intermediaryApi = mock(ParticipantIntermediaryApi.class);
handler.setIntermediaryApi(intermediaryApi);
- return handler;
+
+ handler.undeploy(AC_ID, automationCompositionElementId);
+ verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId,
+ DeployState.UNDEPLOYED, LockState.NONE);
}
private AcElementDeploy getTestingAcElement() {
@@ -81,25 +79,58 @@
}
@Test
- void testAcElementUpdate() throws PfModelException {
+ void testDeploy() throws PfModelException {
// Mock success scenario for policy creation and deployment
+ var api = mock(PolicyApiHttpClient.class);
doReturn(Response.ok().build()).when(api).createPolicyType(any());
doReturn(Response.ok().build()).when(api).createPolicy(any());
+
+ var pap = mock(PolicyPapHttpClient.class);
doReturn(Response.accepted().build()).when(pap).handlePolicyDeployOrUndeploy(any(), any(), any());
- var handler = getTestingHandler();
+ var handler = new AutomationCompositionElementHandler(api, pap);
+ var intermediaryApi = mock(ParticipantIntermediaryApi.class);
+ handler.setIntermediaryApi(intermediaryApi);
+
+ handler.deploy(AC_ID, getTestingAcElement(), Map.of());
+ handler.undeploy(AC_ID, automationCompositionElementId);
+ verify(intermediaryApi).updateAutomationCompositionElementState(AC_ID, automationCompositionElementId,
+ DeployState.UNDEPLOYED, LockState.NONE);
+ }
+
+ @Test
+ void testApiException() throws PfModelException {
+ var api = mock(PolicyApiHttpClient.class);
+ doReturn(Response.serverError().build()).when(api).createPolicyType(any());
+ doReturn(Response.ok().build()).when(api).createPolicy(any());
+
+ var pap = mock(PolicyPapHttpClient.class);
+ doReturn(Response.accepted().build()).when(pap).handlePolicyDeployOrUndeploy(any(), any(), any());
+
+ var handler = new AutomationCompositionElementHandler(api, pap);
+ var intermediaryApi = mock(ParticipantIntermediaryApi.class);
+ handler.setIntermediaryApi(intermediaryApi);
var element = getTestingAcElement();
- assertDoesNotThrow(() -> handler.deploy(AC_ID, element, Map.of()));
-
- assertDoesNotThrow(() -> handler.undeploy(AC_ID, automationCompositionElementId));
-
- // Mock failure in policy deployment
- doReturn(Response.serverError().build()).when(pap).handlePolicyDeployOrUndeploy(any(), any(), any());
- assertDoesNotThrow(() -> handler.deploy(AC_ID, element, Map.of()));
-
// Mock failure in policy type creation
- doReturn(Response.serverError().build()).when(api).createPolicyType(any());
- assertDoesNotThrow(() -> handler.deploy(AC_ID, element, Map.of()));
+ assertThatThrownBy(() -> handler.deploy(AC_ID, element, Map.of()))
+ .hasMessageMatching("Creation of PolicyTypes/Policies failed. Policies will not be deployed.");
+ }
+
+ @Test
+ void testDeployPapException() throws PfModelException {
+ var api = mock(PolicyApiHttpClient.class);
+ doReturn(Response.ok().build()).when(api).createPolicyType(any());
+ doReturn(Response.ok().build()).when(api).createPolicy(any());
+
+ var pap = mock(PolicyPapHttpClient.class);
+ doReturn(Response.serverError().build()).when(pap).handlePolicyDeployOrUndeploy(any(), any(), any());
+
+ var handler = new AutomationCompositionElementHandler(api, pap);
+ var intermediaryApi = mock(ParticipantIntermediaryApi.class);
+ handler.setIntermediaryApi(intermediaryApi);
+ var element = getTestingAcElement();
+ assertThatThrownBy(() -> handler.deploy(AC_ID, element, Map.of()))
+ .hasMessageMatching("Deploy of Policy failed.");
}
}