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.MigrationState;
47 import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy;
48 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeploy;
49 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck;
50 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration;
51 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionStateChange;
52 import org.onap.policy.clamp.models.acm.messages.kafka.participant.PropertiesUpdate;
53 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
54 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
55 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
57 class AutomationCompositionHandlerTest {
60 void handleAutomationCompositionStateChangeNullTest() {
61 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
62 var cacheProvider = mock(CacheProvider.class);
64 new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, mock(ThreadHandler.class));
66 var automationCompositionStateChange = new AutomationCompositionStateChange();
67 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
69 automationCompositionStateChange.setAutomationCompositionId(UUID.randomUUID());
70 automationCompositionStateChange.setDeployOrderedState(DeployOrder.DELETE);
71 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
72 verify(participantMessagePublisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class));
74 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
75 automationCompositionStateChange.setAutomationCompositionId(automationComposition.getInstanceId());
76 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
77 .thenReturn(automationComposition);
78 automationCompositionStateChange.setDeployOrderedState(DeployOrder.UPDATE);
79 assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
83 void handleAcStateChangeUndeployTest() {
84 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
85 automationComposition.setCompositionId(UUID.randomUUID());
86 automationComposition.setInstanceId(UUID.randomUUID());
87 automationComposition.setCompositionTargetId(UUID.randomUUID());
88 var participantDeploy =
89 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
91 var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
92 cacheProvider.initializeAutomationComposition(automationComposition.getCompositionId(),
93 automationComposition.getInstanceId(), participantDeploy, UUID.randomUUID());
95 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
96 automationComposition.getInstanceId(), DeployOrder.UNDEPLOY, LockOrder.NONE);
98 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
99 var listener = mock(ThreadHandler.class);
100 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
101 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
102 automationComposition = cacheProvider.getAutomationComposition(automationComposition.getInstanceId());
103 verify(listener, times(automationComposition.getElements().size())).undeploy(any(), any(), any());
104 for (var element : automationComposition.getElements().values()) {
105 assertEquals(DeployState.UNDEPLOYING, element.getDeployState());
110 void handleAutomationCompositionStateChangeUndeployTest() {
111 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
112 var cacheProvider = mock(CacheProvider.class);
113 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
114 .thenReturn(automationComposition);
115 when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
117 var acDefinition = new AcDefinition();
118 acDefinition.setCompositionId(automationComposition.getCompositionId());
119 for (var element : automationComposition.getElements().values()) {
120 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
122 when(cacheProvider.getAcElementsDefinitions())
123 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
124 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
125 automationComposition.getInstanceId(), DeployOrder.UNDEPLOY, LockOrder.NONE);
127 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
128 var listener = mock(ThreadHandler.class);
129 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
130 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
131 verify(listener, times(automationComposition.getElements().size())).undeploy(any(), any(), any());
132 for (var element : automationComposition.getElements().values()) {
133 assertEquals(DeployState.UNDEPLOYING, element.getDeployState());
136 clearInvocations(listener);
137 automationCompositionStateChange.setStartPhase(2);
138 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
139 verify(listener, times(0)).undeploy(any(), any(), any());
143 void handleAutomationCompositionStateChangeDeleteTest() {
144 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
145 var cacheProvider = mock(CacheProvider.class);
146 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
147 .thenReturn(automationComposition);
148 when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
150 var acDefinition = new AcDefinition();
151 acDefinition.setCompositionId(automationComposition.getCompositionId());
152 for (var element : automationComposition.getElements().values()) {
153 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
155 when(cacheProvider.getAcElementsDefinitions())
156 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
157 var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
158 automationComposition.getInstanceId(), DeployOrder.DELETE, LockOrder.NONE);
159 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
160 var listener = mock(ThreadHandler.class);
161 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
162 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
163 verify(listener, times(automationComposition.getElements().size())).delete(any(), any(), any());
164 for (var element : automationComposition.getElements().values()) {
165 assertEquals(DeployState.DELETING, element.getDeployState());
168 clearInvocations(listener);
169 automationCompositionStateChange.setStartPhase(2);
170 ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
171 verify(listener, times(0)).delete(any(), any(), any());
175 void handleAcPropertyUpdateTest() {
176 var cacheProvider = mock(CacheProvider.class);
177 var listener = mock(ThreadHandler.class);
178 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
179 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
181 var updateMsg = new PropertiesUpdate();
182 assertDoesNotThrow(() -> ach.handleAcPropertyUpdate(updateMsg));
184 updateMsg.setParticipantId(CommonTestData.getParticipantId());
185 when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
186 var participantDeploy = new ParticipantDeploy();
187 participantDeploy.setParticipantId(CommonTestData.getParticipantId());
188 updateMsg.getParticipantUpdatesList().add(participantDeploy);
190 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
191 updateMsg.setAutomationCompositionId(automationComposition.getInstanceId());
192 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
193 .thenReturn(automationComposition);
194 var acElementDeploy = new AcElementDeploy();
195 acElementDeploy.setProperties(Map.of());
196 acElementDeploy.setId(automationComposition.getElements().values().iterator().next().getId());
197 participantDeploy.getAcElementList().add(acElementDeploy);
199 var acDefinition = new AcDefinition();
200 acDefinition.setCompositionId(automationComposition.getCompositionId());
201 for (var element : automationComposition.getElements().values()) {
202 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
204 when(cacheProvider.getAcElementsDefinitions())
205 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
206 ach.handleAcPropertyUpdate(updateMsg);
207 verify(listener).update(any(), any(), any(), any());
211 void handleAutomationCompositionDeployTest() {
212 var cacheProvider = mock(CacheProvider.class);
213 var listener = mock(ThreadHandler.class);
214 var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
215 var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
217 var deployMsg = new AutomationCompositionDeploy();
218 assertDoesNotThrow(() -> ach.handleAutomationCompositionDeploy(deployMsg));
220 deployMsg.setParticipantId(CommonTestData.getParticipantId());
221 when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
222 var participantDeploy = new ParticipantDeploy();
223 participantDeploy.setParticipantId(CommonTestData.getParticipantId());
224 deployMsg.getParticipantUpdatesList().add(participantDeploy);
226 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
227 deployMsg.setAutomationCompositionId(automationComposition.getInstanceId());
228 when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
229 .thenReturn(automationComposition);
230 var acDefinition = new AcDefinition();
231 acDefinition.setCompositionId(automationComposition.getCompositionId());
232 for (var element : automationComposition.getElements().values()) {
233 var acElementDeploy = new AcElementDeploy();
234 acElementDeploy.setProperties(Map.of());
235 acElementDeploy.setId(element.getId());
236 participantDeploy.getAcElementList().add(acElementDeploy);
237 acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
239 when(cacheProvider.getAcElementsDefinitions())
240 .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
242 ach.handleAutomationCompositionDeploy(deployMsg);
243 verify(listener, times(automationComposition.getElements().size())).deploy(any(), any(), any());
245 clearInvocations(listener);
246 deployMsg.setStartPhase(2);
247 deployMsg.setFirstStartPhase(false);
248 ach.handleAutomationCompositionDeploy(deployMsg);
249 verify(listener, times(0)).deploy(any(), any(), any());
253 void handleMigrationNullTest() {
254 var ach = new AutomationCompositionHandler(
255 mock(CacheProvider.class), mock(ParticipantMessagePublisher.class), mock(ThreadHandler.class));
256 var migrationMsg = new AutomationCompositionMigration();
257 var rollbackMsg = new AutomationCompositionMigration();
258 rollbackMsg.setRollback(true);
260 migrationMsg.setStage(0);
261 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
262 migrationMsg.setAutomationCompositionId(UUID.randomUUID());
263 migrationMsg.setCompositionTargetId(UUID.randomUUID());
264 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
266 rollbackMsg.setStage(0);
267 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(rollbackMsg));
268 rollbackMsg.setAutomationCompositionId(UUID.randomUUID());
269 rollbackMsg.setCompositionTargetId(UUID.randomUUID());
270 assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(rollbackMsg));
274 void handleAutomationCompositionMigrationTest() {
275 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
276 automationComposition.setCompositionId(UUID.randomUUID());
277 var instanceId = UUID.randomUUID();
278 automationComposition.setInstanceId(instanceId);
279 automationComposition.setCompositionTargetId(UUID.randomUUID());
281 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
282 var participantDeploy =
283 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
285 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
286 automationComposition.getInstanceId(), definitions,
287 automationComposition.getCompositionTargetId(), definitions);
289 var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
290 automationComposition.getInstanceId(), definitions,
291 automationComposition.getCompositionTargetId(), definitions);
293 testMigration(cacheProvider, automationComposition, 0,
294 automationComposition.getElements().size(), false);
295 testMigration(cacheProviderRollback, automationComposition, 0,
296 automationComposition.getElements().size(), true);
298 // New participant with new elements added in Migration
299 cacheProvider.removeAutomationComposition(instanceId);
300 for (var element : automationComposition.getElements().entrySet()) {
301 element.getValue().setMigrationState(MigrationState.NEW);
303 testMigration(cacheProvider, automationComposition, 0,
304 automationComposition.getElements().size(), false);
308 void handleMigrationAddRemoveTest() {
309 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
310 automationComposition.setCompositionId(UUID.randomUUID());
311 automationComposition.setInstanceId(UUID.randomUUID());
313 var acMigrate = new AutomationComposition(automationComposition);
314 acMigrate.setCompositionTargetId(UUID.randomUUID());
317 var element = acMigrate.getElements().values().iterator().next();
318 element.setMigrationState(MigrationState.REMOVED);
321 var newElement = new AutomationCompositionElement(element);
322 newElement.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.2.4"));
323 newElement.setId(UUID.randomUUID());
324 newElement.setMigrationState(MigrationState.NEW);
326 acMigrate.getElements().put(newElement.getId(), newElement);
328 var migrateDefinitions =
329 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
331 var participantDeploy =
332 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
334 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
335 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
336 automationComposition.getInstanceId(), definitions,
337 acMigrate.getCompositionTargetId(), migrateDefinitions);
338 var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
339 automationComposition.getInstanceId(), definitions,
340 acMigrate.getCompositionTargetId(), migrateDefinitions);
342 testMigration(cacheProvider, acMigrate, 0, acMigrate.getElements().size(), false);
343 testMigration(cacheProviderRollback, acMigrate, 0, acMigrate.getElements().size(), true);
348 void handleAcMigrationStageTest() {
349 var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
350 automationComposition.setCompositionId(UUID.randomUUID());
351 automationComposition.setInstanceId(UUID.randomUUID());
353 var acMigrate = new AutomationComposition(automationComposition);
354 acMigrate.setCompositionTargetId(UUID.randomUUID());
357 var element = acMigrate.getElements().values().iterator().next();
358 element.setMigrationState(MigrationState.REMOVED);
361 var newElement = new AutomationCompositionElement(element);
362 newElement.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.2.4"));
363 newElement.setId(UUID.randomUUID());
364 newElement.setMigrationState(MigrationState.NEW);
366 acMigrate.getElements().put(newElement.getId(), newElement);
369 // replacing definition version
370 acMigrate.getElements().values().forEach(el -> el.setDefinition(
371 new ToscaConceptIdentifier(el.getDefinition().getName(), "1.2.4")));
373 var migrateDefinitions =
374 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
376 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
377 .setProperties(Map.of("stage", List.of(0, 1))));
379 var participantDeploy =
380 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
382 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
383 var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
384 automationComposition.getInstanceId(), definitions,
385 acMigrate.getCompositionTargetId(), migrateDefinitions);
386 var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
387 automationComposition.getInstanceId(), definitions,
388 acMigrate.getCompositionTargetId(), migrateDefinitions);
392 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
393 .setProperties(Map.of("stage", List.of(1, 2))));
395 // expected the element deleted
396 testMigration(cacheProvider, acMigrate, 0, 1, false);
397 testMigration(cacheProviderRollback, acMigrate, 0, 1, true);
399 // expected 4 elements from stage 1
400 testMigration(cacheProvider, acMigrate, 1, 4, false);
401 testMigration(cacheProviderRollback, acMigrate, 1, 4, true);
404 cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
405 automationComposition.getInstanceId(), definitions,
406 acMigrate.getCompositionTargetId(), migrateDefinitions);
407 cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
408 automationComposition.getInstanceId(), definitions,
409 acMigrate.getCompositionTargetId(), migrateDefinitions);
411 migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
412 .setProperties(Map.of("stage", List.of(0, 2))));
414 // expected the element deleted + 4 elements from stage 0
415 testMigration(cacheProvider, acMigrate, 0, 5, false);
416 testMigration(cacheProviderRollback, acMigrate, 0, 5, true);
418 // expected 0 elements
419 testMigration(cacheProvider, acMigrate, 1, 0, false);
420 testMigration(cacheProviderRollback, acMigrate, 1, 0, true);
423 private CacheProvider createCacheProvider(ParticipantDeploy participantDeploy,
424 UUID compositionId, UUID instanceId, List<AutomationCompositionElementDefinition> definitions,
425 UUID compositionTargetId, List<AutomationCompositionElementDefinition> migrateDefinitions) {
426 var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
427 cacheProvider.addElementDefinition(compositionId, definitions, UUID.randomUUID());
428 cacheProvider.initializeAutomationComposition(compositionId, instanceId, participantDeploy, UUID.randomUUID());
429 cacheProvider.addElementDefinition(compositionTargetId, migrateDefinitions, UUID.randomUUID());
430 return cacheProvider;
433 private void testMigration(CacheProvider cacheProvider, AutomationComposition acMigrate,
434 int stage, int expectedMigrated, boolean rollback) {
435 var migrationMsg = new AutomationCompositionMigration();
436 migrationMsg.setStage(stage);
437 migrationMsg.setCompositionId(acMigrate.getCompositionId());
438 migrationMsg.setAutomationCompositionId(acMigrate.getInstanceId());
439 migrationMsg.setCompositionTargetId(acMigrate.getCompositionTargetId());
440 var participantMigrate = CommonTestData.createparticipantDeploy(cacheProvider.getParticipantId(), acMigrate);
441 migrationMsg.setParticipantUpdatesList(List.of(participantMigrate));
442 var listener = mock(ThreadHandler.class);
445 var ach = new AutomationCompositionHandler(cacheProvider,
446 mock(ParticipantMessagePublisher.class), listener);
449 migrationMsg.setRollback(rollback);
450 ach.handleAutomationCompositionMigration(migrationMsg);
453 verify(listener, times(expectedMigrated)).migrate(any(), any(), any(), any(), any(), anyInt());
455 verify(listener, times(expectedMigrated)).rollback(any(), any(), any(), any(), any(), anyInt());