diff options
147 files changed, 4891 insertions, 1864 deletions
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationComposition.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationComposition.java index eb5b6dc9b..61610bb47 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationComposition.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationComposition.java @@ -44,7 +44,7 @@ public class AutomationComposition extends ToscaEntity implements Comparable<Aut private UUID compositionTargetId; - private Boolean restarting; + private Boolean precheck; @NonNull private DeployState deployState = DeployState.UNDEPLOYED; @@ -56,6 +56,9 @@ public class AutomationComposition extends ToscaEntity implements Comparable<Aut private Integer phase; + @NonNull + private SubState subState = SubState.NONE; + private Map<UUID, AutomationCompositionElement> elements; private StateChangeResult stateChangeResult; @@ -70,11 +73,12 @@ public class AutomationComposition extends ToscaEntity implements Comparable<Aut this.instanceId = otherAutomationComposition.instanceId; this.compositionId = otherAutomationComposition.compositionId; this.compositionTargetId = otherAutomationComposition.compositionTargetId; - this.restarting = otherAutomationComposition.restarting; + this.precheck = otherAutomationComposition.precheck; this.deployState = otherAutomationComposition.deployState; this.lockState = otherAutomationComposition.lockState; this.lastMsg = otherAutomationComposition.lastMsg; this.phase = otherAutomationComposition.phase; + this.subState = otherAutomationComposition.subState; this.elements = PfUtils.mapMap(otherAutomationComposition.elements, AutomationCompositionElement::new); this.stateChangeResult = otherAutomationComposition.stateChangeResult; } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionDefinition.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionDefinition.java index 987cb8832..57b6837af 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionDefinition.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionDefinition.java @@ -41,8 +41,6 @@ public class AutomationCompositionDefinition { @NonNull private ToscaServiceTemplate serviceTemplate; - private Boolean restarting; - @NonNull private AcTypeState state; @@ -63,7 +61,6 @@ public class AutomationCompositionDefinition { public AutomationCompositionDefinition(final AutomationCompositionDefinition otherAcmDefinition) { this.compositionId = otherAcmDefinition.compositionId; this.serviceTemplate = new ToscaServiceTemplate(otherAcmDefinition.serviceTemplate); - this.restarting = otherAcmDefinition.restarting; this.state = otherAcmDefinition.state; this.lastMsg = otherAcmDefinition.lastMsg; this.elementStateMap = PfUtils.mapMap(otherAcmDefinition.elementStateMap, NodeTemplateState::new); diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionElement.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionElement.java index 5afa7e0bb..7d3acaa52 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionElement.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositionElement.java @@ -55,6 +55,11 @@ public class AutomationCompositionElement { @NonNull private LockState lockState = LockState.LOCKED; + @NonNull + private SubState subState = SubState.NONE; + + private Integer stage; + private String operationalState; private String useState; private String description; @@ -81,8 +86,10 @@ public class AutomationCompositionElement { this.restarting = otherElement.restarting; this.deployState = otherElement.deployState; this.lockState = otherElement.lockState; + this.subState = otherElement.subState; this.operationalState = otherElement.operationalState; this.useState = otherElement.useState; + this.stage = otherElement.stage; this.message = otherElement.message; } } 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 d6079d0e7..9c827d701 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 @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation. + * Copyright (C) 2021-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,11 @@ package org.onap.policy.clamp.models.acm.concepts; +import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; @@ -50,8 +54,26 @@ public final class ParticipantUtils { } return DeployState.DEPLOYING.equals(automationComposition.getDeployState()) - || LockState.UNLOCKING.equals(automationComposition.getLockState()) ? minStartPhase - : maxStartPhase; + || LockState.UNLOCKING.equals(automationComposition.getLockState()) ? minStartPhase : maxStartPhase; + } + + /** + * Get the First Stage. + * + * @param automationComposition the automation composition + * @param toscaServiceTemplate the ToscaServiceTemplate + * @return the First stage + */ + public static int getFirstStage( + AutomationComposition automationComposition, ToscaServiceTemplate toscaServiceTemplate) { + Set<Integer> minStage = new HashSet<>(); + for (var element : automationComposition.getElements().values()) { + var toscaNodeTemplate = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates() + .get(element.getDefinition().getName()); + var stage = ParticipantUtils.findStageSet(toscaNodeTemplate.getProperties()); + minStage.addAll(stage); + } + return minStage.stream().min(Integer::compare).orElse(0); } /** @@ -63,8 +85,25 @@ public final class ParticipantUtils { public static int findStartPhase(Map<String, Object> properties) { var objStartPhase = properties.get("startPhase"); if (objStartPhase != null) { - return Integer.valueOf(objStartPhase.toString()); + return Integer.parseInt(objStartPhase.toString()); } return 0; } + + + /** + * Finds stage from a map of properties. + * + * @param properties Map of properties + * @return stage + */ + public static Set<Integer> findStageSet(Map<String, Object> properties) { + var objStage = properties.get("stage"); + if (objStage instanceof List<?> stageSet) { + return stageSet.stream() + .map(obj -> Integer.valueOf(obj.toString())) + .collect(Collectors.toSet()); + } + return Set.of(0); + } } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/SubState.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/SubState.java new file mode 100644 index 000000000..5f979c50f --- /dev/null +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/SubState.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.models.acm.concepts; + +public enum SubState { + NONE, + MIGRATION_PRECHECKING, + PREPARING, + REVIEWING +} diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionDeployAck.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionDeployAck.java index 2c7d51fe7..9807ff9ca 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionDeployAck.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionDeployAck.java @@ -41,7 +41,7 @@ import org.onap.policy.models.base.PfUtils; public class AutomationCompositionDeployAck extends ParticipantAckMessage { private UUID automationCompositionId; - private Integer startPhase; + private Integer stage; // A map with AutomationCompositionElementID as its key, and a pair of result and message as value per // AutomationCompositionElement. @@ -63,7 +63,7 @@ public class AutomationCompositionDeployAck extends ParticipantAckMessage { public AutomationCompositionDeployAck(final AutomationCompositionDeployAck source) { super(source); this.automationCompositionId = source.automationCompositionId; - this.startPhase = source.startPhase; + this.stage = source.stage; this.automationCompositionResultMap = PfUtils.mapMap(source.automationCompositionResultMap, UnaryOperator.identity()); } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionMigration.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionMigration.java index fb1f1925c..2d7608afd 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionMigration.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionMigration.java @@ -37,6 +37,9 @@ public class AutomationCompositionMigration extends ParticipantMessage { // A list of updates to AC element properties private List<ParticipantDeploy> participantUpdatesList = new ArrayList<>(); + private Boolean precheck = false; + private Integer stage = 0; + public AutomationCompositionMigration() { super(ParticipantMessageType.AUTOMATION_COMPOSITION_MIGRATION); } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantRestart.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionPrepare.java index ff9755ec1..343143eed 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantRestart.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/AutomationCompositionPrepare.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. + * Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,38 +25,23 @@ import java.util.List; import lombok.Getter; import lombok.Setter; import lombok.ToString; -import org.onap.policy.clamp.models.acm.concepts.AcTypeState; -import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition; -import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc; +import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy; import org.onap.policy.models.base.PfUtils; @Getter @Setter @ToString(callSuper = true) -public class ParticipantRestart extends ParticipantMessage { +public class AutomationCompositionPrepare extends ParticipantMessage { - // composition state - private AcTypeState state; - - // element definition - private List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>(); - - // automation composition instances list - private List<ParticipantRestartAc> automationcompositionList = new ArrayList<>(); + private List<ParticipantDeploy> participantList = new ArrayList<>(); + private boolean preDeploy = true; /** - * Constructor. - */ - public ParticipantRestart() { - super(ParticipantMessageType.PARTICIPANT_RESTART); - } - - /** - * Constructor with message type. - * @param messageType messageType + * Constructor for instantiating class with message name. + * */ - public ParticipantRestart(ParticipantMessageType messageType) { - super(messageType); + public AutomationCompositionPrepare() { + super(ParticipantMessageType.AUTOMATION_COMPOSITION_PREPARE); } /** @@ -64,11 +49,9 @@ public class ParticipantRestart extends ParticipantMessage { * * @param source source from which to copy */ - public ParticipantRestart(ParticipantRestart source) { + public AutomationCompositionPrepare(AutomationCompositionPrepare source) { super(source); - this.state = source.state; - this.participantDefinitionUpdates = - PfUtils.mapList(source.participantDefinitionUpdates, ParticipantDefinition::new); - this.automationcompositionList = PfUtils.mapList(source.automationcompositionList, ParticipantRestartAc::new); + this.preDeploy = source.preDeploy; + this.participantList = PfUtils.mapList(source.participantList, ParticipantDeploy::new); } } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantMessageType.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantMessageType.java index e6e42e851..7e19f6f79 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantMessageType.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantMessageType.java @@ -115,5 +115,10 @@ public enum ParticipantMessageType { /** * Used by runtime to send composition and instances to sync participant replicas. */ - PARTICIPANT_SYNC_MSG + PARTICIPANT_SYNC_MSG, + + /** + * Used by the acm runtime to ask for a preparation check to participants. + */ + AUTOMATION_COMPOSITION_PREPARE } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantSync.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantSync.java index 962b6137c..85b715b86 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantSync.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantSync.java @@ -20,17 +20,32 @@ package org.onap.policy.clamp.models.acm.messages.kafka.participant; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.UUID; import lombok.Getter; import lombok.Setter; import lombok.ToString; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition; +import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc; +import org.onap.policy.models.base.PfUtils; @Getter @Setter @ToString(callSuper = true) -public class ParticipantSync extends ParticipantRestart { +public class ParticipantSync extends ParticipantMessage { + + // composition state + private AcTypeState state; + + // element definition + private List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>(); + + // automation composition instances list + private List<ParticipantRestartAc> automationcompositionList = new ArrayList<>(); private Set<UUID> excludeReplicas = new HashSet<>(); private boolean restarting = false; @@ -50,6 +65,10 @@ public class ParticipantSync extends ParticipantRestart { */ public ParticipantSync(ParticipantSync source) { super(source); + this.state = source.state; + this.participantDefinitionUpdates = + PfUtils.mapList(source.participantDefinitionUpdates, ParticipantDefinition::new); + this.automationcompositionList = PfUtils.mapList(source.automationcompositionList, ParticipantRestartAc::new); this.excludeReplicas = new HashSet<>(source.excludeReplicas); this.restarting = source.restarting; this.delete = source.delete; diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/GenericNameVersion.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/GenericNameVersion.java deleted file mode 100644 index 3e39e970d..000000000 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/GenericNameVersion.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.clamp.models.acm.messages.rest; - -import lombok.Data; - -@Data -public class GenericNameVersion { - - private String name; - - private String version; -} diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/AcInstanceStateUpdate.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/AcInstanceStateUpdate.java index e47947a02..68c597b32 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/AcInstanceStateUpdate.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/AcInstanceStateUpdate.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2022 Nordix Foundation. + * Copyright (C) 2021-2022,2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,4 +26,5 @@ import lombok.Data; public class AcInstanceStateUpdate { private DeployOrder deployOrder; private LockOrder lockOrder; + private SubOrder subOrder; } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/SubOrder.java b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/SubOrder.java new file mode 100644 index 000000000..9cf7efaa6 --- /dev/null +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/instantiation/SubOrder.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.models.acm.messages.rest.instantiation; + +public enum SubOrder { + NONE, + MIGRATE_PRECHECK, + PREPARE, + REVIEW +} diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationComposition.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationComposition.java index 355fcaff0..001f2e7f3 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationComposition.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationComposition.java @@ -45,6 +45,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; 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.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.utils.TimestampHelper; import org.onap.policy.common.parameters.annotations.NotNull; import org.onap.policy.common.parameters.annotations.Valid; @@ -86,9 +87,6 @@ public class JpaAutomationComposition extends Validated private String compositionTargetId; @Column - private Boolean restarting; - - @Column @NotNull private DeployState deployState; @@ -97,6 +95,10 @@ public class JpaAutomationComposition extends Validated private LockState lockState; @Column + @NotNull + private SubState subState; + + @Column private StateChangeResult stateChangeResult; @Column @@ -119,7 +121,7 @@ public class JpaAutomationComposition extends Validated */ public JpaAutomationComposition() { this(UUID.randomUUID().toString(), new PfConceptKey(), UUID.randomUUID().toString(), new ArrayList<>(), - DeployState.UNDEPLOYED, LockState.NONE); + DeployState.UNDEPLOYED, LockState.NONE, SubState.NONE); } /** @@ -131,10 +133,12 @@ public class JpaAutomationComposition extends Validated * @param elements the elements of the automation composition in participants * @param deployState the Deploy State * @param lockState the Lock State + * @param subState the Sub State */ public JpaAutomationComposition(@NonNull final String instanceId, @NonNull final PfConceptKey key, @NonNull final String compositionId, @NonNull final List<JpaAutomationCompositionElement> elements, - @NonNull final DeployState deployState, @NonNull final LockState lockState) { + @NonNull final DeployState deployState, @NonNull final LockState lockState, + @NonNull final SubState subState) { this.instanceId = instanceId; this.name = key.getName(); this.version = key.getVersion(); @@ -142,6 +146,7 @@ public class JpaAutomationComposition extends Validated this.deployState = deployState; this.lockState = lockState; this.elements = elements; + this.subState = subState; } /** @@ -155,11 +160,11 @@ public class JpaAutomationComposition extends Validated this.version = copyConcept.version; this.compositionId = copyConcept.compositionId; this.compositionTargetId = copyConcept.compositionTargetId; - this.restarting = copyConcept.restarting; this.deployState = copyConcept.deployState; this.lockState = copyConcept.lockState; this.lastMsg = copyConcept.lastMsg; this.phase = copyConcept.phase; + this.subState = copyConcept.subState; this.description = copyConcept.description; this.stateChangeResult = copyConcept.stateChangeResult; this.elements = PfUtils.mapList(copyConcept.elements, JpaAutomationCompositionElement::new); @@ -185,11 +190,11 @@ public class JpaAutomationComposition extends Validated if (compositionTargetId != null) { automationComposition.setCompositionTargetId(UUID.fromString(compositionTargetId)); } - automationComposition.setRestarting(restarting); automationComposition.setDeployState(deployState); automationComposition.setLockState(lockState); automationComposition.setLastMsg(lastMsg.toString()); automationComposition.setPhase(phase); + automationComposition.setSubState(subState); automationComposition.setDescription(description); automationComposition.setStateChangeResult(stateChangeResult); automationComposition.setElements(new LinkedHashMap<>(this.elements.size())); @@ -225,11 +230,11 @@ public class JpaAutomationComposition extends Validated if (automationComposition.getCompositionTargetId() != null) { this.compositionTargetId = automationComposition.getCompositionTargetId().toString(); } - this.restarting = automationComposition.getRestarting(); this.deployState = automationComposition.getDeployState(); this.lockState = automationComposition.getLockState(); this.lastMsg = TimestampHelper.toTimestamp(automationComposition.getLastMsg()); this.phase = automationComposition.getPhase(); + this.subState = automationComposition.getSubState(); this.description = automationComposition.getDescription(); this.stateChangeResult = automationComposition.getStateChangeResult(); } @@ -278,17 +283,17 @@ public class JpaAutomationComposition extends Validated return result; } - result = ObjectUtils.compare(restarting, other.restarting); + result = ObjectUtils.compare(deployState, other.deployState); if (result != 0) { return result; } - result = ObjectUtils.compare(deployState, other.deployState); + result = ObjectUtils.compare(lockState, other.lockState); if (result != 0) { return result; } - result = ObjectUtils.compare(lockState, other.lockState); + result = ObjectUtils.compare(subState, other.subState); if (result != 0) { return result; } 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 1cab89d5d..3d61c4ed9 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 @@ -79,9 +79,6 @@ public class JpaAutomationCompositionDefinition extends Validated private String version; @Column - private Boolean restarting; - - @Column @NotNull private AcTypeState state; @@ -107,7 +104,6 @@ public class JpaAutomationCompositionDefinition extends Validated public AutomationCompositionDefinition toAuthorative() { var acmDefinition = new AutomationCompositionDefinition(); acmDefinition.setCompositionId(UUID.fromString(this.compositionId)); - acmDefinition.setRestarting(this.restarting); acmDefinition.setState(this.state); acmDefinition.setStateChangeResult(this.stateChangeResult); acmDefinition.setLastMsg(this.lastMsg.toString()); @@ -122,7 +118,6 @@ public class JpaAutomationCompositionDefinition extends Validated @Override public void fromAuthorative(final AutomationCompositionDefinition copyConcept) { this.compositionId = copyConcept.getCompositionId().toString(); - this.restarting = copyConcept.getRestarting(); this.state = copyConcept.getState(); this.stateChangeResult = copyConcept.getStateChangeResult(); this.lastMsg = TimestampHelper.toTimestamp(copyConcept.getLastMsg()); diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionElement.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionElement.java index 74426a747..e511ba1fc 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionElement.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionElement.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation. + * Copyright (C) 2021-2024 Nordix Foundation. * ================================================================================ * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ @@ -42,6 +42,7 @@ import org.apache.commons.lang3.ObjectUtils; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; 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.concepts.SubState; import org.onap.policy.common.parameters.annotations.NotNull; import org.onap.policy.common.parameters.annotations.Valid; import org.onap.policy.models.base.PfAuthorative; @@ -94,12 +95,19 @@ public class JpaAutomationCompositionElement extends Validated private LockState lockState; @Column + @NotNull + private SubState subState; + + @Column private String operationalState; @Column private String useState; @Column + private Integer stage; + + @Column private String description; @Column @@ -134,7 +142,7 @@ public class JpaAutomationCompositionElement extends Validated */ public JpaAutomationCompositionElement(@NonNull final String elementId, @NonNull final String instanceId) { this(elementId, instanceId, new PfConceptKey(), - DeployState.UNDEPLOYED, LockState.LOCKED); + DeployState.UNDEPLOYED, LockState.NONE, SubState.NONE); } /** @@ -145,15 +153,18 @@ public class JpaAutomationCompositionElement extends Validated * @param definition the TOSCA definition of the automation composition element * @param deployState the Deploy State of the automation composition * @param lockState the Lock State of the automation composition + * @param subState the Sub State of the automation composition */ public JpaAutomationCompositionElement(@NonNull final String elementId, @NonNull final String instanceId, @NonNull final PfConceptKey definition, - @NonNull final DeployState deployState, @NonNull final LockState lockState) { + @NonNull final DeployState deployState, @NonNull final LockState lockState, + @NonNull final SubState subState) { this.elementId = elementId; this.instanceId = instanceId; this.definition = definition; this.deployState = deployState; this.lockState = lockState; + this.subState = subState; } /** @@ -174,8 +185,10 @@ public class JpaAutomationCompositionElement extends Validated this.restarting = copyConcept.restarting; this.deployState = copyConcept.deployState; this.lockState = copyConcept.lockState; + this.subState = copyConcept.subState; this.operationalState = copyConcept.operationalState; this.useState = copyConcept.useState; + this.stage = copyConcept.stage; this.message = copyConcept.message; } @@ -201,8 +214,10 @@ public class JpaAutomationCompositionElement extends Validated element.setRestarting(restarting); element.setDeployState(deployState); element.setLockState(lockState); + element.setSubState(subState); element.setOperationalState(operationalState); element.setUseState(useState); + element.setStage(stage); element.setMessage(message); return element; @@ -218,8 +233,10 @@ public class JpaAutomationCompositionElement extends Validated this.restarting = element.getRestarting(); this.deployState = element.getDeployState(); this.lockState = element.getLockState(); + this.subState = element.getSubState(); this.operationalState = element.getOperationalState(); this.useState = element.getUseState(); + this.stage = element.getStage(); this.message = element.getMessage(); } @@ -267,11 +284,21 @@ public class JpaAutomationCompositionElement extends Validated return result; } + result = ObjectUtils.compare(subState, other.subState); + if (result != 0) { + return result; + } + result = ObjectUtils.compare(useState, other.useState); if (result != 0) { return result; } + result = ObjectUtils.compare(stage, other.stage); + if (result != 0) { + return result; + } + result = ObjectUtils.compare(operationalState, other.operationalState); if (result != 0) { return result; 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 46b43f950..bb05c46c6 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 @@ -138,10 +138,8 @@ public class AcDefinitionProvider { * @param compositionId The UUID of the automation composition definition to update * @param state the AcTypeState * @param stateChangeResult the StateChangeResult - * @param restarting restarting process */ - public void updateAcDefinitionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult, - Boolean restarting) { + public void updateAcDefinitionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult) { var jpaUpdate = acmDefinitionRepository.findById(compositionId.toString()); if (jpaUpdate.isEmpty()) { String errorMessage = "update of Automation Composition Definition \"" + compositionId @@ -151,7 +149,6 @@ public class AcDefinitionProvider { var acDefinition = jpaUpdate.get(); acDefinition.setState(state); acDefinition.setStateChangeResult(stateChangeResult); - acDefinition.setRestarting(restarting); acmDefinitionRepository.save(acDefinition); acmDefinitionRepository.flush(); } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolver.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolver.java index ace246c5d..7bffdd966 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolver.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolver.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,8 +23,10 @@ package org.onap.policy.clamp.models.acm.persistence.provider; 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.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.SubOrder; import org.onap.policy.clamp.models.acm.utils.StateDefinition; import org.springframework.stereotype.Component; @@ -39,6 +41,8 @@ public class AcInstanceStateResolver { private static final String UPDATING = DeployState.UPDATING.name(); private static final String DELETING = DeployState.DELETING.name(); private static final String MIGRATING = DeployState.MIGRATING.name(); + private static final String MIGRATION_PRECHECKING = SubState.MIGRATION_PRECHECKING.name(); + private static final String SUB_STATE_NONE = SubState.NONE.name(); private static final String LOCKED = LockState.LOCKED.name(); private static final String LOCKING = LockState.LOCKING.name(); @@ -48,6 +52,7 @@ public class AcInstanceStateResolver { private static final String DEPLOY_NONE = DeployOrder.NONE.name(); private static final String LOCK_NONE = LockOrder.NONE.name(); + private static final String SUB_NONE = SubOrder.NONE.name(); private static final String NO_ERROR = StateChangeResult.NO_ERROR.name(); private static final String FAILED = StateChangeResult.FAILED.name(); @@ -60,55 +65,105 @@ public class AcInstanceStateResolver { public static final String LOCK = LockOrder.LOCK.name(); public static final String UNLOCK = LockOrder.UNLOCK.name(); public static final String MIGRATE = DeployOrder.MIGRATE.name(); + public static final String MIGRATE_PRECHECK = SubOrder.MIGRATE_PRECHECK.name(); + public static final String PREPARE = SubOrder.PREPARE.name(); + public static final String REVIEW = SubOrder.REVIEW.name(); + public static final String UPDATE = DeployOrder.UPDATE.name(); public static final String NONE = "NONE"; /** * Construct. */ public AcInstanceStateResolver() { - this.graph = new StateDefinition<>(5, NONE); - - // no error - this.graph.put(new String[] {DEPLOY, LOCK_NONE, UNDEPLOYED, STATE_LOCKED_NONE, NO_ERROR}, DEPLOY); - this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, DEPLOYED, LOCKED, NO_ERROR}, UNDEPLOY); - this.graph.put(new String[] {DELETE, LOCK_NONE, UNDEPLOYED, LOCK_NONE, NO_ERROR}, DELETE); - this.graph.put(new String[] {DEPLOY_NONE, UNLOCK, DEPLOYED, LOCKED, NO_ERROR}, UNLOCK); - this.graph.put(new String[] {DEPLOY_NONE, LOCK, DEPLOYED, UNLOCKED, NO_ERROR}, LOCK); - this.graph.put(new String[] {MIGRATE, LOCK_NONE, DEPLOYED, LOCKED, NO_ERROR}, MIGRATE); - - // failed - this.graph.put(new String[] {DEPLOY, LOCK_NONE, UNDEPLOYING, STATE_LOCKED_NONE, FAILED}, DEPLOY); - this.graph.put(new String[] {DEPLOY, LOCK_NONE, DEPLOYING, STATE_LOCKED_NONE, FAILED}, DEPLOY); - - this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, UNDEPLOYING, STATE_LOCKED_NONE, FAILED}, UNDEPLOY); - this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, UPDATING, LOCKED, FAILED}, UNDEPLOY); - this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, MIGRATING, LOCKED, FAILED}, UNDEPLOY); - this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, DEPLOYING, STATE_LOCKED_NONE, FAILED}, UNDEPLOY); - - this.graph.put(new String[] {DELETE, LOCK_NONE, DELETING, LOCK_NONE, FAILED}, DELETE); - - this.graph.put(new String[] {DEPLOY_NONE, UNLOCK, DEPLOYED, LOCKING, FAILED}, UNLOCK); - this.graph.put(new String[] {DEPLOY_NONE, UNLOCK, DEPLOYED, UNLOCKING, FAILED}, UNLOCK); - - this.graph.put(new String[] {DEPLOY_NONE, LOCK, DEPLOYED, LOCKING, FAILED}, LOCK); - this.graph.put(new String[] {DEPLOY_NONE, LOCK, DEPLOYED, UNLOCKING, FAILED}, LOCK); + this.graph = new StateDefinition<>(7, NONE); + + // make an order when there are no fails + this.graph.put(new String[] {DEPLOY, LOCK_NONE, SUB_NONE, + UNDEPLOYED, STATE_LOCKED_NONE, SUB_STATE_NONE, NO_ERROR}, DEPLOY); + this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE, + DEPLOYED, LOCKED, SUB_STATE_NONE, NO_ERROR}, UNDEPLOY); + this.graph.put(new String[] {DELETE, LOCK_NONE, SUB_NONE, + UNDEPLOYED, LOCK_NONE, SUB_STATE_NONE, NO_ERROR}, DELETE); + this.graph.put(new String[] {DEPLOY_NONE, UNLOCK, SUB_NONE, + DEPLOYED, LOCKED, SUB_STATE_NONE, NO_ERROR}, UNLOCK); + this.graph.put(new String[] {DEPLOY_NONE, LOCK, SUB_NONE, + DEPLOYED, UNLOCKED, SUB_STATE_NONE, NO_ERROR}, LOCK); + this.graph.put(new String[] {MIGRATE, LOCK_NONE, SUB_NONE, + DEPLOYED, LOCKED, SUB_STATE_NONE, NO_ERROR}, MIGRATE); + this.graph.put(new String[] {UPDATE, LOCK_NONE, SUB_NONE, + DEPLOYED, LOCKED, SUB_STATE_NONE, NO_ERROR}, UPDATE); + this.graph.put(new String[] {DEPLOY_NONE, LOCK_NONE, REVIEW, + DEPLOYED, LOCKED, SUB_STATE_NONE, NO_ERROR}, REVIEW); + this.graph.put(new String[] {DEPLOY_NONE, LOCK_NONE, PREPARE, + UNDEPLOYED, STATE_LOCKED_NONE, SUB_STATE_NONE, NO_ERROR}, PREPARE); + this.graph.put(new String[] {DEPLOY_NONE, LOCK_NONE, MIGRATE_PRECHECK, + DEPLOYED, LOCKED, SUB_STATE_NONE, NO_ERROR}, MIGRATE_PRECHECK); + + // make an order in a failed scenario + this.graph.put(new String[] {DEPLOY, LOCK_NONE, SUB_NONE, + UNDEPLOYING, STATE_LOCKED_NONE, SUB_STATE_NONE, FAILED}, DEPLOY); + this.graph.put(new String[] {DEPLOY, LOCK_NONE, SUB_NONE, + DEPLOYING, STATE_LOCKED_NONE, SUB_STATE_NONE, FAILED}, DEPLOY); + + this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE, + UNDEPLOYING, STATE_LOCKED_NONE, SUB_STATE_NONE, FAILED}, UNDEPLOY); + this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE, + UPDATING, LOCKED, SUB_STATE_NONE, FAILED}, UNDEPLOY); + this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE, + MIGRATING, LOCKED, SUB_STATE_NONE, FAILED}, UNDEPLOY); + this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE, + DEPLOYING, STATE_LOCKED_NONE, SUB_STATE_NONE, FAILED}, UNDEPLOY); + + this.graph.put(new String[] {DELETE, LOCK_NONE, SUB_NONE, + DELETING, LOCK_NONE, SUB_STATE_NONE, FAILED}, DELETE); + + this.graph.put(new String[] {DEPLOY_NONE, UNLOCK, SUB_NONE, + DEPLOYED, LOCKING, SUB_STATE_NONE, FAILED}, UNLOCK); + this.graph.put(new String[] {DEPLOY_NONE, UNLOCK, SUB_NONE, + DEPLOYED, UNLOCKING, SUB_STATE_NONE, FAILED}, UNLOCK); + + this.graph.put(new String[] {DEPLOY_NONE, LOCK, SUB_NONE, DEPLOYED, LOCKING, SUB_STATE_NONE, FAILED}, LOCK); + this.graph.put(new String[] {DEPLOY_NONE, LOCK, SUB_NONE, DEPLOYED, UNLOCKING, SUB_STATE_NONE, FAILED}, LOCK); + + this.graph.put(new String[] {UPDATE, LOCK_NONE, SUB_NONE, UPDATING, LOCKED, SUB_STATE_NONE, FAILED}, UPDATE); + + this.graph.put(new String[] {DEPLOY_NONE, LOCK_NONE, MIGRATE_PRECHECK, + DEPLOYED, LOCKED, MIGRATION_PRECHECKING, FAILED}, MIGRATE_PRECHECK); // timeout - this.graph.put(new String[] {DEPLOY, LOCK_NONE, UNDEPLOYING, STATE_LOCKED_NONE, TIMEOUT}, DEPLOY); - this.graph.put(new String[] {DEPLOY, LOCK_NONE, DEPLOYING, STATE_LOCKED_NONE, TIMEOUT}, DEPLOY); - - this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, UNDEPLOYING, STATE_LOCKED_NONE, TIMEOUT}, UNDEPLOY); - this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, UPDATING, LOCKED, TIMEOUT}, UNDEPLOY); - this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, MIGRATING, LOCKED, TIMEOUT}, UNDEPLOY); - this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, DEPLOYING, STATE_LOCKED_NONE, TIMEOUT}, UNDEPLOY); - - this.graph.put(new String[] {DELETE, LOCK_NONE, DELETING, LOCK_NONE, TIMEOUT}, DELETE); - - this.graph.put(new String[] {DEPLOY_NONE, UNLOCK, DEPLOYED, LOCKING, TIMEOUT}, UNLOCK); - this.graph.put(new String[] {DEPLOY_NONE, LOCK, DEPLOYED, LOCKING, TIMEOUT}, LOCK); - - this.graph.put(new String[] {DEPLOY_NONE, LOCK, DEPLOYED, UNLOCKING, TIMEOUT}, LOCK); - this.graph.put(new String[] {DEPLOY_NONE, UNLOCK, DEPLOYED, UNLOCKING, TIMEOUT}, UNLOCK); + this.graph.put(new String[] {DEPLOY, LOCK_NONE, SUB_NONE, + UNDEPLOYING, STATE_LOCKED_NONE, SUB_STATE_NONE, TIMEOUT}, DEPLOY); + this.graph.put(new String[] {DEPLOY, LOCK_NONE, SUB_NONE, + DEPLOYING, STATE_LOCKED_NONE, SUB_STATE_NONE, TIMEOUT}, DEPLOY); + + this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE, + UNDEPLOYING, STATE_LOCKED_NONE, SUB_STATE_NONE, TIMEOUT}, UNDEPLOY); + this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE, + UPDATING, LOCKED, SUB_STATE_NONE, TIMEOUT}, UNDEPLOY); + this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE, + MIGRATING, LOCKED, SUB_STATE_NONE, TIMEOUT}, UNDEPLOY); + this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE, + MIGRATION_PRECHECKING, LOCKED, SUB_STATE_NONE, TIMEOUT}, UNDEPLOY); + this.graph.put(new String[] {UNDEPLOY, LOCK_NONE, SUB_NONE, + DEPLOYING, STATE_LOCKED_NONE, SUB_STATE_NONE, TIMEOUT}, UNDEPLOY); + + this.graph.put(new String[] {DELETE, LOCK_NONE, SUB_NONE, + DELETING, LOCK_NONE, SUB_STATE_NONE, TIMEOUT}, DELETE); + + this.graph.put(new String[] {DEPLOY_NONE, UNLOCK, SUB_NONE, + DEPLOYED, LOCKING, SUB_STATE_NONE, TIMEOUT}, UNLOCK); + this.graph.put(new String[] {DEPLOY_NONE, LOCK, SUB_NONE, + DEPLOYED, LOCKING, SUB_STATE_NONE, TIMEOUT}, LOCK); + + this.graph.put(new String[] {DEPLOY_NONE, LOCK, SUB_NONE, + DEPLOYED, UNLOCKING, SUB_STATE_NONE, TIMEOUT}, LOCK); + this.graph.put(new String[] {DEPLOY_NONE, UNLOCK, SUB_NONE, + DEPLOYED, UNLOCKING, SUB_STATE_NONE, TIMEOUT}, UNLOCK); + + this.graph.put(new String[] {UPDATE, LOCK_NONE, SUB_NONE, UPDATING, LOCKED, SUB_STATE_NONE, TIMEOUT}, UPDATE); + + this.graph.put(new String[] {DEPLOY_NONE, LOCK_NONE, MIGRATE_PRECHECK, + DEPLOYED, LOCKED, MIGRATION_PRECHECKING, TIMEOUT}, MIGRATE_PRECHECK); } /** @@ -116,20 +171,24 @@ public class AcInstanceStateResolver { * * @param acDeployOrder the Deploy Ordered * @param acLockOrder the Lock Ordered + * @param acSubOrder the Sub Ordered * @param acDeployState then current Deploy State * @param acLockState the current Lock State + * @param acSubState the current Sub State * @param acStateChangeResult the current Result of the State Change * @return the order (DEPLOY/UNDEPLOY/LOCK/UNLOCK) to send to participant or NONE if order is not consistent */ - public String resolve(DeployOrder acDeployOrder, LockOrder acLockOrder, DeployState acDeployState, - LockState acLockState, StateChangeResult acStateChangeResult) { + public String resolve(DeployOrder acDeployOrder, LockOrder acLockOrder, SubOrder acSubOrder, + DeployState acDeployState, LockState acLockState, SubState acSubState, StateChangeResult acStateChangeResult) { var deployOrder = acDeployOrder != null ? acDeployOrder : DeployOrder.NONE; var lockOrder = acLockOrder != null ? acLockOrder : LockOrder.NONE; + var subOrder = acSubOrder != null ? acSubOrder : SubOrder.NONE; var stateChangeResult = acStateChangeResult != null ? acStateChangeResult : StateChangeResult.NO_ERROR; var deployState = acDeployState != null ? acDeployState : DeployState.UNDEPLOYED; var lockState = acLockState != null ? acLockState : LockState.NONE; - return this.graph.get(new String[] {deployOrder.name(), lockOrder.name(), deployState.name(), lockState.name(), - stateChangeResult.name()}); + var subState = acSubState != null ? acSubState : SubState.NONE; + return this.graph.get(new String[] {deployOrder.name(), lockOrder.name(), subOrder.name(), + deployState.name(), lockState.name(), subState.name(), stateChangeResult.name()}); } } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java index ce258094a..ab80bc277 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java @@ -35,6 +35,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionInfo; 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.concepts.SubState; import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationComposition; import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionElement; import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionElementRepository; @@ -172,6 +173,8 @@ public class AutomationCompositionProvider { DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING)); jpaList.addAll(automationCompositionRepository.findByLockStateIn( List.of(LockState.LOCKING, LockState.UNLOCKING))); + jpaList.addAll(automationCompositionRepository.findBySubStateIn( + List.of(SubState.PREPARING, SubState.MIGRATION_PRECHECKING, SubState.REVIEWING))); return ProviderUtils.asEntityList(jpaList); } @@ -258,6 +261,8 @@ public class AutomationCompositionProvider { jpaAcElement.setUseState(element.getUseState()); jpaAcElement.setDeployState(element.getDeployState()); jpaAcElement.setLockState(element.getLockState()); + jpaAcElement.setSubState(element.getSubState()); + jpaAcElement.setStage(element.getStage()); jpaAcElement.setRestarting(element.getRestarting()); ProviderUtils.validate(element, jpaAcElement, "AutomationCompositionElement"); @@ -265,6 +270,15 @@ public class AutomationCompositionProvider { } /** + * Delete AutomationCompositionElement. + * + * @param elementId the AutomationCompositionElement Id + */ + public void deleteAutomationCompositionElement(@NonNull final UUID elementId) { + acElementRepository.deleteById(elementId.toString()); + } + + /** * Validate ElementIds. * * @param automationComposition the AutomationComposition diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionElementRepository.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionElementRepository.java index 19d791e6c..d0a996e20 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionElementRepository.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionElementRepository.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,14 +20,19 @@ package org.onap.policy.clamp.models.acm.persistence.repository; +import jakarta.persistence.LockModeType; import java.util.List; import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionElement; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.repository.query.QueryByExampleExecutor; +import org.springframework.data.jpa.repository.Lock; +import org.springframework.lang.NonNull; -public interface AutomationCompositionElementRepository extends - JpaRepository<JpaAutomationCompositionElement, String>, - QueryByExampleExecutor<JpaAutomationCompositionElement> { +public interface AutomationCompositionElementRepository extends JpaRepository<JpaAutomationCompositionElement, String> { + + @NonNull + @Override + @Lock(LockModeType.PESSIMISTIC_READ) + JpaAutomationCompositionElement getReferenceById(@NonNull String id); List<JpaAutomationCompositionElement> findByParticipantId(String participantId); } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionRepository.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionRepository.java index d61dfb41b..7a1c61f5a 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionRepository.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionRepository.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.List; 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.concepts.SubState; import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationComposition; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -36,4 +37,6 @@ public interface AutomationCompositionRepository extends JpaRepository<JpaAutoma List<JpaAutomationComposition> findByDeployStateIn(Collection<DeployState> deployStates); List<JpaAutomationComposition> findByLockStateIn(Collection<LockState> lockStates); + + List<JpaAutomationComposition> findBySubStateIn(Collection<SubState> subStates); } 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 f90e5a807..172de34fe 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 @@ -51,6 +51,7 @@ 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.ParticipantDeploy; import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder; import org.onap.policy.clamp.models.acm.persistence.concepts.StringToMapConverter; @@ -64,6 +65,8 @@ 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; import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Utility functions used in acm-runtime and participants. @@ -74,6 +77,8 @@ public final class AcmUtils { public static final String ENTRY = "entry "; private static final StringToMapConverter MAP_CONVERTER = new StringToMapConverter(); + private static final Logger LOGGER = LoggerFactory.getLogger(AcmUtils.class); + /** * Get the Policy information in the service template for the deploy message to participants. * @@ -288,16 +293,20 @@ public final class AcmUtils { // @formatter:on } + /** - * Return true if DeployState and LockState are in a Transitional State. + * Return true if DeployState, LockState and SubState are in a Transitional State. * - * @return true if DeployState and LockState are in a Transitional State + * @param deployState the DeployState + * @param lockState the LockState + * @param subState the SubState + * @return true if there is a state in a Transitional State */ - public static boolean isInTransitionalState(DeployState deployState, LockState lockState) { + public static boolean isInTransitionalState(DeployState deployState, LockState lockState, SubState subState) { return DeployState.DEPLOYING.equals(deployState) || DeployState.UNDEPLOYING.equals(deployState) || LockState.LOCKING.equals(lockState) || LockState.UNLOCKING.equals(lockState) || DeployState.DELETING.equals(deployState) || DeployState.UPDATING.equals(deployState) - || DeployState.MIGRATING.equals(deployState); + || DeployState.MIGRATING.equals(deployState) || !SubState.NONE.equals(subState); } /** @@ -381,9 +390,23 @@ public final class AcmUtils { */ public static void setCascadedState(final AutomationComposition automationComposition, final DeployState deployState, final LockState lockState) { + setCascadedState(automationComposition, deployState, lockState, SubState.NONE); + } + + /** + /** + * Set the states on the automation composition and on all its automation composition elements. + * + * @param deployState the DeployState we want the automation composition to transition to + * @param lockState the LockState we want the automation composition to transition to + * @param subState the SubState we want the automation composition to transition to + */ + public static void setCascadedState(final AutomationComposition automationComposition, + final DeployState deployState, final LockState lockState, final SubState subState) { automationComposition.setDeployState(deployState); automationComposition.setLockState(lockState); automationComposition.setLastMsg(TimestampHelper.now()); + automationComposition.setSubState(subState); if (MapUtils.isEmpty(automationComposition.getElements())) { return; @@ -392,7 +415,9 @@ public final class AcmUtils { for (var element : automationComposition.getElements().values()) { element.setDeployState(deployState); element.setLockState(lockState); + element.setSubState(subState); element.setMessage(null); + element.setStage(null); } } @@ -515,6 +540,19 @@ public final class AcmUtils { return list; } + /** + * Validated the Message field. + * + * @param message the message + * @return a validated message + */ + public static String validatedMessage(String message) { + if (message != null && message.length() > 255) { + LOGGER.warn("message too long {}", message); + return message.substring(0, 255); + } + return message; + } /** * Recursive Merge. diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/utils/StateDefinition.java b/models/src/main/java/org/onap/policy/clamp/models/acm/utils/StateDefinition.java index b7c6a31ac..491ae101e 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/utils/StateDefinition.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/utils/StateDefinition.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -74,7 +74,7 @@ public class StateDefinition<V> { if (key == null || key.contains(separator)) { throw new PfModelRuntimeException(Status.INTERNAL_SERVER_ERROR, "wrong key " + key); } - sb.append(key + separator); + sb.append(key).append(separator); } return sb.toString(); } 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 6bb7f1eb7..bac0842f1 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 @@ -47,9 +47,31 @@ class ParticipantUtilsTest { @Test void testGetFirstStartPhase() throws CoderException { var serviceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML); + var automationComposition = + CODER.decode(ResourceUtils.getResourceAsString(AUTOMATION_COMPOSITION_JSON), AutomationCompositions.class) + .getAutomationCompositionList().get(0); + automationComposition.setDeployState(DeployState.DEPLOYING); + automationComposition.setLockState(LockState.NONE); + var result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate); + assertThat(result).isZero(); + + automationComposition.setDeployState(DeployState.DEPLOYED); + automationComposition.setLockState(LockState.UNLOCKING); + result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate); + assertThat(result).isZero(); + + automationComposition.setDeployState(DeployState.UNDEPLOYING); + automationComposition.setLockState(LockState.NONE); + result = ParticipantUtils.getFirstStartPhase(automationComposition, serviceTemplate); + assertThat(result).isEqualTo(1); + } + + @Test + void testGetFirstStage() throws CoderException { + 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), + var result = ParticipantUtils.getFirstStage(automationCompositions.getAutomationCompositionList().get(0), serviceTemplate); assertThat(result).isZero(); } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantAckMessageTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantAckMessageTest.java index 72e4efb49..2535c375a 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantAckMessageTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantAckMessageTest.java @@ -32,7 +32,6 @@ import org.onap.policy.clamp.models.acm.utils.CommonTestData; import org.onap.policy.common.utils.coder.CoderException; class ParticipantAckMessageTest { - private ParticipantAckMessage message; @Test void testCopyConstructor() throws CoderException { @@ -40,8 +39,8 @@ class ParticipantAckMessageTest { .isInstanceOf(NullPointerException.class); // verify with null values - message = new ParticipantAckMessage(ParticipantMessageType.PARTICIPANT_STATE_CHANGE); - ParticipantAckMessage newmsg = new ParticipantAckMessage(message); + var message = new ParticipantAckMessage(ParticipantMessageType.PARTICIPANT_STATE_CHANGE); + var newmsg = new ParticipantAckMessage(message); newmsg.setResponseTo(message.getResponseTo()); assertEquals(message.toString(), newmsg.toString()); @@ -56,14 +55,15 @@ class ParticipantAckMessageTest { @Test void testAppliesTo_NullParticipantId() { - message = makeMessage(); - assertThatThrownBy(() -> message.appliesTo(UUID.randomUUID(), null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> message.appliesTo(null, UUID.randomUUID())).isInstanceOf(NullPointerException.class); + var message = makeMessage(); + var participantId = CommonTestData.getRndParticipantId(); + assertThatThrownBy(() -> message.appliesTo(participantId, null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> message.appliesTo(null, participantId)).isInstanceOf(NullPointerException.class); } @Test void testAppliesTo_ParticipantIdMatches() { - message = makeMessage(); + var message = makeMessage(); // ParticipantId matches assertTrue(message.appliesTo(CommonTestData.getParticipantId(), CommonTestData.getReplicaId())); @@ -72,7 +72,7 @@ class ParticipantAckMessageTest { @Test void testAppliesTo_ParticipantIdNoMatch() { - message = makeMessage(); + var message = makeMessage(); // ParticipantId does not match assertFalse(message.appliesTo(CommonTestData.getRndParticipantId(), CommonTestData.getReplicaId())); @@ -80,7 +80,7 @@ class ParticipantAckMessageTest { } private ParticipantAckMessage makeMessage() { - ParticipantAckMessage msg = new ParticipantAckMessage(ParticipantMessageType.PARTICIPANT_DEREGISTER_ACK); + var msg = new ParticipantAckMessage(ParticipantMessageType.PARTICIPANT_DEREGISTER_ACK); msg.setParticipantId(CommonTestData.getParticipantId()); msg.setMessage("Successfull Ack"); diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantMessageTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantMessageTest.java index db31d0f01..c6386a571 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantMessageTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantMessageTest.java @@ -33,7 +33,6 @@ import org.onap.policy.clamp.models.acm.utils.CommonTestData; import org.onap.policy.common.utils.coder.CoderException; class ParticipantMessageTest { - private ParticipantMessage message; @Test void testCopyConstructor() throws CoderException { @@ -41,7 +40,7 @@ class ParticipantMessageTest { .isInstanceOf(NullPointerException.class); // verify with null values - message = new ParticipantMessage(ParticipantMessageType.PARTICIPANT_STATE_CHANGE); + var message = new ParticipantMessage(ParticipantMessageType.PARTICIPANT_STATE_CHANGE); var newmsg = new ParticipantMessage(message); newmsg.setMessageId(message.getMessageId()); newmsg.setTimestamp(message.getTimestamp()); @@ -59,15 +58,15 @@ class ParticipantMessageTest { @Test void testAppliesTo_NullParticipantId() { - message = makeMessage(); - - assertThatThrownBy(() -> message.appliesTo(UUID.randomUUID(), null)).isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> message.appliesTo(null, UUID.randomUUID())).isInstanceOf(NullPointerException.class); + var message = makeMessage(); + var participantId = CommonTestData.getParticipantId(); + assertThatThrownBy(() -> message.appliesTo(participantId, null)).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> message.appliesTo(null, participantId)).isInstanceOf(NullPointerException.class); } @Test void testAppliesTo_ParticipantIdMatches() { - message = makeMessage(); + var message = makeMessage(); // ParticipantId matches assertTrue(message.appliesTo(CommonTestData.getParticipantId(), CommonTestData.getReplicaId())); @@ -76,7 +75,7 @@ class ParticipantMessageTest { @Test void testAppliesTo_ParticipantIdNoMatch() { - message = makeMessage(); + var message = makeMessage(); assertFalse(message.appliesTo(CommonTestData.getRndParticipantId(), CommonTestData.getReplicaId())); assertTrue(message.appliesTo(CommonTestData.getParticipantId(), CommonTestData.getReplicaId())); } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantRestartTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantRestartTest.java deleted file mode 100644 index 95b718e68..000000000 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/messages/kafka/participant/ParticipantRestartTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.clamp.models.acm.messages.kafka.participant; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantMessageUtils.assertSerializable; -import static org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantMessageUtils.removeVariableFields; - -import java.time.Instant; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import org.junit.jupiter.api.Test; -import org.onap.policy.clamp.models.acm.concepts.AcElementRestart; -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.concepts.ParticipantDefinition; -import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc; -import org.onap.policy.clamp.models.acm.utils.CommonTestData; -import org.onap.policy.common.utils.coder.CoderException; -import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; - -class ParticipantRestartTest { - - @Test - void testCopyConstructor() throws CoderException { - - final var orig = new ParticipantRestart(); - // verify with null values - assertEquals(removeVariableFields(orig.toString()), - removeVariableFields(new ParticipantRestart(orig).toString())); - - orig.setMessageId(UUID.randomUUID()); - orig.setCompositionId(UUID.randomUUID()); - orig.setTimestamp(Instant.ofEpochMilli(3000)); - orig.setParticipantId(CommonTestData.getParticipantId()); - - var participantDefinitionUpdate = new ParticipantDefinition(); - var type = new ToscaConceptIdentifier("id", "1.2.3"); - var acDefinition = CommonTestData.getAcElementDefinition(type); - participantDefinitionUpdate.setAutomationCompositionElementDefinitionList(List.of(acDefinition)); - orig.setParticipantDefinitionUpdates(List.of(participantDefinitionUpdate)); - - var acElement = new AcElementRestart(); - acElement.setId(UUID.randomUUID()); - var id = new ToscaConceptIdentifier("id", "1.2.3"); - acElement.setDefinition(id); - acElement.setDeployState(DeployState.DEPLOYED); - acElement.setLockState(LockState.LOCKED); - acElement.setOperationalState("OperationalState"); - acElement.setUseState("UseState"); - acElement.setProperties(Map.of("key", "value")); - acElement.setOutProperties(Map.of("keyOut", "valueOut")); - - var acRestart = new ParticipantRestartAc(); - acRestart.setAcElementList(List.of(acElement)); - acRestart.setAutomationCompositionId(UUID.randomUUID()); - - orig.setAutomationcompositionList(List.of(acRestart)); - - assertEquals(removeVariableFields(orig.toString()), - removeVariableFields(new ParticipantRestart(orig).toString())); - - assertSerializable(orig, ParticipantRestart.class); - } -} diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionElementTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionElementTest.java index a6b3c0f80..fab3dac9b 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionElementTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionElementTest.java @@ -33,6 +33,7 @@ import org.junit.jupiter.api.Test; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; 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.concepts.SubState; import org.onap.policy.clamp.models.acm.utils.CommonTestData; import org.onap.policy.models.base.PfConceptKey; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; @@ -47,6 +48,8 @@ class JpaAutomationCompositionElementTest { private static final String NULL_ERROR = " is marked .*ull but is null"; private static final String ELEMENT_ID = "a95757ba-b34a-4049-a2a8-46773abcbe5e"; private static final String INSTANCE_ID = "a78757co-b34a-8949-a2a8-46773abcbe2a"; + private static final String KEY = "key"; + private static final String BAD_VALUE = "BadValue"; private static final PfConceptKey CONCEPT_KEY = new PfConceptKey(); @@ -54,18 +57,18 @@ class JpaAutomationCompositionElementTest { void testJpaAutomationCompositionElementConstructor() { assertThatThrownBy(() -> { new JpaAutomationCompositionElement((AutomationCompositionElement) null); - }).hasMessageMatching("authorativeConcept is marked .*ull but is null"); + }).hasMessageMatching("authorativeConcept" + NULL_ERROR); assertThatThrownBy(() -> { new JpaAutomationCompositionElement((JpaAutomationCompositionElement) null); - }).hasMessageMatching("copyConcept is marked .*ull but is null"); + }).hasMessageMatching("copyConcept" + NULL_ERROR); assertThatThrownBy(() -> { - new JpaAutomationCompositionElement("key", null); + new JpaAutomationCompositionElement(KEY, null); }).hasMessageMatching(NULL_INSTANCE_ID_ERROR); assertThatThrownBy(() -> { - new JpaAutomationCompositionElement(null, "key"); + new JpaAutomationCompositionElement(null, KEY); }).hasMessageMatching(NULL_ELEMENT_ID_ERROR); assertThatThrownBy(() -> { @@ -73,33 +76,38 @@ class JpaAutomationCompositionElementTest { }).hasMessageMatching(NULL_ELEMENT_ID_ERROR); assertThatThrownBy(() -> { - new JpaAutomationCompositionElement(null, null, null, null, null); + new JpaAutomationCompositionElement(null, null, null, null, null, null); }).hasMessageMatching(NULL_ELEMENT_ID_ERROR); assertThatThrownBy(() -> { - new JpaAutomationCompositionElement("key", null, null, - DeployState.UNDEPLOYED, LockState.LOCKED); + new JpaAutomationCompositionElement(KEY, null, null, + DeployState.UNDEPLOYED, LockState.LOCKED, SubState.NONE); }).hasMessageMatching(NULL_INSTANCE_ID_ERROR); assertThatThrownBy(() -> { - new JpaAutomationCompositionElement("key", "key", null, - DeployState.UNDEPLOYED, LockState.LOCKED); + new JpaAutomationCompositionElement(KEY, KEY, null, + DeployState.UNDEPLOYED, LockState.LOCKED, SubState.NONE); }).hasMessageMatching("definition" + NULL_ERROR); assertThatThrownBy(() -> { - new JpaAutomationCompositionElement("key", "key", CONCEPT_KEY, - null, LockState.LOCKED); + new JpaAutomationCompositionElement(KEY, KEY, CONCEPT_KEY, + null, LockState.LOCKED, SubState.NONE); }).hasMessageMatching("deployState" + NULL_ERROR); assertThatThrownBy(() -> { - new JpaAutomationCompositionElement("key", "key", CONCEPT_KEY, - DeployState.UNDEPLOYED, null); + new JpaAutomationCompositionElement(KEY, KEY, CONCEPT_KEY, + DeployState.UNDEPLOYED, null, SubState.NONE); }).hasMessageMatching("lockState" + NULL_ERROR); + assertThatThrownBy(() -> { + new JpaAutomationCompositionElement(KEY, KEY, CONCEPT_KEY, + DeployState.UNDEPLOYED, LockState.NONE, null); + }).hasMessageMatching("subState" + NULL_ERROR); + assertDoesNotThrow(() -> new JpaAutomationCompositionElement()); - assertDoesNotThrow(() -> new JpaAutomationCompositionElement("key", "key")); - assertDoesNotThrow(() -> new JpaAutomationCompositionElement("key", "key", - CONCEPT_KEY, DeployState.UNDEPLOYED, LockState.LOCKED)); + assertDoesNotThrow(() -> new JpaAutomationCompositionElement(KEY, KEY)); + assertDoesNotThrow(() -> new JpaAutomationCompositionElement(KEY, KEY, + new PfConceptKey(), DeployState.UNDEPLOYED, LockState.LOCKED, SubState.NONE)); } @Test @@ -111,7 +119,7 @@ class JpaAutomationCompositionElementTest { assertThatThrownBy(() -> { testJpaAcElement.fromAuthorative(null); - }).hasMessageMatching("element is marked .*ull but is null"); + }).hasMessageMatching("element" + NULL_ERROR); assertThatThrownBy(() -> new JpaAutomationCompositionElement((JpaAutomationCompositionElement) null)) .isInstanceOf(NullPointerException.class); @@ -137,7 +145,7 @@ class JpaAutomationCompositionElementTest { var testJpaAutomationCompositionElement = createJpaAutomationCompositionElementInstance(); assertThatThrownBy(() -> testJpaAutomationCompositionElement.validate(null)) - .hasMessageMatching("fieldName is marked .*ull but is null"); + .hasMessageMatching("fieldName" + NULL_ERROR); assertTrue(testJpaAutomationCompositionElement.validate("").isValid()); } @@ -164,17 +172,17 @@ class JpaAutomationCompositionElementTest { var otherJpaAcElement = new JpaAutomationCompositionElement(testJpaAcElement); - testJpaAcElement.setElementId("BadValue"); + testJpaAcElement.setElementId(BAD_VALUE); assertNotEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); testJpaAcElement.setElementId(ELEMENT_ID); assertEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); - testJpaAcElement.setInstanceId("BadValue"); + testJpaAcElement.setInstanceId(BAD_VALUE); assertNotEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); testJpaAcElement.setInstanceId(INSTANCE_ID); assertEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); - testJpaAcElement.setDefinition(new PfConceptKey("BadValue", "0.0.1")); + testJpaAcElement.setDefinition(new PfConceptKey(BAD_VALUE, "0.0.1")); assertNotEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); testJpaAcElement.setDefinition(new PfConceptKey("aceDef", "0.0.1")); assertEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); @@ -194,16 +202,26 @@ class JpaAutomationCompositionElementTest { testJpaAcElement.setLockState(LockState.LOCKED); assertEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); - testJpaAcElement.setUseState("BadValue"); + testJpaAcElement.setSubState(SubState.PREPARING); + assertNotEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); + testJpaAcElement.setSubState(SubState.NONE); + assertEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); + + testJpaAcElement.setUseState(BAD_VALUE); assertNotEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); testJpaAcElement.setUseState("IDLE"); assertEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); - testJpaAcElement.setOperationalState("BadValue"); + testJpaAcElement.setOperationalState(BAD_VALUE); assertNotEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); testJpaAcElement.setOperationalState("DEFAULT"); assertEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); + testJpaAcElement.setStage(1); + assertNotEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); + testJpaAcElement.setStage(null); + assertEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); + testJpaAcElement.setMessage("Message"); assertNotEquals(0, testJpaAcElement.compareTo(otherJpaAcElement)); testJpaAcElement.setMessage(null); @@ -249,7 +267,7 @@ class JpaAutomationCompositionElementTest { var testJpaAcElement = new JpaAutomationCompositionElement(testAce.getId().toString(), INSTANCE_ID); testJpaAcElement.fromAuthorative(testAce); - testJpaAcElement.setProperties(Map.of("key", "{}")); + testJpaAcElement.setProperties(Map.of(KEY, "{}")); return testJpaAcElement; } @@ -259,7 +277,7 @@ class JpaAutomationCompositionElementTest { automationCompositionElement.setId(UUID.fromString(ELEMENT_ID)); automationCompositionElement.setDefinition(new ToscaConceptIdentifier("aceDef", "0.0.1")); automationCompositionElement.setParticipantId(CommonTestData.getParticipantId()); - automationCompositionElement.setProperties(Map.of("key", "{}")); + automationCompositionElement.setProperties(Map.of(KEY, "{}")); automationCompositionElement.setUseState("IDLE"); automationCompositionElement.setOperationalState("DEFAULT"); diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionTest.java index b56e77801..38153d488 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaAutomationCompositionTest.java @@ -37,6 +37,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; 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.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.utils.TimestampHelper; import org.onap.policy.models.base.PfConceptKey; @@ -46,7 +47,7 @@ import org.onap.policy.models.base.PfConceptKey; class JpaAutomationCompositionTest { private static final String NULL_INSTANCE_ID_ERROR = "instanceId is marked .*ull but is null"; - private static final String NULL_TEXT_ERROR = " is marked .*ull but is null"; + private static final String NULL_ERROR = " is marked .*ull but is null"; private static final String INSTANCE_ID = "709c62b3-8918-41b9-a747-d21eb79c6c20"; private static final String COMPOSITION_ID = "709c62b3-8918-41b9-a747-e21eb79c6c41"; @@ -54,44 +55,49 @@ class JpaAutomationCompositionTest { void testJpaAutomationCompositionConstructor() { assertThatThrownBy(() -> { new JpaAutomationComposition((JpaAutomationComposition) null); - }).hasMessageMatching("copyConcept is marked .*ull but is null"); + }).hasMessageMatching("copyConcept" + NULL_ERROR); assertThatThrownBy(() -> { new JpaAutomationComposition((AutomationComposition) null); - }).hasMessageMatching("authorativeConcept is marked .*ull but is null"); + }).hasMessageMatching("authorativeConcept" + NULL_ERROR); assertThatThrownBy(() -> { - new JpaAutomationComposition(null, null, null, null, null, null); + new JpaAutomationComposition(null, null, null, null, null, null, null); }).hasMessageMatching(NULL_INSTANCE_ID_ERROR); assertThatThrownBy(() -> { new JpaAutomationComposition(INSTANCE_ID, null, null, new ArrayList<>(), DeployState.UNDEPLOYED, - LockState.LOCKED); - }).hasMessageMatching("key" + NULL_TEXT_ERROR); + LockState.LOCKED, SubState.NONE); + }).hasMessageMatching("key" + NULL_ERROR); assertThatThrownBy(() -> { new JpaAutomationComposition(INSTANCE_ID, new PfConceptKey(), null, new ArrayList<>(), - DeployState.UNDEPLOYED, LockState.LOCKED); - }).hasMessageMatching("compositionId" + NULL_TEXT_ERROR); + DeployState.UNDEPLOYED, LockState.LOCKED, SubState.NONE); + }).hasMessageMatching("compositionId" + NULL_ERROR); assertThatThrownBy(() -> { new JpaAutomationComposition(INSTANCE_ID, new PfConceptKey(), COMPOSITION_ID, null, - DeployState.UNDEPLOYED, LockState.LOCKED); - }).hasMessageMatching("elements" + NULL_TEXT_ERROR); + DeployState.UNDEPLOYED, LockState.LOCKED, SubState.NONE); + }).hasMessageMatching("elements" + NULL_ERROR); assertThatThrownBy(() -> { new JpaAutomationComposition(INSTANCE_ID, new PfConceptKey(), COMPOSITION_ID, new ArrayList<>(), - null, LockState.LOCKED); - }).hasMessageMatching("deployState" + NULL_TEXT_ERROR); + null, LockState.LOCKED, SubState.NONE); + }).hasMessageMatching("deployState" + NULL_ERROR); assertThatThrownBy(() -> { new JpaAutomationComposition(INSTANCE_ID, new PfConceptKey(), COMPOSITION_ID, new ArrayList<>(), - DeployState.UNDEPLOYED, null); - }).hasMessageMatching("lockState" + NULL_TEXT_ERROR); + DeployState.UNDEPLOYED, null, SubState.NONE); + }).hasMessageMatching("lockState" + NULL_ERROR); + + assertThatThrownBy(() -> { + new JpaAutomationComposition(INSTANCE_ID, new PfConceptKey(), COMPOSITION_ID, new ArrayList<>(), + DeployState.UNDEPLOYED, LockState.NONE, null); + }).hasMessageMatching("subState" + NULL_ERROR); assertDoesNotThrow(() -> new JpaAutomationComposition()); assertDoesNotThrow(() -> new JpaAutomationComposition(INSTANCE_ID, new PfConceptKey(), COMPOSITION_ID, - new ArrayList<>(), DeployState.UNDEPLOYED, LockState.LOCKED)); + new ArrayList<>(), DeployState.UNDEPLOYED, LockState.LOCKED, SubState.NONE)); } @Test @@ -108,7 +114,7 @@ class JpaAutomationCompositionTest { assertThatThrownBy(() -> { jpaAutomationComposition.fromAuthorative(null); - }).hasMessageMatching("automationComposition is marked .*ull but is null"); + }).hasMessageMatching("automationComposition" + NULL_ERROR); assertThatThrownBy(() -> new JpaAutomationComposition((JpaAutomationComposition) null)) .isInstanceOf(NullPointerException.class); @@ -137,7 +143,7 @@ class JpaAutomationCompositionTest { } @Test - void testJpaAutomationCompositionCompareTo() { + void testJpaAutomationCompositionCompareTo1() { var jpaAutomationComposition = new JpaAutomationComposition(createAutomationCompositionInstance()); var otherJpaAutomationComposition = new JpaAutomationComposition(jpaAutomationComposition); @@ -180,6 +186,12 @@ class JpaAutomationCompositionTest { assertNotEquals(0, jpaAutomationComposition.compareTo(otherJpaAutomationComposition)); jpaAutomationComposition.setPhase(null); assertEquals(0, jpaAutomationComposition.compareTo(otherJpaAutomationComposition)); + } + + @Test + void testJpaAutomationCompositionCompareTo2() { + var jpaAutomationComposition = new JpaAutomationComposition(createAutomationCompositionInstance()); + var otherJpaAutomationComposition = new JpaAutomationComposition(jpaAutomationComposition); jpaAutomationComposition.setDeployState(DeployState.DEPLOYED); assertNotEquals(0, jpaAutomationComposition.compareTo(otherJpaAutomationComposition)); @@ -191,14 +203,14 @@ class JpaAutomationCompositionTest { jpaAutomationComposition.setLockState(LockState.NONE); assertEquals(0, jpaAutomationComposition.compareTo(otherJpaAutomationComposition)); - jpaAutomationComposition.setDescription("A description"); + jpaAutomationComposition.setSubState(SubState.PREPARING); assertNotEquals(0, jpaAutomationComposition.compareTo(otherJpaAutomationComposition)); - jpaAutomationComposition.setDescription(null); + jpaAutomationComposition.setSubState(SubState.NONE); assertEquals(0, jpaAutomationComposition.compareTo(otherJpaAutomationComposition)); - jpaAutomationComposition.setRestarting(true); + jpaAutomationComposition.setDescription("A description"); assertNotEquals(0, jpaAutomationComposition.compareTo(otherJpaAutomationComposition)); - jpaAutomationComposition.setRestarting(null); + jpaAutomationComposition.setDescription(null); assertEquals(0, jpaAutomationComposition.compareTo(otherJpaAutomationComposition)); jpaAutomationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); 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 85dadc3de..95811917d 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 @@ -83,7 +83,7 @@ class AcDefinitionProviderTest { .hasMessageStartingWith("\"AutomationCompositionDefinition\" INVALID, item has status INVALID"); assertThatThrownBy(() -> acDefinitionProvider.updateAcDefinitionState(compositionId, AcTypeState.PRIMED, - StateChangeResult.NO_ERROR, false)) + StateChangeResult.NO_ERROR)) .hasMessageStartingWith("update of Automation Composition Definition"); } @@ -195,7 +195,7 @@ class AcDefinitionProviderTest { when(acmDefinitionRepository.findById(acmDefinition.getCompositionId().toString())) .thenReturn(Optional.of(jpa)); acDefinitionProvider.updateAcDefinitionState(acmDefinition.getCompositionId(), AcTypeState.PRIMED, - StateChangeResult.NO_ERROR, false); + StateChangeResult.NO_ERROR); verify(acmDefinitionRepository).save(jpa); } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolverTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolverTest.java index 7f6cb2f0c..a807a1179 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolverTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AcInstanceStateResolverTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,42 +26,78 @@ import org.junit.jupiter.api.Test; 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.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.SubOrder; class AcInstanceStateResolverTest { @Test void testResolve() { var acTypeStateResolver = new AcInstanceStateResolver(); - var result = acTypeStateResolver.resolve(DeployOrder.DEPLOY, LockOrder.NONE, DeployState.UNDEPLOYED, - LockState.NONE, StateChangeResult.NO_ERROR); + // deploy + var result = acTypeStateResolver.resolve(DeployOrder.DEPLOY, LockOrder.NONE, SubOrder.NONE, + DeployState.UNDEPLOYED, LockState.NONE, SubState.NONE, StateChangeResult.NO_ERROR); assertThat(result).isEqualTo(AcInstanceStateResolver.DEPLOY); - result = acTypeStateResolver.resolve(DeployOrder.UNDEPLOY, LockOrder.NONE, DeployState.DEPLOYED, - LockState.LOCKED, StateChangeResult.NO_ERROR); + + // undeploy + result = acTypeStateResolver.resolve(DeployOrder.UNDEPLOY, LockOrder.NONE, SubOrder.NONE, + DeployState.DEPLOYED, LockState.LOCKED, SubState.NONE, StateChangeResult.NO_ERROR); assertThat(result).isEqualTo(AcInstanceStateResolver.UNDEPLOY); - result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.UNLOCK, DeployState.DEPLOYED, LockState.LOCKED, - StateChangeResult.NO_ERROR); + + // unlock + result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.UNLOCK, SubOrder.NONE, + DeployState.DEPLOYED, LockState.LOCKED, SubState.NONE, StateChangeResult.NO_ERROR); assertThat(result).isEqualTo(AcInstanceStateResolver.UNLOCK); - result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.LOCK, DeployState.DEPLOYED, LockState.UNLOCKED, - StateChangeResult.NO_ERROR); + + // lock + result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.LOCK, SubOrder.NONE, + DeployState.DEPLOYED, LockState.UNLOCKED, SubState.NONE, StateChangeResult.NO_ERROR); assertThat(result).isEqualTo(AcInstanceStateResolver.LOCK); - result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.NONE, DeployState.UNDEPLOYED, LockState.NONE, - StateChangeResult.NO_ERROR); + // migrate + result = acTypeStateResolver.resolve(DeployOrder.MIGRATE, LockOrder.NONE, SubOrder.NONE, + DeployState.DEPLOYED, LockState.LOCKED, SubState.NONE, StateChangeResult.NO_ERROR); + assertThat(result).isEqualTo(AcInstanceStateResolver.MIGRATE); + + // migrate-precheck + result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.NONE, SubOrder.MIGRATE_PRECHECK, + DeployState.DEPLOYED, LockState.LOCKED, SubState.NONE, StateChangeResult.NO_ERROR); + assertThat(result).isEqualTo(AcInstanceStateResolver.MIGRATE_PRECHECK); + + // prepare + result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.NONE, SubOrder.PREPARE, + DeployState.UNDEPLOYED, LockState.NONE, SubState.NONE, StateChangeResult.NO_ERROR); + assertThat(result).isEqualTo(AcInstanceStateResolver.PREPARE); + + // review + result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.NONE, SubOrder.REVIEW, + DeployState.DEPLOYED, LockState.LOCKED, SubState.NONE, StateChangeResult.NO_ERROR); + assertThat(result).isEqualTo(AcInstanceStateResolver.REVIEW); + } + + @Test + void testResolveWrongOrder() { + var acTypeStateResolver = new AcInstanceStateResolver(); + + var result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.NONE, SubOrder.NONE, + DeployState.UNDEPLOYED, LockState.NONE, SubState.NONE, StateChangeResult.NO_ERROR); assertThat(result).isEqualTo(AcInstanceStateResolver.NONE); - result = acTypeStateResolver.resolve(DeployOrder.UNDEPLOY, LockOrder.UNLOCK, DeployState.DEPLOYED, - LockState.LOCKED, StateChangeResult.NO_ERROR); + + result = acTypeStateResolver.resolve(DeployOrder.UNDEPLOY, LockOrder.UNLOCK, SubOrder.NONE, + DeployState.DEPLOYED, LockState.LOCKED, SubState.NONE, StateChangeResult.NO_ERROR); assertThat(result).isEqualTo(AcInstanceStateResolver.NONE); - result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.UNLOCK, DeployState.UNDEPLOYED, LockState.NONE, - StateChangeResult.NO_ERROR); + + result = acTypeStateResolver.resolve(DeployOrder.NONE, LockOrder.UNLOCK, SubOrder.NONE, + DeployState.UNDEPLOYED, LockState.NONE, SubState.NONE, StateChangeResult.NO_ERROR); assertThat(result).isEqualTo(AcInstanceStateResolver.NONE); - result = acTypeStateResolver.resolve(DeployOrder.UNDEPLOY, LockOrder.NONE, DeployState.DEPLOYING, - LockState.NONE, StateChangeResult.NO_ERROR); + + result = acTypeStateResolver.resolve(DeployOrder.UNDEPLOY, LockOrder.NONE, SubOrder.NONE, + DeployState.DEPLOYING, LockState.NONE, SubState.NONE, StateChangeResult.NO_ERROR); assertThat(result).isEqualTo(AcInstanceStateResolver.NONE); - result = acTypeStateResolver.resolve(null, null, null, null, null); + result = acTypeStateResolver.resolve(null, null, null, null, null, null, null); assertThat(result).isEqualTo(AcInstanceStateResolver.NONE); } - } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java index 515dfaa83..c2368fe10 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java @@ -56,6 +56,7 @@ class AutomationCompositionProviderTest { private static final String AC_IS_NULL = "automationComposition is marked non-null but is null"; private static final String ACELEMENT_IS_NULL = "element is marked non-null but is null"; + private static final String ACELEMENT_ID_IS_NULL = "elementId is marked non-null but is null"; private static final Coder CODER = new StandardCoder(); private static final String AUTOMATION_COMPOSITION_JSON = @@ -241,6 +242,18 @@ class AutomationCompositionProviderTest { } @Test + void testDeleteElementById() { + var acElementRepository = mock(AutomationCompositionElementRepository.class); + var automationCompositionProvider = new AutomationCompositionProvider( + mock(AutomationCompositionRepository.class), acElementRepository); + assertThatThrownBy(() -> automationCompositionProvider.deleteAutomationCompositionElement(null)) + .hasMessageMatching(ACELEMENT_ID_IS_NULL); + var elementId = UUID.randomUUID(); + automationCompositionProvider.deleteAutomationCompositionElement(elementId); + verify(acElementRepository).deleteById(elementId.toString()); + } + + @Test void testValidateElementIds() { var acElementRepository = mock(AutomationCompositionElementRepository.class); var automationCompositionProvider = new AutomationCompositionProvider( 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 f17eff398..97af64cf7 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 @@ -43,6 +43,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; 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.concepts.SubState; import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder; @@ -68,14 +69,16 @@ class AcmUtilsTest { @Test void testIsInTransitionalState() { - assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYED, LockState.LOCKED)).isFalse(); - assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYING, LockState.NONE)).isTrue(); - assertThat(AcmUtils.isInTransitionalState(DeployState.UNDEPLOYING, LockState.NONE)).isTrue(); - assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYED, LockState.LOCKING)).isTrue(); - assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYED, LockState.UNLOCKING)).isTrue(); - assertThat(AcmUtils.isInTransitionalState(DeployState.DELETING, LockState.NONE)).isTrue(); - assertThat(AcmUtils.isInTransitionalState(DeployState.UPDATING, LockState.LOCKED)).isTrue(); - assertThat(AcmUtils.isInTransitionalState(DeployState.MIGRATING, LockState.LOCKED)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYED, LockState.LOCKED, SubState.NONE)).isFalse(); + assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYING, LockState.NONE, SubState.NONE)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.UNDEPLOYING, LockState.NONE, SubState.NONE)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYED, LockState.LOCKING, SubState.NONE)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYED, LockState.UNLOCKING, SubState.NONE)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.DELETING, LockState.NONE, SubState.NONE)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.UPDATING, LockState.LOCKED, SubState.NONE)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.MIGRATING, LockState.LOCKED, SubState.NONE)).isTrue(); + assertThat(AcmUtils.isInTransitionalState(DeployState.DEPLOYED, LockState.LOCKED, + SubState.MIGRATION_PRECHECKING)).isTrue(); } @Test @@ -235,6 +238,16 @@ class AcmUtilsTest { assertEquals(element.getOutProperties(), result.getOutProperties()); } + @Test + void testValidatedMessage() { + var message = "completed"; + assertEquals(message, AcmUtils.validatedMessage(message)); + + var serviceTemplate = CommonTestData.getToscaServiceTemplate(TOSCA_TEMPLATE_YAML); + message = serviceTemplate.toString(); + assertEquals(message.substring(0, 255), AcmUtils.validatedMessage(message)); + } + private AutomationComposition getDummyAutomationComposition() { var automationComposition = new AutomationComposition(); automationComposition.setCompositionId(UUID.randomUUID()); diff --git a/models/src/test/resources/examples/acm/test-pm-subscription-handling.yaml b/models/src/test/resources/examples/acm/test-pm-subscription-handling.yaml index 2b0b4feff..6539a9c75 100644 --- a/models/src/test/resources/examples/acm/test-pm-subscription-handling.yaml +++ b/models/src/test/resources/examples/acm/test-pm-subscription-handling.yaml @@ -317,6 +317,15 @@ node_types: provider: type: string required: false + stage: + type: array + required: false + items: + type: integer + constraints: + - greater-or-equal: 0 + metadata: + common: true startPhase: type: integer required: false @@ -394,6 +403,7 @@ topology_template: description: Participant for DCAE microservices properties: provider: ONAP + startPhase: 0 org.onap.policy.acm.PolicyAutomationCompositionParticipant: version: 2.3.1 type: org.onap.policy.clamp.acm.Participant @@ -401,6 +411,7 @@ topology_template: description: Participant for DCAE microservices properties: provider: ONAP + startPhase: 0 org.onap.ccsdk.cds.acm.CdsAutomationCompositionParticipant: version: 2.2.1 type: org.onap.policy.clamp.acm.Participant @@ -408,6 +419,7 @@ topology_template: description: Participant for DCAE microservices properties: provider: ONAP + startPhase: 1 org.onap.domain.pmsh.PMSH_DCAEMicroservice: version: 1.2.3 type: org.onap.policy.clamp.acm.DCAEMicroserviceAutomationCompositionElement @@ -415,6 +427,7 @@ topology_template: description: Automation composition element for the DCAE microservice for Performance Management Subscription Handling properties: provider: Ericsson + startPhase: 1 dcae_blueprint: tosca_definitions_version: cloudify_dsl_1_3 imports: @@ -641,6 +654,7 @@ topology_template: version: 1.0.0 policy_id: get_input: pmsh_monitoring_policy + stage: [0,1,2] org.onap.domain.pmsh.PMSH_OperationalPolicyAutomationCompositionElement: version: 1.2.3 type: org.onap.policy.clamp.acm.PolicyAutomationCompositionElement diff --git a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/MicrometerConfig.java b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/MicrometerConfig.java index 5e3441d82..e599b7c43 100644 --- a/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/MicrometerConfig.java +++ b/participant/participant-impl/participant-impl-a1pms/src/main/java/org/onap/policy/clamp/acm/participant/a1pms/config/MicrometerConfig.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.participant.a1pms.config; import io.micrometer.core.aop.TimedAspect; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,8 +35,9 @@ public class MicrometerConfig { * Load up the metrics registry. */ @Bean - public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, - MeterRegistry registry) { + public InitializingBean forcePrometheusPostProcessor(@Qualifier("meterRegistryPostProcessor") + BeanPostProcessor meterRegistryPostProcessor, + MeterRegistry registry) { return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, ""); } diff --git a/participant/participant-impl/participant-impl-acelement/pom.xml b/participant/participant-impl/participant-impl-acelement/pom.xml index 64f5653f5..d428c45c0 100644 --- a/participant/participant-impl/participant-impl-acelement/pom.xml +++ b/participant/participant-impl/participant-impl-acelement/pom.xml @@ -67,7 +67,7 @@ <generateModels>false</generateModels> <generateSupportingFiles>false</generateSupportingFiles> <importMappings> - ElementConfig=org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig + ElementConfig=org.onap.policy.clamp.acm.element.main.concepts.ElementConfig </importMappings> <configOptions> <sourceFolder>src/gen/java</sourceFolder> diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/config/MicrometerConfig.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/config/MicrometerConfig.java index d34b34add..5621587a2 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/config/MicrometerConfig.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/config/MicrometerConfig.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.element.config; import io.micrometer.core.aop.TimedAspect; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,8 +35,9 @@ public class MicrometerConfig { * Load up the metrics registry. */ @Bean - public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, - MeterRegistry registry) { + public InitializingBean forcePrometheusPostProcessor(@Qualifier("meterRegistryPostProcessor") + BeanPostProcessor meterRegistryPostProcessor, + MeterRegistry registry) { return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, ""); } diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageActivator.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageActivator.java index b3ba26223..61f05db51 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageActivator.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageActivator.java @@ -22,7 +22,7 @@ package org.onap.policy.clamp.acm.element.handler; import java.io.IOException; import java.util.List; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessageType; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessageType; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.event.comm.TopicSource; import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher; diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageHandler.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageHandler.java index bbafa071a..12d14c7f2 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageHandler.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageHandler.java @@ -26,12 +26,12 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; import lombok.NonNull; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessage; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; +import org.onap.policy.clamp.acm.element.main.concepts.ElementType; import org.onap.policy.clamp.acm.element.main.parameters.AcElement; import org.onap.policy.clamp.acm.element.service.ElementService; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessage; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementType; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.springframework.stereotype.Component; diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageListener.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageListener.java index 5e3dfa4e1..162d9bc8e 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageListener.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageListener.java @@ -20,7 +20,7 @@ package org.onap.policy.clamp.acm.element.handler; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementStatus; +import org.onap.policy.clamp.acm.element.handler.messages.ElementStatus; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.listeners.ScoListener; import org.onap.policy.common.utils.coder.StandardCoderObject; diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessagePublisher.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessagePublisher.java index bd53cec0f..ab733d777 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessagePublisher.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessagePublisher.java @@ -23,8 +23,8 @@ package org.onap.policy.clamp.acm.element.handler; import io.micrometer.core.annotation.Timed; import jakarta.ws.rs.core.Response; import java.util.List; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessage; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessage; import org.onap.policy.common.endpoints.event.comm.TopicSink; import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; import org.slf4j.Logger; diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/element/ElementMessage.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/messages/ElementMessage.java index 13a1b735b..0b6da78dd 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/element/ElementMessage.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/messages/ElementMessage.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.models.acm.messages.kafka.element; +package org.onap.policy.clamp.acm.element.handler.messages; import java.time.Instant; import java.util.UUID; diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/element/ElementMessageType.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/messages/ElementMessageType.java index cb2eaae95..31c8d5c2c 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/element/ElementMessageType.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/messages/ElementMessageType.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.models.acm.messages.kafka.element; +package org.onap.policy.clamp.acm.element.handler.messages; public enum ElementMessageType { STATUS, ACK_MSG diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/element/ElementStatus.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/messages/ElementStatus.java index 497dca408..b8f03eb95 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/kafka/element/ElementStatus.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/messages/ElementStatus.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.models.acm.messages.kafka.element; +package org.onap.policy.clamp.acm.element.handler.messages; import lombok.Getter; import lombok.Setter; diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/element/ElementConfig.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/concepts/ElementConfig.java index bb3670cb7..31a1ef6c1 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/element/ElementConfig.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/concepts/ElementConfig.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.models.acm.messages.rest.element; +package org.onap.policy.clamp.acm.element.main.concepts; import lombok.Data; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/element/ElementType.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/concepts/ElementType.java index 4bc08a36e..3a24bfbdc 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/element/ElementType.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/concepts/ElementType.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022,2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.models.acm.messages.rest.element; +package org.onap.policy.clamp.acm.element.main.concepts; public enum ElementType { diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/element/KafkaConfig.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/concepts/KafkaConfig.java index 35871fcbf..0da934f1c 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/messages/rest/element/KafkaConfig.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/concepts/KafkaConfig.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.models.acm.messages.rest.element; +package org.onap.policy.clamp.acm.element.main.concepts; import lombok.Data; diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/parameters/ElementTopicParameters.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/parameters/ElementTopicParameters.java index ba9fcf327..3e16d6352 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/parameters/ElementTopicParameters.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/parameters/ElementTopicParameters.java @@ -23,7 +23,7 @@ package org.onap.policy.clamp.acm.element.main.parameters; import java.util.List; import lombok.Data; import lombok.EqualsAndHashCode; -import org.onap.policy.clamp.models.acm.messages.rest.element.KafkaConfig; +import org.onap.policy.clamp.acm.element.main.concepts.KafkaConfig; import org.onap.policy.common.endpoints.parameters.TopicParameters; @Data diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/rest/AcElementController.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/rest/AcElementController.java index 021567a7b..bc4bbe86f 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/rest/AcElementController.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/rest/AcElementController.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022,2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,9 +22,9 @@ package org.onap.policy.clamp.acm.element.main.rest; import java.util.UUID; import lombok.RequiredArgsConstructor; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; import org.onap.policy.clamp.acm.element.main.rest.genapi.AcElementControllerApi; import org.onap.policy.clamp.acm.element.service.ConfigService; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/AbstractElementService.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/AbstractElementService.java index 04449252b..f8c8a2936 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/AbstractElementService.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/AbstractElementService.java @@ -20,8 +20,8 @@ package org.onap.policy.clamp.acm.element.service; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessage; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessage; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; public abstract class AbstractElementService implements ElementService { diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/BridgeService.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/BridgeService.java index e21a5cc99..68cfcefee 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/BridgeService.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/BridgeService.java @@ -21,11 +21,11 @@ package org.onap.policy.clamp.acm.element.service; import org.onap.policy.clamp.acm.element.handler.MessagePublisher; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessage; +import org.onap.policy.clamp.acm.element.handler.messages.ElementStatus; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; +import org.onap.policy.clamp.acm.element.main.concepts.ElementType; import org.onap.policy.clamp.acm.element.main.parameters.AcElement; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessage; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementStatus; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementType; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.springframework.stereotype.Service; diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/ConfigService.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/ConfigService.java index b3f662c86..947566685 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/ConfigService.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/ConfigService.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022,2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,13 +22,14 @@ package org.onap.policy.clamp.acm.element.service; import jakarta.ws.rs.core.Response; import java.util.List; +import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; import org.onap.policy.clamp.acm.element.handler.MessageActivator; import org.onap.policy.clamp.acm.element.handler.MessageHandler; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; import org.onap.policy.clamp.acm.element.main.parameters.ElementTopicParameters; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; import org.onap.policy.common.endpoints.parameters.TopicParameterGroup; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,6 +41,7 @@ public class ConfigService { private static final Logger LOGGER = LoggerFactory.getLogger(ConfigService.class); + @Getter private ElementConfig elementConfig = new ElementConfig(); private final MessageHandler handler; @@ -78,15 +80,6 @@ public class ConfigService { } /** - * Fetch element configuration. - * - * @return element configuration present - */ - public ElementConfig getElementConfig() { - return elementConfig; - } - - /** * Deactivate messages and service and delete the element config. */ public void deleteConfig() { diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/ElementService.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/ElementService.java index 425def915..0768e0ad8 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/ElementService.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/ElementService.java @@ -20,9 +20,9 @@ package org.onap.policy.clamp.acm.element.service; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessage; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementType; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessage; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; +import org.onap.policy.clamp.acm.element.main.concepts.ElementType; public interface ElementService { diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/SinkService.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/SinkService.java index 3f28f461e..d8fc38ec0 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/SinkService.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/SinkService.java @@ -20,8 +20,8 @@ package org.onap.policy.clamp.acm.element.service; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessage; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementType; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessage; +import org.onap.policy.clamp.acm.element.main.concepts.ElementType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/StarterService.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/StarterService.java index cb1a6ac51..8cf878e03 100644 --- a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/StarterService.java +++ b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/StarterService.java @@ -25,10 +25,10 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.onap.policy.clamp.acm.element.handler.MessagePublisher; +import org.onap.policy.clamp.acm.element.handler.messages.ElementStatus; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; +import org.onap.policy.clamp.acm.element.main.concepts.ElementType; import org.onap.policy.clamp.acm.element.main.parameters.AcElement; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementStatus; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementType; import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.springframework.stereotype.Service; diff --git a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/handler/MessageHandlerTest.java b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/handler/MessageHandlerTest.java index 39db8c3e1..5aaeb23e6 100644 --- a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/handler/MessageHandlerTest.java +++ b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/handler/MessageHandlerTest.java @@ -28,12 +28,12 @@ import static org.mockito.Mockito.when; import java.util.List; import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.acm.element.handler.messages.ElementStatus; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; +import org.onap.policy.clamp.acm.element.main.concepts.ElementType; import org.onap.policy.clamp.acm.element.main.parameters.AcElement; import org.onap.policy.clamp.acm.element.service.ElementService; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementStatus; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementType; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; class MessageHandlerTest { diff --git a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/handler/MessagePublisherTest.java b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/handler/MessagePublisherTest.java index dafb01651..f3cc885b9 100644 --- a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/handler/MessagePublisherTest.java +++ b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/handler/MessagePublisherTest.java @@ -27,8 +27,8 @@ import static org.mockito.Mockito.verify; import java.util.List; import org.junit.jupiter.api.Test; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessage; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessageType; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessage; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessageType; import org.onap.policy.common.endpoints.event.comm.TopicSink; diff --git a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/rest/AcElementControllerTest.java b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/rest/AcElementControllerTest.java index a2ed1ca34..a5e8e2c3d 100644 --- a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/rest/AcElementControllerTest.java +++ b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/rest/AcElementControllerTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation. + * Copyright (C) 2022-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,11 +40,11 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; import org.onap.policy.clamp.acm.element.main.parameters.AcElement; import org.onap.policy.clamp.acm.element.main.rest.AcElementController; import org.onap.policy.clamp.acm.element.service.ConfigService; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; diff --git a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/BridgeServiceTest.java b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/BridgeServiceTest.java index 386e9e74d..1eac5cba4 100644 --- a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/BridgeServiceTest.java +++ b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/BridgeServiceTest.java @@ -22,23 +22,34 @@ package org.onap.policy.clamp.acm.element.service; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.element.handler.MessagePublisher; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessage; +import org.onap.policy.clamp.acm.element.handler.messages.ElementStatus; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; +import org.onap.policy.clamp.acm.element.main.concepts.ElementType; import org.onap.policy.clamp.acm.element.main.parameters.AcElement; import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessage; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementStatus; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementType; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; class BridgeServiceTest { @Test + void testNotThrow() { + var acElement = new AcElement(); + acElement.setElementId(new ToscaConceptIdentifier("onap.policy.clamp.ac.element1", "1.0.0")); + var bridgeService = new BridgeService(mock(MessagePublisher.class), acElement); + assertDoesNotThrow(bridgeService::deactivate); + var elementConfig = new ElementConfig(); + assertDoesNotThrow(() -> bridgeService.update(elementConfig)); + } + + @Test void testHandleMessage() { var acElement = new AcElement(); acElement.setElementId(new ToscaConceptIdentifier("onap.policy.clamp.ac.element1", "1.0.0")); diff --git a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/ConfigServiceTest.java b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/ConfigServiceTest.java index 086676fd4..57db855c8 100644 --- a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/ConfigServiceTest.java +++ b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/ConfigServiceTest.java @@ -28,8 +28,8 @@ import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.element.handler.MessageActivator; import org.onap.policy.clamp.acm.element.handler.MessageHandler; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; -import org.onap.policy.clamp.models.acm.messages.rest.element.KafkaConfig; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; +import org.onap.policy.clamp.acm.element.main.concepts.KafkaConfig; import org.onap.policy.common.endpoints.parameters.TopicParameterGroup; class ConfigServiceTest { diff --git a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/SinkServiceTest.java b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/SinkServiceTest.java new file mode 100644 index 000000000..03710b988 --- /dev/null +++ b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/SinkServiceTest.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.element.service; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessage; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessageType; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; +import org.onap.policy.clamp.acm.element.main.parameters.AcElement; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +class SinkServiceTest { + + @Test + void testNotThrow() { + var acElement = new AcElement(); + acElement.setElementId(new ToscaConceptIdentifier("onap.policy.clamp.ac.element1", "1.0.0")); + var sinkService = new SinkService(); + var elementConfig = new ElementConfig(); + assertDoesNotThrow(() -> sinkService.active(elementConfig)); + var message = new ElementMessage(ElementMessageType.STATUS); + assertDoesNotThrow(() -> sinkService.handleMessage(message)); + } +} diff --git a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/StarterServiceTest.java b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/StarterServiceTest.java index 71bb4c6b6..2e1341bb9 100644 --- a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/StarterServiceTest.java +++ b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/service/StarterServiceTest.java @@ -29,10 +29,10 @@ import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.element.handler.MessagePublisher; +import org.onap.policy.clamp.acm.element.handler.messages.ElementMessage; +import org.onap.policy.clamp.acm.element.main.concepts.ElementConfig; +import org.onap.policy.clamp.acm.element.main.concepts.ElementType; import org.onap.policy.clamp.acm.element.main.parameters.AcElement; -import org.onap.policy.clamp.models.acm.messages.kafka.element.ElementMessage; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig; -import org.onap.policy.clamp.models.acm.messages.rest.element.ElementType; import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; diff --git a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/config/MicrometerConfig.java b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/config/MicrometerConfig.java index 06cecc6f5..ec9c95a19 100644 --- a/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/config/MicrometerConfig.java +++ b/participant/participant-impl/participant-impl-http/src/main/java/org/onap/policy/clamp/acm/participant/http/config/MicrometerConfig.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.participant.http.config; import io.micrometer.core.aop.TimedAspect; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,8 +35,9 @@ public class MicrometerConfig { * Load up the metrics registry. */ @Bean - public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, - MeterRegistry registry) { + public InitializingBean forcePrometheusPostProcessor(@Qualifier("meterRegistryPostProcessor") + BeanPostProcessor meterRegistryPostProcessor, + MeterRegistry registry) { return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, ""); } diff --git a/participant/participant-impl/participant-impl-kserve/pom.xml b/participant/participant-impl/participant-impl-kserve/pom.xml index 8b5ba564f..05cc2dcd2 100644 --- a/participant/participant-impl/participant-impl-kserve/pom.xml +++ b/participant/participant-impl/participant-impl-kserve/pom.xml @@ -52,7 +52,7 @@ <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> - <version>2022.0.5</version> + <version>2023.0.3</version> <type>pom</type> <scope>import</scope> </dependency> diff --git a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/MicrometerConfig.java b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/MicrometerConfig.java index 92dc5d3d6..1192f7703 100644 --- a/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/MicrometerConfig.java +++ b/participant/participant-impl/participant-impl-kserve/src/main/java/org/onap/policy/clamp/acm/participant/kserve/config/MicrometerConfig.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.participant.kserve.config; import io.micrometer.core.aop.TimedAspect; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,8 +35,9 @@ public class MicrometerConfig { * Load up the metrics registry. */ @Bean - public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, - MeterRegistry registry) { + public InitializingBean forcePrometheusPostProcessor(@Qualifier("meterRegistryPostProcessor") + BeanPostProcessor meterRegistryPostProcessor, + MeterRegistry registry) { return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, ""); } diff --git a/participant/participant-impl/participant-impl-kserve/src/test/java/org/onap/policy/clamp/acm/participant/kserve/k8s/InferenceServiceValidatorTest.java b/participant/participant-impl/participant-impl-kserve/src/test/java/org/onap/policy/clamp/acm/participant/kserve/k8s/InferenceServiceValidatorTest.java index 5bf7bf13b..70285f778 100644 --- a/participant/participant-impl/participant-impl-kserve/src/test/java/org/onap/policy/clamp/acm/participant/kserve/k8s/InferenceServiceValidatorTest.java +++ b/participant/participant-impl/participant-impl-kserve/src/test/java/org/onap/policy/clamp/acm/participant/kserve/k8s/InferenceServiceValidatorTest.java @@ -36,15 +36,15 @@ class InferenceServiceValidatorTest { private static final int TIMEOUT = 2; private static final int STATUS_CHECK_INTERVAL = 1; - private static final String inferenceSvcName = "inference-test"; - private static final String namespace = "test"; + private static final String INFERENCE_SVC_NAME = "inference-test"; + private static final String NAMESPACE = "test"; @Test void test_runningPodState() throws IOException, ApiException { var kserveClient = mock(KserveClient.class); doReturn("True").when(kserveClient).getInferenceServiceStatus(any(), any()); var inferenceServiceValidator = - new InferenceServiceValidator(inferenceSvcName, namespace, TIMEOUT, STATUS_CHECK_INTERVAL, + new InferenceServiceValidator(INFERENCE_SVC_NAME, NAMESPACE, TIMEOUT, STATUS_CHECK_INTERVAL, kserveClient); assertDoesNotThrow(inferenceServiceValidator::run); } @@ -54,7 +54,7 @@ class InferenceServiceValidatorTest { var kserveClient = mock(KserveClient.class); doReturn("").when(kserveClient).getInferenceServiceStatus(any(), any()); var inferenceServiceValidator = - new InferenceServiceValidator("", namespace, TIMEOUT, STATUS_CHECK_INTERVAL, + new InferenceServiceValidator("", NAMESPACE, TIMEOUT, STATUS_CHECK_INTERVAL, kserveClient); assertThatThrownBy(inferenceServiceValidator::run).isInstanceOf(KserveException.class) .cause().hasMessage("Kserve setup is unavailable for inference service to be deployed"); @@ -65,7 +65,7 @@ class InferenceServiceValidatorTest { var kserveClient = mock(KserveClient.class); doReturn("False").when(kserveClient).getInferenceServiceStatus(any(), any()); var inferenceServiceValidator = - new InferenceServiceValidator(inferenceSvcName, namespace, TIMEOUT, STATUS_CHECK_INTERVAL, + new InferenceServiceValidator(INFERENCE_SVC_NAME, NAMESPACE, TIMEOUT, STATUS_CHECK_INTERVAL, kserveClient); assertThatThrownBy(inferenceServiceValidator::run).isInstanceOf(KserveException.class) .hasMessage("Error verifying the status of the inference service. Exiting"); diff --git a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/acm/participant/kubernetes/configurations/MicrometerConfig.java b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/acm/participant/kubernetes/configurations/MicrometerConfig.java index 0532dc97d..b4afe5e89 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/acm/participant/kubernetes/configurations/MicrometerConfig.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/main/java/org/onap/policy/clamp/acm/participant/kubernetes/configurations/MicrometerConfig.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.participant.kubernetes.configurations; import io.micrometer.core.aop.TimedAspect; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,8 +35,9 @@ public class MicrometerConfig { * Load up the metrics registry. */ @Bean - public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, - MeterRegistry registry) { + public InitializingBean forcePrometheusPostProcessor(@Qualifier("meterRegistryPostProcessor") + BeanPostProcessor meterRegistryPostProcessor, + MeterRegistry registry) { return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, ""); } diff --git a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/helm/PodStatusValidatorTest.java b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/helm/PodStatusValidatorTest.java index 5640ac4be..c9253856b 100644 --- a/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/helm/PodStatusValidatorTest.java +++ b/participant/participant-impl/participant-impl-kubernetes/src/test/java/org/onap/policy/clamp/acm/participant/kubernetes/helm/PodStatusValidatorTest.java @@ -47,8 +47,8 @@ class PodStatusValidatorTest { private static final Coder CODER = new StandardCoder(); private static final String CHART_INFO_YAML = "src/test/resources/ChartList.json"; - private static int TIMEOUT = 2; - private static int STATUS_CHECK_INTERVAL = 1; + private static final int TIMEOUT = 2; + private static final int STATUS_CHECK_INTERVAL = 1; private static List<ChartInfo> charts; @InjectMocks diff --git a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/config/MicrometerConfig.java b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/config/MicrometerConfig.java index 2f942eaa8..de1242b9e 100644 --- a/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/config/MicrometerConfig.java +++ b/participant/participant-impl/participant-impl-policy/src/main/java/org/onap/policy/clamp/acm/participant/policy/config/MicrometerConfig.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.participant.policy.config; import io.micrometer.core.aop.TimedAspect; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,8 +35,9 @@ public class MicrometerConfig { * Load up the metrics registry. */ @Bean - public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, - MeterRegistry registry) { + public InitializingBean forcePrometheusPostProcessor(@Qualifier("meterRegistryPostProcessor") + BeanPostProcessor meterRegistryPostProcessor, + MeterRegistry registry) { return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, ""); } diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/MicrometerConfig.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/MicrometerConfig.java index 2a319c3bd..4ddec02e5 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/MicrometerConfig.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/MicrometerConfig.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.participant.sim.config; import io.micrometer.core.aop.TimedAspect; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,8 +35,9 @@ public class MicrometerConfig { * Load up the metrics registry. */ @Bean - public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, - MeterRegistry registry) { + public InitializingBean forcePrometheusPostProcessor(@Qualifier("meterRegistryPostProcessor") + BeanPostProcessor meterRegistryPostProcessor, + MeterRegistry registry) { return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, ""); } diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV1.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV1.java index aa9d90e91..534b01b32 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV1.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV1.java @@ -27,7 +27,6 @@ import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantInterme import org.onap.policy.clamp.acm.participant.intermediary.api.impl.AcElementListenerV1; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; -import org.onap.policy.models.base.PfModelException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; @@ -48,61 +47,58 @@ public class AutomationCompositionElementHandlerV1 extends AcElementListenerV1 { } @Override - public void deploy(UUID instanceId, AcElementDeploy element, Map<String, Object> properties) - throws PfModelException { + public void deploy(UUID instanceId, AcElementDeploy element, Map<String, Object> properties) { LOGGER.debug("deploy call instanceId: {}, element: {}, properties: {}", instanceId, element, properties); simulatorService.deploy(instanceId, element.getId()); } @Override - public void undeploy(UUID instanceId, UUID elementId) throws PfModelException { + public void undeploy(UUID instanceId, UUID elementId) { LOGGER.debug("undeploy call instanceId: {}, elementId: {}", instanceId, elementId); simulatorService.undeploy(instanceId, elementId); } @Override - public void lock(UUID instanceId, UUID elementId) throws PfModelException { + public void lock(UUID instanceId, UUID elementId) { LOGGER.debug("lock call instanceId: {}, elementId: {}", instanceId, elementId); simulatorService.lock(instanceId, elementId); } @Override - public void unlock(UUID instanceId, UUID elementId) throws PfModelException { + public void unlock(UUID instanceId, UUID elementId) { LOGGER.debug("unlock call instanceId: {}, elementId: {}", instanceId, elementId); simulatorService.unlock(instanceId, elementId); } @Override - public void delete(UUID instanceId, UUID elementId) throws PfModelException { + public void delete(UUID instanceId, UUID elementId) { LOGGER.debug("delete call instanceId: {}, elementId: {}", instanceId, elementId); simulatorService.delete(instanceId, elementId); } @Override - public void update(UUID instanceId, AcElementDeploy element, Map<String, Object> properties) - throws PfModelException { + public void update(UUID instanceId, AcElementDeploy element, Map<String, Object> properties) { LOGGER.debug("update call instanceId: {}, element: {}, properties: {}", instanceId, element, properties); simulatorService.update(instanceId, element.getId()); } @Override - public void prime(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList) - throws PfModelException { + public void prime(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList) { LOGGER.debug("prime call compositionId: {}, elementDefinitionList: {}", compositionId, elementDefinitionList); simulatorService.prime(compositionId); } @Override - public void deprime(UUID compositionId) throws PfModelException { + public void deprime(UUID compositionId) { LOGGER.debug("deprime call compositionId: {}", compositionId); simulatorService.deprime(compositionId); } @Override public void migrate(UUID instanceId, AcElementDeploy element, UUID compositionTargetId, - Map<String, Object> properties) throws PfModelException { + Map<String, Object> properties) { LOGGER.debug("migrate call instanceId: {}, element: {}, compositionTargetId: {}, properties: {}", instanceId, element, compositionTargetId, properties); - simulatorService.migrate(instanceId, element.getId()); + simulatorService.migrate(instanceId, element.getId(), 0, Map.of()); } } diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV2.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV2.java index eaad5d902..82602c1e1 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV2.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV2.java @@ -22,10 +22,10 @@ package org.onap.policy.clamp.acm.participant.sim.main.handler; import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto; import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState; import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; import org.onap.policy.clamp.acm.participant.intermediary.api.impl.AcElementListenerV2; -import org.onap.policy.models.base.PfModelException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; @@ -34,7 +34,7 @@ import org.springframework.stereotype.Component; /** * This class handles implementation of automationCompositionElement updates. */ -@ConditionalOnExpression("'${element.handler:AcElementHandlerV2}' == 'AcElementHandlerV2'") +@ConditionalOnExpression("'${element.handler}'=='AcElementHandlerV2'") @Component public class AutomationCompositionElementHandlerV2 extends AcElementListenerV2 { @@ -53,11 +53,9 @@ public class AutomationCompositionElementHandlerV2 extends AcElementListenerV2 { * * @param compositionElement the information of the Automation Composition Definition Element * @param instanceElement the information of the Automation Composition Instance Element - * @throws PfModelException from Policy framework */ @Override - public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { + public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { LOGGER.debug("deploy call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); simulatorService.deploy(instanceElement.instanceId(), instanceElement.elementId()); } @@ -67,63 +65,90 @@ public class AutomationCompositionElementHandlerV2 extends AcElementListenerV2 { * * @param compositionElement the information of the Automation Composition Definition Element * @param instanceElement the information of the Automation Composition Instance Element - * @throws PfModelException from Policy framework */ @Override - public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { + public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { LOGGER.debug("undeploy call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); simulatorService.undeploy(instanceElement.instanceId(), instanceElement.elementId()); } @Override - public void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { + public void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { LOGGER.debug("lock call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); simulatorService.lock(instanceElement.instanceId(), instanceElement.elementId()); } @Override - public void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { + public void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { LOGGER.debug("unlock call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); simulatorService.unlock(instanceElement.instanceId(), instanceElement.elementId()); } @Override - public void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { + public void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { LOGGER.debug("delete call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); simulatorService.delete(instanceElement.instanceId(), instanceElement.elementId()); } @Override public void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement, - InstanceElementDto instanceElementUpdated) throws PfModelException { + InstanceElementDto instanceElementUpdated) { LOGGER.debug("update call compositionElement: {}, instanceElement: {}, instanceElementUpdated: {}", compositionElement, instanceElement, instanceElementUpdated); simulatorService.update(instanceElement.instanceId(), instanceElement.elementId()); } @Override - public void prime(CompositionDto composition) throws PfModelException { + public void prime(CompositionDto composition) { LOGGER.debug("prime call composition: {}", composition); simulatorService.prime(composition.compositionId()); } @Override - public void deprime(CompositionDto composition) throws PfModelException { + public void deprime(CompositionDto composition) { LOGGER.debug("deprime call composition: {}", composition); simulatorService.deprime(composition.compositionId()); } @Override public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, - InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) - throws PfModelException { + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) { LOGGER.debug("migrate call compositionElement: {}, compositionElementTarget: {}, instanceElement: {}," + " instanceElementMigrate: {}", compositionElement, compositionElementTarget, instanceElement, instanceElementMigrate); - simulatorService.migrate(instanceElement.instanceId(), instanceElement.elementId()); + + if (ElementState.NEW.equals(instanceElementMigrate.state())) { + LOGGER.debug("new element scenario"); + + } + if (ElementState.REMOVED.equals(instanceElementMigrate.state())) { + simulatorService.undeploy(instanceElement.instanceId(), instanceElement.elementId()); + simulatorService.delete(instanceElement.instanceId(), instanceElement.elementId()); + } else { + simulatorService.migrate(instanceElement.instanceId(), instanceElement.elementId(), + 0, compositionElementTarget.inProperties()); + } + } + + @Override + public void migratePrecheck(CompositionElementDto compositionElement, + CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, + InstanceElementDto instanceElementMigrate) { + LOGGER.debug("migrate precheck call compositionElement: {}, compositionElementTarget: {}, instanceElement: {}," + + " instanceElementMigrate: {}", + compositionElement, compositionElementTarget, instanceElement, instanceElementMigrate); + simulatorService.migratePrecheck(instanceElement.instanceId(), instanceElement.elementId()); + } + + @Override + public void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + LOGGER.debug("prepare call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); + simulatorService.prepare(instanceElement.instanceId(), instanceElement.elementId()); + } + + @Override + public void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + LOGGER.debug("review call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); + simulatorService.review(instanceElement.instanceId(), instanceElement.elementId()); } } diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3.java new file mode 100644 index 000000000..e406a6127 --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3.java @@ -0,0 +1,165 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.participant.sim.main.handler; + +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; +import lombok.Setter; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState; +import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; +import org.onap.policy.clamp.acm.participant.intermediary.api.impl.AcElementListenerV3; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.stereotype.Component; + +/** + * This class handles implementation of automationCompositionElement updates. + */ +@Getter +@Setter +@ConditionalOnExpression("'${element.handler:AcElementHandlerV3}' == 'AcElementHandlerV3'") +@Component +public class AutomationCompositionElementHandlerV3 extends AcElementListenerV3 { + + private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionElementHandlerV3.class); + + private final SimulatorService simulatorService; + + public AutomationCompositionElementHandlerV3(ParticipantIntermediaryApi intermediaryApi, + SimulatorService simulatorService) { + super(intermediaryApi); + this.simulatorService = simulatorService; + } + + /** + * Handle a deploy on a automation composition element. + * + * @param compositionElement the information of the Automation Composition Definition Element + * @param instanceElement the information of the Automation Composition Instance Element + */ + @Override + public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + LOGGER.debug("deploy call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); + simulatorService.deploy(instanceElement.instanceId(), instanceElement.elementId()); + } + + /** + * Handle a automation composition element state change. + * + * @param compositionElement the information of the Automation Composition Definition Element + * @param instanceElement the information of the Automation Composition Instance Element + */ + @Override + public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + LOGGER.debug("undeploy call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); + simulatorService.undeploy(instanceElement.instanceId(), instanceElement.elementId()); + } + + @Override + public void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + LOGGER.debug("lock call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); + simulatorService.lock(instanceElement.instanceId(), instanceElement.elementId()); + } + + @Override + public void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + LOGGER.debug("unlock call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); + simulatorService.unlock(instanceElement.instanceId(), instanceElement.elementId()); + } + + @Override + public void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + LOGGER.debug("delete call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); + simulatorService.delete(instanceElement.instanceId(), instanceElement.elementId()); + } + + @Override + public void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement, + InstanceElementDto instanceElementUpdated) { + LOGGER.debug("update call compositionElement: {}, instanceElement: {}, instanceElementUpdated: {}", + compositionElement, instanceElement, instanceElementUpdated); + simulatorService.update(instanceElement.instanceId(), instanceElement.elementId()); + } + + @Override + public void prime(CompositionDto composition) { + LOGGER.debug("prime call composition: {}", composition); + simulatorService.prime(composition.compositionId()); + } + + @Override + public void deprime(CompositionDto composition) { + LOGGER.debug("deprime call composition: {}", composition); + simulatorService.deprime(composition.compositionId()); + } + + @Override + public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate, int stage) { + LOGGER.debug("migrate call compositionElement: {}, compositionElementTarget: {}, instanceElement: {}," + + " instanceElementMigrate: {}, stage: {}", + compositionElement, compositionElementTarget, instanceElement, instanceElementMigrate, stage); + + if (ElementState.NEW.equals(instanceElementMigrate.state())) { + LOGGER.debug("new element scenario"); + } + if (ElementState.REMOVED.equals(instanceElementMigrate.state())) { + simulatorService.undeploy(instanceElement.instanceId(), instanceElement.elementId()); + simulatorService.delete(instanceElement.instanceId(), instanceElement.elementId()); + } else { + simulatorService.migrate(instanceElementMigrate.instanceId(), instanceElementMigrate.elementId(), stage, + compositionElementTarget.inProperties()); + instanceElementMigrate.outProperties().putIfAbsent("stage", new ArrayList<>()); + @SuppressWarnings("unchecked") + var stageList = (List<Integer>) instanceElementMigrate.outProperties().get("stage"); + stageList.add(stage); + intermediaryApi.sendAcElementInfo(instanceElementMigrate.instanceId(), instanceElementMigrate.elementId(), + null, null, instanceElementMigrate.outProperties()); + } + } + + @Override + public void migratePrecheck(CompositionElementDto compositionElement, + CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, + InstanceElementDto instanceElementMigrate) { + LOGGER.debug("migrate precheck call compositionElement: {}, compositionElementTarget: {}, instanceElement: {}," + + " instanceElementMigrate: {}", + compositionElement, compositionElementTarget, instanceElement, instanceElementMigrate); + simulatorService.migratePrecheck(instanceElement.instanceId(), instanceElement.elementId()); + } + + @Override + public void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + LOGGER.debug("prepare call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); + simulatorService.prepare(instanceElement.instanceId(), instanceElement.elementId()); + } + + @Override + public void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + LOGGER.debug("review call compositionElement: {}, instanceElement: {}", compositionElement, instanceElement); + simulatorService.review(instanceElement.instanceId(), instanceElement.elementId()); + } +} diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java index d37edf761..b0006f711 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/SimulatorService.java @@ -35,6 +35,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions; 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.concepts.ParticipantUtils; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.slf4j.Logger; @@ -327,19 +328,98 @@ public class SimulatorService { * * @param instanceId the instanceId * @param elementId the elementId + * @param stage the stage */ - public void migrate(UUID instanceId, UUID elementId) { + public void migrate(UUID instanceId, UUID elementId, int stage, Map<String, Object> compositionInProperties) { if (!execution(getConfig().getMigrateTimerMs(), "Current Thread migrate is Interrupted during execution {}", elementId)) { return; } - if (getConfig().isMigrateSuccess()) { + if (config.isMigrateSuccess()) { + var stageSet = ParticipantUtils.findStageSet(compositionInProperties); + var nextStage = 1000; + for (var s : stageSet) { + if (s > stage) { + nextStage = Math.min(s, nextStage); + } + } + if (nextStage == 1000) { + intermediaryApi.updateAutomationCompositionElementState( + instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); + } else { + intermediaryApi.updateAutomationCompositionElementStage( + instanceId, elementId, + StateChangeResult.NO_ERROR, nextStage, "stage " + stage + " Migrated"); + } + } else { + intermediaryApi.updateAutomationCompositionElementState( + instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!"); + } + } + + /** + * Handle a Migrate Precheck on a automation composition element. + * + * @param instanceId the instanceId + * @param elementId the elementId + */ + public void migratePrecheck(UUID instanceId, UUID elementId) { + if (!execution(config.getMigratePrecheckTimerMs(), + "Current Thread migrate precheck is Interrupted during execution {}", elementId)) { + return; + } + + if (config.isMigratePrecheck()) { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migration precheck completed"); } else { intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!"); + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migration precheck failed"); + } + } + + /** + * Handle a Prepare on a automation composition element. + * + * @param instanceId the instanceId + * @param elementId the elementId + */ + public void prepare(UUID instanceId, UUID elementId) { + if (!execution(config.getPrepareTimerMs(), + "Current Thread prepare is Interrupted during execution {}", elementId)) { + return; + } + + if (config.isPrepare()) { + intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed"); + } else { + intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Prepare failed"); + } + } + + /** + * Handle a Review on a automation composition element. + * + * @param instanceId the instanceId + * @param elementId the elementId + */ + public void review(UUID instanceId, UUID elementId) { + if (!execution(config.getReviewTimerMs(), + "Current Thread review is Interrupted during execution {}", elementId)) { + return; + } + + if (config.isReview()) { + intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Review completed"); + } else { + intermediaryApi.updateAutomationCompositionElementState(instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Review failed"); } } } diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java index f4d4c6e2e..f38f3079b 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,6 +38,12 @@ public class SimConfig { private boolean migrateSuccess = true; + private boolean migratePrecheck = true; + + private boolean prepare = true; + + private boolean review = true; + private boolean primeSuccess = true; private boolean deprimeSuccess = true; @@ -54,6 +60,12 @@ public class SimConfig { private int migrateTimerMs = 100; + private int migratePrecheckTimerMs = 100; + + private int prepareTimerMs = 100; + + private int reviewTimerMs = 100; + private int deleteTimerMs = 100; private int primeTimerMs = 100; diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/parameters/ParticipantSimParameters.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/parameters/ParticipantSimParameters.java index 4c7845143..4157bfd88 100644 --- a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/parameters/ParticipantSimParameters.java +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/parameters/ParticipantSimParameters.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,5 +41,5 @@ public class ParticipantSimParameters implements ParticipantParameters { @NotNull @Valid - private ParticipantIntermediaryParameters intermediaryParameters; + private ParticipantIntermediaryParameters intermediaryParameters = new ParticipantIntermediaryParameters(); } diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/comm/CommonTestData.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/comm/CommonTestData.java index 5499931a2..f73f75970 100644 --- a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/comm/CommonTestData.java +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/comm/CommonTestData.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.TreeMap; import java.util.UUID; import org.onap.policy.clamp.acm.participant.intermediary.parameters.Topics; +import org.onap.policy.clamp.acm.participant.sim.model.SimConfig; import org.onap.policy.clamp.acm.participant.sim.parameters.ParticipantSimParameters; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; @@ -102,7 +103,7 @@ public class CommonTestData { * @return topic parameters */ private static TopicParameters getSinkTopicParams() { - final TopicParameters topicParams = new TopicParameters(); + final var topicParams = new TopicParameters(); topicParams.setTopic("policy-acruntime-participant"); topicParams.setTopicCommInfrastructure("NOOP"); topicParams.setServers(List.of("localhost")); @@ -115,7 +116,7 @@ public class CommonTestData { * @return topic parameters */ private static TopicParameters getSyncTopicParams() { - final TopicParameters topicParams = new TopicParameters(); + final var topicParams = new TopicParameters(); topicParams.setTopic("acm-ppnt-sync"); topicParams.setTopicCommInfrastructure("NOOP"); topicParams.setServers(List.of("localhost")); @@ -135,8 +136,6 @@ public class CommonTestData { * Returns a Map of ToscaConceptIdentifier and AutomationComposition for test cases. * * @return automationCompositionMap - * - * @throws CoderException if there is an error with .json file. */ public static Map<UUID, AutomationComposition> getTestAutomationCompositionMap() { var automationComposition = getTestAutomationComposition(); @@ -147,8 +146,6 @@ public class CommonTestData { * Returns List of AutomationComposition for test cases. * * @return AutomationCompositions - * - * @throws CoderException if there is an error with .json file. */ public static AutomationComposition getTestAutomationComposition() { var automationComposition = new AutomationComposition(); @@ -158,4 +155,26 @@ public class CommonTestData { automationComposition.setElements(Map.of(element.getId(), element)); return automationComposition; } + + /** + * Create a new SimConfig. + * + * @return a new SimConfig + */ + public static SimConfig createSimConfig() { + var config = new SimConfig(); + config.setPrepareTimerMs(1); + config.setDeployTimerMs(1); + config.setReviewTimerMs(1); + config.setUndeployTimerMs(1); + config.setLockTimerMs(1); + config.setUnlockTimerMs(1); + config.setUpdateTimerMs(1); + config.setDeleteTimerMs(1); + config.setPrimeTimerMs(1); + config.setDeprimeTimerMs(1); + config.setMigrateTimerMs(1); + config.setMigratePrecheckTimerMs(1); + return config; + } } diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV1Test.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV1Test.java index 300caa52c..d78b851d4 100644 --- a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV1Test.java +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV1Test.java @@ -28,194 +28,178 @@ import java.util.Map; import java.util.UUID; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; -import org.onap.policy.clamp.acm.participant.sim.model.SimConfig; +import org.onap.policy.clamp.acm.participant.sim.comm.CommonTestData; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; 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.concepts.StateChangeResult; -import org.onap.policy.models.base.PfModelException; class AutomationCompositionElementHandlerV1Test { + private static final UUID COMPOSITION_ID = UUID.randomUUID(); + private static final UUID INSTANCE_ID = UUID.randomUUID(); + private static final UUID ELEMENT_ID = UUID.randomUUID(); + + private AcElementDeploy createAcElementDeploy() { + var element = new AcElementDeploy(); + element.setId(ELEMENT_ID); + return element; + } + @Test - void testDeploy() throws PfModelException { - var config = new SimConfig(); - config.setDeployTimerMs(1); + void testDeploy() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV1(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var instanceId = UUID.randomUUID(); - var element = new AcElementDeploy(); - element.setId(UUID.randomUUID()); - acElementHandler.deploy(instanceId, element, Map.of()); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + var element = createAcElementDeploy(); + acElementHandler.deploy(INSTANCE_ID, element, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, element.getId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); config.setDeploySuccess(false); - acElementHandler.deploy(instanceId, element, Map.of()); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + acElementHandler.deploy(INSTANCE_ID, element, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, element.getId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!"); } @Test - void testUndeploy() throws PfModelException { - var config = new SimConfig(); - config.setUndeployTimerMs(1); + void testUndeploy() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV1(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var instanceId = UUID.randomUUID(); - var elementId = UUID.randomUUID(); - acElementHandler.undeploy(instanceId, elementId); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.UNDEPLOYED, + acElementHandler.undeploy(INSTANCE_ID, ELEMENT_ID); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, ELEMENT_ID, DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); config.setUndeploySuccess(false); - acElementHandler.undeploy(instanceId, elementId); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, + acElementHandler.undeploy(INSTANCE_ID, ELEMENT_ID); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, ELEMENT_ID, DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Undeploy failed!"); } @Test - void testLock() throws PfModelException { - var config = new SimConfig(); - config.setLockTimerMs(1); + void testLock() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV1(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var instanceId = UUID.randomUUID(); - var elementId = UUID.randomUUID(); - acElementHandler.lock(instanceId, elementId); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.LOCKED, - StateChangeResult.NO_ERROR, "Locked"); + acElementHandler.lock(INSTANCE_ID, ELEMENT_ID); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, ELEMENT_ID, + null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); config.setLockSuccess(false); - acElementHandler.lock(instanceId, elementId); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.UNLOCKED, - StateChangeResult.FAILED, "Lock failed!"); + acElementHandler.lock(INSTANCE_ID, ELEMENT_ID); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, ELEMENT_ID, + null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!"); } @Test - void testUnlock() throws PfModelException { - var config = new SimConfig(); - config.setUnlockTimerMs(1); + void testUnlock() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV1(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var instanceId = UUID.randomUUID(); - var elementId = UUID.randomUUID(); - acElementHandler.unlock(instanceId, elementId); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.UNLOCKED, - StateChangeResult.NO_ERROR, "Unlocked"); + acElementHandler.unlock(INSTANCE_ID, ELEMENT_ID); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, ELEMENT_ID, + null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); config.setUnlockSuccess(false); - acElementHandler.unlock(instanceId, elementId); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.LOCKED, - StateChangeResult.FAILED, "Unlock failed!"); + acElementHandler.unlock(INSTANCE_ID, ELEMENT_ID); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, ELEMENT_ID, + null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!"); } @Test - void testUpdate() throws PfModelException { - var config = new SimConfig(); - config.setUpdateTimerMs(1); + void testUpdate() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV1(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var instanceId = UUID.randomUUID(); - var element = new AcElementDeploy(); - element.setId(UUID.randomUUID()); - acElementHandler.update(instanceId, element, Map.of()); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + var element = createAcElementDeploy(); + acElementHandler.update(INSTANCE_ID, element, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, element.getId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated"); config.setUpdateSuccess(false); - acElementHandler.update(instanceId, element, Map.of()); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + acElementHandler.update(INSTANCE_ID, element, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, element.getId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!"); } @Test - void testDelete() throws PfModelException { - var config = new SimConfig(); - config.setDeleteTimerMs(1); + void testDelete() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV1(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var instanceId = UUID.randomUUID(); - var elementId = UUID.randomUUID(); - acElementHandler.delete(instanceId, elementId); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.DELETED, + acElementHandler.delete(INSTANCE_ID, ELEMENT_ID); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, ELEMENT_ID, DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); config.setDeleteSuccess(false); - acElementHandler.delete(instanceId, elementId); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.UNDEPLOYED, + acElementHandler.delete(INSTANCE_ID, ELEMENT_ID); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, ELEMENT_ID, DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Delete failed!"); } @Test - void testPrime() throws PfModelException { - var config = new SimConfig(); - config.setPrimeTimerMs(1); + void testPrime() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV1(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionId = UUID.randomUUID(); - acElementHandler.prime(compositionId, List.of()); - verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, + acElementHandler.prime(COMPOSITION_ID, List.of()); + verify(intermediaryApi).updateCompositionState(COMPOSITION_ID, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed"); config.setPrimeSuccess(false); - acElementHandler.prime(compositionId, List.of()); - verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, + acElementHandler.prime(COMPOSITION_ID, List.of()); + verify(intermediaryApi).updateCompositionState(COMPOSITION_ID, AcTypeState.COMMISSIONED, StateChangeResult.FAILED, "Prime failed!"); } @Test - void testDeprime() throws PfModelException { - var config = new SimConfig(); - config.setDeprimeTimerMs(1); + void testDeprime() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV1(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionId = UUID.randomUUID(); - acElementHandler.deprime(compositionId); - verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, + acElementHandler.deprime(COMPOSITION_ID); + verify(intermediaryApi).updateCompositionState(COMPOSITION_ID, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); config.setDeprimeSuccess(false); - acElementHandler.deprime(compositionId); - verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.FAILED, + acElementHandler.deprime(COMPOSITION_ID); + verify(intermediaryApi).updateCompositionState(COMPOSITION_ID, AcTypeState.PRIMED, StateChangeResult.FAILED, "Deprime failed!"); } @Test - void testMigrate() throws PfModelException { - var config = new SimConfig(); - config.setUpdateTimerMs(1); + void testMigrate() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV1(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var instanceId = UUID.randomUUID(); - var element = new AcElementDeploy(); - element.setId(UUID.randomUUID()); - acElementHandler.migrate(instanceId, element, UUID.randomUUID(), Map.of()); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + var element = createAcElementDeploy(); + acElementHandler.migrate(INSTANCE_ID, element, COMPOSITION_ID, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, element.getId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); config.setMigrateSuccess(false); - acElementHandler.migrate(instanceId, element, UUID.randomUUID(), Map.of()); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + acElementHandler.migrate(INSTANCE_ID, element, COMPOSITION_ID, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(INSTANCE_ID, element.getId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!"); } } diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV2Test.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV2Test.java index 51e39067f..f3a1839f0 100644 --- a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV2Test.java +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV2Test.java @@ -28,227 +28,312 @@ import java.util.UUID; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto; import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState; import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; -import org.onap.policy.clamp.acm.participant.sim.model.SimConfig; -import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.acm.participant.sim.comm.CommonTestData; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; 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.concepts.StateChangeResult; -import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; class AutomationCompositionElementHandlerV2Test { + private static final CompositionElementDto COMPOSITION_ELEMENT = + new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); + private static final InstanceElementDto INSTANCE_ELEMENT = + new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + private static final CompositionDto COMPOSITION = new CompositionDto(UUID.randomUUID(), Map.of(), Map.of()); + @Test - void testDeploy() throws PfModelException { - var config = new SimConfig(); - config.setDeployTimerMs(1); + void testDeploy() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of()); - var instanceId = UUID.randomUUID(); - var elementId = UUID.randomUUID(); - var instanceElement = new InstanceElementDto(instanceId, elementId, null, Map.of(), Map.of()); - acElementHandler.deploy(compositionElement, instanceElement); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, + acElementHandler.deploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); config.setDeploySuccess(false); - acElementHandler.deploy(compositionElement, instanceElement); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.UNDEPLOYED, + acElementHandler.deploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!"); } @Test - void testUndeploy() throws PfModelException { - var config = new SimConfig(); - config.setUndeployTimerMs(1); + void testUndeploy() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of()); - var instanceId = UUID.randomUUID(); - var elementId = UUID.randomUUID(); - var instanceElement = new InstanceElementDto(instanceId, elementId, null, Map.of(), Map.of()); - acElementHandler.undeploy(compositionElement, instanceElement); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.UNDEPLOYED, + acElementHandler.undeploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); config.setUndeploySuccess(false); - acElementHandler.undeploy(compositionElement, instanceElement); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, + acElementHandler.undeploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Undeploy failed!"); } @Test - void testLock() throws PfModelException { - var config = new SimConfig(); - config.setLockTimerMs(1); + void testLock() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of()); - var instanceId = UUID.randomUUID(); - var elementId = UUID.randomUUID(); - var instanceElement = new InstanceElementDto(instanceId, elementId, null, Map.of(), Map.of()); - acElementHandler.lock(compositionElement, instanceElement); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.LOCKED, + acElementHandler.lock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); config.setLockSuccess(false); - acElementHandler.lock(compositionElement, instanceElement); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.UNLOCKED, + acElementHandler.lock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!"); } @Test - void testUnlock() throws PfModelException { - var config = new SimConfig(); - config.setUnlockTimerMs(1); + void testUnlock() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of()); - var instanceId = UUID.randomUUID(); - var elementId = UUID.randomUUID(); - var instanceElement = new InstanceElementDto(instanceId, elementId, null, Map.of(), Map.of()); - acElementHandler.unlock(compositionElement, instanceElement); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.UNLOCKED, + acElementHandler.unlock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); config.setUnlockSuccess(false); - acElementHandler.unlock(compositionElement, instanceElement); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.LOCKED, + acElementHandler.unlock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!"); } @Test - void testUpdate() throws PfModelException { - var config = new SimConfig(); - config.setUpdateTimerMs(1); + void testUpdate() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of()); - var instanceId = UUID.randomUUID(); - var element = new AcElementDeploy(); - element.setId(UUID.randomUUID()); - var instanceElement = new InstanceElementDto(instanceId, element.getId(), null, Map.of(), Map.of()); - var instanceElementUpdated = new InstanceElementDto(instanceId, element.getId(), null, + var instanceElementUpdated = new InstanceElementDto( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, Map.of("key", "value"), Map.of()); - acElementHandler.update(compositionElement, instanceElement, instanceElementUpdated); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + acElementHandler.update(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, instanceElementUpdated); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated"); config.setUpdateSuccess(false); - acElementHandler.update(compositionElement, instanceElement, instanceElementUpdated); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + acElementHandler.update(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, instanceElementUpdated); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!"); } @Test - void testDelete() throws PfModelException { - var config = new SimConfig(); - config.setDeleteTimerMs(1); + void testDelete() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of()); - var instanceId = UUID.randomUUID(); - var elementId = UUID.randomUUID(); - var instanceElement = new InstanceElementDto(instanceId, elementId, null, Map.of(), Map.of()); - acElementHandler.delete(compositionElement, instanceElement); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.DELETED, + acElementHandler.delete(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); config.setDeleteSuccess(false); - acElementHandler.delete(compositionElement, instanceElement); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.UNDEPLOYED, + acElementHandler.delete(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Delete failed!"); } @Test - void testPrime() throws PfModelException { - var config = new SimConfig(); - config.setPrimeTimerMs(1); + void testPrime() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionId = UUID.randomUUID(); - var composition = new CompositionDto(compositionId, Map.of(), Map.of()); - acElementHandler.prime(composition); - verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, - "Primed"); + acElementHandler.prime(COMPOSITION); + verify(intermediaryApi).updateCompositionState( + COMPOSITION.compositionId(), AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed"); config.setPrimeSuccess(false); - acElementHandler.prime(composition); - verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, - StateChangeResult.FAILED, "Prime failed!"); + acElementHandler.prime(COMPOSITION); + verify(intermediaryApi).updateCompositionState( + COMPOSITION.compositionId(), AcTypeState.COMMISSIONED, StateChangeResult.FAILED, "Prime failed!"); } @Test - void testDeprime() throws PfModelException { - var config = new SimConfig(); - config.setDeprimeTimerMs(1); + void testDeprime() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionId = UUID.randomUUID(); - var composition = new CompositionDto(compositionId, Map.of(), Map.of()); - acElementHandler.deprime(composition); - verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, - StateChangeResult.NO_ERROR, "Deprimed"); + acElementHandler.deprime(COMPOSITION); + verify(intermediaryApi).updateCompositionState( + COMPOSITION.compositionId(), AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); config.setDeprimeSuccess(false); - acElementHandler.deprime(composition); - verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.FAILED, - "Deprime failed!"); + acElementHandler.deprime(COMPOSITION); + verify(intermediaryApi).updateCompositionState( + COMPOSITION.compositionId(), AcTypeState.PRIMED, StateChangeResult.FAILED, "Deprime failed!"); } @Test - void testMigrate() throws PfModelException { - var config = new SimConfig(); - config.setUpdateTimerMs(1); + void testMigrate() { + var config = CommonTestData.createSimConfig(); var intermediaryApi = mock(ParticipantIntermediaryApi.class); var simulatorService = new SimulatorService(intermediaryApi); var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); simulatorService.setConfig(config); - var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + var compositionElementTarget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); - var compositionElementTraget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of()); - var instanceId = UUID.randomUUID(); - var element = new AcElementDeploy(); - element.setId(UUID.randomUUID()); - var instanceElement = new InstanceElementDto(instanceId, element.getId(), null, Map.of(), Map.of()); - var instanceElementMigrated = new InstanceElementDto(instanceId, element.getId(), + var instanceElementMigrated = new InstanceElementDto( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, Map.of("key", "value"), Map.of()); acElementHandler - .migrate(compositionElement, compositionElementTraget, instanceElement, instanceElementMigrated); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); config.setMigrateSuccess(false); acElementHandler - .migrate(compositionElement, compositionElementTraget, instanceElement, instanceElementMigrated); - verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!"); } + + @Test + void testMigrateAdd() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + + var compositionElement = new CompositionElementDto( + UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NOT_PRESENT); + + var instanceElement = new InstanceElementDto( + UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of(), ElementState.NOT_PRESENT); + + var compoElTargetAdd = new CompositionElementDto( + UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NEW); + var inElMigratedAdd = new InstanceElementDto( + instanceElement.instanceId(), instanceElement.elementId(), null, Map.of(), Map.of(), ElementState.NEW); + acElementHandler + .migrate(compositionElement, compoElTargetAdd, instanceElement, inElMigratedAdd); + verify(intermediaryApi).updateAutomationCompositionElementState( + instanceElement.instanceId(), instanceElement.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); + } + + @Test + void testMigrateRemove() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + + var compoElTargetRemove = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of(), ElementState.REMOVED); + var inElMigratedRemove = new InstanceElementDto( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + null, Map.of("key", "value"), Map.of(), ElementState.REMOVED); + acElementHandler + .migrate(COMPOSITION_ELEMENT, compoElTargetRemove, INSTANCE_ELEMENT, inElMigratedRemove); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); + } + + @Test + void testMigratePrecheck() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + var compositionElementTarget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElementMigrated = new InstanceElementDto( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + null, Map.of("key", "value"), Map.of()); + acElementHandler.migratePrecheck(COMPOSITION_ELEMENT, compositionElementTarget, + INSTANCE_ELEMENT, instanceElementMigrated); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration precheck completed"); + + config.setMigratePrecheck(false); + acElementHandler.migratePrecheck(COMPOSITION_ELEMENT, compositionElementTarget, + INSTANCE_ELEMENT, instanceElementMigrated); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, + StateChangeResult.FAILED, "Migration precheck failed"); + } + + @Test + void testPrepare() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.prepare(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.NO_ERROR, "Prepare completed"); + + config.setPrepare(false); + acElementHandler.prepare(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.FAILED, "Prepare failed"); + } + + @Test + void testReview() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV2(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.review(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.NO_ERROR, "Review completed"); + + config.setReview(false); + acElementHandler.review(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.FAILED, "Review failed"); + } } diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3Test.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3Test.java new file mode 100644 index 000000000..d2d3d5c7e --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerV3Test.java @@ -0,0 +1,358 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.participant.sim.main.handler; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +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.participant.intermediary.api.CompositionDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState; +import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; +import org.onap.policy.clamp.acm.participant.sim.comm.CommonTestData; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +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.concepts.StateChangeResult; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +class AutomationCompositionElementHandlerV3Test { + + private static final CompositionElementDto COMPOSITION_ELEMENT = + new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); + private static final InstanceElementDto INSTANCE_ELEMENT = + new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + private static final CompositionDto COMPOSITION = new CompositionDto(UUID.randomUUID(), Map.of(), Map.of()); + + @Test + void testDeploy() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.deploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.NO_ERROR, "Deployed"); + + config.setDeploySuccess(false); + acElementHandler.deploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.FAILED, "Deploy failed!"); + } + + @Test + void testUndeploy() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.undeploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.NO_ERROR, "Undeployed"); + + config.setUndeploySuccess(false); + acElementHandler.undeploy(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.FAILED, "Undeploy failed!"); + } + + @Test + void testLock() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.lock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.LOCKED, + StateChangeResult.NO_ERROR, "Locked"); + + config.setLockSuccess(false); + acElementHandler.lock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.UNLOCKED, + StateChangeResult.FAILED, "Lock failed!"); + } + + @Test + void testUnlock() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.unlock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.UNLOCKED, + StateChangeResult.NO_ERROR, "Unlocked"); + + config.setUnlockSuccess(false); + acElementHandler.unlock(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, LockState.LOCKED, + StateChangeResult.FAILED, "Unlock failed!"); + } + + @Test + void testUpdate() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + var instanceElementUpdated = new InstanceElementDto( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), null, + Map.of("key", "value"), Map.of()); + acElementHandler.update(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, instanceElementUpdated); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated"); + + config.setUpdateSuccess(false); + acElementHandler.update(COMPOSITION_ELEMENT, INSTANCE_ELEMENT, instanceElementUpdated); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!"); + } + + @Test + void testDelete() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.delete(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DELETED, + null, StateChangeResult.NO_ERROR, "Deleted"); + + config.setDeleteSuccess(false); + acElementHandler.delete(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.FAILED, "Delete failed!"); + } + + @Test + void testPrime() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.prime(COMPOSITION); + verify(intermediaryApi).updateCompositionState( + COMPOSITION.compositionId(), AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed"); + + config.setPrimeSuccess(false); + acElementHandler.prime(COMPOSITION); + verify(intermediaryApi).updateCompositionState( + COMPOSITION.compositionId(), AcTypeState.COMMISSIONED, StateChangeResult.FAILED, "Prime failed!"); + } + + @Test + void testDeprime() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.deprime(COMPOSITION); + verify(intermediaryApi).updateCompositionState( + COMPOSITION.compositionId(), AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); + + config.setDeprimeSuccess(false); + acElementHandler.deprime(COMPOSITION); + verify(intermediaryApi).updateCompositionState( + COMPOSITION.compositionId(), AcTypeState.PRIMED, StateChangeResult.FAILED, "Deprime failed!"); + } + + @Test + void testMigrate() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + var compositionElementTarget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElementMigrated = new InstanceElementDto( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + null, Map.of("key", "value"), new HashMap<>()); + acElementHandler + .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated, 0); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); + + config.setMigrateSuccess(false); + acElementHandler + .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated, 0); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!"); + } + + @Test + void testMigrateStage() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + var compositionElementTarget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of("stage", List.of(1, 2)), Map.of()); + var instanceElementMigrated = new InstanceElementDto(INSTANCE_ELEMENT.instanceId(), + INSTANCE_ELEMENT.elementId(), null, Map.of(), new HashMap<>()); + acElementHandler + .migrate(COMPOSITION_ELEMENT, compositionElementTarget, INSTANCE_ELEMENT, instanceElementMigrated, 1); + verify(intermediaryApi).updateAutomationCompositionElementStage( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + StateChangeResult.NO_ERROR, 2, "stage 1 Migrated"); + } + + @Test + void testMigrateAdd() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + var compositionElement = new CompositionElementDto( + UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NOT_PRESENT); + + var instanceElement = new InstanceElementDto( + UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of(), ElementState.NOT_PRESENT); + + var compoElTargetAdd = new CompositionElementDto( + UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of(), ElementState.NEW); + var inElMigratedAdd = new InstanceElementDto(instanceElement.instanceId(), instanceElement.elementId(), + null, Map.of(), new HashMap<>(), ElementState.NEW); + acElementHandler + .migrate(compositionElement, compoElTargetAdd, instanceElement, inElMigratedAdd, 0); + verify(intermediaryApi).updateAutomationCompositionElementState( + instanceElement.instanceId(), instanceElement.elementId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); + } + + @Test + void testMigrateRemove() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + + var compoElTargetRemove = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of(), ElementState.REMOVED); + var inElMigratedRemove = new InstanceElementDto( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + null, Map.of("key", "value"), Map.of(), ElementState.REMOVED); + acElementHandler + .migrate(COMPOSITION_ELEMENT, compoElTargetRemove, INSTANCE_ELEMENT, inElMigratedRemove, 0); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed"); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); + } + + @Test + void testMigratePrecheck() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + var compositionElementTarget = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElementMigrated = new InstanceElementDto( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + null, Map.of("key", "value"), Map.of()); + acElementHandler.migratePrecheck(COMPOSITION_ELEMENT, compositionElementTarget, + INSTANCE_ELEMENT, instanceElementMigrated); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration precheck completed"); + + config.setMigratePrecheck(false); + acElementHandler.migratePrecheck(COMPOSITION_ELEMENT, compositionElementTarget, + INSTANCE_ELEMENT, instanceElementMigrated); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), + DeployState.DEPLOYED, null, + StateChangeResult.FAILED, "Migration precheck failed"); + } + + @Test + void testPrepare() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.prepare(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.NO_ERROR, "Prepare completed"); + + config.setPrepare(false); + acElementHandler.prepare(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.FAILED, "Prepare failed"); + } + + @Test + void testReview() { + var config = CommonTestData.createSimConfig(); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var simulatorService = new SimulatorService(intermediaryApi); + var acElementHandler = new AutomationCompositionElementHandlerV3(intermediaryApi, simulatorService); + simulatorService.setConfig(config); + acElementHandler.review(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.NO_ERROR, "Review completed"); + + config.setReview(false); + acElementHandler.review(COMPOSITION_ELEMENT, INSTANCE_ELEMENT); + verify(intermediaryApi).updateAutomationCompositionElementState( + INSTANCE_ELEMENT.instanceId(), INSTANCE_ELEMENT.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.FAILED, "Review failed"); + } +} diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java index 6f4039254..5994328d5 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/AutomationCompositionElementListener.java @@ -89,12 +89,23 @@ public interface AutomationCompositionElementListener { /** * Handle an update on a automation composition element. * - * @param compositionElement the information of the Automation Composition Definition Element + * @param compositionElement the information of the Automation Composition Definition Element * @param compositionElementTarget the information of the Automation Composition Definition Element Target - * @param instanceElement the information of the Automation Composition Instance Element - * @param instanceElementMigrate the information of the Automation Composition Instance Element updated + * @param instanceElement the information of the Automation Composition Instance Element + * @param instanceElementMigrate the information of the Automation Composition Instance Element updated + * @param nextStage the next stage * @throws PfModelException from Policy framework */ void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate, + int nextStage) throws PfModelException; + + void migratePrecheck(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) throws PfModelException; + + void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException; + + void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException; } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/CompositionElementDto.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/CompositionElementDto.java index d203f90cb..50699e22c 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/CompositionElementDto.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/CompositionElementDto.java @@ -25,5 +25,12 @@ import java.util.UUID; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; public record CompositionElementDto(UUID compositionId, ToscaConceptIdentifier elementDefinitionId, - Map<String, Object> inProperties, Map<String, Object> outProperties) { + Map<String, Object> inProperties, Map<String, Object> outProperties, + ElementState state) { + + public CompositionElementDto(UUID compositionId, ToscaConceptIdentifier elementDefinitionId, + Map<String, Object> inProperties, Map<String, Object> outProperties) { + this(compositionId, elementDefinitionId, inProperties, outProperties, ElementState.PRESENT); + + } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ElementState.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ElementState.java new file mode 100644 index 000000000..afb01d014 --- /dev/null +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ElementState.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.participant.intermediary.api; + +public enum ElementState { + PRESENT, + NOT_PRESENT, + REMOVED, + NEW +} diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/InstanceElementDto.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/InstanceElementDto.java index 297af6c43..b4fdefbf3 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/InstanceElementDto.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/InstanceElementDto.java @@ -25,5 +25,11 @@ import java.util.UUID; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; public record InstanceElementDto(UUID instanceId, UUID elementId, ToscaServiceTemplate toscaServiceTemplateFragment, - Map<String, Object> inProperties, Map<String, Object> outProperties) { + Map<String, Object> inProperties, Map<String, Object> outProperties, + ElementState state) { + + public InstanceElementDto(UUID instanceId, UUID elementId, ToscaServiceTemplate toscaServiceTemplateFragment, + Map<String, Object> inProperties, Map<String, Object> outProperties) { + this(instanceId, elementId, toscaServiceTemplateFragment, inProperties, outProperties, ElementState.PRESENT); + } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ParticipantIntermediaryApi.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ParticipantIntermediaryApi.java index 9b3279232..c06ffe62e 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ParticipantIntermediaryApi.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/ParticipantIntermediaryApi.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation. + * Copyright (C) 2021-2024 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,41 +38,52 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; public interface ParticipantIntermediaryApi { /** - * Update the state of a automation composition element. + * Update the state of a AutomationComposition Instance Element. * - * @param automationCompositionId the ID of the automation composition to update the state on - * @param elementId the ID of the automation composition element to update the state on - * @param deployState the Deploy State of the automation composition element - * @param lockState the Lock State of the automation composition element + * @param instance the ID of the AutomationComposition Instance to update the state on + * @param elementId the ID of the AutomationComposition Instance element to update the state on + * @param deployState the Deploy State of the AutomationComposition Instance element + * @param lockState the Lock State of the AutomationComposition Instance element * @param stateChangeResult the indicator if error occurs * @param message the message */ - void updateAutomationCompositionElementState(UUID automationCompositionId, UUID elementId, DeployState deployState, + void updateAutomationCompositionElementState(UUID instance, UUID elementId, DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message); /** - * Get a copy of all AutomationCompositions. + * Update the stage of a AutomationComposition Instance Element. * - * @return get all AutomationCompositions + * @param instance the ID of the AutomationComposition Instance to update the state on + * @param elementId the ID of the AutomationComposition Instance Element to update the state on + * @param stateChangeResult the indicator if error occurs + * @param message the message + */ + void updateAutomationCompositionElementStage(UUID instance, UUID elementId, StateChangeResult stateChangeResult, + int stage, String message); + + /** + * Get a copy of all AutomationComposition Instances. + * + * @return get all AutomationComposition Instances */ Map<UUID, AutomationComposition> getAutomationCompositions(); /** - * Get a copy of the AutomationComposition by automationCompositionId. + * Get a copy of the AutomationComposition Instance by AutomationComposition Instance Id. * - * @param automationCompositionId the ID of the automation composition to update the state on - * @return get the AutomationComposition + * @param instanceId the ID of the AutomationComposition Instance to update the state on + * @return get the AutomationComposition Instance */ - AutomationComposition getAutomationComposition(UUID automationCompositionId); + AutomationComposition getAutomationComposition(UUID instanceId); /** - * Get a copy of the AutomationCompositionElement by automationCompositionId and elementId. + * Get a copy of the AutomationCompositionElement by AutomationComposition Instance Id and elementId. * - * @param automationCompositionId the ID of the automation composition to update the state on - * @param elementId the ID of the automation composition element to update the state on + * @param instanceId the ID of the AutomationComposition Instance to update the state on + * @param elementId the ID of the AutomationComposition Instance Element to update the state on * @return get the AutomationCompositionElement */ - AutomationCompositionElement getAutomationCompositionElement(UUID automationCompositionId, UUID elementId); + AutomationCompositionElement getAutomationCompositionElement(UUID instanceId, UUID elementId); /** * Get a copy of all AutomationCompositionElementDefinition from all primed compositions. @@ -99,15 +110,15 @@ public interface ParticipantIntermediaryApi { AutomationCompositionElementDefinition getAcElementDefinition(UUID compositionId, ToscaConceptIdentifier elementId); /** - * Send Automation Composition Element update Info to AC-runtime. + * Send AutomationComposition Instance Element update Info to AC-runtime. * - * @param automationCompositionId the ID of the automation composition to update the states - * @param elementId the ID of the automation composition element to update the states + * @param instanceId the ID of the AutomationComposition Instance to update the states + * @param elementId the ID of the AutomationComposition Instance Element to update the states * @param useState the use State * @param operationalState the operational State * @param outProperties the output Properties Map */ - void sendAcElementInfo(UUID automationCompositionId, UUID elementId, String useState, String operationalState, + void sendAcElementInfo(UUID instanceId, UUID elementId, String useState, String operationalState, Map<String, Object> outProperties); /** diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV1.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV1.java index cf5ac419d..34bdc349b 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV1.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV1.java @@ -209,7 +209,8 @@ public abstract class AcElementListenerV1 @Override public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, - InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) throws PfModelException { + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate, + int stage) throws PfModelException { var element = new AcElementDeploy(); element.setId(instanceElementMigrate.elementId()); element.setDefinition(compositionElementTarget.elementDefinitionId()); @@ -224,4 +225,29 @@ public abstract class AcElementListenerV1 intermediaryApi.updateAutomationCompositionElementState(instanceId, element.getId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); } + + @Override + public void migratePrecheck(CompositionElementDto compositionElement, + CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, + InstanceElementDto instanceElementMigrate) throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElementMigrate.instanceId(), + instanceElementMigrate.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration Precheck completed"); + } + + @Override + public void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Review completed"); + } + + @Override + public void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.UNDEPLOYED, null, + StateChangeResult.NO_ERROR, "Prepare completed"); + } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV2.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV2.java index 3fe33191f..7db220095 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV2.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV2.java @@ -36,7 +36,8 @@ import org.onap.policy.models.base.PfModelException; * Wrapper of AutomationCompositionElementListener. * Valid since 7.1.1 release. */ -public abstract class AcElementListenerV2 implements AutomationCompositionElementListener { +public abstract class AcElementListenerV2 + implements AutomationCompositionElementListener, AutomationCompositionElementListenerV2 { protected final ParticipantIntermediaryApi intermediaryApi; private static final String NOT_SUPPORTED = "not supported!"; @@ -98,9 +99,41 @@ public abstract class AcElementListenerV2 implements AutomationCompositionElemen @Override public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate, int stage) + throws PfModelException { + migrate(compositionElement, compositionElementTarget, instanceElement, instanceElementMigrate); + } + + @Override + public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) throws PfModelException { intermediaryApi.updateAutomationCompositionElementState(instanceElementMigrate.instanceId(), instanceElementMigrate.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); } + + @Override + public void migratePrecheck(CompositionElementDto compositionElement, + CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, + InstanceElementDto instanceElementMigrate) throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElementMigrate.instanceId(), + instanceElementMigrate.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration Precheck completed"); + } + + @Override + public void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Review completed"); + } + + @Override + public void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException { + intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.UNDEPLOYED, null, + StateChangeResult.NO_ERROR, "Prepare completed"); + } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3.java new file mode 100644 index 000000000..d63323d1a --- /dev/null +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3.java @@ -0,0 +1,119 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.acm.participant.intermediary.api.impl;
+
+import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener;
+import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto;
+import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto;
+import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto;
+import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi;
+import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
+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.concepts.StateChangeResult;
+import org.onap.policy.models.base.PfModelException;
+
+/**
+ * Wrapper of AutomationCompositionElementListener.
+ * Valid since 8.0.1 release.
+ */
+public abstract class AcElementListenerV3 implements AutomationCompositionElementListener {
+ protected final ParticipantIntermediaryApi intermediaryApi;
+
+ protected AcElementListenerV3(ParticipantIntermediaryApi intermediaryApi) {
+ this.intermediaryApi = intermediaryApi;
+ }
+
+ @Override
+ public void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
+ throws PfModelException {
+ intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
+ instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked");
+ }
+
+ @Override
+ public void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
+ throws PfModelException {
+ intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
+ instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked");
+ }
+
+ @Override
+ public void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
+ throws PfModelException {
+ intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
+ instanceElement.elementId(), DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted");
+ }
+
+ @Override
+ public void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement,
+ InstanceElementDto instanceElementUpdated) throws PfModelException {
+ intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
+ instanceElement.elementId(), DeployState.DEPLOYED, null,
+ StateChangeResult.NO_ERROR, "Update not supported");
+
+ }
+
+ @Override
+ public void prime(CompositionDto composition) throws PfModelException {
+ intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED,
+ StateChangeResult.NO_ERROR, "Primed");
+ }
+
+ @Override
+ public void deprime(CompositionDto composition) throws PfModelException {
+ intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED,
+ StateChangeResult.NO_ERROR, "Deprimed");
+ }
+
+ @Override
+ public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget,
+ InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate, int stage)
+ throws PfModelException {
+ intermediaryApi.updateAutomationCompositionElementState(instanceElementMigrate.instanceId(),
+ instanceElementMigrate.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated");
+ }
+
+ @Override
+ public void migratePrecheck(CompositionElementDto compositionElement,
+ CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement,
+ InstanceElementDto instanceElementMigrate) throws PfModelException {
+ intermediaryApi.updateAutomationCompositionElementState(instanceElementMigrate.instanceId(),
+ instanceElementMigrate.elementId(), DeployState.DEPLOYED, null,
+ StateChangeResult.NO_ERROR, "Migration Precheck completed");
+ }
+
+ @Override
+ public void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
+ throws PfModelException {
+ intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
+ instanceElement.elementId(), DeployState.DEPLOYED, null,
+ StateChangeResult.NO_ERROR, "Review completed");
+ }
+
+ @Override
+ public void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
+ throws PfModelException {
+ intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
+ instanceElement.elementId(), DeployState.UNDEPLOYED, null,
+ StateChangeResult.NO_ERROR, "Prepare completed");
+ }
+}
diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AutomationCompositionElementListenerV2.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AutomationCompositionElementListenerV2.java new file mode 100644 index 000000000..721caa88e --- /dev/null +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AutomationCompositionElementListenerV2.java @@ -0,0 +1,58 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.participant.intermediary.api.impl; + +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; +import org.onap.policy.models.base.PfModelException; + +public interface AutomationCompositionElementListenerV2 { + + void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; + + void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; + + void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; + + void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; + + void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException; + + void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement, + InstanceElementDto instanceElementUpdated) throws PfModelException; + + void prime(CompositionDto composition) throws PfModelException; + + void deprime(CompositionDto composition) throws PfModelException; + + void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) throws PfModelException; + + void migratePrecheck(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, + InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) throws PfModelException; + + void review(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException; + + void prepare(CompositionElementDto compositionElement, InstanceElementDto instanceElement) + throws PfModelException; +} diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java index 5cdbacab6..233b55926 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImpl.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation. + * Copyright (C) 2021-2024 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -50,16 +50,23 @@ public class ParticipantIntermediaryApiImpl implements ParticipantIntermediaryAp private final CacheProvider cacheProvider; @Override - public void updateAutomationCompositionElementState(UUID automationCompositionId, UUID id, DeployState newState, + public void updateAutomationCompositionElementState(UUID instance, UUID elementId, DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message) { - automationCompositionHandler.updateAutomationCompositionElementState(automationCompositionId, id, newState, - lockState, stateChangeResult, message); + automationCompositionHandler.updateAutomationCompositionElementState(instance, elementId, deployState, + lockState, stateChangeResult, message); } @Override - public void sendAcElementInfo(UUID automationCompositionId, UUID elementId, String useState, + public void updateAutomationCompositionElementStage(UUID instance, UUID elementId, + StateChangeResult stateChangeResult, int stage, String message) { + automationCompositionHandler.updateAutomationCompositionElementStage(instance, elementId, stateChangeResult, + stage, message); + } + + @Override + public void sendAcElementInfo(UUID instance, UUID elementId, String useState, String operationalState, Map<String, Object> outProperties) { - automationCompositionHandler.sendAcElementInfo(automationCompositionId, elementId, useState, operationalState, + automationCompositionHandler.sendAcElementInfo(instance, elementId, useState, operationalState, outProperties); } @@ -75,8 +82,8 @@ public class ParticipantIntermediaryApiImpl implements ParticipantIntermediaryAp } @Override - public AutomationCompositionElement getAutomationCompositionElement(UUID automationCompositionId, UUID elementId) { - var automationComposition = cacheProvider.getAutomationCompositions().get(automationCompositionId); + public AutomationCompositionElement getAutomationCompositionElement(UUID instanceId, UUID elementId) { + var automationComposition = cacheProvider.getAutomationCompositions().get(instanceId); if (automationComposition == null) { return null; } @@ -91,8 +98,8 @@ public class ParticipantIntermediaryApiImpl implements ParticipantIntermediaryAp } @Override - public AutomationComposition getAutomationComposition(UUID automationCompositionId) { - var automationComposition = cacheProvider.getAutomationCompositions().get(automationCompositionId); + public AutomationComposition getAutomationComposition(UUID instanceId) { + var automationComposition = cacheProvider.getAutomationCompositions().get(instanceId); return automationComposition != null ? new AutomationComposition(automationComposition) : null; } @@ -107,7 +114,7 @@ public class ParticipantIntermediaryApiImpl implements ParticipantIntermediaryAp UUID compositionId) { var acElementDefinitions = cacheProvider.getAcElementsDefinitions().get(compositionId); if (acElementDefinitions == null) { - return null; + return Map.of(); } return PfUtils.mapMap(acElementDefinitions, AutomationCompositionElementDefinition::new); } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/comm/AcPrepareListener.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/comm/AcPrepareListener.java new file mode 100644 index 000000000..0f6d2c09f --- /dev/null +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/comm/AcPrepareListener.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.participant.intermediary.comm; + +import org.onap.policy.clamp.acm.participant.intermediary.handler.ParticipantHandler; +import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionPrepare; +import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantMessageType; +import org.springframework.stereotype.Component; + +@Component +public class AcPrepareListener extends ParticipantListener<AutomationCompositionPrepare> { + + /** + * Constructs the object. + * + * @param participantHandler the handler for managing the state of the participant + */ + public AcPrepareListener(final ParticipantHandler participantHandler) { + super(AutomationCompositionPrepare.class, participantHandler, + participantHandler::handleAutomationCompositionPrepare); + } + + + @Override + public String getType() { + return ParticipantMessageType.AUTOMATION_COMPOSITION_PREPARE.name(); + } +} diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcLockHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcLockHandler.java index 89daa5fd2..95613cc9e 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcLockHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcLockHandler.java @@ -27,6 +27,7 @@ import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionStateChange; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -79,6 +80,7 @@ public class AcLockHandler { int startPhase = ParticipantUtils.findStartPhase(compositionInProperties); if (startPhaseMsg.equals(startPhase)) { element.setLockState(LockState.LOCKING); + element.setSubState(SubState.NONE); var compositionElement = cacheProvider.createCompositionElementDto( automationComposition.getCompositionId(), element, compositionInProperties); var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(), @@ -99,6 +101,7 @@ public class AcLockHandler { int startPhase = ParticipantUtils.findStartPhase(compositionInProperties); if (startPhaseMsg.equals(startPhase)) { element.setLockState(LockState.UNLOCKING); + element.setSubState(SubState.NONE); var compositionElement = cacheProvider.createCompositionElementDto( automationComposition.getCompositionId(), element, compositionInProperties); var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(), diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandler.java new file mode 100644 index 000000000..1dbf2c935 --- /dev/null +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandler.java @@ -0,0 +1,197 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.participant.intermediary.handler; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState; +import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; +import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +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.DeployState; +import org.onap.policy.clamp.models.acm.concepts.SubState; +import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration; +import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionPrepare; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class AcSubStateHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(AcSubStateHandler.class); + + private final CacheProvider cacheProvider; + private final ThreadHandler listener; + + /** + * Handles AutomationComposition Migration Precheck. + * + * @param migrationMsg the AutomationCompositionMigration + */ + public void handleAcMigrationPrecheck(AutomationCompositionMigration migrationMsg) { + if (migrationMsg.getAutomationCompositionId() == null || migrationMsg.getCompositionTargetId() == null) { + return; + } + + var automationComposition = cacheProvider.getAutomationComposition(migrationMsg.getAutomationCompositionId()); + if (automationComposition == null) { + LOGGER.debug("Automation composition {} does not use this participant", + migrationMsg.getAutomationCompositionId()); + return; + } + automationComposition.setSubState(SubState.MIGRATION_PRECHECKING); + for (var participantDeploy : migrationMsg.getParticipantUpdatesList()) { + if (cacheProvider.getParticipantId().equals(participantDeploy.getParticipantId())) { + + callParticipantMigratePrecheck(migrationMsg.getMessageId(), participantDeploy.getAcElementList(), + automationComposition, migrationMsg.getCompositionTargetId()); + } + } + } + + private void callParticipantMigratePrecheck(UUID messageId, List<AcElementDeploy> acElements, + AutomationComposition automationComposition, UUID compositionTargetId) { + var compositionElementMap = cacheProvider.getCompositionElementDtoMap(automationComposition); + var instanceElementMap = cacheProvider.getInstanceElementDtoMap(automationComposition); + var acElementList = automationComposition.getElements(); + for (var acElement : acElements) { + var element = acElementList.get(acElement.getId()); + if (element != null) { + element.setSubState(SubState.MIGRATION_PRECHECKING); + } + } + var acCopyMigrateTo = new AutomationComposition(automationComposition); + var acElementCopyList = acCopyMigrateTo.getElements(); + for (var acElement : acElements) { + var element = acElementCopyList.get(acElement.getId()); + if (element != null) { + AcmUtils.recursiveMerge(element.getProperties(), acElement.getProperties()); + element.setDefinition(acElement.getDefinition()); + } else { + element = CacheProvider.createAutomationCompositionElement(acElement); + element.setSubState(SubState.MIGRATION_PRECHECKING); + acElementCopyList.put(element.getId(), element); + } + } + var toDelete = acElementCopyList.values().stream() + .filter(el -> !SubState.MIGRATION_PRECHECKING.equals(el.getSubState())) + .map(AutomationCompositionElement::getId) + .toList(); + toDelete.forEach(acElementCopyList::remove); + + var compositionElementTargetMap = cacheProvider.getCompositionElementDtoMap(acCopyMigrateTo, + compositionTargetId); + var instanceElementMigrateMap = cacheProvider.getInstanceElementDtoMap(acCopyMigrateTo); + + for (var acElement : acElements) { + var compositionElement = compositionElementMap.get(acElement.getId()); + var compositionElementTarget = compositionElementTargetMap.get(acElement.getId()); + var instanceElement = instanceElementMap.get(acElement.getId()); + var instanceElementMigrate = instanceElementMigrateMap.get(acElement.getId()); + + if (instanceElement == null) { + // new element scenario + compositionElement = new CompositionElementDto(automationComposition.getCompositionId(), + acElement.getDefinition(), Map.of(), Map.of(), ElementState.NOT_PRESENT); + instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), acElement.getId(), + new ToscaServiceTemplate(), Map.of(), Map.of(), ElementState.NOT_PRESENT); + compositionElementTarget = CacheProvider.changeStateToNew(compositionElementTarget); + instanceElementMigrate = CacheProvider.changeStateToNew(instanceElementMigrate); + } + + listener.migratePrecheck(messageId, compositionElement, compositionElementTarget, + instanceElement, instanceElementMigrate); + } + + for (var elementId : toDelete) { + var compositionDtoTarget = + new CompositionElementDto(compositionTargetId, + automationComposition.getElements().get(elementId).getDefinition(), + Map.of(), Map.of(), ElementState.REMOVED); + var instanceDtoTarget = + new InstanceElementDto(automationComposition.getInstanceId(), elementId, + null, Map.of(), Map.of(), ElementState.REMOVED); + + listener.migratePrecheck(messageId, compositionElementMap.get(elementId), compositionDtoTarget, + instanceElementMap.get(elementId), instanceDtoTarget); + } + } + + /** + * Handle AutomationComposition Prepare message. + * + * @param acPrepareMsg the AutomationCompositionPrepare message + */ + public void handleAcPrepare(AutomationCompositionPrepare acPrepareMsg) { + if (acPrepareMsg.isPreDeploy()) { + for (var participantPrepare : acPrepareMsg.getParticipantList()) { + if (cacheProvider.getParticipantId().equals(participantPrepare.getParticipantId())) { + cacheProvider.initializeAutomationComposition(acPrepareMsg.getCompositionId(), + acPrepareMsg.getAutomationCompositionId(), participantPrepare, DeployState.UNDEPLOYED, + SubState.PREPARING); + callParticipanPrepare(acPrepareMsg.getMessageId(), participantPrepare.getAcElementList(), + acPrepareMsg.getAutomationCompositionId()); + } + } + } else { + var automationComposition = + cacheProvider.getAutomationComposition(acPrepareMsg.getAutomationCompositionId()); + automationComposition.setSubState(SubState.REVIEWING); + callParticipanReview(acPrepareMsg.getMessageId(), automationComposition); + } + } + + private void callParticipanPrepare(UUID messageId, List<AcElementDeploy> acElementList, UUID instanceId) { + var automationComposition = cacheProvider.getAutomationComposition(instanceId); + for (var elementDeploy : acElementList) { + var element = automationComposition.getElements().get(elementDeploy.getId()); + var compositionInProperties = cacheProvider + .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition()); + var compositionElement = cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(), + element, compositionInProperties); + var instanceElement = new InstanceElementDto(instanceId, elementDeploy.getId(), + elementDeploy.getToscaServiceTemplateFragment(), + elementDeploy.getProperties(), element.getOutProperties()); + listener.prepare(messageId, compositionElement, instanceElement); + } + } + + private void callParticipanReview(UUID messageId, AutomationComposition automationComposition) { + for (var element : automationComposition.getElements().values()) { + var compositionInProperties = cacheProvider + .getCommonProperties(automationComposition.getCompositionId(), element.getDefinition()); + element.setSubState(SubState.REVIEWING); + var compositionElement = cacheProvider.createCompositionElementDto(automationComposition.getCompositionId(), + element, compositionInProperties); + var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(), + null, element.getProperties(), element.getOutProperties()); + listener.review(messageId, compositionElement, instanceElement); + } + } +} diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java index b60d6372c..6d94efb0f 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandler.java @@ -21,20 +21,24 @@ package org.onap.policy.clamp.acm.participant.intermediary.handler; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState; import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessagePublisher; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; 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.DeployState; +import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy; import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeploy; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration; @@ -119,8 +123,7 @@ public class AutomationCompositionHandler { updateMsg.getAutomationCompositionId()); automationComposition.setDeployState(DeployState.UPDATING); var acCopy = new AutomationComposition(automationComposition); - updateExistingElementsOnThisParticipant(updateMsg.getAutomationCompositionId(), participantDeploy, - DeployState.UPDATING); + updateExistingElementsOnThisParticipant(updateMsg.getAutomationCompositionId(), participantDeploy); callParticipantUpdateProperty(updateMsg.getMessageId(), participantDeploy.getAcElementList(), acCopy); } @@ -171,57 +174,70 @@ public class AutomationCompositionHandler { } } - private Map<UUID, CompositionElementDto> getCompositionElementDtoMap(AutomationComposition automationComposition, - UUID compositionId) { - Map<UUID, CompositionElementDto> map = new HashMap<>(); - for (var element : automationComposition.getElements().values()) { - var compositionInProperties = cacheProvider.getCommonProperties(compositionId, element.getDefinition()); - var compositionElement = cacheProvider - .createCompositionElementDto(compositionId, element, compositionInProperties); - map.put(element.getId(), compositionElement); - } - return map; - } - - private Map<UUID, CompositionElementDto> getCompositionElementDtoMap(AutomationComposition automationComposition) { - return getCompositionElementDtoMap(automationComposition, automationComposition.getCompositionId()); - } - - private Map<UUID, InstanceElementDto> getInstanceElementDtoMap(AutomationComposition automationComposition) { - Map<UUID, InstanceElementDto> map = new HashMap<>(); - var serviceTemplateFragment = cacheProvider - .getServiceTemplateFragmentMap().get(automationComposition.getCompositionId()); - for (var element : automationComposition.getElements().values()) { - var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(), - serviceTemplateFragment, element.getProperties(), element.getOutProperties()); - map.put(element.getId(), instanceElement); - } - return map; - } - private void callParticipantUpdateProperty(UUID messageId, List<AcElementDeploy> acElements, AutomationComposition acCopy) { - var instanceElementDtoMap = getInstanceElementDtoMap(acCopy); - var instanceElementDtoMapUpdated = getInstanceElementDtoMap( + var instanceElementDtoMap = cacheProvider.getInstanceElementDtoMap(acCopy); + var instanceElementDtoMapUpdated = cacheProvider.getInstanceElementDtoMap( cacheProvider.getAutomationComposition(acCopy.getInstanceId())); - var compositionElementDtoMap = getCompositionElementDtoMap(acCopy); + var compositionElementDtoMap = cacheProvider.getCompositionElementDtoMap(acCopy); for (var acElement : acElements) { listener.update(messageId, compositionElementDtoMap.get(acElement.getId()), instanceElementDtoMap.get(acElement.getId()), instanceElementDtoMapUpdated.get(acElement.getId())); } } - private void updateExistingElementsOnThisParticipant(UUID instanceId, ParticipantDeploy participantDeploy, - DeployState deployState) { + private void migrateExistingElementsOnThisParticipant(UUID instanceId, UUID compositionTargetId, + ParticipantDeploy participantDeploy, int stage) { + var automationComposition = cacheProvider.getAutomationComposition(instanceId); + var acElementList = automationComposition.getElements(); + for (var element : participantDeploy.getAcElementList()) { + var compositionInProperties = + cacheProvider.getCommonProperties(compositionTargetId, element.getDefinition()); + var stageSet = ParticipantUtils.findStageSet(compositionInProperties); + if (stageSet.contains(stage)) { + var acElement = acElementList.get(element.getId()); + if (acElement == null) { + var newElement = CacheProvider.createAutomationCompositionElement(element); + newElement.setParticipantId(participantDeploy.getParticipantId()); + newElement.setDeployState(DeployState.MIGRATING); + newElement.setLockState(LockState.LOCKED); + newElement.setStage(stage); + + acElementList.put(element.getId(), newElement); + LOGGER.info("New Ac Element with id {} is added in Migration", element.getId()); + } else { + AcmUtils.recursiveMerge(acElement.getProperties(), element.getProperties()); + acElement.setDeployState(DeployState.MIGRATING); + acElement.setStage(stage); + acElement.setDefinition(element.getDefinition()); + } + } + } + // Check for missing elements and remove them from cache + var elementsToRemove = findElementsToRemove(participantDeploy.getAcElementList(), acElementList); + for (var key : elementsToRemove) { + acElementList.remove(key); + LOGGER.info("Element with id {} is removed in Migration", key); + } + } + + private void updateExistingElementsOnThisParticipant(UUID instanceId, ParticipantDeploy participantDeploy) { var acElementList = cacheProvider.getAutomationComposition(instanceId).getElements(); for (var element : participantDeploy.getAcElementList()) { var acElement = acElementList.get(element.getId()); AcmUtils.recursiveMerge(acElement.getProperties(), element.getProperties()); - acElement.setDeployState(deployState); + acElement.setDeployState(DeployState.UPDATING); + acElement.setSubState(SubState.NONE); acElement.setDefinition(element.getDefinition()); } } + private List<UUID> findElementsToRemove(List<AcElementDeploy> acElementDeployList, Map<UUID, + AutomationCompositionElement> acElementList) { + var acElementDeploySet = acElementDeployList.stream().map(AcElementDeploy::getId).collect(Collectors.toSet()); + return acElementList.keySet().stream().filter(id -> !acElementDeploySet.contains(id)).toList(); + } + /** * Method to handle when the new state from participant is UNINITIALISED state. * @@ -261,6 +277,7 @@ public class AutomationCompositionHandler { int startPhase = ParticipantUtils.findStartPhase(compositionInProperties); if (startPhaseMsg.equals(startPhase)) { element.setDeployState(DeployState.DELETING); + element.setSubState(SubState.NONE); var compositionElement = cacheProvider.createCompositionElementDto( automationComposition.getCompositionId(), element, compositionInProperties); var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(), @@ -292,27 +309,66 @@ public class AutomationCompositionHandler { for (var participantDeploy : migrationMsg.getParticipantUpdatesList()) { if (cacheProvider.getParticipantId().equals(participantDeploy.getParticipantId())) { - updateExistingElementsOnThisParticipant(migrationMsg.getAutomationCompositionId(), participantDeploy, - DeployState.MIGRATING); + migrateExistingElementsOnThisParticipant(migrationMsg.getAutomationCompositionId(), + migrationMsg.getCompositionTargetId(), participantDeploy, migrationMsg.getStage()); callParticipantMigrate(migrationMsg.getMessageId(), participantDeploy.getAcElementList(), - acCopy, migrationMsg.getCompositionTargetId()); + acCopy, migrationMsg.getCompositionTargetId(), migrationMsg.getStage()); } } } private void callParticipantMigrate(UUID messageId, List<AcElementDeploy> acElements, - AutomationComposition acCopy, UUID compositionTargetId) { - var compositionElementMap = getCompositionElementDtoMap(acCopy); - var instanceElementMap = getInstanceElementDtoMap(acCopy); + AutomationComposition acCopy, UUID compositionTargetId, int stage) { + var compositionElementMap = cacheProvider.getCompositionElementDtoMap(acCopy); + var instanceElementMap = cacheProvider.getInstanceElementDtoMap(acCopy); var automationComposition = cacheProvider.getAutomationComposition(acCopy.getInstanceId()); - var compositionElementTargetMap = getCompositionElementDtoMap(automationComposition, compositionTargetId); - var instanceElementMigrateMap = getInstanceElementDtoMap(automationComposition); + var compositionElementTargetMap = cacheProvider.getCompositionElementDtoMap(automationComposition, + compositionTargetId); + var instanceElementMigrateMap = cacheProvider.getInstanceElementDtoMap(automationComposition); + // Call migrate for newly added and updated elements for (var acElement : acElements) { - listener.migrate(messageId, compositionElementMap.get(acElement.getId()), - compositionElementTargetMap.get(acElement.getId()), - instanceElementMap.get(acElement.getId()), instanceElementMigrateMap.get(acElement.getId())); + var compositionInProperties = cacheProvider + .getCommonProperties(compositionTargetId, acElement.getDefinition()); + var stageSet = ParticipantUtils.findStageSet(compositionInProperties); + if (stageSet.contains(stage)) { + if (instanceElementMap.get(acElement.getId()) == null) { + var compositionElementDto = + new CompositionElementDto(acCopy.getCompositionId(), acElement.getDefinition(), + Map.of(), Map.of(), ElementState.NOT_PRESENT); + var instanceElementDto = new InstanceElementDto(acCopy.getInstanceId(), acElement.getId(), + null, Map.of(), Map.of(), ElementState.NOT_PRESENT); + var compositionElementTargetDto = CacheProvider.changeStateToNew( + compositionElementTargetMap.get(acElement.getId())); + var instanceElementMigrateDto = CacheProvider + .changeStateToNew(instanceElementMigrateMap.get(acElement.getId())); + + listener.migrate(messageId, compositionElementDto, compositionElementTargetDto, instanceElementDto, + instanceElementMigrateDto, stage); + } else { + listener.migrate(messageId, compositionElementMap.get(acElement.getId()), + compositionElementTargetMap.get(acElement.getId()), + instanceElementMap.get(acElement.getId()), instanceElementMigrateMap.get(acElement.getId()), + stage); + } + } + } + if (stage == 0) { + // Call migrate for removed elements + List<UUID> removedElements = findElementsToRemove(acElements, acCopy.getElements()); + for (var elementId : removedElements) { + var compositionDtoTarget = + new CompositionElementDto(compositionTargetId, + acCopy.getElements().get(elementId).getDefinition(), + Map.of(), Map.of(), ElementState.REMOVED); + var instanceDtoTarget = + new InstanceElementDto(acCopy.getInstanceId(), elementId, null, Map.of(), + Map.of(), ElementState.REMOVED); + + listener.migrate(messageId, compositionElementMap.get(elementId), compositionDtoTarget, + instanceElementMap.get(elementId), instanceDtoTarget, 0); + } } } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java index 1f4c036e7..7cf83db9d 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandler.java @@ -37,10 +37,12 @@ import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition; import org.onap.policy.clamp.models.acm.concepts.ParticipantState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantMessageType; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantStatus; +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; @@ -55,27 +57,94 @@ public class AutomationCompositionOutHandler { private final CacheProvider cacheProvider; /** + * Handle a automation composition element stage change message. + * + * @param instance the automationComposition Id + * @param elementId the automationComposition Element Id + * @param stage the next stage + * @param message the message + * @param stateChangeResult the indicator if error occurs + */ + public void updateAutomationCompositionElementStage(UUID instance, UUID elementId, + StateChangeResult stateChangeResult, int stage, String message) { + if (!validateData(instance, elementId, stateChangeResult)) { + return; + } + + var automationComposition = cacheProvider.getAutomationComposition(instance); + if (automationComposition == null) { + LOGGER.error("Cannot update Automation composition element stage, Automation composition id {} not present", + instance); + return; + } + + var element = automationComposition.getElements().get(elementId); + if (element == null) { + var msg = "Cannot update Automation composition element stage, AC Element id {} not present"; + LOGGER.error(msg, elementId); + return; + } + + var automationCompositionStateChangeAck = + new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK); + automationCompositionStateChangeAck.setParticipantId(cacheProvider.getParticipantId()); + automationCompositionStateChangeAck.setMessage(AcmUtils.validatedMessage(message)); + automationCompositionStateChangeAck.setResponseTo(cacheProvider.getMsgIdentification().get(element.getId())); + automationCompositionStateChangeAck.setStateChangeResult(stateChangeResult); + automationCompositionStateChangeAck.setStage(stage); + automationCompositionStateChangeAck.setAutomationCompositionId(instance); + automationCompositionStateChangeAck.getAutomationCompositionResultMap().put(element.getId(), + new AcElementDeployAck(element.getDeployState(), element.getLockState(), element.getOperationalState(), + element.getUseState(), element.getOutProperties(), true, message)); + LOGGER.debug("Automation composition element {} stage changed to {}", elementId, stage); + automationCompositionStateChangeAck.setResult(true); + publisher.sendAutomationCompositionAck(automationCompositionStateChangeAck); + cacheProvider.getMsgIdentification().remove(element.getId()); + } + + private boolean validateData(UUID instance, UUID elementId, StateChangeResult stateChangeResult) { + if (instance == null || elementId == null) { + LOGGER.error("Not valid Ac instance, id is null"); + return false; + } + if (stateChangeResult == null) { + LOGGER.error("Not valid Ac instance, stateChangeResult is null"); + return false; + } + if (!StateChangeResult.NO_ERROR.equals(stateChangeResult) + && !StateChangeResult.FAILED.equals(stateChangeResult)) { + LOGGER.error("Not valid Ac instance, stateChangeResult is not valid"); + return false; + } + return true; + } + + /** * Handle a automation composition element state change message. * - * @param automationCompositionId the automationComposition Id + * @param instance the automationComposition Id * @param elementId the automationComposition Element Id * @param deployState the DeployState state * @param lockState the LockState state * @param message the message * @param stateChangeResult the indicator if error occurs */ - public void updateAutomationCompositionElementState(UUID automationCompositionId, UUID elementId, + public void updateAutomationCompositionElementState(UUID instance, UUID elementId, DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message) { + if (!validateData(instance, elementId, stateChangeResult)) { + return; + } - if (automationCompositionId == null || elementId == null) { - LOGGER.error("Cannot update Automation composition element state, id is null"); + if ((deployState != null && lockState != null) || (deployState == null && lockState == null) + || AcmUtils.isInTransitionalState(deployState, lockState, SubState.NONE)) { + LOGGER.error("state error {} and {} cannot be handled", deployState, lockState); return; } - var automationComposition = cacheProvider.getAutomationComposition(automationCompositionId); + var automationComposition = cacheProvider.getAutomationComposition(instance); if (automationComposition == null) { LOGGER.error("Cannot update Automation composition element state, Automation composition id {} not present", - automationCompositionId); + instance); return; } @@ -86,14 +155,13 @@ public class AutomationCompositionOutHandler { return; } - if ((element.getRestarting() == null) - && ((deployState != null && lockState != null) || (deployState == null && lockState == null))) { - LOGGER.error("state error {} and {} cannot be handled", deployState, lockState); - return; - } - element.setRestarting(null); - - if (deployState != null) { + if (deployState != null && !SubState.NONE.equals(element.getSubState())) { + handleSubState(automationComposition, element); + if (!StateChangeResult.NO_ERROR.equals(stateChangeResult)) { + stateChangeResult = StateChangeResult.NO_ERROR; + LOGGER.warn("SubState has always NO_ERROR result!"); + } + } else if (deployState != null) { handleDeployState(automationComposition, element, deployState); } if (lockState != null) { @@ -104,10 +172,10 @@ public class AutomationCompositionOutHandler { new AutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK); automationCompositionStateChangeAck.setParticipantId(cacheProvider.getParticipantId()); automationCompositionStateChangeAck.setReplicaId(cacheProvider.getReplicaId()); - automationCompositionStateChangeAck.setMessage(message); + automationCompositionStateChangeAck.setMessage(AcmUtils.validatedMessage(message)); automationCompositionStateChangeAck.setResponseTo(cacheProvider.getMsgIdentification().get(element.getId())); automationCompositionStateChangeAck.setStateChangeResult(stateChangeResult); - automationCompositionStateChangeAck.setAutomationCompositionId(automationCompositionId); + automationCompositionStateChangeAck.setAutomationCompositionId(instance); automationCompositionStateChangeAck.getAutomationCompositionResultMap().put(element.getId(), new AcElementDeployAck(element.getDeployState(), element.getLockState(), element.getOperationalState(), element.getUseState(), element.getOutProperties(), true, message)); @@ -132,6 +200,7 @@ public class AutomationCompositionOutHandler { } automationComposition.setDeployState(deployState); automationComposition.setLockState(element.getLockState()); + automationComposition.setSubState(SubState.NONE); if (DeployState.DELETED.equals(deployState)) { cacheProvider.removeAutomationComposition(automationComposition.getInstanceId()); @@ -146,6 +215,16 @@ public class AutomationCompositionOutHandler { .filter(acElement -> !lockState.equals(acElement.getLockState())).findAny(); if (checkOpt.isEmpty()) { automationComposition.setLockState(lockState); + automationComposition.setSubState(SubState.NONE); + } + } + + private void handleSubState(AutomationComposition automationComposition, AutomationCompositionElement element) { + element.setSubState(SubState.NONE); + var checkOpt = automationComposition.getElements().values().stream() + .filter(acElement -> !SubState.NONE.equals(acElement.getSubState())).findAny(); + if (checkOpt.isEmpty()) { + automationComposition.setSubState(SubState.NONE); } } @@ -221,9 +300,29 @@ public class AutomationCompositionOutHandler { */ public void updateCompositionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult, String message) { + if (compositionId == null) { + LOGGER.error("Cannot update Automation composition definition state, id is null"); + return; + } + + if (stateChangeResult == null) { + LOGGER.error("Cannot update Automation composition definition state, stateChangeResult is null"); + return; + } + if (!StateChangeResult.NO_ERROR.equals(stateChangeResult) + && !StateChangeResult.FAILED.equals(stateChangeResult)) { + LOGGER.error("Cannot update Automation composition definition state, stateChangeResult is not valid"); + return; + } + + if ((state == null) || AcTypeState.PRIMING.equals(state) || AcTypeState.DEPRIMING.equals(state)) { + LOGGER.error("state invalid {} cannot be handled", state); + return; + } + var participantPrimeAck = new ParticipantPrimeAck(); participantPrimeAck.setCompositionId(compositionId); - participantPrimeAck.setMessage(message); + participantPrimeAck.setMessage(AcmUtils.validatedMessage(message)); participantPrimeAck.setResult(true); participantPrimeAck.setResponseTo(cacheProvider.getMsgIdentification().get(compositionId)); participantPrimeAck.setCompositionState(state); diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProvider.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProvider.java index 29b77fcb6..65ad627d1 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProvider.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProvider.java @@ -30,7 +30,10 @@ import lombok.Getter; import lombok.NonNull; import lombok.Setter; import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ElementState; +import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; import org.onap.policy.clamp.acm.participant.intermediary.parameters.ParticipantParameters; +import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; 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; @@ -39,6 +42,7 @@ import org.onap.policy.clamp.models.acm.concepts.LockState; import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy; import org.onap.policy.clamp.models.acm.concepts.ParticipantRestartAc; import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.models.base.PfUtils; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; @@ -161,16 +165,28 @@ public class CacheProvider { */ public void initializeAutomationComposition(@NonNull UUID compositionId, @NonNull UUID instanceId, ParticipantDeploy participantDeploy) { + initializeAutomationComposition(compositionId, instanceId, participantDeploy, + DeployState.DEPLOYING, SubState.NONE); + } + + /** + * Initialize an AutomationComposition from a ParticipantDeploy. + * + * @param compositionId the composition Id + * @param instanceId the Automation Composition Id + * @param participantDeploy the ParticipantDeploy + * @param deployState the DeployState + * @param subState the SubState + */ + public void initializeAutomationComposition(@NonNull UUID compositionId, @NonNull UUID instanceId, + ParticipantDeploy participantDeploy, DeployState deployState, SubState subState) { var acLast = automationCompositions.get(instanceId); Map<UUID, AutomationCompositionElement> acElementMap = new LinkedHashMap<>(); for (var element : participantDeploy.getAcElementList()) { - var acElement = new AutomationCompositionElement(); - acElement.setId(element.getId()); + var acElement = createAutomationCompositionElement(element); acElement.setParticipantId(getParticipantId()); - acElement.setDefinition(element.getDefinition()); - acElement.setDeployState(DeployState.DEPLOYING); - acElement.setLockState(LockState.NONE); - acElement.setProperties(element.getProperties()); + acElement.setDeployState(deployState); + acElement.setSubState(subState); var acElementLast = acLast != null ? acLast.getElements().get(element.getId()) : null; if (acElementLast != null) { acElement.setOutProperties(acElementLast.getOutProperties()); @@ -186,6 +202,8 @@ public class CacheProvider { automationComposition.setCompositionId(compositionId); automationComposition.setInstanceId(instanceId); automationComposition.setElements(acElementMap); + automationComposition.setDeployState(deployState); + automationComposition.setSubState(subState); automationCompositions.put(instanceId, automationComposition); } @@ -208,6 +226,7 @@ public class CacheProvider { acElement.setDefinition(element.getDefinition()); acElement.setDeployState(element.getDeployState()); acElement.setLockState(element.getLockState()); + acElement.setSubState(SubState.NONE); acElement.setOperationalState(element.getOperationalState()); acElement.setUseState(element.getUseState()); acElement.setProperties(element.getProperties()); @@ -228,6 +247,22 @@ public class CacheProvider { } /** + * Create AutomationCompositionElement to save in memory. + * + * @param element AcElementDeploy + * @return a new AutomationCompositionElement + */ + public static AutomationCompositionElement createAutomationCompositionElement(AcElementDeploy element) { + var acElement = new AutomationCompositionElement(); + acElement.setId(element.getId()); + acElement.setDefinition(element.getDefinition()); + acElement.setProperties(element.getProperties()); + acElement.setSubState(SubState.NONE); + acElement.setLockState(LockState.LOCKED); + return acElement; + } + + /** * Create CompositionElementDto. * * @param compositionId the composition Id @@ -236,10 +271,78 @@ public class CacheProvider { * @return the CompositionElementDto */ public CompositionElementDto createCompositionElementDto(UUID compositionId, AutomationCompositionElement element, - Map<String, Object> compositionInProperties) { + Map<String, Object> compositionInProperties) { var compositionOutProperties = getAcElementsDefinitions() .get(compositionId).get(element.getDefinition()).getOutProperties(); return new CompositionElementDto(compositionId, element.getDefinition(), compositionInProperties, compositionOutProperties); } + + /** + * Get a Map of CompositionElementDto by elementId from the elements of an AutomationComposition. + * + * @param automationComposition the AutomationComposition + * @param compositionId the compositionId + * @return the Map of CompositionElementDto + */ + public Map<UUID, CompositionElementDto> getCompositionElementDtoMap(AutomationComposition automationComposition, + UUID compositionId) { + var definitions = acElementsDefinitions.get(compositionId); + Map<UUID, CompositionElementDto> map = new HashMap<>(); + for (var element : automationComposition.getElements().values()) { + var definition = definitions.get(element.getDefinition()); + var compositionElement = (definition != null) + ? new CompositionElementDto(compositionId, element.getDefinition(), + definition.getAutomationCompositionElementToscaNodeTemplate().getProperties(), + definition.getOutProperties()) : + new CompositionElementDto(compositionId, element.getDefinition(), + Map.of(), Map.of(), ElementState.NOT_PRESENT); + map.put(element.getId(), compositionElement); + } + return map; + } + + public Map<UUID, CompositionElementDto> getCompositionElementDtoMap(AutomationComposition automationComposition) { + return getCompositionElementDtoMap(automationComposition, automationComposition.getCompositionId()); + } + + /** + * Get a Map of InstanceElementDto by elementId from the elements of an AutomationComposition. + * + * @param automationComposition the AutomationComposition + * @return the Map of InstanceElementDto + */ + public Map<UUID, InstanceElementDto> getInstanceElementDtoMap(AutomationComposition automationComposition) { + Map<UUID, InstanceElementDto> map = new HashMap<>(); + var serviceTemplateFragment = serviceTemplateFragmentMap.get(automationComposition.getCompositionId()); + for (var element : automationComposition.getElements().values()) { + var instanceElement = new InstanceElementDto(automationComposition.getInstanceId(), element.getId(), + serviceTemplateFragment, element.getProperties(), element.getOutProperties()); + map.put(element.getId(), instanceElement); + } + return map; + } + + /** + * Create a new InstanceElementDto record with state New. + * + * @param instanceElement the InstanceElementDto + * @return a new InstanceElementDto + */ + public static InstanceElementDto changeStateToNew(InstanceElementDto instanceElement) { + return new InstanceElementDto(instanceElement.instanceId(), instanceElement.elementId(), + instanceElement.toscaServiceTemplateFragment(), + instanceElement.inProperties(), instanceElement.outProperties(), ElementState.NEW); + } + + /** + * Create a new CompositionElementDto record with state New. + * + * @param compositionElement the CompositionElementDto + * @return a new CompositionElementDto + */ + public static CompositionElementDto changeStateToNew(CompositionElementDto compositionElement) { + return new CompositionElementDto(compositionElement.compositionId(), compositionElement.elementDefinitionId(), + compositionElement.inProperties(), compositionElement.outProperties(), ElementState.NEW); + } } 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 5ae8f0422..6615ae102 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 @@ -28,6 +28,7 @@ import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessag import org.onap.policy.clamp.models.acm.concepts.ParticipantState; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeploy; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration; +import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionPrepare; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionStateChange; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantAckMessage; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantDeregister; @@ -55,6 +56,7 @@ public class ParticipantHandler { private final AutomationCompositionHandler automationCompositionHandler; private final AcLockHandler acLockHandler; + private final AcSubStateHandler acSubStateHandler; private final AcDefinitionHandler acDefinitionHandler; private final ParticipantMessagePublisher publisher; private final CacheProvider cacheProvider; @@ -106,7 +108,11 @@ public class ParticipantHandler { value = "listener.automation_composition_migration", description = "AUTOMATION_COMPOSITION_MIGRATION messages received") public void handleAutomationCompositionMigration(AutomationCompositionMigration migrationMsg) { - automationCompositionHandler.handleAutomationCompositionMigration(migrationMsg); + if (Boolean.TRUE.equals(migrationMsg.getPrecheck())) { + acSubStateHandler.handleAcMigrationPrecheck(migrationMsg); + } else { + automationCompositionHandler.handleAutomationCompositionMigration(migrationMsg); + } } /** @@ -119,6 +125,11 @@ public class ParticipantHandler { automationCompositionHandler.handleAcPropertyUpdate(propertyUpdateMsg); } + @Timed(value = "listener.prepare", description = "AUTOMATION_COMPOSITION_PREPARE message received") + public void handleAutomationCompositionPrepare(AutomationCompositionPrepare acPrepareMsg) { + acSubStateHandler.handleAcPrepare(acPrepareMsg); + } + /** * Check if a participant message applies to this participant handler. * diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java index 00e0044b4..9a43bf4c3 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandler.java @@ -53,7 +53,7 @@ public class ThreadHandler implements Closeable { private final ParticipantIntermediaryApi intermediaryApi; private final CacheProvider cacheProvider; - private final Map<UUID, Future> executionMap = new ConcurrentHashMap<>(); + private final Map<UUID, Future<?>> executionMap = new ConcurrentHashMap<>(); private final ExecutorService executor = Context.taskWrapping(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())); @@ -295,21 +295,24 @@ public class ThreadHandler implements Closeable { * @param compositionElementTarget the information of the Automation Composition Definition Element Target * @param instanceElement the information of the Automation Composition Instance Element * @param instanceElementMigrate the information of the Automation Composition Instance Element updated + * @param stage the stage */ public void migrate(UUID messageId, CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, - InstanceElementDto instanceElementMigrate) { + InstanceElementDto instanceElementMigrate, int stage) { cleanExecution(instanceElement.elementId(), messageId); var result = executor.submit(() -> - this.migrateProcess(compositionElement, compositionElementTarget, instanceElement, instanceElementMigrate)); + this.migrateProcess(compositionElement, compositionElementTarget, + instanceElement, instanceElementMigrate, stage)); executionMap.put(instanceElement.elementId(), result); } private void migrateProcess(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, - InstanceElementDto instanceElementMigrate) { + InstanceElementDto instanceElementMigrate, int stage) { try { - listener.migrate(compositionElement, compositionElementTarget, instanceElement, instanceElementMigrate); + listener.migrate(compositionElement, compositionElementTarget, + instanceElement, instanceElementMigrate, stage); } catch (PfModelException e) { LOGGER.error("Automation composition element migrate failed {} {}", instanceElement.elementId(), e.getMessage()); @@ -319,4 +322,93 @@ public class ThreadHandler implements Closeable { } executionMap.remove(instanceElement.elementId()); } + + /** + * Handles AutomationComposition Migration Precheck. + * + * @param messageId the messageId + * @param compositionElement the information of the Automation Composition Definition Element + * @param compositionElementTarget the information of the Automation Composition Definition Element Target + * @param instanceElement the information of the Automation Composition Instance Element + * @param instanceElementMigrate the information of the Automation Composition Instance Element updated + */ + public void migratePrecheck(UUID messageId, CompositionElementDto compositionElement, + CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, + InstanceElementDto instanceElementMigrate) { + cleanExecution(instanceElement.elementId(), messageId); + var result = executor.submit(() -> + this.migratePrecheckProcess(compositionElement, compositionElementTarget, instanceElement, + instanceElementMigrate)); + executionMap.put(instanceElement.elementId(), result); + } + + private void migratePrecheckProcess(CompositionElementDto compositionElement, + CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, + InstanceElementDto instanceElementMigrate) { + try { + listener.migratePrecheck(compositionElement, compositionElementTarget, instanceElement, + instanceElementMigrate); + } catch (PfModelException e) { + LOGGER.error("Automation composition element migrate precheck failed {} {}", + instanceElement.elementId(), e.getMessage()); + intermediaryApi.updateAutomationCompositionElementState( + instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.FAILED, "Automation composition element migrate precheck failed"); + } + executionMap.remove(instanceElement.elementId()); + } + + /** + * Handles AutomationComposition Prepare Post Deploy. + * + * @param messageId the messageId + * @param compositionElement the information of the Automation Composition Definition Element + * @param instanceElement the information of the Automation Composition Instance Element + */ + public void review(UUID messageId, CompositionElementDto compositionElement, + InstanceElementDto instanceElement) { + cleanExecution(instanceElement.elementId(), messageId); + var result = executor.submit(() -> this.reviewProcess(compositionElement, instanceElement)); + executionMap.put(instanceElement.elementId(), result); + } + + private void reviewProcess(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + try { + listener.review(compositionElement, instanceElement); + } catch (PfModelException e) { + LOGGER.error("Automation composition element Review failed {} {}", + instanceElement.elementId(), e.getMessage()); + intermediaryApi.updateAutomationCompositionElementState( + instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, + null, StateChangeResult.FAILED, "Automation composition element Review failed"); + } + executionMap.remove(instanceElement.elementId()); + } + + /** + * Handles AutomationComposition Prepare Pre Deploy. + * + * @param messageId the messageId + * @param compositionElement the information of the Automation Composition Definition Element + * @param instanceElement the information of the Automation Composition Instance Element + */ + public void prepare(UUID messageId, CompositionElementDto compositionElement, + InstanceElementDto instanceElement) { + cleanExecution(instanceElement.elementId(), messageId); + var result = executor.submit(() -> this.prepareProcess(compositionElement, instanceElement)); + executionMap.put(instanceElement.elementId(), result); + } + + private void prepareProcess(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + try { + listener.prepare(compositionElement, instanceElement); + } catch (PfModelException e) { + LOGGER.error("Automation composition element prepare Pre Deploy failed {} {}", + instanceElement.elementId(), e.getMessage()); + intermediaryApi.updateAutomationCompositionElementState( + instanceElement.instanceId(), instanceElement.elementId(), DeployState.UNDEPLOYED, + null, StateChangeResult.FAILED, "Automation composition element prepare Pre Deploy failed"); + } + executionMap.remove(instanceElement.elementId()); + } } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/parameters/ParticipantIntermediaryParameters.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/parameters/ParticipantIntermediaryParameters.java index 1c36ad17f..47fa7754e 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/parameters/ParticipantIntermediaryParameters.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/parameters/ParticipantIntermediaryParameters.java @@ -62,6 +62,6 @@ public class ParticipantIntermediaryParameters { @NotNull @Valid - private Topics topics; + private Topics topics = new Topics(); } diff --git a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/parameters/Topics.java b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/parameters/Topics.java index ddf72052f..7a93255b0 100644 --- a/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/parameters/Topics.java +++ b/participant/participant-intermediary/src/main/java/org/onap/policy/clamp/acm/participant/intermediary/parameters/Topics.java @@ -24,6 +24,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; /** @@ -32,6 +33,7 @@ import lombok.Setter; @Getter @Setter @AllArgsConstructor +@NoArgsConstructor public class Topics { @NotNull diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV1Test.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV1Test.java index 7355b03e9..12acdbbb6 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV1Test.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV1Test.java @@ -157,23 +157,61 @@ class AcElementListenerV1Test { var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); - acElementListenerV1.migrate(compositionElement, compositionElement, instanceElement, instanceElement); + acElementListenerV1.migrate(compositionElement, compositionElement, instanceElement, instanceElement, 0); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); } + @Test + void migratePrecheckTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV1 = createAcElementListenerV1(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV1.migratePrecheck(compositionElement, compositionElement, instanceElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration Precheck completed"); + } + + @Test + void reviewTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV1 = createAcElementListenerV1(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV1.review(compositionElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Review completed"); + } + + @Test + void prepareTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV1 = createAcElementListenerV1(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV1.prepare(compositionElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.UNDEPLOYED, null, + StateChangeResult.NO_ERROR, "Prepare completed"); + } + private AcElementListenerV1 createAcElementListenerV1(ParticipantIntermediaryApi intermediaryApi) { return new AcElementListenerV1(intermediaryApi) { @Override - public void deploy(UUID instanceId, AcElementDeploy element, Map<String, Object> properties) - throws PfModelException { - + public void deploy(UUID instanceId, AcElementDeploy element, Map<String, Object> properties) { + // dummy implementation } @Override - public void undeploy(UUID instanceId, UUID elementId) throws PfModelException { - + public void undeploy(UUID instanceId, UUID elementId) { + // dummy implementation } }; } diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV2Test.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV2Test.java index c8ab9e222..a6cb7b005 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV2Test.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV2Test.java @@ -134,22 +134,61 @@ class AcElementListenerV2Test { var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), Map.of(), Map.of()); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); - acElementListenerV2.migrate(compositionElement, compositionElement, instanceElement, instanceElement); + acElementListenerV2.migrate(compositionElement, compositionElement, instanceElement, instanceElement, 0); verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated"); } + @Test + void migratePrecheckTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV1 = createAcElementListenerV2(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV1.migratePrecheck(compositionElement, compositionElement, instanceElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration Precheck completed"); + } + + @Test + void reviewTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV1 = createAcElementListenerV2(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV1.review(compositionElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Review completed"); + } + + @Test + void prepareTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV1 = createAcElementListenerV2(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV1.prepare(compositionElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.UNDEPLOYED, null, + StateChangeResult.NO_ERROR, "Prepare completed"); + } + private AcElementListenerV2 createAcElementListenerV2(ParticipantIntermediaryApi intermediaryApi) { return new AcElementListenerV2(intermediaryApi) { @Override - public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { + public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + // dummy implementation } @Override - public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { + public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + // dummy implementation } }; } diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java new file mode 100644 index 000000000..1385f439a --- /dev/null +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AcElementListenerV3Test.java @@ -0,0 +1,180 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.participant.intermediary.api.impl; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.util.Map; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; +import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +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.concepts.StateChangeResult; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +class AcElementListenerV3Test { + + @Test + void lockTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV2.lock(compositionElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); + } + + @Test + void deleteTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV2.delete(compositionElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); + } + + @Test + void updateTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV2.update(compositionElement, instanceElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Update not supported"); + } + + @Test + void unlockTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV2.unlock(compositionElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); + } + + @Test + void primeTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var compositionId = UUID.randomUUID(); + var toscaConceptIdentifier = new ToscaConceptIdentifier(); + var composition = new CompositionDto(compositionId, Map.of(toscaConceptIdentifier, Map.of()), Map.of()); + acElementListenerV2.prime(composition); + verify(intermediaryApi) + .updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed"); + } + + @Test + void deprimeTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var compositionId = UUID.randomUUID(); + var toscaConceptIdentifier = new ToscaConceptIdentifier(); + var composition = new CompositionDto(compositionId, Map.of(toscaConceptIdentifier, Map.of()), Map.of()); + acElementListenerV2.deprime(composition); + verify(intermediaryApi) + .updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, "Deprimed"); + } + + @Test + void migrateTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV2 = createAcElementListenerV3(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV2.migrate(compositionElement, compositionElement, instanceElement, instanceElement, 0); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migrated"); + } + + @Test + void migratePrecheckTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV1 = createAcElementListenerV3(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV1.migratePrecheck(compositionElement, compositionElement, instanceElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Migration Precheck completed"); + } + + @Test + void reviewTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV1 = createAcElementListenerV3(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV1.review(compositionElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.DEPLOYED, null, + StateChangeResult.NO_ERROR, "Review completed"); + } + + @Test + void prepareTest() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementListenerV1 = createAcElementListenerV3(intermediaryApi); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + Map.of(), Map.of()); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, Map.of(), Map.of()); + acElementListenerV1.prepare(compositionElement, instanceElement); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceElement.instanceId(), + instanceElement.elementId(), DeployState.UNDEPLOYED, null, + StateChangeResult.NO_ERROR, "Prepare completed"); + } + + private AcElementListenerV3 createAcElementListenerV3(ParticipantIntermediaryApi intermediaryApi) { + return new AcElementListenerV3(intermediaryApi) { + @Override + public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + // dummy implementation + } + + @Override + public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) { + // dummy implementation + } + }; + } +} diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AutomationCompositionElementListenerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AutomationCompositionElementListenerTest.java deleted file mode 100644 index b01065d09..000000000 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/AutomationCompositionElementListenerTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.clamp.acm.participant.intermediary.api.impl; - -import static org.assertj.core.api.Assertions.assertThatCode; - -import java.util.Map; -import java.util.UUID; -import org.junit.jupiter.api.Test; -import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; -import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; -import org.onap.policy.clamp.acm.participant.intermediary.handler.DummyAcElementListener; -import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; - -class AutomationCompositionElementListenerTest { - - @Test - void defaultTest() { - var listener = new DummyAcElementListener(); - var compositionElementDto = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), - Map.of(), Map.of()); - var instanceElementDto = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), null, - Map.of(), Map.of()); - assertThatCode(() -> listener.lock(compositionElementDto, instanceElementDto)).doesNotThrowAnyException(); - assertThatCode(() -> listener.unlock(compositionElementDto, instanceElementDto)).doesNotThrowAnyException(); - } -} diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImplTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImplTest.java index 22929a237..71af77fbf 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImplTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/api/impl/ParticipantIntermediaryApiImplTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation. + * Copyright (C) 2021-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,7 +84,7 @@ class ParticipantIntermediaryApiImplTest { var automationComposiitonHandler = mock(AutomationCompositionOutHandler.class); var apiImpl = new ParticipantIntermediaryApiImpl(automationComposiitonHandler, mock(CacheProvider.class)); apiImpl.sendAcDefinitionInfo(COMPOSITION_ID, DEFINITION_ELEMENT_ID, MAP); - verify(automationComposiitonHandler).sendAcDefinitionInfo(COMPOSITION_ID, DEFINITION_ELEMENT_ID, MAP);; + verify(automationComposiitonHandler).sendAcDefinitionInfo(COMPOSITION_ID, DEFINITION_ELEMENT_ID, MAP); } @Test @@ -134,7 +134,7 @@ class ParticipantIntermediaryApiImplTest { assertEquals(map, mapResult); var result = apiImpl.getAcElementsDefinitions(UUID.randomUUID()); - assertThat(result).isNull(); + assertThat(result).isEmpty(); result = apiImpl.getAcElementsDefinitions(COMPOSITION_ID); assertEquals(elementsDefinitions, result); diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/comm/ParticipantCommTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/comm/ParticipantCommTest.java index eaf89ec51..39e51f576 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/comm/ParticipantCommTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/comm/ParticipantCommTest.java @@ -88,6 +88,9 @@ class ParticipantCommTest { var acMigrationListener = new AutomationCompositionMigrationListener(participantHandler); assertEquals(ParticipantMessageType.AUTOMATION_COMPOSITION_MIGRATION.name(), acMigrationListener.getType()); + + var acPrepareListener = new AcPrepareListener(participantHandler); + assertEquals(ParticipantMessageType.AUTOMATION_COMPOSITION_PREPARE.name(), acPrepareListener.getType()); } @Test diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandlerTest.java new file mode 100644 index 000000000..8fad1d22b --- /dev/null +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AcSubStateHandlerTest.java @@ -0,0 +1,199 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.participant.intermediary.handler; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +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.participant.intermediary.main.parameters.CommonTestData; +import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; +import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy; +import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration; +import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionPrepare; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; + +class AcSubStateHandlerTest { + + @Test + void handleAcStateChangeNullTest() { + var cacheProvider = mock(CacheProvider.class); + var ach = new AcSubStateHandler(cacheProvider, mock(ThreadHandler.class)); + + var acMigration = new AutomationCompositionMigration(); + acMigration.setPrecheck(true); + assertDoesNotThrow(() -> ach.handleAcMigrationPrecheck(acMigration)); + + var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); + acMigration.setAutomationCompositionId(automationComposition.getInstanceId()); + acMigration.setCompositionTargetId(UUID.randomUUID()); + assertDoesNotThrow(() -> ach.handleAcMigrationPrecheck(acMigration)); + + var acPrepare = new AutomationCompositionPrepare(); + assertDoesNotThrow(() -> ach.handleAcPrepare(acPrepare)); + + acPrepare.setAutomationCompositionId(automationComposition.getInstanceId()); + assertDoesNotThrow(() -> ach.handleAcPrepare(acPrepare)); + } + + @Test + void handleAcMigrationPrecheckTest() { + var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); + automationComposition.setCompositionId(UUID.randomUUID()); + automationComposition.setInstanceId(UUID.randomUUID()); + automationComposition.setCompositionTargetId(UUID.randomUUID()); + var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters()); + var definitions = + CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition); + cacheProvider.addElementDefinition(automationComposition.getCompositionId(), definitions); + cacheProvider.addElementDefinition(automationComposition.getCompositionTargetId(), definitions); + var participantDeploy = + CommonTestData.createparticipantDeploy(cacheProvider.getParticipantId(), automationComposition); + cacheProvider.initializeAutomationComposition(automationComposition.getCompositionId(), + automationComposition.getInstanceId(), participantDeploy); + var migrationMsg = new AutomationCompositionMigration(); + migrationMsg.setStage(0); + migrationMsg.setCompositionId(automationComposition.getCompositionId()); + migrationMsg.setAutomationCompositionId(automationComposition.getInstanceId()); + migrationMsg.setCompositionTargetId(automationComposition.getCompositionTargetId()); + migrationMsg.setParticipantUpdatesList(List.of(participantDeploy)); + migrationMsg.setPrecheck(true); + var listener = mock(ThreadHandler.class); + var ach = new AcSubStateHandler(cacheProvider, listener); + ach.handleAcMigrationPrecheck(migrationMsg); + verify(listener, times(automationComposition.getElements().size())) + .migratePrecheck(any(), any(), any(), any(), any()); + } + + @Test + void handleAcMigrationPrecheckAddRemoveTest() { + var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); + automationComposition.setCompositionId(UUID.randomUUID()); + automationComposition.setInstanceId(UUID.randomUUID()); + var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters()); + var definitions = + CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition); + cacheProvider.addElementDefinition(automationComposition.getCompositionId(), definitions); + var participantDeploy = + CommonTestData.createparticipantDeploy(cacheProvider.getParticipantId(), automationComposition); + cacheProvider.initializeAutomationComposition(automationComposition.getCompositionId(), + automationComposition.getInstanceId(), participantDeploy); + + var acMigrate = new AutomationComposition(automationComposition); + acMigrate.setCompositionTargetId(UUID.randomUUID()); + + // replacing first element with new one + var element = acMigrate.getElements().values().iterator().next(); + element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.0.0")); + element.setId(UUID.randomUUID()); + + var migrateDefinitions = + CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate); + cacheProvider.addElementDefinition(acMigrate.getCompositionTargetId(), migrateDefinitions); + + var migrationMsg = new AutomationCompositionMigration(); + migrationMsg.setStage(0); + migrationMsg.setCompositionId(acMigrate.getCompositionId()); + migrationMsg.setAutomationCompositionId(acMigrate.getInstanceId()); + migrationMsg.setCompositionTargetId(acMigrate.getCompositionTargetId()); + var participantMigrate = CommonTestData.createparticipantDeploy(cacheProvider.getParticipantId(), acMigrate); + migrationMsg.setParticipantUpdatesList(List.of(participantMigrate)); + var listener = mock(ThreadHandler.class); + var ach = new AcSubStateHandler(cacheProvider, listener); + ach.handleAcMigrationPrecheck(migrationMsg); + verify(listener, times(acMigrate.getElements().size() + 1)) + .migratePrecheck(any(), any(), any(), any(), any()); + } + + @Test + void handlePrepareTest() { + var listener = mock(ThreadHandler.class); + var cacheProvider = mock(CacheProvider.class); + var ach = new AcSubStateHandler(cacheProvider, listener); + + var acPrepareMsg = new AutomationCompositionPrepare(); + acPrepareMsg.setPreDeploy(true); + assertDoesNotThrow(() -> ach.handleAcPrepare(acPrepareMsg)); + + acPrepareMsg.setParticipantId(CommonTestData.getParticipantId()); + when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId()); + var participantDeploy = new ParticipantDeploy(); + participantDeploy.setParticipantId(CommonTestData.getParticipantId()); + acPrepareMsg.getParticipantList().add(participantDeploy); + + var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); + acPrepareMsg.setAutomationCompositionId(automationComposition.getInstanceId()); + when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId())) + .thenReturn(automationComposition); + Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> map = new HashMap<>(); + for (var element : automationComposition.getElements().values()) { + var acElementDeploy = new AcElementDeploy(); + acElementDeploy.setProperties(Map.of()); + acElementDeploy.setId(element.getId()); + participantDeploy.getAcElementList().add(acElementDeploy); + map.put(element.getDefinition(), new AutomationCompositionElementDefinition()); + } + when(cacheProvider.getAcElementsDefinitions()) + .thenReturn(Map.of(automationComposition.getCompositionId(), map)); + + ach.handleAcPrepare(acPrepareMsg); + verify(listener, times(automationComposition.getElements().size())).prepare(any(), any(), any()); + } + + @Test + void handleReviewTest() { + var cacheProvider = mock(CacheProvider.class); + when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId()); + + var acPrepareMsg = new AutomationCompositionPrepare(); + acPrepareMsg.setPreDeploy(false); + acPrepareMsg.setParticipantId(CommonTestData.getParticipantId()); + + var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); + acPrepareMsg.setAutomationCompositionId(automationComposition.getInstanceId()); + when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId())) + .thenReturn(automationComposition); + Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> map = new HashMap<>(); + for (var element : automationComposition.getElements().values()) { + var acElementDeploy = new AcElementDeploy(); + acElementDeploy.setProperties(Map.of()); + acElementDeploy.setId(element.getId()); + map.put(element.getDefinition(), new AutomationCompositionElementDefinition()); + } + when(cacheProvider.getAcElementsDefinitions()) + .thenReturn(Map.of(automationComposition.getCompositionId(), map)); + + var listener = mock(ThreadHandler.class); + var ach = new AcSubStateHandler(cacheProvider, listener); + ach.handleAcPrepare(acPrepareMsg); + verify(listener, times(automationComposition.getElements().size())).review(any(), any(), any()); + } +} diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandlerTest.java index 40e3b1eec..ec61f886e 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandlerTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionHandlerTest.java @@ -23,18 +23,22 @@ package org.onap.policy.clamp.acm.participant.intermediary.handler; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; 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.participant.intermediary.comm.ParticipantMessagePublisher; import org.onap.policy.clamp.acm.participant.intermediary.main.parameters.CommonTestData; import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy; @@ -196,36 +200,145 @@ class AutomationCompositionHandlerTest { } @Test - void handleAutomationCompositionMigrationTest() { - var listener = mock(ThreadHandler.class); - var cacheProvider = mock(CacheProvider.class); - var ach = new AutomationCompositionHandler(cacheProvider, mock(ParticipantMessagePublisher.class), listener); + void handleMigrationNullTest() { + var ach = new AutomationCompositionHandler( + mock(CacheProvider.class), mock(ParticipantMessagePublisher.class), mock(ThreadHandler.class)); var migrationMsg = new AutomationCompositionMigration(); + migrationMsg.setStage(0); assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg)); - var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); + migrationMsg.setAutomationCompositionId(UUID.randomUUID()); migrationMsg.setCompositionTargetId(UUID.randomUUID()); - migrationMsg.setAutomationCompositionId(automationComposition.getInstanceId()); assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg)); - when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId())) - .thenReturn(automationComposition); - var participantDeploy = new ParticipantDeploy(); - participantDeploy.setParticipantId(CommonTestData.getParticipantId()); - when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId()); - migrationMsg.getParticipantUpdatesList().add(participantDeploy); - Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> map = new HashMap<>(); - for (var element : automationComposition.getElements().values()) { - var acElementDeploy = new AcElementDeploy(); - acElementDeploy.setProperties(Map.of()); - acElementDeploy.setId(element.getId()); - acElementDeploy.setDefinition(element.getDefinition()); - participantDeploy.getAcElementList().add(acElementDeploy); - map.put(element.getDefinition(), new AutomationCompositionElementDefinition()); - } - when(cacheProvider.getAcElementsDefinitions()) - .thenReturn(Map.of(automationComposition.getCompositionId(), map, - migrationMsg.getCompositionTargetId(), map)); + } + + @Test + void handleAutomationCompositionMigrationTest() { + var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); + automationComposition.setCompositionId(UUID.randomUUID()); + automationComposition.setInstanceId(UUID.randomUUID()); + automationComposition.setCompositionTargetId(UUID.randomUUID()); + var definitions = + CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition); + var participantDeploy = + CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition); + + var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(), + automationComposition.getInstanceId(), definitions, + automationComposition.getCompositionTargetId(), definitions); + + testMigration(cacheProvider, automationComposition, 0, automationComposition.getElements().size()); + } + + @Test + void handleMigrationAddRemoveTest() { + var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); + automationComposition.setCompositionId(UUID.randomUUID()); + automationComposition.setInstanceId(UUID.randomUUID()); + var acMigrate = new AutomationComposition(automationComposition); + acMigrate.setCompositionTargetId(UUID.randomUUID()); + + // replacing first element with new one + var element = acMigrate.getElements().values().iterator().next(); + element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.0.0")); + element.setId(UUID.randomUUID()); + + var migrateDefinitions = + CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate); + + var participantDeploy = + CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition); + var definitions = + CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition); + var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(), + automationComposition.getInstanceId(), definitions, + acMigrate.getCompositionTargetId(), migrateDefinitions); + + testMigration(cacheProvider, acMigrate, 0, acMigrate.getElements().size() + 1); + } + + @Test + void handleAcMigrationStageTest() { + var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); + automationComposition.setCompositionId(UUID.randomUUID()); + automationComposition.setInstanceId(UUID.randomUUID()); + + var acMigrate = new AutomationComposition(automationComposition); + acMigrate.setCompositionTargetId(UUID.randomUUID()); + + // replacing first element with new one + var element = acMigrate.getElements().values().iterator().next(); + element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.2.4")); + element.setId(UUID.randomUUID()); + + // replacing definition version + acMigrate.getElements().values().forEach(el -> el.setDefinition( + new ToscaConceptIdentifier(el.getDefinition().getName(), "1.2.4"))); + + var migrateDefinitions = + CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate); + + migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate() + .setProperties(Map.of("stage", List.of(0, 1)))); + + var participantDeploy = + CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition); + var definitions = + CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition); + var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(), + automationComposition.getInstanceId(), definitions, + acMigrate.getCompositionTargetId(), migrateDefinitions); + + // scenario 1,2 + migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate() + .setProperties(Map.of("stage", List.of(1, 2)))); + + // expected the element deleted + testMigration(cacheProvider, acMigrate, 0, 1); + + // expected 4 elements from stage 1 + testMigration(cacheProvider, acMigrate, 1, 4); + + // scenario 0,2 + cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(), + automationComposition.getInstanceId(), definitions, + acMigrate.getCompositionTargetId(), migrateDefinitions); + + migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate() + .setProperties(Map.of("stage", List.of(0, 2)))); + + // expected the element deleted + 4 elements from stage 0 + testMigration(cacheProvider, acMigrate, 0, 5); + + // expected 0 elements + testMigration(cacheProvider, acMigrate, 1, 0); + } + + private CacheProvider createCacheProvider(ParticipantDeploy participantDeploy, + UUID compositionId, UUID instanceId, List<AutomationCompositionElementDefinition> definitions, + UUID compositionTargetId, List<AutomationCompositionElementDefinition> migrateDefinitions) { + var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters()); + cacheProvider.addElementDefinition(compositionId, definitions); + cacheProvider.initializeAutomationComposition(compositionId, instanceId, participantDeploy); + cacheProvider.addElementDefinition(compositionTargetId, migrateDefinitions); + return cacheProvider; + } + + private void testMigration(CacheProvider cacheProvider, AutomationComposition acMigrate, + int stage, int expectedMigrated) { + var migrationMsg = new AutomationCompositionMigration(); + migrationMsg.setStage(stage); + migrationMsg.setCompositionId(acMigrate.getCompositionId()); + migrationMsg.setAutomationCompositionId(acMigrate.getInstanceId()); + migrationMsg.setCompositionTargetId(acMigrate.getCompositionTargetId()); + var participantMigrate = CommonTestData.createparticipantDeploy(cacheProvider.getParticipantId(), acMigrate); + migrationMsg.setParticipantUpdatesList(List.of(participantMigrate)); + var listener = mock(ThreadHandler.class); + + clearInvocations(); + var ach = new AutomationCompositionHandler(cacheProvider, mock(ParticipantMessagePublisher.class), listener); ach.handleAutomationCompositionMigration(migrationMsg); - verify(listener, times(automationComposition.getElements().size())).migrate(any(), any(), any(), any(), any()); + verify(listener, times(expectedMigrated)).migrate(any(), any(), any(), any(), any(), anyInt()); } + } diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java index eed5319f8..202f25c6f 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/AutomationCompositionOutHandlerTest.java @@ -20,7 +20,6 @@ package org.onap.policy.clamp.acm.participant.intermediary.handler; -import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; @@ -39,6 +38,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDef 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.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantStatus; @@ -49,45 +49,77 @@ class AutomationCompositionOutHandlerTest { @Test void updateAutomationCompositionElementStateNullTest() { var cacheProvider = mock(CacheProvider.class); - var acOutHandler = new AutomationCompositionOutHandler(mock(ParticipantMessagePublisher.class), cacheProvider); + var publisher = mock(ParticipantMessagePublisher.class); + var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider); assertDoesNotThrow( () -> acOutHandler.updateAutomationCompositionElementState(null, null, null, null, null, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(null, + UUID.randomUUID(), null, null, null, null)); + + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(UUID.randomUUID(), + null, null, null, null, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(UUID.randomUUID(), UUID.randomUUID(), null, null, null, null)); assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(UUID.randomUUID(), + UUID.randomUUID(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, null)); + + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState(UUID.randomUUID(), UUID.randomUUID(), DeployState.DEPLOYED, null, null, null)); var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId())) .thenReturn(automationComposition); assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState( - automationComposition.getInstanceId(), UUID.randomUUID(), DeployState.DEPLOYED, null, null, null)); + automationComposition.getInstanceId(), UUID.randomUUID(), DeployState.DEPLOYED, + null, StateChangeResult.NO_ERROR, null)); var elementId = automationComposition.getElements().values().iterator().next().getId(); assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState( - automationComposition.getInstanceId(), elementId, null, null, null, null)); + automationComposition.getInstanceId(), elementId, null, null, + StateChangeResult.NO_ERROR, null)); + + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementStage( + elementId, null, StateChangeResult.NO_ERROR, 0, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementStage( + null, elementId, StateChangeResult.NO_ERROR, 0, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementStage( + UUID.randomUUID(), elementId, StateChangeResult.NO_ERROR, 0, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementStage( + automationComposition.getInstanceId(), UUID.randomUUID(), + StateChangeResult.NO_ERROR, 0, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState( + automationComposition.getInstanceId(), elementId, DeployState.DEPLOYED, LockState.LOCKED, + StateChangeResult.NO_ERROR, null)); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState( + automationComposition.getInstanceId(), elementId, DeployState.DEPLOYING, null, + StateChangeResult.NO_ERROR, "")); + assertDoesNotThrow(() -> acOutHandler.updateAutomationCompositionElementState( + automationComposition.getInstanceId(), elementId, DeployState.DEPLOYED, null, + StateChangeResult.TIMEOUT, "")); + + verify(publisher, times(0)).sendAutomationCompositionAck(any()); } @Test - void updateAutomationCompositionElementStateDeployedTest() { + void updateAutomationCompositionElementStageTest() { var publisher = mock(ParticipantMessagePublisher.class); var cacheProvider = mock(CacheProvider.class); var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider); - var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId())) .thenReturn(automationComposition); var elementId = automationComposition.getElements().values().iterator().next().getId(); - acOutHandler.updateAutomationCompositionElementState(automationComposition.getInstanceId(), elementId, - DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); + acOutHandler.updateAutomationCompositionElementStage( + automationComposition.getInstanceId(), elementId, StateChangeResult.NO_ERROR, 0, "OK"); verify(publisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class)); } @Test - void updateAutomationCompositionElementStateLockTest() { + void updateAutomationCompositionElementStateDeployedTest() { var publisher = mock(ParticipantMessagePublisher.class); var cacheProvider = mock(CacheProvider.class); var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider); @@ -96,13 +128,30 @@ class AutomationCompositionOutHandlerTest { when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId())) .thenReturn(automationComposition); var elementId = automationComposition.getElements().values().iterator().next().getId(); - acOutHandler.updateAutomationCompositionElementState(automationComposition.getInstanceId(), elementId, null, - LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); + acOutHandler.updateAutomationCompositionElementState(automationComposition.getInstanceId(), elementId, + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); + verify(publisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class)); + } + + @Test + void updateAutomationCompositionElementStatePrepareTest() { + var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); + automationComposition.setSubState(SubState.PREPARING); + var cacheProvider = mock(CacheProvider.class); + when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId())) + .thenReturn(automationComposition); + var element = automationComposition.getElements().values().iterator().next(); + element.setSubState(SubState.PREPARING); + var elementId = element.getId(); + var publisher = mock(ParticipantMessagePublisher.class); + var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider); + acOutHandler.updateAutomationCompositionElementState(automationComposition.getInstanceId(), elementId, + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Prepare completed"); verify(publisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class)); } @Test - void updateAutomationCompositionElementStateRestartedTest() { + void updateAutomationCompositionElementStateLockTest() { var publisher = mock(ParticipantMessagePublisher.class); var cacheProvider = mock(CacheProvider.class); var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider); @@ -110,12 +159,10 @@ class AutomationCompositionOutHandlerTest { var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next(); when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId())) .thenReturn(automationComposition); - var element = automationComposition.getElements().values().iterator().next(); - element.setRestarting(true); - acOutHandler.updateAutomationCompositionElementState(automationComposition.getInstanceId(), element.getId(), - DeployState.DEPLOYED, LockState.LOCKED, StateChangeResult.NO_ERROR, "Restarted"); + var elementId = automationComposition.getElements().values().iterator().next().getId(); + acOutHandler.updateAutomationCompositionElementState(automationComposition.getInstanceId(), elementId, null, + LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); verify(publisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class)); - assertThat(element.getRestarting()).isNull(); } @Test @@ -169,6 +216,28 @@ class AutomationCompositionOutHandlerTest { } @Test + void updateCompositionStateNullTest() { + var publisher = mock(ParticipantMessagePublisher.class); + var cacheProvider = mock(CacheProvider.class); + var acOutHandler = new AutomationCompositionOutHandler(publisher, cacheProvider); + + assertDoesNotThrow( + () -> acOutHandler.updateCompositionState(null, null, null, null)); + assertDoesNotThrow(() -> acOutHandler.updateCompositionState(UUID.randomUUID(), null, + StateChangeResult.NO_ERROR, null)); + assertDoesNotThrow( + () -> acOutHandler.updateCompositionState(UUID.randomUUID(), AcTypeState.PRIMED, null, null)); + assertDoesNotThrow(() -> acOutHandler.updateCompositionState(UUID.randomUUID(), AcTypeState.PRIMING, + StateChangeResult.NO_ERROR, null)); + assertDoesNotThrow(() -> acOutHandler.updateCompositionState(UUID.randomUUID(), AcTypeState.DEPRIMING, + StateChangeResult.NO_ERROR, null)); + assertDoesNotThrow(() -> acOutHandler.updateCompositionState(UUID.randomUUID(), AcTypeState.PRIMED, + StateChangeResult.TIMEOUT, null)); + + verify(publisher, times(0)).sendParticipantPrimeAck(any()); + } + + @Test void updateCompositionStatePrimedTest() { var cacheProvider = mock(CacheProvider.class); when(cacheProvider.getParticipantId()).thenReturn(UUID.randomUUID()); diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProviderTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProviderTest.java index 9451f0138..ced2d81e8 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProviderTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/CacheProviderTest.java @@ -186,4 +186,36 @@ class CacheProviderTest { assertEquals(element.getDefinition(), result.elementDefinitionId()); } } + + @Test + void testGetCompositionElementDtoMap() { + var parameter = CommonTestData.getParticipantParameters(); + var cacheProvider = new CacheProvider(parameter); + var compositionId = UUID.randomUUID(); + var automationComposition = + CommonTestData.getTestAutomationCompositions().getAutomationCompositionList().get(0); + automationComposition.setCompositionId(compositionId); + cacheProvider.addElementDefinition(compositionId, + CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition)); + var result = cacheProvider.getCompositionElementDtoMap(automationComposition); + for (var element : automationComposition.getElements().values()) { + var compositionElementDto = result.get(element.getId()); + assertEquals(element.getDefinition(), compositionElementDto.elementDefinitionId()); + } + } + + @Test + void testGetInstanceElementDtoMap() { + var parameter = CommonTestData.getParticipantParameters(); + var cacheProvider = new CacheProvider(parameter); + var compositionId = UUID.randomUUID(); + var automationComposition = + CommonTestData.getTestAutomationCompositions().getAutomationCompositionList().get(0); + automationComposition.setCompositionId(compositionId); + var result = cacheProvider.getInstanceElementDtoMap(automationComposition); + for (var element : automationComposition.getElements().values()) { + var compositionElementDto = result.get(element.getId()); + assertEquals(element.getId(), compositionElementDto.elementId()); + } + } } diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/DummyAcElementListener.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/DummyAcElementListener.java deleted file mode 100644 index 173ed031b..000000000 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/DummyAcElementListener.java +++ /dev/null @@ -1,78 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.clamp.acm.participant.intermediary.handler; - -import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener; -import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionDto; -import org.onap.policy.clamp.acm.participant.intermediary.api.CompositionElementDto; -import org.onap.policy.clamp.acm.participant.intermediary.api.InstanceElementDto; -import org.onap.policy.models.base.PfModelException; - -public class DummyAcElementListener implements AutomationCompositionElementListener { - @Override - public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { - - } - - @Override - public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { - - } - - @Override - public void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { - - } - - @Override - public void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { - - } - - @Override - public void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) - throws PfModelException { - } - - @Override - public void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement, - InstanceElementDto instanceElementUpdated) - throws PfModelException { - } - - @Override - public void prime(CompositionDto composition) throws PfModelException { - } - - @Override - public void deprime(CompositionDto composition) throws PfModelException { - } - - @Override - public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, - InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) - throws PfModelException { - } -} 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 8c2b2473c..1fb72812b 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 @@ -62,7 +62,8 @@ class ParticipantHandlerTest { when(publisher.isActive()).thenReturn(true); var cacheProvider = mock(CacheProvider.class); var participantHandler = new ParticipantHandler(mock(AutomationCompositionHandler.class), - mock(AcLockHandler.class), mock(AcDefinitionHandler.class), publisher, cacheProvider); + mock(AcLockHandler.class), mock(AcSubStateHandler.class), mock(AcDefinitionHandler.class), + publisher, cacheProvider); participantHandler.handleParticipantStatusReq(new ParticipantStatusReq()); verify(publisher).sendParticipantRegister(any(ParticipantRegister.class)); @@ -76,7 +77,8 @@ class ParticipantHandlerTest { void handleAutomationCompositionDeployTest() { var acHandler = mock(AutomationCompositionHandler.class); var participantHandler = new ParticipantHandler(acHandler, mock(AcLockHandler.class), - mock(AcDefinitionHandler.class), mock(ParticipantMessagePublisher.class), mock(CacheProvider.class)); + mock(AcSubStateHandler.class), mock(AcDefinitionHandler.class), mock(ParticipantMessagePublisher.class), + mock(CacheProvider.class)); var automationCompositionDeploy = new AutomationCompositionDeploy(); participantHandler.handleAutomationCompositionDeploy(automationCompositionDeploy); verify(acHandler).handleAutomationCompositionDeploy(automationCompositionDeploy); @@ -86,8 +88,8 @@ class ParticipantHandlerTest { void handleAutomationCompositionStateChangeTest() { var acHandler = mock(AutomationCompositionHandler.class); var acLockHandler = mock(AcLockHandler.class); - var participantHandler = new ParticipantHandler(acHandler, acLockHandler, mock(AcDefinitionHandler.class), - mock(ParticipantMessagePublisher.class), mock(CacheProvider.class)); + var participantHandler = new ParticipantHandler(acHandler, acLockHandler, mock(AcSubStateHandler.class), + mock(AcDefinitionHandler.class), mock(ParticipantMessagePublisher.class), mock(CacheProvider.class)); var acStateChange = new AutomationCompositionStateChange(); acStateChange.setDeployOrderedState(DeployOrder.DEPLOY); @@ -104,18 +106,25 @@ class ParticipantHandlerTest { @Test void handleAutomationCompositionMigrationTest() { var acHandler = mock(AutomationCompositionHandler.class); + var acSubStateHandler = mock(AcSubStateHandler.class); var participantHandler = new ParticipantHandler(acHandler, mock(AcLockHandler.class), - mock(AcDefinitionHandler.class), mock(ParticipantMessagePublisher.class), mock(CacheProvider.class)); + acSubStateHandler, mock(AcDefinitionHandler.class), mock(ParticipantMessagePublisher.class), + mock(CacheProvider.class)); var migrationMsg = new AutomationCompositionMigration(); participantHandler.handleAutomationCompositionMigration(migrationMsg); verify(acHandler).handleAutomationCompositionMigration(migrationMsg); + + migrationMsg.setPrecheck(true); + participantHandler.handleAutomationCompositionMigration(migrationMsg); + verify(acSubStateHandler).handleAcMigrationPrecheck(migrationMsg); } @Test void handleAcPropertyUpdateTest() { var acHandler = mock(AutomationCompositionHandler.class); var participantHandler = new ParticipantHandler(acHandler, mock(AcLockHandler.class), - mock(AcDefinitionHandler.class), mock(ParticipantMessagePublisher.class), mock(CacheProvider.class)); + mock(AcSubStateHandler.class), mock(AcDefinitionHandler.class), mock(ParticipantMessagePublisher.class), + mock(CacheProvider.class)); var propertyUpdateMsg = new PropertiesUpdate(); participantHandler.handleAcPropertyUpdate(propertyUpdateMsg); verify(acHandler).handleAcPropertyUpdate(propertyUpdateMsg); @@ -127,8 +136,8 @@ class ParticipantHandlerTest { when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId()); when(cacheProvider.getReplicaId()).thenReturn(CommonTestData.getReplicaId()); var participantHandler = new ParticipantHandler(mock(AutomationCompositionHandler.class), - mock(AcLockHandler.class), mock(AcDefinitionHandler.class), mock(ParticipantMessagePublisher.class), - cacheProvider); + mock(AcLockHandler.class), mock(AcSubStateHandler.class), mock(AcDefinitionHandler.class), + mock(ParticipantMessagePublisher.class), cacheProvider); var participantAckMsg = new ParticipantAckMessage(ParticipantMessageType.AUTOMATION_COMPOSITION_DEPLOY); assertTrue(participantHandler.appliesTo(participantAckMsg)); @@ -147,7 +156,8 @@ class ParticipantHandlerTest { when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId()); when(cacheProvider.getSupportedAcElementTypes()).thenReturn(List.of(new ParticipantSupportedElementType())); var participantHandler = new ParticipantHandler(mock(AutomationCompositionHandler.class), - mock(AcLockHandler.class), mock(AcDefinitionHandler.class), publisher, cacheProvider); + mock(AcLockHandler.class), mock(AcSubStateHandler.class), mock(AcDefinitionHandler.class), publisher, + cacheProvider); participantHandler.sendParticipantRegister(); verify(publisher).sendParticipantRegister(any(ParticipantRegister.class)); @@ -159,7 +169,8 @@ class ParticipantHandlerTest { var cacheProvider = mock(CacheProvider.class); when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId()); var participantHandler = new ParticipantHandler(mock(AutomationCompositionHandler.class), - mock(AcLockHandler.class), mock(AcDefinitionHandler.class), publisher, cacheProvider); + mock(AcLockHandler.class), mock(AcSubStateHandler.class), mock(AcDefinitionHandler.class), publisher, + cacheProvider); participantHandler.handleParticipantRegisterAck(new ParticipantRegisterAck()); verify(publisher).sendParticipantStatus(any(ParticipantStatus.class)); @@ -171,7 +182,8 @@ class ParticipantHandlerTest { var cacheProvider = mock(CacheProvider.class); when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId()); var participantHandler = new ParticipantHandler(mock(AutomationCompositionHandler.class), - mock(AcLockHandler.class), mock(AcDefinitionHandler.class), publisher, cacheProvider); + mock(AcLockHandler.class), mock(AcSubStateHandler.class), mock(AcDefinitionHandler.class), publisher, + cacheProvider); participantHandler.sendParticipantDeregister(); verify(publisher).sendParticipantDeregister(any(ParticipantDeregister.class)); @@ -180,8 +192,8 @@ class ParticipantHandlerTest { @Test void handleParticipantDeregisterAckTest() { var participantHandler = new ParticipantHandler(mock(AutomationCompositionHandler.class), - mock(AcLockHandler.class), mock(AcDefinitionHandler.class), mock(ParticipantMessagePublisher.class), - mock(CacheProvider.class)); + mock(AcLockHandler.class), mock(AcSubStateHandler.class), mock(AcDefinitionHandler.class), + mock(ParticipantMessagePublisher.class), mock(CacheProvider.class)); var participantDeregisterAck = new ParticipantDeregisterAck(); assertDoesNotThrow(() -> participantHandler.handleParticipantDeregisterAck(participantDeregisterAck)); } @@ -194,8 +206,8 @@ class ParticipantHandlerTest { var acHandler = mock(AcDefinitionHandler.class); var participantHandler = new ParticipantHandler(mock(AutomationCompositionHandler.class), - mock(AcLockHandler.class), acHandler, mock(ParticipantMessagePublisher.class), - mock(CacheProvider.class)); + mock(AcLockHandler.class), mock(AcSubStateHandler.class), acHandler, + mock(ParticipantMessagePublisher.class), mock(CacheProvider.class)); participantHandler.handleParticipantPrime(participantPrime); verify(acHandler).handlePrime(participantPrime); @@ -213,7 +225,7 @@ class ParticipantHandlerTest { var publisher = mock(ParticipantMessagePublisher.class); var acHandler = mock(AcDefinitionHandler.class); var participantHandler = new ParticipantHandler(mock(AutomationCompositionHandler.class), - mock(AcLockHandler.class), acHandler, publisher, cacheProvider); + mock(AcLockHandler.class), mock(AcSubStateHandler.class), acHandler, publisher, cacheProvider); participantHandler.handleParticipantSync(participantSyncMsg); verify(acHandler).handleParticipantSync(participantSyncMsg); @@ -229,7 +241,7 @@ class ParticipantHandlerTest { when(publisher.isActive()).thenReturn(true); var acHandler = mock(AcDefinitionHandler.class); var participantHandler = new ParticipantHandler(mock(AutomationCompositionHandler.class), - mock(AcLockHandler.class), acHandler, publisher, cacheProvider); + mock(AcLockHandler.class), mock(AcSubStateHandler.class), acHandler, publisher, cacheProvider); participantHandler.sendHeartbeat(); verify(publisher).sendParticipantRegister(any(ParticipantRegister.class)); diff --git a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java index f3471e6ee..d05471901 100644 --- a/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java +++ b/participant/participant-intermediary/src/test/java/org/onap/policy/clamp/acm/participant/intermediary/handler/ThreadHandlerTest.java @@ -49,7 +49,7 @@ class ThreadHandlerTest { private static final int TIMEOUT = 400; @Test - void test() throws PfModelException, IOException { + void testPrime() throws PfModelException, IOException { var listener = mock(AutomationCompositionElementListener.class); var intermediaryApi = mock(ParticipantIntermediaryApi.class); try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) { @@ -61,11 +61,45 @@ class ThreadHandlerTest { verify(listener, timeout(TIMEOUT)).prime(composition); clearInvocations(listener); + threadHandler.deprime(messageId, composition); + verify(listener, timeout(TIMEOUT)).deprime(composition); + } + } + + @Test + void testPrimeException() throws PfModelException, IOException { + var listener = mock(AutomationCompositionElementListener.class); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) { + + var compositionId = UUID.randomUUID(); + var composition = new CompositionDto(compositionId, Map.of(), Map.of()); + doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener).prime(composition); + var messageId = UUID.randomUUID(); + threadHandler.prime(messageId, composition); + verify(intermediaryApi, timeout(TIMEOUT)).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, + StateChangeResult.FAILED, "Composition Defintion prime failed"); + + clearInvocations(listener); + doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener).deprime(composition); + threadHandler.deprime(messageId, composition); + verify(intermediaryApi, timeout(TIMEOUT)).updateCompositionState(compositionId, AcTypeState.PRIMED, + StateChangeResult.FAILED, "Composition Defintion deprime failed"); + } + } + + @Test + void testDeploy() throws PfModelException, IOException { + var listener = mock(AutomationCompositionElementListener.class); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) { + Map<String, Object> properties = Map.of("key", "value"); var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), properties, properties); var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), - null, properties, properties); + null, properties, properties); + var messageId = UUID.randomUUID(); threadHandler.deploy(messageId, compositionElement, instanceElement); verify(listener, timeout(TIMEOUT)).deploy(compositionElement, instanceElement); @@ -83,17 +117,9 @@ class ThreadHandlerTest { var compositionElementTarget = new CompositionElementDto(compositionTargetId, new ToscaConceptIdentifier(), properties, properties); threadHandler.migrate(messageId, compositionElement, compositionElementTarget, - instanceElement, instanceElementUpdated); + instanceElement, instanceElementUpdated, 0); verify(listener, timeout(TIMEOUT)).migrate(compositionElement, compositionElementTarget, - instanceElement, instanceElementUpdated); - - clearInvocations(listener); - threadHandler.lock(messageId, compositionElement, instanceElement); - verify(listener, timeout(TIMEOUT)).lock(compositionElement, instanceElement); - - clearInvocations(listener); - threadHandler.unlock(messageId, compositionElement, instanceElement); - verify(listener, timeout(TIMEOUT)).unlock(compositionElement, instanceElement); + instanceElement, instanceElementUpdated, 0); clearInvocations(listener); threadHandler.undeploy(messageId, compositionElement, instanceElement); @@ -102,29 +128,15 @@ class ThreadHandlerTest { clearInvocations(listener); threadHandler.delete(messageId, compositionElement, instanceElement); verify(listener, timeout(TIMEOUT)).delete(compositionElement, instanceElement); - - clearInvocations(listener); - threadHandler.deprime(messageId, composition); - verify(listener, timeout(TIMEOUT)).deprime(composition); } } @Test - void testException() throws PfModelException, IOException { + void testDeployException() throws PfModelException, IOException { var listener = mock(AutomationCompositionElementListener.class); var intermediaryApi = mock(ParticipantIntermediaryApi.class); try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) { - var compositionId = UUID.randomUUID(); - var composition = new CompositionDto(compositionId, Map.of(), Map.of()); - doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) - .prime(composition); - var messageId = UUID.randomUUID(); - threadHandler.prime(messageId, composition); - verify(intermediaryApi, timeout(TIMEOUT)).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, - StateChangeResult.FAILED, "Composition Defintion prime failed"); - - clearInvocations(intermediaryApi); Map<String, Object> properties = Map.of("key", "value"); var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), properties, properties); @@ -135,9 +147,10 @@ class ThreadHandlerTest { element.setId(elementId); doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) .deploy(compositionElement, instanceElement); + var messageId = UUID.randomUUID(); threadHandler.deploy(messageId, compositionElement, instanceElement); verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, - DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Automation composition element deploy failed"); clearInvocations(listener); @@ -147,44 +160,169 @@ class ThreadHandlerTest { .update(compositionElement, instanceElement, instanceElementUpdated); threadHandler.update(messageId, compositionElement, instanceElement, instanceElementUpdated); verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.FAILED, - "Automation composition element update failed"); + DeployState.DEPLOYED, null, StateChangeResult.FAILED, + "Automation composition element update failed"); + + clearInvocations(listener); + var compositionTargetId = UUID.randomUUID(); + var compositionElementTarget = new CompositionElementDto(compositionTargetId, new ToscaConceptIdentifier(), + properties, properties); + doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) + .migrate(compositionElement, compositionElementTarget, instanceElement, instanceElementUpdated, 0); + threadHandler.migrate(messageId, compositionElement, compositionElementTarget, + instanceElement, instanceElementUpdated, 0); + verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.FAILED, + "Automation composition element migrate failed"); + + clearInvocations(listener); + doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) + .undeploy(compositionElement, instanceElement); + threadHandler.undeploy(messageId, compositionElement, instanceElement); + verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.FAILED, + "Automation composition element undeploy failed"); + + clearInvocations(listener); + doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) + .delete(compositionElement, instanceElement); + threadHandler.delete(messageId, compositionElement, instanceElement); + verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, + "Automation composition element delete failed"); + } + } + + @Test + void testLock() throws PfModelException, IOException { + var listener = mock(AutomationCompositionElementListener.class); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) { + + Map<String, Object> properties = Map.of("key", "value"); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + properties, properties); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), + null, properties, properties); + var messageId = UUID.randomUUID(); + threadHandler.lock(messageId, compositionElement, instanceElement); + verify(listener, timeout(TIMEOUT)).lock(compositionElement, instanceElement); + + clearInvocations(listener); + threadHandler.unlock(messageId, compositionElement, instanceElement); + verify(listener, timeout(TIMEOUT)).unlock(compositionElement, instanceElement); clearInvocations(listener); + threadHandler.undeploy(messageId, compositionElement, instanceElement); + verify(listener, timeout(TIMEOUT)).undeploy(compositionElement, instanceElement); + } + } + + @Test + void testLockException() throws PfModelException, IOException { + var listener = mock(AutomationCompositionElementListener.class); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) { + + Map<String, Object> properties = Map.of("key", "value"); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + properties, properties); + var instanceId = UUID.randomUUID(); + var elementId = UUID.randomUUID(); + var instanceElement = new InstanceElementDto(instanceId, elementId, null, properties, properties); + var element = new AcElementDeploy(); + element.setId(elementId); + var messageId = UUID.randomUUID(); doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) .lock(compositionElement, instanceElement); threadHandler.lock(messageId, compositionElement, instanceElement); verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, - null, LockState.UNLOCKED, StateChangeResult.FAILED, "Automation composition element lock failed"); + null, LockState.UNLOCKED, StateChangeResult.FAILED, "Automation composition element lock failed"); clearInvocations(listener); doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) .unlock(compositionElement, instanceElement); threadHandler.unlock(messageId, compositionElement, instanceElement); verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, - null, LockState.LOCKED, StateChangeResult.FAILED, "Automation composition element unlock failed"); + null, LockState.LOCKED, StateChangeResult.FAILED, "Automation composition element unlock failed"); + } + } + + @Test + void testSubState() throws PfModelException, IOException { + var listener = mock(AutomationCompositionElementListener.class); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) { + + Map<String, Object> properties = Map.of("key", "value"); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + properties, properties); + var instanceElement = new InstanceElementDto(UUID.randomUUID(), UUID.randomUUID(), + null, properties, properties); + var messageId = UUID.randomUUID(); + threadHandler.prepare(messageId, compositionElement, instanceElement); + verify(listener, timeout(TIMEOUT)).prepare(compositionElement, instanceElement); clearInvocations(listener); + threadHandler.review(messageId, compositionElement, instanceElement); + verify(listener, timeout(TIMEOUT)).review(compositionElement, instanceElement); + + clearInvocations(listener); + var instanceElementMigrate = new InstanceElementDto(instanceElement.instanceId(), + instanceElement.elementId(), null, properties, properties); + var compositionTargetId = UUID.randomUUID(); + var compositionElementTarget = new CompositionElementDto(compositionTargetId, new ToscaConceptIdentifier(), + properties, properties); + threadHandler.migratePrecheck(messageId, compositionElement, compositionElementTarget, + instanceElement, instanceElementMigrate); + verify(listener, timeout(TIMEOUT)).migratePrecheck(compositionElement, compositionElementTarget, + instanceElement, instanceElementMigrate); + } + } + + @Test + void testSubStateException() throws PfModelException, IOException { + var listener = mock(AutomationCompositionElementListener.class); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + try (var threadHandler = new ThreadHandler(listener, intermediaryApi, mock(CacheProvider.class))) { + + Map<String, Object> properties = Map.of("key", "value"); + var compositionElement = new CompositionElementDto(UUID.randomUUID(), new ToscaConceptIdentifier(), + properties, properties); + var instanceId = UUID.randomUUID(); + var elementId = UUID.randomUUID(); + var instanceElement = new InstanceElementDto(instanceId, elementId, null, properties, properties); + var element = new AcElementDeploy(); + element.setId(elementId); doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) - .undeploy(compositionElement, instanceElement); - threadHandler.undeploy(messageId, compositionElement, instanceElement); + .prepare(compositionElement, instanceElement); + var messageId = UUID.randomUUID(); + threadHandler.prepare(messageId, compositionElement, instanceElement); verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, - DeployState.DEPLOYED, null, StateChangeResult.FAILED, - "Automation composition element undeploy failed"); + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, + "Automation composition element prepare Pre Deploy failed"); clearInvocations(listener); doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) - .delete(compositionElement, instanceElement); - threadHandler.delete(messageId, compositionElement, instanceElement); + .review(compositionElement, instanceElement); + threadHandler.review(messageId, compositionElement, instanceElement); verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, - DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, - "Automation composition element delete failed"); + DeployState.DEPLOYED, null, StateChangeResult.FAILED, + "Automation composition element Review failed"); clearInvocations(listener); - doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener).deprime(composition); - threadHandler.deprime(messageId, composition); - verify(intermediaryApi, timeout(TIMEOUT)).updateCompositionState(compositionId, AcTypeState.PRIMED, - StateChangeResult.FAILED, "Composition Defintion deprime failed"); + var compositionTargetId = UUID.randomUUID(); + var compositionElementTarget = new CompositionElementDto(compositionTargetId, new ToscaConceptIdentifier(), + properties, properties); + var instanceElementMigrate = new InstanceElementDto(instanceElement.instanceId(), + instanceElement.elementId(), null, properties, properties); + doThrow(new PfModelException(Status.INTERNAL_SERVER_ERROR, "Error")).when(listener) + .migratePrecheck(compositionElement, compositionElementTarget, instanceElement, instanceElementMigrate); + threadHandler.migratePrecheck(messageId, compositionElement, compositionElementTarget, + instanceElement, instanceElementMigrate); + verify(intermediaryApi, timeout(TIMEOUT)).updateAutomationCompositionElementState(instanceId, elementId, + DeployState.DEPLOYED, null, StateChangeResult.FAILED, + "Automation composition element migrate precheck failed"); } } } diff --git a/runtime-acm/pom.xml b/runtime-acm/pom.xml index 0b3624d86..82283eaf7 100644 --- a/runtime-acm/pom.xml +++ b/runtime-acm/pom.xml @@ -139,7 +139,6 @@ <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> - <version>${version.jupiter}</version> <scope>test</scope> </dependency> <dependency> 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 8a56fbb1e..48b139495 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 @@ -188,10 +188,6 @@ public class CommissioningProvider { throw new PfModelRuntimeException(Status.BAD_REQUEST, "There are instances, Priming/Depriming not allowed"); } var acmDefinition = acDefinitionProvider.getAcDefinition(compositionId); - if (acmDefinition.getRestarting() != null) { - throw new PfModelRuntimeException(Status.BAD_REQUEST, - "There is a restarting process, Priming/Depriming not allowed"); - } var stateOrdered = acTypeStateResolver.resolve(acTypeStateUpdate.getPrimeOrder(), acmDefinition.getState(), acmDefinition.getStateChangeResult()); switch (stateOrdered) { diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/MetricsConfiguration.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/MetricsConfiguration.java index 084f7c774..f5c8368e2 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/MetricsConfiguration.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/MetricsConfiguration.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2022 Nordix Foundation. + * Copyright (C) 2022, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.runtime.config; import io.micrometer.core.aop.TimedAspect; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -34,8 +35,9 @@ public class MetricsConfiguration { * Load up the metrics registry. */ @Bean - public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, - MeterRegistry registry) { + public InitializingBean forcePrometheusPostProcessor(@Qualifier("meterRegistryPostProcessor") + BeanPostProcessor meterRegistryPostProcessor, + MeterRegistry registry) { return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, ""); } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/OpenTelConfiguration.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/OpenTelConfiguration.java index 3727333a4..05d47d4f7 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/OpenTelConfiguration.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/OpenTelConfiguration.java @@ -35,7 +35,7 @@ import org.springframework.context.annotation.Configuration; public class OpenTelConfiguration { @Bean - @ConditionalOnProperty(prefix = "tracing", name = "enabled", havingValue = "true", matchIfMissing = false) + @ConditionalOnProperty(prefix = "tracing", name = "enabled", havingValue = "true") @ConditionalOnExpression("'http'.equals('${tracing.exporter.protocol}')") OtlpHttpSpanExporter otlpHttpSpanExporter(@Value("${tracing.exporter.endpoint:http://jaeger:4318/v1/traces}") String url) { return OtlpHttpSpanExporter.builder() @@ -44,7 +44,7 @@ public class OpenTelConfiguration { } @Bean - @ConditionalOnProperty(prefix = "tracing", name = "enabled", havingValue = "true", matchIfMissing = false) + @ConditionalOnProperty(prefix = "tracing", name = "enabled", havingValue = "true") @ConditionalOnExpression("'grpc'.equals('${tracing.exporter.protocol}')") OtlpGrpcSpanExporter otlpGrpcSpanExporter(@Value("${tracing.exporter.endpoint:http://jaeger:4317}") String url) { return OtlpGrpcSpanExporter.builder() @@ -53,7 +53,7 @@ public class OpenTelConfiguration { } @Bean - @ConditionalOnProperty(prefix = "tracing", name = "enabled", havingValue = "true", matchIfMissing = false) + @ConditionalOnProperty(prefix = "tracing", name = "enabled", havingValue = "true") JaegerRemoteSampler jaegerRemoteSampler( @Value("${tracing.sampler.jaeger-remote.endpoint:http://jaeger:14250}") String url, @Value("${SERVICE_ID:unknown_service}") String serviceId) { diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/messaging/MessageDispatcherActivator.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/messaging/MessageDispatcherActivator.java index a3e55c3f7..ff1f60b69 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/messaging/MessageDispatcherActivator.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/config/messaging/MessageDispatcherActivator.java @@ -22,7 +22,6 @@ package org.onap.policy.clamp.acm.runtime.config.messaging; import java.io.Closeable; -import java.io.IOException; import java.util.List; import java.util.function.UnaryOperator; import java.util.stream.Collectors; @@ -139,7 +138,7 @@ public class MessageDispatcherActivator extends ServiceManagerContainer implemen } @Override - public void close() throws IOException { + public void close() { if (isAlive()) { super.shutdown(); } 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 2bf08220a..42af70596 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 @@ -22,8 +22,8 @@ package org.onap.policy.clamp.acm.runtime.instantiation; import jakarta.validation.Valid; -import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response.Status; +import java.util.List; import java.util.UUID; import java.util.stream.Collectors; import lombok.NonNull; @@ -37,8 +37,12 @@ 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.concepts.NodeTemplateState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AcInstanceStateUpdate; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.SubOrder; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; @@ -47,6 +51,7 @@ import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.onap.policy.common.parameters.BeanValidationResult; import org.onap.policy.common.parameters.ObjectValidationResult; import org.onap.policy.common.parameters.ValidationStatus; +import org.onap.policy.models.base.PfConceptKey; import org.onap.policy.models.base.PfKey; import org.onap.policy.models.base.PfModelRuntimeException; import org.slf4j.Logger; @@ -62,6 +67,7 @@ import org.springframework.transaction.annotation.Transactional; @RequiredArgsConstructor public class AutomationCompositionInstantiationProvider { private static final String DO_NOT_MATCH = " do not match with "; + private static final String ELEMENT_ID_NOT_PRESENT = "Element id not present "; private static final Logger LOGGER = LoggerFactory.getLogger(AutomationCompositionInstantiationProvider.class); @@ -82,19 +88,19 @@ public class AutomationCompositionInstantiationProvider { public InstantiationResponse createAutomationComposition(UUID compositionId, AutomationComposition automationComposition) { if (!compositionId.equals(automationComposition.getCompositionId())) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + throw new PfModelRuntimeException(Status.BAD_REQUEST, automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId); } var checkAutomationCompositionOpt = automationCompositionProvider.findAutomationComposition(automationComposition.getKey().asIdentifier()); if (checkAutomationCompositionOpt.isPresent()) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + throw new PfModelRuntimeException(Status.BAD_REQUEST, automationComposition.getKey().asIdentifier() + " already defined"); } var validationResult = validateAutomationComposition(automationComposition); if (!validationResult.isValid()) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult()); + throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult()); } automationComposition = automationCompositionProvider.createAutomationComposition(automationComposition); @@ -120,7 +126,7 @@ public class AutomationCompositionInstantiationProvider { var instanceId = automationComposition.getInstanceId(); var acToUpdate = automationCompositionProvider.getAutomationComposition(instanceId); if (!compositionId.equals(acToUpdate.getCompositionId())) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + throw new PfModelRuntimeException(Status.BAD_REQUEST, automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId); } if (DeployState.UNDEPLOYED.equals(acToUpdate.getDeployState())) { @@ -131,22 +137,38 @@ public class AutomationCompositionInstantiationProvider { acToUpdate.setDerivedFrom(automationComposition.getDerivedFrom()); var validationResult = validateAutomationComposition(acToUpdate); if (!validationResult.isValid()) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult()); + throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult()); } automationComposition = automationCompositionProvider.updateAutomationComposition(acToUpdate); return createInstantiationResponse(automationComposition); - } else if ((DeployState.DEPLOYED.equals(acToUpdate.getDeployState()) - || DeployState.UPDATING.equals(acToUpdate.getDeployState())) - && LockState.LOCKED.equals(acToUpdate.getLockState())) { - if (automationComposition.getCompositionTargetId() != null) { - return migrateAutomationComposition(automationComposition, acToUpdate); + } + + var deployOrder = DeployOrder.UPDATE; + var subOrder = SubOrder.NONE; + + if (automationComposition.getCompositionTargetId() != null) { + + if (Boolean.TRUE.equals(automationComposition.getPrecheck())) { + subOrder = SubOrder.MIGRATE_PRECHECK; + deployOrder = DeployOrder.NONE; } else { - return updateDeployedAutomationComposition(automationComposition, acToUpdate); + deployOrder = DeployOrder.MIGRATE; } } - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, - "Not allowed to update in the state " + acToUpdate.getDeployState()); + var result = acInstanceStateResolver.resolve(deployOrder, LockOrder.NONE, subOrder, + acToUpdate.getDeployState(), acToUpdate.getLockState(), acToUpdate.getSubState(), + acToUpdate.getStateChangeResult()); + return switch (result) { + case "UPDATE" -> updateDeployedAutomationComposition(automationComposition, acToUpdate); + + case "MIGRATE" -> migrateAutomationComposition(automationComposition, acToUpdate); + + case "MIGRATE_PRECHECK" -> migratePrecheckAc(automationComposition, acToUpdate); + + default -> throw new PfModelRuntimeException(Status.BAD_REQUEST, + "Not allowed to " + deployOrder + " in the state " + acToUpdate.getDeployState()); + }; } /** @@ -164,17 +186,14 @@ public class AutomationCompositionInstantiationProvider { var elementId = element.getKey(); var dbAcElement = acToBeUpdated.getElements().get(elementId); if (dbAcElement == null) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, "Element id not present " + elementId); + throw new PfModelRuntimeException(Status.BAD_REQUEST, ELEMENT_ID_NOT_PRESENT + elementId); } AcmUtils.recursiveMerge(dbAcElement.getProperties(), element.getValue().getProperties()); } - if (automationComposition.getRestarting() != null) { - throw new PfModelRuntimeException(Status.BAD_REQUEST, "There is a restarting process, Update not allowed"); - } var validationResult = validateAutomationComposition(acToBeUpdated); if (!validationResult.isValid()) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult()); + throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult()); } // Publish property update event to the participants supervisionAcHandler.update(acToBeUpdated); @@ -187,47 +206,104 @@ public class AutomationCompositionInstantiationProvider { AutomationComposition automationComposition, AutomationComposition acToBeUpdated) { if (!DeployState.DEPLOYED.equals(acToBeUpdated.getDeployState())) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + throw new PfModelRuntimeException(Status.BAD_REQUEST, "Not allowed to migrate in the state " + acToBeUpdated.getDeployState()); } - if (automationComposition.getRestarting() != null) { - throw new PfModelRuntimeException(Status.BAD_REQUEST, "There is a restarting process, Migrate not allowed"); - } // Iterate and update the element property values for (var element : automationComposition.getElements().entrySet()) { var elementId = element.getKey(); var dbAcElement = acToBeUpdated.getElements().get(elementId); + // Add additional elements if present for migration if (dbAcElement == null) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, "Element id not present " + elementId); - } - AcmUtils.recursiveMerge(dbAcElement.getProperties(), element.getValue().getProperties()); - var newDefinition = element.getValue().getDefinition(); - var compatibility = - newDefinition.asConceptKey().getCompatibility(dbAcElement.getDefinition().asConceptKey()); - if (PfKey.Compatibility.DIFFERENT.equals(compatibility)) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, - dbAcElement.getDefinition() + " is not compatible with " + newDefinition); - } - if (PfKey.Compatibility.MAJOR.equals(compatibility) || PfKey.Compatibility.MINOR.equals(compatibility)) { - LOGGER.warn("Migrate {}: Version {} has {} compatibility with {} ", - automationComposition.getInstanceId(), newDefinition, compatibility, dbAcElement.getDefinition()); + LOGGER.info("New Ac element {} added in Migration", elementId); + acToBeUpdated.getElements().put(elementId, element.getValue()); + } else { + AcmUtils.recursiveMerge(dbAcElement.getProperties(), element.getValue().getProperties()); + var newDefinition = element.getValue().getDefinition().asConceptKey(); + var dbElementDefinition = dbAcElement.getDefinition().asConceptKey(); + checkCompatibility(newDefinition, dbElementDefinition, automationComposition.getInstanceId()); + dbAcElement.setDefinition(element.getValue().getDefinition()); } - dbAcElement.setDefinition(element.getValue().getDefinition()); } + // Remove element which is not present in the new Ac instance + var elementsRemoved = getElementRemoved(acToBeUpdated, automationComposition); + elementsRemoved.forEach(uuid -> acToBeUpdated.getElements().remove(uuid)); var validationResult = - validateAutomationComposition(acToBeUpdated, automationComposition.getCompositionTargetId()); + validateAutomationComposition(acToBeUpdated, automationComposition.getCompositionTargetId()); if (!validationResult.isValid()) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, validationResult.getResult()); + throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult()); } acToBeUpdated.setCompositionTargetId(automationComposition.getCompositionTargetId()); + var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionTargetId()); + // Publish migrate event to the participants + supervisionAcHandler.migrate(acToBeUpdated, acDefinition.getServiceTemplate()); + + var ac = automationCompositionProvider.updateAutomationComposition(acToBeUpdated); + elementsRemoved.forEach(automationCompositionProvider::deleteAutomationCompositionElement); + return createInstantiationResponse(ac); + } + + private List<UUID> getElementRemoved(AutomationComposition acFromDb, AutomationComposition acFromMigration) { + return acFromDb.getElements().keySet().stream() + .filter(id -> acFromMigration.getElements().get(id) == null).toList(); + } + + void checkCompatibility(PfConceptKey newDefinition, PfConceptKey dbElementDefinition, + UUID instanceId) { + var compatibility = newDefinition.getCompatibility(dbElementDefinition); + if (PfKey.Compatibility.DIFFERENT.equals(compatibility)) { + throw new PfModelRuntimeException(Status.BAD_REQUEST, + dbElementDefinition + " is not compatible with " + newDefinition); + } + if (PfKey.Compatibility.MAJOR.equals(compatibility) || PfKey.Compatibility.MINOR + .equals(compatibility)) { + LOGGER.warn("Migrate {}: Version {} has {} compatibility with {} ", instanceId, newDefinition, + compatibility, dbElementDefinition); + } + } + + private InstantiationResponse migratePrecheckAc( + AutomationComposition automationComposition, AutomationComposition acToBeUpdated) { + + acToBeUpdated.setPrecheck(true); + var copyAc = new AutomationComposition(acToBeUpdated); + // Iterate and update the element property values + for (var element : automationComposition.getElements().entrySet()) { + var elementId = element.getKey(); + var copyElement = copyAc.getElements().get(elementId); + // Add additional elements if present for migration + if (copyElement == null) { + LOGGER.info("New Ac element {} added in Migration", elementId); + copyAc.getElements().put(elementId, element.getValue()); + } else { + AcmUtils.recursiveMerge(copyElement.getProperties(), element.getValue().getProperties()); + var newDefinition = element.getValue().getDefinition().asConceptKey(); + var copyElementDefinition = copyElement.getDefinition().asConceptKey(); + checkCompatibility(newDefinition, copyElementDefinition, automationComposition.getInstanceId()); + copyElement.setDefinition(element.getValue().getDefinition()); + } + } + // Remove element which is not present in the new Ac instance + var elementsRemoved = getElementRemoved(copyAc, automationComposition); + elementsRemoved.forEach(uuid -> copyAc.getElements().remove(uuid)); + + var validationResult = + validateAutomationComposition(copyAc, automationComposition.getCompositionTargetId()); + if (!validationResult.isValid()) { + throw new PfModelRuntimeException(Status.BAD_REQUEST, validationResult.getResult()); + } + copyAc.setCompositionTargetId(automationComposition.getCompositionTargetId()); // Publish migrate event to the participants - supervisionAcHandler.migrate(acToBeUpdated, automationComposition.getCompositionTargetId()); + supervisionAcHandler.migratePrecheck(copyAc); - automationComposition = automationCompositionProvider.updateAutomationComposition(acToBeUpdated); - return createInstantiationResponse(automationComposition); + AcmUtils.setCascadedState(acToBeUpdated, DeployState.DEPLOYED, LockState.LOCKED, + SubState.MIGRATION_PRECHECKING); + acToBeUpdated.setStateChangeResult(StateChangeResult.NO_ERROR); + + return createInstantiationResponse(automationCompositionProvider.updateAutomationComposition(acToBeUpdated)); } private BeanValidationResult validateAutomationComposition(AutomationComposition automationComposition) { @@ -256,12 +332,6 @@ public class AutomationCompositionInstantiationProvider { ValidationStatus.INVALID, "Commissioned automation composition definition not primed")); return result; } - if (acDefinitionOpt.get().getRestarting() != null) { - result.addResult( - new ObjectValidationResult("ServiceTemplate.restarting", acDefinitionOpt.get().getRestarting(), - ValidationStatus.INVALID, "There is a restarting process in composition")); - return result; - } var participantIds = acDefinitionOpt.get().getElementStateMap().values().stream() .map(NodeTemplateState::getParticipantId).collect(Collectors.toSet()); @@ -296,7 +366,7 @@ public class AutomationCompositionInstantiationProvider { var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId); if (!compositionId.equals(automationComposition.getCompositionId()) && !compositionId.equals(automationComposition.getCompositionTargetId())) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + throw new PfModelRuntimeException(Status.BAD_REQUEST, automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId); } return automationComposition; @@ -312,22 +382,19 @@ public class AutomationCompositionInstantiationProvider { public InstantiationResponse deleteAutomationComposition(UUID compositionId, UUID instanceId) { var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId); if (!compositionId.equals(automationComposition.getCompositionId())) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + throw new PfModelRuntimeException(Status.BAD_REQUEST, automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId); } if (!DeployState.UNDEPLOYED.equals(automationComposition.getDeployState()) && !DeployState.DELETING.equals(automationComposition.getDeployState())) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + throw new PfModelRuntimeException(Status.BAD_REQUEST, "Automation composition state is still " + automationComposition.getDeployState()); } if (DeployState.DELETING.equals(automationComposition.getDeployState()) && StateChangeResult.NO_ERROR.equals(automationComposition.getStateChangeResult())) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + throw new PfModelRuntimeException(Status.BAD_REQUEST, "Automation composition state is still " + automationComposition.getDeployState()); } - if (automationComposition.getRestarting() != null) { - throw new PfModelRuntimeException(Status.BAD_REQUEST, "There is a restarting process, Delete not allowed"); - } var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId()); var participantIds = acDefinition.getElementStateMap().values().stream() .map(NodeTemplateState::getParticipantId).collect(Collectors.toSet()); @@ -366,7 +433,7 @@ public class AutomationCompositionInstantiationProvider { @Valid AcInstanceStateUpdate acInstanceStateUpdate) { var automationComposition = automationCompositionProvider.getAutomationComposition(instanceId); if (!compositionId.equals(automationComposition.getCompositionId())) { - throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, + throw new PfModelRuntimeException(Status.BAD_REQUEST, automationComposition.getCompositionId() + DO_NOT_MATCH + compositionId); } var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId()); @@ -376,8 +443,9 @@ public class AutomationCompositionInstantiationProvider { participantProvider.verifyParticipantState(participantIds); var result = acInstanceStateResolver.resolve(acInstanceStateUpdate.getDeployOrder(), - acInstanceStateUpdate.getLockOrder(), automationComposition.getDeployState(), - automationComposition.getLockState(), automationComposition.getStateChangeResult()); + acInstanceStateUpdate.getLockOrder(), acInstanceStateUpdate.getSubOrder(), + automationComposition.getDeployState(), automationComposition.getLockState(), + automationComposition.getSubState(), automationComposition.getStateChangeResult()); switch (result) { case "DEPLOY": supervisionAcHandler.deploy(automationComposition, acDefinition); @@ -395,6 +463,14 @@ public class AutomationCompositionInstantiationProvider { supervisionAcHandler.unlock(automationComposition, acDefinition); break; + case "PREPARE": + supervisionAcHandler.prepare(automationComposition); + break; + + case "REVIEW": + supervisionAcHandler.review(automationComposition); + break; + default: throw new PfModelRuntimeException(Status.BAD_REQUEST, "Not valid " + acInstanceStateUpdate); } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/parameters/AcRuntimeParameterGroup.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/parameters/AcRuntimeParameterGroup.java index a0b6fe13e..e6ce61438 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/parameters/AcRuntimeParameterGroup.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/parameters/AcRuntimeParameterGroup.java @@ -53,5 +53,5 @@ public class AcRuntimeParameterGroup { @Valid @NotNull - private Topics topics; + private Topics topics = new Topics(); } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/parameters/Topics.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/parameters/Topics.java index d485a24ba..6e230d3df 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/parameters/Topics.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/parameters/Topics.java @@ -20,6 +20,7 @@ package org.onap.policy.clamp.acm.runtime.main.parameters; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import org.springframework.validation.annotation.Validated; @@ -27,6 +28,7 @@ import org.springframework.validation.annotation.Validated; @Setter @Validated @AllArgsConstructor +@NoArgsConstructor public class Topics { private String operationTopic; diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java index 75477866a..6a56a2c2b 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandler.java @@ -23,13 +23,13 @@ package org.onap.policy.clamp.acm.runtime.supervision; import io.micrometer.core.annotation.Timed; import io.opentelemetry.context.Context; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import lombok.AllArgsConstructor; import org.onap.policy.clamp.acm.runtime.supervision.comm.AcElementPropertiesPublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.AcPreparePublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionDeployPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionMigrationPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionStateChangePublisher; @@ -37,15 +37,16 @@ import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublish import org.onap.policy.clamp.models.acm.concepts.AcElementDeployAck; 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.AutomationCompositionElement; 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.concepts.ParticipantUtils; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; import org.onap.policy.clamp.models.acm.utils.AcmUtils; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -68,6 +69,7 @@ public class SupervisionAcHandler { private final AcElementPropertiesPublisher acElementPropertiesPublisher; private final AutomationCompositionMigrationPublisher acCompositionMigrationPublisher; private final ParticipantSyncPublisher participantSyncPublisher; + private final AcPreparePublisher acPreparePublisher; private final ExecutorService executor = Context.taskWrapping(Executors.newFixedThreadPool(1)); @@ -150,6 +152,30 @@ public class SupervisionAcHandler { } /** + * Handle prepare Pre Deploy an AutomationComposition instance. + * + * @param automationComposition the AutomationComposition + */ + public void prepare(AutomationComposition automationComposition) { + AcmUtils.setCascadedState(automationComposition, DeployState.UNDEPLOYED, LockState.NONE, SubState.PREPARING); + automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); + automationCompositionProvider.updateAutomationComposition(automationComposition); + executor.execute(() -> acPreparePublisher.sendPrepare(automationComposition)); + } + + /** + * Handle prepare Post Deploy an AutomationComposition instance. + * + * @param automationComposition the AutomationComposition + */ + public void review(AutomationComposition automationComposition) { + AcmUtils.setCascadedState(automationComposition, DeployState.DEPLOYED, LockState.LOCKED, SubState.REVIEWING); + automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); + automationCompositionProvider.updateAutomationComposition(automationComposition); + executor.execute(() -> acPreparePublisher.sendRevew(automationComposition)); + } + + /** * Handle Lock an AutomationComposition instance. * * @param automationComposition the AutomationComposition @@ -231,10 +257,14 @@ public class SupervisionAcHandler { } private void setAcElementStateInDb(AutomationCompositionDeployAck automationCompositionAckMessage) { + if (!validateMessage(automationCompositionAckMessage)) { + return; + } + var automationCompositionOpt = automationCompositionProvider .findAutomationComposition(automationCompositionAckMessage.getAutomationCompositionId()); if (automationCompositionOpt.isEmpty()) { - LOGGER.warn("AutomationComposition not found in database {}", + LOGGER.error("AutomationComposition not found in database {}", automationCompositionAckMessage.getAutomationCompositionId()); return; } @@ -243,13 +273,7 @@ public class SupervisionAcHandler { if (automationCompositionAckMessage.getAutomationCompositionResultMap() == null || automationCompositionAckMessage.getAutomationCompositionResultMap().isEmpty()) { if (DeployState.DELETING.equals(automationComposition.getDeployState())) { - // scenario when Automation Composition instance has never been deployed - for (var element : automationComposition.getElements().values()) { - if (element.getParticipantId().equals(automationCompositionAckMessage.getParticipantId())) { - element.setDeployState(DeployState.DELETED); - automationCompositionProvider.updateAutomationCompositionElement(element); - } - } + deleteAcInstance(automationComposition, automationCompositionAckMessage.getParticipantId()); } else { LOGGER.warn("Empty AutomationCompositionResultMap {} {}", automationCompositionAckMessage.getAutomationCompositionId(), @@ -260,7 +284,7 @@ public class SupervisionAcHandler { var updated = updateState(automationComposition, automationCompositionAckMessage.getAutomationCompositionResultMap().entrySet(), - automationCompositionAckMessage.getStateChangeResult()); + automationCompositionAckMessage.getStateChangeResult(), automationCompositionAckMessage.getStage()); if (updated) { automationComposition = automationCompositionProvider.updateAcState(automationComposition); var acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId()); @@ -268,9 +292,43 @@ public class SupervisionAcHandler { } } + private boolean validateMessage(AutomationCompositionDeployAck acAckMessage) { + if (acAckMessage.getAutomationCompositionId() == null + || acAckMessage.getStateChangeResult() == null) { + LOGGER.error("Not valid AutomationCompositionDeployAck message"); + return false; + } + if (!StateChangeResult.NO_ERROR.equals(acAckMessage.getStateChangeResult()) + && !StateChangeResult.FAILED.equals(acAckMessage.getStateChangeResult())) { + LOGGER.error("Not valid AutomationCompositionDeployAck message, stateChangeResult is not valid {} ", + acAckMessage.getStateChangeResult()); + return false; + } + + if (acAckMessage.getStage() == null) { + for (var el : acAckMessage.getAutomationCompositionResultMap().values()) { + if (AcmUtils.isInTransitionalState(el.getDeployState(), el.getLockState(), SubState.NONE)) { + LOGGER.error("Not valid AutomationCompositionDeployAck message, states are not valid"); + return false; + } + } + } + return true; + } + + private void deleteAcInstance(AutomationComposition automationComposition, UUID participantId) { + // scenario when Automation Composition instance has never been deployed + for (var element : automationComposition.getElements().values()) { + if (element.getParticipantId().equals(participantId)) { + element.setDeployState(DeployState.DELETED); + automationCompositionProvider.updateAutomationCompositionElement(element); + } + } + } + private boolean updateState(AutomationComposition automationComposition, Set<Map.Entry<UUID, AcElementDeployAck>> automationCompositionResultSet, - StateChangeResult stateChangeResult) { + StateChangeResult stateChangeResult, Integer stage) { var updated = false; boolean inProgress = !StateChangeResult.FAILED.equals(automationComposition.getStateChangeResult()); if (inProgress && !stateChangeResult.equals(automationComposition.getStateChangeResult())) { @@ -281,26 +339,20 @@ public class SupervisionAcHandler { for (var acElementAck : automationCompositionResultSet) { var element = automationComposition.getElements().get(acElementAck.getKey()); if (element != null) { - element.setMessage(acElementAck.getValue().getMessage()); + element.setMessage(AcmUtils.validatedMessage(acElementAck.getValue().getMessage())); element.setOutProperties(acElementAck.getValue().getOutProperties()); element.setOperationalState(acElementAck.getValue().getOperationalState()); element.setUseState(acElementAck.getValue().getUseState()); + if (stage == null) { + element.setSubState(SubState.NONE); + } element.setDeployState(acElementAck.getValue().getDeployState()); element.setLockState(acElementAck.getValue().getLockState()); - element.setRestarting(null); + element.setStage(stage); automationCompositionProvider.updateAutomationCompositionElement(element); } } - if (automationComposition.getRestarting() != null) { - var restarting = automationComposition.getElements().values().stream() - .map(AutomationCompositionElement::getRestarting).filter(Objects::nonNull).findAny(); - if (restarting.isEmpty()) { - automationComposition.setRestarting(null); - updated = true; - } - } - return updated; } @@ -308,12 +360,22 @@ public class SupervisionAcHandler { * Handle Migration of an AutomationComposition instance to other ACM Definition. * * @param automationComposition the AutomationComposition - * @param compositionTargetId the ACM Definition Id + * @param serviceTemplate the ServiceTemplate */ - public void migrate(AutomationComposition automationComposition, UUID compositionTargetId) { + public void migrate(AutomationComposition automationComposition, ToscaServiceTemplate serviceTemplate) { AcmUtils.setCascadedState(automationComposition, DeployState.MIGRATING, LockState.LOCKED); + var stage = ParticipantUtils.getFirstStage(automationComposition, serviceTemplate); automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); - executor.execute( - () -> acCompositionMigrationPublisher.send(automationComposition, compositionTargetId)); + automationComposition.setPhase(stage); + executor.execute(() -> acCompositionMigrationPublisher.send(automationComposition, stage)); + } + + /** + * Handle Migration precheck of an AutomationComposition instance to other ACM Definition. + * + * @param automationComposition the AutomationComposition + */ + public void migratePrecheck(AutomationComposition automationComposition) { + executor.execute(() -> acCompositionMigrationPublisher.send(automationComposition, 0)); } } 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 a4e470495..f13f5da2c 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 @@ -30,6 +30,7 @@ import org.onap.policy.clamp.models.acm.concepts.NodeTemplateState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -53,6 +54,22 @@ public class SupervisionHandler { */ @Timed(value = "listener.participant_prime_ack", description = "PARTICIPANT_PRIME_ACK messages received") public void handleParticipantMessage(ParticipantPrimeAck participantPrimeAckMessage) { + if (participantPrimeAckMessage.getCompositionId() == null + || participantPrimeAckMessage.getCompositionState() == null + || participantPrimeAckMessage.getStateChangeResult() == null) { + LOGGER.error("Not valid ParticipantPrimeAck message"); + return; + } + if (AcTypeState.PRIMING.equals(participantPrimeAckMessage.getCompositionState()) + || AcTypeState.DEPRIMING.equals(participantPrimeAckMessage.getCompositionState())) { + LOGGER.error("Not valid state {}", participantPrimeAckMessage.getCompositionState()); + return; + } + if (!StateChangeResult.NO_ERROR.equals(participantPrimeAckMessage.getStateChangeResult()) + && !StateChangeResult.FAILED.equals(participantPrimeAckMessage.getStateChangeResult())) { + LOGGER.error("Vot valid stateChangeResult {} ", participantPrimeAckMessage.getStateChangeResult()); + return; + } var acDefinitionOpt = acDefinitionProvider.findAcDefinition(participantPrimeAckMessage.getCompositionId()); if (acDefinitionOpt.isEmpty()) { LOGGER.warn("AC Definition not found in database {}", participantPrimeAckMessage.getCompositionId()); @@ -60,7 +77,7 @@ public class SupervisionHandler { } var acDefinition = acDefinitionOpt.get(); if (!AcTypeState.PRIMING.equals(acDefinition.getState()) - && !AcTypeState.DEPRIMING.equals(acDefinition.getState()) && acDefinition.getRestarting() == null) { + && !AcTypeState.DEPRIMING.equals(acDefinition.getState())) { LOGGER.error("AC Definition {} already primed/deprimed with participant {}", participantPrimeAckMessage.getCompositionId(), participantPrimeAckMessage.getParticipantId()); return; @@ -81,15 +98,11 @@ public class SupervisionHandler { } boolean completed = true; - boolean restarting = false; for (var element : acDefinition.getElementStateMap().values()) { handlePrimeAckElement(participantPrimeAckMessage, element); if (!finalState.equals(element.getState())) { completed = false; } - if (element.getRestarting() != null) { - restarting = true; - } } if (inProgress && !msgInErrors && completed) { @@ -99,13 +112,9 @@ public class SupervisionHandler { acDefinition.setStateChangeResult(StateChangeResult.NO_ERROR); } } - if (!restarting && acDefinition.getRestarting() != null) { - toUpdate = true; - acDefinition.setRestarting(null); - } if (toUpdate) { acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(), acDefinition.getState(), - acDefinition.getStateChangeResult(), acDefinition.getRestarting()); + acDefinition.getStateChangeResult()); if (!participantPrimeAckMessage.getParticipantId().equals(participantPrimeAckMessage.getReplicaId())) { participantSyncPublisher.sendSync(acDefinition, participantPrimeAckMessage.getReplicaId()); } @@ -114,9 +123,8 @@ public class SupervisionHandler { private void handlePrimeAckElement(ParticipantPrimeAck participantPrimeAckMessage, NodeTemplateState element) { if (participantPrimeAckMessage.getParticipantId().equals(element.getParticipantId())) { - element.setMessage(participantPrimeAckMessage.getMessage()); + element.setMessage(AcmUtils.validatedMessage(participantPrimeAckMessage.getMessage())); element.setState(participantPrimeAckMessage.getCompositionState()); - element.setRestarting(null); acDefinitionProvider.updateAcDefinitionElement(element, participantPrimeAckMessage.getCompositionId()); } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java index 3c93a3571..ea3ef0ff7 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java @@ -30,7 +30,6 @@ import org.apache.commons.collections4.MapUtils; import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantDeregisterAckPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantRegisterAckPublisher; -import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantRestartPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; @@ -40,7 +39,6 @@ import org.onap.policy.clamp.models.acm.concepts.ParticipantDefinition; import org.onap.policy.clamp.models.acm.concepts.ParticipantReplica; import org.onap.policy.clamp.models.acm.concepts.ParticipantState; import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType; -import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantDeregister; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantRegister; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantStatus; @@ -65,7 +63,6 @@ public class SupervisionParticipantHandler { private final ParticipantDeregisterAckPublisher participantDeregisterAckPublisher; private final AutomationCompositionProvider automationCompositionProvider; private final AcDefinitionProvider acDefinitionProvider; - private final ParticipantRestartPublisher participantRestartPublisher; private final ParticipantSyncPublisher participantSyncPublisher; private final AcRuntimeParameterGroup acRuntimeParameterGroup; @@ -183,61 +180,11 @@ public class SupervisionParticipantHandler { private void handleRestart(UUID participantId, UUID replicaId) { var compositionIds = participantProvider.getCompositionIds(participantId); - var oldParticipant = participantId.equals(replicaId); for (var compositionId : compositionIds) { var acDefinition = acDefinitionProvider.getAcDefinition(compositionId); LOGGER.debug("Scan Composition {} for restart", acDefinition.getCompositionId()); - if (oldParticipant) { - handleRestart(participantId, acDefinition); - } else { - handleSyncRestart(participantId, replicaId, acDefinition); - } - } - } - - private void handleRestart(final UUID participantId, AutomationCompositionDefinition acDefinition) { - if (AcTypeState.COMMISSIONED.equals(acDefinition.getState())) { - LOGGER.debug("Composition {} COMMISSIONED", acDefinition.getCompositionId()); - return; - } - LOGGER.debug("Composition to be send in Restart message {}", acDefinition.getCompositionId()); - for (var elementState : acDefinition.getElementStateMap().values()) { - if (participantId.equals(elementState.getParticipantId())) { - elementState.setRestarting(true); - } - } - // expected final state - if (StateChangeResult.TIMEOUT.equals(acDefinition.getStateChangeResult())) { - acDefinition.setStateChangeResult(StateChangeResult.NO_ERROR); - } - acDefinition.setRestarting(true); - acDefinitionProvider.updateAcDefinition(acDefinition, - acRuntimeParameterGroup.getAcmParameters().getToscaCompositionName()); - - var automationCompositionList = - automationCompositionProvider.getAcInstancesByCompositionId(acDefinition.getCompositionId()); - var automationCompositions = automationCompositionList.stream() - .filter(ac -> isAcToBeRestarted(participantId, ac)).toList(); - participantRestartPublisher.send(participantId, acDefinition, automationCompositions); - } - - private boolean isAcToBeRestarted(UUID participantId, AutomationComposition automationComposition) { - boolean toAdd = false; - for (var element : automationComposition.getElements().values()) { - if (participantId.equals(element.getParticipantId())) { - element.setRestarting(true); - toAdd = true; - } - } - if (toAdd) { - automationComposition.setRestarting(true); - // expected final state - if (StateChangeResult.TIMEOUT.equals(automationComposition.getStateChangeResult())) { - automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); - } - automationCompositionProvider.updateAutomationComposition(automationComposition); + handleSyncRestart(participantId, replicaId, acDefinition); } - return toAdd; } private void handleSyncRestart(final UUID participantId, UUID replicaId, diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java index d1aa6c239..c4cebb430 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java @@ -22,10 +22,12 @@ package org.onap.policy.clamp.acm.runtime.supervision; +import java.util.Comparator; import java.util.HashMap; import java.util.UUID; import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionDeployPublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionMigrationPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionStateChangePublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; @@ -34,6 +36,7 @@ import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.ParticipantUtils; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; import org.onap.policy.clamp.models.acm.utils.AcmUtils; @@ -57,6 +60,7 @@ public class SupervisionScanner { private final AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher; private final AutomationCompositionDeployPublisher automationCompositionDeployPublisher; private final ParticipantSyncPublisher participantSyncPublisher; + private final AutomationCompositionMigrationPublisher automationCompositionMigrationPublisher; /** * Constructor for instantiating SupervisionScanner. @@ -72,12 +76,14 @@ public class SupervisionScanner { final AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher, final AutomationCompositionDeployPublisher automationCompositionDeployPublisher, final ParticipantSyncPublisher participantSyncPublisher, + final AutomationCompositionMigrationPublisher automationCompositionMigrationPublisher, final AcRuntimeParameterGroup acRuntimeParameterGroup) { this.automationCompositionProvider = automationCompositionProvider; this.acDefinitionProvider = acDefinitionProvider; this.automationCompositionStateChangePublisher = automationCompositionStateChangePublisher; this.automationCompositionDeployPublisher = automationCompositionDeployPublisher; this.participantSyncPublisher = participantSyncPublisher; + this.automationCompositionMigrationPublisher = automationCompositionMigrationPublisher; this.maxStatusWaitMs = acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs(); } @@ -95,11 +101,9 @@ public class SupervisionScanner { var acList = automationCompositionProvider.getAcInstancesInTransition(); HashMap<UUID, AutomationCompositionDefinition> acDefinitionMap = new HashMap<>(); for (var automationComposition : acList) { - var acDefinition = acDefinitionMap.get(automationComposition.getCompositionId()); - if (acDefinition == null) { - acDefinition = acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId()); - acDefinitionMap.put(acDefinition.getCompositionId(), acDefinition); - } + var compositionId = automationComposition.getCompositionTargetId() != null + ? automationComposition.getCompositionTargetId() : automationComposition.getCompositionId(); + var acDefinition = acDefinitionMap.computeIfAbsent(compositionId, acDefinitionProvider::getAcDefinition); scanAutomationComposition(automationComposition, acDefinition.getServiceTemplate()); } LOGGER.debug("Automation composition scan complete . . ."); @@ -117,11 +121,12 @@ public class SupervisionScanner { for (var element : acDefinition.getElementStateMap().values()) { if (!finalState.equals(element.getState())) { completed = false; + break; } } if (completed) { acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(), finalState, - StateChangeResult.NO_ERROR, null); + StateChangeResult.NO_ERROR); participantSyncPublisher.sendSync(acDefinition, null); } else { handleTimeout(acDefinition); @@ -133,13 +138,33 @@ public class SupervisionScanner { LOGGER.debug("scanning automation composition {} . . .", automationComposition.getInstanceId()); if (!AcmUtils.isInTransitionalState(automationComposition.getDeployState(), - automationComposition.getLockState()) + automationComposition.getLockState(), automationComposition.getSubState()) || StateChangeResult.FAILED.equals(automationComposition.getStateChangeResult())) { LOGGER.debug("automation composition {} scanned, OK", automationComposition.getInstanceId()); return; } + if (DeployState.MIGRATING.equals(automationComposition.getDeployState())) { + scanStage(automationComposition, serviceTemplate); + } else if (DeployState.UPDATING.equals(automationComposition.getDeployState()) + || SubState.PREPARING.equals(automationComposition.getSubState()) + || SubState.REVIEWING.equals(automationComposition.getSubState()) + || SubState.MIGRATION_PRECHECKING.equals(automationComposition.getSubState())) { + simpleScan(automationComposition, serviceTemplate); + } else { + scanWithPhase(automationComposition, serviceTemplate); + } + } + + /** + * Scan with startPhase: DEPLOY, UNDEPLOY, LOCK and UNLOCK. + * + * @param automationComposition the AutomationComposition + * @param serviceTemplate the ToscaServiceTemplate + */ + private void scanWithPhase(final AutomationComposition automationComposition, + ToscaServiceTemplate serviceTemplate) { var completed = true; var minSpNotCompleted = 1000; // min startPhase not completed var maxSpNotCompleted = 0; // max startPhase not completed @@ -151,7 +176,8 @@ public class SupervisionScanner { int startPhase = ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties()); defaultMin = Math.min(defaultMin, startPhase); defaultMax = Math.max(defaultMax, startPhase); - if (AcmUtils.isInTransitionalState(element.getDeployState(), element.getLockState())) { + if (AcmUtils.isInTransitionalState(element.getDeployState(), element.getLockState(), + element.getSubState())) { completed = false; minSpNotCompleted = Math.min(minSpNotCompleted, startPhase); maxSpNotCompleted = Math.max(maxSpNotCompleted, startPhase); @@ -159,36 +185,86 @@ public class SupervisionScanner { } if (completed) { - LOGGER.debug("automation composition scan: transition state {} {} completed", - automationComposition.getDeployState(), automationComposition.getLockState()); - complete(automationComposition, serviceTemplate); } else { LOGGER.debug("automation composition scan: transition state {} {} not completed", automationComposition.getDeployState(), automationComposition.getLockState()); - if (DeployState.UPDATING.equals(automationComposition.getDeployState()) - || DeployState.MIGRATING.equals(automationComposition.getDeployState())) { - // UPDATING do not need phases - handleTimeoutUpdate(automationComposition); - return; - } - var isForward = AcmUtils.isForward(automationComposition.getDeployState(), automationComposition.getLockState()); var nextSpNotCompleted = isForward ? minSpNotCompleted : maxSpNotCompleted; if (nextSpNotCompleted != automationComposition.getPhase()) { - sendAutomationCompositionMsg(automationComposition, serviceTemplate, nextSpNotCompleted, false); + sendAutomationCompositionMsg(automationComposition, serviceTemplate, nextSpNotCompleted); + } else { + handleTimeout(automationComposition); + } + } + } + + /** + * Simple scan: UPDATE, PREPARE, REVIEW, MIGRATE_PRECHECKING. + * + * @param automationComposition the AutomationComposition + * @param serviceTemplate the ToscaServiceTemplate + */ + private void simpleScan(final AutomationComposition automationComposition, ToscaServiceTemplate serviceTemplate) { + var completed = automationComposition.getElements().values().stream() + .filter(element -> AcmUtils.isInTransitionalState(element.getDeployState(), element.getLockState(), + element.getSubState())).findFirst().isEmpty(); + + if (completed) { + complete(automationComposition, serviceTemplate); + } else { + handleTimeout(automationComposition); + } + } + + /** + * Scan with stage: MIGRATE. + * + * @param automationComposition the AutomationComposition + * @param serviceTemplate the ToscaServiceTemplate + */ + private void scanStage(final AutomationComposition automationComposition, ToscaServiceTemplate serviceTemplate) { + var completed = true; + var minStageNotCompleted = 1000; // min stage not completed + for (var element : automationComposition.getElements().values()) { + if (AcmUtils.isInTransitionalState(element.getDeployState(), element.getLockState(), + element.getSubState())) { + var toscaNodeTemplate = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() + .get(element.getDefinition().getName()); + var stageSet = ParticipantUtils.findStageSet(toscaNodeTemplate.getProperties()); + var minStage = stageSet.stream().min(Comparator.comparing(Integer::valueOf)).orElse(0); + int stage = element.getStage() != null ? element.getStage() : minStage; + minStageNotCompleted = Math.min(minStageNotCompleted, stage); + completed = false; + } + } + + if (completed) { + complete(automationComposition, serviceTemplate); + } else { + LOGGER.debug("automation composition scan: transition from state {} to {} not completed", + automationComposition.getDeployState(), automationComposition.getLockState()); + + if (minStageNotCompleted != automationComposition.getPhase()) { + savePahese(automationComposition, minStageNotCompleted); + LOGGER.debug("retry message AutomationCompositionMigration"); + automationCompositionMigrationPublisher.send(automationComposition, minStageNotCompleted); } else { - handleTimeoutWithPhase(automationComposition, serviceTemplate); + handleTimeout(automationComposition); } } } private void complete(final AutomationComposition automationComposition, ToscaServiceTemplate serviceTemplate) { + LOGGER.debug("automation composition scan: transition state {} {} {} completed", + automationComposition.getDeployState(), automationComposition.getLockState(), + automationComposition.getSubState()); + var deployState = automationComposition.getDeployState(); if (DeployState.MIGRATING.equals(automationComposition.getDeployState())) { // migration scenario @@ -198,6 +274,8 @@ public class SupervisionScanner { automationComposition.setDeployState(AcmUtils.deployCompleted(deployState)); automationComposition.setLockState(AcmUtils.lockCompleted(deployState, automationComposition.getLockState())); automationComposition.setPhase(null); + automationComposition.setSubState(SubState.NONE); + automationComposition.setPrecheck(null); if (StateChangeResult.TIMEOUT.equals(automationComposition.getStateChangeResult())) { automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); } @@ -221,71 +299,45 @@ public class SupervisionScanner { LOGGER.debug("Report timeout for the ac definition {}", acDefinition.getCompositionId()); acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT); acDefinitionProvider.updateAcDefinitionState(acDefinition.getCompositionId(), - acDefinition.getState(), acDefinition.getStateChangeResult(), acDefinition.getRestarting()); + acDefinition.getState(), acDefinition.getStateChangeResult()); } } - private void handleTimeoutUpdate(AutomationComposition automationComposition) { - if (StateChangeResult.TIMEOUT.equals(automationComposition.getStateChangeResult())) { - LOGGER.debug("The ac instance is in timeout {}", automationComposition.getInstanceId()); - return; - } - var now = TimestampHelper.nowEpochMilli(); - var lastMsg = TimestampHelper.toEpochMilli(automationComposition.getLastMsg()); - for (var element : automationComposition.getElements().values()) { - if (!AcmUtils.isInTransitionalState(element.getDeployState(), element.getLockState())) { - continue; - } - if ((now - lastMsg) > maxStatusWaitMs) { - LOGGER.debug("Report timeout for the ac instance {}", automationComposition.getInstanceId()); - automationComposition.setStateChangeResult(StateChangeResult.TIMEOUT); - automationCompositionProvider.updateAutomationComposition(automationComposition); - break; - } - } - } + private void handleTimeout(AutomationComposition automationComposition) { + LOGGER.debug("automation composition scan: transition from state {} to {} {} not completed", + automationComposition.getDeployState(), automationComposition.getLockState(), + automationComposition.getSubState()); - private void handleTimeoutWithPhase(AutomationComposition automationComposition, - ToscaServiceTemplate serviceTemplate) { if (StateChangeResult.TIMEOUT.equals(automationComposition.getStateChangeResult())) { LOGGER.debug("The ac instance is in timeout {}", automationComposition.getInstanceId()); return; } - int currentPhase = automationComposition.getPhase(); var now = TimestampHelper.nowEpochMilli(); var lastMsg = TimestampHelper.toEpochMilli(automationComposition.getLastMsg()); - for (var element : automationComposition.getElements().values()) { - if (!AcmUtils.isInTransitionalState(element.getDeployState(), element.getLockState())) { - continue; - } - var toscaNodeTemplate = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() - .get(element.getDefinition().getName()); - int startPhase = ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties()); - if (currentPhase != startPhase) { - continue; - } - if ((now - lastMsg) > maxStatusWaitMs) { - LOGGER.debug("Report timeout for the ac instance {}", automationComposition.getInstanceId()); - automationComposition.setStateChangeResult(StateChangeResult.TIMEOUT); - automationCompositionProvider.updateAutomationComposition(automationComposition); - break; - } + if ((now - lastMsg) > maxStatusWaitMs) { + LOGGER.debug("Report timeout for the ac instance {}", automationComposition.getInstanceId()); + automationComposition.setStateChangeResult(StateChangeResult.TIMEOUT); + automationCompositionProvider.updateAcState(automationComposition); } } - private void sendAutomationCompositionMsg(AutomationComposition automationComposition, - ToscaServiceTemplate serviceTemplate, int startPhase, boolean firstStartPhase) { + private void savePahese(AutomationComposition automationComposition, int startPhase) { automationComposition.setLastMsg(TimestampHelper.now()); automationComposition.setPhase(startPhase); - automationCompositionProvider.updateAutomationComposition(automationComposition); + automationCompositionProvider.updateAcState(automationComposition); + } + + private void sendAutomationCompositionMsg(AutomationComposition automationComposition, + ToscaServiceTemplate serviceTemplate, int startPhase) { + savePahese(automationComposition, startPhase); if (DeployState.DEPLOYING.equals(automationComposition.getDeployState())) { - LOGGER.debug("retry message AutomationCompositionUpdate"); + LOGGER.debug("retry message AutomationCompositionDeploy"); automationCompositionDeployPublisher.send(automationComposition, serviceTemplate, startPhase, - firstStartPhase); + false); } else { LOGGER.debug("retry message AutomationCompositionStateChange"); - automationCompositionStateChangePublisher.send(automationComposition, startPhase, firstStartPhase); + automationCompositionStateChangePublisher.send(automationComposition, startPhase, false); } } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcPreparePublisher.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcPreparePublisher.java new file mode 100644 index 000000000..acf403595 --- /dev/null +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AcPreparePublisher.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.supervision.comm; + +import io.micrometer.core.annotation.Timed; +import java.time.Instant; +import java.util.UUID; +import lombok.AllArgsConstructor; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionPrepare; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +@AllArgsConstructor +public class AcPreparePublisher extends AbstractParticipantPublisher<AutomationCompositionPrepare> { + + private static final Logger LOGGER = LoggerFactory.getLogger(AcPreparePublisher.class); + + /** + * Send AutomationCompositionPrepare Prepare message to Participant. + * + * @param automationComposition the AutomationComposition + */ + @Timed(value = "publisher.prepare", description = "AC Prepare Pre Deploy published") + public void sendPrepare(AutomationComposition automationComposition) { + var acPrepare = createAutomationCompositionPrepare(automationComposition.getCompositionId(), + automationComposition.getInstanceId()); + acPrepare.setParticipantList( + AcmUtils.createParticipantDeployList(automationComposition, DeployOrder.NONE)); + LOGGER.debug("AC Prepare sent {}", acPrepare); + super.send(acPrepare); + } + + /** + * Send AutomationCompositionPrepare Review message to Participant. + * + * @param automationComposition the AutomationComposition + */ + @Timed(value = "publisher.review", description = "AC Review Post Deploy published") + public void sendRevew(AutomationComposition automationComposition) { + var acPrepare = createAutomationCompositionPrepare(automationComposition.getCompositionId(), + automationComposition.getInstanceId()); + acPrepare.setPreDeploy(false); + LOGGER.debug("AC Review sent {}", acPrepare); + super.send(acPrepare); + } + + private AutomationCompositionPrepare createAutomationCompositionPrepare(UUID compositionId, UUID instanceId) { + var acPrepare = new AutomationCompositionPrepare(); + acPrepare.setCompositionId(compositionId); + acPrepare.setAutomationCompositionId(instanceId); + acPrepare.setMessageId(UUID.randomUUID()); + acPrepare.setTimestamp(Instant.now()); + return acPrepare; + } +} diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AutomationCompositionMigrationPublisher.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AutomationCompositionMigrationPublisher.java index e26a5403b..572f7b1fe 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AutomationCompositionMigrationPublisher.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/AutomationCompositionMigrationPublisher.java @@ -36,20 +36,22 @@ public class AutomationCompositionMigrationPublisher * Send AutomationCompositionMigration message to Participant. * * @param automationComposition the AutomationComposition - * @param compositionTargetId the Composition Definition Target + * @param stage the stage to execute */ @Timed( value = "publisher.automation_composition_migration", description = "AUTOMATION_COMPOSITION_MIGRATION messages published") - public void send(AutomationComposition automationComposition, UUID compositionTargetId) { - var acsc = new AutomationCompositionMigration(); - acsc.setCompositionId(automationComposition.getCompositionId()); - acsc.setAutomationCompositionId(automationComposition.getInstanceId()); - acsc.setMessageId(UUID.randomUUID()); - acsc.setCompositionTargetId(compositionTargetId); - acsc.setParticipantUpdatesList( + public void send(AutomationComposition automationComposition, int stage) { + var acMigration = new AutomationCompositionMigration(); + acMigration.setPrecheck(Boolean.TRUE.equals(automationComposition.getPrecheck())); + acMigration.setCompositionId(automationComposition.getCompositionId()); + acMigration.setAutomationCompositionId(automationComposition.getInstanceId()); + acMigration.setMessageId(UUID.randomUUID()); + acMigration.setCompositionTargetId(automationComposition.getCompositionTargetId()); + acMigration.setStage(stage); + acMigration.setParticipantUpdatesList( AcmUtils.createParticipantDeployList(automationComposition, DeployOrder.MIGRATE)); - super.send(acsc); + super.send(acMigration); } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantRestartPublisher.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantRestartPublisher.java deleted file mode 100644 index 540cf62be..000000000 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/comm/ParticipantRestartPublisher.java +++ /dev/null @@ -1,75 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.clamp.acm.runtime.supervision.comm; - -import io.micrometer.core.annotation.Timed; -import java.time.Instant; -import java.util.List; -import java.util.UUID; -import lombok.AllArgsConstructor; -import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup; -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.messages.kafka.participant.ParticipantRestart; -import org.onap.policy.clamp.models.acm.utils.AcmUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -@Component -@AllArgsConstructor -public class ParticipantRestartPublisher extends AbstractParticipantPublisher<ParticipantRestart> { - - private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantRestartPublisher.class); - private final AcRuntimeParameterGroup acRuntimeParameterGroup; - - /** - * Send Restart to Participant. - * - * @param participantId the ParticipantId - * @param acmDefinition the AutomationComposition Definition - * @param automationCompositions the list of automationCompositions - */ - @Timed(value = "publisher.participant_restart", description = "Participant Restart published") - public void send(UUID participantId, AutomationCompositionDefinition acmDefinition, - List<AutomationComposition> automationCompositions) { - - var message = new ParticipantRestart(); - message.setParticipantId(participantId); - message.setCompositionId(acmDefinition.getCompositionId()); - message.setMessageId(UUID.randomUUID()); - message.setTimestamp(Instant.now()); - message.setState(acmDefinition.getState()); - message.setParticipantDefinitionUpdates( - AcmUtils.prepareParticipantRestarting(participantId, acmDefinition, - acRuntimeParameterGroup.getAcmParameters().getToscaElementName())); - var toscaServiceTemplateFragment = AcmUtils.getToscaServiceTemplateFragment(acmDefinition.getServiceTemplate()); - - for (var automationComposition : automationCompositions) { - var restartAc = AcmUtils - .createAcRestart(automationComposition, participantId, toscaServiceTemplateFragment); - message.getAutomationcompositionList().add(restartAc); - } - - LOGGER.debug("Participant Restart sent {}", message.getMessageId()); - super.send(message); - } -} diff --git a/runtime-acm/src/main/resources/application.yaml b/runtime-acm/src/main/resources/application.yaml index 0e2585dba..bca01ace8 100644 --- a/runtime-acm/src/main/resources/application.yaml +++ b/runtime-acm/src/main/resources/application.yaml @@ -44,21 +44,18 @@ runtime: maxStatusWaitMs: 200000 topicParameterGroup: topicSources: - - - topic: ${runtime.topics.operationTopic} + - topic: ${runtime.topics.operationTopic} servers: - ${topicServer:kafka:9092} topicCommInfrastructure: NOOP fetchTimeout: 15000 topicSinks: - - - topic: ${runtime.topics.operationTopic} + - topic: ${runtime.topics.operationTopic} servers: - ${topicServer:kafka:9092} topicCommInfrastructure: NOOP - - - topic: ${runtime.topics.syncTopic} + - topic: ${runtime.topics.syncTopic} servers: - ${topicServer:kafka:9092} topicCommInfrastructure: NOOP 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 413719110..8c76baef7 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.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; @@ -53,8 +54,6 @@ class CommissioningProviderTest { /** * Test the fetching of automation composition definitions (ToscaServiceTemplates). - * - * @throws Exception . */ @Test void testGetAutomationCompositionDefinitions() { @@ -63,7 +62,7 @@ class CommissioningProviderTest { var acRuntimeParameterGroup = mock(AcRuntimeParameterGroup.class); var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, null, null, - acRuntimeParameterGroup); + acRuntimeParameterGroup); var serviceTemplates = provider.getAutomationCompositionDefinitions(null, null); assertThat(serviceTemplates.getServiceTemplates()).isEmpty(); @@ -75,12 +74,11 @@ class CommissioningProviderTest { /** * Test the creation of automation composition definitions (ToscaServiceTemplates). - * - * @throws Exception . */ @Test void testCreateAutomationCompositionDefinitions() { var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + assertNotNull(serviceTemplate); serviceTemplate.setName("Name"); serviceTemplate.setVersion("1.0.0"); var acmDefinition = new AutomationCompositionDefinition(); @@ -88,15 +86,15 @@ class CommissioningProviderTest { acmDefinition.setServiceTemplate(serviceTemplate); var acDefinitionProvider = mock(AcDefinitionProvider.class); when(acDefinitionProvider.createAutomationCompositionDefinition(serviceTemplate, - CommonTestData.TOSCA_ELEMENT_NAME, CommonTestData.TOSCA_COMP_NAME)).thenReturn(acmDefinition); + CommonTestData.TOSCA_ELEMENT_NAME, CommonTestData.TOSCA_COMP_NAME)).thenReturn(acmDefinition); var acProvider = mock(AutomationCompositionProvider.class); var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, null, null, - CommonTestData.getTestParamaterGroup()); + CommonTestData.getTestParamaterGroup()); var affectedDefinitions = provider.createAutomationCompositionDefinition(serviceTemplate) - .getAffectedAutomationCompositionDefinitions(); + .getAffectedAutomationCompositionDefinitions(); verify(acDefinitionProvider).createAutomationCompositionDefinition(serviceTemplate, - CommonTestData.TOSCA_ELEMENT_NAME, CommonTestData.TOSCA_COMP_NAME); + CommonTestData.TOSCA_ELEMENT_NAME, CommonTestData.TOSCA_COMP_NAME); // Response should return the number of node templates present in the service template assertThat(affectedDefinitions).hasSize(7); } @@ -104,7 +102,6 @@ class CommissioningProviderTest { /** * Test the fetching of a full ToscaServiceTemplate object - as opposed to the reduced template that is being * tested in the testGetToscaServiceTemplateReduced() test. - * */ @Test void testGetToscaServiceTemplateList() { @@ -113,6 +110,7 @@ class CommissioningProviderTest { var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, null, null, null); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + assertNotNull(serviceTemplate); when(acDefinitionProvider.getServiceTemplateList(null, null)).thenReturn(List.of(serviceTemplate)); var returnedServiceTemplate = provider.getAutomationCompositionDefinitions(null, null); @@ -121,7 +119,7 @@ class CommissioningProviderTest { } @Test - void testDeletecDefinitionDabRequest() { + void testDeleteAcDefinitionDabRequest() { var acDefinitionProvider = mock(AcDefinitionProvider.class); var acProvider = mock(AutomationCompositionProvider.class); @@ -131,7 +129,7 @@ class CommissioningProviderTest { var provider = new CommissioningProvider(acDefinitionProvider, acProvider, null, null, null, null); assertThatThrownBy(() -> provider.deleteAutomationCompositionDefinition(compositionId)) - .hasMessageMatching("Delete instances, to commission automation composition definitions"); + .hasMessageMatching("Delete instances, to commission automation composition definitions"); } @Test @@ -139,6 +137,7 @@ class CommissioningProviderTest { var acDefinitionProvider = mock(AcDefinitionProvider.class); var compositionId = UUID.randomUUID(); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + assertNotNull(serviceTemplate); when(acDefinitionProvider.deleteAcDefintion(compositionId)).thenReturn(serviceTemplate); var acmDefinition = new AutomationCompositionDefinition(); @@ -159,14 +158,14 @@ class CommissioningProviderTest { void testPriming() { var acDefinitionProvider = mock(AcDefinitionProvider.class); var acmDefinition = CommonTestData.createAcDefinition( - InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.COMMISSIONED); + InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.COMMISSIONED); var compositionId = acmDefinition.getCompositionId(); when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acmDefinition); var participantPrimePublisher = mock(ParticipantPrimePublisher.class); var provider = new CommissioningProvider(acDefinitionProvider, mock(AutomationCompositionProvider.class), - mock(ParticipantProvider.class), new AcTypeStateResolver(), participantPrimePublisher, - CommonTestData.getTestParamaterGroup()); + mock(ParticipantProvider.class), new AcTypeStateResolver(), participantPrimePublisher, + CommonTestData.getTestParamaterGroup()); var acTypeStateUpdate = new AcTypeStateUpdate(); acTypeStateUpdate.setPrimeOrder(PrimeOrder.PRIME); @@ -179,15 +178,15 @@ class CommissioningProviderTest { void testDepriming() { var acDefinitionProvider = mock(AcDefinitionProvider.class); var acmDefinition = CommonTestData.createAcDefinition( - InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMED); + InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMED); var compositionId = acmDefinition.getCompositionId(); when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acmDefinition); var participantPrimePublisher = mock(ParticipantPrimePublisher.class); var participantProvider = mock(ParticipantProvider.class); var provider = new CommissioningProvider(acDefinitionProvider, mock(AutomationCompositionProvider.class), - participantProvider, new AcTypeStateResolver(), participantPrimePublisher, - CommonTestData.getTestParamaterGroup()); + participantProvider, new AcTypeStateResolver(), participantPrimePublisher, + CommonTestData.getTestParamaterGroup()); var acTypeStateUpdate = new AcTypeStateUpdate(); acTypeStateUpdate.setPrimeOrder(PrimeOrder.DEPRIME); @@ -201,19 +200,19 @@ class CommissioningProviderTest { void testBadRequest() { var acProvider = mock(AutomationCompositionProvider.class); var provider = new CommissioningProvider(mock(AcDefinitionProvider.class), acProvider, - mock(ParticipantProvider.class), new AcTypeStateResolver(), mock(ParticipantPrimePublisher.class), - mock(AcRuntimeParameterGroup.class)); + mock(ParticipantProvider.class), new AcTypeStateResolver(), mock(ParticipantPrimePublisher.class), + mock(AcRuntimeParameterGroup.class)); var compositionId = UUID.randomUUID(); when(acProvider.getAcInstancesByCompositionId(compositionId)).thenReturn(List.of(new AutomationComposition())); var toscaServiceTemplate = new ToscaServiceTemplate(); assertThatThrownBy(() -> provider.updateCompositionDefinition(compositionId, toscaServiceTemplate)) - .hasMessageMatching("There are ACM instances, Update of ACM Definition not allowed"); + .hasMessageMatching("There are ACM instances, Update of ACM Definition not allowed"); var acTypeStateUpdate = new AcTypeStateUpdate(); assertThatThrownBy(() -> provider.compositionDefinitionPriming(compositionId, acTypeStateUpdate)) - .hasMessageMatching("There are instances, Priming/Depriming not allowed"); + .hasMessageMatching("There are instances, Priming/Depriming not allowed"); } @Test @@ -225,31 +224,13 @@ class CommissioningProviderTest { when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acmDefinition); var provider = new CommissioningProvider(acDefinitionProvider, mock(AutomationCompositionProvider.class), - mock(ParticipantProvider.class), new AcTypeStateResolver(), mock(ParticipantPrimePublisher.class), - mock(AcRuntimeParameterGroup.class)); + mock(ParticipantProvider.class), new AcTypeStateResolver(), mock(ParticipantPrimePublisher.class), + mock(AcRuntimeParameterGroup.class)); assertThatThrownBy(() -> provider.updateCompositionDefinition(compositionId, toscaServiceTemplate)) - .hasMessageMatching("ACM not in COMMISSIONED state, Update of ACM Definition not allowed"); + .hasMessageMatching("ACM not in COMMISSIONED state, Update of ACM Definition not allowed"); assertThatThrownBy(() -> provider.deleteAutomationCompositionDefinition(compositionId)) - .hasMessageMatching("ACM not in COMMISSIONED state, Delete of ACM Definition not allowed"); - } - - @Test - void testPrimingBadRequest() { - var acDefinitionProvider = mock(AcDefinitionProvider.class); - var toscaServiceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); - var acmDefinition = CommonTestData.createAcDefinition(toscaServiceTemplate, AcTypeState.PRIMED); - acmDefinition.setRestarting(true); - var compositionId = acmDefinition.getCompositionId(); - when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acmDefinition); - - var provider = new CommissioningProvider(acDefinitionProvider, mock(AutomationCompositionProvider.class), - mock(ParticipantProvider.class), new AcTypeStateResolver(), mock(ParticipantPrimePublisher.class), - mock(AcRuntimeParameterGroup.class)); - - var acTypeStateUpdate = new AcTypeStateUpdate(); - assertThatThrownBy(() -> provider.compositionDefinitionPriming(compositionId, acTypeStateUpdate)) - .hasMessageMatching("There is a restarting process, Priming/Depriming not allowed"); + .hasMessageMatching("ACM not in COMMISSIONED state, Delete of ACM Definition not allowed"); } } 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 ed8badf8b..16de37e7f 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 @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation. + * Copyright (C) 2021-2024 Nordix Foundation. * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,6 +34,7 @@ import jakarta.ws.rs.core.Response; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -61,7 +62,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -@ActiveProfiles({ "test", "default" }) +@ActiveProfiles({"test", "default"}) class CommissioningControllerTest extends CommonRestController { private static final String COMMISSIONING_ENDPOINT = "compositions"; @@ -72,6 +73,7 @@ class CommissioningControllerTest extends CommonRestController { @Autowired private ParticipantProvider participantProvider; + @LocalServerPort private int randomServerPort; @@ -88,6 +90,11 @@ class CommissioningControllerTest extends CommonRestController { super.setHttpPrefix(randomServerPort); } + @AfterEach + void after() { + super.client.close(); + } + @Test void testSwagger() { super.testSwagger(COMMISSIONING_ENDPOINT); @@ -111,15 +118,16 @@ class CommissioningControllerTest extends CommonRestController { @Test void testCreateBadRequest() { var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); - var resp = invocationBuilder.post(Entity.json("NotToscaServiceTempalte")); + var resp = invocationBuilder.post(Entity.json("NotToscaServiceTemplate")); assertThat(Response.Status.BAD_REQUEST.getStatusCode()).isEqualTo(resp.getStatus()); var commissioningResponse = resp.readEntity(CommissioningResponse.class); assertThat(commissioningResponse.getErrorDetails()) .isEqualTo("org.springframework.http.converter.HttpMessageNotReadableException " - + "Bad Request Could not read JSON: java.lang.IllegalStateException: " + + "Could not read JSON: java.lang.IllegalStateException: " + "Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $"); assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).isNull(); + resp.close(); } @Test @@ -132,7 +140,7 @@ class CommissioningControllerTest extends CommonRestController { var commissioningResponse = createServiceTemplate(serviceTemplateCreate, Response.Status.INTERNAL_SERVER_ERROR); assertThat(commissioningResponse.getErrorDetails()) - .isEqualTo("java.lang.IllegalArgumentException Internal Server Error parameter " + .isEqualTo("java.lang.IllegalArgumentException parameter " + "\"version\": value \"1.0.wrong\", does not match regular expression \"" + PfKey.VERSION_REGEXP + "\""); assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).isNull(); @@ -149,7 +157,7 @@ class CommissioningControllerTest extends CommonRestController { assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(7); for (var nodeTemplateName : serviceTemplateCreate.getToscaTopologyTemplate().getNodeTemplates().keySet()) { assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream() - .anyMatch(ac -> ac.getName().equals(nodeTemplateName))); + .anyMatch(ac -> ac.getName().equals(nodeTemplateName))); } } @@ -161,6 +169,7 @@ class CommissioningControllerTest extends CommonRestController { assertNull(commissioningResponse.getErrorDetails()); // Response should return the number of node templates present in the service template assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(11); + assertNotNull(serviceTemplateCreate); for (var nodeTemplateName : serviceTemplateCreate.getToscaTopologyTemplate().getNodeTemplates().keySet()) { assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream() .anyMatch(ac -> ac.getName().equals(nodeTemplateName))); @@ -168,7 +177,7 @@ class CommissioningControllerTest extends CommonRestController { } private CommissioningResponse createServiceTemplate(ToscaServiceTemplate serviceTemplateCreate, - Response.Status statusExpected) { + Response.Status statusExpected) { var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); try (var resp = invocationBuilder.post(Entity.json(serviceTemplateCreate))) { assertEquals(statusExpected.getStatusCode(), resp.getStatus()); @@ -199,17 +208,17 @@ class CommissioningControllerTest extends CommonRestController { assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(7); for (var nodeTemplateName : serviceTemplateUpdate.getToscaTopologyTemplate().getNodeTemplates().keySet()) { assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream() - .anyMatch(ac -> ac.getName().equals(nodeTemplateName))); + .anyMatch(ac -> ac.getName().equals(nodeTemplateName))); } - var entity = getServiceTemplate(COMMISSIONING_ENDPOINT + "/" + compositionId, Response.Status.OK); + var entity = getServiceTemplate(COMMISSIONING_ENDPOINT + "/" + compositionId); assertThat(entity.getServiceTemplate().getDataTypes()).containsKey(toscaDataType.getName()); } - private AutomationCompositionDefinition getServiceTemplate(String url, Response.Status statusExpected) { + private AutomationCompositionDefinition getServiceTemplate(String url) { var invocationBuilder = super.sendRequest(url); try (var resp = invocationBuilder.buildGet().invoke()) { - assertEquals(statusExpected.getStatusCode(), resp.getStatus()); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); return resp.readEntity(AutomationCompositionDefinition.class); } } @@ -221,6 +230,7 @@ class CommissioningControllerTest extends CommonRestController { assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); var entityList = rawresp.readEntity(ToscaServiceTemplate.class); assertThat(entityList.getNodeTypes()).isNull(); + rawresp.close(); } @Test @@ -232,6 +242,7 @@ class CommissioningControllerTest extends CommonRestController { assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); var entityList = rawresp.readEntity(ToscaServiceTemplate.class); assertNotNull(entityList); + rawresp.close(); } @Test @@ -264,14 +275,15 @@ class CommissioningControllerTest extends CommonRestController { body.setPrimeOrder(PrimeOrder.PRIME); var resp = invocationBuilder.put(Entity.json(body)); assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + resp.close(); } private UUID createEntryInDB(String name) { var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate); serviceTemplateCreate.setName(name); var acmDefinition = acDefinitionProvider - .createAutomationCompositionDefinition(serviceTemplateCreate, CommonTestData.TOSCA_ELEMENT_NAME, - CommonTestData.TOSCA_COMP_NAME); + .createAutomationCompositionDefinition(serviceTemplateCreate, CommonTestData.TOSCA_ELEMENT_NAME, + CommonTestData.TOSCA_COMP_NAME); return acmDefinition.getCompositionId(); } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/config/TestOpenTelemetry.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/config/TestOpenTelemetry.java new file mode 100644 index 000000000..8996d77cd --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/config/TestOpenTelemetry.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START=============================================== + * Copyright (C) 2024 Nordix Foundation. + * ======================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END================================================= + */ + +package org.onap.policy.clamp.acm.runtime.config; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ActiveProfiles; + +@ActiveProfiles("tracing") +@SpringBootTest(classes = OpenTelConfiguration.class) +class TestOpenTelemetry { + + @Autowired + ApplicationContext context; + + @Test + void testOpenTelemetry() { + assertThat(context).isNotNull(); + assertTrue(context.containsBean("otlpGrpcSpanExporter")); + assertTrue(context.containsBean("jaegerRemoteSampler")); + assertFalse(context.containsBean("otlpHttpSpanExporter")); + } +} 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 2ee6a152e..21ad2f616 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 @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.runtime.instantiation; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; @@ -32,6 +33,7 @@ import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVIC import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.UUID; import org.junit.jupiter.api.BeforeAll; @@ -42,17 +44,23 @@ 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.AutomationCompositionElement; 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.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AcInstanceStateUpdate; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder; import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.SubOrder; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.AcInstanceStateResolver; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; import org.onap.policy.clamp.models.acm.persistence.provider.ProviderUtils; +import org.onap.policy.clamp.models.acm.utils.AcmUtils; +import org.onap.policy.models.base.PfConceptKey; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.onap.policy.models.tosca.simple.concepts.JpaToscaServiceTemplate; @@ -64,6 +72,7 @@ class AutomationCompositionInstantiationProviderTest { private static final String AC_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/acm/AutomationComposition.json"; private static final String AC_INSTANTIATION_UPDATE_JSON = "src/test/resources/rest/acm/AutomationCompositionUpdate.json"; + private static final String AC_MIGRATE_JSON = "src/test/resources/rest/acm/AutomationCompositionMigrate.json"; private static final String AC_INSTANTIATION_DEFINITION_NAME_NOT_FOUND_JSON = "src/test/resources/rest/acm/AutomationCompositionElementsNotFound.json"; @@ -71,15 +80,17 @@ class AutomationCompositionInstantiationProviderTest { "src/test/resources/rest/acm/AutomationCompositionNotFound.json"; private static final String DELETE_BAD_REQUEST = "Automation composition state is still %s"; - private static final String AC_ELEMENT_NAME_NOT_FOUND = - "\"AutomationComposition\" INVALID, item has status INVALID\n" - + " \"entry PMSHInstance0AcElementNotFound\" INVALID, item has status INVALID\n" - + " \"entry org.onap.domain.pmsh.DCAEMicroservice\" INVALID, Not found\n" - + " \"entry org.onap.domain.pmsh.PMSH_MonitoringPolicyAutomationCompositionElement\"" - + " INVALID, Not found\n"; - private static final String AC_DEFINITION_NOT_FOUND = "\"AutomationComposition\" INVALID, item has status INVALID\n" - + " item \"ServiceTemplate\" value \"%s\" INVALID," - + " Commissioned automation composition definition not found\n"; + private static final String AC_ELEMENT_NAME_NOT_FOUND = """ + "AutomationComposition" INVALID, item has status INVALID + "entry PMSHInstance0AcElementNotFound" INVALID, item has status INVALID + "entry org.onap.domain.pmsh.DCAEMicroservice" INVALID, Not found + "entry org.onap.domain.pmsh.PMSH_MonitoringPolicyAutomationCompositionElement" INVALID, Not found + """; + private static final String AC_DEFINITION_NOT_FOUND = """ + "AutomationComposition" INVALID, item has status INVALID + item "ServiceTemplate" value "%s" INVALID, Commissioned automation composition definition not found + """; + private static final String DO_NOT_MATCH = " do not match with "; private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate(); @@ -169,7 +180,7 @@ class AutomationCompositionInstantiationProviderTest { var supervisionAcHandler = mock(SupervisionAcHandler.class); var participantProvider = mock(ParticipantProvider.class); var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, - null, supervisionAcHandler, participantProvider, + new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, CommonTestData.getTestParamaterGroup()); var instantiationResponse = instantiationProvider.updateAutomationComposition( automationCompositionUpdate.getCompositionId(), automationCompositionUpdate); @@ -200,15 +211,15 @@ class AutomationCompositionInstantiationProviderTest { .thenReturn(automationCompositionUpdate); var instantiationProvider = - new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class), null, - mock(SupervisionAcHandler.class), mock(ParticipantProvider.class), - mock(AcRuntimeParameterGroup.class)); + new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class), + new AcInstanceStateResolver(), mock(SupervisionAcHandler.class), mock(ParticipantProvider.class), + mock(AcRuntimeParameterGroup.class)); var compositionId = automationCompositionUpdate.getCompositionId(); assertThatThrownBy( () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) .hasMessageMatching( - "Not allowed to update in the state " + automationCompositionUpdate.getDeployState()); + "Not allowed to UPDATE in the state " + automationCompositionUpdate.getDeployState()); automationCompositionUpdate.setDeployState(DeployState.UPDATING); automationCompositionUpdate.setLockState(LockState.LOCKED); @@ -216,72 +227,103 @@ class AutomationCompositionInstantiationProviderTest { assertThatThrownBy( () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) .hasMessageMatching( - "Not allowed to migrate in the state " + automationCompositionUpdate.getDeployState()); + "Not allowed to MIGRATE in the state " + automationCompositionUpdate.getDeployState()); } @Test - void testUpdateRestartedBadRequest() { - var automationCompositionUpdate = - InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); - automationCompositionUpdate.setDeployState(DeployState.DEPLOYED); - automationCompositionUpdate.setLockState(LockState.LOCKED); - automationCompositionUpdate.setRestarting(true); + void testMigrationAddRemoveElements() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + var compositionId = acDefinition.getCompositionId(); + when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(acDefinition)); + var instanceId = UUID.randomUUID(); + + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_MIGRATE_JSON, "Crud"); + automationComposition.setCompositionId(compositionId); + automationComposition.setInstanceId(instanceId); + automationComposition.setDeployState(DeployState.DEPLOYED); + automationComposition.setLockState(LockState.LOCKED); var acProvider = mock(AutomationCompositionProvider.class); - when(acProvider.getAutomationComposition(automationCompositionUpdate.getInstanceId())) - .thenReturn(automationCompositionUpdate); + when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) + .thenReturn(automationComposition); - var instantiationProvider = - new AutomationCompositionInstantiationProvider(acProvider, mock(AcDefinitionProvider.class), null, - mock(SupervisionAcHandler.class), mock(ParticipantProvider.class), - mock(AcRuntimeParameterGroup.class)); + var automationCompositionTarget = new AutomationComposition(automationComposition); + automationCompositionTarget.setInstanceId(instanceId); + automationCompositionTarget.setCompositionId(compositionId); + // Add a new element + var uuid = UUID.randomUUID(); + var newElement = new AutomationCompositionElement(); + newElement.setId(uuid); + newElement.setDefinition(new ToscaConceptIdentifier( + "org.onap.domain.pmsh.PMSH_OperationalPolicyAutomationCompositionElement", "1.2.3")); + newElement.setProperties(Map.of("testVar", "1", "testVar2", "2")); + automationCompositionTarget.getElements().put(uuid, newElement); + + //Remove an existing element + var elementIdToRemove = UUID.randomUUID(); + for (var element : automationCompositionTarget.getElements().values()) { + if (element.getDefinition().getName() + .equals("org.onap.domain.database.Http_PMSHMicroserviceAutomationCompositionElement")) { + elementIdToRemove = element.getId(); + } + } + automationCompositionTarget.getElements().remove(elementIdToRemove); - var compositionId = automationCompositionUpdate.getCompositionId(); - assertThatThrownBy( - () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) - .hasMessageMatching("There is a restarting process, Update not allowed"); + var acDefinitionTarget = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + var compositionTargetId = acDefinitionTarget.getCompositionId(); + automationCompositionTarget.setCompositionTargetId(compositionTargetId); + when(acDefinitionProvider.findAcDefinition(compositionTargetId)).thenReturn(Optional.of(acDefinitionTarget)); + when(acDefinitionProvider.getAcDefinition(compositionTargetId)).thenReturn(acDefinitionTarget); + when(acProvider.updateAutomationComposition(any())).thenReturn(automationCompositionTarget); - automationCompositionUpdate.setCompositionTargetId(UUID.randomUUID()); - assertThatThrownBy( - () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) - .hasMessageMatching("There is a restarting process, Migrate not allowed"); + var supervisionAcHandler = mock(SupervisionAcHandler.class); + var participantProvider = mock(ParticipantProvider.class); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, + new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, + new AcRuntimeParameterGroup()); - automationCompositionUpdate.setDeployState(DeployState.UNDEPLOYED); - automationCompositionUpdate.setLockState(LockState.NONE); + automationCompositionTarget.setPrecheck(true); + var preCheckResponse = instantiationProvider.updateAutomationComposition(compositionId, + automationCompositionTarget); + verify(supervisionAcHandler).migratePrecheck(any()); + InstantiationUtils.assertInstantiationResponse(preCheckResponse, automationCompositionTarget); + + automationCompositionTarget.setPrecheck(false); + AcmUtils.setCascadedState(automationComposition, DeployState.DEPLOYED, LockState.LOCKED, + SubState.NONE); + var instantiationResponse = instantiationProvider.updateAutomationComposition(compositionId, + automationCompositionTarget); + + verify(supervisionAcHandler).migrate(any(), any()); + InstantiationUtils.assertInstantiationResponse(instantiationResponse, automationCompositionTarget); - var instanceId = automationCompositionUpdate.getInstanceId(); - assertThatThrownBy(() -> instantiationProvider.deleteAutomationComposition(compositionId, instanceId)) - .hasMessageMatching("There is a restarting process, Delete not allowed"); } @Test - void testUpdateCompositionRestartedBadRequest() { - var acDefinitionProvider = mock(AcDefinitionProvider.class); - var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); - acDefinition.setRestarting(true); - var compositionId = acDefinition.getCompositionId(); - when(acDefinitionProvider.findAcDefinition(compositionId)).thenReturn(Optional.of(acDefinition)); - - var automationCompositionUpdate = - InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); - automationCompositionUpdate.setCompositionId(compositionId); - automationCompositionUpdate.setDeployState(DeployState.DEPLOYED); - automationCompositionUpdate.setLockState(LockState.LOCKED); + void testVersionCompatibility() { var acProvider = mock(AutomationCompositionProvider.class); - when(acProvider.getAutomationComposition(automationCompositionUpdate.getInstanceId())) - .thenReturn(automationCompositionUpdate); - when(acProvider.updateAutomationComposition(automationCompositionUpdate)) - .thenReturn(automationCompositionUpdate); - + var acDefinitionProvider = mock(AcDefinitionProvider.class); var supervisionAcHandler = mock(SupervisionAcHandler.class); var participantProvider = mock(ParticipantProvider.class); + var newDefinition = new PfConceptKey("policy.clamp.element", "1.2.3"); + var oldDefinition = new PfConceptKey("policy.clamp.element", "2.2.3"); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, - null, supervisionAcHandler, participantProvider, - mock(AcRuntimeParameterGroup.class)); - assertThatThrownBy( - () -> instantiationProvider.updateAutomationComposition(compositionId, automationCompositionUpdate)) - .hasMessageMatching("\"AutomationComposition\" INVALID, item has status INVALID\n" - + " item \"ServiceTemplate.restarting\" value \"true\" INVALID," - + " There is a restarting process in composition\n"); + new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, + new AcRuntimeParameterGroup()); + var instanceId = UUID.randomUUID(); + assertDoesNotThrow(() -> { + instantiationProvider.checkCompatibility(newDefinition, oldDefinition, instanceId); + }, "No exception for major version update"); + + // Not compatible + newDefinition.setName("policy.clamp.newElement"); + newDefinition.setVersion("2.2.4"); + + assertThatThrownBy(() -> instantiationProvider + .checkCompatibility(newDefinition, oldDefinition, instanceId)) + .hasMessageContaining("is not compatible"); } @Test @@ -305,7 +347,7 @@ class AutomationCompositionInstantiationProviderTest { var supervisionAcHandler = mock(SupervisionAcHandler.class); var participantProvider = mock(ParticipantProvider.class); var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, - null, supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup()); + new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup()); assertThatThrownBy(() -> instantiationProvider .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition)) @@ -315,6 +357,7 @@ class AutomationCompositionInstantiationProviderTest { var acDefinitionTarget = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); var compositionTargetId = acDefinitionTarget.getCompositionId(); when(acDefinitionProvider.findAcDefinition(compositionTargetId)).thenReturn(Optional.of(acDefinitionTarget)); + when(acDefinitionProvider.getAcDefinition(compositionTargetId)).thenReturn(acDefinitionTarget); automationComposition.setCompositionTargetId(compositionTargetId); @@ -327,6 +370,49 @@ class AutomationCompositionInstantiationProviderTest { } @Test + void testInstantiationMigrationPrecheck() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + 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_UPDATE_JSON, "Crud"); + automationComposition.setCompositionId(compositionId); + automationComposition.setDeployState(DeployState.DEPLOYED); + automationComposition.setLockState(LockState.LOCKED); + automationComposition.setCompositionTargetId(UUID.randomUUID()); + automationComposition.setPrecheck(true); + var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) + .thenReturn(automationComposition); + when(acProvider.updateAutomationComposition(automationComposition)).thenReturn(automationComposition); + + var supervisionAcHandler = mock(SupervisionAcHandler.class); + var acmParticipantProvider = mock(ParticipantProvider.class); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, + new AcInstanceStateResolver(), supervisionAcHandler, acmParticipantProvider, new AcRuntimeParameterGroup()); + + assertThatThrownBy(() -> instantiationProvider + .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition)) + .hasMessageMatching( + String.format(AC_DEFINITION_NOT_FOUND, automationComposition.getCompositionTargetId())); + + var acDefinitionTarget = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + var compositionTargetId = acDefinitionTarget.getCompositionId(); + when(acDefinitionProvider.findAcDefinition(compositionTargetId)).thenReturn(Optional.of(acDefinitionTarget)); + + automationComposition.setCompositionTargetId(compositionTargetId); + + var instantiationResponse = instantiationProvider + .updateAutomationComposition(automationComposition.getCompositionId(), automationComposition); + + verify(supervisionAcHandler).migratePrecheck(any()); + verify(acProvider).updateAutomationComposition(automationComposition); + InstantiationUtils.assertInstantiationResponse(instantiationResponse, automationComposition); + } + + @Test void testMigrateBadRequest() { var acDefinitionProvider = mock(AcDefinitionProvider.class); var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); @@ -349,16 +435,55 @@ class AutomationCompositionInstantiationProviderTest { var acMigrate = new AutomationComposition(automationComposition); acMigrate.setCompositionTargetId(compositionTargetId); - automationComposition.getElements().clear(); + automationComposition.setDeployState(DeployState.DEPLOYING); var supervisionAcHandler = mock(SupervisionAcHandler.class); var participantProvider = mock(ParticipantProvider.class); var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, - null, supervisionAcHandler, participantProvider, new AcRuntimeParameterGroup()); + new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, + new AcRuntimeParameterGroup()); assertThatThrownBy(() -> instantiationProvider .updateAutomationComposition(automationComposition.getCompositionId(), acMigrate)) - .hasMessageStartingWith("Element id not present"); + .hasMessageStartingWith("Not allowed to MIGRATE in the state DEPLOYING"); + } + + @Test + void testMigratePrecheckBadRequest() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + 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_UPDATE_JSON, "Crud"); + automationComposition.setCompositionId(compositionId); + automationComposition.setDeployState(DeployState.DEPLOYED); + automationComposition.setLockState(LockState.LOCKED); + automationComposition.setPrecheck(true); + var acProvider = mock(AutomationCompositionProvider.class); + when(acProvider.getAutomationComposition(automationComposition.getInstanceId())) + .thenReturn(automationComposition); + when(acProvider.updateAutomationComposition(automationComposition)).thenReturn(automationComposition); + + var acDefinitionTarget = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); + var compositionTargetId = acDefinitionTarget.getCompositionId(); + when(acDefinitionProvider.findAcDefinition(compositionTargetId)).thenReturn(Optional.of(acDefinitionTarget)); + + var acMigrate = new AutomationComposition(automationComposition); + acMigrate.setCompositionTargetId(compositionTargetId); + automationComposition.setDeployState(DeployState.DEPLOYING); + automationComposition.setPrecheck(true); + + var supervisionAcHandler = mock(SupervisionAcHandler.class); + var participantProvider = mock(ParticipantProvider.class); + var instantiationProvider = new AutomationCompositionInstantiationProvider(acProvider, acDefinitionProvider, + new AcInstanceStateResolver(), supervisionAcHandler, participantProvider, + new AcRuntimeParameterGroup()); + + assertThatThrownBy(() -> instantiationProvider + .updateAutomationComposition(automationComposition.getCompositionId(), acMigrate)) + .hasMessageStartingWith("Not allowed to NONE in the state DEPLOYING"); } @Test @@ -550,10 +675,14 @@ class AutomationCompositionInstantiationProviderTest { var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); automationComposition.setCompositionId(compositionId); + var message = """ + "AutomationComposition" INVALID, item has status INVALID + item "ServiceTemplate.state" value "COMMISSIONED" INVALID, Commissioned automation composition \ + definition not primed + """; + assertThatThrownBy(() -> provider.createAutomationComposition(compositionId, automationComposition)) - .hasMessageMatching("\"AutomationComposition\" INVALID, item has status INVALID\n" - + " item \"ServiceTemplate.state\" value \"COMMISSIONED\" INVALID," - + " Commissioned automation composition definition not primed\n"); + .hasMessageMatching(message); } @Test @@ -605,5 +734,21 @@ class AutomationCompositionInstantiationProviderTest { acInstanceStateUpdate.setLockOrder(LockOrder.LOCK); provider.compositionInstanceState(compositionId, instanceId, acInstanceStateUpdate); verify(supervisionAcHandler).lock(any(AutomationComposition.class), any(AutomationCompositionDefinition.class)); + + automationComposition.setDeployState(DeployState.UNDEPLOYED); + automationComposition.setLockState(LockState.NONE); + acInstanceStateUpdate.setDeployOrder(DeployOrder.NONE); + acInstanceStateUpdate.setLockOrder(LockOrder.NONE); + acInstanceStateUpdate.setSubOrder(SubOrder.PREPARE); + provider.compositionInstanceState(compositionId, instanceId, acInstanceStateUpdate); + verify(supervisionAcHandler).prepare(any(AutomationComposition.class)); + + automationComposition.setDeployState(DeployState.DEPLOYED); + automationComposition.setLockState(LockState.LOCKED); + acInstanceStateUpdate.setDeployOrder(DeployOrder.NONE); + acInstanceStateUpdate.setLockOrder(LockOrder.NONE); + acInstanceStateUpdate.setSubOrder(SubOrder.REVIEW); + provider.compositionInstanceState(compositionId, instanceId, acInstanceStateUpdate); + verify(supervisionAcHandler).review(any(AutomationComposition.class)); } } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/ActuatorControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/ActuatorControllerTest.java index bdfaedc04..18911f461 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/ActuatorControllerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/ActuatorControllerTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation. + * Copyright (C) 2021-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,84 +20,62 @@ package org.onap.policy.clamp.acm.runtime.main.rest; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.http.MediaType.APPLICATION_JSON; +import static org.springframework.http.MediaType.TEXT_PLAIN; -import jakarta.ws.rs.core.Response; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.autoconfigure.actuate.observability.AutoConfigureObservability; +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.web.reactive.function.client.ExchangeFilterFunctions; -@AutoConfigureObservability(tracing = false) -@ExtendWith(SpringExtension.class) +@AutoConfigureObservability +@AutoConfigureWebTestClient @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -@ActiveProfiles({ "test", "default" }) -class ActuatorControllerTest extends CommonRestController { +@ActiveProfiles("test") +class ActuatorControllerTest { - private static final String HEALTH_ENDPOINT = "health"; - private static final String METRICS_ENDPOINT = "metrics"; - private static final String PROMETHEUS_ENDPOINT = "prometheus"; - private static final String SWAGGER_ENDPOINT = "v3/api-docs"; + @Autowired + WebTestClient webClient; - @LocalServerPort - private int randomServerPort; + @Value("${spring.security.user.name}") + String username; + @Value("${spring.security.user.password}") + String password; @BeforeEach - public void setUpPort() { - super.setHttpPrefix(randomServerPort); - } - - @Test - void testGetHealth_Unauthorized() { - assertUnauthorizedActGet(HEALTH_ENDPOINT); - } - - @Test - void testGetMetrics_Unauthorized() { - assertUnauthorizedActGet(METRICS_ENDPOINT); - } - - @Test - void testGetPrometheus_Unauthorized() { - assertUnauthorizedActGet(PROMETHEUS_ENDPOINT); - } - - @Test - void testGetSwagger_Unauthorized() { - assertUnauthorizedActGet(SWAGGER_ENDPOINT); + void beforeEach() { + var filter = ExchangeFilterFunctions.basicAuthentication(username, password); + webClient = webClient.mutate().filter(filter).build(); } @Test void testGetHealth() { - var invocationBuilder = super.sendActRequest(HEALTH_ENDPOINT); - var rawresp = invocationBuilder.buildGet().invoke(); - assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + webClient.get().uri("/health").accept(APPLICATION_JSON) + .exchange().expectStatus().isOk(); } @Test void testGetMetrics() { - var invocationBuilder = super.sendActRequest(METRICS_ENDPOINT); - var rawresp = invocationBuilder.buildGet().invoke(); - assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + webClient.get().uri("/metrics").accept(APPLICATION_JSON) + .exchange().expectStatus().isOk(); } @Test void testGetPrometheus() { - var invocationBuilder = super.sendActRequest(PROMETHEUS_ENDPOINT); - var rawresp = invocationBuilder.buildGet().invoke(); - assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + webClient.get().uri("/prometheus").accept(TEXT_PLAIN) + .exchange().expectStatus().isOk(); } @Test void testGetSwagger() { - var invocationBuilder = super.sendActRequest(SWAGGER_ENDPOINT); - var rawresp = invocationBuilder.buildGet().invoke(); - assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + webClient.get().uri("/v3/api-docs").accept(APPLICATION_JSON) + .exchange().expectStatus().isOk(); } } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/PrometheusNoAuthTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/PrometheusNoAuthTest.java index 5b94814fb..87e43ea8c 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/PrometheusNoAuthTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/main/rest/PrometheusNoAuthTest.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation. + * Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,39 +20,29 @@ package org.onap.policy.clamp.acm.runtime.main.rest; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.http.MediaType.TEXT_PLAIN; -import jakarta.ws.rs.client.Invocation; -import jakarta.ws.rs.core.Response; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.actuate.observability.AutoConfigureObservability; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.reactive.server.WebTestClient; @AutoConfigureObservability(tracing = false) @ExtendWith(SpringExtension.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles({ "prometheus-noauth", "default" }) -class PrometheusNoAuthTest extends CommonRestController { - private static final String PROMETHEUS_ENDPOINT = "prometheus"; +@ActiveProfiles({"prometheus-noauth", "default"}) +class PrometheusNoAuthTest { - @LocalServerPort - private int randomServerPort; - - @BeforeEach - public void setUpPort() { - super.setHttpPrefix(randomServerPort); - } + @Autowired + WebTestClient webClient; @Test - void testGetPrometheusNoAuth() { - Invocation.Builder invocationBuilder = super.sendNoAuthActRequest(PROMETHEUS_ENDPOINT); - Response rawresp = invocationBuilder.buildGet().invoke(); - assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + void testGetPrometheus() { + webClient.get().uri("/prometheus").accept(TEXT_PLAIN) + .exchange().expectStatus().isOk(); } } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java index 4842a77a8..ca3b9bfab 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java @@ -70,8 +70,8 @@ class ParticipantControllerTest extends CommonRestController { private static final String PARTICIPANT_JSON2 = "src/test/resources/providers/TestParticipant2.json"; private static final List<Participant> inputParticipants = new ArrayList<>(); - private static final String originalJson = ResourceUtils.getResourceAsString(PARTICIPANT_JSON); - private static final String originalJson2 = ResourceUtils.getResourceAsString(PARTICIPANT_JSON2); + private static final String ORIGINAL_JSON = ResourceUtils.getResourceAsString(PARTICIPANT_JSON); + private static final String ORIGINAL_JSON2 = ResourceUtils.getResourceAsString(PARTICIPANT_JSON2); @Autowired private ParticipantProvider participantProvider; @@ -81,8 +81,8 @@ class ParticipantControllerTest extends CommonRestController { */ @BeforeAll public static void setUpBeforeClass() throws CoderException { - inputParticipants.add(CODER.decode(originalJson, Participant.class)); - inputParticipants.add(CODER.decode(originalJson2, Participant.class)); + inputParticipants.add(CODER.decode(ORIGINAL_JSON, Participant.class)); + inputParticipants.add(CODER.decode(ORIGINAL_JSON2, Participant.class)); } @BeforeEach diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java index e895401a4..b104084a8 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionAcHandlerTest.java @@ -36,6 +36,7 @@ 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.comm.AcElementPropertiesPublisher; +import org.onap.policy.clamp.acm.runtime.supervision.comm.AcPreparePublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionDeployPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionMigrationPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionStateChangePublisher; @@ -59,6 +60,68 @@ class SupervisionAcHandlerTest { private static final UUID IDENTIFIER = UUID.randomUUID(); @Test + void testAutomationCompositionDeployAckNull() { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), + mock(AutomationCompositionDeployPublisher.class), mock(AutomationCompositionStateChangePublisher.class), + mock(AcElementPropertiesPublisher.class), null, + mock(ParticipantSyncPublisher.class), null); + + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); + automationComposition.setInstanceId(IDENTIFIER); + var automationCompositionAckMessage = + getAutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK, + automationComposition, DeployState.DEPLOYED, LockState.UNLOCKED); + automationCompositionAckMessage.setStateChangeResult(null); + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + automationCompositionAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); + automationCompositionAckMessage.setAutomationCompositionId(null); + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + automationCompositionAckMessage.setAutomationCompositionId(automationComposition.getInstanceId()); + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + automationCompositionAckMessage = + getAutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK, + automationComposition, DeployState.DEPLOYING, LockState.UNLOCKED); + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + verify(automationCompositionProvider, times(0)).updateAutomationCompositionElement(any()); + } + + @Test + void testHandleAcMigrationWithStage() { + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); + automationComposition.setInstanceId(IDENTIFIER); + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + when(automationCompositionProvider.findAutomationComposition(IDENTIFIER)) + .thenReturn(Optional.of(automationComposition)); + when(automationCompositionProvider.updateAcState(any(AutomationComposition.class))) + .thenReturn(automationComposition); + + var acDefinitionProvider = mock(AcDefinitionProvider.class); + when(acDefinitionProvider.getAcDefinition(automationComposition.getCompositionId())) + .thenReturn(new AutomationCompositionDefinition()); + + var handler = new SupervisionAcHandler(automationCompositionProvider, acDefinitionProvider, + mock(AutomationCompositionDeployPublisher.class), mock(AutomationCompositionStateChangePublisher.class), + mock(AcElementPropertiesPublisher.class), null, + mock(ParticipantSyncPublisher.class), null); + + var automationCompositionAckMessage = + getAutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK, + automationComposition, DeployState.MIGRATING, LockState.LOCKED); + automationCompositionAckMessage.setStage(1); + handler.handleAutomationCompositionStateChangeAckMessage(automationCompositionAckMessage); + + verify(automationCompositionProvider, times(3)) + .updateAutomationCompositionElement(any(AutomationCompositionElement.class)); + } + + @Test void testHandleAutomationCompositionStateChangeAckMessage() { var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); @@ -76,7 +139,7 @@ class SupervisionAcHandlerTest { var handler = new SupervisionAcHandler(automationCompositionProvider, acDefinitionProvider, mock(AutomationCompositionDeployPublisher.class), mock(AutomationCompositionStateChangePublisher.class), mock(AcElementPropertiesPublisher.class), null, - mock(ParticipantSyncPublisher.class)); + mock(ParticipantSyncPublisher.class), null); var automationCompositionAckMessage = getAutomationCompositionDeployAck(ParticipantMessageType.AUTOMATION_COMPOSITION_STATECHANGE_ACK, @@ -124,7 +187,7 @@ class SupervisionAcHandlerTest { var handler = new SupervisionAcHandler(automationCompositionProvider, acDefinitionProvider, mock(AutomationCompositionDeployPublisher.class), mock(AutomationCompositionStateChangePublisher.class), mock(AcElementPropertiesPublisher.class), null, - mock(ParticipantSyncPublisher.class)); + mock(ParticipantSyncPublisher.class), null); handler.handleAutomationCompositionUpdateAckMessage(automationCompositionAckMessage); @@ -161,7 +224,7 @@ class SupervisionAcHandlerTest { var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), mock(AutomationCompositionDeployPublisher.class), automationCompositionStateChangePublisher, null, - null, mock(ParticipantSyncPublisher.class)); + null, mock(ParticipantSyncPublisher.class), null); handler.handleAutomationCompositionUpdateAckMessage(automationCompositionAckMessage); @@ -175,7 +238,8 @@ class SupervisionAcHandlerTest { var automationCompositionProvider = mock(AutomationCompositionProvider.class); var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), automationCompositionDeployPublisher, mock(AutomationCompositionStateChangePublisher.class), - mock(AcElementPropertiesPublisher.class), null, mock(ParticipantSyncPublisher.class)); + mock(AcElementPropertiesPublisher.class), null, + mock(ParticipantSyncPublisher.class), null); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); @@ -195,7 +259,7 @@ class SupervisionAcHandlerTest { var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), mock(AutomationCompositionDeployPublisher.class), acStateChangePublisher, mock(AcElementPropertiesPublisher.class), null, - mock(ParticipantSyncPublisher.class)); + mock(ParticipantSyncPublisher.class), null); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); var automationComposition = @@ -213,7 +277,7 @@ class SupervisionAcHandlerTest { var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), mock(AutomationCompositionDeployPublisher.class), acStateChangePublisher, mock(AcElementPropertiesPublisher.class), null, - mock(ParticipantSyncPublisher.class)); + mock(ParticipantSyncPublisher.class), null); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); @@ -234,7 +298,7 @@ class SupervisionAcHandlerTest { var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), mock(AutomationCompositionDeployPublisher.class), acStateChangePublisher, mock(AcElementPropertiesPublisher.class), null, - mock(ParticipantSyncPublisher.class)); + mock(ParticipantSyncPublisher.class), null); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); var automationComposition = @@ -252,7 +316,7 @@ class SupervisionAcHandlerTest { var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), mock(AutomationCompositionDeployPublisher.class), acStateChangePublisher, mock(AcElementPropertiesPublisher.class), null, - mock(ParticipantSyncPublisher.class)); + mock(ParticipantSyncPublisher.class), null); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); var automationComposition = @@ -272,7 +336,7 @@ class SupervisionAcHandlerTest { var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), mock(AutomationCompositionDeployPublisher.class), acStateChangePublisher, mock(AcElementPropertiesPublisher.class), null, - mock(ParticipantSyncPublisher.class)); + mock(ParticipantSyncPublisher.class), null); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); var automationComposition = @@ -290,7 +354,7 @@ class SupervisionAcHandlerTest { var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), mock(AutomationCompositionDeployPublisher.class), acStateChangePublisher, mock(AcElementPropertiesPublisher.class), null, - mock(ParticipantSyncPublisher.class)); + mock(ParticipantSyncPublisher.class), null); var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); var acDefinition = CommonTestData.createAcDefinition(serviceTemplate, AcTypeState.PRIMED); var automationComposition = @@ -317,11 +381,12 @@ class SupervisionAcHandlerTest { automationCompositionAckMessage .setParticipantId(automationComposition.getElements().values().iterator().next().getParticipantId()); automationCompositionAckMessage.setAutomationCompositionId(IDENTIFIER); + automationCompositionAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), mock(AutomationCompositionDeployPublisher.class), mock(AutomationCompositionStateChangePublisher.class), mock(AcElementPropertiesPublisher.class), null, - mock(ParticipantSyncPublisher.class)); + mock(ParticipantSyncPublisher.class), null); handler.handleAutomationCompositionUpdateAckMessage(automationCompositionAckMessage); @@ -335,7 +400,7 @@ class SupervisionAcHandlerTest { var handler = new SupervisionAcHandler(mock(AutomationCompositionProvider.class), mock(AcDefinitionProvider.class), mock(AutomationCompositionDeployPublisher.class), mock(AutomationCompositionStateChangePublisher.class), acElementPropertiesPublisher, null, - mock(ParticipantSyncPublisher.class)); + mock(ParticipantSyncPublisher.class), null); var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Lock"); handler.update(automationComposition); @@ -348,10 +413,47 @@ class SupervisionAcHandlerTest { var acCompositionMigrationPublisher = mock(AutomationCompositionMigrationPublisher.class); var handler = new SupervisionAcHandler(automationCompositionProvider, mock(AcDefinitionProvider.class), null, null, null, - acCompositionMigrationPublisher, mock(ParticipantSyncPublisher.class)); + acCompositionMigrationPublisher, mock(ParticipantSyncPublisher.class), null); + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Migrate"); + var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); + handler.migrate(automationComposition, serviceTemplate); + verify(acCompositionMigrationPublisher, timeout(1000)).send(any(AutomationComposition.class), anyInt()); + } + + @Test + void testMigratePrecheck() { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var acCompositionMigrationPublisher = mock(AutomationCompositionMigrationPublisher.class); + var handler = new SupervisionAcHandler(automationCompositionProvider, null, null, null, + null, acCompositionMigrationPublisher, null, null); + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Migrate"); + handler.migratePrecheck(automationComposition); + verify(acCompositionMigrationPublisher, timeout(1000)).send(any(AutomationComposition.class), anyInt()); + } + + @Test + void testPrepare() { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var acPreparePublisher = mock(AcPreparePublisher.class); + var handler = new SupervisionAcHandler(automationCompositionProvider, null, null, null, + null, null, null, acPreparePublisher); + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Migrate"); + handler.prepare(automationComposition); + verify(acPreparePublisher, timeout(1000)).sendPrepare(any(AutomationComposition.class)); + } + + @Test + void testReview() { + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + var acPreparePublisher = mock(AcPreparePublisher.class); + var handler = new SupervisionAcHandler(automationCompositionProvider, null, null, null, + null, null, null, acPreparePublisher); var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Migrate"); - handler.migrate(automationComposition, UUID.randomUUID()); - verify(acCompositionMigrationPublisher, timeout(1000)).send(any(AutomationComposition.class), any()); + handler.review(automationComposition); + verify(acPreparePublisher, timeout(1000)).sendRevew(any(AutomationComposition.class)); } } 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 e8be3b6b7..09a79d890 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 @@ -28,12 +28,12 @@ import static org.mockito.Mockito.when; import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML; import java.util.Optional; +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.comm.ParticipantSyncPublisher; 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.ParticipantState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; import org.onap.policy.clamp.models.acm.messages.kafka.participant.ParticipantPrimeAck; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; @@ -41,22 +41,55 @@ import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvide class SupervisionHandlerTest { @Test + void testParticipantPrimeAckNull() { + var acDefinitionProvider = mock(AcDefinitionProvider.class); + var handler = new SupervisionHandler(acDefinitionProvider, mock(ParticipantSyncPublisher.class)); + + var participantPrimeAckMessage = new ParticipantPrimeAck(); + participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); + handler.handleParticipantMessage(participantPrimeAckMessage); + + participantPrimeAckMessage.setCompositionId(UUID.randomUUID()); + handler.handleParticipantMessage(participantPrimeAckMessage); + + participantPrimeAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); + handler.handleParticipantMessage(participantPrimeAckMessage); + + participantPrimeAckMessage.setStateChangeResult(null); + participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED); + handler.handleParticipantMessage(participantPrimeAckMessage); + + participantPrimeAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); + participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMING); + handler.handleParticipantMessage(participantPrimeAckMessage); + + participantPrimeAckMessage.setCompositionState(AcTypeState.DEPRIMING); + handler.handleParticipantMessage(participantPrimeAckMessage); + + verify(acDefinitionProvider, times(0)).findAcDefinition(any()); + verify(acDefinitionProvider, times(0)).updateAcDefinitionElement(any(), any()); + } + + @Test void testParticipantPrimeAckNotFound() { var participantPrimeAckMessage = new ParticipantPrimeAck(); participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); - participantPrimeAckMessage.setState(ParticipantState.ON_LINE); + participantPrimeAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); + participantPrimeAckMessage.setCompositionId(UUID.randomUUID()); + participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED); var acDefinitionProvider = mock(AcDefinitionProvider.class); var handler = new SupervisionHandler(acDefinitionProvider, mock(ParticipantSyncPublisher.class)); - handler.handleParticipantMessage(participantPrimeAckMessage); - verify(acDefinitionProvider).findAcDefinition(any()); + verify(acDefinitionProvider).findAcDefinition(participantPrimeAckMessage.getCompositionId()); + verify(acDefinitionProvider, times(0)).updateAcDefinitionElement(any(), any()); } @Test void testParticipantPrimeAckPrimed() { var participantPrimeAckMessage = new ParticipantPrimeAck(); participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); - participantPrimeAckMessage.setState(ParticipantState.ON_LINE); + participantPrimeAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); + participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED); var acDefinition = CommonTestData.createAcDefinition( InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMED); @@ -76,7 +109,7 @@ class SupervisionHandlerTest { var participantPrimeAckMessage = new ParticipantPrimeAck(); participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED); - participantPrimeAckMessage.setState(ParticipantState.ON_LINE); + participantPrimeAckMessage.setStateChangeResult(StateChangeResult.NO_ERROR); var acDefinition = CommonTestData.createAcDefinition( InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMING); @@ -97,14 +130,14 @@ class SupervisionHandlerTest { verify(acDefinitionProvider, times(acDefinition.getElementStateMap().size())) .updateAcDefinitionElement(any(), any()); verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), AcTypeState.PRIMED, - StateChangeResult.NO_ERROR, null); + StateChangeResult.NO_ERROR); } @Test void testParticipantPrimeAckFailed() { var participantPrimeAckMessage = new ParticipantPrimeAck(); participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); - participantPrimeAckMessage.setState(ParticipantState.ON_LINE); + participantPrimeAckMessage.setCompositionState(AcTypeState.COMMISSIONED); participantPrimeAckMessage.setStateChangeResult(StateChangeResult.FAILED); var acDefinition = CommonTestData.createAcDefinition( @@ -123,37 +156,6 @@ class SupervisionHandlerTest { verify(acDefinitionProvider).findAcDefinition(any()); verify(acDefinitionProvider).updateAcDefinitionElement(any(), any()); verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), AcTypeState.PRIMING, - StateChangeResult.FAILED, null); - } - - @Test - void testParticipantPrimeAckRestarted() { - var participantPrimeAckMessage = new ParticipantPrimeAck(); - participantPrimeAckMessage.setParticipantId(CommonTestData.getParticipantId()); - participantPrimeAckMessage.setCompositionState(AcTypeState.PRIMED); - participantPrimeAckMessage.setState(ParticipantState.ON_LINE); - - var acDefinition = CommonTestData.createAcDefinition( - InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML), AcTypeState.PRIMED); - acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT); - acDefinition.setRestarting(true); - participantPrimeAckMessage.setCompositionId(acDefinition.getCompositionId()); - for (var element : acDefinition.getElementStateMap().values()) { - element.setParticipantId(CommonTestData.getParticipantId()); - element.setRestarting(true); - } - - var acDefinitionProvider = mock(AcDefinitionProvider.class); - when(acDefinitionProvider.findAcDefinition(acDefinition.getCompositionId())) - .thenReturn(Optional.of(acDefinition)); - - var handler = new SupervisionHandler(acDefinitionProvider, mock(ParticipantSyncPublisher.class)); - - handler.handleParticipantMessage(participantPrimeAckMessage); - verify(acDefinitionProvider).findAcDefinition(any()); - verify(acDefinitionProvider, times(acDefinition.getElementStateMap().size())) - .updateAcDefinitionElement(any(), any()); - verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), AcTypeState.PRIMED, - StateChangeResult.NO_ERROR, null); + StateChangeResult.FAILED); } } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java index 932529d79..aab1a1ceb 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java @@ -37,7 +37,6 @@ import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; import org.onap.policy.clamp.acm.runtime.main.parameters.AcRuntimeParameterGroup; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantDeregisterAckPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantRegisterAckPublisher; -import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantRestartPublisher; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher; import org.onap.policy.clamp.acm.runtime.util.CommonTestData; import org.onap.policy.clamp.models.acm.concepts.AcTypeState; @@ -77,8 +76,8 @@ class SupervisionParticipantHandlerTest { var handler = new SupervisionParticipantHandler(participantProvider, mock(ParticipantRegisterAckPublisher.class), participantDeregisterAckPublisher, mock(AutomationCompositionProvider.class), - mock(AcDefinitionProvider.class), mock(ParticipantRestartPublisher.class), - mock(ParticipantSyncPublisher.class), mock(AcRuntimeParameterGroup.class)); + mock(AcDefinitionProvider.class), mock(ParticipantSyncPublisher.class), + mock(AcRuntimeParameterGroup.class)); handler.handleParticipantMessage(participantDeregisterMessage); @@ -98,8 +97,8 @@ class SupervisionParticipantHandlerTest { var participantRegisterAckPublisher = mock(ParticipantRegisterAckPublisher.class); var handler = new SupervisionParticipantHandler(participantProvider, participantRegisterAckPublisher, mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionProvider.class), - mock(AcDefinitionProvider.class), mock(ParticipantRestartPublisher.class), - mock(ParticipantSyncPublisher.class), mock(AcRuntimeParameterGroup.class)); + mock(AcDefinitionProvider.class), mock(ParticipantSyncPublisher.class), + mock(AcRuntimeParameterGroup.class)); handler.handleParticipantMessage(participantRegisterMessage); verify(participantProvider).saveParticipant(any()); @@ -108,64 +107,6 @@ class SupervisionParticipantHandlerTest { } @Test - void testHandleParticipantRestart() { - var participantRegisterMessage = new ParticipantRegister(); - participantRegisterMessage.setMessageId(UUID.randomUUID()); - var participantId = CommonTestData.getParticipantId(); - participantRegisterMessage.setParticipantId(participantId); - participantRegisterMessage.setReplicaId(participantId); - var supportedElementType = CommonTestData.createParticipantSupportedElementType(); - participantRegisterMessage.setParticipantSupportedElementType(List.of(supportedElementType)); - - var participant = new Participant(); - var replica = new ParticipantReplica(); - replica.setReplicaId(participantId); - participant.setParticipantId(participantId); - participant.getReplicas().put(replica.getReplicaId(), replica); - var participantProvider = mock(ParticipantProvider.class); - when(participantProvider.findParticipant(participantId)).thenReturn(Optional.of(participant)); - when(participantProvider.findParticipantReplica(participantId)).thenReturn(Optional.of(replica)); - var compositionId = UUID.randomUUID(); - var composition2Id = UUID.randomUUID(); - when(participantProvider.getCompositionIds(participantId)).thenReturn(Set.of(compositionId, composition2Id)); - - var acDefinitionProvider = mock(AcDefinitionProvider.class); - var acDefinition = new AutomationCompositionDefinition(); - acDefinition.setState(AcTypeState.COMMISSIONED); - acDefinition.setCompositionId(composition2Id); - when(acDefinitionProvider.getAcDefinition(composition2Id)).thenReturn(acDefinition); - - acDefinition = new AutomationCompositionDefinition(); - acDefinition.setCompositionId(compositionId); - acDefinition.setState(AcTypeState.PRIMED); - var nodeTemplateState = new NodeTemplateState(); - nodeTemplateState.setParticipantId(participantId); - acDefinition.setElementStateMap(Map.of("code", nodeTemplateState)); - when(acDefinitionProvider.getAcDefinition(compositionId)).thenReturn(acDefinition); - - var automationComposition = - InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Crud"); - automationComposition.getElements().values().iterator().next().setParticipantId(participantId); - var automationCompositionProvider = mock(AutomationCompositionProvider.class); - when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId)) - .thenReturn(List.of(automationComposition)); - - var participantRegisterAckPublisher = mock(ParticipantRegisterAckPublisher.class); - var participantRestartPublisher = mock(ParticipantRestartPublisher.class); - var handler = new SupervisionParticipantHandler(participantProvider, participantRegisterAckPublisher, - mock(ParticipantDeregisterAckPublisher.class), automationCompositionProvider, acDefinitionProvider, - participantRestartPublisher, mock(ParticipantSyncPublisher.class), - CommonTestData.getTestParamaterGroup()); - handler.handleParticipantMessage(participantRegisterMessage); - - verify(participantRegisterAckPublisher) - .send(participantRegisterMessage.getMessageId(), participantId, participantId); - verify(acDefinitionProvider).updateAcDefinition(any(AutomationCompositionDefinition.class), - eq(CommonTestData.TOSCA_COMP_NAME)); - verify(participantRestartPublisher).send(any(), any(AutomationCompositionDefinition.class), any()); - } - - @Test void testHandleParticipantSyncRestart() { var participantRegisterMessage = new ParticipantRegister(); participantRegisterMessage.setMessageId(UUID.randomUUID()); @@ -213,8 +154,7 @@ class SupervisionParticipantHandlerTest { var participantSyncPublisher = mock(ParticipantSyncPublisher.class); var handler = new SupervisionParticipantHandler(participantProvider, participantRegisterAckPublisher, mock(ParticipantDeregisterAckPublisher.class), automationCompositionProvider, acDefinitionProvider, - mock(ParticipantRestartPublisher.class), participantSyncPublisher, - CommonTestData.getTestParamaterGroup()); + participantSyncPublisher, CommonTestData.getTestParamaterGroup()); handler.handleParticipantMessage(participantRegisterMessage); verify(participantRegisterAckPublisher) @@ -235,8 +175,8 @@ class SupervisionParticipantHandlerTest { var handler = new SupervisionParticipantHandler(participantProvider, mock(ParticipantRegisterAckPublisher.class), mock(ParticipantDeregisterAckPublisher.class), automationCompositionProvider, - mock(AcDefinitionProvider.class), mock(ParticipantRestartPublisher.class), - mock(ParticipantSyncPublisher.class), mock(AcRuntimeParameterGroup.class)); + mock(AcDefinitionProvider.class), mock(ParticipantSyncPublisher.class), + mock(AcRuntimeParameterGroup.class)); var participant = CommonTestData.createParticipant(CommonTestData.getParticipantId()); when(participantProvider.findParticipant(CommonTestData.getParticipantId())) .thenReturn(Optional.of(participant)); @@ -271,8 +211,8 @@ class SupervisionParticipantHandlerTest { var handler = new SupervisionParticipantHandler(participantProvider, mock(ParticipantRegisterAckPublisher.class), mock(ParticipantDeregisterAckPublisher.class), mock(AutomationCompositionProvider.class), - acDefinitionProvider, mock(ParticipantRestartPublisher.class), - mock(ParticipantSyncPublisher.class), CommonTestData.getTestParamaterGroup()); + acDefinitionProvider, mock(ParticipantSyncPublisher.class), + CommonTestData.getTestParamaterGroup()); handler.handleParticipantMessage(participantStatusMessage); verify(acDefinitionProvider).updateAcDefinition(acDefinition, CommonTestData.TOSCA_COMP_NAME); @@ -288,8 +228,8 @@ class SupervisionParticipantHandlerTest { var handler = new SupervisionParticipantHandler(participantProvider, mock(ParticipantRegisterAckPublisher.class), mock(ParticipantDeregisterAckPublisher.class), automationCompositionProvider, - mock(AcDefinitionProvider.class), mock(ParticipantRestartPublisher.class), - mock(ParticipantSyncPublisher.class), mock(AcRuntimeParameterGroup.class)); + mock(AcDefinitionProvider.class), mock(ParticipantSyncPublisher.class), + mock(AcRuntimeParameterGroup.class)); handler.handleParticipantMessage(participantStatusMessage); verify(participantProvider).saveParticipant(any()); @@ -306,8 +246,8 @@ class SupervisionParticipantHandlerTest { var handler = new SupervisionParticipantHandler(participantProvider, mock(ParticipantRegisterAckPublisher.class), mock(ParticipantDeregisterAckPublisher.class), automationCompositionProvider, - mock(AcDefinitionProvider.class), mock(ParticipantRestartPublisher.class), - mock(ParticipantSyncPublisher.class), mock(AcRuntimeParameterGroup.class)); + mock(AcDefinitionProvider.class), mock(ParticipantSyncPublisher.class), + mock(AcRuntimeParameterGroup.class)); var participant = CommonTestData.createParticipant(CommonTestData.getParticipantId()); when(participantProvider.findParticipant(CommonTestData.getParticipantId())) .thenReturn(Optional.of(participant)); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java index 6bdab706c..5cefd5f09 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; +import java.util.function.Consumer; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils; import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionDeployPublisher; @@ -49,6 +50,7 @@ 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.concepts.NodeTemplateState; import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.clamp.models.acm.concepts.SubState; import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider; import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider; import org.onap.policy.clamp.models.acm.utils.TimestampHelper; @@ -57,6 +59,8 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; class SupervisionScannerTest { private static final String AC_JSON = "src/test/resources/rest/acm/AutomationCompositionSmoke.json"; + private static final String ELEMENT_NAME = + "org.onap.domain.database.Http_PMSHMicroserviceAutomationCompositionElement"; private static final UUID compositionId = UUID.randomUUID(); @@ -102,9 +106,9 @@ class SupervisionScannerTest { var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); var supervisionScanner = new SupervisionScanner(mock(AutomationCompositionProvider.class), acDefinitionProvider, mock(AutomationCompositionStateChangePublisher.class), mock(AutomationCompositionDeployPublisher.class), - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); supervisionScanner.run(); - verify(acDefinitionProvider, times(0)).updateAcDefinitionState(any(), any(), any(), any()); + verify(acDefinitionProvider, times(0)).updateAcDefinitionState(any(), any(), any()); } @Test @@ -114,25 +118,25 @@ class SupervisionScannerTest { var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); var supervisionScanner = new SupervisionScanner(mock(AutomationCompositionProvider.class), acDefinitionProvider, mock(AutomationCompositionStateChangePublisher.class), mock(AutomationCompositionDeployPublisher.class), - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); supervisionScanner.run(); // Ac Definition in Priming state - verify(acDefinitionProvider, times(0)).updateAcDefinitionState(any(), any(), any(), any()); + verify(acDefinitionProvider, times(0)).updateAcDefinitionState(any(), any(), any()); acRuntimeParameterGroup.getParticipantParameters().setMaxStatusWaitMs(-1); supervisionScanner = new SupervisionScanner(mock(AutomationCompositionProvider.class), acDefinitionProvider, mock(AutomationCompositionStateChangePublisher.class), mock(AutomationCompositionDeployPublisher.class), - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); supervisionScanner.run(); // set Timeout verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), acDefinition.getState(), - StateChangeResult.TIMEOUT, null); + StateChangeResult.TIMEOUT); clearInvocations(acDefinitionProvider); acDefinition.setStateChangeResult(StateChangeResult.TIMEOUT); supervisionScanner.run(); // already in Timeout - verify(acDefinitionProvider, times(0)).updateAcDefinitionState(any(), any(), any(), any()); + verify(acDefinitionProvider, times(0)).updateAcDefinitionState(any(), any(), any()); clearInvocations(acDefinitionProvider); // retry by the user @@ -140,7 +144,7 @@ class SupervisionScannerTest { supervisionScanner.run(); // set Timeout verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), acDefinition.getState(), - StateChangeResult.TIMEOUT, null); + StateChangeResult.TIMEOUT); clearInvocations(acDefinitionProvider); for (var element : acDefinition.getElementStateMap().values()) { @@ -149,7 +153,7 @@ class SupervisionScannerTest { supervisionScanner.run(); // completed verify(acDefinitionProvider).updateAcDefinitionState(acDefinition.getCompositionId(), AcTypeState.PRIMED, - StateChangeResult.NO_ERROR, null); + StateChangeResult.NO_ERROR); } @Test @@ -165,7 +169,7 @@ class SupervisionScannerTest { var supervisionScanner = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(), automationCompositionStateChangePublisher, automationCompositionDeployPublisher, - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); // not in transition supervisionScanner.run(); @@ -194,7 +198,7 @@ class SupervisionScannerTest { var supervisionScanner = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(), automationCompositionStateChangePublisher, automationCompositionDeployPublisher, - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); supervisionScanner.run(); verify(automationCompositionProvider).updateAcState(any(AutomationComposition.class)); @@ -215,7 +219,7 @@ class SupervisionScannerTest { var supervisionScanner = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(), automationCompositionStateChangePublisher, automationCompositionDeployPublisher, - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); supervisionScanner.run(); verify(automationCompositionProvider).deleteAutomationComposition(automationComposition.getInstanceId()); @@ -234,7 +238,7 @@ class SupervisionScannerTest { var supervisionScanner = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(), automationCompositionStateChangePublisher, automationCompositionDeployPublisher, - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); supervisionScanner.run(); verify(automationCompositionProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class)); @@ -265,12 +269,12 @@ class SupervisionScannerTest { // verify timeout scenario var scannerObj2 = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(), automationCompositionStateChangePublisher, automationCompositionDeployPublisher, - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); automationComposition.setStateChangeResult(StateChangeResult.NO_ERROR); automationComposition.setLastMsg(TimestampHelper.now()); scannerObj2.run(); - verify(automationCompositionProvider, times(1)).updateAutomationComposition(any(AutomationComposition.class)); + verify(automationCompositionProvider, times(1)).updateAcState(any(AutomationComposition.class)); assertEquals(StateChangeResult.TIMEOUT, automationComposition.getStateChangeResult()); //already in TIMEOUT @@ -295,8 +299,7 @@ class SupervisionScannerTest { automationComposition.setPhase(0); automationComposition.setCompositionId(compositionId); for (var element : automationComposition.getElements().values()) { - if ("org.onap.domain.database.Http_PMSHMicroserviceAutomationCompositionElement" - .equals(element.getDefinition().getName())) { + if (ELEMENT_NAME.equals(element.getDefinition().getName())) { element.setDeployState(DeployState.DEPLOYING); element.setLockState(LockState.NONE); } else { @@ -314,7 +317,7 @@ class SupervisionScannerTest { var supervisionScanner = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(), automationCompositionStateChangePublisher, automationCompositionDeployPublisher, - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); supervisionScanner.run(); @@ -348,9 +351,14 @@ class SupervisionScannerTest { var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); - var supervisionScanner = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(), + var definitionTarget = createAutomationCompositionDefinition(AcTypeState.PRIMED, StateChangeResult.NO_ERROR); + definitionTarget.setCompositionId(compositionTargetId); + var acDefinitionProvider = createAcDefinitionProvider(); + when(acDefinitionProvider.getAcDefinition(compositionTargetId)).thenReturn(definitionTarget); + + var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider, automationCompositionStateChangePublisher, automationCompositionDeployPublisher, - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); supervisionScanner.run(); verify(automationCompositionProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class)); @@ -367,6 +375,93 @@ class SupervisionScannerTest { } @Test + void testSendAutomationCompositionUpdate() { + var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud"); + automationComposition.setLockState(LockState.LOCKED); + automationComposition.setDeployState(DeployState.UPDATING); + for (var element : automationComposition.getElements().values()) { + element.setSubState(SubState.NONE); + element.setLockState(LockState.LOCKED); + if (ELEMENT_NAME.equals(element.getDefinition().getName())) { + element.setDeployState(DeployState.UPDATING); + } else { + element.setDeployState(DeployState.DEPLOYED); + } + } + testSimpleScan(automationComposition, element -> element.setDeployState(DeployState.DEPLOYED)); + } + + @Test + void testSendAutomationCompositionMigratingPrecheck() { + var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud"); + automationComposition.setLockState(LockState.LOCKED); + automationComposition.setDeployState(DeployState.DEPLOYED); + automationComposition.setSubState(SubState.MIGRATION_PRECHECKING); + for (var element : automationComposition.getElements().values()) { + element.setDeployState(DeployState.DEPLOYED); + element.setSubState(SubState.NONE); + element.setLockState(LockState.LOCKED); + if (ELEMENT_NAME.equals(element.getDefinition().getName())) { + element.setSubState(SubState.MIGRATION_PRECHECKING); + } + } + testSimpleScan(automationComposition, element -> element.setSubState(SubState.NONE)); + } + + @Test + void testSendAutomationCompositionPrepare() { + var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud"); + automationComposition.setLockState(LockState.NONE); + automationComposition.setDeployState(DeployState.UNDEPLOYED); + automationComposition.setSubState(SubState.PREPARING); + for (var element : automationComposition.getElements().values()) { + element.setDeployState(DeployState.UNDEPLOYED); + element.setSubState(SubState.NONE); + element.setLockState(LockState.NONE); + if (ELEMENT_NAME.equals(element.getDefinition().getName())) { + element.setSubState(SubState.PREPARING); + } + } + testSimpleScan(automationComposition, element -> element.setSubState(SubState.NONE)); + } + + @Test + void testSendAutomationCompositionReview() { + var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud"); + automationComposition.setLockState(LockState.LOCKED); + automationComposition.setDeployState(DeployState.DEPLOYED); + automationComposition.setSubState(SubState.REVIEWING); + for (var element : automationComposition.getElements().values()) { + element.setDeployState(DeployState.DEPLOYED); + element.setSubState(SubState.NONE); + element.setLockState(LockState.LOCKED); + if (ELEMENT_NAME.equals(element.getDefinition().getName())) { + element.setSubState(SubState.REVIEWING); + } + } + testSimpleScan(automationComposition, element -> element.setSubState(SubState.NONE)); + } + + private void testSimpleScan(AutomationComposition automationComposition, Consumer<AutomationCompositionElement> c) { + automationComposition.setLockState(LockState.NONE); + automationComposition.setCompositionId(compositionId); + automationComposition.setLastMsg(TimestampHelper.now()); + var automationCompositionProvider = mock(AutomationCompositionProvider.class); + when(automationCompositionProvider.getAcInstancesInTransition()).thenReturn(List.of(automationComposition)); + + var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); + var supervisionScanner = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(), + null, null, + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); + supervisionScanner.run(); + verify(automationCompositionProvider, times(0)).updateAcState(any()); + + automationComposition.getElements().values().forEach(c); + supervisionScanner.run(); + verify(automationCompositionProvider).updateAcState(any()); + } + + @Test void testSendAutomationCompositionMsgUnlocking() { var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud"); automationComposition.setDeployState(DeployState.DEPLOYED); @@ -374,8 +469,7 @@ class SupervisionScannerTest { automationComposition.setCompositionId(compositionId); automationComposition.setPhase(0); for (var element : automationComposition.getElements().values()) { - if ("org.onap.domain.database.Http_PMSHMicroserviceAutomationCompositionElement" - .equals(element.getDefinition().getName())) { + if (ELEMENT_NAME.equals(element.getDefinition().getName())) { element.setDeployState(DeployState.DEPLOYED); element.setLockState(LockState.UNLOCKING); } else { @@ -393,7 +487,7 @@ class SupervisionScannerTest { var supervisionScanner = new SupervisionScanner(automationCompositionProvider, createAcDefinitionProvider(), automationCompositionStateChangePublisher, automationCompositionDeployPublisher, - mock(ParticipantSyncPublisher.class), acRuntimeParameterGroup); + mock(ParticipantSyncPublisher.class), null, acRuntimeParameterGroup); supervisionScanner.run(); 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 7cf0bf84f..a1ef9b4e2 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 @@ -231,31 +231,29 @@ class SupervisionMessagesTest { publisher.active(topicSink); var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); - publisher.send(automationComposition, UUID.randomUUID()); + publisher.send(automationComposition, 0); verify(topicSink).send(anyString()); } @Test - void testParticipantRestartPublisher() { - var publisher = new ParticipantRestartPublisher(CommonTestData.getTestParamaterGroup()); + void testAcPreparePublisher() { + var publisher = new AcPreparePublisher(); var topicSink = mock(TopicSink.class); publisher.active(topicSink); - - var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML); - var acmDefinition = new AutomationCompositionDefinition(); - acmDefinition.setCompositionId(UUID.randomUUID()); - acmDefinition.setServiceTemplate(serviceTemplate); - var acElements = AcmUtils - .extractAcElementsFromServiceTemplate(serviceTemplate, ""); - acmDefinition.setElementStateMap(AcmUtils.createElementStateMap(acElements, AcTypeState.PRIMED)); - var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); + publisher.sendPrepare(automationComposition); + verify(topicSink).send(anyString()); + } - var participantId = automationComposition.getElements().values().iterator().next().getParticipantId(); - acmDefinition.getElementStateMap().values().iterator().next().setParticipantId(participantId); - - publisher.send(participantId, acmDefinition, List.of(automationComposition)); + @Test + void testAcReviewPublisher() { + var publisher = new AcPreparePublisher(); + var topicSink = mock(TopicSink.class); + publisher.active(topicSink); + var automationComposition = + InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Crud"); + publisher.sendRevew(automationComposition); verify(topicSink).send(anyString()); } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/rest/CommonRestController.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/rest/CommonRestController.java index 0df9719c2..9c765e1b3 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/rest/CommonRestController.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/util/rest/CommonRestController.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021-2023 Nordix Foundation. + * Copyright (C) 2021-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.clamp.acm.runtime.util.rest; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; +import jakarta.ws.rs.client.Client; import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.client.Invocation; @@ -45,6 +46,7 @@ public class CommonRestController { public static final String ACTUATOR_ENDPOINT = CONTEXT_PATH + "/"; private static String httpPrefix; + protected Client client; /** * Verifies that an endpoint appears within the swagger response. @@ -52,7 +54,7 @@ public class CommonRestController { * @param endpoint the endpoint of interest */ protected void testSwagger(final String endpoint) { - final var invocationBuilder = sendActRequest("v3/api-docs"); + final var invocationBuilder = sendActRequest(); final var resp = invocationBuilder.get(String.class); assertThat(resp).contains(endpoint); @@ -71,15 +73,14 @@ public class CommonRestController { /** * Sends a request to an actuator endpoint. * - * @param endpoint the target endpoint * @return a request builder */ - protected Invocation.Builder sendActRequest(final String endpoint) { - return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + endpoint, true); + protected Invocation.Builder sendActRequest() { + return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + "v3/api-docs", true); } /** - * Sends a request to an Rest Api endpoint, without any authorization header. + * Sends a request to a Rest Api endpoint, without any authorization header. * * @param endpoint the target endpoint * @return a request builder @@ -89,16 +90,6 @@ public class CommonRestController { } /** - * Sends a request to an actuator endpoint, without any authorization header. - * - * @param endpoint the target endpoint - * @return a request builder - */ - protected Invocation.Builder sendNoAuthActRequest(final String endpoint) { - return sendFqeRequest(httpPrefix + ACTUATOR_ENDPOINT + endpoint, false); - } - - /** * Sends a request to a fully qualified endpoint. * * @param fullyQualifiedEndpoint the fully qualified target endpoint @@ -106,7 +97,7 @@ public class CommonRestController { * @return a request builder */ protected Invocation.Builder sendFqeRequest(final String fullyQualifiedEndpoint, boolean includeAuth) { - final var client = ClientBuilder.newBuilder().build(); + client = ClientBuilder.newBuilder().build(); client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true"); client.register(GsonMessageBodyHandler.class); @@ -124,11 +115,12 @@ public class CommonRestController { * Assert that POST call is Unauthorized. * * @param endPoint the endpoint - * @param entity the entity ofthe body + * @param entity the entity of the body */ protected void assertUnauthorizedPost(final String endPoint, final Entity<?> entity) { var rawresp = sendNoAuthRequest(endPoint).post(entity); assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + rawresp.close(); } /** @@ -140,6 +132,7 @@ public class CommonRestController { protected void assertUnauthorizedPut(final String endPoint, final Entity<?> entity) { var rawresp = sendNoAuthRequest(endPoint).put(entity); assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + rawresp.close(); } /** @@ -150,16 +143,7 @@ public class CommonRestController { protected void assertUnauthorizedGet(final String endPoint) { var rawresp = sendNoAuthRequest(endPoint).buildGet().invoke(); assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); - } - - /** - * Assert that GET call to actuator endpoint is Unauthorized. - * - * @param endPoint the endpoint - */ - protected void assertUnauthorizedActGet(final String endPoint) { - var rawresp = sendNoAuthActRequest(endPoint).buildGet().invoke(); - assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + rawresp.close(); } /** @@ -170,6 +154,7 @@ public class CommonRestController { protected void assertUnauthorizedDelete(final String endPoint) { var rawresp = sendNoAuthRequest(endPoint).delete(); assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + rawresp.close(); } /** @@ -181,7 +166,4 @@ public class CommonRestController { httpPrefix = "http://" + SELF + ":" + port + "/"; } - protected String getHttpPrefix() { - return httpPrefix; - } } diff --git a/runtime-acm/src/test/resources/application-prometheus-noauth.yaml b/runtime-acm/src/test/resources/application-prometheus-noauth.yaml index 57da3af18..a75c5d36f 100644 --- a/runtime-acm/src/test/resources/application-prometheus-noauth.yaml +++ b/runtime-acm/src/test/resources/application-prometheus-noauth.yaml @@ -10,37 +10,6 @@ spring: ddl-auto: create open-in-view: false -server: - servlet: - context-path: /onap/policy/clamp/acm - -runtime: - topics: - operationTopic: policy-acruntime-participant - syncTopic: acm-ppnt-sync - participantParameters: - updateParameters: - maxRetryCount: 3 - topicParameterGroup: - topicSources: - - - topic: ${runtime.topics.operationTopic} - servers: - - localhost - topicCommInfrastructure: noop - fetchTimeout: 15000 - topicSinks: - - - topicCommInfrastructure: noop - servers: - - localhost - topic: ${runtime.topics.operationTopic} - - - topic: ${runtime.topics.syncTopic} - servers: - - ${topicServer:kafka:9092} - topicCommInfrastructure: noop - tracing: enabled: true exporter: diff --git a/runtime-acm/src/test/resources/application-test.yaml b/runtime-acm/src/test/resources/application-test.yaml index 31e54737e..e3d4a48df 100644 --- a/runtime-acm/src/test/resources/application-test.yaml +++ b/runtime-acm/src/test/resources/application-test.yaml @@ -7,60 +7,5 @@ spring: maximumPoolSize: 3 jpa: hibernate: - ddl-auto: create + ddl-auto: create-drop open-in-view: false - -server: - servlet: - context-path: /onap/policy/clamp/acm - -runtime: - topics: - operationTopic: policy-acruntime-participant - syncTopic: acm-ppnt-sync - participantParameters: - updateParameters: - maxRetryCount: 3 - topicParameterGroup: - topicSources: - - - topic: ${runtime.topics.operationTopic} - servers: - - kafka:9092 - topicCommInfrastructure: NOOP - fetchTimeout: 15000 - topicSinks: - - - topicCommInfrastructure: NOOP - servers: - - kafka:9092 - topic: ${runtime.topics.operationTopic} - - - topic: ${runtime.topics.syncTopic} - servers: - - ${topicServer:kafka:9092} - topicCommInfrastructure: NOOP - acmParameters: - acElementName: org.onap.policy.clamp.acm.AutomationCompositionElement - acNodeType: org.onap.policy.clamp.acm.AutomationComposition - -management: - endpoints: - web: - base-path: / - exposure: - include: health, metrics, prometheus - tracing: - propagation: - produce: b3 - sampling: - probability: 1.0 - -tracing: - enabled: true - exporter: - endpoint: http://jaeger:4317 - protocol: grpc - sampler: - jaeger-remote: - endpoint: http://jaeger:14250
\ No newline at end of file diff --git a/runtime-acm/src/test/resources/application-tracing.yaml b/runtime-acm/src/test/resources/application-tracing.yaml new file mode 100644 index 000000000..d24fe9c53 --- /dev/null +++ b/runtime-acm/src/test/resources/application-tracing.yaml @@ -0,0 +1,27 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb + driverClassName: org.h2.Driver + hikari: + maxLifetime: 1800000 + maximumPoolSize: 3 + jpa: + hibernate: + ddl-auto: create-drop + open-in-view: false + +management: + tracing: + propagation: + produce: b3 + sampling: + probability: 1.0 + +tracing: + enabled: true + exporter: + endpoint: http://jaeger:4317 + protocol: grpc + sampler: + jaeger-remote: + endpoint: http://jaeger:14250
\ No newline at end of file diff --git a/runtime-acm/src/test/resources/rest/acm/AutomationCompositionMigrate.json b/runtime-acm/src/test/resources/rest/acm/AutomationCompositionMigrate.json new file mode 100644 index 000000000..d74970d4f --- /dev/null +++ b/runtime-acm/src/test/resources/rest/acm/AutomationCompositionMigrate.json @@ -0,0 +1,30 @@ +{ + "name": "PMSHInstance1", + "version": "1.0.1", + "compositionId": "709c62b3-8918-41b9-a747-d21eb79c6c40", + "deployState": "DEPLOYED", + "lockState": "LOCKED", + "description": "PMSH automation composition instance 0", + "elements": { + "709c62b3-8918-41b9-a747-d21eb79c6c21": { + "id": "709c62b3-8918-41b9-a747-d21eb79c6c21", + "definition": { + "name": "org.onap.domain.database.PMSH_K8SMicroserviceAutomationCompositionElement", + "version": "1.2.3" + }, + "deployState": "DEPLOYED", + "lockState": "LOCKED", + "description": "Automation composition element for the K8S microservice for PMSH" + }, + "709c62b3-8918-41b9-a747-d21eb79c6c22": { + "id": "709c62b3-8918-41b9-a747-d21eb79c6c22", + "definition": { + "name": "org.onap.domain.database.Http_PMSHMicroserviceAutomationCompositionElement", + "version": "1.2.3" + }, + "deployState": "DEPLOYED", + "lockState": "LOCKED", + "description": "Automation composition element for the operational policy for Performance Management Subscription Handling" + } + } +}
\ No newline at end of file diff --git a/runtime-acm/src/test/resources/testscripts/listenOnTopic.sh b/runtime-acm/src/test/resources/testscripts/listenOnTopic.sh deleted file mode 100755 index 5e661777b..000000000 --- a/runtime-acm/src/test/resources/testscripts/listenOnTopic.sh +++ /dev/null @@ -1,31 +0,0 @@ -#! /bin/bash -# ============LICENSE_START======================================================= -# Copyright (C) 2021 Nordix Foundation. -# ================================================================================ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# ============LICENSE_END========================================================= - -if [ $# -ne 1 ] -then - echo invalid parameters $*, specify a single parameter as the topic to listen on - exit 1 -fi - -while true -do - curl "http://localhost:3904/events/$1/TEST/1?timeout=60000" - echo "" -done - |