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