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.commissioning.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.junit.jupiter.api.Assertions.assertTrue;
29 import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_SERVICE_TEMPLATE_YAML;
30 import static org.onap.policy.clamp.acm.runtime.util.CommonTestData.TOSCA_VERSIONING;
32 import jakarta.ws.rs.client.Entity;
33 import jakarta.ws.rs.core.Response;
34 import java.util.HashMap;
36 import java.util.UUID;
37 import org.junit.jupiter.api.AfterEach;
38 import org.junit.jupiter.api.BeforeAll;
39 import org.junit.jupiter.api.BeforeEach;
40 import org.junit.jupiter.api.Test;
41 import org.junit.jupiter.api.extension.ExtendWith;
42 import org.onap.policy.clamp.acm.runtime.instantiation.InstantiationUtils;
43 import org.onap.policy.clamp.acm.runtime.util.CommonTestData;
44 import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController;
45 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionDefinition;
46 import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType;
47 import org.onap.policy.clamp.models.acm.messages.rest.commissioning.AcTypeStateUpdate;
48 import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse;
49 import org.onap.policy.clamp.models.acm.messages.rest.commissioning.PrimeOrder;
50 import org.onap.policy.clamp.models.acm.persistence.provider.AcDefinitionProvider;
51 import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
52 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
53 import org.onap.policy.models.base.PfKey;
54 import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType;
55 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
56 import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
57 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
58 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplates;
59 import org.springframework.beans.factory.annotation.Autowired;
60 import org.springframework.boot.test.context.SpringBootTest;
61 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
62 import org.springframework.boot.test.web.server.LocalServerPort;
63 import org.springframework.test.context.ActiveProfiles;
64 import org.springframework.test.context.junit.jupiter.SpringExtension;
66 @ExtendWith(SpringExtension.class)
67 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
68 @ActiveProfiles({"test", "default"})
69 class CommissioningControllerTest extends CommonRestController {
71 private static final int NUMBER_COMPOSITIONS = 10;
72 private static final String COMMISSIONING_ENDPOINT = "compositions";
73 private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate();
76 private AcDefinitionProvider acDefinitionProvider;
79 private ParticipantProvider participantProvider;
82 private int randomServerPort;
85 * starts Main and inserts a commissioning template.
88 static void setUpBeforeClass() {
89 serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
94 super.setHttpPrefix(randomServerPort);
104 super.testSwagger(COMMISSIONING_ENDPOINT);
108 void testUnauthorizedCreate() {
109 assertUnauthorizedPost(COMMISSIONING_ENDPOINT, Entity.json(serviceTemplate));
113 void testUnauthorizedQuery() {
114 assertUnauthorizedGet(COMMISSIONING_ENDPOINT);
118 void testUnauthorizedDelete() {
119 assertUnauthorizedDelete(COMMISSIONING_ENDPOINT);
123 void testCreateBadRequest() {
124 var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT);
125 var resp = invocationBuilder.post(Entity.json("NotToscaServiceTemplate"));
127 assertThat(Response.Status.BAD_REQUEST.getStatusCode()).isEqualTo(resp.getStatus());
128 var commissioningResponse = resp.readEntity(CommissioningResponse.class);
129 assertThat(commissioningResponse.getErrorDetails())
130 .contains("org.springframework.http.converter.HttpMessageNotReadableException");
131 assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).isNull();
136 void testCreateBadVersion() {
137 var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate);
138 var x = new ToscaNodeTemplate(serviceTemplateCreate
139 .getToscaTopologyTemplate().getNodeTemplates().values().iterator().next());
140 x.setVersion("1.0.wrong");
141 serviceTemplateCreate.getToscaTopologyTemplate().getNodeTemplates().put(x.getName(), x);
143 var commissioningResponse = createServiceTemplate(serviceTemplateCreate, Response.Status.INTERNAL_SERVER_ERROR);
144 assertThat(commissioningResponse.getErrorDetails())
145 .isEqualTo("java.lang.IllegalArgumentException parameter "
146 + "\"version\": value \"1.0.wrong\", does not match regular expression \""
147 + PfKey.VERSION_REGEXP + "\"");
148 assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).isNull();
153 var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate);
154 serviceTemplateCreate.setName("Create");
155 var commissioningResponse = createServiceTemplate(serviceTemplateCreate, Response.Status.CREATED);
156 assertNotNull(commissioningResponse);
157 assertNull(commissioningResponse.getErrorDetails());
158 // Response should return the number of node templates present in the service template
159 assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(7);
160 for (var nodeTemplateName : serviceTemplateCreate.getToscaTopologyTemplate().getNodeTemplates().keySet()) {
161 assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream()
162 .anyMatch(ac -> ac.getName().equals(nodeTemplateName)));
167 void testVersioning() {
168 var serviceTemplateCreate = InstantiationUtils.getToscaServiceTemplate(TOSCA_VERSIONING);
169 var commissioningResponse = createServiceTemplate(serviceTemplateCreate, Response.Status.CREATED);
170 assertNotNull(commissioningResponse);
171 assertNull(commissioningResponse.getErrorDetails());
172 // Response should return the number of node templates present in the service template
173 assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(11);
174 assertNotNull(serviceTemplateCreate);
175 for (var nodeTemplateName : serviceTemplateCreate.getToscaTopologyTemplate().getNodeTemplates().keySet()) {
176 assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream()
177 .anyMatch(ac -> ac.getName().equals(nodeTemplateName)));
181 private CommissioningResponse createServiceTemplate(ToscaServiceTemplate serviceTemplateCreate,
182 Response.Status statusExpected) {
183 var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT);
184 try (var resp = invocationBuilder.post(Entity.json(serviceTemplateCreate))) {
185 assertEquals(statusExpected.getStatusCode(), resp.getStatus());
186 return resp.readEntity(CommissioningResponse.class);
192 var toscaDataType = new ToscaDataType();
193 toscaDataType.setName("org.onap.datatypes.policy.clamp.Configuration");
194 toscaDataType.setDerivedFrom("tosca.datatypes.Root");
195 toscaDataType.setProperties(new HashMap<>());
196 var toscaProperty = new ToscaProperty();
197 toscaProperty.setName("configurationEntityId");
198 toscaProperty.setType("onap.datatypes.ToscaConceptIdentifier");
199 toscaDataType.getProperties().put(toscaProperty.getName(), toscaProperty);
201 var compositionId = createEntryInDB("forUpdate");
202 var serviceTemplateUpdate = new ToscaServiceTemplate(serviceTemplate);
203 serviceTemplateUpdate.getDataTypes().put(toscaDataType.getName(), toscaDataType);
204 serviceTemplateUpdate.setMetadata(Map.of("compositionId", compositionId));
206 var commissioningResponse = createServiceTemplate(serviceTemplateUpdate, Response.Status.OK);
207 assertNotNull(commissioningResponse);
208 assertNull(commissioningResponse.getErrorDetails());
209 // Response should return the number of node templates present in the service template
210 assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(7);
211 for (var nodeTemplateName : serviceTemplateUpdate.getToscaTopologyTemplate().getNodeTemplates().keySet()) {
212 assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream()
213 .anyMatch(ac -> ac.getName().equals(nodeTemplateName)));
216 var entity = getServiceTemplate(COMMISSIONING_ENDPOINT + "/" + compositionId);
217 assertThat(entity.getServiceTemplate().getDataTypes()).containsKey(toscaDataType.getName());
220 private AutomationCompositionDefinition getServiceTemplate(String url) {
221 var invocationBuilder = super.sendRequest(url);
222 try (var resp = invocationBuilder.buildGet().invoke()) {
223 assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus());
224 return resp.readEntity(AutomationCompositionDefinition.class);
229 void testQuery_NoResultWithThisName() {
230 var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name=noResultWithThisName");
231 try (var rawresp = invocationBuilder.buildGet().invoke()) {
232 assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
233 var entityList = rawresp.readEntity(ToscaServiceTemplate.class);
234 assertThat(entityList.getNodeTypes()).isNull();
240 createEntryInDB("forQuery");
242 var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT);
243 try (var rawresp = invocationBuilder.buildGet().invoke()) {
244 assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
245 var entityList = rawresp.readEntity(ToscaServiceTemplates.class);
246 assertNotNull(entityList);
247 assertThat(entityList.getServiceTemplates()).isNotEmpty();
252 void testQueryPageable() {
253 for (var i = 0; i < NUMBER_COMPOSITIONS; i++) {
254 createEntryInDB("queryPageable" + i);
256 // filter by name with wrong name
257 validateQueryPageable("?name=wrongName", 0);
260 validateQueryPageable("?name=queryPageable1", 1);
263 validateQueryPageable("?page=1&size=5", 5);
266 validateQueryNotPageable("?size=4");
267 validateQueryNotPageable("?page=2");
268 validateQueryNotPageable("");
271 private void validateQueryNotPageable(String parameters) {
272 var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + parameters);
273 try (var response = invocationBuilder.buildGet().invoke()) {
274 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
275 var entityList = response.readEntity(ToscaServiceTemplates.class);
276 assertThat(entityList.getServiceTemplates()).hasSizeGreaterThanOrEqualTo(NUMBER_COMPOSITIONS);
280 private void validateQueryPageable(String parameters, int size) {
281 var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + parameters);
282 try (var response = invocationBuilder.buildGet().invoke()) {
283 assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
284 var entityList = response.readEntity(ToscaServiceTemplates.class);
285 assertThat(entityList.getServiceTemplates()).hasSize(size);
290 void testDeleteBadRequest() {
291 createEntryInDB("DeleteBadRequest");
292 deleteServiceTemplate(COMMISSIONING_ENDPOINT + "/" + UUID.randomUUID(), Response.Status.NOT_FOUND);
295 private void deleteServiceTemplate(String url, Response.Status statusExpected) {
296 var invocationBuilder = super.sendRequest(url);
297 try (var resp = invocationBuilder.delete()) {
298 assertEquals(statusExpected.getStatusCode(), resp.getStatus());
304 var compositionId = createEntryInDB("forDelete");
305 deleteServiceTemplate(COMMISSIONING_ENDPOINT + "/" + compositionId, Response.Status.OK);
307 var templatesInDB = acDefinitionProvider.findAcDefinition(compositionId);
308 assertThat(templatesInDB).isEmpty();
313 var compositionId = createEntryInDB("Prime");
314 var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/" + compositionId);
316 var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate,
317 "org.onap.policy.clamp.acm.AutomationCompositionElement");
318 for (var elementEntry : acElements) {
319 var participant = CommonTestData.createParticipant(UUID.randomUUID());
320 var supportedElementType = new ParticipantSupportedElementType();
321 supportedElementType.setTypeName(elementEntry.getValue().getType());
322 supportedElementType.setTypeVersion(elementEntry.getValue().getTypeVersion());
323 participant.getParticipantSupportedElementTypes().put(supportedElementType.getId(), supportedElementType);
324 var replica = CommonTestData.createParticipantReplica(UUID.randomUUID());
325 participant.getReplicas().put(replica.getReplicaId(), replica);
326 participantProvider.saveParticipant(participant);
329 var body = new AcTypeStateUpdate();
330 body.setPrimeOrder(PrimeOrder.PRIME);
331 try (var resp = invocationBuilder.put(Entity.json(body))) {
332 assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus());
337 void testPrimeBadRequest() {
338 var compositionId = createEntryInDB("Prime");
339 var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/" + compositionId);
341 var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate,
342 "org.onap.policy.clamp.acm.AutomationCompositionElement");
343 for (var elementEntry : acElements) {
344 var participant = CommonTestData.createParticipant(UUID.randomUUID());
345 var supportedElementType = new ParticipantSupportedElementType();
346 supportedElementType.setTypeName(elementEntry.getValue().getType());
347 supportedElementType.setTypeVersion(elementEntry.getValue().getTypeVersion());
348 participant.getParticipantSupportedElementTypes().put(supportedElementType.getId(), supportedElementType);
349 participantProvider.saveParticipant(participant);
352 var body = new AcTypeStateUpdate();
353 body.setPrimeOrder(PrimeOrder.PRIME);
354 try (var resp = invocationBuilder.put(Entity.json(body))) {
355 assertEquals(Response.Status.CONFLICT.getStatusCode(), resp.getStatus());
359 private UUID createEntryInDB(String name) {
360 var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate);
361 serviceTemplateCreate.setName(name);
362 var acmDefinition = acDefinitionProvider
363 .createAutomationCompositionDefinition(serviceTemplateCreate, CommonTestData.TOSCA_ELEMENT_NAME,
364 CommonTestData.TOSCA_COMP_NAME);
366 return acmDefinition.getCompositionId();