diff options
24 files changed, 557 insertions, 292 deletions
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtils.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtils.java index 015a96aad..54e6db1cc 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtils.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtils.java @@ -32,8 +32,6 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; public final class ParticipantUtils { private static final Coder CODER = new StandardCoder(); - private static final String AUTOMATION_COMPOSITION_ELEMENT = - "org.onap.policy.clamp.acm.AutomationCompositionElement"; /** * Get the First StartPhase. @@ -75,27 +73,4 @@ public final class ParticipantUtils { } return 0; } - - /** - * Checks if a NodeTemplate is an AutomationCompositionElement. - * - * @param nodeTemplate the ToscaNodeTemplate - * @param toscaServiceTemplate the ToscaServiceTemplate - * @return true if the NodeTemplate is an AutomationCompositionElement - */ - public static boolean checkIfNodeTemplateIsAutomationCompositionElement(ToscaNodeTemplate nodeTemplate, - ToscaServiceTemplate toscaServiceTemplate) { - if (nodeTemplate.getType().contains(AUTOMATION_COMPOSITION_ELEMENT)) { - return true; - } else { - var nodeType = toscaServiceTemplate.getNodeTypes().get(nodeTemplate.getType()); - if (nodeType != null) { - var derivedFrom = nodeType.getDerivedFrom(); - if (derivedFrom != null) { - return derivedFrom.contains(AUTOMATION_COMPOSITION_ELEMENT); - } - } - } - return false; - } } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantAckMessage.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantAckMessage.java index bdb2be861..e73f2e795 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantAckMessage.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/dmaap/participant/ParticipantAckMessage.java @@ -46,6 +46,8 @@ public class ParticipantAckMessage { private ParticipantMessageType messageType; + private UUID compositionId; + /** * Participant ID, or {@code null} for messages from participants. */ diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionDefinition.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionDefinition.java index fcaa6e6db..11e3f583e 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionDefinition.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionDefinition.java @@ -89,8 +89,9 @@ public class JpaAutomationCompositionDefinition extends Validated @Override public AutomationCompositionDefinition toAuthorative() { var acmDefinition = new AutomationCompositionDefinition(); - acmDefinition.setCompositionId(UUID.fromString(compositionId)); - acmDefinition.setServiceTemplate(serviceTemplate.toAuthorative()); + acmDefinition.setCompositionId(UUID.fromString(this.compositionId)); + acmDefinition.setState(this.state); + acmDefinition.setServiceTemplate(this.serviceTemplate.toAuthorative()); for (var element : this.elements) { var key = element.getNodeTemplateId().getName(); acmDefinition.getElementStateMap().put(key, element.toAuthorative()); @@ -105,11 +106,12 @@ public class JpaAutomationCompositionDefinition extends Validated this.serviceTemplate = new DocToscaServiceTemplate(copyConcept.getServiceTemplate()); setName(this.serviceTemplate.getName()); setVersion(this.serviceTemplate.getVersion()); - elements = new HashSet<>(copyConcept.getElementStateMap().size()); + this.elements = new HashSet<>(copyConcept.getElementStateMap().size()); for (var element : copyConcept.getElementStateMap().values()) { var nodeTemplateStateId = element.getNodeTemplateStateId().toString(); var jpaNodeTemplateState = new JpaNodeTemplateState(nodeTemplateStateId, this.compositionId); jpaNodeTemplateState.fromAuthorative(element); + this.elements.add(jpaNodeTemplateState); } } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaNodeTemplateState.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaNodeTemplateState.java index a6d13a638..088bf2196 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaNodeTemplateState.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaNodeTemplateState.java @@ -21,6 +21,7 @@ package org.onap.policy.clamp.models.acm.persistence.concepts; import java.util.UUID; +import javax.persistence.AttributeOverride; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; @@ -33,7 +34,9 @@ import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.NodeTemplateState; import org.onap.policy.common.parameters.annotations.NotNull; import org.onap.policy.models.base.PfAuthorative; +import org.onap.policy.models.base.PfConceptKey; import org.onap.policy.models.base.Validated; +import org.onap.policy.models.base.validation.annotations.VerifyKey; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; @Entity @@ -54,9 +57,11 @@ public class JpaNodeTemplateState extends Validated implements PfAuthorative<Nod @Column private String participantId; - @Column + @VerifyKey @NotNull - private ToscaConceptIdentifier nodeTemplateId; + @AttributeOverride(name = "name", column = @Column(name = "nodeTemplate_name")) + @AttributeOverride(name = "version", column = @Column(name = "nodeTemplate_version")) + private PfConceptKey nodeTemplateId; @Column @NotNull @@ -86,7 +91,8 @@ public class JpaNodeTemplateState extends Validated implements PfAuthorative<Nod if (copyConcept.getParticipantId() != null) { this.participantId = copyConcept.getParticipantId().toString(); } - this.nodeTemplateId = copyConcept.getNodeTemplateId(); + this.nodeTemplateId = copyConcept.getNodeTemplateId().asConceptKey(); + this.state = copyConcept.getState(); } @Override @@ -96,7 +102,7 @@ public class JpaNodeTemplateState extends Validated implements PfAuthorative<Nod if (this.participantId != null) { nodeTemplateState.setParticipantId(UUID.fromString(this.participantId)); } - nodeTemplateState.setNodeTemplateId(this.nodeTemplateId); + nodeTemplateState.setNodeTemplateId(new ToscaConceptIdentifier(this.nodeTemplateId)); nodeTemplateState.setState(this.state); return nodeTemplateState; } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProvider.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProvider.java index 3757f6c7b..71f510a67 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProvider.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProvider.java @@ -32,6 +32,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate; import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionDefinition; import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionDefinitionRepository; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.springframework.data.domain.Example; @@ -62,6 +63,8 @@ public class AcDefinitionProvider { } serviceTemplate.getMetadata().put("compositionId", compositionId); acmDefinition.setServiceTemplate(serviceTemplate); + var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate); + acmDefinition.setElementStateMap(AcmUtils.createElementStateMap(acElements, AcTypeState.COMMISSIONED)); var jpaAcmDefinition = ProviderUtils.getJpaAndValidate(acmDefinition, JpaAutomationCompositionDefinition::new, "AutomationCompositionDefinition"); var result = acmDefinitionRepository.save(jpaAcmDefinition); @@ -80,6 +83,8 @@ public class AcDefinitionProvider { acmDefinition.setCompositionId(compositionId); acmDefinition.setState(AcTypeState.COMMISSIONED); acmDefinition.setServiceTemplate(serviceTemplate); + var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate); + acmDefinition.setElementStateMap(AcmUtils.createElementStateMap(acElements, AcTypeState.COMMISSIONED)); updateAcDefinition(acmDefinition); } @@ -137,10 +142,9 @@ public class AcDefinitionProvider { * @return the automation composition definition */ @Transactional(readOnly = true) - public Optional<ToscaServiceTemplate> findAcDefinition(UUID compositionId) { + public Optional<AutomationCompositionDefinition> findAcDefinition(UUID compositionId) { var jpaGet = acmDefinitionRepository.findById(compositionId.toString()); - return jpaGet.stream().map(JpaAutomationCompositionDefinition::getServiceTemplate) - .map(DocToscaServiceTemplate::toAuthorative).findFirst(); + return jpaGet.stream().map(JpaAutomationCompositionDefinition::toAuthorative).findFirst(); } /** diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java index 7b8ebc038..8e45c770b 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java @@ -20,7 +20,9 @@ package org.onap.policy.clamp.models.acm.persistence.provider; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.UUID; import javax.ws.rs.core.Response.Status; @@ -30,6 +32,7 @@ import org.onap.policy.clamp.models.acm.concepts.Participant; import org.onap.policy.clamp.models.acm.persistence.concepts.JpaParticipant; import org.onap.policy.clamp.models.acm.persistence.repository.ParticipantRepository; import org.onap.policy.models.base.PfModelRuntimeException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -127,4 +130,23 @@ public class ParticipantProvider { return jpaDeleteParticipantOpt.get().toAuthorative(); } + + + /** + * Get a map with SupportedElement as key and the participantId as value. + * + * @return a map + */ + public Map<ToscaConceptIdentifier, UUID> getSupportedElementMap() { + var list = participantRepository.findAll(); + Map<ToscaConceptIdentifier, UUID> map = new HashMap<>(); + for (var participant : list) { + for (var element : participant.getSupportedElements()) { + var supportedElement = new ToscaConceptIdentifier(element.getTypeName(), element.getTypeVersion()); + map.put(supportedElement, UUID.fromString(participant.getParticipantId())); + } + } + return map; + } + } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java b/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java index 8bd9039fd..9f73cb144 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/utils/AcmUtils.java @@ -22,25 +22,31 @@ package org.onap.policy.clamp.models.acm.utils; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.UUID; import java.util.function.Function; import java.util.function.UnaryOperator; import java.util.stream.Collectors; +import javax.ws.rs.core.Response; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; +import org.onap.policy.clamp.models.acm.concepts.NodeTemplateState; import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition; import org.onap.policy.clamp.models.acm.concepts.ParticipantUpdates; import org.onap.policy.common.parameters.BeanValidationResult; import org.onap.policy.common.parameters.ObjectValidationResult; import org.onap.policy.common.parameters.ValidationResult; import org.onap.policy.common.parameters.ValidationStatus; +import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; @@ -53,6 +59,8 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate; @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class AcmUtils { + public static final String AUTOMATION_COMPOSITION_ELEMENT = + "org.onap.policy.clamp.acm.AutomationCompositionElement"; public static final String AUTOMATION_COMPOSITION_NODE_TYPE = "org.onap.policy.clamp.acm.AutomationComposition"; public static final String ENTRY = "entry "; @@ -111,51 +119,107 @@ public final class AcmUtils { } /** - * Prepare ParticipantDefinitionUpdate to set in the message. + * Checks if a NodeTemplate is an AutomationCompositionElement. * - * @param acParticipantId participant id - * @param entryKey key for the entry - * @param entryValue value relates to toscaNodeTemplate - * @param participantDefinitionUpdates list of participantDefinitionUpdates + * @param nodeTemplate the ToscaNodeTemplate + * @param toscaServiceTemplate the ToscaServiceTemplate + * @return true if the NodeTemplate is an AutomationCompositionElement */ - public static void prepareParticipantDefinitionUpdate(UUID acParticipantId, String entryKey, - ToscaNodeTemplate entryValue, - List<ParticipantDefinition> participantDefinitionUpdates) { - - var acDefinition = new AutomationCompositionElementDefinition(); - acDefinition.setAcElementDefinitionId(new ToscaConceptIdentifier(entryKey, entryValue.getVersion())); - acDefinition.setAutomationCompositionElementToscaNodeTemplate(entryValue); - - List<AutomationCompositionElementDefinition> automationCompositionElementDefinitionList = new ArrayList<>(); - - if (participantDefinitionUpdates.isEmpty()) { - participantDefinitionUpdates.add(getParticipantDefinition(acDefinition, acParticipantId, - automationCompositionElementDefinitionList)); + public static boolean checkIfNodeTemplateIsAutomationCompositionElement(ToscaNodeTemplate nodeTemplate, + ToscaServiceTemplate toscaServiceTemplate) { + if (nodeTemplate.getType().contains(AUTOMATION_COMPOSITION_ELEMENT)) { + return true; } else { - var participantExists = false; - for (ParticipantDefinition participantDefinitionUpdate : participantDefinitionUpdates) { - if (acParticipantId != null || participantDefinitionUpdate.getParticipantId() != null) { - if (participantDefinitionUpdate.getParticipantId().equals(acParticipantId)) { - participantDefinitionUpdate.getAutomationCompositionElementDefinitionList().add(acDefinition); - participantExists = true; - } + var nodeType = toscaServiceTemplate.getNodeTypes().get(nodeTemplate.getType()); + if (nodeType != null) { + var derivedFrom = nodeType.getDerivedFrom(); + if (derivedFrom != null) { + return derivedFrom.contains(AUTOMATION_COMPOSITION_ELEMENT); } } - if (!participantExists) { - participantDefinitionUpdates.add(getParticipantDefinition(acDefinition, acParticipantId, - automationCompositionElementDefinitionList)); + } + return false; + } + + /** + * Prepare list of ParticipantDefinition for the Priming message. + * + * @param acElements the extracted AcElements from ServiceTemplate + * @param supportedElementMap supported Element Map + */ + public static List<ParticipantDefinition> prepareParticipantPriming( + List<Entry<String, ToscaNodeTemplate>> acElements, Map<ToscaConceptIdentifier, UUID> supportedElementMap) { + + Map<UUID, List<AutomationCompositionElementDefinition>> map = new HashMap<>(); + for (var elementEntry : acElements) { + var type = new ToscaConceptIdentifier(elementEntry.getValue().getType(), + elementEntry.getValue().getTypeVersion()); + var participantId = supportedElementMap.get(type); + if (participantId == null) { + throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + "Element Type " + type + " not supported"); } + var acElementDefinition = new AutomationCompositionElementDefinition(); + acElementDefinition.setAcElementDefinitionId( + new ToscaConceptIdentifier(elementEntry.getKey(), elementEntry.getValue().getVersion())); + acElementDefinition.setAutomationCompositionElementToscaNodeTemplate(elementEntry.getValue()); + map.putIfAbsent(participantId, new ArrayList<>()); + map.get(participantId).add(acElementDefinition); + } + return prepareParticipantPriming(map); + } + + /** + * Prepare ParticipantPriming. + * + * @param map of AutomationCompositionElementDefinition with participantId as key + * @return list of ParticipantDefinition + */ + public static List<ParticipantDefinition> prepareParticipantPriming( + Map<UUID, List<AutomationCompositionElementDefinition>> map) { + List<ParticipantDefinition> result = new ArrayList<>(); + for (var entry : map.entrySet()) { + var participantDefinition = new ParticipantDefinition(); + participantDefinition.setParticipantId(entry.getKey()); + participantDefinition.setAutomationCompositionElementDefinitionList(entry.getValue()); + result.add(participantDefinition); } + return result; } - private static ParticipantDefinition getParticipantDefinition(AutomationCompositionElementDefinition acDefinition, - UUID acParticipantId, - List<AutomationCompositionElementDefinition> automationCompositionElementDefinitionList) { - var participantDefinition = new ParticipantDefinition(); - participantDefinition.setParticipantId(acParticipantId); - automationCompositionElementDefinitionList.add(acDefinition); - participantDefinition.setAutomationCompositionElementDefinitionList(automationCompositionElementDefinitionList); - return participantDefinition; + /** + * Extract AcElements from ServiceTemplate. + * + * @param serviceTemplate the ToscaServiceTemplate + * @return the list of Entry of AutomationCompositionElement + */ + public static List<Entry<String, ToscaNodeTemplate>> extractAcElementsFromServiceTemplate( + ToscaServiceTemplate serviceTemplate) { + return serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().entrySet().stream().filter( + nodeTemplateEntry -> checkIfNodeTemplateIsAutomationCompositionElement(nodeTemplateEntry.getValue(), + serviceTemplate)) + .collect(Collectors.toList()); + } + + /** + * Create NodeTemplateState Map. + * + * @param acElements extracted AcElements from ServiceTemplate. + * @param state the AcTypeState + * @return the NodeTemplateState Map + */ + public static Map<String, NodeTemplateState> createElementStateMap( + List<Entry<String, ToscaNodeTemplate>> acElements, AcTypeState state) { + Map<String, NodeTemplateState> result = new HashMap<>(acElements.size()); + for (var entry : acElements) { + var nodeTemplateState = new NodeTemplateState(); + nodeTemplateState.setNodeTemplateStateId(UUID.randomUUID()); + nodeTemplateState.setState(state); + nodeTemplateState + .setNodeTemplateId(new ToscaConceptIdentifier(entry.getKey(), entry.getValue().getVersion())); + result.put(entry.getKey(), nodeTemplateState); + } + return result; } /** diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtilsTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtilsTest.java index b3efc2765..6bb7f1eb7 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtilsTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/concepts/ParticipantUtilsTest.java @@ -24,13 +24,11 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.Map; import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.models.acm.utils.CommonTestData; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; -import org.onap.policy.common.utils.coder.StandardYamlCoder; import org.onap.policy.common.utils.resources.ResourceUtils; -import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; -import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; class ParticipantUtilsTest { @@ -38,12 +36,6 @@ class ParticipantUtilsTest { private static final String TOSCA_TEMPLATE_YAML = "examples/acm/test-pm-subscription-handling.yaml"; private static final String AUTOMATION_COMPOSITION_JSON = "src/test/resources/providers/TestAutomationCompositions.json"; - private static final String AUTOMATION_COMPOSITION_ELEMENT = - "org.onap.policy.clamp.acm.AutomationCompositionElement"; - private static final String POLICY_AUTOMATION_COMPOSITION_ELEMENT = - "org.onap.policy.clamp.acm.PolicyAutomationCompositionElement"; - private static final String PARTICIPANT_AUTOMATION_COMPOSITION_ELEMENT = "org.onap.policy.clamp.acm.Participant"; - private static final StandardYamlCoder YAML_TRANSLATOR = new StandardYamlCoder(); @Test void testFindStartPhase() { @@ -54,30 +46,11 @@ class ParticipantUtilsTest { @Test void testGetFirstStartPhase() throws CoderException { - var serviceTemplate = - YAML_TRANSLATOR.decode(ResourceUtils.getResourceAsStream(TOSCA_TEMPLATE_YAML), ToscaServiceTemplate.class); + var serviceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML); var automationCompositions = CODER.decode(ResourceUtils.getResourceAsString(AUTOMATION_COMPOSITION_JSON), AutomationCompositions.class); var result = ParticipantUtils.getFirstStartPhase(automationCompositions.getAutomationCompositionList().get(0), serviceTemplate); assertThat(result).isZero(); } - - @Test - void testCheckIfNodeTemplateIsAutomationCompositionElement() throws CoderException { - var serviceTemplate = - YAML_TRANSLATOR.decode(ResourceUtils.getResourceAsStream(TOSCA_TEMPLATE_YAML), ToscaServiceTemplate.class); - var nodeTemplate = new ToscaNodeTemplate(); - nodeTemplate.setType(AUTOMATION_COMPOSITION_ELEMENT); - assertThat(ParticipantUtils.checkIfNodeTemplateIsAutomationCompositionElement(nodeTemplate, serviceTemplate)) - .isTrue(); - - nodeTemplate.setType(POLICY_AUTOMATION_COMPOSITION_ELEMENT); - assertThat(ParticipantUtils.checkIfNodeTemplateIsAutomationCompositionElement(nodeTemplate, serviceTemplate)) - .isTrue(); - - nodeTemplate.setType(PARTICIPANT_AUTOMATION_COMPOSITION_ELEMENT); - assertThat(ParticipantUtils.checkIfNodeTemplateIsAutomationCompositionElement(nodeTemplate, serviceTemplate)) - .isFalse(); - } } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProviderTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProviderTest.java index a27a74be4..784f1cfde 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProviderTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcDefinitionProviderTest.java @@ -200,6 +200,7 @@ class AcDefinitionProviderTest { nodeTemplateState.setNodeTemplateStateId(UUID.randomUUID()); nodeTemplateState.setNodeTemplateId(new ToscaConceptIdentifier("name", "1.0.0")); nodeTemplateState.setState(AcTypeState.COMMISSIONED); + nodeTemplateState.setParticipantId(UUID.randomUUID()); acmDefinition.setElementStateMap(Map.of(nodeTemplateState.getNodeTemplateId().getName(), nodeTemplateState)); return acmDefinition; } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java index a40d1cc1f..0c5137824 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java @@ -104,6 +104,9 @@ class ParticipantProviderTest { when(participantRepository.findAll()).thenReturn(jpaParticipantList); assertThat(participantProvider.getParticipants()).hasSize(inputParticipants.size()); + assertThatThrownBy(() -> participantProvider.getParticipantById(inputParticipants.get(0).getParticipantId())) + .hasMessageMatching("Participant Not Found with ID: " + inputParticipants.get(0).getParticipantId()); + when(participantRepository.findById(any())).thenReturn( Optional.ofNullable(jpaParticipantList.get(0))); @@ -128,4 +131,14 @@ class ParticipantProviderTest { var deletedParticipant = participantProvider.deleteParticipant(participantId); assertThat(inputParticipants.get(0)).usingRecursiveComparison().isEqualTo(deletedParticipant); } + + @Test + void testGetSupportedElementMap() { + var participantRepository = mock(ParticipantRepository.class); + when(participantRepository.findAll()).thenReturn(jpaParticipantList); + var participantProvider = new ParticipantProvider(participantRepository); + + var result = participantProvider.getSupportedElementMap(); + assertThat(result).hasSize(2); + } } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java index c5acada59..c23c38c5b 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/utils/AcmUtilsTest.java @@ -21,11 +21,13 @@ package org.onap.policy.clamp.models.acm.utils; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.fail; import java.io.File; import java.util.ArrayList; @@ -38,7 +40,7 @@ import org.junit.jupiter.api.Test; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.ParticipantUpdates; -import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType; @@ -50,7 +52,10 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate; class AcmUtilsTest { - private static final ToscaConceptIdentifier TYPE = new ToscaConceptIdentifier("id", "1.0.0"); + private static final String POLICY_AUTOMATION_COMPOSITION_ELEMENT = + "org.onap.policy.clamp.acm.PolicyAutomationCompositionElement"; + private static final String PARTICIPANT_AUTOMATION_COMPOSITION_ELEMENT = "org.onap.policy.clamp.acm.Participant"; + private static final String TOSCA_TEMPLATE_YAML = "clamp/acm/pmsh/funtional-pmsh-usecase.yaml"; @Test void testCommonUtilsParticipantUpdate() { @@ -72,6 +77,39 @@ class AcmUtilsTest { } @Test + void testCheckIfNodeTemplateIsAutomationCompositionElement() { + var serviceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML); + var nodeTemplate = new ToscaNodeTemplate(); + nodeTemplate.setType(AcmUtils.AUTOMATION_COMPOSITION_ELEMENT); + assertThat(AcmUtils.checkIfNodeTemplateIsAutomationCompositionElement(nodeTemplate, serviceTemplate)).isTrue(); + + nodeTemplate.setType(POLICY_AUTOMATION_COMPOSITION_ELEMENT); + assertThat(AcmUtils.checkIfNodeTemplateIsAutomationCompositionElement(nodeTemplate, serviceTemplate)).isTrue(); + + nodeTemplate.setType(PARTICIPANT_AUTOMATION_COMPOSITION_ELEMENT); + assertThat(AcmUtils.checkIfNodeTemplateIsAutomationCompositionElement(nodeTemplate, serviceTemplate)).isFalse(); + } + + @Test + void testPrepareParticipantPriming() { + var serviceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML); + + var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate); + Map<ToscaConceptIdentifier, UUID> map = new HashMap<>(); + var participantId = UUID.randomUUID(); + assertThatThrownBy(() -> AcmUtils.prepareParticipantPriming(acElements, map)).hasMessageMatching( + "Element Type org.onap.policy.clamp.acm.PolicyAutomationCompositionElement 1.0.1 not supported"); + map.put(new ToscaConceptIdentifier("org.onap.policy.clamp.acm.PolicyAutomationCompositionElement", "1.0.1"), + participantId); + map.put(new ToscaConceptIdentifier("org.onap.policy.clamp.acm.K8SMicroserviceAutomationCompositionElement", + "1.0.1"), participantId); + map.put(new ToscaConceptIdentifier("org.onap.policy.clamp.acm.HttpAutomationCompositionElement", "1.0.1"), + participantId); + var result = AcmUtils.prepareParticipantPriming(acElements, map); + assertThat(result).isNotEmpty().hasSize(1); + } + + @Test void testCommonUtilsServiceTemplate() { var acElement = new AutomationCompositionElement(); var toscaServiceTemplate = getDummyToscaServiceTemplate(); @@ -90,7 +128,7 @@ class AcmUtilsTest { } @Test - void testValidateAutomationComposition() throws Exception { + void testValidateAutomationComposition() { var automationComposition = getDummyAutomationComposition(); var toscaServiceTemplate = getDummyToscaServiceTemplate(); var result = AcmUtils.validateAutomationComposition(automationComposition, toscaServiceTemplate); @@ -102,19 +140,27 @@ class AcmUtilsTest { nodeTemplate.setType("org.onap.policy.clamp.acm.AutomationComposition"); nodeTemplates.put("org.onap.dcae.acm.DCAEMicroserviceAutomationCompositionParticipant", nodeTemplate); toscaServiceTemplate.getToscaTopologyTemplate().setNodeTemplates(nodeTemplates); - var result2 = AcmUtils.validateAutomationComposition(automationComposition, toscaServiceTemplate); - toscaServiceTemplate.setToscaTopologyTemplate(null); - assertFalse(result2.isValid()); + result = AcmUtils.validateAutomationComposition(automationComposition, toscaServiceTemplate); + assertFalse(result.isValid()); + + var doc = new DocToscaServiceTemplate(CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML)); + result = AcmUtils.validateAutomationComposition(automationComposition, doc.toAuthorative()); + assertFalse(result.isValid()); } - private AutomationComposition getDummyAutomationComposition() throws CoderException { + private AutomationComposition getDummyAutomationComposition() { var automationComposition = new AutomationComposition(); - var element = new StandardCoder().decode( - new File("src/test/resources/json/AutomationCompositionElementNoOrderedState.json"), - AutomationCompositionElement.class); automationComposition.setCompositionId(UUID.randomUUID()); Map<UUID, AutomationCompositionElement> map = new LinkedHashMap<>(); - map.put(UUID.randomUUID(), element); + try { + var element = new StandardCoder().decode( + new File("src/test/resources/json/AutomationCompositionElementNoOrderedState.json"), + AutomationCompositionElement.class); + map.put(UUID.randomUUID(), element); + } catch (Exception e) { + fail("Cannot read or decode " + e.getMessage()); + return null; + } automationComposition.setElements(map); return automationComposition; } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ParticipantHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ParticipantHandler.java index f324cea0c..75f2d81ab 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ParticipantHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ParticipantHandler.java @@ -209,15 +209,16 @@ public class ParticipantHandler { // This message is to decommission the automation composition acElementDefsMap.get(participantUpdateMsg.getCompositionId()).clear(); } - sendParticipantUpdateAck(participantUpdateMsg.getMessageId()); + sendParticipantUpdateAck(participantUpdateMsg.getMessageId(), participantUpdateMsg.getCompositionId()); } /** * Method to send ParticipantUpdateAck message to automation composition runtime. */ - public void sendParticipantUpdateAck(UUID messageId) { + public void sendParticipantUpdateAck(UUID messageId, UUID compositionId) { var participantUpdateAck = new ParticipantUpdateAck(); participantUpdateAck.setResponseTo(messageId); + participantUpdateAck.setCompositionId(compositionId); participantUpdateAck.setMessage("Participant Update Ack message"); participantUpdateAck.setResult(true); participantUpdateAck.setParticipantId(participantId); diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ParticipantHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ParticipantHandlerTest.java index c538a0248..dc04440ca 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ParticipantHandlerTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ParticipantHandlerTest.java @@ -25,6 +25,9 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import java.time.Instant; import java.util.List; @@ -36,14 +39,13 @@ import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantAckMessage; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessage; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMessageType; +import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantRegisterAck; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantUpdate; import org.onap.policy.common.utils.coder.CoderException; class ParticipantHandlerTest { private final CommonTestData commonTestData = new CommonTestData(); - private static final String ID_NAME = "org.onap.PM_CDS_Blueprint"; - private static final String ID_VERSION = "1.0.1"; @Test void handleUpdateTest() { @@ -119,4 +121,14 @@ class ParticipantHandlerTest { } + @Test + void testHandleParticipantRegisterAck() { + var parameters = CommonTestData.getParticipantParameters(); + var automationCompositionHandler = commonTestData.getMockAutomationCompositionHandler(); + var publisher = mock(ParticipantMessagePublisher.class); + var participantHandler = new ParticipantHandler(parameters, publisher, automationCompositionHandler); + + participantHandler.handleParticipantRegisterAck(new ParticipantRegisterAck()); + verify(publisher).sendParticipantStatus(any()); + } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java index 450c75564..c273a627a 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProvider.java @@ -25,13 +25,14 @@ import java.util.UUID; import java.util.stream.Collectors; import javax.ws.rs.core.Response.Status; import lombok.RequiredArgsConstructor; -import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantUpdatePublisher; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; +import org.onap.policy.clamp.models.acm.messages.rest.commissioning.AcTypeStateUpdate; import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.AcTypeStateResolver; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; -import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; @@ -51,8 +52,8 @@ public class CommissioningProvider { private final AcDefinitionProvider acDefinitionProvider; private final AutomationCompositionProvider acProvider; - private final SupervisionHandler supervisionHandler; - private final ParticipantProvider participantProvider; + private final AcTypeStateResolver acTypeStateResolver; + private final ParticipantUpdatePublisher participantUpdatePublisher; private CommissioningResponse createCommissioningResponse(UUID compositionId, ToscaServiceTemplate serviceTemplate) { @@ -80,10 +81,6 @@ public class CommissioningProvider { var acmDefinition = acDefinitionProvider.createAutomationCompositionDefinition(serviceTemplate); serviceTemplate = acmDefinition.getServiceTemplate(); - var participantList = participantProvider.getParticipants(); - if (!participantList.isEmpty()) { - supervisionHandler.handleSendCommissionMessage(acmDefinition); - } return createCommissioningResponse(acmDefinition.getCompositionId(), serviceTemplate); } @@ -100,7 +97,7 @@ public class CommissioningProvider { "There are ACM instances, Update of ACM Definition not allowed"); } var acDefinition = acDefinitionProvider.getAcDefinition(compositionId); - if (AcTypeState.COMMISSIONED.equals(acDefinition.getState())) { + if (!AcTypeState.COMMISSIONED.equals(acDefinition.getState())) { throw new PfModelRuntimeException(Status.BAD_REQUEST, "ACM not in COMMISSIONED state, Update of ACM Definition not allowed"); } @@ -116,14 +113,14 @@ public class CommissioningProvider { * @return the result of the deletion */ public CommissioningResponse deleteAutomationCompositionDefinition(UUID compositionId) { - if (verifyIfInstanceExists(compositionId)) { throw new PfModelRuntimeException(Status.BAD_REQUEST, "Delete instances, to commission automation composition definitions"); } - var participantList = participantProvider.getParticipants(); - if (!participantList.isEmpty()) { - supervisionHandler.handleSendDeCommissionMessage(compositionId); + var acDefinition = acDefinitionProvider.getAcDefinition(compositionId); + if (!AcTypeState.COMMISSIONED.equals(acDefinition.getState())) { + throw new PfModelRuntimeException(Status.BAD_REQUEST, + "ACM not in COMMISSIONED state, Update of ACM Definition not allowed"); } var serviceTemplate = acDefinitionProvider.deleteAcDefintion(compositionId); return createCommissioningResponse(compositionId, serviceTemplate); @@ -165,4 +162,49 @@ public class CommissioningProvider { private boolean verifyIfInstanceExists(UUID compositionId) { return !acProvider.getAcInstancesByCompositionId(compositionId).isEmpty(); } + + /** + * Composition Definition Priming. + * + * @param compositionId the compositionId + * @param acTypeStateUpdate the ACMTypeStateUpdate + */ + public void compositionDefinitionPriming(UUID compositionId, AcTypeStateUpdate acTypeStateUpdate) { + if (verifyIfInstanceExists(compositionId)) { + throw new PfModelRuntimeException(Status.BAD_REQUEST, "There are instances, Priming/Depriming not allowed"); + } + var acmDefinition = acDefinitionProvider.getAcDefinition(compositionId); + var stateOrdered = acTypeStateResolver.resolve(acTypeStateUpdate.getPrimeOrder(), acmDefinition.getState()); + switch (stateOrdered) { + case PRIME: + prime(acmDefinition); + break; + + case DEPRIME: + deprime(acmDefinition); + + break; + + default: + throw new PfModelRuntimeException(Status.BAD_REQUEST, "Not valid " + acTypeStateUpdate.getPrimeOrder()); + } + } + + private void prime(AutomationCompositionDefinition acmDefinition) { + var prearation = participantUpdatePublisher.prepareParticipantPriming(acmDefinition); + acDefinitionProvider.updateAcDefinition(acmDefinition); + participantUpdatePublisher.sendPriming(prearation, acmDefinition.getCompositionId(), null); + } + + private void deprime(AutomationCompositionDefinition acmDefinition) { + if (!AcTypeState.COMMISSIONED.equals(acmDefinition.getState())) { + for (var elementState : acmDefinition.getElementStateMap().values()) { + elementState.setState(AcTypeState.DEPRIMING); + } + acmDefinition.setState(AcTypeState.DEPRIMING); + acDefinitionProvider.updateAcDefinition(acmDefinition); + } + participantUpdatePublisher.sendDepriming(acmDefinition.getCompositionId()); + } + } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java index b7e7644ef..4949c6612 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java @@ -138,12 +138,13 @@ public class AutomationCompositionInstantiationProvider { private BeanValidationResult validateAutomationComposition(AutomationComposition automationComposition) { var result = new BeanValidationResult("AutomationComposition", automationComposition); - var serviceTemplate = acDefinitionProvider.findAcDefinition(automationComposition.getCompositionId()); - if (serviceTemplate.isEmpty()) { + var acDefinitionOpt = acDefinitionProvider.findAcDefinition(automationComposition.getCompositionId()); + if (acDefinitionOpt.isEmpty()) { result.addResult(new ObjectValidationResult("ServiceTemplate", "", ValidationStatus.INVALID, "Commissioned automation composition definition not found")); } else { - result.addResult(AcmUtils.validateAutomationComposition(automationComposition, serviceTemplate.get())); + result.addResult(AcmUtils.validateAutomationComposition(automationComposition, + acDefinitionOpt.get().getServiceTemplate())); } return result; } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java index 6d7ae7d4d..4799880db 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/CommissioningController.java @@ -100,7 +100,7 @@ public class CommissioningController extends AbstractRestController implements A @Override public ResponseEntity<Void> compositionDefinitionPriming(UUID compositionId, UUID requestId, @Valid AcTypeStateUpdate body) { - // TODO Auto-generated method stub - return null; + provider.compositionDefinitionPriming(compositionId, body); + return ResponseEntity.accepted().build(); } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java index 2c5d48717..2542bdb15 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java @@ -29,10 +29,9 @@ import javax.ws.rs.core.Response; import lombok.AllArgsConstructor; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionStateChangePublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionUpdatePublisher; -import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantUpdatePublisher; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionException; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; -import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementAck; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionState; import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils; @@ -69,27 +68,6 @@ public class SupervisionHandler { // Publishers for participant communication private final AutomationCompositionUpdatePublisher automationCompositionUpdatePublisher; private final AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher; - private final ParticipantUpdatePublisher participantUpdatePublisher; - - /** - * Send commissioning update message to dmaap. - * - * @param acmDefinition the AutomationComposition Definition - */ - public void handleSendCommissionMessage(AutomationCompositionDefinition acmDefinition) { - LOGGER.debug("Participant update message with serviveTemplate {} being sent to all participants", - acmDefinition.getCompositionId()); - participantUpdatePublisher.sendComissioningBroadcast(acmDefinition); - } - - /** - * Send decommissioning update message to dmaap. - * - */ - public void handleSendDeCommissionMessage(UUID compositionId) { - LOGGER.debug("Participant update message being sent {}", compositionId); - participantUpdatePublisher.sendDecomisioning(compositionId); - } /** * Handle a AutomationComposition update acknowledge message from a participant. @@ -110,10 +88,34 @@ public class SupervisionHandler { * * @param participantUpdateAckMessage the ParticipantUpdateAck message received from a participant */ - @MessageIntercept @Timed(value = "listener.participant_update_ack", description = "PARTICIPANT_UPDATE_ACK messages received") public void handleParticipantMessage(ParticipantUpdateAck participantUpdateAckMessage) { LOGGER.debug("Participant Update Ack message received {}", participantUpdateAckMessage); + var acDefinitionOpt = acDefinitionProvider.findAcDefinition(participantUpdateAckMessage.getCompositionId()); + if (acDefinitionOpt.isEmpty()) { + LOGGER.warn("AC Definition not found in database {}", participantUpdateAckMessage.getCompositionId()); + return; + } + var acDefinition = acDefinitionOpt.get(); + if (!AcTypeState.PRIMING.equals(acDefinition.getState()) + && !AcTypeState.DEPRIMING.equals(acDefinition.getState())) { + LOGGER.warn("AC Definition {} already primed/deprimed with participant {}", + participantUpdateAckMessage.getCompositionId(), participantUpdateAckMessage.getParticipantId()); + return; + } + var state = AcTypeState.PRIMING.equals(acDefinition.getState()) ? AcTypeState.PRIMED : AcTypeState.COMMISSIONED; + boolean completed = true; + for (var element : acDefinition.getElementStateMap().values()) { + if (participantUpdateAckMessage.getParticipantId().equals(element.getParticipantId())) { + element.setState(state); + } else if (!state.equals(element.getState())) { + completed = false; + } + } + if (completed) { + acDefinition.setState(state); + } + acDefinitionProvider.updateAcDefinition(acDefinition); } /** diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantUpdatePublisher.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantUpdatePublisher.java index e4bfedd9d..1915f1b0d 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantUpdatePublisher.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantUpdatePublisher.java @@ -24,16 +24,18 @@ package org.onap.policy.clamp.acm.runtime.supervision.comm; import io.micrometer.core.annotation.Timed; import java.time.Instant; -import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import lombok.AllArgsConstructor; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition; -import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantUpdate; -import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; import org.onap.policy.clamp.models.acm.utils.AcmUtils; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -47,72 +49,67 @@ public class ParticipantUpdatePublisher extends AbstractParticipantPublisher<Par private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantUpdatePublisher.class); - private final AcDefinitionProvider acDefinitionProvider; - - /** - * Send ParticipantUpdate to all Participants. - * - * @param acmDefinition the AutomationComposition Definition - */ - @Timed(value = "publisher.participant_update", description = "PARTICIPANT_UPDATE messages published") - public void sendComissioningBroadcast(AutomationCompositionDefinition acmDefinition) { - sendCommissioning(acmDefinition, null); - } + private final ParticipantProvider participantProvider; /** * Send ParticipantUpdate to Participant * if participantId is null then message is broadcast. * + * @param participantDefinitions the list of ParticipantDefinition to send + * @param compositionId the compositionId * @param participantId the ParticipantId */ @Timed(value = "publisher.participant_update", description = "PARTICIPANT_UPDATE messages published") - public void sendCommissioning(UUID participantId) { - var list = acDefinitionProvider.getAllAcDefinitions(); - if (list.isEmpty()) { - LOGGER.warn("No tosca service template found, cannot send participantupdate"); - } - for (var acmDefinition : list) { - sendCommissioning(acmDefinition, participantId); - } + public void sendPriming(List<ParticipantDefinition> participantDefinitions, UUID compositionId, + UUID participantId) { + var message = new ParticipantUpdate(); + message.setCompositionId(compositionId); + message.setParticipantId(participantId); + message.setTimestamp(Instant.now()); + message.setParticipantDefinitionUpdates(participantDefinitions); + LOGGER.debug("Participant Update sent {}", message); + super.send(message); } /** - * Send ParticipantUpdate to Participant - * if participantId is null then message is broadcast. + * Pepare the Priming message creating the list of ParticipantDefinition to send + * and fill the ElementState map of the AC Definition. * * @param acmDefinition the AutomationComposition Definition - * @param participantId the ParticipantId + * @return list of ParticipantDefinition */ - @Timed(value = "publisher.participant_update", description = "PARTICIPANT_UPDATE messages published") - public void sendCommissioning(AutomationCompositionDefinition acmDefinition, - UUID participantId) { - var message = new ParticipantUpdate(); - message.setCompositionId(acmDefinition.getCompositionId()); - message.setParticipantId(participantId); - message.setTimestamp(Instant.now()); - - var toscaServiceTemplate = acmDefinition.getServiceTemplate(); - List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>(); - for (var toscaInputEntry : toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().entrySet()) { - if (ParticipantUtils.checkIfNodeTemplateIsAutomationCompositionElement(toscaInputEntry.getValue(), - toscaServiceTemplate)) { - AcmUtils.prepareParticipantDefinitionUpdate( - participantId, - toscaInputEntry.getKey(), toscaInputEntry.getValue(), participantDefinitionUpdates); + public List<ParticipantDefinition> prepareParticipantPriming(AutomationCompositionDefinition acmDefinition) { + acmDefinition.setState(AcTypeState.PRIMING); + var acElements = AcmUtils.extractAcElementsFromServiceTemplate(acmDefinition.getServiceTemplate()); + Map<ToscaConceptIdentifier, UUID> supportedElementMap = new HashMap<>(); + if (AcTypeState.PRIMED.equals(acmDefinition.getState())) { + // scenario Prime again, participants already assigned + for (var elementEntry : acElements) { + var elementState = acmDefinition.getElementStateMap().get(elementEntry.getKey()); + elementState.setState(AcTypeState.PRIMING); + var type = new ToscaConceptIdentifier(elementEntry.getValue().getType(), + elementEntry.getValue().getTypeVersion()); + supportedElementMap.put(type, elementState.getParticipantId()); + } + } else { + // scenario Prime participants not assigned yet + supportedElementMap = participantProvider.getSupportedElementMap(); + for (var elementEntry : acElements) { + var elementState = acmDefinition.getElementStateMap().get(elementEntry.getKey()); + elementState.setState(AcTypeState.PRIMING); + var type = new ToscaConceptIdentifier(elementEntry.getValue().getType(), + elementEntry.getValue().getTypeVersion()); + elementState.setParticipantId(supportedElementMap.get(type)); } } - - // Commission the automation composition but sending participantdefinitions to participants - message.setParticipantDefinitionUpdates(participantDefinitionUpdates); - LOGGER.debug("Participant Update sent {}", message); - super.send(message); + return AcmUtils.prepareParticipantPriming(acElements, supportedElementMap); } /** * Send ParticipantUpdate to Participant after that commissioning has been removed. */ @Timed(value = "publisher.participant_update", description = "PARTICIPANT_UPDATE messages published") - public void sendDecomisioning(UUID compositionId) { + public void sendDepriming(UUID compositionId) { var message = new ParticipantUpdate(); message.setCompositionId(compositionId); message.setTimestamp(Instant.now()); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java index 6ecb8e6f2..071fc26fd 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/CommissioningProviderTest.java @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.runtime.commissioning; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -32,13 +33,16 @@ import java.util.List; import java.util.UUID; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; -import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantUpdatePublisher; +import org.onap.policy.clamp.acm.runtime.util.CommonTestData; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; -import org.onap.policy.clamp.models.acm.concepts.Participant; +import org.onap.policy.clamp.models.acm.messages.rest.commissioning.AcTypeStateUpdate; +import org.onap.policy.clamp.models.acm.messages.rest.commissioning.PrimeOrder; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.AcTypeStateResolver; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; -import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; class CommissioningProviderTest { @@ -51,16 +55,14 @@ class CommissioningProviderTest { @Test void testGetAutomationCompositionDefinitions() { var acProvider = mock(AutomationCompositionProvider.class); - var participantProvider = mock(ParticipantProvider.class); var acDefinitionProvider = mock(AcDefinitionProvider.class); - var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, participantProvider); + var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, null); var serviceTemplates = provider.getAutomationCompositionDefinitions(null, null); assertThat(serviceTemplates.getServiceTemplates()).isEmpty(); - when(acDefinitionProvider.getServiceTemplateList(null, null)) - .thenReturn(List.of(new ToscaServiceTemplate())); + when(acDefinitionProvider.getServiceTemplateList(null, null)).thenReturn(List.of(new ToscaServiceTemplate())); serviceTemplates = provider.getAutomationCompositionDefinitions(null, null); assertThat(serviceTemplates.getServiceTemplates()).hasSize(1); } @@ -81,16 +83,11 @@ class CommissioningProviderTest { var acDefinitionProvider = mock(AcDefinitionProvider.class); when(acDefinitionProvider.createAutomationCompositionDefinition(serviceTemplate)).thenReturn(acmDefinition); - var participantProvider = mock(ParticipantProvider.class); - when(participantProvider.getParticipants()).thenReturn(List.of(new Participant())); var acProvider = mock(AutomationCompositionProvider.class); - var supervisionHandler = mock(SupervisionHandler.class); - var provider = - new CommissioningProvider(acDefinitionProvider, acProvider, supervisionHandler, participantProvider); - var affectedDefinitions = provider - .createAutomationCompositionDefinition(serviceTemplate).getAffectedAutomationCompositionDefinitions(); + var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, null); + var affectedDefinitions = provider.createAutomationCompositionDefinition(serviceTemplate) + .getAffectedAutomationCompositionDefinitions(); verify(acDefinitionProvider).createAutomationCompositionDefinition(serviceTemplate); - verify(supervisionHandler).handleSendCommissionMessage(acmDefinition); // Response should return the number of node templates present in the service template assertThat(affectedDefinitions).hasSize(7); } @@ -104,10 +101,8 @@ class CommissioningProviderTest { void testGetToscaServiceTemplateList() { var acDefinitionProvider = mock(AcDefinitionProvider.class); var acProvider = mock(AutomationCompositionProvider.class); - var participantProvider = mock(ParticipantProvider.class); - var provider = - new CommissioningProvider(acDefinitionProvider, acProvider, null, participantProvider); + var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, null); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); when(acDefinitionProvider.getServiceTemplateList(null, null)).thenReturn(List.of(serviceTemplate)); @@ -120,12 +115,11 @@ class CommissioningProviderTest { void testDeletecDefinitionDabRequest() { var acDefinitionProvider = mock(AcDefinitionProvider.class); var acProvider = mock(AutomationCompositionProvider.class); - var participantProvider = mock(ParticipantProvider.class); var compositionId = UUID.randomUUID(); when(acProvider.getAcInstancesByCompositionId(compositionId)).thenReturn(List.of(new AutomationComposition())); - var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, participantProvider); + var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, null); assertThatThrownBy(() -> provider.deleteAutomationCompositionDefinition(compositionId)) .hasMessageMatching("Delete instances, to commission automation composition definitions"); @@ -133,22 +127,59 @@ class CommissioningProviderTest { @Test void testDeleteAutomationCompositionDefinition() { - var participantProvider = mock(ParticipantProvider.class); - when(participantProvider.getParticipants()).thenReturn(List.of(new Participant())); - var acDefinitionProvider = mock(AcDefinitionProvider.class); var compositionId = UUID.randomUUID(); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); when(acDefinitionProvider.deleteAcDefintion(compositionId)).thenReturn(serviceTemplate); + var acmDefinition = new AutomationCompositionDefinition(); + acmDefinition.setCompositionId(compositionId); + acmDefinition.setServiceTemplate(serviceTemplate); + acmDefinition.setState(AcTypeState.COMMISSIONED); + when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acmDefinition); + var acProvider = mock(AutomationCompositionProvider.class); - var supervisionHandler = mock(SupervisionHandler.class); - var provider = - new CommissioningProvider(acDefinitionProvider, acProvider, supervisionHandler, participantProvider); + var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, null); provider.deleteAutomationCompositionDefinition(compositionId); - verify(supervisionHandler).handleSendDeCommissionMessage(compositionId); verify(acDefinitionProvider).deleteAcDefintion(compositionId); } + + @Test + void testPriming() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var acmDefinition = CommonTestData.createAcDefinition( + InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.COMMISSIONED); + var compositionId = acmDefinition.getCompositionId(); + when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acmDefinition); + + var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); + var provider = new CommissioningProvider(acDefinitionProvider, mock(AutomationCompositionProvider.class), + new AcTypeStateResolver(), participantUpdatePublisher); + + var acTypeStateUpdate = new AcTypeStateUpdate(); + acTypeStateUpdate.setPrimeOrder(PrimeOrder.PRIME); + provider.compositionDefinitionPriming(compositionId, acTypeStateUpdate); + verify(acDefinitionProvider).updateAcDefinition(acmDefinition); + verify(participantUpdatePublisher).sendPriming(any(), any(), any()); + } + + @Test + void testDepriming() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var acmDefinition = CommonTestData.createAcDefinition( + InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMED); + var compositionId = acmDefinition.getCompositionId(); + when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acmDefinition); + + var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); + var provider = new CommissioningProvider(acDefinitionProvider, mock(AutomationCompositionProvider.class), + new AcTypeStateResolver(), participantUpdatePublisher); + + var acTypeStateUpdate = new AcTypeStateUpdate(); + acTypeStateUpdate.setPrimeOrder(PrimeOrder.DEPRIME); + provider.compositionDefinitionPriming(compositionId, acTypeStateUpdate); + verify(participantUpdatePublisher).sendDepriming(compositionId); + } } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java index 53fa945b2..73f3a687e 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/commissioning/rest/CommissioningControllerTest.java @@ -40,7 +40,9 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; +import org.onap.policy.clamp.models.acm.messages.rest.commissioning.AcTypeStateUpdate; import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse; +import org.onap.policy.clamp.models.acm.messages.rest.commissioning.PrimeOrder; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType; import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty; @@ -207,6 +209,16 @@ class CommissioningControllerTest extends CommonRestController { assertThat(templatesInDB).isEmpty(); } + @Test + void testPrimeBadRequest() { + var compositionId = createEntryInDB("Prime"); + var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/" + compositionId); + var body = new AcTypeStateUpdate(); + body.setPrimeOrder(PrimeOrder.PRIME); + var resp = invocationBuilder.put(Entity.json(body)); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + } + private UUID createEntryInDB(String name) { var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate); serviceTemplateCreate.setName(name); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java index cd6e021c5..0a46bc6b8 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProviderTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation. + * Copyright (C) 2021-2023 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,6 +37,7 @@ import org.mockito.Mockito; import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler; import org.onap.policy.clamp.acm.runtime.util.CommonTestData; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionException; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionState; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationCommand; @@ -90,8 +91,9 @@ class AutomationCompositionInstantiationProviderTest { when(participantProvider.getParticipants()).thenReturn(participants); var acDefinitionProvider = mock(AcDefinitionProvider.class); - var compositionId = UUID.randomUUID(); - when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(serviceTemplate)); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + var compositionId = acDefinition.getCompositionId(); + when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(acDefinition)); var supervisionHandler = mock(SupervisionHandler.class); var acProvider = mock(AutomationCompositionProvider.class); var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, supervisionHandler, @@ -203,8 +205,9 @@ class AutomationCompositionInstantiationProviderTest { @Test void testCreateAutomationCompositions_NoDuplicates() { var acDefinitionProvider = mock(AcDefinitionProvider.class); - var compositionId = UUID.randomUUID(); - when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(serviceTemplate)); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + var compositionId = acDefinition.getCompositionId(); + when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(acDefinition)); var automationCompositionCreate = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "NoDuplicates"); @@ -236,8 +239,9 @@ class AutomationCompositionInstantiationProviderTest { @Test void testCreateAutomationCompositions_CommissionedAcElementNotFound() { var acDefinitionProvider = mock(AcDefinitionProvider.class); - var compositionId = UUID.randomUUID(); - when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(serviceTemplate)); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + var compositionId = acDefinition.getCompositionId(); + when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(acDefinition)); var automationComposition = InstantiationUtils.getAutomationCompositionFromResource( AC_INSTANTIATION_DEFINITION_NAME_NOT_FOUND_JSON, "AcElementNotFound"); automationComposition.setCompositionId(compositionId); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java index aa8905917..c6535702b 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandlerTest.java @@ -20,7 +20,6 @@ package org.onap.policy.clamp.acm.runtime.supervision; -import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -39,9 +38,9 @@ import org.mockito.Mockito; import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionStateChangePublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionUpdatePublisher; -import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantUpdatePublisher; import org.onap.policy.clamp.acm.runtime.util.CommonTestData; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionException; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionOrderedState; @@ -52,7 +51,7 @@ import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantMe import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantUpdateAck; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; -import org.onap.policy.models.base.PfModelException; + class SupervisionHandlerTest { private static final String AC_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/acm/AutomationComposition.json"; @@ -102,8 +101,7 @@ class SupervisionHandlerTest { var automationCompositionProvider = mock(AutomationCompositionProvider.class); var handler = new SupervisionHandler(automationCompositionProvider, acDefinitionProvider, - mock(AutomationCompositionUpdatePublisher.class), automationCompositionStateChangePublisher, - mock(ParticipantUpdatePublisher.class)); + mock(AutomationCompositionUpdatePublisher.class), automationCompositionStateChangePublisher); handler.triggerAutomationCompositionSupervision(automationComposition); @@ -152,8 +150,7 @@ class SupervisionHandlerTest { var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); var handler = createSupervisionHandler(mock(AutomationCompositionProvider.class), mock(AutomationCompositionUpdatePublisher.class), automationCompositionStateChangePublisher, - mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE, - AutomationCompositionState.UNINITIALISED); + AutomationCompositionOrderedState.PASSIVE, AutomationCompositionState.UNINITIALISED); var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); @@ -197,8 +194,7 @@ class SupervisionHandlerTest { var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); var handler = createSupervisionHandler(mock(AutomationCompositionProvider.class), mock(AutomationCompositionUpdatePublisher.class), automationCompositionStateChangePublisher, - mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE, - AutomationCompositionState.UNINITIALISED); + AutomationCompositionOrderedState.PASSIVE, AutomationCompositionState.UNINITIALISED); var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); @@ -215,8 +211,7 @@ class SupervisionHandlerTest { var automationCompositionProvider = mock(AutomationCompositionProvider.class); var handler = createSupervisionHandler(automationCompositionProvider, mock(AutomationCompositionUpdatePublisher.class), mock(AutomationCompositionStateChangePublisher.class), - mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE, - AutomationCompositionState.UNINITIALISED); + AutomationCompositionOrderedState.PASSIVE, AutomationCompositionState.UNINITIALISED); var automationCompositionAckMessage = new AutomationCompositionAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK); automationCompositionAckMessage.setAutomationCompositionResultMap(Map.of()); @@ -237,8 +232,7 @@ class SupervisionHandlerTest { var automationCompositionProvider = mock(AutomationCompositionProvider.class); var handler = createSupervisionHandler(automationCompositionProvider, mock(AutomationCompositionUpdatePublisher.class), mock(AutomationCompositionStateChangePublisher.class), - mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE, - AutomationCompositionState.UNINITIALISED); + AutomationCompositionOrderedState.PASSIVE, AutomationCompositionState.UNINITIALISED); handler.handleAutomationCompositionUpdateAckMessage(automationCompositionAckMessage); @@ -246,48 +240,68 @@ class SupervisionHandlerTest { } @Test - void testParticipantUpdateAck() { + void testParticipantUpdateAckNotFound() { var participantUpdateAckMessage = new ParticipantUpdateAck(); participantUpdateAckMessage.setParticipantId(CommonTestData.getParticipantId()); participantUpdateAckMessage.setState(ParticipantState.ON_LINE); - var handler = createSupervisionHandler(mock(AutomationCompositionProvider.class), - mock(AutomationCompositionUpdatePublisher.class), mock(AutomationCompositionStateChangePublisher.class), - mock(ParticipantUpdatePublisher.class), AutomationCompositionOrderedState.PASSIVE, - AutomationCompositionState.UNINITIALISED); + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var handler = new SupervisionHandler(mock(AutomationCompositionProvider.class), acDefinitionProvider, + mock(AutomationCompositionUpdatePublisher.class), + mock(AutomationCompositionStateChangePublisher.class)); - assertThatCode(() -> handler.handleParticipantMessage(participantUpdateAckMessage)).doesNotThrowAnyException(); + handler.handleParticipantMessage(participantUpdateAckMessage); + verify(acDefinitionProvider).findAcDefinition(any()); } @Test - void testHandleSendCommissionMessage() { - var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); - var handler = createSupervisionHandler(mock(AutomationCompositionProvider.class), - mock(AutomationCompositionUpdatePublisher.class), mock(AutomationCompositionStateChangePublisher.class), - participantUpdatePublisher, AutomationCompositionOrderedState.PASSIVE, - AutomationCompositionState.UNINITIALISED); - var acmDefinition = new AutomationCompositionDefinition(); - handler.handleSendCommissionMessage(acmDefinition); + void testParticipantUpdateAckPrimed() { + var participantUpdateAckMessage = new ParticipantUpdateAck(); + participantUpdateAckMessage.setParticipantId(CommonTestData.getParticipantId()); + participantUpdateAckMessage.setState(ParticipantState.ON_LINE); + + var acDefinition = CommonTestData.createAcDefinition( + InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMED); + participantUpdateAckMessage.setCompositionId(acDefinition.getCompositionId()); + + var acDefinitionProvider = mock(AcDefinitionProvider.class); + when(acDefinitionProvider.findAcDefinition(acDefinition.getCompositionId())) + .thenReturn(Optional.of(acDefinition)); - verify(participantUpdatePublisher).sendComissioningBroadcast(acmDefinition); + var handler = new SupervisionHandler(mock(AutomationCompositionProvider.class), acDefinitionProvider, + mock(AutomationCompositionUpdatePublisher.class), + mock(AutomationCompositionStateChangePublisher.class)); + + handler.handleParticipantMessage(participantUpdateAckMessage); + verify(acDefinitionProvider).findAcDefinition(any()); } @Test - void testHandleSendDeCommissionMessage() throws PfModelException { - var participantUpdatePublisher = mock(ParticipantUpdatePublisher.class); - var handler = createSupervisionHandler(mock(AutomationCompositionProvider.class), - mock(AutomationCompositionUpdatePublisher.class), mock(AutomationCompositionStateChangePublisher.class), - participantUpdatePublisher, AutomationCompositionOrderedState.PASSIVE, - AutomationCompositionState.UNINITIALISED); - handler.handleSendDeCommissionMessage(IDENTIFIER); + void testParticipantUpdateAck() { + var participantUpdateAckMessage = new ParticipantUpdateAck(); + participantUpdateAckMessage.setParticipantId(CommonTestData.getParticipantId()); + participantUpdateAckMessage.setState(ParticipantState.ON_LINE); + + var acDefinition = CommonTestData.createAcDefinition( + InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMING); + participantUpdateAckMessage.setCompositionId(acDefinition.getCompositionId()); + + var acDefinitionProvider = mock(AcDefinitionProvider.class); + when(acDefinitionProvider.findAcDefinition(acDefinition.getCompositionId())) + .thenReturn(Optional.of(acDefinition)); - verify(participantUpdatePublisher).sendDecomisioning(IDENTIFIER); + var handler = new SupervisionHandler(mock(AutomationCompositionProvider.class), acDefinitionProvider, + mock(AutomationCompositionUpdatePublisher.class), + mock(AutomationCompositionStateChangePublisher.class)); + + handler.handleParticipantMessage(participantUpdateAckMessage); + verify(acDefinitionProvider).findAcDefinition(any()); + verify(acDefinitionProvider).updateAcDefinition(any()); } private SupervisionHandler createSupervisionHandler(AutomationCompositionProvider automationCompositionProvider, AutomationCompositionUpdatePublisher automationCompositionUpdatePublisher, AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher, - ParticipantUpdatePublisher participantUpdatePublisher, AutomationCompositionOrderedState orderedState, - AutomationCompositionState state) { + AutomationCompositionOrderedState orderedState, AutomationCompositionState state) { var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); @@ -306,21 +320,19 @@ class SupervisionHandlerTest { when(acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId())).thenReturn(acDefinition); return new SupervisionHandler(automationCompositionProvider, acDefinitionProvider, - automationCompositionUpdatePublisher, automationCompositionStateChangePublisher, - participantUpdatePublisher); + automationCompositionUpdatePublisher, automationCompositionStateChangePublisher); } private SupervisionHandler createSupervisionHandlerForTrigger() { return new SupervisionHandler(mock(AutomationCompositionProvider.class), mock(AcDefinitionProvider.class), - mock(AutomationCompositionUpdatePublisher.class), mock(AutomationCompositionStateChangePublisher.class), - mock(ParticipantUpdatePublisher.class)); + mock(AutomationCompositionUpdatePublisher.class), + mock(AutomationCompositionStateChangePublisher.class)); } private SupervisionHandler createSupervisionHandlerForTrigger( AutomationCompositionUpdatePublisher automationCompositionUpdatePublisher) { return new SupervisionHandler(mock(AutomationCompositionProvider.class), mock(AcDefinitionProvider.class), - automationCompositionUpdatePublisher, mock(AutomationCompositionStateChangePublisher.class), - mock(ParticipantUpdatePublisher.class)); + automationCompositionUpdatePublisher, mock(AutomationCompositionStateChangePublisher.class)); } } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java index 5ea3bea2c..d558deae3 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/comm/SupervisionMessagesTest.java @@ -25,16 +25,20 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler; import org.onap.policy.clamp.acm.runtime.supervision.SupervisionParticipantHandler; import org.onap.policy.clamp.acm.runtime.util.CommonTestData; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionState; @@ -46,9 +50,11 @@ import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantRe import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantRegisterAck; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantStatus; import org.onap.policy.clamp.models.acm.messages.dmaap.participant.ParticipantUpdateAck; -import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.TopicSink; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; class SupervisionMessagesTest { @@ -133,16 +139,28 @@ class SupervisionMessagesTest { @Test void testParticipantUpdatePublisherDecomisioning() { - var publisher = new ParticipantUpdatePublisher(mock(AcDefinitionProvider.class)); + var publisher = new ParticipantUpdatePublisher(mock(ParticipantProvider.class)); var topicSink = mock(TopicSink.class); publisher.active(List.of(topicSink)); - publisher.sendDecomisioning(UUID.randomUUID()); + publisher.sendDepriming(UUID.randomUUID()); verify(topicSink).send(anyString()); } @Test - void testParticipantUpdatePublisherComissioning() { - var publisher = new ParticipantUpdatePublisher(mock(AcDefinitionProvider.class)); + void testParticipantUpdatePublisherPriming() { + var participantId = UUID.randomUUID(); + Map<ToscaConceptIdentifier, UUID> supportedElementMap = new HashMap<>(); + supportedElementMap.put( + new ToscaConceptIdentifier("org.onap.policy.clamp.acm.PolicyAutomationCompositionElement", "1.0.1"), + participantId); + supportedElementMap.put(new ToscaConceptIdentifier( + "org.onap.policy.clamp.acm.K8SMicroserviceAutomationCompositionElement", "1.0.1"), participantId); + supportedElementMap.put( + new ToscaConceptIdentifier("org.onap.policy.clamp.acm.HttpAutomationCompositionElement", "1.0.1"), + participantId); + var participantProvider = mock(ParticipantProvider.class); + when(participantProvider.getSupportedElementMap()).thenReturn(supportedElementMap); + var publisher = new ParticipantUpdatePublisher(participantProvider); var topicSink = mock(TopicSink.class); publisher.active(List.of(topicSink)); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); @@ -151,7 +169,10 @@ class SupervisionMessagesTest { var acmDefinition = new AutomationCompositionDefinition(); acmDefinition.setCompositionId(UUID.randomUUID()); acmDefinition.setServiceTemplate(serviceTemplate); - publisher.sendComissioningBroadcast(acmDefinition); + var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate); + acmDefinition.setElementStateMap(AcmUtils.createElementStateMap(acElements, AcTypeState.COMMISSIONED)); + var preparation = publisher.prepareParticipantPriming(acmDefinition); + publisher.sendPriming(preparation, acmDefinition.getCompositionId(), null); verify(topicSink).send(anyString()); } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java index b99140914..702a93678 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/CommonTestData.java @@ -25,11 +25,15 @@ import java.util.UUID; import javax.ws.rs.core.Response.Status; import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition; import org.onap.policy.clamp.models.acm.concepts.Participant; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; /** * Class to hold/create all parameters for test cases. @@ -37,8 +41,7 @@ import org.onap.policy.common.utils.resources.ResourceUtils; */ public class CommonTestData { private static final Coder CODER = new StandardCoder(); - public static final String TOSCA_SERVICE_TEMPLATE_YAML = - "clamp/acm/pmsh/funtional-pmsh-usecase.yaml"; + public static final String TOSCA_SERVICE_TEMPLATE_YAML = "clamp/acm/pmsh/funtional-pmsh-usecase.yaml"; /** * Gets the standard automation composition parameters. @@ -53,7 +56,7 @@ public class CommonTestData { } catch (CoderException e) { throw new AutomationCompositionRuntimeException(Status.NOT_ACCEPTABLE, - "cannot read automation composition parameters", e); + "cannot read automation composition parameters", e); } } @@ -65,7 +68,7 @@ public class CommonTestData { */ public static String getParameterGroupAsString(final String dbName) { return ResourceUtils.getResourceAsString("src/test/resources/parameters/TestParameters.json") - .replace("${dbName}", "jdbc:h2:mem:" + dbName); + .replace("${dbName}", "jdbc:h2:mem:" + dbName); } /** @@ -95,4 +98,23 @@ public class CommonTestData { public static UUID getParticipantId() { return UUID.fromString("101c62b3-8918-41b9-a747-d21eb79c6c03"); } + + /** + * Create a new AutomationCompositionDefinition. + * + * @param serviceTemplate the serviceTemplate + * @param state the AcTypeState + * @return a new AutomationCompositionDefinition + */ + public static AutomationCompositionDefinition createAcDefinition(ToscaServiceTemplate serviceTemplate, + AcTypeState state) { + var acDefinition = new AutomationCompositionDefinition(); + acDefinition.setCompositionId(UUID.randomUUID()); + acDefinition.setState(state); + acDefinition.setServiceTemplate(serviceTemplate); + var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate); + acDefinition.setElementStateMap(AcmUtils.createElementStateMap(acElements, state)); + return acDefinition; + } + } |