2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.clamp.acm.runtime.supervision.scanner;
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.junit.jupiter.api.Assertions.assertEquals;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.Mockito.clearInvocations;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.times;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.when;
31 import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML;
33 import java.util.List;
35 import java.util.UUID;
36 import org.junit.jupiter.api.Test;
37 import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils;
38 import org.onap.policy.clamp.acm.runtime.main.utils.EncryptionUtils;
39 import org.onap.policy.clamp.acm.runtime.supervision.comm.AcPreparePublisher;
40 import org.onap.policy.clamp.acm.runtime.supervision.comm.AutomationCompositionMigrationPublisher;
41 import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantSyncPublisher;
42 import org.onap.policy.clamp.acm.runtime.util.CommonTestData;
43 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
44 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
45 import org.onap.policy.clamp.models.acm.concepts.DeployState;
46 import org.onap.policy.clamp.models.acm.concepts.LockState;
47 import org.onap.policy.clamp.models.acm.concepts.SubState;
48 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
49 import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
51 class StageScannerTest {
52 private static final String AC_JSON = "src/test/resources/rest/acm/AutomationCompositionSmoke.json";
53 private static final UUID COMPOSITION_ID = UUID.randomUUID();
56 void testSendAutomationCompositionMigrate() {
57 var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
58 assert automationComposition != null;
59 automationComposition.setCompositionId(COMPOSITION_ID);
60 var compositionTargetId = UUID.randomUUID();
61 automationComposition.setCompositionTargetId(compositionTargetId);
62 CommonTestData.modifyAcState(automationComposition, DeployState.MIGRATING);
63 // first element is not migrated yet
64 var element = automationComposition.getElements().entrySet().iterator().next().getValue();
65 element.setDeployState(DeployState.MIGRATING);
67 var acProvider = mock(AutomationCompositionProvider.class);
68 when(acProvider.updateAutomationComposition(any())).thenReturn(automationComposition);
69 var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
70 var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
71 var participantSyncPublisher = mock(ParticipantSyncPublisher.class);
72 var supervisionScanner = new StageScanner(acProvider, participantSyncPublisher,
73 mock(AutomationCompositionMigrationPublisher.class), mock(AcPreparePublisher.class),
74 acRuntimeParameterGroup, encryptionUtils);
75 var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
76 var acDefinition = new AutomationCompositionDefinition();
77 acDefinition.setServiceTemplate(serviceTemplate);
78 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
79 verify(acProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class));
80 assertEquals(DeployState.MIGRATING, automationComposition.getDeployState());
82 // send message for next stage
83 clearInvocations(acProvider);
84 var toscaNodeTemplate = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates()
85 .get(element.getDefinition().getName());
86 toscaNodeTemplate.setProperties(Map.of("stage", List.of(1)));
88 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
89 verify(acProvider).updateAutomationComposition(any(AutomationComposition.class));
90 assertEquals(DeployState.MIGRATING, automationComposition.getDeployState());
92 // first element is migrated
93 clearInvocations(acProvider);
94 element.setDeployState(DeployState.DEPLOYED);
95 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
96 verify(acProvider).updateAutomationComposition(any(AutomationComposition.class));
98 assertEquals(DeployState.DEPLOYED, automationComposition.getDeployState());
99 assertEquals(compositionTargetId, automationComposition.getCompositionId());
101 // remove all element for a participant
102 clearInvocations(acProvider);
103 clearInvocations(participantSyncPublisher);
104 element.setDeployState(DeployState.DELETED);
105 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
106 verify(acProvider).updateAutomationComposition(any(AutomationComposition.class));
107 assertThat(automationComposition.getElements()).doesNotContainKey(element.getId()); //element deleted
108 verify(participantSyncPublisher, times(1)).sendDeleteSync(automationComposition, element.getParticipantId());
110 // remove one element; participant retains other elements
111 clearInvocations(acProvider);
112 clearInvocations(participantSyncPublisher);
113 for (var e : automationComposition.getElements().values()) {
114 e.setParticipantId(element.getParticipantId());
116 automationComposition.getElements().put(element.getId(), element);
117 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
118 verify(acProvider).updateAutomationComposition(any(AutomationComposition.class));
119 assertThat(automationComposition.getElements()).doesNotContainKey(element.getId()); //element deleted
120 verify(participantSyncPublisher, times(0)).sendDeleteSync(automationComposition,
121 element.getParticipantId());
125 void testSendAutomationCompositionMigrationReverting() {
126 var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
127 assert automationComposition != null;
128 automationComposition.setCompositionId(COMPOSITION_ID);
129 automationComposition.setCompositionTargetId(UUID.randomUUID());
130 CommonTestData.modifyAcState(automationComposition, DeployState.MIGRATION_REVERTING);
132 // first element is not migrated yet
133 var element = automationComposition.getElements().entrySet().iterator().next().getValue();
134 element.setDeployState(DeployState.MIGRATION_REVERTING);
136 var acProvider = mock(AutomationCompositionProvider.class);
137 when(acProvider.updateAutomationComposition(any())).thenReturn(automationComposition);
138 var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
139 var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
140 var supervisionScanner = new StageScanner(acProvider, mock(ParticipantSyncPublisher.class),
141 mock(AutomationCompositionMigrationPublisher.class), mock(AcPreparePublisher.class),
142 acRuntimeParameterGroup, encryptionUtils);
143 var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
144 var acDefinition = new AutomationCompositionDefinition();
145 acDefinition.setServiceTemplate(serviceTemplate);
146 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
147 verify(acProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class));
148 assertEquals(DeployState.MIGRATION_REVERTING, automationComposition.getDeployState());
150 // send message for next stage
151 clearInvocations(acProvider);
152 var toscaNodeTemplate = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates()
153 .get(element.getDefinition().getName());
154 toscaNodeTemplate.setProperties(Map.of("stage", List.of(1)));
156 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
157 verify(acProvider).updateAutomationComposition(any(AutomationComposition.class));
158 assertEquals(DeployState.MIGRATION_REVERTING, automationComposition.getDeployState());
160 // first element is migrated
161 clearInvocations(acProvider);
162 element.setDeployState(DeployState.DEPLOYED);
163 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
164 verify(acProvider).updateAutomationComposition(any(AutomationComposition.class));
166 assertEquals(DeployState.DEPLOYED, automationComposition.getDeployState());
170 void testSendAutomationCompositionPrepare() {
171 var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud");
172 automationComposition.setDeployState(DeployState.UNDEPLOYED);
173 automationComposition.setSubState(SubState.PREPARING);
174 automationComposition.setLockState(LockState.NONE);
175 automationComposition.setCompositionId(COMPOSITION_ID);
176 automationComposition.setLastMsg(TimestampHelper.now());
177 automationComposition.setPhase(0);
178 for (var element : automationComposition.getElements().values()) {
179 element.setDeployState(DeployState.UNDEPLOYED);
180 element.setLockState(LockState.NONE);
181 element.setSubState(SubState.NONE);
183 // first element is not prepared yet
184 var element = automationComposition.getElements().entrySet().iterator().next().getValue();
185 element.setSubState(SubState.PREPARING);
187 var acProvider = mock(AutomationCompositionProvider.class);
188 when(acProvider.updateAutomationComposition(any())).thenReturn(automationComposition);
190 var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner");
191 var encryptionUtils = new EncryptionUtils(acRuntimeParameterGroup);
192 var supervisionScanner = new StageScanner(acProvider, mock(ParticipantSyncPublisher.class),
193 mock(AutomationCompositionMigrationPublisher.class), mock(AcPreparePublisher.class),
194 acRuntimeParameterGroup, encryptionUtils);
196 var serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
197 var acDefinition = new AutomationCompositionDefinition();
198 acDefinition.setServiceTemplate(serviceTemplate);
199 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
200 verify(acProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class));
201 assertEquals(SubState.PREPARING, automationComposition.getSubState());
203 // send message for next stage
204 clearInvocations(acProvider);
205 var toscaNodeTemplate = serviceTemplate.getToscaTopologyTemplate().getNodeTemplates()
206 .get(element.getDefinition().getName());
207 var prepare = Map.of("prepare", List.of(1));
208 toscaNodeTemplate.setProperties(Map.of("stage", prepare));
210 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
211 verify(acProvider).updateAutomationComposition(any(AutomationComposition.class));
212 assertEquals(SubState.PREPARING, automationComposition.getSubState());
214 // first element is prepared
215 clearInvocations(acProvider);
216 element.setSubState(SubState.NONE);
217 supervisionScanner.scanStage(automationComposition, acDefinition, new UpdateSync(), UUID.randomUUID());
218 verify(acProvider).updateAutomationComposition(any(AutomationComposition.class));
220 assertEquals(SubState.NONE, automationComposition.getSubState());