2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.vid.job.impl;
23 import com.fasterxml.jackson.databind.JsonNode;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.ImmutableMap;
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.commons.lang3.mutable.MutableInt;
28 import org.jetbrains.annotations.NotNull;
29 import org.mockito.ArgumentCaptor;
30 import org.mockito.Mockito;
31 import org.mockito.hamcrest.MockitoHamcrest;
32 import org.onap.portalsdk.core.service.DataAccessService;
33 import org.onap.portalsdk.core.util.SystemProperties;
34 import org.onap.vid.asdc.AsdcCatalogException;
35 import org.onap.vid.changeManagement.RequestDetailsWrapper;
36 import org.onap.vid.job.Job;
37 import org.onap.vid.job.Job.JobStatus;
38 import org.onap.vid.job.JobType;
39 import org.onap.vid.job.JobsBrokerService;
40 import org.onap.vid.job.command.CommandUtils;
41 import org.onap.vid.job.command.InternalState;
42 import org.onap.vid.model.*;
43 import org.onap.vid.model.serviceInstantiation.BaseResource;
44 import org.onap.vid.model.serviceInstantiation.InstanceGroup;
45 import org.onap.vid.model.serviceInstantiation.ServiceInstantiation;
46 import org.onap.vid.mso.RestMsoImplementation;
47 import org.onap.vid.mso.RestObject;
48 import org.onap.vid.mso.model.RequestReferences;
49 import org.onap.vid.mso.rest.AsyncRequestStatus;
50 import org.onap.vid.mso.rest.AsyncRequestStatusList;
51 import org.onap.vid.properties.Features;
52 import org.onap.vid.services.AsyncInstantiationBusinessLogic;
53 import org.onap.vid.services.AuditService;
54 import org.onap.vid.services.VersionService;
55 import org.onap.vid.utils.DaoUtils;
56 import org.onap.vid.config.DataSourceConfig;
57 import org.onap.vid.config.JobCommandsConfigWithMockedMso;
58 import org.onap.vid.config.MockedAaiClientAndFeatureManagerConfig;
59 import org.onap.vid.services.AsyncInstantiationBaseTest;
60 import org.onap.vid.testUtils.TestUtils;
61 import org.springframework.http.HttpMethod;
62 import org.springframework.test.context.ContextConfiguration;
63 import org.testng.annotations.BeforeClass;
64 import org.testng.annotations.BeforeMethod;
65 import org.testng.annotations.DataProvider;
66 import org.testng.annotations.Test;
67 import org.togglz.core.manager.FeatureManager;
69 import javax.inject.Inject;
70 import javax.ws.rs.ProcessingException;
71 import java.io.IOException;
72 import java.lang.reflect.Method;
74 import java.util.function.BiConsumer;
75 import java.util.function.Supplier;
76 import java.util.stream.Collectors;
77 import java.util.stream.IntStream;
78 import java.util.stream.Stream;
80 import static java.util.stream.Collectors.*;
81 import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
82 import static net.javacrumbs.jsonunit.JsonMatchers.*;
83 import static org.hamcrest.CoreMatchers.*;
84 import static org.hamcrest.MatcherAssert.assertThat;
85 import static org.hamcrest.Matchers.hasProperty;
86 import static org.hamcrest.Matchers.hasSize;
87 import static org.hamcrest.core.Every.everyItem;
88 import static org.mockito.ArgumentMatchers.any;
89 import static org.mockito.ArgumentMatchers.endsWith;
90 import static org.mockito.ArgumentMatchers.*;
91 import static org.mockito.Mockito.*;
92 import static org.onap.vid.job.Job.JobStatus.*;
93 import static org.onap.vid.job.impl.JobSchedulerInitializer.WORKERS_TOPICS;
94 import static org.onap.vid.model.JobAuditStatus.SourceStatus.VID;
95 import static org.testng.AssertJUnit.*;
97 //it's more like integration test than UT
98 //But it's very hard to test in API test so I use UT
99 @ContextConfiguration(classes = {DataSourceConfig.class, SystemProperties.class, MockedAaiClientAndFeatureManagerConfig.class, JobCommandsConfigWithMockedMso.class})
100 public class AsyncInstantiationIntegrationTest extends AsyncInstantiationBaseTest {
102 private static final String FAILED_STR = "FAILED";
103 private static final String COMPLETE_STR = "COMPLETE";
104 private static final String IN_PROGRESS_STR = "IN_PROGRESS";
105 private static final String REQUESTED = "REQUESTED";
106 private static final String PENDING_MANUAL_TASK = "PENDING_MANUAL_TASK";
107 public static final String RAW_DATA_FROM_MSO = "RAW DATA FROM MSO";
108 private static String USER_ID = "123";
109 public static String REQUEST_ID = UUID.randomUUID().toString();
110 public static String SERVICE_INSTANCE_ID = UUID.randomUUID().toString();
113 private VersionService versionService;
116 private JobsBrokerService jobsBrokerService;
119 private JobWorker jobWorker;
122 private FeatureManager featureManager;
125 private AsyncInstantiationBusinessLogic asyncInstantiationBL;
128 private AuditService auditService;
131 private RestMsoImplementation restMso;
134 private DataAccessService dataAccessService;
137 private CommandUtils commandUtils;
140 void initServicesInfoService() {
141 createInstanceParamsMaps();
142 when(versionService.retrieveBuildNumber()).thenReturn("fakeBuild");
147 dataAccessService.deleteDomainObjects(ServiceInfo.class, "1=1", DaoUtils.getPropsMap());
148 dataAccessService.deleteDomainObjects(JobDaoImpl.class, "1=1", DaoUtils.getPropsMap());
149 dataAccessService.deleteDomainObjects(NameCounter.class, "1=1", DaoUtils.getPropsMap());
154 Mockito.reset(restMso);
155 Mockito.reset(aaiClient);
156 mockAaiClientAnyNameFree();
160 public void whenPushNewBulk_thenAllServicesAreInPending() {
163 List<ServiceInfo> serviceInfoList = asyncInstantiationBL.getAllServicesInfo();
164 assertThat( serviceInfoList, everyItem(hasProperty("jobStatus", is(PENDING))));
167 private List<UUID> pushMacroBulk() {
168 ServiceInstantiation serviceInstantiation = generateMockMacroServiceInstantiationPayload(false,
169 createVnfList(instanceParamsMapWithoutParams, Collections.EMPTY_LIST, true),
170 3, true,PROJECT_NAME, true);
171 return asyncInstantiationBL.pushBulkJob(serviceInstantiation, USER_ID);
174 private UUID pushALaCarteWithVnf() {
175 ServiceInstantiation serviceInstantiation = generateALaCarteWithVnfsServiceInstantiationPayload();
176 List<UUID> uuids = asyncInstantiationBL.pushBulkJob(serviceInstantiation, USER_ID);
177 assertThat(uuids, hasSize(1));
181 private UUID pushALaCarteUpdateWithGroups() {
182 ServiceInstantiation serviceInstantiation = generateALaCarteUpdateWith1ExistingGroup2NewGroupsPayload();
183 List<UUID> uuids = asyncInstantiationBL.pushBulkJob(serviceInstantiation, USER_ID);
184 assertThat(uuids, hasSize(1));
188 public static RestObject<RequestReferencesContainer> createResponse(int statusCode) {
189 return createResponse(statusCode, SERVICE_INSTANCE_ID, REQUEST_ID);
192 public static RestObject<RequestReferencesContainer> createResponseRandomIds(int statusCode) {
193 return createResponse(statusCode, UUID.randomUUID().toString(), UUID.randomUUID().toString());
196 public static RestObject<RequestReferencesContainer> createResponse(int statusCode, String instanceId, String requestId) {
197 RequestReferences requestReferences = new RequestReferences();
198 requestReferences.setRequestId(requestId);
199 requestReferences.setInstanceId(instanceId);
200 RestObject<RequestReferencesContainer> restObject = new RestObject<>();
201 restObject.set(new RequestReferencesContainer(requestReferences));
202 restObject.setStatusCode(statusCode);
203 restObject.setRaw(RAW_DATA_FROM_MSO);
207 ImmutableList<String> statusesToStrings(JobStatus... jobStatuses) {
208 return Stream.of(jobStatuses).map(
209 Enum::toString).collect(ImmutableList.toImmutableList());
213 Make sure service state is in progress once request has sent to MSO
214 Make sure service state is in progress once request has sent to MSO and MSO status is in_progress
215 Make sure service state is Failed once we got from MSO failure state, and that job's are not collected any more.
216 Make sure service state is Completed successfully once we got from MSO complete, and that next job is peeked.
217 Once a service in the bulk is failed, other services moved to Stopped, and no other jobs from the bulk are peeked.
220 public void testStatusesOfMacroServiceInBulkDuringBulkLifeCycle() {
222 final String SERVICE_REQUEST_ID = UUID.randomUUID().toString();
223 final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString();
224 final String SERVICE2_REQUEST_ID = UUID.randomUUID().toString();
225 final String SERVICE2_INSTANCE_ID = UUID.randomUUID().toString();
227 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty())))
228 .thenReturn(createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID));
230 ImmutableList<ImmutableList<String>> expectedStatusesForVid = ImmutableList.of(
231 statusesToStrings(PENDING, IN_PROGRESS, COMPLETED),
232 statusesToStrings(PENDING, IN_PROGRESS, FAILED),
233 statusesToStrings(PENDING, STOPPED)
236 ImmutableList<ImmutableList<String>> expectedStatusesForMso = ImmutableList.of(
237 ImmutableList.of(REQUESTED, IN_PROGRESS_STR, "not a state", FAILED_STR ,COMPLETE_STR),
238 ImmutableList.of(REQUESTED, FAILED_STR),
242 List<UUID> uuids = pushMacroBulk();
243 UUID firstJobUuid = uuids.get(0);
244 UUID secondJobUuid = uuids.get(1);
245 //assert that when get ProcessingException from restMso, status remain the same
246 when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenThrow(new ProcessingException("fake message"));
247 processJobsCountTimesAndAssertStatus(firstJobUuid, 10, IN_PROGRESS, PENDING);
249 //assert that when get IN_PROGRESS status from restMso, status remain IN_PROGRESS
250 when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR));
251 processJobsCountTimesAndAssertStatus(firstJobUuid, 10, IN_PROGRESS, PENDING);
253 //assert that when get unrecognized status from restMso, status remain IN_PROGRESS
254 when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject("not a state"));
255 processJobsCountTimesAndAssertStatus(firstJobUuid, 10, IN_PROGRESS, PENDING);
257 //assert that when get non 200 status code during IN_PROGRESS, status remain IN_PROGRESS
258 when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR, 404));
259 processJobsCountTimesAndAssertStatus(firstJobUuid, 10, IN_PROGRESS, PENDING);
261 //when get job COMPLETE from MSO, service status become COMPLETED
262 when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
263 pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, COMPLETED);
264 List<ServiceInfo> serviceInfoList = listServicesAndAssertStatus(COMPLETED, PENDING, firstJobUuid);
267 //for use later in the test
268 Map<UUID, JobStatus> expectedJobStatusMap = serviceInfoList.stream().collect(
269 Collectors.toMap(ServiceInfo::getJobId, x-> PENDING));
270 expectedJobStatusMap.put(firstJobUuid, COMPLETED);
272 //when handling another PENDING job, statuses are : COMPLETED, IN_PROGRESS, PENDING
273 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty())))
274 .thenReturn(createResponse(200, SERVICE2_INSTANCE_ID, SERVICE2_REQUEST_ID));
275 when(restMso.GetForObject(endsWith(SERVICE2_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR));
276 processJobsCountTimes(10);
278 expectedJobStatusMap.put(secondJobUuid, JobStatus.IN_PROGRESS);
279 listServicesAndAssertStatus(expectedJobStatusMap);
282 //when get FAILED status from MSO statuses are : COMPLETED, FAILED, STOPPED
283 when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).thenReturn(asyncRequestStatusResponseAsRestObject(FAILED_STR));
284 pullJobProcessAndPushBack(JobStatus.IN_PROGRESS, JobStatus.FAILED);
285 expectedJobStatusMap.put(secondJobUuid, JobStatus.FAILED);
286 expectedJobStatusMap = expectedJobStatusMap.entrySet().stream().collect(Collectors.toMap(
287 e -> e.getKey(), e -> e.getValue() == PENDING ? JobStatus.STOPPED : e.getValue()
290 listServicesAndAssertStatus(expectedJobStatusMap);
291 IntStream.range(0, uuids.size()).forEach(i -> {
292 UUID uuid = uuids.get(i);
293 List<String> vidStatuses = auditService.getAuditStatuses(uuid, VID).stream().map(x -> x.getJobStatus()).collect(Collectors.toList());
294 assertThat(vidStatuses, is(expectedStatusesForVid.get(i)));
297 //assert no more jobs to pull
298 assertFalse(jobsBrokerService.pull(PENDING, randomUuid()).isPresent());
299 assertFalse(jobsBrokerService.pull(JobStatus.IN_PROGRESS, randomUuid()).isPresent());
304 public static Object[][] AlaCarteStatuses(Method test) {
305 return new Object[][]{
306 {COMPLETE_STR, JobStatus.COMPLETED},
307 {FAILED_STR, JobStatus.COMPLETED_WITH_ERRORS},
312 Make sure service state is in progress once request has sent to MSO
313 Make sure service state is watching until state changes to complemented
314 Make sure service state is watching until vnf state changes to completed
315 Make sure service state is Completed successfully once we got from MSO complete for the vnf job.
318 @Test(dataProvider = "AlaCarteStatuses")
319 public void testStatusesOfServiceDuringALaCarteLifeCycleIgnoringVfModules(String msoVnfStatus, JobStatus expectedServiceStatus) {
321 [v] + push alacarte with 1 vnf
322 [v] verify STATUS pending
323 [v] + pull+execute (should post to MSO)
324 [v] verify STATUS in progress
325 [v] + pull+execute (should GET completed from MSO)
326 [v] verify STATUS in progress; TYPE watching
327 [v] verify job#2 *new* VNF job STATUS creating
328 [v] + pull+execute job#2 (should post to MSO)
329 [v] verify job#2 STATUS resource in progress
330 [v] verify job#1 STATUS in progress
331 [v] + pull+execute job#2 (should GET completed from MSO)
332 [v] verify job#2 STATUS completed
333 [v] + pull+execute job#1
334 [v] verify job#1 STATUS completed
336 * not looking on audit (yet)
339 when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true);
340 when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(false);
341 final String SERVICE_REQUEST_ID = UUID.randomUUID().toString();
342 final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString();
343 final String VNF_REQUEST_ID = UUID.randomUUID().toString();
346 //push alacarte with 1 vnf, verify STATUS pending
347 UUID uuid = pushALaCarteWithVnf();
348 singleServicesAndAssertStatus(JobStatus.PENDING, uuid);
349 //mock mso to answer 200 of create service instance request, verify STATUS in progress
350 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith("serviceInstances"), any())).thenReturn(
351 createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID));
352 //mock mso to answer COMPLETE for service instance create, job status shall remain IN_PROGRESS and type shall be Watching
353 when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).
354 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
355 //mock mso to answer 200 of create vnf instance request, pull+execute vnf job, STATUS resource in progress
356 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), any())).thenReturn(
357 createResponse(200, UUID.randomUUID().toString(), VNF_REQUEST_ID));
358 when(restMso.GetForObject(endsWith(VNF_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(
359 asyncRequestStatusResponseAsRestObject(msoVnfStatus));
361 processJobsCountTimesAndAssertStatus(uuid, 100, expectedServiceStatus);
362 verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), eq("/serviceInstantiation/v7/serviceInstances"), any());
363 verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), any());
364 verify(restMso, times(2)).GetForObject(any(), any());
369 this test is almost duplication of testStatusesOfServiceDuringALaCarteLifeCycleIgnoringVfModules.
371 IgnoringVfModules test check the scenario while FLAG_ASYNC_ALACARTE_VFMODULE is off
372 WithVfModules test check the scenario while FLAG_ASYNC_ALACARTE_VFMODULE is on
374 We shall consider later to remove testStatusesOfServiceDuringALaCarteLifeCycleIgnoringVfModules
375 And union these tests to single one.
379 public void testALaCarteLifeCycle1Vnf2VfModules() {
382 String msoVnfStatus = COMPLETE_STR;
383 when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VNF)).thenReturn(true);
384 when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true);
385 final String SERVICE_REQUEST_ID = UUID.randomUUID().toString();
386 final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString();
387 final String VNF_REQUEST_ID = UUID.randomUUID().toString();
388 final String VNF_INSTANCE_ID = UUID.randomUUID().toString();
389 final String VG_REQUEST_ID = UUID.randomUUID().toString();
390 final String VG_INSTANCE_ID = UUID.randomUUID().toString();
391 final String VF_MODULE_REQUEST_ID = UUID.randomUUID().toString();
392 final String VF_MODULE_REQUEST_ID2 = UUID.randomUUID().toString();
395 //push alacarte with 1 vnf, verify STATUS pending
396 UUID uuid = pushALaCarteWithVnf();
397 singleServicesAndAssertStatus(JobStatus.PENDING, uuid);
400 /*---------- service -----------*/
402 //mock mso to answer 200 of create service instance request, verify STATUS in progress
403 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith("serviceInstances"), any())).thenReturn(
404 createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID));
406 //mock mso to answer COMPLETE for service instance create
407 when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).
408 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
410 /*---------- vnf -----------*/
412 //mock mso to answer 200 of create vnf instance request
413 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), any())).thenReturn(
414 createResponse(200, VNF_INSTANCE_ID, VNF_REQUEST_ID));
416 //mock mso to answer msoVnfStatus (COMPLETE/FAILED) for vnf creation status,
417 when(restMso.GetForObject(endsWith(VNF_REQUEST_ID), eq(AsyncRequestStatus.class))).
418 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
422 when(commandUtils.isVfModuleBaseModule(SERVICE_MODEL_VERSION_ID, VF_MODULE_0_MODEL_VERSION_ID)).thenReturn(true);
423 when(commandUtils.isVfModuleBaseModule(SERVICE_MODEL_VERSION_ID, VF_MODULE_1_MODEL_VERSION_ID)).thenReturn(false);
424 } catch (AsdcCatalogException e) {
428 /*---------- vf Module without volume group name (base) -----------*/
430 //mock mso to answer 200 of create vfModule instance request, pull+execute volumeGroup job, STATUS resource in progress
431 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/vfModules"), any())).thenReturn(
432 createResponse(200, UUID.randomUUID().toString(), VG_REQUEST_ID));
433 //mock mso to answer for vf module orchestration request
434 when(restMso.GetForObject(endsWith(VF_MODULE_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(
435 asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
437 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/volumeGroups"), any())).thenReturn(
438 createResponse(200, VG_INSTANCE_ID, VG_REQUEST_ID));
439 //mock mso to answer for volume group orchestration request
440 when(restMso.GetForObject(endsWith(VG_REQUEST_ID), eq(AsyncRequestStatus.class))).thenReturn(
441 asyncRequestStatusResponseAsRestObject(msoVnfStatus));
443 /*---------- vfModule -----------*/
445 //mock mso to answer 200 of create vfModule instance request, pull+execute volumeGroup job, STATUS resource in progress
446 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/vfModules"), any())).thenReturn(
447 createResponse(200, UUID.randomUUID().toString(), VF_MODULE_REQUEST_ID2));
449 //mock mso to answer for vf module orchestration request
450 when(restMso.GetForObject(endsWith(VF_MODULE_REQUEST_ID2), eq(AsyncRequestStatus.class))).thenReturn(
451 asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
453 processJobsCountTimesAndAssertStatus(uuid, 200, COMPLETED);
454 verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), eq("/serviceInstantiation/v7/serviceInstances"), any());
455 verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs"), any());
456 verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/volumeGroups"), any());
457 verify(restMso, times(2)).restCall(eq(HttpMethod.POST), any(), any(), endsWith(SERVICE_INSTANCE_ID + "/vnfs/" + VNF_INSTANCE_ID + "/vfModules"), any());
458 verify(restMso, times(5)).GetForObject(any(), any());
462 public void testALaCarteLifeCycle2Networks() {
464 //Create Service with 2 networks, and make sure they created in sequence (and not in parallel)
465 //Config MSO to response 200 only to first network creation. And answer 500 for second one.
466 //Then MSO return in_progress some times (like 10 times), and then return COMPLETE.
467 //Only when MSO return COMPLETE for first network, config MSO to return 200 for second network creation
469 final String SERVICE_REQUEST_ID = UUID.randomUUID().toString();
470 final String SERVICE_INSTANCE_ID = UUID.randomUUID().toString();
471 final String NETWORK_REQUEST_ID1 = UUID.randomUUID().toString();
472 final String NETWORK_INSTANCE_ID1 = UUID.randomUUID().toString();
473 //TODO use them later for different networks
474 final String NETWORK_REQUEST_ID2 = UUID.randomUUID().toString();
475 final String NETWORK_INSTANCE_ID2 = UUID.randomUUID().toString();
478 NetworkDetails networkDetails1 = new NetworkDetails("LukaDoncic", "1");
479 NetworkDetails networkDetails2 = new NetworkDetails("KevinDurant", "2");
483 /*---------- service -----------*/
485 //mock mso to answer 200 of create service instance request, verify STATUS in progress
486 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith("serviceInstances"), any())).thenReturn(
487 createResponse(200, SERVICE_INSTANCE_ID, SERVICE_REQUEST_ID));
489 //mock mso to answer COMPLETE for service instance create
490 when(restMso.GetForObject(endsWith(SERVICE_REQUEST_ID), eq(AsyncRequestStatus.class))).
491 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
493 final MutableInt secondNetworkCode = new MutableInt(500);
494 final MutableInt inProgressCount = new MutableInt(0);
496 /*---------- network 1-----------*/
498 //mock mso to answer 200 of first create network instance request
499 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class),
500 MockitoHamcrest.argThat(jsonPartMatches("requestDetails.requestInfo.instanceName", equalTo(networkDetails1.name))) ,
501 endsWith(SERVICE_INSTANCE_ID + "/networks"), any())).thenReturn(
502 createResponse(200, NETWORK_INSTANCE_ID1, NETWORK_REQUEST_ID1));
504 //mock mso to answer IN_PROGRESS 10 times, and only then COMPLETE for first network
505 //Once COMPLETE, second network creation will return 200
506 when(restMso.GetForObject(endsWith(NETWORK_REQUEST_ID1), eq(AsyncRequestStatus.class))).
509 if (inProgressCount.getValue()<10) {
510 status = IN_PROGRESS_STR;
512 secondNetworkCode.setValue(200);
513 status = COMPLETE_STR;
515 inProgressCount.add(1);
516 return asyncRequestStatusResponseAsRestObject(status);
519 /*---------- network 2-----------*/
521 //mock MSO to return status code of secondNetworkCode (500 and 200 after first one COMPLETED)
522 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class),
523 MockitoHamcrest.argThat(jsonPartMatches("requestDetails.requestInfo.instanceName", equalTo(networkDetails2.name))) ,
524 endsWith(SERVICE_INSTANCE_ID + "/networks"), any())).thenAnswer(x->
525 createResponse(secondNetworkCode.intValue(), NETWORK_INSTANCE_ID2, NETWORK_REQUEST_ID2));
527 // when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any() , endsWith(SERVICE_INSTANCE_ID + "/networks"), any())).thenReturn(
528 // createResponse(200, NETWORK_INSTANCE_ID1, NETWORK_REQUEST_ID1));
529 //mock mso to answer COMPLETE for network creation status,
531 when(restMso.GetForObject(endsWith(NETWORK_REQUEST_ID2), eq(AsyncRequestStatus.class))).
532 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
535 /*---------- Create request and process it -----------*/
536 //push alacarte with 2 networks, verify STATUS pending
537 when(featureManager.isActive(Features.FLAG_EXP_CREATE_RESOURCES_IN_PARALLEL)).thenReturn(false);
538 ServiceInstantiation serviceInstantiation = generateALaCarteWithNetworksPayload(ImmutableList.of(networkDetails1, networkDetails2));
539 UUID uuid = asyncInstantiationBL.pushBulkJob(serviceInstantiation, USER_ID).get(0);
540 singleServicesAndAssertStatus(JobStatus.PENDING, uuid);
542 processJobsCountTimesAndAssertStatus(uuid, 200, COMPLETED);
544 //validate the mso request id is the right one
545 List<ServiceInfo> serviceInfoList = asyncInstantiationBL.getAllServicesInfo();
546 ServiceInfo serviceInfo = serviceInfoList.get(0);
547 assertThat(serviceInfo.getMsoRequestId(), is(UUID.fromString(SERVICE_REQUEST_ID)));
549 /*---------- verify -----------*/
550 verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), eq("/serviceInstantiation/v7/serviceInstances"), any());
551 verify(restMso, times(2)).restCall(eq(HttpMethod.POST), any(), any(), endsWith(SERVICE_INSTANCE_ID + "/networks"), any());
553 verify(restMso, times(1)).GetForObject(endsWith(SERVICE_REQUEST_ID), any());
554 verify(restMso, times(11)).GetForObject(endsWith(NETWORK_REQUEST_ID1), any());
555 verify(restMso, times(1)).GetForObject(endsWith(NETWORK_REQUEST_ID2), any());
559 public void testBadAaiResponseForSearchNamesAndBackToNormal() {
560 when(aaiClient.isNodeTypeExistsByName(any(), any())).thenThrow(aaiNodeQueryBadResponseException());
561 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))).thenReturn(createResponse(200));
562 when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).
563 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
565 List<UUID> uuids = pushMacroBulk();
566 processJobsCountTimesAndAssertStatus(uuids.get(0), 5, IN_PROGRESS, PENDING); //JOB shall become IN_PROGRESS but service info is still pending
568 //simulate AAI back to normal, AAI return name is free, and MSO return good response
569 Mockito.reset(aaiClient); // must forget the "thenThrow"
570 when(aaiClient.isNodeTypeExistsByName(any(), any())).thenReturn(false);
571 processJobsCountTimesAndAssertStatus(uuids.get(0), 30, COMPLETED, COMPLETED);
576 public void testAaiResponseNameUsedTillMaxRetries() {
577 when(aaiClient.isNodeTypeExistsByName(any(), any())).thenReturn(true);
578 //simulate MSO to return good result, for making sure we failed because of AAI error
579 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))).thenReturn(createResponse(200));
580 when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).
581 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
583 asyncInstantiationBL.setMaxRetriesGettingFreeNameFromAai(10);
584 List<UUID> uuids = pushMacroBulk();
585 processJobsCountTimesAndAssertStatus(uuids.get(0), 20, FAILED, STOPPED);
588 private Job pullJobProcessAndPushBack(JobStatus topic, JobStatus expectedNextJobStatus) {
589 return pullJobProcessAndPushBack(topic, expectedNextJobStatus, true);
592 //return the pulled job (and not the pushed job)
593 private Job pullJobProcessAndPushBack(JobStatus topic, JobStatus expectedNextJobStatus, boolean pullingAssertion) {
594 Optional<Job> job = pullJob(topic, pullingAssertion);
596 Job nextJob = jobWorker.executeJobAndGetNext(job.get());
599 assertThat("next job not ok: " + nextJob.getData(), nextJob.getStatus(), is(expectedNextJobStatus));
601 if (pullingAssertion) {
602 //assert another pulling on same topic return no result (before push back)
603 assertFalse(jobsBrokerService.pull(topic, randomUuid()).isPresent());
607 jobsBrokerService.pushBack(nextJob); // push back to let retries - even if any assertion failure
609 assertThat(jobsBrokerService.peek(job.get().getUuid()).getStatus(), is(expectedNextJobStatus));
613 private void simplePullJobProcessAndPushBack(JobStatus topic) {
614 Optional<Job> optionalJob = jobsBrokerService.pull(topic, randomUuid());
615 optionalJob.ifPresent(job->{
616 Job nextJob = jobWorker.executeJobAndGetNext(job);
617 jobsBrokerService.pushBack(nextJob);
621 private Job pullJobProcessAndPushBackWithTypeAssertion(JobStatus topic, JobStatus expectedNextJobStatus,
622 JobType expectedNextJobType) {
623 Job job = pullJobProcessAndPushBack(topic, expectedNextJobStatus, false);
624 assertThat("job not ok: " + job.getData(), job.getType(), is(expectedNextJobType));
628 private Job pullJobProcessAndPushBackWithTypeAssertion(JobStatus topic, JobStatus expectedNextJobStatus,
629 JobType expectedNextJobType, Action actionPhase, InternalState internalState, int retries) {
630 return retryWithAssertionsLimit(retries, () -> {
631 Job job = pullJobProcessAndPushBackWithTypeAssertion(topic, expectedNextJobStatus, expectedNextJobType);
632 assertThat("job not ok: " + job.getData(), job.getData(), is(jsonPartEquals("actionPhase", actionPhase.name())));
633 if (internalState != null) {
634 assertThat("job not ok: " + job.getData(), job.getData(), is(jsonPartEquals("internalState", internalState.name())));
640 private Job retryWithAssertionsLimit(int retries, Supplier<Job> supplier) {
641 java.util.Stack<AssertionError> history = new Stack<>();
645 return supplier.get();
646 } catch (AssertionError assertionError) {
647 history.push(assertionError);
649 } while (history.size() < retries);
652 throw new AssertionError("No luck while all of these assertion errors: " + history.stream()
653 .map(Throwable::getMessage)
654 .map(s -> s.replace('\n', ' '))
655 .map(s -> s.replaceAll("\\s{2,}"," "))
657 .collect(joining("\n ", "\n ", "")), history.peek());
660 private Optional<Job> pullJob(JobStatus topic, boolean pullingAssertion) {
661 if (pullingAssertion) {
662 //assert pulling on inverse topic return no result
663 assertFalse(jobsBrokerService.pull(inverseTopic(topic), randomUuid()).isPresent());
666 Optional<Job> job = jobsBrokerService.pull(topic, randomUuid());
667 assertTrue("no job fetched", job.isPresent());
669 if (pullingAssertion) {
670 //assert another pulling on same topic return no result
671 assertFalse(jobsBrokerService.pull(topic, randomUuid()).isPresent());
677 private JobStatus inverseTopic(JobStatus topic) {
678 return topic==JobStatus.IN_PROGRESS ? PENDING : JobStatus.IN_PROGRESS;
683 public void whenPushNewBulk_andGetNoResponseFromMsoOnCreation_thenServiceMoveToFailedAndOtherToStopped() {
684 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))).thenReturn(createResponse(500));
685 //assert that when get ProcessingException from restMso, status remain the same
686 List<UUID> uuids = pushMacroBulk();
687 processJobsCountTimesAndAssertStatus(uuids.get(0), 30, JobStatus.FAILED, JobStatus.STOPPED);
691 public void whenMsoStatusIsPendingManualTask_ThenJobStatusIsPaused() {
692 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty()))).thenReturn(createResponse(200));
693 when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).
694 thenReturn(asyncRequestStatusResponseAsRestObject(PENDING_MANUAL_TASK));
696 //assert that when get ProcessingException from restMso, status remain the same
697 List<UUID> uuids = pushMacroBulk();
698 processJobsCountTimesAndAssertStatus(uuids.get(0), 30, PAUSE, PENDING);
701 //the job get IN_PROGRESS response (simulate activate operation) and status changed to IN_PROGRESS
702 when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).
703 thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR));
704 processJobsCountTimesAndAssertStatus(uuids.get(0), 30, IN_PROGRESS, PENDING);
706 //the job get COMPLETE response this job is copmpleted and then also other jobs
707 when(restMso.GetForObject(any(), eq(AsyncRequestStatus.class))).
708 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
709 processJobsCountTimesAndAssertStatus(uuids.get(0), 200, COMPLETED, COMPLETED);
711 ImmutableList<String> expectedStatusesForVid = statusesToStrings(PENDING, IN_PROGRESS, PAUSE, IN_PROGRESS, COMPLETED);
712 List<String> vidStatuses = auditService.getAuditStatuses(uuids.get(0), VID).stream().map(x -> x.getJobStatus()).collect(Collectors.toList());
713 assertThat(vidStatuses, is(expectedStatusesForVid));
716 private Job pushBulkPullPendingJobAndAssertJobStatus(JobStatus pulledJobStatus, JobStatus otherJobsStatus) {
718 return pullPendingJobAndAssertJobStatus(pulledJobStatus, otherJobsStatus);
721 private Job pullPendingJobAndAssertJobStatus(JobStatus pulledJobStatus, JobStatus otherJobsStatus) {
722 Job job = pullJobProcessAndPushBack(PENDING, pulledJobStatus, false);
723 listServicesAndAssertStatus(pulledJobStatus, otherJobsStatus, job.getUuid());
728 public void test2BulksLifeCyclesAreIndependent() {
730 final String SERVICE1_REQUEST_ID = UUID.randomUUID().toString();
731 final String SERVICE1_INSTANCE_ID = UUID.randomUUID().toString();
732 final String SERVICE2_REQUEST_ID = UUID.randomUUID().toString();
733 final String SERVICE2_INSTANCE_ID = UUID.randomUUID().toString();
734 final String SERVICE3_4_REQUEST_ID = UUID.randomUUID().toString();
735 final String SERVICE3_4_INSTANCE_ID = UUID.randomUUID().toString();
738 //create first bulk and make one job in progress
739 List<UUID> firstBulksIDs = pushMacroBulk();
740 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty())))
741 .thenReturn(createResponse(200, SERVICE1_INSTANCE_ID, SERVICE1_REQUEST_ID));
742 when(restMso.GetForObject(endsWith(SERVICE1_REQUEST_ID), eq(AsyncRequestStatus.class))).
743 thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR));
744 processJobsCountTimesAndAssertStatus(firstBulksIDs.get(0), 30, IN_PROGRESS, PENDING);
746 //create 2nd bulk, then when pulling first job the job become in_progress, other jobs (from 2 bulks) remain pending
747 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty())))
748 .thenReturn(createResponse(200, SERVICE2_INSTANCE_ID, SERVICE2_REQUEST_ID));
749 when(restMso.GetForObject(endsWith(SERVICE2_REQUEST_ID), eq(AsyncRequestStatus.class))).
750 thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR));
751 List<UUID> secondBulksIDs = pushMacroBulk();
752 processJobsCountTimes(30);
753 Map<JobStatus, Long> statusCount = getJobStatusesCount();
754 assertThat(statusCount.get(IN_PROGRESS), is(2L));
755 assertThat(statusCount.get(PENDING), is(4L));
757 //return failed to first job
758 //first bulk statuses shall be: FAILED, STOPPED, STOPPED
759 //second bulk statuses shall be: IN_PROGRESS, PENDING, PENDING
760 when(restMso.GetForObject(endsWith(SERVICE1_REQUEST_ID), eq(AsyncRequestStatus.class))).
761 thenReturn(asyncRequestStatusResponseAsRestObject(FAILED_STR));
762 processJobsCountTimes(30);
763 Map<UUID, List<ServiceInfo>> servicesByTemplateId =
764 asyncInstantiationBL.getAllServicesInfo()
765 .stream().collect(groupingBy(ServiceInfo::getTemplateId));
766 ServiceInfo failedJob = asyncInstantiationBL.getAllServicesInfo().stream().filter(x->x.getJobId().equals(firstBulksIDs.get(0))).findFirst().get();
767 assertServicesStatus(servicesByTemplateId.get(failedJob.getTemplateId()), JobStatus.FAILED, JobStatus.STOPPED, failedJob.getJobId());
768 ServiceInfo successJob = asyncInstantiationBL.getAllServicesInfo().stream().filter(x->x.getJobId().equals(secondBulksIDs.get(0))).findFirst().get();
769 assertServicesStatus(servicesByTemplateId.get(successJob.getTemplateId()), JobStatus.IN_PROGRESS, PENDING, successJob.getJobId());
771 //return completed to all other jobs
772 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), any(), eq(Optional.empty())))
773 .thenReturn(createResponse(200, SERVICE3_4_INSTANCE_ID, SERVICE3_4_REQUEST_ID));
774 when(restMso.GetForObject(endsWith(SERVICE2_REQUEST_ID), eq(AsyncRequestStatus.class))).
775 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
776 when(restMso.GetForObject(endsWith(SERVICE3_4_REQUEST_ID), eq(AsyncRequestStatus.class))).
777 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
779 processJobsCountTimes(30);
780 servicesByTemplateId = asyncInstantiationBL.getAllServicesInfo().stream().collect(groupingBy(ServiceInfo::getTemplateId));
781 assertServicesStatus(servicesByTemplateId.get(failedJob.getTemplateId()), JobStatus.FAILED, JobStatus.STOPPED, failedJob.getJobId());
782 assertServicesStatus(servicesByTemplateId.get(successJob.getTemplateId()), COMPLETED, COMPLETED, successJob.getJobId());
783 //assert no more PENDING jobs nor IN_PROGRESS jobs to pull
784 assertFalse(jobsBrokerService.pull(PENDING, randomUuid()).isPresent());
785 assertFalse(jobsBrokerService.pull(JobStatus.IN_PROGRESS, randomUuid()).isPresent());
788 protected Map<JobStatus, Long> getJobStatusesCount() {
789 return asyncInstantiationBL.getAllServicesInfo().stream().collect(groupingBy(ServiceInfo::getJobStatus, counting()));
793 public void deploy2NewGroupsToServiceWith1ExistingGroup() {
796 new feature: skip service (existing impl) and skip group (new impl)
797 service+group aren't touched, 2 groups ARE created
799 [v] success if all GROUPs success
801 Next test variation should:
802 [ ] error if all GROUPs error
803 [ ] completed with error if 1 GROUP error
806 [v] + service with 3 groups - 1 action=none, 2 action=create; service's action=none
807 [v] verify STATUS pending
808 [v] + pull+execute (should NOT post to MSO)
809 [v] verify STATUS in progress; TYPE watching
812 [v] + pull+execute job#1
813 [v] verify job#1 STATUS in progress; TYPE watching
815 [v] + pull+execute job#6 (should post to MSO)
816 [v] verify job#6 STATUS resource in progress
817 [v] + pull+execute job#1
818 [v] verify job#1 STATUS in progress; TYPE watching
819 [v] + pull+execute job#6 (should get from MSO)
820 [v] verify job#6 STATUS completed
821 [v] + pull+execute job#1
822 [v] verify job#1 STATUS in progress; TYPE watching
824 [v] + pull+execute job#7 (should post to MSO)
825 [v] verify job#7 STATUS resource in progress
826 [v] + pull+execute job#1
827 [v] verify job#1 STATUS in progress; TYPE watching
828 [v] + pull+execute job#7 (should get from MSO)
829 [v] verify job#7 STATUS completed
830 [v] + pull+execute job#1
831 [v] verify job#1 STATUS completed
835 final String GROUP1_REQUEST_ID = UUID.randomUUID().toString();
836 final String GROUP1_INSTANCE_ID = UUID.randomUUID().toString();
837 final String GROUP2_REQUEST_ID = UUID.randomUUID().toString();
838 final String GROUP2_INSTANCE_ID = UUID.randomUUID().toString();
841 final BiConsumer<Action, JobStatus> verify_Job1InProgress = (phase, nextJobStatus) -> {
842 pullJobProcessAndPushBackWithTypeAssertion(IN_PROGRESS, nextJobStatus, JobType.ALaCarteService, phase, InternalState.WATCHING, 2);
845 //service with 3 groups - 1 action=none, 2 action=create; service's action=none
846 UUID uuid = pushALaCarteUpdateWithGroups();
847 singleServicesAndAssertStatus(PENDING, uuid);
849 // take from pending, put in-progress -> 3 delete-child were born
850 pullJobProcessAndPushBackWithTypeAssertion(PENDING, IN_PROGRESS, JobType.ALaCarteService, Action.Create, InternalState.INITIAL, 1);
851 verifyQueueSizes(ImmutableMap.of(
855 // take job #1 from phase delete to phase create -> 3 create-child were born
856 verify_Job1InProgress.accept(Action.Create, IN_PROGRESS);
857 verifyQueueSizes(ImmutableMap.of(
858 IN_PROGRESS, 1, PENDING_RESOURCE, 3
862 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), endsWith("instanceGroups"), eq(Optional.empty())))
863 .thenReturn(createResponse(200, GROUP1_INSTANCE_ID, GROUP1_REQUEST_ID))
864 .thenReturn(createResponse(200, GROUP2_INSTANCE_ID, GROUP2_REQUEST_ID))
866 when(restMso.GetForObject(argThat(uri -> StringUtils.endsWithAny(uri, GROUP1_REQUEST_ID, GROUP2_REQUEST_ID)), eq(AsyncRequestStatus.class))).
867 thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
869 // take first "none" child from creating to COMPLETED_WITH_NO_ACTION
870 // note there's no concrete mechanism that makes the first child be
871 // the "action=None" case, but that's what happens, and following lines
872 // relies on that fact.
873 pullJobProcessAndPushBackWithTypeAssertion(PENDING_RESOURCE, COMPLETED_WITH_NO_ACTION, JobType.InstanceGroup, Action.Create, null, 1);
875 // take each of next two children from creating to in-progress, then to completed
876 // verify job #1 is watching, and MSO is getting requests
877 Stream.of(1, 2).forEach(i -> {
878 verify_Job1InProgress.accept(Action.Create, IN_PROGRESS);
879 pullJobProcessAndPushBackWithTypeAssertion(PENDING_RESOURCE, RESOURCE_IN_PROGRESS, JobType.InstanceGroup, Action.Create, InternalState.IN_PROGRESS, 1);
880 verify(restMso, times(i)).restCall(any(), any(), any(), any(), any());
882 verify_Job1InProgress.accept(Action.Create, IN_PROGRESS);
883 pullJobProcessAndPushBackWithTypeAssertion(RESOURCE_IN_PROGRESS, COMPLETED, JobType.InstanceGroup, Action.Create, null, 3);
884 verify(restMso, times(i)).GetForObject(any(), any());
887 // job #1 is done as all children are done
888 verify_Job1InProgress.accept(Action.Create, COMPLETED);
889 verifyQueueSizes(ImmutableMap.of(COMPLETED, 3, COMPLETED_WITH_NO_ACTION, 1));
893 public static Object[][] createAndDeleteIntegrationTestDataProvider(Method test) {
894 return new Object[][]{
895 {"create and delete both bad http code", createResponse(400), createResponse(500), null, null, FAILED, 0},
896 {"create and delete success and status is success ", createResponseRandomIds(202), createResponseRandomIds(202),
897 asyncRequestStatusResponseAsRestObject(COMPLETE_STR), asyncRequestStatusResponseAsRestObject(COMPLETE_STR), COMPLETED, 2},
898 {"create and delete success, create status FAILED, delete status COMPLETED", createResponseRandomIds(202), createResponseRandomIds(202),
899 asyncRequestStatusResponseAsRestObject(FAILED_STR), asyncRequestStatusResponseAsRestObject(COMPLETE_STR), COMPLETED_WITH_ERRORS, 2},
900 {"create and delete success, create status FAILED, delete status FAILED", createResponseRandomIds(202), createResponseRandomIds(202),
901 asyncRequestStatusResponseAsRestObject(FAILED_STR), asyncRequestStatusResponseAsRestObject(FAILED_STR), FAILED, 2},
902 {"create success but delete failed and status is success ", createResponseRandomIds(202), createResponseRandomIds(400),
903 asyncRequestStatusResponseAsRestObject(COMPLETE_STR), null, COMPLETED_WITH_ERRORS, 1},
904 {"delete success but create failed and status is success ", createResponseRandomIds(400), createResponseRandomIds(202),
905 null, asyncRequestStatusResponseAsRestObject(COMPLETE_STR), COMPLETED_WITH_ERRORS, 1},
906 {"delete success but create failed and status of delete is FAILED ", createResponseRandomIds(400), createResponseRandomIds(202),
907 null, asyncRequestStatusResponseAsRestObject(FAILED_STR), FAILED, 1}
911 //this test is going along with AsyncInstantiationALaCarteApiTest.viewEditVnfGroup__verifyStatusAndAudit API test
912 //The API test has only the happy flow scenario, while this test also test additional MSO responses (mostly non happy)
913 @Test(dataProvider="createAndDeleteIntegrationTestDataProvider")
914 public void vnfGropingIntegrationTest(
916 RestObject<RequestReferencesContainer> createGroupResponse,
917 RestObject<RequestReferencesContainer> deleteGroupResponse,
918 RestObject<AsyncRequestStatus> createStatusResponse,
919 RestObject<AsyncRequestStatus> deleteStatusResponse,
920 JobStatus expectedJobStatus,
921 int getStatusCounter) throws IOException {
923 UUID jobUUID = createAndDeleteIntegrationTest("/payload_jsons/VnfGroupCreate1Delete1None1Request.json",
924 "/serviceInstantiation/v7/instanceGroups",
926 "/serviceInstantiation/v7/instanceGroups/VNF_GROUP1_INSTANCE_ID",
928 createStatusResponse,
929 deleteStatusResponse,
933 ServiceInstantiation bulkForRetry = asyncInstantiationBL.getBulkForRetry(jobUUID);
934 InstanceGroup vnfGroupShouldBeDeleted = bulkForRetry.getVnfGroups().get("groupingservicefortest..ResourceInstanceGroup..0:001");
935 InstanceGroup vnfGroupShouldBeCreated = bulkForRetry.getVnfGroups().get("groupingservicefortest..ResourceInstanceGroup..0");
937 if (deleteStatusResponse == null || deleteStatusResponse.get().request.requestStatus.getRequestState().equals(FAILED_STR)) {
938 assertThat(vnfGroupShouldBeDeleted.getAction(), equalTo(Action.Delete));
939 assertErrorForResource(vnfGroupShouldBeDeleted, deleteGroupResponse, deleteStatusResponse);
942 if (createStatusResponse == null || createStatusResponse.get().request.requestStatus.getRequestState().equals(FAILED_STR)) {
943 assertThat(vnfGroupShouldBeCreated.getAction(), equalTo(Action.Create));
944 assertErrorForResource(vnfGroupShouldBeCreated, createGroupResponse, createStatusResponse);
948 //this test is going along with AsyncInstantiationALaCarteApiTest3.delete1Create1VnfFromService API test
949 //The API test has only the happy flow scenario, while this test also test additional MSO responses (mostly non happy)
950 @Test(dataProvider="createAndDeleteIntegrationTestDataProvider")
951 public void vnfsIntegrationTest(
953 RestObject<RequestReferencesContainer> createVnfResponse,
954 RestObject<RequestReferencesContainer> deleteVnfResponse,
955 RestObject<AsyncRequestStatus> createStatusResponse,
956 RestObject<AsyncRequestStatus> deleteStatusResponse,
957 JobStatus expectedJobStatus,
958 int getStatusCounter) throws IOException {
960 createAndDeleteIntegrationTest("/payload_jsons/vnfDelete1Create1Request.json",
961 "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/vnfs",
963 "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/vnfs/VNF_INSTANCE_ID",
965 createStatusResponse,
966 deleteStatusResponse,
971 @Test(dataProvider="createAndDeleteIntegrationTestDataProvider")
972 public void vfModulesIntegrationTest(
974 RestObject<RequestReferencesContainer> createVfModuleResponse,
975 RestObject<RequestReferencesContainer> deleteVfModuleResponse,
976 RestObject<AsyncRequestStatus> createStatusResponse,
977 RestObject<AsyncRequestStatus> deleteStatusResponse,
978 JobStatus expectedJobStatus,
979 int getStatusCounter) throws IOException, AsdcCatalogException {
981 when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true);
983 when(commandUtils.isVfModuleBaseModule("6b528779-44a3-4472-bdff-9cd15ec93450", "f8360508-3f17-4414-a2ed-6bc71161e8db")).thenReturn(true);
984 when(commandUtils.isVfModuleBaseModule("6b528779-44a3-4472-bdff-9cd15ec93450", "25284168-24bb-4698-8cb4-3f509146eca5")).thenReturn(false);
986 createAndDeleteIntegrationTest("/payload_jsons/vfModuleDelete1Create1None1Request.json",
987 "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/vnfs/VNF_INSTANCE_ID/vfModules",
988 createVfModuleResponse,
989 "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/vnfs/VNF_INSTANCE_ID/vfModules/VF_MODULE_INSTANCE_ID",
990 deleteVfModuleResponse,
991 createStatusResponse,
992 deleteStatusResponse,
997 //this test is going along with AsyncInstantiationALaCarteApiTest.delete1Create1NetworkFromService API test
998 //The API test has only the happy flow scenario, while this test also test additional MSO responses (mostly non happy)
999 @Test(dataProvider="createAndDeleteIntegrationTestDataProvider")
1000 public void networksIntegrationTest(
1002 RestObject<RequestReferencesContainer> createNetworkResponse,
1003 RestObject<RequestReferencesContainer> deleteNetworkResponse,
1004 RestObject<AsyncRequestStatus> createStatusResponse,
1005 RestObject<AsyncRequestStatus> deleteStatusResponse,
1006 JobStatus expectedJobStatus,
1007 int getStatusCounter) throws IOException {
1009 createAndDeleteIntegrationTest("/payload_jsons/networkDelete1Create1Request.json",
1010 "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/networks",
1011 createNetworkResponse,
1012 "/serviceInstantiation/v7/serviceInstances/f8791436-8d55-4fde-b4d5-72dd2cf13cfb/networks/NETWORK_INSTANCE_ID",
1013 deleteNetworkResponse,
1014 createStatusResponse,
1015 deleteStatusResponse,
1020 private UUID createAndDeleteIntegrationTest(String payload,
1022 RestObject<RequestReferencesContainer> createResponse,
1024 RestObject<RequestReferencesContainer> deleteResponse,
1025 RestObject<AsyncRequestStatus> createStatusResponse,
1026 RestObject<AsyncRequestStatus> deleteStatusResponse,
1027 JobStatus expectedJobStatus,
1028 int getStatusCounter) throws IOException {
1029 UUID jobUUID = asyncInstantiationBL.pushBulkJob(
1030 TestUtils.readJsonResourceFileAsObject(payload, ServiceInstantiation.class), "userId")
1033 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), eq(createPath), any())).thenReturn(createResponse);
1034 when(restMso.restCall(eq(HttpMethod.DELETE), eq(RequestReferencesContainer.class), any(), eq(deletePath), any())).thenReturn(deleteResponse);
1035 if (createStatusResponse!=null) {
1036 when(restMso.GetForObject(endsWith(createResponse.get().getRequestReferences().getRequestId()), eq(AsyncRequestStatus.class))).thenReturn(createStatusResponse);
1038 if (deleteStatusResponse!=null) {
1039 when(restMso.GetForObject(endsWith(deleteResponse.get().getRequestReferences().getRequestId()), eq(AsyncRequestStatus.class))).thenReturn(deleteStatusResponse);
1042 processJobsCountTimesAndAssertStatus(jobUUID, 40, expectedJobStatus);
1044 verify(restMso, times(1)).restCall(eq(HttpMethod.POST), any(), any(), eq(createPath), any());
1045 verify(restMso, times(1)).restCall(eq(HttpMethod.DELETE), any(), any(), eq(deletePath), any());
1046 verify(restMso, times(getStatusCounter)).GetForObject(any(), any());
1052 public void whenCreateTransportService_thanExpectedPre1806MacroRequestSent() throws IOException {
1053 UUID jobUUID = asyncInstantiationBL.pushBulkJob(generatePre1806MacroTransportServiceInstantiationPayload(null, null),"az2016").get(0);
1054 RestObject<RequestReferencesContainer> createResponse = createResponseRandomIds(202);
1056 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), eq("/serviceInstantiation/v7/serviceInstances"), any()))
1057 .thenReturn(createResponse);
1058 when(restMso.GetForObject(endsWith(createResponse.get().getRequestReferences().getRequestId()), eq(AsyncRequestStatus.class)))
1059 .thenReturn(asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
1060 processJobsCountTimesAndAssertStatus(jobUUID, 20, COMPLETED);
1062 JsonNode expectedJson = TestUtils.readJsonResourceFileAsObject("/payload_jsons/pre_1806_macro_without_cloudConfiguration.json", JsonNode.class);
1063 ArgumentCaptor<RequestDetailsWrapper> requestCaptor = ArgumentCaptor.forClass(RequestDetailsWrapper.class);
1064 verify(restMso).restCall(any(), any(), requestCaptor.capture(), any(), any());
1065 requestCaptor.getAllValues().forEach(x->assertJsonEquals(expectedJson, x));
1068 private void assertErrorForResource(BaseResource resource,
1069 RestObject<RequestReferencesContainer> deleteOrCreateResponse,
1070 RestObject<AsyncRequestStatus> statusResponse) {
1071 JobAuditStatus auditStatus = auditService.getResourceAuditStatus(resource.getTrackById());
1072 assertThat(auditStatus, is(notNullValue()));
1073 assertThat(auditStatus.getJobStatus(), equalTo(FAILED_STR));
1074 if (statusResponse == null) {
1075 String errorMessage = "Http Code:" + deleteOrCreateResponse.getStatusCode() + ", " + RAW_DATA_FROM_MSO;
1076 assertThat(auditStatus.getAdditionalInfo(), equalTo(errorMessage));
1077 assertThat(auditStatus.getRequestId(), is(nullValue()));
1079 assertThat(auditStatus.getRequestId().toString(), equalTo(statusResponse.get().request.requestId));
1083 protected void processJobsCountTimesAndAssertStatus(UUID serviceJobId, int times, JobStatus expectedStatus) {
1084 processJobsCountTimes(times);
1085 singleServicesAndAssertStatus(expectedStatus, serviceJobId);
1088 private void processJobsCountTimes(int times) {
1089 for (int i = 0; i < times; i++) {
1090 WORKERS_TOPICS.forEach(this::simplePullJobProcessAndPushBack);
1094 protected void processJobsCountTimesAndAssertStatus(UUID serviceJobId, int times, JobStatus expectedStatus, JobStatus otherJobsStatus) {
1095 processJobsCountTimes(times);
1096 listServicesAndAssertStatus(expectedStatus, otherJobsStatus, serviceJobId);
1100 private void verifyQueueSizes(ImmutableMap<JobStatus, Integer> expected) {
1101 final Collection<Job> peek = jobsBrokerService.peek();
1102 final Map<JobStatus, Long> jobTypes = peek.stream().collect(groupingBy(Job::getStatus, counting()));
1103 assertThat(jobTypes, jsonEquals(expected));
1106 private List<ServiceInfo> listServicesAndAssertStatus(JobStatus pulledJobStatus, JobStatus otherJobsStatus, UUID jobUUID) {
1107 List<ServiceInfo> serviceInfoList = asyncInstantiationBL.getAllServicesInfo();
1108 assertServicesStatus(serviceInfoList, pulledJobStatus, otherJobsStatus, jobUUID);
1110 return serviceInfoList;
1113 private ServiceInfo singleServicesAndAssertStatus(JobStatus expectedStatus, UUID jobUUID) {
1114 List<ServiceInfo> serviceInfoList = asyncInstantiationBL.getAllServicesInfo();
1115 assertEquals(1, serviceInfoList.size());
1116 ServiceInfo serviceInfo = serviceInfoList.get(0);
1117 assertThat(serviceInfo.getJobStatus(), is(expectedStatus));
1118 assertThat(serviceInfo.getJobId(), is(jobUUID));
1122 private boolean isServiceOnStatus(JobStatus expectedStatus) {
1123 List<ServiceInfo> serviceInfoList = asyncInstantiationBL.getAllServicesInfo();
1124 assertEquals(1, serviceInfoList.size());
1125 return serviceInfoList.get(0).getJobStatus()==expectedStatus;
1128 private void assertServicesStatus(List<ServiceInfo> serviceInfoList, JobStatus pulledJobStatus, JobStatus otherJobsStatus, UUID jobUUID) {
1129 serviceInfoList.forEach(si->{
1130 if (si.getJobId().equals(jobUUID)) {
1131 assertThat(si.getJobStatus(), is(pulledJobStatus));
1134 assertThat(si.getJobStatus(), is(otherJobsStatus));
1139 private void listServicesAndAssertStatus(Map<UUID, JobStatus> expectedJobStatusMap) {
1140 Map<UUID, JobStatus> actualStatuses = asyncInstantiationBL.getAllServicesInfo()
1141 .stream().collect(Collectors.toMap(ServiceInfo::getJobId, ServiceInfo::getJobStatus));
1142 assertThat(actualStatuses.entrySet(), equalTo(expectedJobStatusMap.entrySet()));
1145 private String randomUuid() {
1146 return UUID.randomUUID().toString();
1150 public void whenResumeService_thanExpectedResumeRequestSent() throws IOException {
1151 String instanceId = "a565e6ad-75d1-4493-98f1-33234b5c17e2"; //from feRequestResumeMacroService.json
1152 String originalRequestId = "894089b8-f7f4-418d-81da-34186fd32670"; //from msoResponseGetRequestsOfServiceInstance.json
1153 String resumeRequestId = randomUuid();
1154 String userId = TestUtils.generateRandomAlphaNumeric(6);
1156 //prepare mocks for get all requests for instance id
1157 RestObject<AsyncRequestStatusList> getRequestByIdResponse = createAsyncRequestStatusListByInstanceId();
1158 when(restMso.GetForObject(
1159 eq("/orchestrationRequests/v7?filter=serviceInstanceId:EQUALS:" + instanceId),
1160 eq(AsyncRequestStatusList.class)))
1161 .thenReturn(getRequestByIdResponse);
1163 //prepare mocks resume request
1164 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), isNull(), eq(String.format("/orchestrationRequests/v7/%s/resume", originalRequestId)), eq(Optional.of(userId))))
1165 .thenReturn(createResponse(202, instanceId, resumeRequestId));
1167 //prepare mocks for get resume status
1168 when(restMso.GetForObject(eq("/orchestrationRequests/v7/" + resumeRequestId), eq(AsyncRequestStatus.class)))
1169 .thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR),
1170 asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR),
1171 asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
1174 UUID jobUUID = asyncInstantiationBL.pushBulkJob(generateResumeMacroPayload(), userId).get(0);
1175 processJobsCountTimesAndAssertStatus(jobUUID, 20, COMPLETED);
1176 verify(restMso).GetForObject(
1177 eq("/orchestrationRequests/v7?filter=serviceInstanceId:EQUALS:" + instanceId),
1178 eq(AsyncRequestStatusList.class));
1179 verify(restMso).restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), isNull(), eq(String.format("/orchestrationRequests/v7/%s/resume", originalRequestId)), eq(Optional.of(userId)));
1180 verify(restMso, times(3)).GetForObject(eq("/orchestrationRequests/v7/" + resumeRequestId), eq(AsyncRequestStatus.class));
1184 public void givenResumeRequest_whenMsoReturnBadResponse_thanJobIsFailed() throws IOException {
1185 //there is no mocks for restMSO which means restMso return bad response...
1186 UUID jobUUID = asyncInstantiationBL.pushBulkJob(generateResumeMacroPayload(), "abc").get(0);
1187 processJobsCountTimesAndAssertStatus(jobUUID, 20, FAILED);
1191 private RestObject<AsyncRequestStatusList> createAsyncRequestStatusListByInstanceId() throws IOException {
1192 AsyncRequestStatusList asyncRequestStatusList = TestUtils.readJsonResourceFileAsObject(
1193 "/payload_jsons/resume/msoResponseGetRequestsOfServiceInstance.json",
1194 AsyncRequestStatusList.class);
1195 RestObject<AsyncRequestStatusList> getRequestByIdResponse = new RestObject<>();
1196 getRequestByIdResponse.set(asyncRequestStatusList);
1197 getRequestByIdResponse.setStatusCode(200);
1198 return getRequestByIdResponse;
1201 private ServiceInstantiation generateResumeMacroPayload() throws IOException {
1202 return TestUtils.readJsonResourceFileAsObject("/payload_jsons/resume/feRequestResumeMacroService.json", ServiceInstantiation.class);
1206 public void whenUpgradingAvfModule_thanExpectedReplaceRequestSent() throws IOException {
1207 String instanceId = "5d49c3b1-fc90-4762-8c98-e800170baa55"; //from feRequestResumeMacroService.json
1208 String replaceRequestId = randomUuid();
1209 String userId = "az2016";
1212 //prepare mocks resume request
1213 when(restMso.restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), any(), eq("/serviceInstantiation/v7/serviceInstances/e9993045-cc96-4f3f-bf9a-71b2a400a956/vnfs/5c9c2896-1fe6-4055-b7ec-d0a01e5f9bf5/vfModules/5d49c3b1-fc90-4762-8c98-e800170baa55/replace"), eq(Optional.of(userId))))
1214 .thenReturn(createResponse(202, instanceId, replaceRequestId));
1217 when(restMso.GetForObject(eq("/orchestrationRequests/v7/" + replaceRequestId), eq(AsyncRequestStatus.class)))
1218 .thenReturn(asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR),
1219 asyncRequestStatusResponseAsRestObject(IN_PROGRESS_STR),
1220 asyncRequestStatusResponseAsRestObject(COMPLETE_STR));
1222 ///orchestrationRequests/v7/0174b25a-dd81-45b7-b4af-0057bcc30857
1224 when(featureManager.isActive(Features.FLAG_ASYNC_ALACARTE_VFMODULE)).thenReturn(true);
1225 enableAddCloudOwnerOnMsoRequest();
1227 UUID jobUUID = asyncInstantiationBL.pushBulkJob(generateReplaceVfModulePayload(), userId).get(0);
1228 processJobsCountTimesAndAssertStatus(jobUUID, 20, COMPLETED);
1232 JsonNode expectedJson = TestUtils.readJsonResourceFileAsObject("/payload_jsons/vfmodule/replace_vfmodule.json", JsonNode.class);
1233 ArgumentCaptor<RequestDetailsWrapper> requestCaptor = ArgumentCaptor.forClass(RequestDetailsWrapper.class);
1234 verify(restMso).restCall(eq(HttpMethod.POST), eq(RequestReferencesContainer.class), requestCaptor.capture(), eq("/serviceInstantiation/v7/serviceInstances/e9993045-cc96-4f3f-bf9a-71b2a400a956/vnfs/5c9c2896-1fe6-4055-b7ec-d0a01e5f9bf5/vfModules/5d49c3b1-fc90-4762-8c98-e800170baa55/replace"), eq(Optional.of(userId)));
1235 requestCaptor.getAllValues().forEach(x->assertJsonEquals(expectedJson, x));
1238 private ServiceInstantiation generateReplaceVfModulePayload() throws IOException {
1239 return TestUtils.readJsonResourceFileAsObject("/payload_jsons/vfmodule/replace_vfmodule_fe_input.json", ServiceInstantiation.class);