e7d6e36bf9d2d715f5408066c1274684ed1f878c
[policy/clamp.git] /
1 /*-
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.clamp.acm.participant.intermediary.handler;
22
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;
32
33 import java.util.List;
34 import java.util.Map;
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.AutomationCompositionElementDefinition;
44 import org.onap.policy.clamp.models.acm.concepts.DeployState;
45 import org.onap.policy.clamp.models.acm.concepts.ParticipantDeploy;
46 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeploy;
47 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionDeployAck;
48 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionMigration;
49 import org.onap.policy.clamp.models.acm.messages.kafka.participant.AutomationCompositionStateChange;
50 import org.onap.policy.clamp.models.acm.messages.kafka.participant.PropertiesUpdate;
51 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
52 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.LockOrder;
53 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
54
55 class AutomationCompositionHandlerTest {
56
57     @Test
58     void handleAutomationCompositionStateChangeNullTest() {
59         var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
60         var cacheProvider = mock(CacheProvider.class);
61         var ach =
62                 new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, mock(ThreadHandler.class));
63
64         var automationCompositionStateChange = new AutomationCompositionStateChange();
65         assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
66
67         automationCompositionStateChange.setAutomationCompositionId(UUID.randomUUID());
68         automationCompositionStateChange.setDeployOrderedState(DeployOrder.DELETE);
69         assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
70         verify(participantMessagePublisher).sendAutomationCompositionAck(any(AutomationCompositionDeployAck.class));
71
72         var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
73         automationCompositionStateChange.setAutomationCompositionId(automationComposition.getInstanceId());
74         when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
75                 .thenReturn(automationComposition);
76         automationCompositionStateChange.setDeployOrderedState(DeployOrder.UPDATE);
77         assertDoesNotThrow(() -> ach.handleAutomationCompositionStateChange(automationCompositionStateChange));
78     }
79
80     @Test
81     void handleAcStateChangeUndeployTest() {
82         var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
83         automationComposition.setCompositionId(UUID.randomUUID());
84         automationComposition.setInstanceId(UUID.randomUUID());
85         automationComposition.setCompositionTargetId(UUID.randomUUID());
86         var participantDeploy =
87                 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
88
89         var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
90         cacheProvider.initializeAutomationComposition(automationComposition.getCompositionId(),
91                 automationComposition.getInstanceId(), participantDeploy, UUID.randomUUID());
92
93         var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
94                 automationComposition.getInstanceId(), DeployOrder.UNDEPLOY, LockOrder.NONE);
95
96         var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
97         var listener = mock(ThreadHandler.class);
98         var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
99         ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
100         automationComposition = cacheProvider.getAutomationComposition(automationComposition.getInstanceId());
101         verify(listener, times(automationComposition.getElements().size())).undeploy(any(), any(), any());
102         for (var element : automationComposition.getElements().values()) {
103             assertEquals(DeployState.UNDEPLOYING, element.getDeployState());
104         }
105     }
106
107     @Test
108     void handleAutomationCompositionStateChangeUndeployTest() {
109         var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
110         var cacheProvider = mock(CacheProvider.class);
111         when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
112                 .thenReturn(automationComposition);
113         when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
114
115         var acDefinition = new AcDefinition();
116         acDefinition.setCompositionId(automationComposition.getCompositionId());
117         for (var element : automationComposition.getElements().values()) {
118             acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
119         }
120         when(cacheProvider.getAcElementsDefinitions())
121             .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
122         var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
123             automationComposition.getInstanceId(), DeployOrder.UNDEPLOY, LockOrder.NONE);
124
125         var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
126         var listener = mock(ThreadHandler.class);
127         var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
128         ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
129         verify(listener, times(automationComposition.getElements().size())).undeploy(any(), any(), any());
130         for (var element : automationComposition.getElements().values()) {
131             assertEquals(DeployState.UNDEPLOYING, element.getDeployState());
132         }
133
134         clearInvocations(listener);
135         automationCompositionStateChange.setStartPhase(2);
136         ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
137         verify(listener, times(0)).undeploy(any(), any(), any());
138     }
139
140     @Test
141     void handleAutomationCompositionStateChangeDeleteTest() {
142         var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
143         var cacheProvider = mock(CacheProvider.class);
144         when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
145                 .thenReturn(automationComposition);
146         when(cacheProvider.getCommonProperties(any(UUID.class), any(UUID.class))).thenReturn(Map.of());
147
148         var acDefinition = new AcDefinition();
149         acDefinition.setCompositionId(automationComposition.getCompositionId());
150         for (var element : automationComposition.getElements().values()) {
151             acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
152         }
153         when(cacheProvider.getAcElementsDefinitions())
154             .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
155         var automationCompositionStateChange = CommonTestData.getStateChange(CommonTestData.getParticipantId(),
156             automationComposition.getInstanceId(), DeployOrder.DELETE, LockOrder.NONE);
157         var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
158         var listener = mock(ThreadHandler.class);
159         var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
160         ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
161         verify(listener, times(automationComposition.getElements().size())).delete(any(), any(), any());
162         for (var element : automationComposition.getElements().values()) {
163             assertEquals(DeployState.DELETING, element.getDeployState());
164         }
165
166         clearInvocations(listener);
167         automationCompositionStateChange.setStartPhase(2);
168         ach.handleAutomationCompositionStateChange(automationCompositionStateChange);
169         verify(listener, times(0)).delete(any(), any(), any());
170     }
171
172     @Test
173     void handleAcPropertyUpdateTest() {
174         var cacheProvider = mock(CacheProvider.class);
175         var listener = mock(ThreadHandler.class);
176         var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
177         var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
178
179         var updateMsg = new PropertiesUpdate();
180         assertDoesNotThrow(() -> ach.handleAcPropertyUpdate(updateMsg));
181
182         updateMsg.setParticipantId(CommonTestData.getParticipantId());
183         when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
184         var participantDeploy = new ParticipantDeploy();
185         participantDeploy.setParticipantId(CommonTestData.getParticipantId());
186         updateMsg.getParticipantUpdatesList().add(participantDeploy);
187
188         var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
189         updateMsg.setAutomationCompositionId(automationComposition.getInstanceId());
190         when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
191                 .thenReturn(automationComposition);
192         var acElementDeploy = new AcElementDeploy();
193         acElementDeploy.setProperties(Map.of());
194         acElementDeploy.setId(automationComposition.getElements().values().iterator().next().getId());
195         participantDeploy.getAcElementList().add(acElementDeploy);
196
197         var acDefinition = new AcDefinition();
198         acDefinition.setCompositionId(automationComposition.getCompositionId());
199         for (var element : automationComposition.getElements().values()) {
200             acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
201         }
202         when(cacheProvider.getAcElementsDefinitions())
203             .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
204         ach.handleAcPropertyUpdate(updateMsg);
205         verify(listener).update(any(), any(), any(), any());
206     }
207
208     @Test
209     void handleAutomationCompositionDeployTest() {
210         var cacheProvider = mock(CacheProvider.class);
211         var listener = mock(ThreadHandler.class);
212         var participantMessagePublisher = mock(ParticipantMessagePublisher.class);
213         var ach = new AutomationCompositionHandler(cacheProvider, participantMessagePublisher, listener);
214
215         var deployMsg = new AutomationCompositionDeploy();
216         assertDoesNotThrow(() -> ach.handleAutomationCompositionDeploy(deployMsg));
217
218         deployMsg.setParticipantId(CommonTestData.getParticipantId());
219         when(cacheProvider.getParticipantId()).thenReturn(CommonTestData.getParticipantId());
220         var participantDeploy = new ParticipantDeploy();
221         participantDeploy.setParticipantId(CommonTestData.getParticipantId());
222         deployMsg.getParticipantUpdatesList().add(participantDeploy);
223
224         var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
225         deployMsg.setAutomationCompositionId(automationComposition.getInstanceId());
226         when(cacheProvider.getAutomationComposition(automationComposition.getInstanceId()))
227                 .thenReturn(automationComposition);
228         var acDefinition = new AcDefinition();
229         acDefinition.setCompositionId(automationComposition.getCompositionId());
230         for (var element : automationComposition.getElements().values()) {
231             var acElementDeploy = new AcElementDeploy();
232             acElementDeploy.setProperties(Map.of());
233             acElementDeploy.setId(element.getId());
234             participantDeploy.getAcElementList().add(acElementDeploy);
235             acDefinition.getElements().put(element.getDefinition(), new AutomationCompositionElementDefinition());
236         }
237         when(cacheProvider.getAcElementsDefinitions())
238             .thenReturn(Map.of(automationComposition.getCompositionId(), acDefinition));
239
240         ach.handleAutomationCompositionDeploy(deployMsg);
241         verify(listener, times(automationComposition.getElements().size())).deploy(any(), any(), any());
242
243         clearInvocations(listener);
244         deployMsg.setStartPhase(2);
245         deployMsg.setFirstStartPhase(false);
246         ach.handleAutomationCompositionDeploy(deployMsg);
247         verify(listener, times(0)).deploy(any(), any(), any());
248     }
249
250     @Test
251     void handleMigrationNullTest() {
252         var ach = new AutomationCompositionHandler(
253                 mock(CacheProvider.class), mock(ParticipantMessagePublisher.class), mock(ThreadHandler.class));
254         var migrationMsg = new AutomationCompositionMigration();
255         var rollbackMsg = new AutomationCompositionMigration();
256         rollbackMsg.setRollback(true);
257
258         migrationMsg.setStage(0);
259         assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
260         migrationMsg.setAutomationCompositionId(UUID.randomUUID());
261         migrationMsg.setCompositionTargetId(UUID.randomUUID());
262         assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(migrationMsg));
263
264         rollbackMsg.setStage(0);
265         assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(rollbackMsg));
266         rollbackMsg.setAutomationCompositionId(UUID.randomUUID());
267         rollbackMsg.setCompositionTargetId(UUID.randomUUID());
268         assertDoesNotThrow(() -> ach.handleAutomationCompositionMigration(rollbackMsg));
269     }
270
271     @Test
272     void handleAutomationCompositionMigrationTest() {
273         var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
274         automationComposition.setCompositionId(UUID.randomUUID());
275         automationComposition.setInstanceId(UUID.randomUUID());
276         automationComposition.setCompositionTargetId(UUID.randomUUID());
277         var definitions =
278                 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
279         var participantDeploy =
280                 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
281
282         var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
283                 automationComposition.getInstanceId(), definitions,
284                 automationComposition.getCompositionTargetId(), definitions);
285
286         var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
287                 automationComposition.getInstanceId(), definitions,
288                 automationComposition.getCompositionTargetId(), definitions);
289
290         testMigration(cacheProvider, automationComposition, 0,
291                 automationComposition.getElements().size(), false);
292         testMigration(cacheProviderRollback, automationComposition, 0,
293                 automationComposition.getElements().size(), true);
294     }
295
296     @Test
297     void handleMigrationAddRemoveTest() {
298         var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
299         automationComposition.setCompositionId(UUID.randomUUID());
300         automationComposition.setInstanceId(UUID.randomUUID());
301
302         var acMigrate = new AutomationComposition(automationComposition);
303         acMigrate.setCompositionTargetId(UUID.randomUUID());
304
305         // replacing first element with new one
306         var element = acMigrate.getElements().values().iterator().next();
307         element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.0.0"));
308         element.setId(UUID.randomUUID());
309
310         var migrateDefinitions =
311                 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
312
313         var participantDeploy =
314                 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
315         var definitions =
316                 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
317         var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
318                 automationComposition.getInstanceId(), definitions,
319                 acMigrate.getCompositionTargetId(), migrateDefinitions);
320         var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
321                 automationComposition.getInstanceId(), definitions,
322                 acMigrate.getCompositionTargetId(), migrateDefinitions);
323
324         testMigration(cacheProvider, acMigrate, 0, acMigrate.getElements().size() + 1, false);
325         testMigration(cacheProviderRollback, acMigrate, 0, acMigrate.getElements().size() + 1, true);
326     }
327
328     @Test
329     void handleAcMigrationStageTest() {
330         var automationComposition = CommonTestData.getTestAutomationCompositionMap().values().iterator().next();
331         automationComposition.setCompositionId(UUID.randomUUID());
332         automationComposition.setInstanceId(UUID.randomUUID());
333
334         var acMigrate = new AutomationComposition(automationComposition);
335         acMigrate.setCompositionTargetId(UUID.randomUUID());
336
337         // replacing first element with new one
338         var element = acMigrate.getElements().values().iterator().next();
339         element.setDefinition(new ToscaConceptIdentifier("policy.clamp.new.element", "1.2.4"));
340         element.setId(UUID.randomUUID());
341
342         // replacing definition version
343         acMigrate.getElements().values().forEach(el -> el.setDefinition(
344                 new ToscaConceptIdentifier(el.getDefinition().getName(), "1.2.4")));
345
346         var migrateDefinitions =
347                 CommonTestData.createAutomationCompositionElementDefinitionList(acMigrate);
348
349         migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
350                 .setProperties(Map.of("stage", List.of(0, 1))));
351
352         var participantDeploy =
353                 CommonTestData.createparticipantDeploy(CommonTestData.getParticipantId(), automationComposition);
354         var definitions =
355                 CommonTestData.createAutomationCompositionElementDefinitionList(automationComposition);
356         var cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
357                 automationComposition.getInstanceId(), definitions,
358                 acMigrate.getCompositionTargetId(), migrateDefinitions);
359         var cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
360                 automationComposition.getInstanceId(), definitions,
361                 acMigrate.getCompositionTargetId(), migrateDefinitions);
362
363
364         // scenario 1,2
365         migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
366                 .setProperties(Map.of("stage", List.of(1, 2))));
367
368         // expected the element deleted
369         testMigration(cacheProvider, acMigrate, 0, 1, false);
370         testMigration(cacheProviderRollback, acMigrate, 0, 1, true);
371
372         // expected 4 elements from stage 1
373         testMigration(cacheProvider, acMigrate, 1, 4, false);
374         testMigration(cacheProviderRollback, acMigrate, 1, 4, true);
375
376         // scenario 0,2
377         cacheProvider = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
378                 automationComposition.getInstanceId(), definitions,
379                 acMigrate.getCompositionTargetId(), migrateDefinitions);
380         cacheProviderRollback = createCacheProvider(participantDeploy, automationComposition.getCompositionId(),
381                 automationComposition.getInstanceId(), definitions,
382                 acMigrate.getCompositionTargetId(), migrateDefinitions);
383
384         migrateDefinitions.forEach(el -> el.getAutomationCompositionElementToscaNodeTemplate()
385                 .setProperties(Map.of("stage", List.of(0, 2))));
386
387         // expected the element deleted + 4 elements from stage 0
388         testMigration(cacheProvider, acMigrate, 0, 5, false);
389         testMigration(cacheProviderRollback, acMigrate, 0, 5, true);
390
391         // expected 0 elements
392         testMigration(cacheProvider, acMigrate, 1, 0, false);
393         testMigration(cacheProviderRollback, acMigrate, 1, 0, true);
394     }
395
396     private CacheProvider createCacheProvider(ParticipantDeploy participantDeploy,
397             UUID compositionId, UUID instanceId, List<AutomationCompositionElementDefinition> definitions,
398             UUID compositionTargetId, List<AutomationCompositionElementDefinition> migrateDefinitions) {
399         var cacheProvider = new CacheProvider(CommonTestData.getParticipantParameters());
400         cacheProvider.addElementDefinition(compositionId, definitions, UUID.randomUUID());
401         cacheProvider.initializeAutomationComposition(compositionId, instanceId, participantDeploy, UUID.randomUUID());
402         cacheProvider.addElementDefinition(compositionTargetId, migrateDefinitions, UUID.randomUUID());
403         return cacheProvider;
404     }
405
406     private void testMigration(CacheProvider cacheProvider, AutomationComposition acMigrate,
407             int stage, int expectedMigrated, boolean rollback) {
408         var migrationMsg = new AutomationCompositionMigration();
409         migrationMsg.setStage(stage);
410         migrationMsg.setCompositionId(acMigrate.getCompositionId());
411         migrationMsg.setAutomationCompositionId(acMigrate.getInstanceId());
412         migrationMsg.setCompositionTargetId(acMigrate.getCompositionTargetId());
413         var participantMigrate = CommonTestData.createparticipantDeploy(cacheProvider.getParticipantId(), acMigrate);
414         migrationMsg.setParticipantUpdatesList(List.of(participantMigrate));
415         var listener = mock(ThreadHandler.class);
416
417         clearInvocations();
418         var ach = new AutomationCompositionHandler(cacheProvider,
419                 mock(ParticipantMessagePublisher.class), listener);
420
421         clearInvocations();
422         migrationMsg.setRollback(rollback);
423         ach.handleAutomationCompositionMigration(migrationMsg);
424
425         if (!rollback) {
426             verify(listener, times(expectedMigrated)).migrate(any(), any(), any(), any(), any(), anyInt());
427         } else {
428             verify(listener, times(expectedMigrated)).rollback(any(), any(), any(), any(), any(), anyInt());
429         }
430     }
431 }