d214e73558515a0a948f46c7e94941ade9a8028f
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved.
4  *  Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.clamp.acm.runtime.instantiation.rest;
23
24 import static org.assertj.core.api.Assertions.assertThat;
25 import static org.junit.jupiter.api.Assertions.assertEquals;
26 import static org.junit.jupiter.api.Assertions.assertNotNull;
27 import static org.junit.jupiter.api.Assertions.assertNull;
28 import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML;
29 import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_VERSIONING;
30
31 import jakarta.ws.rs.client.Entity;
32 import jakarta.ws.rs.core.MediaType;
33 import jakarta.ws.rs.core.Response;
34 import java.util.UUID;
35 import org.junit.jupiter.api.BeforeAll;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.Test;
38 import org.junit.jupiter.api.extension.ExtendWith;
39 import org.onap.policy.clamp.acm.runtime.instantiation.AutomationCompositionInstantiationProvider;
40 import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils;
41 import org.onap.policy.clamp.acm.runtime.main.rest.InstantiationController;
42 import org.onap.policy.clamp.acm.runtime.util.CommonTestData;
43 import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController;
44 import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
45 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
46 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions;
47 import org.onap.policy.clamp.models.acm.concepts.DeployState;
48 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.AcInstanceStateUpdate;
49 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.DeployOrder;
50 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse;
51 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
52 import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
53 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
54 import org.springframework.beans.factory.annotation.Autowired;
55 import org.springframework.boot.test.context.SpringBootTest;
56 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
57 import org.springframework.boot.test.web.server.LocalServerPort;
58 import org.springframework.data.domain.Pageable;
59 import org.springframework.test.context.ActiveProfiles;
60 import org.springframework.test.context.junit.jupiter.SpringExtension;
61
62 /**
63  * Class to perform unit test of {@link InstantiationController}}.
64  *
65  */
66 @ExtendWith(SpringExtension.class)
67 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
68 @ActiveProfiles({ "test", "default" })
69 class InstantiationControllerTest extends CommonRestController {
70
71     private static final int NUMBER_ISTANCES = 10;
72     private static final String AC_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/acm/AutomationComposition.json";
73     private static final String AC_VERSIONING_YAML = "src/test/resources/rest/acm/AutomationCompositionVersioning.yaml";
74
75     private static final String AC_INSTANTIATION_UPDATE_JSON =
76             "src/test/resources/rest/acm/AutomationCompositionUpdate.json";
77
78     private static final String INSTANTIATION_ENDPOINT = "compositions/%s/instances";
79
80     private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate();
81
82     private static final String NODE_TYPE = "org.onap.policy.clamp.acm.AutomationComposition";
83
84     @Autowired
85     private AcDefinitionProvider acDefinitionProvider;
86
87     @Autowired
88     private ParticipantProvider participantProvider;
89
90     @Autowired
91     private AutomationCompositionInstantiationProvider instantiationProvider;
92
93     @LocalServerPort
94     private int randomServerPort;
95
96     @BeforeAll
97     static void setUpBeforeClass() {
98         serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
99     }
100
101     @BeforeEach
102     void setUpPort() {
103         super.setHttpPrefix(randomServerPort);
104     }
105
106     private String getInstanceEndPoint(UUID compositionId) {
107         return String.format(INSTANTIATION_ENDPOINT, compositionId.toString());
108     }
109
110     private String getInstanceEndPoint(UUID compositionId, UUID instanceId) {
111         return String.format(INSTANTIATION_ENDPOINT, compositionId.toString()) + "/" + instanceId;
112     }
113
114     @Test
115     void testSwagger() {
116         super.testSwagger(String.format(INSTANTIATION_ENDPOINT, "{compositionId}"));
117     }
118
119     @Test
120     void testCreate_Unauthorized() {
121         var automationComposition =
122                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Unauthorized");
123
124         assertUnauthorizedPost(getInstanceEndPoint(UUID.randomUUID()), Entity.json(automationComposition));
125     }
126
127     @Test
128     void testQuery_Unauthorized() {
129         assertUnauthorizedGet(getInstanceEndPoint(UUID.randomUUID()));
130     }
131
132     @Test
133     void testUpdate_Unauthorized() {
134         var automationComposition =
135                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Unauthorized");
136
137         assertUnauthorizedPut(getInstanceEndPoint(UUID.randomUUID()), Entity.json(automationComposition));
138     }
139
140     @Test
141     void testDelete_Unauthorized() {
142         assertUnauthorizedDelete(getInstanceEndPoint(UUID.randomUUID()));
143     }
144
145     @Test
146     void testCreate() {
147         var compositionId = createAcDefinitionInDB("Create");
148         var automationCompositionFromRsc =
149                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Create");
150         automationCompositionFromRsc.setCompositionId(compositionId);
151
152         var instResponse = createAutomationComposition(compositionId, automationCompositionFromRsc,
153             Response.Status.CREATED);
154         InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionFromRsc);
155         automationCompositionFromRsc.setInstanceId(instResponse.getInstanceId());
156         automationCompositionFromRsc.getElements().values()
157                 .forEach(element -> element.setParticipantId(CommonTestData.getParticipantId()));
158
159         var automationCompositionFromDb =
160                 instantiationProvider.getAutomationComposition(compositionId, instResponse.getInstanceId());
161         automationCompositionFromRsc.setLastMsg(automationCompositionFromDb.getLastMsg());
162
163         assertNotNull(automationCompositionFromDb);
164         assertEquals(automationCompositionFromRsc, automationCompositionFromDb);
165     }
166
167     private InstantiationResponse createAutomationComposition(UUID compositionId,
168         AutomationComposition automationComposition, Response.Status statusExpected) {
169         var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId));
170         try (var resp = invocationBuilder.post(Entity.json(automationComposition))) {
171             assertEquals(statusExpected.getStatusCode(), resp.getStatus());
172             return resp.readEntity(InstantiationResponse.class);
173         }
174     }
175
176     @Test
177     void testCreateBadRequest() {
178         var compositionId = createAcDefinitionInDB("CreateBadRequest");
179         var automationCompositionFromRsc = InstantiationUtils
180                 .getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "CreateBadRequest");
181         automationCompositionFromRsc.setCompositionId(compositionId);
182
183         createAutomationComposition(compositionId, automationCompositionFromRsc, Response.Status.CREATED);
184
185         // testing Bad Request: AC already defined
186         var instResponse = createAutomationComposition(compositionId, automationCompositionFromRsc,
187             Response.Status.BAD_REQUEST);
188         assertNotNull(instResponse.getErrorDetails());
189         assertNull(instResponse.getAffectedAutomationComposition());
190     }
191
192     @Test
193     void testVersioning() {
194         var serviceTemplateVer = InstantiationUtils.getToscaServiceTemplate(TOSCA_VERSIONING);
195         var compositionId = createAcDefinitionInDB(serviceTemplateVer);
196         var automationCompositionFromRsc = InstantiationUtils
197             .getAutomationCompositionFromYaml(AC_VERSIONING_YAML, "Versioning");
198         automationCompositionFromRsc.setCompositionId(compositionId);
199         var instResponse =
200             createAutomationComposition(compositionId, automationCompositionFromRsc, Response.Status.CREATED);
201         InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionFromRsc);
202     }
203
204     @Test
205     void testQuery_NoResultWithThisName() {
206         var invocationBuilder =
207                 super.sendRequest(getInstanceEndPoint(UUID.randomUUID()) + "?name=noResultWithThisName");
208         try (var rawresp = invocationBuilder.buildGet().invoke()) {
209             assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
210             var resp = rawresp.readEntity(AutomationCompositions.class);
211             assertThat(resp.getAutomationCompositionList()).isEmpty();
212         }
213     }
214
215     @Test
216     void testQuery() {
217         var compositionId = createAcDefinitionInDB("Query");
218         var automationComposition =
219                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Query");
220         automationComposition.setCompositionId(compositionId);
221
222         instantiationProvider.createAutomationComposition(compositionId, automationComposition);
223
224         var invocationBuilder = super.sendRequest(
225                 getInstanceEndPoint(compositionId) + "?name=" + automationComposition.getKey().getName());
226         try (var rawresp = invocationBuilder.buildGet().invoke()) {
227             assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
228             var automationCompositionsQuery = rawresp.readEntity(AutomationCompositions.class);
229             assertNotNull(automationCompositionsQuery);
230             assertThat(automationCompositionsQuery.getAutomationCompositionList()).hasSize(1);
231             var automationCompositionRc = automationCompositionsQuery.getAutomationCompositionList().get(0);
232             automationComposition.setLastMsg(automationCompositionRc.getLastMsg());
233             assertEquals(automationComposition, automationCompositionRc);
234         }
235     }
236
237     @Test
238     void testQueryPageable() {
239         var compositionId = createAcDefinitionInDB("Query");
240         var automationComposition =
241             InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Query");
242         automationComposition.setCompositionId(compositionId);
243         for (var i = 0; i < NUMBER_ISTANCES; i++) {
244             automationComposition.setName("acm_" + i);
245             instantiationProvider.createAutomationComposition(compositionId, automationComposition);
246         }
247         var endpoint = getInstanceEndPoint(compositionId);
248         validateQueryPageable(endpoint + "?name=wrong_name", 0);
249         validateQueryPageable(endpoint + "?name=acm_1", 1);
250         validateQueryPageable(endpoint + "?page=1&size=4", 4);
251
252         validateQueryNotPageable(endpoint + "?page=0");
253         validateQueryNotPageable(endpoint + "?size=5");
254         validateQueryNotPageable(endpoint);
255     }
256
257     private void validateQueryNotPageable(String link) {
258         var invocationBuilder = super.sendRequest(link);
259         try (var response = invocationBuilder.buildGet().invoke()) {
260             assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
261             var resultList = response.readEntity(AutomationCompositions.class);
262             assertNotNull(resultList);
263             assertThat(resultList.getAutomationCompositionList()).hasSizeGreaterThanOrEqualTo(NUMBER_ISTANCES);
264         }
265     }
266
267     private void validateQueryPageable(String link, int size) {
268         var invocationBuilder = super.sendRequest(link);
269         try (var response = invocationBuilder.buildGet().invoke()) {
270             assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
271             var resultList = response.readEntity(AutomationCompositions.class);
272             assertNotNull(resultList);
273             assertThat(resultList.getAutomationCompositionList()).hasSize(size);
274         }
275     }
276
277     @Test
278     void testGet() {
279         var compositionId = createAcDefinitionInDB("Get");
280         var automationComposition =
281                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Get");
282         automationComposition.setCompositionId(compositionId);
283
284         instantiationProvider.createAutomationComposition(compositionId, automationComposition);
285
286         var invocationBuilder = super.sendRequest(
287                 getInstanceEndPoint(compositionId, automationComposition.getInstanceId()));
288         var rawresp = invocationBuilder.buildGet().invoke();
289         assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
290         var automationCompositionGet = rawresp.readEntity(AutomationComposition.class);
291         rawresp.close();
292         assertNotNull(automationCompositionGet);
293         automationComposition.setLastMsg(automationCompositionGet.getLastMsg());
294         assertEquals(automationComposition, automationCompositionGet);
295     }
296
297     @Test
298     void testUpdate() {
299         var compositionId = createAcDefinitionInDB("Update");
300         var automationCompositionCreate =
301                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Update");
302         automationCompositionCreate.setCompositionId(compositionId);
303
304         var response = instantiationProvider.createAutomationComposition(compositionId, automationCompositionCreate);
305
306         var automationComposition =
307                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Update");
308         automationComposition.setCompositionId(compositionId);
309         automationComposition.setInstanceId(response.getInstanceId());
310         automationComposition.getElements().values()
311                 .forEach(element -> element.setParticipantId(CommonTestData.getParticipantId()));
312
313         var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId));
314         try (var resp = invocationBuilder.post(Entity.json(automationComposition))) {
315             assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus());
316
317             var instResponse = resp.readEntity(InstantiationResponse.class);
318             InstantiationUtils.assertInstantiationResponse(instResponse, automationComposition);
319         }
320         var automationCompositionsFromDb = instantiationProvider.getAutomationCompositions(
321                 compositionId, automationComposition.getKey().getName(),
322                 automationComposition.getKey().getVersion(), Pageable.unpaged());
323
324         assertNotNull(automationCompositionsFromDb);
325         assertThat(automationCompositionsFromDb.getAutomationCompositionList()).hasSize(1);
326         var acFromDb = automationCompositionsFromDb.getAutomationCompositionList().get(0);
327         automationComposition.setLastMsg(acFromDb.getLastMsg());
328         automationComposition.setRevisionId(acFromDb.getRevisionId());
329         assertEquals(automationComposition, acFromDb);
330     }
331
332     @Test
333     void testDelete() {
334         var compositionId = createAcDefinitionInDB("Delete");
335         var automationCompositionFromRsc =
336                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Delete");
337         automationCompositionFromRsc.setCompositionId(compositionId);
338
339         var instResponse =
340                 instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc);
341
342         var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, instResponse.getInstanceId()));
343         try (var resp = invocationBuilder.delete()) {
344             assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus());
345             instResponse = resp.readEntity(InstantiationResponse.class);
346         }
347         InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionFromRsc);
348
349         var automationCompositionsFromDb = instantiationProvider.getAutomationCompositions(compositionId,
350                 automationCompositionFromRsc.getKey().getName(), automationCompositionFromRsc.getKey().getVersion(),
351                 Pageable.unpaged());
352         assertEquals(DeployState.DELETING,
353                 automationCompositionsFromDb.getAutomationCompositionList().get(0).getDeployState());
354     }
355
356     @Test
357     void testDeleteNotFound() {
358         var compositionId = createAcDefinitionInDB("DeleteNotFound");
359         var automationCompositionFromRsc =
360                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "DelNotFound");
361         automationCompositionFromRsc.setCompositionId(compositionId);
362
363         instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc);
364
365         var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, UUID.randomUUID()));
366         try (var resp = invocationBuilder.delete()) {
367             assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus());
368         }
369     }
370
371     @Test
372     void testRollbackNotValid() {
373         var compositionId = createAcDefinitionInDB("RollbackNotFound");
374
375         // instance not found
376         var url = getInstanceEndPoint(compositionId, UUID.randomUUID()) + "/rollback";
377         var invocationBuilder = super.sendRequest(url);
378         try (var resp = invocationBuilder.post(Entity.entity("", MediaType.APPLICATION_JSON))) {
379             assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus());
380         }
381
382         // instance not valid state
383         var automationCompositionFromRsc =
384                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "NotValid");
385         automationCompositionFromRsc.setCompositionId(compositionId);
386         var instanceResponce =
387                 instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc);
388         url = getInstanceEndPoint(compositionId, instanceResponce.getInstanceId()) + "/rollback";
389         invocationBuilder = super.sendRequest(url);
390         try (var resp = invocationBuilder.post(Entity.entity("", MediaType.APPLICATION_JSON))) {
391             assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus());
392         }
393     }
394
395     @Test
396     void testDeploy_NotFound() {
397         var compositionId = createAcDefinitionInDB("Deploy_NotFound");
398         var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, UUID.randomUUID()));
399         try (var resp = invocationBuilder.put(Entity.json(new AcInstanceStateUpdate()))) {
400             assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus());
401         }
402     }
403
404     @Test
405     void testDeploy_BadRequest() {
406         var compositionId = createAcDefinitionInDB("Deploy_BadRequest");
407         var acFromRsc =
408                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "BadRequest");
409         acFromRsc.setCompositionId(compositionId);
410
411         var instResponse = instantiationProvider.createAutomationComposition(compositionId, acFromRsc);
412
413         var command = new AcInstanceStateUpdate();
414         command.setDeployOrder(null);
415         command.setLockOrder(null);
416
417         var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, instResponse.getInstanceId()));
418         try (var resp = invocationBuilder.put(Entity.json(command))) {
419             assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus());
420         }
421     }
422
423     @Test
424     void testDeploy() {
425         var compositionId = createAcDefinitionInDB("Deploy");
426         var automationComposition =
427                 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Command");
428         automationComposition.setCompositionId(compositionId);
429         var instResponse = instantiationProvider.createAutomationComposition(compositionId, automationComposition);
430
431         var instantiationUpdate = new AcInstanceStateUpdate();
432         instantiationUpdate.setDeployOrder(DeployOrder.DEPLOY);
433         instantiationUpdate.setLockOrder(null);
434
435         var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, instResponse.getInstanceId()));
436         try (var resp = invocationBuilder.put(Entity.json(instantiationUpdate))) {
437             assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus());
438         }
439     }
440
441     private UUID createAcDefinitionInDB(String name) {
442         var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate);
443         serviceTemplateCreate.setName(name);
444         return createAcDefinitionInDB(serviceTemplateCreate);
445     }
446
447     private UUID createAcDefinitionInDB(ToscaServiceTemplate serviceTemplateCreate) {
448         var acmDefinition = CommonTestData.createAcDefinition(serviceTemplateCreate, AcTypeState.PRIMED);
449         acDefinitionProvider.updateAcDefinition(acmDefinition, NODE_TYPE);
450         saveDummyParticipantInDb();
451         return acmDefinition.getCompositionId();
452     }
453
454     private void saveDummyParticipantInDb() {
455         var participant = CommonTestData.createParticipant(CommonTestData.getParticipantId());
456         var replica = CommonTestData.createParticipantReplica(CommonTestData.getReplicaId());
457         participant.getReplicas().put(replica.getReplicaId(), replica);
458         participantProvider.saveParticipant(participant);
459     }
460 }