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