2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021-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.participant.intermediary.handler;
23 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
24 import static org.junit.jupiter.api.Assertions.assertEquals;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.ArgumentMatchers.anyInt;
27 import static org.mockito.Mockito.clearInvocations;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.times;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
33 import java.util.List;
35 import java.util.UUID;
36 import org.junit.jupiter.api.Test;
37 import org.onap.policy.clamp.acm.participant.intermediary.comm.ParticipantMessagePublisher;
38 import org.onap.policy.clamp.acm.participant.intermediary.handler.cache.AcDefinition;
39 import org.onap.policy.clamp.acm.participant.intermediary.handler.cache.CacheProvider;
40 import org.onap.policy.clamp.acm.participant.intermediary.main.parameters.CommonTestData;
41 import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy;
42 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
43 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
44 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition;
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.MigrationState;
48 import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy;
49 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeploy;
50 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck;
51 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration;
52 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionStateChange;
53 import org.onap.policy.clamp.models.acm.messages.kafka.participant.PropertiesUpdate;
54 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
55 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
56 import org.onap.policy.clamp.models.acm.utils.AcmStateUtils;
57 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
59 class AutomationCompositionHandlerTest {
62 void handleAutomationCompositionStateChangeNullTest() {
63 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
64 var cacheProvider = mock(CacheProvider.class);
66 new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, mock(ThreadHandler.class));
68 var automationCompositionStateChange = new AutomationCompositionStateChange();
69 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
71 automationCompositionStateChange.setAutomationCompositionId(UUID.randomUUID());
72 automationCompositionStateChange.setDeployOrderedState(DeployOrder.DELETE);
73 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
74 verify(participantMessagePublisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class));
76 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
77 automationCompositionStateChange.setAutomationCompositionId(automationComposition.getInstanceId());
78 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
79 .thenReturn(automationComposition);
80 automationCompositionStateChange.setDeployOrderedState(DeployOrder.UPDATE);
81 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
85 void handleAcStateChangeUndeployTest() {
86 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
87 automationComposition.setCompositionId(UUID.randomUUID());
88 automationComposition.setInstanceId(UUID.randomUUID());
89 automationComposition.setCompositionTargetId(UUID.randomUUID());
90 var participantDeploy =
91 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
93 var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
94 cacheProvider.initializeAutomationComposition(automationComposition.getCompositionId(),
95 automationComposition.getInstanceId(), participantDeploy, UUID.randomUUID());
97 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
98 automationComposition.getInstanceId(), DeployOrder.UNDEPLOY, LockOrder.NONE);
100 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
101 var listener = mock(ThreadHandler.class);
102 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
103 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
104 automationComposition = cacheProvider.getAutomationComposition(automationComposition.getInstanceId());
105 verify(listener, times(automationComposition.getElements().size())).undeploy(any(), any(), any());
106 for (var element : automationComposition.getElements().values()) {
107 assertEquals(DeployState.UNDEPLOYING, element.getDeployState());
112 void handleAutomationCompositionStateChangeUndeployTest() {
113 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
114 var cacheProvider = mock(CacheProvider.class);
115 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
116 .thenReturn(automationComposition);
117 when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
119 var acDefinition = new AcDefinition();
120 acDefinition.setCompositionId(automationComposition.getCompositionId());
121 for (var element : automationComposition.getElements().values()) {
122 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
124 when(cacheProvider.getAcElementsDefinitions())
125 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
126 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
127 automationComposition.getInstanceId(), DeployOrder.UNDEPLOY, LockOrder.NONE);
129 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
130 var listener = mock(ThreadHandler.class);
131 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
132 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
133 verify(listener, times(automationComposition.getElements().size())).undeploy(any(), any(), any());
134 for (var element : automationComposition.getElements().values()) {
135 assertEquals(DeployState.UNDEPLOYING, element.getDeployState());
138 clearInvocations(listener);
139 automationCompositionStateChange.setStartPhase(2);
140 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
141 verify(listener, times(0)).undeploy(any(), any(), any());
145 void handleAutomationCompositionStateChangeDeleteTest() {
146 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
147 var cacheProvider = mock(CacheProvider.class);
148 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
149 .thenReturn(automationComposition);
150 when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
152 var acDefinition = new AcDefinition();
153 acDefinition.setCompositionId(automationComposition.getCompositionId());
154 for (var element : automationComposition.getElements().values()) {
155 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
157 when(cacheProvider.getAcElementsDefinitions())
158 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
159 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
160 automationComposition.getInstanceId(), DeployOrder.DELETE, LockOrder.NONE);
161 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
162 var listener = mock(ThreadHandler.class);
163 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
164 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
165 verify(listener, times(automationComposition.getElements().size())).delete(any(), any(), any());
166 for (var element : automationComposition.getElements().values()) {
167 assertEquals(DeployState.DELETING, element.getDeployState());
170 clearInvocations(listener);
171 automationCompositionStateChange.setStartPhase(2);
172 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
173 verify(listener, times(0)).delete(any(), any(), any());
177 void handleAcPropertyUpdateTest() {
178 var cacheProvider = mock(CacheProvider.class);
179 var listener = mock(ThreadHandler.class);
180 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
181 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
183 var updateMsg = new PropertiesUpdate();
184 assertDoesNotThrow(() -> ach.handleAcPropertyUpdate(updateMsg));
186 updateMsg.setParticipantId(CommonTestData.getParticipantId());
187 when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
188 var participantDeploy = new ParticipantDeploy();
189 participantDeploy.setParticipantId(CommonTestData.getParticipantId());
190 updateMsg.getParticipantUpdatesList().add(participantDeploy);
192 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
193 updateMsg.setAutomationCompositionId(automationComposition.getInstanceId());
194 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
195 .thenReturn(automationComposition);
196 var acElementDeploy = new AcElementDeploy();
197 acElementDeploy.setProperties(Map.of());
198 acElementDeploy.setId(automationComposition.getElements().values().iterator().next().getId());
199 participantDeploy.getAcElementList().add(acElementDeploy);
201 var acDefinition = new AcDefinition();
202 acDefinition.setCompositionId(automationComposition.getCompositionId());
203 for (var element : automationComposition.getElements().values()) {
204 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
206 when(cacheProvider.getAcElementsDefinitions())
207 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
208 ach.handleAcPropertyUpdate(updateMsg);
209 verify(listener).update(any(), any(), any(), any());
213 void handleAutomationCompositionDeployTest() {
214 var cacheProvider = mock(CacheProvider.class);
215 var listener = mock(ThreadHandler.class);
216 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
217 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
219 var deployMsg = new AutomationCompositionDeploy();
220 assertDoesNotThrow(() -> ach.handleAutomationCompositionDeploy(deployMsg));
222 deployMsg.setParticipantId(CommonTestData.getParticipantId());
223 when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
224 var participantDeploy = new ParticipantDeploy();
225 participantDeploy.setParticipantId(CommonTestData.getParticipantId());
226 deployMsg.getParticipantUpdatesList().add(participantDeploy);
228 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
229 deployMsg.setAutomationCompositionId(automationComposition.getInstanceId());
230 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
231 .thenReturn(automationComposition);
232 var acDefinition = new AcDefinition();
233 acDefinition.setCompositionId(automationComposition.getCompositionId());
234 for (var element : automationComposition.getElements().values()) {
235 var acElementDeploy = new AcElementDeploy();
236 acElementDeploy.setProperties(Map.of());
237 acElementDeploy.setId(element.getId());
238 participantDeploy.getAcElementList().add(acElementDeploy);
239 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
241 when(cacheProvider.getAcElementsDefinitions())
242 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
244 ach.handleAutomationCompositionDeploy(deployMsg);
245 verify(listener, times(automationComposition.getElements().size())).deploy(any(), any(), any());
247 clearInvocations(listener);
248 deployMsg.setStartPhase(2);
249 deployMsg.setFirstStartPhase(false);
250 ach.handleAutomationCompositionDeploy(deployMsg);
251 verify(listener, times(0)).deploy(any(), any(), any());
255 void handleAutomationCompositionMigrationTest() {
256 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
257 automationComposition.setCompositionId(UUID.randomUUID());
258 automationComposition.setInstanceId(UUID.randomUUID());
259 automationComposition.setCompositionTargetId(UUID.randomUUID());
261 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
262 var participantDeploy =
263 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
265 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
266 automationComposition.getInstanceId(), definitions,
267 automationComposition.getCompositionTargetId(), definitions);
269 var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
270 automationComposition.getInstanceId(), definitions,
271 automationComposition.getCompositionTargetId(), definitions);
273 testMigration(cacheProvider, automationComposition, 0,
274 automationComposition.getElements().size(), false);
275 testMigration(cacheProviderRollback, automationComposition, 0,
276 automationComposition.getElements().size(), true);
280 void handleAcMigrationStageTest() {
281 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
282 AcmStateUtils.setCascadedState(automationComposition, DeployState.DEPLOYED, LockState.LOCKED);
283 automationComposition.setCompositionId(UUID.randomUUID());
284 automationComposition.setInstanceId(UUID.randomUUID());
286 var acMigrate = new AutomationComposition(automationComposition);
287 AcmStateUtils.setCascadedState(acMigrate, DeployState.MIGRATING, LockState.LOCKED);
288 acMigrate.setCompositionTargetId(UUID.randomUUID());
290 // remove first element
291 var elementRemoved = acMigrate.getElements().values().iterator().next();
292 elementRemoved.setMigrationState(MigrationState.REMOVED);
295 var element = new AutomationCompositionElement(elementRemoved);
296 element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.2.4"));
297 element.setId(UUID.randomUUID());
298 element.setMigrationState(MigrationState.NEW);
299 acMigrate.getElements().put(element.getId(), element);
301 // replacing definition version excluding the removed element
302 acMigrate.getElements().values().stream()
303 .filter(el -> !el.getId().equals(elementRemoved.getId()))
304 .forEach(el -> el.setDefinition(
305 new ToscaConceptIdentifier(el.getDefinition().getName(), "1.2.4")));
307 var migrateDefinitions =
308 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
311 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
312 .setProperties(Map.of("stage", List.of(1, 2))));
314 var participantDeploy =
315 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
317 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
318 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
319 automationComposition.getInstanceId(), definitions,
320 acMigrate.getCompositionTargetId(), migrateDefinitions);
322 definitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
323 .setProperties(Map.of("stage", List.of(1, 2))));
324 automationComposition.getElements().put(element.getId(), element);
326 // expected the element deleted
327 testMigration(cacheProvider, acMigrate, 0, 1, false);
329 // expected 4 elements from stage 1
330 testMigration(cacheProvider, acMigrate, 1, 4, false);
333 cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
334 automationComposition.getInstanceId(), definitions,
335 acMigrate.getCompositionTargetId(), migrateDefinitions);
337 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
338 .setProperties(Map.of("stage", List.of(0, 2))));
340 // expected the element deleted + 4 elements from stage 0
341 testMigration(cacheProvider, acMigrate, 0, 5, false);
343 // expected 0 elements
344 testMigration(cacheProvider, acMigrate, 1, 0, false);
347 private CacheProvider createCacheProvider(ParticipantDeploy participantDeploy,
348 UUID compositionId, UUID instanceId, List<AutomationCompositionElementDefinition> definitions,
349 UUID compositionTargetId, List<AutomationCompositionElementDefinition> migrateDefinitions) {
350 var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
351 cacheProvider.addElementDefinition(compositionId, definitions, UUID.randomUUID());
352 cacheProvider.initializeAutomationComposition(compositionId, instanceId, participantDeploy, UUID.randomUUID());
353 cacheProvider.addElementDefinition(compositionTargetId, migrateDefinitions, UUID.randomUUID());
354 return cacheProvider;
357 private void testMigration(CacheProvider cacheProvider, AutomationComposition acMigrate,
358 int stage, int expectedMigrated, boolean rollback) {
359 var migrationMsg = new AutomationCompositionMigration();
360 migrationMsg.setStage(stage);
361 migrationMsg.setCompositionId(acMigrate.getCompositionId());
362 migrationMsg.setAutomationCompositionId(acMigrate.getInstanceId());
363 migrationMsg.setCompositionTargetId(acMigrate.getCompositionTargetId());
364 var participantMigrate = CommonTestData.createparticipantDeploy(cacheProvider.getParticipantId(), acMigrate);
365 migrationMsg.setParticipantUpdatesList(List.of(participantMigrate));
366 var listener = mock(ThreadHandler.class);
369 var ach = new AutomationCompositionHandler(cacheProvider,
370 mock(ParticipantMessagePublisher.class), listener);
373 migrationMsg.setRollback(rollback);
374 ach.handleAutomationCompositionMigration(migrationMsg);
377 verify(listener, times(expectedMigrated)).migrate(any(), any(), any(), any(), any(), anyInt());
379 verify(listener, times(expectedMigrated)).rollback(any(), any(), any(), any(), any(), anyInt());
384 void handleAcRollbackStageTest() {
385 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
386 AcmStateUtils.setCascadedState(automationComposition, DeployState.MIGRATING, LockState.LOCKED);
387 automationComposition.setCompositionId(UUID.randomUUID());
388 automationComposition.setInstanceId(UUID.randomUUID());
389 automationComposition.setCompositionTargetId(UUID.randomUUID());
391 var acRollback = new AutomationComposition(automationComposition);
392 AcmStateUtils.setCascadedState(acRollback, DeployState.MIGRATION_REVERTING, LockState.LOCKED);
394 var acRollbackDefinitions =
395 CommonTestData.createAutomationCompositionElementDefinitionList(acRollback);
396 acRollbackDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
397 .setProperties(Map.of("stage", List.of(1, 2))));
399 // remove first element
400 var elementRemoved = automationComposition.getElements().values().iterator().next();
401 elementRemoved.setMigrationState(MigrationState.REMOVED);
402 acRollback.getElements().get(elementRemoved.getId()).setMigrationState(MigrationState.REMOVED);
405 var element = new AutomationCompositionElement(elementRemoved);
406 element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.2.4"));
407 element.setId(UUID.randomUUID());
408 element.setMigrationState(MigrationState.NEW);
409 automationComposition.getElements().put(element.getId(), element);
410 acRollback.getElements().put(element.getId(), element);
412 // replacing definition version excluding the removed element
413 automationComposition.getElements().values().stream()
414 .filter(el -> !el.getId().equals(elementRemoved.getId()))
415 .forEach(el -> el.setDefinition(
416 new ToscaConceptIdentifier(el.getDefinition().getName(), "1.2.4")));
419 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
420 acDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
421 .setProperties(Map.of("stage", List.of(1, 2))));
423 var participantDeploy =
424 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
425 var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
426 cacheProvider.addElementDefinition(
427 automationComposition.getCompositionTargetId(), acDefinitions, UUID.randomUUID());
428 cacheProvider.initializeAutomationComposition(automationComposition.getCompositionId(),
429 automationComposition.getInstanceId(), participantDeploy, UUID.randomUUID());
430 cacheProvider.addElementDefinition(
431 automationComposition.getCompositionId(), acRollbackDefinitions, UUID.randomUUID());
433 // expected the new element deleted
434 testMigration(cacheProvider, acRollback, 0, 1, true);
436 // expected default elements
437 testMigration(cacheProvider, acRollback, 1, 4, true);
439 // expected default elements
440 testMigration(cacheProvider, acRollback, 2, 4, true);