c5683e8b24d6fe710a235b949f3fb44aff5f4d84
[so/adapters/so-cnf-adapter.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2023 Nordix Foundation.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20 package org.onap.so.cnfm.lcm.bpmn.flows.tasks;
21
22 import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
23 import static com.github.tomakehurst.wiremock.client.WireMock.get;
24 import static com.github.tomakehurst.wiremock.client.WireMock.notFound;
25 import static com.github.tomakehurst.wiremock.client.WireMock.ok;
26 import static com.github.tomakehurst.wiremock.client.WireMock.okJson;
27 import static com.github.tomakehurst.wiremock.client.WireMock.put;
28 import static com.github.tomakehurst.wiremock.client.WireMock.serverError;
29 import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
30 import static org.junit.Assert.assertEquals;
31 import static org.junit.Assert.assertFalse;
32 import static org.junit.Assert.assertNotNull;
33 import static org.junit.Assert.assertNull;
34 import static org.junit.Assert.assertTrue;
35 import static org.onap.aaiclient.client.aai.AAIVersion.V19;
36 import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.CREATE_AS_RESPONSE_PARAM_NAME;
37 import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.CLOUD_OWNER_PARAM_KEY;
38 import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.CLOUD_REGION_PARAM_KEY;
39 import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.RESOURCE_ID_KEY;
40 import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.SERVICE_INSTANCE_ID_PARAM_KEY;
41 import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.SERVICE_INSTANCE_NAME_PARAM_KEY;
42 import static org.onap.so.cnfm.lcm.model.utils.AdditionalParamsConstants.TENANT_ID_PARAM_KEY;
43 import static org.springframework.http.HttpHeaders.ACCEPT;
44 import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
45 import java.io.File;
46 import java.io.IOException;
47 import java.nio.file.Files;
48 import java.nio.file.Path;
49 import java.time.LocalDateTime;
50 import java.util.Map;
51 import java.util.Optional;
52 import java.util.UUID;
53 import org.camunda.bpm.engine.history.HistoricProcessInstance;
54 import org.camunda.bpm.engine.history.HistoricVariableInstance;
55 import org.junit.After;
56 import org.junit.Before;
57 import org.junit.Test;
58 import org.onap.aaiclient.client.aai.entities.Results;
59 import org.onap.aaiclient.client.graphinventory.entities.Resource;
60 import org.onap.so.cnfm.lcm.bpmn.flows.BaseTest;
61 import org.onap.so.cnfm.lcm.bpmn.flows.exceptions.AsRequestProcessingException;
62 import org.onap.so.cnfm.lcm.bpmn.flows.service.JobExecutorService;
63 import org.onap.so.cnfm.lcm.bpmn.flows.service.WorkflowQueryService;
64 import org.onap.so.cnfm.lcm.database.beans.AsInst;
65 import org.onap.so.cnfm.lcm.database.beans.Job;
66 import org.onap.so.cnfm.lcm.database.beans.JobStatusEnum;
67 import org.onap.so.cnfm.lcm.database.beans.State;
68 import org.onap.so.cnfm.lcm.model.AsInstance;
69 import org.onap.so.cnfm.lcm.model.AsInstance.InstantiationStateEnum;
70 import org.onap.so.cnfm.lcm.model.CreateAsRequest;
71 import org.onap.so.cnfm.lcm.model.ErrorDetails;
72 import org.springframework.beans.factory.annotation.Autowired;
73 import org.springframework.http.HttpStatus;
74 import com.fasterxml.jackson.core.JsonProcessingException;
75 import com.fasterxml.jackson.databind.ObjectMapper;
76
77 /**
78  * @author Waqas Ikram (waqas.ikram@est.tech)
79  *
80  */
81 public class CreateAsTaskTest extends BaseTest {
82     private static final String DUMMY_VALUE = "DUMMY_VALUE";
83     private static final String SRC_TEST_DIR = "src/test/resources";
84     private static final String TENAT_ID = UUID.randomUUID().toString();
85     private static final String CLOUD_OWNER = "CloudOwner";
86     private static final String CLOUD_REGION = "CloudRegion";
87     private static final String ASD_ID = UUID.randomUUID().toString();
88     private static final String AS_NAME = "CreateAsService-" + ASD_ID;
89     private static final String RESOURCE_ASD_PACKAGE_CSAR_PATH =
90             SRC_TEST_DIR + "/resource-Generatedasdpackage-csar.csar";
91
92     @Autowired
93     private JobExecutorService objUnderTest;
94
95     @Autowired
96     private WorkflowQueryService workflowQueryService;
97
98     @Before
99     public void before() {
100         wireMockServer.resetAll();
101     }
102
103     @After
104     public void after() {
105         wireMockServer.resetAll();
106     }
107
108     @Test
109     public void testCreateAsWorkflow_SuccessfullCase() throws InterruptedException, IOException {
110
111         mockSdcResourceEndpoint(ASD_ID);
112
113         final CreateAsRequest createAsRequest = getCreateAsRequest();
114
115         mockAAIEndpoints();
116
117         final AsInstance nsResponse = objUnderTest.runCreateAsJob(createAsRequest);
118         assertNotNull(nsResponse);
119         assertNotNull(nsResponse.getAsInstanceid());
120
121         final Optional<Job> optional = getJobByResourceId(createAsRequest.getAsdId());
122         assertTrue(optional.isPresent());
123         final Job job = optional.get();
124
125         assertTrue(waitForProcessInstanceToFinish(job.getProcessInstanceId()));
126
127         final HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(job.getProcessInstanceId());
128         assertNotNull(historicProcessInstance);
129
130         assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
131         assertTrue(databaseServiceProvider.isAsInstExists(createAsRequest.getAsInstanceName()));
132
133         final Job actualJob = optional.get();
134         assertEquals(JobStatusEnum.FINISHED, actualJob.getStatus());
135
136         assertEquals(AS_NAME, nsResponse.getAsInstanceName());
137         assertEquals(InstantiationStateEnum.NOT_INSTANTIATED, nsResponse.getInstantiationState());
138
139         final HistoricVariableInstance doesNsPackageExistsVar =
140                 getVariable(job.getProcessInstanceId(), "doesAsPackageExists");
141         assertNotNull(doesNsPackageExistsVar);
142         assertTrue((boolean) doesNsPackageExistsVar.getValue());
143
144         final HistoricVariableInstance doesNsInstanceExistsVar =
145                 getVariable(job.getProcessInstanceId(), "doesAsInstanceExists");
146         assertNotNull(doesNsInstanceExistsVar);
147         assertFalse((boolean) doesNsInstanceExistsVar.getValue());
148
149     }
150
151     @Test
152     public void testCreateAsWorkflow_FailsToGetAsPackage() throws InterruptedException {
153         final String asdId = UUID.randomUUID().toString();
154         final String asName = AS_NAME + "-" + System.currentTimeMillis();
155
156         final CreateAsRequest createAsRequest = getCreateAsRequest(asdId, asName);
157
158         wireMockServer.stubFor(
159                 get(getSdcResourceUrl(asdId)).willReturn(aResponse().withStatus(HttpStatus.NOT_FOUND.value())));
160         try {
161             objUnderTest.runCreateAsJob(createAsRequest);
162         } catch (final Exception exception) {
163             assertEquals(AsRequestProcessingException.class, exception.getClass());
164         }
165
166         final Optional<Job> optional = getJobByResourceId(createAsRequest.getAsdId());
167         assertTrue(optional.isPresent());
168         final Job job = optional.get();
169
170         assertTrue(waitForProcessInstanceToFinish(job.getProcessInstanceId()));
171
172         final HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(job.getProcessInstanceId());
173         assertNotNull(historicProcessInstance);
174
175         assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
176
177         final HistoricVariableInstance nsResponseVariable =
178                 getVariable(job.getProcessInstanceId(), CREATE_AS_RESPONSE_PARAM_NAME);
179         assertNull(nsResponseVariable);
180
181         final Optional<ErrorDetails> errorDetailsOptional =
182                 workflowQueryService.getErrorDetails(job.getProcessInstanceId());
183         assertTrue(errorDetailsOptional.isPresent());
184
185         final ErrorDetails errorDetails = errorDetailsOptional.get();
186         assertNotNull(errorDetails);
187         assertNotNull(errorDetails.getDetail());
188
189         final HistoricVariableInstance doesAsPackageExistsVar =
190                 getVariable(job.getProcessInstanceId(), "doesAsPackageExists");
191         assertNotNull(doesAsPackageExistsVar);
192         assertFalse((boolean) doesAsPackageExistsVar.getValue());
193
194     }
195
196     @Test
197     public void testCreateAsWorkflow_AsInstanceExistsInDb() throws IOException, InterruptedException {
198         final String asdId = UUID.randomUUID().toString();
199         final String asName = AS_NAME + "-" + System.currentTimeMillis();
200
201         mockSdcResourceEndpoint(asdId);
202
203         final CreateAsRequest createAsRequest = getCreateAsRequest(asdId, asName);
204
205         databaseServiceProvider.saveAsInst(new AsInst().asdId(asdId).name(createAsRequest.getAsInstanceName())
206                 .asPackageId(UUID.randomUUID().toString()).asdInvariantId(asdId).asProvider(DUMMY_VALUE)
207                 .asApplicationName(DUMMY_VALUE).asApplicationVersion(DUMMY_VALUE).serviceInstanceId(DUMMY_VALUE)
208                 .serviceInstanceName(DUMMY_VALUE).cloudOwner(DUMMY_VALUE).cloudRegion(DUMMY_VALUE).tenantId(DUMMY_VALUE)
209                 .status(State.INSTANTIATED).statusUpdatedTime(LocalDateTime.now()));
210
211         try {
212             objUnderTest.runCreateAsJob(createAsRequest);
213         } catch (final Exception exception) {
214             assertEquals(AsRequestProcessingException.class, exception.getClass());
215         }
216
217         final Optional<Job> optional = getJobByResourceId(createAsRequest.getAsdId());
218         assertTrue(optional.isPresent());
219         final Job job = optional.get();
220         assertEquals(JobStatusEnum.ERROR, job.getStatus());
221
222         assertTrue(waitForProcessInstanceToFinish(job.getProcessInstanceId()));
223
224         final HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(job.getProcessInstanceId());
225         assertNotNull(historicProcessInstance);
226         assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
227
228         assertTrue(databaseServiceProvider.isAsInstExists(createAsRequest.getAsInstanceName()));
229
230         final Optional<ErrorDetails> errorDetailsOptional =
231                 workflowQueryService.getErrorDetails(job.getProcessInstanceId());
232         assertTrue(errorDetailsOptional.isPresent());
233
234         final ErrorDetails errorDetails = errorDetailsOptional.get();
235         assertNotNull(errorDetails);
236         assertNotNull(errorDetails.getDetail());
237
238         final HistoricVariableInstance doesAsInstanceExistsVar =
239                 getVariable(job.getProcessInstanceId(), "doesAsInstanceExists");
240         assertNotNull(doesAsInstanceExistsVar);
241         assertTrue((boolean) doesAsInstanceExistsVar.getValue());
242
243     }
244
245     @Test
246     public void testCreateAsWorkflow_FailToCreateResouceInAai() throws InterruptedException, IOException {
247         final String asdId = UUID.randomUUID().toString();
248         final String asName = AS_NAME + "-" + System.currentTimeMillis();
249         final String resourceId = UUID.randomUUID().toString();
250
251         mockSdcResourceEndpoint(asdId);
252
253         final CreateAsRequest createAsRequest = getCreateAsRequest(asdId, asName, resourceId);
254
255
256         final String modelEndpoint = "/aai/" + V19 + "/network/generic-vnfs/generic-vnf/" + resourceId;
257         wireMockServer.stubFor(
258                 get(urlMatching(modelEndpoint + "\\?resultIndex=0&resultSize=1&format=count")).willReturn(notFound()));
259         wireMockServer.stubFor(put(urlMatching(modelEndpoint)).willReturn(serverError()));
260
261         try {
262             objUnderTest.runCreateAsJob(createAsRequest);
263         } catch (final Exception exception) {
264             assertEquals(AsRequestProcessingException.class, exception.getClass());
265         }
266
267         final Optional<Job> optional = getJobByResourceId(createAsRequest.getAsdId());
268         assertTrue(optional.isPresent());
269         final Job job = optional.get();
270
271         assertTrue(waitForProcessInstanceToFinish(job.getProcessInstanceId()));
272
273         final HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(job.getProcessInstanceId());
274         assertNotNull(historicProcessInstance);
275
276         assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
277         assertTrue(databaseServiceProvider.isAsInstExists(createAsRequest.getAsInstanceName()));
278
279         final Optional<ErrorDetails> errorDetailsOptional =
280                 workflowQueryService.getErrorDetails(job.getProcessInstanceId());
281         assertTrue(errorDetailsOptional.isPresent());
282
283         final ErrorDetails errorDetails = errorDetailsOptional.get();
284         assertNotNull(errorDetails);
285         assertNotNull(errorDetails.getDetail());
286
287     }
288
289     private void mockSdcResourceEndpoint(final String asdId) throws IOException {
290         wireMockServer.stubFor(get(getSdcResourceUrl(asdId))
291                 .willReturn(aResponse().withBody(getFileContent(getAbsolutePath(RESOURCE_ASD_PACKAGE_CSAR_PATH)))
292                         .withHeader(ACCEPT, APPLICATION_OCTET_STREAM_VALUE)));
293     }
294
295     private CreateAsRequest getCreateAsRequest() {
296         return getCreateAsRequest(ASD_ID, AS_NAME);
297     }
298
299     private String getSdcResourceUrl(final String asdId) {
300         return "/sdc/v1/catalog/resources/" + asdId + "/toscaModel";
301     }
302
303     private CreateAsRequest getCreateAsRequest(final String asdId, final String asName) {
304         final Map<String, Object> additionalParams = Map.of(SERVICE_INSTANCE_ID_PARAM_KEY, SERVICE_INSTANCE_ID,
305                 SERVICE_INSTANCE_NAME_PARAM_KEY, SERVICE_INSTANCE_NAME, CLOUD_OWNER_PARAM_KEY, CLOUD_OWNER,
306                 CLOUD_REGION_PARAM_KEY, CLOUD_REGION, TENANT_ID_PARAM_KEY, TENAT_ID);
307
308         return getCreateAsRequest(asdId, asName, additionalParams);
309     }
310
311     private CreateAsRequest getCreateAsRequest(final String asdId, final String asName, final String resourceId) {
312         final Map<String, Object> additionalParams = Map.of(SERVICE_INSTANCE_ID_PARAM_KEY, SERVICE_INSTANCE_ID,
313                 SERVICE_INSTANCE_NAME_PARAM_KEY, SERVICE_INSTANCE_NAME, CLOUD_OWNER_PARAM_KEY, CLOUD_OWNER,
314                 CLOUD_REGION_PARAM_KEY, CLOUD_REGION, TENANT_ID_PARAM_KEY, TENAT_ID, RESOURCE_ID_KEY, resourceId);
315
316         return getCreateAsRequest(asdId, asName, additionalParams);
317     }
318
319     private CreateAsRequest getCreateAsRequest(final String asdId, final String asName,
320             final Map<String, Object> additionalParams) {
321         return new CreateAsRequest().asdId(asdId).asInstanceName(asName).additionalParams(additionalParams);
322     }
323
324     private void mockAAIEndpoints() throws JsonProcessingException {
325         final String modelEndpoint = "/aai/" + V19 + "/network/generic-vnfs/generic-vnf/" + UUID_REGEX;
326
327         wireMockServer.stubFor(
328                 get(urlMatching(modelEndpoint + "\\?resultIndex=0&resultSize=1&format=count")).willReturn(notFound()));
329
330         wireMockServer.stubFor(put(urlMatching(modelEndpoint)).willReturn(ok()));
331         wireMockServer.stubFor(put(urlMatching(modelEndpoint + "/relationship-list/relationship")).willReturn(ok()));
332
333         wireMockServer.stubFor(get(urlMatching(modelEndpoint)).willReturn(ok())
334                 .willReturn(okJson("{\"orchestration-status\": \"Created\"}")));
335
336         wireMockServer.stubFor(get(urlMatching("/aai/" + V19 + "/nodes/service-instances/service-instance/.*"))
337                 .willReturn(okJson(getResourceResultsResponseAsJson(SERVICE_INSTANCE_ID))));
338
339         wireMockServer.stubFor(put(urlMatching("/aai/" + V19 + "/cloud-infrastructure/cloud-regions/cloud-region/"
340                 + CLOUD_OWNER + "/" + CLOUD_REGION + "/tenants/tenant/" + TENAT_ID + "/relationship-list/relationship"))
341                         .willReturn(ok()));
342
343     }
344
345     private String getResourceResultsResponseAsJson(final String nsdId) throws JsonProcessingException {
346         final Resource resource = new Resource();
347         resource.setResourceType("service-instance");
348         resource.setResourceLink("/aai/" + V19 + "/business/customers/customer/GLOBAL_CUSTOMER_ID"
349                 + "/service-subscriptions/service-subscription/NetworkService/service-instances/service-instance/"
350                 + nsdId);
351         final Results<Resource> results = new Results<>();
352         results.getResult().add(resource);
353         return new ObjectMapper().writeValueAsString(results);
354     }
355
356     private Path getAbsolutePath(final String path) {
357         final File file = new File(path);
358         return file.toPath();
359     }
360
361     private byte[] getFileContent(final Path path) throws IOException {
362         return Files.readAllBytes(path);
363     }
364 }