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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.clamp.acm.runtime.instantiation.rest;
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;
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.annotation.DirtiesContext;
60 import org.springframework.test.context.ActiveProfiles;
61 import org.springframework.test.context.junit.jupiter.SpringExtension;
64 * Class to perform unit test of {@link InstantiationController}}.
67 @ExtendWith(SpringExtension.class)
68 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
69 @ActiveProfiles({ "test", "default" })
70 @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
71 class InstantiationControllerTest extends CommonRestController {
73 private static final int NUMBER_INSTANCES = 10;
74 private static final String AC_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/acm/AutomationComposition.json";
75 private static final String AC_VERSIONING_YAML = "src/test/resources/rest/acm/AutomationCompositionVersioning.yaml";
77 private static final String AC_INSTANTIATION_UPDATE_JSON =
78 "src/test/resources/rest/acm/AutomationCompositionUpdate.json";
80 private static final String INSTANTIATION_ENDPOINT = "compositions/%s/instances";
82 private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate();
84 private static final String NODE_TYPE = "org.onap.policy.clamp.acm.AutomationComposition";
87 private AcDefinitionProvider acDefinitionProvider;
90 private ParticipantProvider participantProvider;
93 private AutomationCompositionInstantiationProvider instantiationProvider;
96 private int randomServerPort;
99 static void setUpBeforeClass() {
100 serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
105 super.setHttpPrefix(randomServerPort);
108 private String getInstanceEndPoint(UUID compositionId) {
109 return String.format(INSTANTIATION_ENDPOINT, compositionId.toString());
112 private String getInstanceEndPoint(UUID compositionId, UUID instanceId) {
113 return String.format(INSTANTIATION_ENDPOINT, compositionId.toString()) + "/" + instanceId;
118 super.testSwagger(String.format(INSTANTIATION_ENDPOINT, "{compositionId}"));
122 void testCreate_Unauthorized() {
123 var automationComposition =
124 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Unauthorized");
126 assertUnauthorizedPost(getInstanceEndPoint(UUID.randomUUID()), Entity.json(automationComposition));
130 void testQuery_Unauthorized() {
131 assertUnauthorizedGet(getInstanceEndPoint(UUID.randomUUID()));
135 void testUpdate_Unauthorized() {
136 var automationComposition =
137 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Unauthorized");
139 assertUnauthorizedPut(getInstanceEndPoint(UUID.randomUUID()), Entity.json(automationComposition));
143 void testDelete_Unauthorized() {
144 assertUnauthorizedDelete(getInstanceEndPoint(UUID.randomUUID()));
149 var compositionId = createAcDefinitionInDB("Create");
150 var automationCompositionFromRsc =
151 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Create");
152 assertNotNull(automationCompositionFromRsc);
153 automationCompositionFromRsc.setCompositionId(compositionId);
155 var instResponse = createAutomationComposition(compositionId, automationCompositionFromRsc,
156 Response.Status.CREATED);
157 InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionFromRsc);
158 automationCompositionFromRsc.setInstanceId(instResponse.getInstanceId());
159 automationCompositionFromRsc.getElements().values()
160 .forEach(element -> element.setParticipantId(CommonTestData.getParticipantId()));
162 var automationCompositionFromDb =
163 instantiationProvider.getAutomationComposition(compositionId, instResponse.getInstanceId());
164 automationCompositionFromRsc.setLastMsg(automationCompositionFromDb.getLastMsg());
166 assertNotNull(automationCompositionFromDb);
167 assertEquals(automationCompositionFromRsc, automationCompositionFromDb);
170 private InstantiationResponse createAutomationComposition(UUID compositionId,
171 AutomationComposition automationComposition, Response.Status statusExpected) {
172 var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId));
173 try (var resp = invocationBuilder.post(Entity.json(automationComposition))) {
174 assertEquals(statusExpected.getStatusCode(), resp.getStatus());
175 return resp.readEntity(InstantiationResponse.class);
180 void testCreateBadRequest() {
181 var compositionId = createAcDefinitionInDB("CreateBadRequest");
182 var automationCompositionFromRsc = InstantiationUtils
183 .getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "CreateBadRequest");
184 assertNotNull(automationCompositionFromRsc);
185 automationCompositionFromRsc.setCompositionId(compositionId);
187 createAutomationComposition(compositionId, automationCompositionFromRsc, Response.Status.CREATED);
189 // testing Bad Request: AC already defined
190 var instResponse = createAutomationComposition(compositionId, automationCompositionFromRsc,
191 Response.Status.BAD_REQUEST);
192 assertNotNull(instResponse.getErrorDetails());
193 assertNull(instResponse.getAffectedAutomationComposition());
197 void testVersioning() {
198 var serviceTemplateVer = InstantiationUtils.getToscaServiceTemplate(TOSCA_VERSIONING);
199 var compositionId = createAcDefinitionInDB(serviceTemplateVer);
200 var automationCompositionFromRsc = InstantiationUtils
201 .getAutomationCompositionFromYaml(AC_VERSIONING_YAML, "Versioning");
202 assertNotNull(automationCompositionFromRsc);
203 automationCompositionFromRsc.setCompositionId(compositionId);
205 createAutomationComposition(compositionId, automationCompositionFromRsc, Response.Status.CREATED);
206 InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionFromRsc);
210 void testQuery_NoResultWithThisName() {
211 var invocationBuilder =
212 super.sendRequest(getInstanceEndPoint(UUID.randomUUID()) + "?name=noResultWithThisName");
213 try (var rawresp = invocationBuilder.buildGet().invoke()) {
214 assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
215 var resp = rawresp.readEntity(AutomationCompositions.class);
216 assertThat(resp.getAutomationCompositionList()).isEmpty();
222 var compositionId = createAcDefinitionInDB("Query");
223 var automationComposition =
224 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Query");
225 assertNotNull(automationComposition);
226 automationComposition.setCompositionId(compositionId);
228 instantiationProvider.createAutomationComposition(compositionId, automationComposition);
230 var invocationBuilder = super.sendRequest(
231 getInstanceEndPoint(compositionId) + "?name=" + automationComposition.getKey().getName());
232 try (var rawresp = invocationBuilder.buildGet().invoke()) {
233 assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
234 var automationCompositionsQuery = rawresp.readEntity(AutomationCompositions.class);
235 assertNotNull(automationCompositionsQuery);
236 assertThat(automationCompositionsQuery.getAutomationCompositionList()).hasSize(1);
237 var automationCompositionRc = automationCompositionsQuery.getAutomationCompositionList().get(0);
238 automationComposition.setLastMsg(automationCompositionRc.getLastMsg());
239 assertEquals(automationComposition, automationCompositionRc);
244 void testQueryPageable() {
245 var compositionId = createAcDefinitionInDB("Query");
246 var automationComposition =
247 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Query");
248 assertNotNull(automationComposition);
249 automationComposition.setCompositionId(compositionId);
250 for (var i = 0; i < NUMBER_INSTANCES; i++) {
251 automationComposition.setName("acm_" + i);
252 instantiationProvider.createAutomationComposition(compositionId, automationComposition);
254 var endpoint = getInstanceEndPoint(compositionId);
255 validateQueryPageable(endpoint + "?name=wrong_name", 0);
256 validateQueryPageable(endpoint + "?name=acm_1", 1);
257 validateQueryPageable(endpoint + "?page=1&size=4", 4);
259 validateQueryNotPageable(endpoint + "?page=0");
260 validateQueryNotPageable(endpoint + "?size=5");
261 validateQueryNotPageable(endpoint);
264 private void validateQueryNotPageable(String link) {
265 var invocationBuilder = super.sendRequest(link);
266 try (var response = invocationBuilder.buildGet().invoke()) {
267 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
268 var resultList = response.readEntity(AutomationCompositions.class);
269 assertNotNull(resultList);
270 assertThat(resultList.getAutomationCompositionList()).hasSizeGreaterThanOrEqualTo(NUMBER_INSTANCES);
274 private void validateQueryPageable(String link, int size) {
275 var invocationBuilder = super.sendRequest(link);
276 try (var response = invocationBuilder.buildGet().invoke()) {
277 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
278 var resultList = response.readEntity(AutomationCompositions.class);
279 assertNotNull(resultList);
280 assertThat(resultList.getAutomationCompositionList()).hasSize(size);
286 var compositionId = createAcDefinitionInDB("Get");
287 var automationComposition =
288 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Get");
289 assertNotNull(automationComposition);
290 automationComposition.setCompositionId(compositionId);
292 instantiationProvider.createAutomationComposition(compositionId, automationComposition);
294 var invocationBuilder = super.sendRequest(
295 getInstanceEndPoint(compositionId, automationComposition.getInstanceId()));
296 var rawresp = invocationBuilder.buildGet().invoke();
297 assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
298 var automationCompositionGet = rawresp.readEntity(AutomationComposition.class);
300 assertNotNull(automationCompositionGet);
301 automationComposition.setLastMsg(automationCompositionGet.getLastMsg());
302 assertEquals(automationComposition, automationCompositionGet);
307 var compositionId = createAcDefinitionInDB("Update");
308 var automationCompositionCreate =
309 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Update");
310 assertNotNull(automationCompositionCreate);
311 automationCompositionCreate.setCompositionId(compositionId);
313 var response = instantiationProvider.createAutomationComposition(compositionId, automationCompositionCreate);
315 var automationComposition =
316 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_UPDATE_JSON, "Update");
317 assertNotNull(automationComposition);
318 automationComposition.setCompositionId(compositionId);
319 automationComposition.setInstanceId(response.getInstanceId());
320 automationComposition.getElements().values()
321 .forEach(element -> element.setParticipantId(CommonTestData.getParticipantId()));
323 var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId));
324 try (var resp = invocationBuilder.post(Entity.json(automationComposition))) {
325 assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus());
327 var instResponse = resp.readEntity(InstantiationResponse.class);
328 InstantiationUtils.assertInstantiationResponse(instResponse, automationComposition);
330 var automationCompositionsFromDb = instantiationProvider.getAutomationCompositions(
331 compositionId, automationComposition.getKey().getName(),
332 automationComposition.getKey().getVersion(), Pageable.unpaged());
334 assertNotNull(automationCompositionsFromDb);
335 assertThat(automationCompositionsFromDb.getAutomationCompositionList()).hasSize(1);
336 var acFromDb = automationCompositionsFromDb.getAutomationCompositionList().get(0);
337 automationComposition.setLastMsg(acFromDb.getLastMsg());
338 automationComposition.setRevisionId(acFromDb.getRevisionId());
339 assertEquals(automationComposition, acFromDb);
344 var compositionId = createAcDefinitionInDB("Delete");
345 var automationCompositionFromRsc =
346 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Delete");
347 assertNotNull(automationCompositionFromRsc);
348 automationCompositionFromRsc.setCompositionId(compositionId);
351 instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc);
353 var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, instResponse.getInstanceId()));
354 try (var resp = invocationBuilder.delete()) {
355 assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus());
356 instResponse = resp.readEntity(InstantiationResponse.class);
358 InstantiationUtils.assertInstantiationResponse(instResponse, automationCompositionFromRsc);
360 var automationCompositionsFromDb = instantiationProvider.getAutomationCompositions(compositionId,
361 automationCompositionFromRsc.getKey().getName(), automationCompositionFromRsc.getKey().getVersion(),
363 assertEquals(DeployState.DELETING,
364 automationCompositionsFromDb.getAutomationCompositionList().get(0).getDeployState());
368 void testDeleteNotFound() {
369 var compositionId = createAcDefinitionInDB("DeleteNotFound");
370 var automationCompositionFromRsc =
371 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "DelNotFound");
372 assertNotNull(automationCompositionFromRsc);
373 automationCompositionFromRsc.setCompositionId(compositionId);
375 instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc);
377 var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, UUID.randomUUID()));
378 try (var resp = invocationBuilder.delete()) {
379 assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus());
384 void testRollbackNotValid() {
385 var compositionId = createAcDefinitionInDB("RollbackNotFound");
387 // instance not found
388 var url = getInstanceEndPoint(compositionId, UUID.randomUUID()) + "/rollback";
389 var invocationBuilder = super.sendRequest(url);
390 try (var resp = invocationBuilder.post(Entity.entity("", MediaType.APPLICATION_JSON))) {
391 assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus());
394 // instance not valid state
395 var automationCompositionFromRsc =
396 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "NotValid");
397 assertNotNull(automationCompositionFromRsc);
398 automationCompositionFromRsc.setCompositionId(compositionId);
399 var instanceResponse =
400 instantiationProvider.createAutomationComposition(compositionId, automationCompositionFromRsc);
401 url = getInstanceEndPoint(compositionId, instanceResponse.getInstanceId()) + "/rollback";
402 invocationBuilder = super.sendRequest(url);
403 try (var resp = invocationBuilder.post(Entity.entity("", MediaType.APPLICATION_JSON))) {
404 assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus());
409 void testDeploy_NotFound() {
410 var compositionId = createAcDefinitionInDB("Deploy_NotFound");
411 var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, UUID.randomUUID()));
412 try (var resp = invocationBuilder.put(Entity.json(new AcInstanceStateUpdate()))) {
413 assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus());
418 void testDeploy_BadRequest() {
419 var compositionId = createAcDefinitionInDB("Deploy_BadRequest");
421 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "BadRequest");
422 assertNotNull(acFromRsc);
423 acFromRsc.setCompositionId(compositionId);
425 var instResponse = instantiationProvider.createAutomationComposition(compositionId, acFromRsc);
427 var command = new AcInstanceStateUpdate();
428 command.setDeployOrder(null);
429 command.setLockOrder(null);
431 var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, instResponse.getInstanceId()));
432 try (var resp = invocationBuilder.put(Entity.json(command))) {
433 assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus());
439 var compositionId = createAcDefinitionInDB("Deploy");
440 var automationComposition =
441 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Command");
442 assertNotNull(automationComposition);
443 automationComposition.setCompositionId(compositionId);
444 var instResponse = instantiationProvider.createAutomationComposition(compositionId, automationComposition);
446 var instantiationUpdate = new AcInstanceStateUpdate();
447 instantiationUpdate.setDeployOrder(DeployOrder.DEPLOY);
448 instantiationUpdate.setLockOrder(null);
450 var invocationBuilder = super.sendRequest(getInstanceEndPoint(compositionId, instResponse.getInstanceId()));
451 try (var resp = invocationBuilder.put(Entity.json(instantiationUpdate))) {
452 assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus());
457 void test_QueryCompositionInstancesByStateChangeDeployState() {
459 var compositionId = createAcDefinitionInDB("Query");
460 var automationComposition =
461 InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Query");
462 assertNotNull(automationComposition);
463 automationComposition.setCompositionId(compositionId);
464 for (var i = 0; i < NUMBER_INSTANCES; i++) {
465 automationComposition.setName("acmr_" + i);
466 instantiationProvider.createAutomationComposition(compositionId, automationComposition);
469 validateQueryPageable("instances", 10);
470 validateQueryPageable("instances?page=1&size=4", 4);
471 validateQueryPageable("instances?size=4", 10); // only works if page is also informed, so listAll
472 validateQueryPageable("instances?stateChangeResult=FAILED,TIMEOUT", 0);
473 validateQueryPageable("instances?deployState=UNDEPLOYED", 10);
474 validateQueryPageable("instances?stateChangeResult=NO_ERROR&deployState=UNDEPLOYED", 0);
475 validateQueryPageable("instances?sort=name&sortOrder=DESC", 10);
478 private UUID createAcDefinitionInDB(String name) {
479 var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate);
480 serviceTemplateCreate.setName(name);
481 return createAcDefinitionInDB(serviceTemplateCreate);
484 private UUID createAcDefinitionInDB(ToscaServiceTemplate serviceTemplateCreate) {
485 var acmDefinition = CommonTestData.createAcDefinition(serviceTemplateCreate, AcTypeState.PRIMED);
486 acDefinitionProvider.updateAcDefinition(acmDefinition, NODE_TYPE);
487 saveDummyParticipantInDb();
488 return acmDefinition.getCompositionId();
491 private void saveDummyParticipantInDb() {
492 var participant = CommonTestData.createParticipant(CommonTestData.getParticipantId());
493 var replica = CommonTestData.createParticipantReplica(CommonTestData.getReplicaId());
494 participant.getReplicas().put(replica.getReplicaId(), replica);
495 participantProvider.saveParticipant(participant);