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