488c4b15ba59996094f7091694c7ec5082d79ca8
[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.commissioning.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.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;
31
32 import jakarta.ws.rs.client.Entity;
33 import jakarta.ws.rs.core.Response;
34 import java.util.HashMap;
35 import java.util.Map;
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.annotation.DirtiesContext;
64 import org.springframework.test.context.ActiveProfiles;
65 import org.springframework.test.context.junit.jupiter.SpringExtension;
66
67 @ExtendWith(SpringExtension.class)
68 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
69 @ActiveProfiles({"test", "default"})
70 @DirtiesContext
71 class CommissioningControllerTest extends CommonRestController {
72
73     private static final int NUMBER_COMPOSITIONS = 10;
74     private static final String COMMISSIONING_ENDPOINT = "compositions";
75     private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate();
76
77     @Autowired
78     private AcDefinitionProvider acDefinitionProvider;
79
80     @Autowired
81     private ParticipantProvider participantProvider;
82
83     @LocalServerPort
84     private int randomServerPort;
85
86     /**
87      * starts Main and inserts a commissioning template.
88      */
89     @BeforeAll
90     static void setUpBeforeClass() {
91         serviceTemplate = InstantiationUtils.getToscaServiceTemplate(TOSCA_SERVICE_TEMPLATE_YAML);
92     }
93
94     @BeforeEach
95     void setUpPort() {
96         super.setHttpPrefix(randomServerPort);
97     }
98
99     @AfterEach
100     void after() {
101         super.client.close();
102     }
103
104     @Test
105     void testSwagger() {
106         super.testSwagger(COMMISSIONING_ENDPOINT);
107     }
108
109     @Test
110     void testUnauthorizedCreate() {
111         assertUnauthorizedPost(COMMISSIONING_ENDPOINT, Entity.json(serviceTemplate));
112     }
113
114     @Test
115     void testUnauthorizedQuery() {
116         assertUnauthorizedGet(COMMISSIONING_ENDPOINT);
117     }
118
119     @Test
120     void testUnauthorizedDelete() {
121         assertUnauthorizedDelete(COMMISSIONING_ENDPOINT);
122     }
123
124     @Test
125     void testCreateBadRequest() {
126         var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT);
127         var resp = invocationBuilder.post(Entity.json("NotToscaServiceTemplate"));
128
129         assertThat(Response.Status.BAD_REQUEST.getStatusCode()).isEqualTo(resp.getStatus());
130         var commissioningResponse = resp.readEntity(CommissioningResponse.class);
131         assertThat(commissioningResponse.getErrorDetails())
132             .contains("org.springframework.http.converter.HttpMessageNotReadableException");
133         assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).isNull();
134         resp.close();
135     }
136
137     @Test
138     void testCreateBadVersion() {
139         var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate);
140         var x = new ToscaNodeTemplate(serviceTemplateCreate
141             .getToscaTopologyTemplate().getNodeTemplates().values().iterator().next());
142         x.setVersion("1.0.wrong");
143         serviceTemplateCreate.getToscaTopologyTemplate().getNodeTemplates().put(x.getName(), x);
144
145         var commissioningResponse = createServiceTemplate(serviceTemplateCreate, Response.Status.INTERNAL_SERVER_ERROR);
146         assertThat(commissioningResponse.getErrorDetails())
147             .isEqualTo("java.lang.IllegalArgumentException parameter "
148                 + "\"version\": value \"1.0.wrong\", does not match regular expression \""
149                 + PfKey.VERSION_REGEXP + "\"");
150         assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).isNull();
151     }
152
153     @Test
154     void testCreate() {
155         var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate);
156         serviceTemplateCreate.setName("Create");
157         var commissioningResponse = createServiceTemplate(serviceTemplateCreate, Response.Status.CREATED);
158         assertNotNull(commissioningResponse);
159         assertNull(commissioningResponse.getErrorDetails());
160         // Response should return the number of node templates present in the service template
161         assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(7);
162         for (var nodeTemplateName : serviceTemplateCreate.getToscaTopologyTemplate().getNodeTemplates().keySet()) {
163             assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream()
164                 .anyMatch(ac -> ac.getName().equals(nodeTemplateName)));
165         }
166     }
167
168     @Test
169     void testVersioning() {
170         var serviceTemplateCreate = InstantiationUtils.getToscaServiceTemplate(TOSCA_VERSIONING);
171         var commissioningResponse = createServiceTemplate(serviceTemplateCreate, Response.Status.CREATED);
172         assertNotNull(commissioningResponse);
173         assertNull(commissioningResponse.getErrorDetails());
174         // Response should return the number of node templates present in the service template
175         assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(11);
176         assertNotNull(serviceTemplateCreate);
177         for (var nodeTemplateName : serviceTemplateCreate.getToscaTopologyTemplate().getNodeTemplates().keySet()) {
178             assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream()
179                 .anyMatch(ac -> ac.getName().equals(nodeTemplateName)));
180         }
181     }
182
183     private CommissioningResponse createServiceTemplate(ToscaServiceTemplate serviceTemplateCreate,
184                                                         Response.Status statusExpected) {
185         var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT);
186         try (var resp = invocationBuilder.post(Entity.json(serviceTemplateCreate))) {
187             assertEquals(statusExpected.getStatusCode(), resp.getStatus());
188             return resp.readEntity(CommissioningResponse.class);
189         }
190     }
191
192     @Test
193     void testUpdate() {
194         var toscaDataType = new ToscaDataType();
195         toscaDataType.setName("org.onap.datatypes.policy.clamp.Configuration");
196         toscaDataType.setDerivedFrom("tosca.datatypes.Root");
197         toscaDataType.setProperties(new HashMap<>());
198         var toscaProperty = new ToscaProperty();
199         toscaProperty.setName("configurationEntityId");
200         toscaProperty.setType("onap.datatypes.ToscaConceptIdentifier");
201         toscaDataType.getProperties().put(toscaProperty.getName(), toscaProperty);
202
203         var compositionId = createEntryInDB("forUpdate");
204         var serviceTemplateUpdate = new ToscaServiceTemplate(serviceTemplate);
205         serviceTemplateUpdate.getDataTypes().put(toscaDataType.getName(), toscaDataType);
206         serviceTemplateUpdate.setMetadata(Map.of("compositionId", compositionId));
207
208         var commissioningResponse = createServiceTemplate(serviceTemplateUpdate, Response.Status.OK);
209         assertNotNull(commissioningResponse);
210         assertNull(commissioningResponse.getErrorDetails());
211         // Response should return the number of node templates present in the service template
212         assertThat(commissioningResponse.getAffectedAutomationCompositionDefinitions()).hasSize(7);
213         for (var nodeTemplateName : serviceTemplateUpdate.getToscaTopologyTemplate().getNodeTemplates().keySet()) {
214             assertTrue(commissioningResponse.getAffectedAutomationCompositionDefinitions().stream()
215                 .anyMatch(ac -> ac.getName().equals(nodeTemplateName)));
216         }
217
218         var entity = getServiceTemplate(COMMISSIONING_ENDPOINT + "/" + compositionId);
219         assertThat(entity.getServiceTemplate().getDataTypes()).containsKey(toscaDataType.getName());
220     }
221
222     private AutomationCompositionDefinition getServiceTemplate(String url) {
223         var invocationBuilder = super.sendRequest(url);
224         try (var resp = invocationBuilder.buildGet().invoke()) {
225             assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus());
226             return resp.readEntity(AutomationCompositionDefinition.class);
227         }
228     }
229
230     @Test
231     void testQuery_NoResultWithThisName() {
232         var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name=noResultWithThisName");
233         try (var rawresp = invocationBuilder.buildGet().invoke()) {
234             assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
235             var entityList = rawresp.readEntity(ToscaServiceTemplate.class);
236             assertThat(entityList.getNodeTypes()).isNull();
237         }
238     }
239
240     @Test
241     void testQuery() {
242         createEntryInDB("forQuery");
243
244         var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT);
245         try (var rawresp = invocationBuilder.buildGet().invoke()) {
246             assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
247             var entityList = rawresp.readEntity(ToscaServiceTemplates.class);
248             assertNotNull(entityList);
249             assertThat(entityList.getServiceTemplates()).isNotEmpty();
250         }
251     }
252
253     @Test
254     void testQueryPageable() {
255         for (var i = 0; i < NUMBER_COMPOSITIONS; i++) {
256             createEntryInDB("queryPageable" + i);
257         }
258         // filter by name with wrong name
259         validateQueryPageable("?name=wrongName", 0);
260
261         // filter by name
262         validateQueryPageable("?name=queryPageable1", 1);
263
264         // page=1 and size=5
265         validateQueryPageable("?page=1&size=5", 5);
266
267         // not pageable
268         validateQueryNotPageable("?size=4");
269         validateQueryNotPageable("?page=2");
270         validateQueryNotPageable("");
271     }
272
273     private void validateQueryNotPageable(String parameters) {
274         var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + parameters);
275         try (var response = invocationBuilder.buildGet().invoke()) {
276             assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
277             var entityList = response.readEntity(ToscaServiceTemplates.class);
278             assertThat(entityList.getServiceTemplates()).hasSizeGreaterThanOrEqualTo(NUMBER_COMPOSITIONS);
279         }
280     }
281
282     private void validateQueryPageable(String parameters, int size) {
283         var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + parameters);
284         try (var response = invocationBuilder.buildGet().invoke()) {
285             assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
286             var entityList = response.readEntity(ToscaServiceTemplates.class);
287             assertThat(entityList.getServiceTemplates()).hasSize(size);
288         }
289     }
290
291     @Test
292     void testDeleteBadRequest() {
293         createEntryInDB("DeleteBadRequest");
294         deleteServiceTemplate(COMMISSIONING_ENDPOINT + "/" + UUID.randomUUID(), Response.Status.NOT_FOUND);
295     }
296
297     private void deleteServiceTemplate(String url, Response.Status statusExpected) {
298         var invocationBuilder = super.sendRequest(url);
299         try (var resp = invocationBuilder.delete()) {
300             assertEquals(statusExpected.getStatusCode(), resp.getStatus());
301         }
302     }
303
304     @Test
305     void testDelete() {
306         var compositionId = createEntryInDB("forDelete");
307         deleteServiceTemplate(COMMISSIONING_ENDPOINT + "/" + compositionId, Response.Status.OK);
308
309         var templatesInDB = acDefinitionProvider.findAcDefinition(compositionId);
310         assertThat(templatesInDB).isEmpty();
311     }
312
313     @Test
314     void testPrime() {
315         var compositionId = createEntryInDB("Prime");
316         var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/" + compositionId);
317
318         var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate,
319             "org.onap.policy.clamp.acm.AutomationCompositionElement");
320         for (var elementEntry : acElements) {
321             var participant = CommonTestData.createParticipant(UUID.randomUUID());
322             var supportedElementType = new ParticipantSupportedElementType();
323             supportedElementType.setTypeName(elementEntry.getValue().getType());
324             supportedElementType.setTypeVersion(elementEntry.getValue().getTypeVersion());
325             participant.getParticipantSupportedElementTypes().put(supportedElementType.getId(), supportedElementType);
326             var replica = CommonTestData.createParticipantReplica(UUID.randomUUID());
327             participant.getReplicas().put(replica.getReplicaId(), replica);
328             participantProvider.saveParticipant(participant);
329         }
330
331         var body = new AcTypeStateUpdate();
332         body.setPrimeOrder(PrimeOrder.PRIME);
333         try (var resp = invocationBuilder.put(Entity.json(body))) {
334             assertEquals(Response.Status.ACCEPTED.getStatusCode(), resp.getStatus());
335         }
336     }
337
338     @Test
339     void testPrimeBadRequest() {
340         var compositionId = createEntryInDB("Prime");
341         var invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/" + compositionId);
342
343         var acElements = AcmUtils.extractAcElementsFromServiceTemplate(serviceTemplate,
344                 "org.onap.policy.clamp.acm.AutomationCompositionElement");
345         for (var elementEntry : acElements) {
346             var participant = CommonTestData.createParticipant(UUID.randomUUID());
347             var supportedElementType = new ParticipantSupportedElementType();
348             supportedElementType.setTypeName(elementEntry.getValue().getType());
349             supportedElementType.setTypeVersion(elementEntry.getValue().getTypeVersion());
350             participant.getParticipantSupportedElementTypes().put(supportedElementType.getId(), supportedElementType);
351             participantProvider.saveParticipant(participant);
352         }
353
354         var body = new AcTypeStateUpdate();
355         body.setPrimeOrder(PrimeOrder.PRIME);
356         try (var resp = invocationBuilder.put(Entity.json(body))) {
357             assertEquals(Response.Status.CONFLICT.getStatusCode(), resp.getStatus());
358         }
359     }
360
361     private UUID createEntryInDB(String name) {
362         var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate);
363         serviceTemplateCreate.setName(name);
364         var acmDefinition = acDefinitionProvider
365             .createAutomationCompositionDefinition(serviceTemplateCreate, CommonTestData.TOSCA_ELEMENT_NAME,
366                 CommonTestData.TOSCA_COMP_NAME);
367
368         return acmDefinition.getCompositionId();
369     }
370
371 }