aboutsummaryrefslogtreecommitdiffstats
path: root/vid-automation/src/main/java/org/onap/vid/api
diff options
context:
space:
mode:
Diffstat (limited to 'vid-automation/src/main/java/org/onap/vid/api')
-rw-r--r--vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java573
-rw-r--r--vid-automation/src/main/java/org/onap/vid/api/BaseApiTest.java163
-rw-r--r--vid-automation/src/main/java/org/onap/vid/api/BaseMsoApiTest.java108
-rw-r--r--vid-automation/src/main/java/org/onap/vid/api/CreateInstanceWithFailedService.java87
-rw-r--r--vid-automation/src/main/java/org/onap/vid/api/CreateServiceWithFailedVnf.java226
-rw-r--r--vid-automation/src/main/java/org/onap/vid/api/TestUtils.java99
6 files changed, 1256 insertions, 0 deletions
diff --git a/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java b/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java
new file mode 100644
index 000000000..2a6b012fe
--- /dev/null
+++ b/vid-automation/src/main/java/org/onap/vid/api/AsyncInstantiationBase.java
@@ -0,0 +1,573 @@
+package org.onap.vid.api;
+
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static java.util.Collections.emptyList;
+import static java.util.stream.Collectors.joining;
+import static java.util.stream.Collectors.toMap;
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.hasSize;
+import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertTrue;
+import static vid.automation.test.utils.ExtendedHamcrestMatcher.hasItemsFromCollection;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.Uninterruptibles;
+import java.time.Instant;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.Description;
+import org.hamcrest.MatcherAssert;
+import org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset;
+import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset;
+import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOwnersByCloudRegionId;
+import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetSubscribersGet;
+import org.onap.simulator.presetGenerator.presets.ecompportal_att.PresetGetSessionSlotCheckIntervalGet;
+import org.onap.simulator.presetGenerator.presets.mso.PresetMSOBaseCreateInstancePost;
+import org.onap.simulator.presetGenerator.presets.mso.PresetMSOBaseDelete;
+import org.onap.simulator.presetGenerator.presets.mso.PresetMSOCreateServiceInstanceGen2WithNames;
+import org.onap.simulator.presetGenerator.presets.mso.PresetMSOOrchestrationRequestGet;
+import org.onap.vid.model.asyncInstantiation.JobAuditStatus;
+import org.onap.vid.model.asyncInstantiation.ServiceInfo;
+import org.onap.vid.model.mso.MsoResponseWrapper2;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import vid.automation.test.infra.Features;
+import vid.automation.test.infra.Wait;
+import vid.automation.test.model.JobStatus;
+import vid.automation.test.model.ServiceAction;
+import vid.automation.test.services.AsyncJobsService;
+import vid.automation.test.services.SimulatorApi;
+
+public class AsyncInstantiationBase extends BaseMsoApiTest {
+
+ public static final String CREATE_BULK_OF_ALACARTE_REQUEST_WITH_VNF = "asyncInstantiation/vidRequestCreateALaCarteWithVnf.json";
+ protected static final String CREATE_BULK_OF_MACRO_REQUEST = "asyncInstantiation/vidRequestCreateBulkOfMacro.json";
+
+ protected static final String MSO_BASE_ERROR =
+ "Received error from SDN-C: java.lang.IllegalArgumentException: All keys must be specified for class org."+
+ "opendaylight.yang.gen.v1.org.onap.sdnc.northbound.generic.resource.rev170824.vf.module.assignments.vf."+
+ "module.assignments.vms.VmKey. Missing key is getVmType. Supplied key is VmKey [].";
+ protected static final String MSO_ERROR = MSO_BASE_ERROR + StringUtils.repeat(" and a lot of sentences for long message", 60);
+
+ @BeforeClass
+ protected void muteAndDropNameCounter() {
+ AsyncJobsService asyncJobsService = new AsyncJobsService();
+ asyncJobsService.muteAllAsyncJobs();
+ asyncJobsService.dropAllFromNameCounter();
+ }
+
+ @AfterMethod
+ protected void muteAllAsyncJobs() {
+ AsyncJobsService asyncJobsService = new AsyncJobsService();
+ asyncJobsService.muteAllAsyncJobs();
+ }
+
+ @DataProvider
+ public static Object[][] trueAndFalse() {
+ return new Object[][]{{TRUE},{FALSE}};
+ }
+
+ protected String getCreateBulkUri() {
+ return uri.toASCIIString() + "/asyncInstantiation/bulk";
+ }
+
+ protected String getHideServiceUri(String jobId) {
+ return uri.toASCIIString() + "/asyncInstantiation/hide/"+jobId;
+ }
+
+ protected String getServiceInfoUrl() {
+ return uri.toASCIIString() + "/asyncInstantiation";
+ }
+
+ protected String getJobAuditUrl() {
+ return uri.toASCIIString() + "/asyncInstantiation/auditStatus/{JOB_ID}?source={SOURCE}";
+ }
+
+ protected String getMsoJobAuditUrl() {
+ return uri.toASCIIString() + "/asyncInstantiation/auditStatus/{JOB_ID}/mso";
+ }
+
+ protected String getDeleteServiceUrl(String uuid) {
+ return uri.toASCIIString() + "/asyncInstantiation/job/" + uuid;
+ }
+
+ protected String getInstanceAuditInfoUrl() {
+ return uri.toASCIIString() + "/asyncInstantiation/auditStatus/{TYPE}/{INSTANCE_ID}/mso";
+ }
+
+ protected String getRetryJobUrl() {
+ return uri.toASCIIString() + "/asyncInstantiation/retry/{JOB_ID}";
+ }
+ protected String getTopologyForRetryUrl() {
+ return uri.toASCIIString() + "/asyncInstantiation/bulkForRetry/{JOB_ID}";
+ }
+
+
+ protected String getRetryJobWithChangedDataUrl() {
+ return uri.toASCIIString() + "/asyncInstantiation/retryJobWithChangedData/{JOB_ID}";
+ }
+
+ protected boolean getExpectedRetryEnabled(JobStatus jobStatus) {
+ return Features.FLAG_1902_RETRY_JOB.isActive() && (jobStatus==JobStatus.FAILED || jobStatus==JobStatus.COMPLETED_WITH_ERRORS);
+ }
+
+ public List<BasePreset> getPresets(List<PresetMSOBaseDelete> presetOnDeleteList, List<PresetMSOBaseCreateInstancePost> presetOnCreateList, List<PresetMSOOrchestrationRequestGet> presetInProgressList) {
+
+ final ImmutableList.Builder<BasePreset> basePresetBuilder = new ImmutableList.Builder<>();
+ basePresetBuilder
+ .add(new PresetGetSessionSlotCheckIntervalGet())
+ .add(new PresetAAIGetSubscribersGet())
+ .addAll(presetOnDeleteList)
+ .addAll(presetOnCreateList)
+ .addAll(presetInProgressList);
+ return basePresetBuilder.build();
+ }
+
+ public List<BasePreset> getDeletePresets(List<PresetMSOBaseDelete> presetOnDeleteList, List<PresetMSOOrchestrationRequestGet> presetInProgressList) {
+ return getPresets(presetOnDeleteList, emptyList(), presetInProgressList);
+ }
+
+ public List<BasePreset> getPresets(List<PresetMSOBaseCreateInstancePost> presetOnCreateList, List<PresetMSOOrchestrationRequestGet> presetInProgressList) {
+ return getPresets(emptyList(), presetOnCreateList, presetInProgressList);
+ }
+
+ public void assertServiceInfoSpecific1(String jobId, JobStatus jobStatus, String serviceInstanceName, String userName) {
+ assertServiceInfoSpecific1(jobId, jobStatus, serviceInstanceName, userName, null, ServiceAction.INSTANTIATE);
+ }
+
+ public void assertServiceInfoSpecific1(String jobId, JobStatus jobStatus, String serviceInstanceName, String userName, String instanceId, ServiceAction action) {
+ assertExpectedStatusAndServiceInfo(jobStatus, jobId, new ServiceInfo(
+ userName, jobStatus, false,
+ "038d99af-0427-42c2-9d15-971b99b9b489", "Lucine Sarika", "zasaki",
+ "de738e5f-3704-4a14-b98f-3bf86ac0c0a0", "voloyakane-senamo",
+ "c85f0e80-0636-44a4-8cb2-4ec00d056e79", "Hedvika Wendelin",
+ "a93f8383-707e-43fa-8191-a6e69a1aab17", null,
+ "TYLER SILVIA", "SILVIA ROBBINS",
+ instanceId, serviceInstanceName,
+ "e3c34d88-a216-4f1d-a782-9af9f9588705", "gayawabawe", "5.1",
+ jobId, null, action, false)
+ );
+ }
+
+ public void assertServiceInfoSpecific1(String jobId, JobStatus jobStatus, String serviceInstanceName) {
+ assertServiceInfoSpecific1(jobId, jobStatus, serviceInstanceName, "us16807000");
+ }
+
+ protected void assertAuditStatuses(String jobId, List<JobAuditStatus> expectedVidStatuses, List<JobAuditStatus> expectedMsoStatuses) {
+ assertAuditStatuses(jobId, expectedVidStatuses, expectedMsoStatuses, 15);
+ }
+
+ protected void assertAuditStatuses(String jobId, List<JobAuditStatus> expectedVidStatuses, List<JobAuditStatus> expectedMsoStatuses, long timeoutInSeconds) {
+ assertAndRetryIfNeeded(() -> {
+ final List<JobAuditStatus> auditVidStatuses = getAuditStatuses(jobId, JobAuditStatus.SourceStatus.VID.name());
+ assertThat(auditVidStatuses, hasItemsFromCollection(expectedVidStatuses));
+ if (expectedMsoStatuses!=null) {
+ final List<JobAuditStatus> auditMsoStatuses = getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO.name());
+ assertThat(auditMsoStatuses, containsInAnyOrder(expectedMsoStatuses.toArray()));
+ }
+ }, timeoutInSeconds);
+ }
+
+ protected void assertAndRetryIfNeeded(Runnable asserter, long timeoutInSeconds) {
+ final Instant expiry = Instant.now().plusSeconds(timeoutInSeconds);
+ while (true) {
+ try {
+ asserter.run();
+ break; // we're cool, assertion passed
+ } catch (AssertionError fail) {
+ Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS);
+ if (Instant.now().isAfter(expiry)) {
+ throw fail;
+ } else {
+ System.out.println("retrying after: " + fail);
+ }
+ }
+ }
+ }
+
+ protected ImmutableList<JobAuditStatus> vidAuditStatusesCompletedWithErrors(String jobId) {
+ return ImmutableList.of(
+ vidAuditStatus(jobId, "PENDING", false),
+ vidAuditStatus(jobId, "IN_PROGRESS", false),
+ vidAuditStatus(jobId, "COMPLETED_WITH_ERRORS", true)
+ );
+ }
+
+ protected ImmutableList<JobAuditStatus> vidAuditStatusesFailed(String jobId) {
+ return ImmutableList.of(
+ vidAuditStatus(jobId, "PENDING", false),
+ vidAuditStatus(jobId, "IN_PROGRESS", false),
+ vidAuditStatus(jobId, "FAILED", true)
+ );
+ }
+
+ protected JobAuditStatus vidAuditStatus(String jobId, String jobStatus, boolean isFinal) {
+ return new JobAuditStatus(UUID.fromString(jobId), jobStatus, JobAuditStatus.SourceStatus.VID, null, null, isFinal);
+ }
+
+ public static class JobIdAndStatusMatcher extends BaseMatcher<ServiceInfo> {
+ protected String expectedJobId;
+
+ public JobIdAndStatusMatcher(String expectedJobId) {
+ this.expectedJobId = expectedJobId;
+ }
+
+ @Override
+ public boolean matches(Object item) {
+ if (!(item instanceof ServiceInfo)) {
+ return false;
+ }
+ ServiceInfo serviceInfo = (ServiceInfo) item;
+ return expectedJobId.equals(serviceInfo.jobId);
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("failed to find job with uuid ")
+ .appendValue(expectedJobId);
+ }
+ }
+
+
+
+ protected Map<Keys,String> generateNames() {
+ return Stream.of(Keys.values()).collect(
+ Collectors.toMap(x->x, x -> UUID.randomUUID().toString().replace("-","")));
+ }
+
+ protected ImmutableList<BasePreset> addPresetsForCreateBulkOfCreateInstances(int bulkSize, Map<Keys, String> names){
+ ImmutableList<BasePreset> msoBulkPresets = generateMsoCreateBulkPresets(bulkSize, names);
+ ImmutableList<BasePreset> presets = new ImmutableList.Builder<BasePreset>()
+ .add(new PresetGetSessionSlotCheckIntervalGet())
+ .add(new PresetAAIGetSubscribersGet())
+ .add(PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MTN3_TO_ATT_SABABA)
+ .addAll(msoBulkPresets)
+ .add(new PresetMSOOrchestrationRequestGet())
+ .build();
+ return presets;
+
+ }
+
+ protected ImmutableList<BasePreset> generateMsoCreateBulkPresets(int bulkSize, Map<Keys, String> names) {
+ return IntStream.rangeClosed(0, bulkSize-1).
+ mapToObj(i-> new PresetMSOCreateServiceInstanceGen2WithNames(names, i))
+ .collect(ImmutableList.toImmutableList());
+ }
+
+ protected ResponseEntity<List<JobAuditStatus>> auditStatusCall(String url) {
+ return restTemplate.exchange(
+ url,
+ org.springframework.http.HttpMethod.GET,
+ null,
+ new ParameterizedTypeReference<List<JobAuditStatus>>() {});
+ }
+
+ @DataProvider
+ public static Object[][] auditSources() {
+ return new Object[][]{{JobAuditStatus.SourceStatus.VID},{JobAuditStatus.SourceStatus.MSO}};
+ }
+
+
+
+ protected List<String> createBulkAndWaitForBeCompleted(int bulkSize){
+ Map<Keys, String> names = generateNames();
+ ImmutableList<BasePreset> presets = addPresetsForCreateBulkOfCreateInstances(bulkSize, names);
+ final List<String> jobIds = createBulkOfMacroInstances(presets, false, bulkSize, names);
+ Assert.assertEquals(jobIds.size(),bulkSize);
+
+ assertTrue(String.format("Not all services with ids: %s are in state completed after 30 sec",
+ jobIds.stream().collect(joining(","))),
+
+ Wait.waitFor(y-> serviceListCall().getBody().stream()
+ .filter(si -> jobIds.contains(si.jobId))
+ .filter(si -> si.jobStatus==JobStatus.COMPLETED)
+ .count() == bulkSize,
+ null, 30, 1 ));
+ return jobIds;
+ }
+
+ protected List<JobAuditStatus> getJobMsoAuditStatusForAlaCarte(String jobUUID, String requestId, String serviceInstanceId){
+ String url = getMsoJobAuditUrl().replace("{JOB_ID}",jobUUID);
+
+ if(!StringUtils.isEmpty(requestId)) {
+ url = url + "?requestId=" + requestId;
+ if(!StringUtils.isEmpty(serviceInstanceId)) {
+ url = url + "&serviceInstanceId=" + serviceInstanceId;
+ }
+ }
+ return callAuditStatus(url);
+ }
+
+ protected List<JobAuditStatus> getAuditStatuses(String jobUUID, String source){
+ String url = getJobAuditUrl().replace("{JOB_ID}",jobUUID).replace("{SOURCE}", source);
+ return callAuditStatus(url);
+ }
+
+ protected List<JobAuditStatus> getAuditStatusesForInstance(String type, String instanceId){
+ String url = getInstanceAuditInfoUrl().replace("{TYPE}",type).replace("{INSTANCE_ID}", instanceId);
+ return callAuditStatus(url);
+ }
+
+ private List<JobAuditStatus> callAuditStatus(String url) {
+ ResponseEntity<List<JobAuditStatus>> statusesResponse = auditStatusCall(url);
+ assertThat(statusesResponse.getStatusCode(), CoreMatchers.equalTo(HttpStatus.OK));
+ return statusesResponse.getBody();
+ }
+
+ protected Map<String, JobStatus> addBulkAllPendingButOneInProgress(){
+ return addBulkAllPendingButOneInProgress(3);
+ }
+
+ protected Map<String, JobStatus> addBulkAllPendingButOneInProgress(int bulkSize){
+ Map<Keys, String> names = generateNames();
+ ImmutableList<BasePreset> msoBulkPresets = generateMsoCreateBulkPresets(bulkSize, names);
+ ImmutableList<BasePreset> presets = new ImmutableList.Builder<BasePreset>()
+ .add(new PresetGetSessionSlotCheckIntervalGet())
+ .add(new PresetAAIGetSubscribersGet())
+ .add(PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MTN3_TO_ATT_SABABA)
+ .addAll(msoBulkPresets)
+ .add(new PresetMSOOrchestrationRequestGet("IN_PROGRESS"))
+ .build();
+ final List<String> jobIds = createBulkOfMacroInstances(presets, false, bulkSize, names);
+
+ // wait for single IN_PROGRESS, so statuses will stop from changing
+ Wait.waitFor(foo -> serviceListCall().getBody().stream()
+ .filter(si -> jobIds.contains(si.jobId))
+ .anyMatch(si -> si.jobStatus.equals(JobStatus.IN_PROGRESS)),
+ null, 20, 1);
+
+ final Map<String, JobStatus> statusMapBefore = serviceListCall().getBody().stream()
+ .filter(si -> jobIds.contains(si.jobId))
+ .collect(toMap(si -> si.jobId, si -> si.jobStatus));
+
+ assertThat(jobIds, hasSize(bulkSize));
+
+
+ return statusMapBefore;
+ }
+
+ protected String deleteOneJobHavingTheStatus(Map<String, JobStatus> jobIdToStatus, JobStatus jobStatus) {
+ final String jobToDelete = jobIdToStatus.entrySet().stream()
+ .filter(entry -> entry.getValue().equals(jobStatus))
+ .map(Map.Entry::getKey)
+ .findFirst().orElseThrow(() -> new AssertionError("no job in " + jobStatus + " state: " + jobIdToStatus));
+
+
+ restTemplate.delete(getDeleteServiceUrl(jobToDelete));
+
+ return jobToDelete;
+ }
+
+
+ protected MsoResponseWrapper2 hideService(String jobId) {
+ MsoResponseWrapper2 responseWrapper2 = callMsoForResponseWrapper(org.springframework.http.HttpMethod.POST, getHideServiceUri(jobId), "");
+ return responseWrapper2;
+ }
+
+ protected List<String> createBulkOfInstancesAndAssert(ImmutableList<BasePreset> presets, boolean isPause, int bulkSize, JobStatus finalState, Map<Keys, String> names){
+ List<String> jobIds = createBulkOfMacroInstances(presets, isPause, bulkSize, names);
+ Assert.assertEquals(jobIds.size(), bulkSize);
+ for(String jobId: jobIds) {
+ assertExpectedStatusAndServiceInfo(isPause, finalState, names, jobId);
+ }
+
+ return jobIds;
+ }
+
+ protected void assertExpectedStatusAndServiceInfo(boolean isPause, JobStatus finalState, Map<Keys, String> names, String jobId) {
+ assertExpectedStatusAndServiceInfo(finalState, jobId, new ServiceInfo("us16807000", JobStatus.IN_PROGRESS, isPause, "someID",
+ "someName", "myProject", "NFT1", "NFTJSSSS-NFT1", "greatTenant", "greatTenant", "hvf3", null,
+ "mySubType", "a9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb", null, names.get(Keys.SERVICE_NAME),
+ "5c9e863f-2716-467b-8799-4a67f378dcaa", "AIM_TRANSPORT_00004", "1.0", jobId, null, ServiceAction.INSTANTIATE, false));
+ }
+
+ protected void assertExpectedStatusAndServiceInfo(JobStatus finalState, String jobId, ServiceInfo expectedServiceInfo) {
+ assertExpectedStatusAndServiceInfo(finalState, jobId, false, expectedServiceInfo);
+ }
+
+ protected void assertExpectedStatusAndServiceInfo(JobStatus finalState, String jobId, boolean longWait, ServiceInfo expectedServiceInfo) {
+ JobInfoChecker<Integer> jobInfoChecker = new JobInfoChecker<>(
+ restTemplate, ImmutableSet.of(JobStatus.PENDING, JobStatus.IN_PROGRESS, finalState), jobId, expectedServiceInfo);
+ boolean result = jobInfoChecker.test(null);
+ assertTrue("service info of jobId: " + jobId + " was in status: " + jobInfoChecker.lastStatus, result);
+
+ jobInfoChecker.setExpectedJobStatus(ImmutableSet.of(finalState));
+ if (ImmutableList.of(JobStatus.COMPLETED, JobStatus.PAUSE).contains(finalState) && expectedServiceInfo.serviceInstanceId==null) {
+ expectedServiceInfo.serviceInstanceId = BaseMSOPreset.DEFAULT_INSTANCE_ID;
+ }
+ result = Wait.waitFor(jobInfoChecker, null, 30, longWait ? 2 : 1);
+ assertTrue("service info of jobId: " + jobId + " was in status: " + jobInfoChecker.lastStatus, result);
+ }
+
+ protected List<String> createBulkOfMacroInstances(ImmutableList<BasePreset> presets, boolean isPause, int bulkSize, Map<Keys, String> names) {
+ SimulatorApi.registerExpectationFromPresets(presets, SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET);
+ return createBulkOfInstances(isPause, bulkSize, names, CREATE_BULK_OF_MACRO_REQUEST);
+ }
+
+ public List<String> createBulkOfInstances(boolean isPause, int bulkSize, Map<Keys, String> names, String requestDetailsFileName){
+
+ String requestBody = TestUtils.convertRequest(objectMapper, requestDetailsFileName);
+ requestBody = requestBody.replace("\"IS_PAUSE_VALUE\"", String.valueOf(isPause)).replace("\"BULK_SIZE\"", String.valueOf(bulkSize));
+ for (Map.Entry<Keys, String> e : names.entrySet()) {
+ requestBody = requestBody.replace(e.getKey().name(), e.getValue());
+ }
+ MsoResponseWrapper2 responseWrapper2 = callMsoForResponseWrapper(org.springframework.http.HttpMethod.POST, getCreateBulkUri(), requestBody);
+ assertNotNull(responseWrapper2);
+ return (List<String>)responseWrapper2.getEntity();
+ }
+
+ protected List<String> retryJob(String jobId) {
+ ResponseEntity<String> retryBulkPayload = getRetryBulk(jobId);
+ return retryJobWithChangedData(jobId, retryBulkPayload.getBody());
+ }
+
+ protected List<String> retryJobWithChangedData(String jobId, String requestBody) {
+ String retryUri = getRetryJobWithChangedDataUrl();
+ retryUri = retryUri.replace("{JOB_ID}", jobId);
+ MsoResponseWrapper2 responseWrapper2 = callMsoForResponseWrapper(HttpMethod.POST, retryUri, requestBody);
+ assertNotNull(responseWrapper2);
+ return (List<String>)responseWrapper2.getEntity();
+ }
+
+ protected ResponseEntity<String> getRetryBulk(String jobId) {
+ String retryUri = getTopologyForRetryUrl();
+ retryUri = retryUri.replace("{JOB_ID}", jobId);
+ return restTemplateErrorAgnostic.getForEntity(retryUri, String.class);
+ }
+
+ protected Object getResourceAuditInfo(String trackById) {
+ return restTemplate.getForObject(buildUri("/asyncInstantiation/auditStatusForRetry/{trackById}"), Object.class, trackById);
+ }
+
+ public class JobInfoChecker<Integer> implements Predicate<Integer> {
+
+ protected final RestTemplate restTemplate;
+ protected Set<JobStatus> expectedJobStatus;
+ protected ServiceInfo expectedServiceInfo;
+ protected final String jobId;
+ protected JobStatus lastStatus;
+
+ public JobInfoChecker(RestTemplate restTemplate, Set<JobStatus> expectedJobStatus, String jobId, ServiceInfo expectedServiceInfo) {
+ this.restTemplate = restTemplate;
+ this.expectedJobStatus = expectedJobStatus;
+ this.jobId = jobId;
+ this.expectedServiceInfo = expectedServiceInfo;
+ }
+
+ public void setExpectedJobStatus(Set<JobStatus> expectedJobStatus) {
+ this.expectedJobStatus = expectedJobStatus;
+ }
+
+ @Override
+ public boolean test(Integer integer) {
+ ResponseEntity<List<ServiceInfo>> serviceListResponse = serviceListCall();
+ assertThat(serviceListResponse.getStatusCode(), CoreMatchers.equalTo(HttpStatus.OK));
+ assertThat(serviceListResponse.getBody(), hasItem(new JobIdAndStatusMatcher(jobId)));
+ ServiceInfo serviceInfoFromDB = serviceListResponse.getBody().stream()
+ .filter(serviceInfo -> serviceInfo.jobId.equals(jobId))
+ .findFirst().orElse(null);
+ Assert.assertNotNull(serviceInfoFromDB);
+ Assert.assertEquals(serviceInfoDataReflected(expectedServiceInfo), serviceInfoDataReflected(serviceInfoFromDB));
+ assertTrue("actual service instance doesn't contain template service name:" + expectedServiceInfo.serviceInstanceName,
+ serviceInfoFromDB.serviceInstanceName.contains(expectedServiceInfo.serviceInstanceName));
+
+ if (expectedServiceInfo.serviceInstanceId != null && ImmutableList.of(JobStatus.COMPLETED, JobStatus.PAUSE, JobStatus.COMPLETED_WITH_ERRORS).contains(serviceInfoFromDB.jobStatus)) {
+ MatcherAssert.assertThat("service instance id is wrong", serviceInfoFromDB.serviceInstanceId, CoreMatchers.is(expectedServiceInfo.serviceInstanceId));
+ }
+ if (expectedJobStatus.size()==1) {
+ assertEquals("job status is wrong", getExpectedRetryEnabled((JobStatus)(expectedJobStatus.toArray()[0])), serviceInfoFromDB.isRetryEnabled);
+ }
+ lastStatus = serviceInfoFromDB.jobStatus;
+ return expectedJobStatus.contains(serviceInfoFromDB.jobStatus);
+ }
+ }
+
+ protected ResponseEntity<List<ServiceInfo>> serviceListCall() {
+ return restTemplate.exchange(
+ getServiceInfoUrl(),
+ org.springframework.http.HttpMethod.GET,
+ null,
+ new ParameterizedTypeReference<List<ServiceInfo>>() {});
+ }
+
+ //serialize fields except of fields we cannot know ahead of time
+ protected static String serviceInfoDataReflected(ServiceInfo service1) {
+ return new ReflectionToStringBuilder(service1, ToStringStyle.SHORT_PREFIX_STYLE)
+ .setExcludeFieldNames("jobStatus", "templateId", "statusModifiedDate", "createdBulkDate", "serviceInstanceId", "serviceInstanceName", "isRetryEnabled")
+ .toString();
+ }
+
+ protected void addBulkPendingWithCustomList(List<BasePreset> customPresets){
+ Map<Keys, String> names = generateNames();
+ final int bulkSize = 2 + customPresets.size();
+
+ List<BasePreset> msoBulkPresets = generateMsoCreateBulkPresets(bulkSize, names);
+ ImmutableList<BasePreset> presets = new ImmutableList.Builder<BasePreset>()
+ .add(new PresetGetSessionSlotCheckIntervalGet())
+ .add(new PresetAAIGetSubscribersGet())
+ .addAll(msoBulkPresets)
+ .addAll(customPresets)
+ .build();
+
+ List<String> jobIds = createBulkOfMacroInstances(presets, false, bulkSize, names);
+ Assert.assertEquals(jobIds.size(),bulkSize);
+ }
+
+ protected void verifyAuditStatuses(String jobId, List<String> statuses, JobAuditStatus.SourceStatus source) {
+ int statusesSize = statuses.size();
+ AtomicReference<List<JobAuditStatus>> actualAudits = new AtomicReference<>();
+ if (source.equals(JobAuditStatus.SourceStatus.VID)) {
+ actualAudits.set(getAuditStatuses(jobId, JobAuditStatus.SourceStatus.VID.name()));
+ org.junit.Assert.assertEquals("Received number of VID statuses is not as expected", statusesSize, actualAudits.get().size());
+ } else {
+ boolean isStatusedSizeAsExpected = Wait.waitFor(x-> {
+ actualAudits.set(getAuditStatuses(jobId, JobAuditStatus.SourceStatus.MSO.name()));
+ return actualAudits.get().size() == statusesSize;
+ },null,5,1);
+ org.junit.Assert.assertTrue("Received number of MSO statuses is not as expected. Expected: " + statusesSize + ". Received: " + actualAudits.get().size(), isStatusedSizeAsExpected);
+ }
+ IntStream.range(0, statusesSize).forEach(i-> org.junit.Assert.assertEquals(source + " status #" + i + " is not as expected", statuses.get(i), actualAudits.get().get(i).getJobStatus()));
+ }
+
+ protected void verifyInstanceAuditStatuses(List<JobAuditStatus> expectedStatuses, List<JobAuditStatus> actualStatuses) {
+ final int expectedSize = expectedStatuses.size();
+ assertTrue("Expected statuses size is "+ expectedSize +", actual size is "+actualStatuses.size(), new Integer(expectedSize).equals(actualStatuses.size()));
+ IntStream.range(0, expectedSize).forEach(i-> {
+
+ final JobAuditStatus expectedStatus = expectedStatuses.get(i);
+ final JobAuditStatus actualStatus = actualStatuses.get(i);
+ org.junit.Assert.assertEquals("MSO status #" + i + " is not as expected", expectedStatus.getJobStatus(), actualStatus.getJobStatus());
+ org.junit.Assert.assertEquals("MSO requestId #" + i + " is not as expected", expectedStatus.getRequestId(), actualStatus.getRequestId());
+ org.junit.Assert.assertEquals("MSO additionalInfo #" + i + " is not as expected", expectedStatus.getAdditionalInfo(), actualStatus.getAdditionalInfo());
+ org.junit.Assert.assertEquals("MSO jobID #" + i + " is not as expected", expectedStatus.getJobId(), actualStatus.getJobId());
+ org.junit.Assert.assertEquals("MSO instanceName #" + i + " is not as expected", expectedStatus.getInstanceName(), actualStatus.getInstanceName());
+ org.junit.Assert.assertEquals("MSO instanceType #" + i + " is not as expected", expectedStatus.getInstanceType(), actualStatus.getInstanceType());
+ });
+ }
+}
diff --git a/vid-automation/src/main/java/org/onap/vid/api/BaseApiTest.java b/vid-automation/src/main/java/org/onap/vid/api/BaseApiTest.java
new file mode 100644
index 000000000..5b7b1b214
--- /dev/null
+++ b/vid-automation/src/main/java/org/onap/vid/api/BaseApiTest.java
@@ -0,0 +1,163 @@
+package org.onap.vid.api;
+
+import static java.util.Collections.singletonList;
+import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
+import static net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER;
+import static org.apache.commons.text.StringEscapeUtils.unescapeJson;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.isEmptyOrNullString;
+import static org.hamcrest.Matchers.not;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+import java.util.Properties;
+import java.util.Random;
+import java.util.TimeZone;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import org.apache.commons.io.IOUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.uri.internal.JerseyUriBuilder;
+import org.onap.sdc.ci.tests.datatypes.UserCredentials;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.web.client.DefaultResponseErrorHandler;
+import org.springframework.web.client.HttpStatusCodeException;
+import org.springframework.web.client.RestTemplate;
+import org.testng.annotations.BeforeClass;
+import vid.automation.test.infra.FeaturesTogglingConfiguration;
+import vid.automation.test.services.UsersService;
+import vid.automation.test.utils.CookieAndJsonHttpHeadersInterceptor;
+
+public class BaseApiTest {
+ protected static final Logger LOGGER = LogManager.getLogger(BaseApiTest.class);
+
+ @SuppressWarnings("WeakerAccess")
+ protected URI uri;
+ @SuppressWarnings("WeakerAccess")
+ protected ObjectMapper objectMapper = new ObjectMapper();
+ @SuppressWarnings("WeakerAccess")
+ protected Client client;
+ protected Random random;
+ protected final RestTemplate restTemplate = new RestTemplate();
+
+ protected final UsersService usersService = new UsersService();
+ protected final RestTemplate restTemplateErrorAgnostic = new RestTemplate();
+
+ @BeforeClass
+ public void init() {
+ uri = getUri();
+ objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+ client = ClientBuilder.newClient();
+ client.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
+ random = new Random(System.currentTimeMillis());
+ FeaturesTogglingConfiguration.initializeFeatureManager();
+ }
+
+ private URI getUri() {
+ String host = System.getProperty("VID_HOST", "10.0.0.10");
+ int port = Integer.valueOf(System.getProperty("VID_PORT", "8080"));
+ return new JerseyUriBuilder().host(host).port(port).scheme("http").path("vid").build();
+ }
+
+ public void login() {
+ login(getUserCredentials());
+ }
+
+ public void login(UserCredentials userCredentials) {
+ final List<ClientHttpRequestInterceptor> interceptors = singletonList(new CookieAndJsonHttpHeadersInterceptor(getUri(), userCredentials));
+ restTemplate.setInterceptors(interceptors);
+ restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
+ @Override
+ public void handleError(ClientHttpResponse response) throws IOException {
+ try {
+ super.handleError(response);
+ } catch (HttpStatusCodeException e) {
+ LOGGER.error("HTTP {}: {}", e.getStatusCode(), e.getResponseBodyAsString(), e);
+ throw e;
+ }
+ }
+ });
+
+ restTemplateErrorAgnostic.setInterceptors(interceptors);
+ restTemplateErrorAgnostic.setErrorHandler(new DefaultResponseErrorHandler() {
+ @Override
+ public boolean hasError(ClientHttpResponse response) {
+ return false;
+ }
+ });
+ }
+
+
+ //set time zone to UTC so clock will go closely with VID app
+ @BeforeClass
+ public void setDefaultTimeZoneToUTC() {
+ System.setProperty("user.timezone", "UTC");
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC")); //since TimeZone cache previous user.timezone
+ }
+
+ public UserCredentials getUserCredentials() {
+ final Properties configProp = new Properties();
+ try {
+ InputStream input = ClassLoader.getSystemResourceAsStream("test_config.properties");
+ configProp.load(input);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ String loginId = configProp.getProperty("test.loginId", "i'm illegal");
+ String loginPassword = configProp.getProperty("test.loginPassword", "i'm illegal");
+ return new UserCredentials(loginId, loginPassword, null, null, null);
+ }
+
+
+
+
+ protected String getCleanJsonString(String jsonString) {
+ // remove leading/trailing double-quotes and unescape
+ String res = unescapeJson(jsonString.replaceAll("^\"|\"$", ""));
+ LOGGER.debug("getCleanJsonString: " + jsonString + " ==> " + res);
+ return res;
+ }
+
+ protected String getCleanJsonString(Object object) throws JsonProcessingException {
+ if (object instanceof String) {
+ return getCleanJsonString((String) object);
+ } else {
+ return new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(object);
+ }
+ }
+
+ protected String buildUri(String path) {
+ return uri + "/" + path;
+ }
+
+ public static String getResourceAsString(String resourcePath) {
+ // load expected result
+ final URL resource = BaseApiTest.class.getClassLoader().getResource(resourcePath);
+ if (resource == null) throw new RuntimeException("resource file not found: " + resourcePath);
+ try {
+ return IOUtils.toString(resource, "UTF-8");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected void assertJsonEquals(String actual, String expected) {
+ LOGGER.info(actual);
+ assertThat(actual, not(isEmptyOrNullString()));
+
+ assertThat(actual, jsonEquals(expected)
+ .when(IGNORING_ARRAY_ORDER)
+ );
+ }
+
+}
diff --git a/vid-automation/src/main/java/org/onap/vid/api/BaseMsoApiTest.java b/vid-automation/src/main/java/org/onap/vid/api/BaseMsoApiTest.java
new file mode 100644
index 000000000..175638008
--- /dev/null
+++ b/vid-automation/src/main/java/org/onap/vid/api/BaseMsoApiTest.java
@@ -0,0 +1,108 @@
+package org.onap.vid.api;
+
+import com.google.common.collect.ImmutableMap;
+import org.json.JSONException;
+import org.onap.simulator.presetGenerator.presets.BasePresets.BaseMSOPreset;
+import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset;
+import org.onap.vid.model.mso.MsoResponseWrapper2;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.skyscreamer.jsonassert.JSONCompareMode;
+import org.springframework.http.HttpMethod;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.HttpServerErrorException;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import vid.automation.test.services.SimulatorApi;
+import vid.automation.test.services.SimulatorApi.RegistrationStrategy;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.List;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+public class BaseMsoApiTest extends BaseApiTest {
+
+ @BeforeClass
+ public void login() {
+ super.login();
+ }
+
+ protected void callMsoWithSimulatedErrorResponse(String expectationJsonFileName, ImmutableMap<String, Object> replacementsForJson, String targetUri, String basicRequestBody, int expectedErrorCode, String expectedResult, HttpMethod method) throws IOException {
+ SimulatorApi.registerExpectation(expectationJsonFileName, replacementsForJson, RegistrationStrategy.CLEAR_THEN_SET);
+ callMsoAndAssertError(targetUri, basicRequestBody, expectedErrorCode, expectedResult, method);
+ }
+
+ protected void callMsoWithSimulatedErrorResponse(BaseMSOPreset expectation, String targetUri, String basicRequestBody, int expectedErrorCode, String expectedResult, HttpMethod method) throws IOException {
+ SimulatorApi.registerExpectationFromPreset(expectation, RegistrationStrategy.CLEAR_THEN_SET);
+ callMsoAndAssertError(targetUri, basicRequestBody, expectedErrorCode, expectedResult, method);
+ }
+
+ protected void callMsoWithSimulatedErrorResponse(List<BasePreset> expectations, String targetUri, String basicRequestBody, int expectedErrorCode, String expectedResult, HttpMethod method) throws IOException {
+ SimulatorApi.registerExpectationFromPresets(expectations, RegistrationStrategy.CLEAR_THEN_SET);
+ callMsoAndAssertError(targetUri, basicRequestBody, expectedErrorCode, expectedResult, method);
+ }
+
+ private void callMsoAndAssertError(String targetUri, String basicRequestBody, int expectedErrorCode, String expectedResult, HttpMethod method) throws IOException {
+ try {
+ MsoResponseWrapper2 responseWrapper = callMsoForResponseWrapper(method, targetUri, basicRequestBody);
+
+ assertThat("Wrong propagated status from MSO", responseWrapper.getStatus(), is(expectedErrorCode));
+ assertThat("Wrong propagated body from MSO", getCleanJsonString(responseWrapper.getEntity()), is(expectedResult));
+ }catch(HttpClientErrorException | HttpServerErrorException e) {
+ assertThat("Wrong propagated status from MSO", e.getStatusCode().value(), is(expectedErrorCode));
+ }
+ }
+
+
+ protected void callMsoWithFineRequest(String expectationJsonFileName, ImmutableMap<String, Object> replacementsForJson, String targetUri, String requestBody, int expectedStatusCode, String expectedResult, HttpMethod method) throws IOException {
+ SimulatorApi.registerExpectation(expectationJsonFileName, replacementsForJson, RegistrationStrategy.CLEAR_THEN_SET);
+ callMsoAndAssertSuccess(targetUri, requestBody, expectedStatusCode, expectedResult, method);
+ }
+
+ protected void callMsoWithFineRequest(BaseMSOPreset expectation, String targetUri, String requestBody, int expectedStatusCode, String expectedResult, HttpMethod method) throws IOException {
+ SimulatorApi.registerExpectationFromPreset(expectation, RegistrationStrategy.CLEAR_THEN_SET);
+ callMsoAndAssertSuccess(targetUri, requestBody, expectedStatusCode, expectedResult, method);
+ }
+
+ protected void callMsoWithFineRequest(List<BasePreset> expectations, String targetUri, String requestBody, int expectedStatusCode, String expectedResult, HttpMethod method) throws IOException {
+ SimulatorApi.registerExpectationFromPresets(expectations, RegistrationStrategy.CLEAR_THEN_SET);
+ callMsoAndAssertSuccess(targetUri, requestBody, expectedStatusCode, expectedResult, method);
+ }
+
+ private void callMsoAndAssertSuccess(String targetUri, String requestBody, int expectedStatusCode, String expectedResult, HttpMethod method) throws IOException {
+ MsoResponseWrapper2 responseWrapper = callMsoForResponseWrapper(method, targetUri, requestBody);
+
+ assertThat("Wrong propagated status from MSO", responseWrapper.getStatus(), is(expectedStatusCode));
+ try {
+ JSONAssert.assertEquals("Wrong propagated body from MSO", expectedResult, getCleanJsonString(responseWrapper.getEntity()), JSONCompareMode.NON_EXTENSIBLE);
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected MsoResponseWrapper2 callMsoForResponseWrapper(HttpMethod method, String uri, String body) {
+ MsoResponseWrapper2 responseWrapper;
+ switch (method) {
+ case POST:
+ responseWrapper = restTemplate.postForObject(uri, body, MsoResponseWrapper2.class);
+ break;
+ case GET:
+ default:
+ responseWrapper = restTemplate.getForObject(uri, MsoResponseWrapper2.class);
+ break;
+ }
+
+ System.out.println("response: " + responseWrapper);
+
+ return responseWrapper;
+ }
+
+ @DataProvider
+ public static Object[][] errorCodes(Method test) {
+ return new Object[][]{
+ {500},{505}, {400}, {401}, {404}, {405}
+ };
+ }
+}
diff --git a/vid-automation/src/main/java/org/onap/vid/api/CreateInstanceWithFailedService.java b/vid-automation/src/main/java/org/onap/vid/api/CreateInstanceWithFailedService.java
new file mode 100644
index 000000000..6c8f3fade
--- /dev/null
+++ b/vid-automation/src/main/java/org/onap/vid/api/CreateInstanceWithFailedService.java
@@ -0,0 +1,87 @@
+package org.onap.vid.api;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset;
+import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOwnersByCloudRegionId;
+import org.onap.simulator.presetGenerator.presets.mso.*;
+import org.springframework.http.ResponseEntity;
+import vid.automation.test.model.JobStatus;
+import vid.automation.test.model.ServiceAction;
+import vid.automation.test.services.SimulatorApi;
+
+import java.util.List;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
+import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys.SERVICE_NAME;
+import static org.onap.vid.api.AsyncInstantiationBase.CREATE_BULK_OF_ALACARTE_REQUEST_WITH_VNF;
+import static org.onap.vid.api.TestUtils.hasOrLacksOfEntry;
+import static vid.automation.test.services.SimulatorApi.registerExpectationFromPreset;
+import static vid.automation.test.services.SimulatorApi.registerExpectationFromPresets;
+
+public class CreateInstanceWithFailedService {
+ private CreateServiceWithFailedVnf.ResourceIds firstIds = new CreateServiceWithFailedVnf.ResourceIds();
+ private AsyncInstantiationBase asyncInstantiationBase;
+ private List<PresetMSOBaseCreateInstancePost> createPresets;
+ private String serviceInstanceName = TestUtils.generateRandomAlphaNumeric(10);
+ private ImmutableMap<PresetMSOServiceInstanceGen2WithNames.Keys, String> names;
+ private List<PresetMSOOrchestrationRequestGet> inProgressPresets;
+ private List<String> uuids;
+ private String originalJobId;
+ ObjectMapper objectMapper = new ObjectMapper();
+
+
+ public CreateInstanceWithFailedService(AsyncInstantiationBase asyncInstantiationALaCarteApiTest) {
+ this.asyncInstantiationBase = asyncInstantiationALaCarteApiTest;
+ }
+
+ private CreateInstanceWithFailedService createInstanceWithFailedService() {
+
+ names = ImmutableMap.of(SERVICE_NAME, serviceInstanceName);
+
+ final String serviceFailedStatusMessage = "The service instantiation is failed.";
+ createPresets = ImmutableList.of(
+ new PresetMSOCreateServiceInstanceGen2WithNamesAlacarteService(names, 0, firstIds.serviceReqId, firstIds.serviceId)
+ );
+ inProgressPresets = ImmutableList.of(
+ new PresetMSOOrchestrationRequestGet("FAILED", firstIds.serviceReqId, serviceFailedStatusMessage)
+ );
+ List<BasePreset> presets = asyncInstantiationBase.getPresets(createPresets, inProgressPresets);
+
+ registerExpectationFromPresets(presets, SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET);
+ registerExpectationFromPreset(PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MDT1_TO_ATT_NC, SimulatorApi.RegistrationStrategy.APPEND);
+
+ uuids = asyncInstantiationBase.createBulkOfInstances(false, 1, names, CREATE_BULK_OF_ALACARTE_REQUEST_WITH_VNF);
+ return this;
+ }
+
+ protected void deployServiceFailedInstance() {
+ createInstanceWithFailedService();
+ firstTimeAssertion();
+ prepareAndAssertJsonFileForCypressTest();
+ }
+
+ private void prepareAndAssertJsonFileForCypressTest() {
+ final ResponseEntity<String> responseEntity = asyncInstantiationBase.getRetryBulk(originalJobId);
+ String expected = TestUtils.convertRequest(objectMapper, "asyncInstantiation/ServiceWithFailedServiceInstance.json");
+ expected = expected
+ .replace("SERVICE_NAME", serviceInstanceName);
+ String originalResponse = responseEntity.getBody();
+ String responseToCompare = originalResponse.replaceFirst("(instanceName\":\")(.*?)(\")", "$1INSTANCE_NAME$3").replaceAll("(trackById\":\")(.*?)(\")", "$1TRACK_BY_ID$3");
+ asyncInstantiationBase.assertJsonEquals(responseToCompare, expected);
+ }
+
+ private void firstTimeAssertion() {
+ assertThat(uuids, hasSize(1));
+ originalJobId = uuids.get(0);
+ asyncInstantiationBase.assertServiceInfoSpecific1(originalJobId, JobStatus.FAILED, names.get(SERVICE_NAME), "us16807000", firstIds.serviceId, ServiceAction.INSTANTIATE);
+ asyncInstantiationBase.assertAuditStatuses(originalJobId, asyncInstantiationBase.vidAuditStatusesFailed(originalJobId), null);
+ assertThat(SimulatorApi.retrieveRecordedRequestsPathCounter(), allOf(
+ hasOrLacksOfEntry(createPresets.get(0).getReqPath(), 1L),
+ hasOrLacksOfEntry(inProgressPresets.get(0).getReqPath(), 1L)
+ ));
+ }
+}
diff --git a/vid-automation/src/main/java/org/onap/vid/api/CreateServiceWithFailedVnf.java b/vid-automation/src/main/java/org/onap/vid/api/CreateServiceWithFailedVnf.java
new file mode 100644
index 000000000..30076a964
--- /dev/null
+++ b/vid-automation/src/main/java/org/onap/vid/api/CreateServiceWithFailedVnf.java
@@ -0,0 +1,226 @@
+package org.onap.vid.api;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.hamcrest.Matchers;
+import org.onap.simulator.presetGenerator.presets.BasePresets.BasePreset;
+import org.onap.simulator.presetGenerator.presets.aai.PresetAAIGetCloudOwnersByCloudRegionId;
+import org.onap.simulator.presetGenerator.presets.mso.*;
+import org.onap.simulator.presetGenerator.presets.sdc.PresetSDCGetServiceMetadataGet;
+import org.onap.simulator.presetGenerator.presets.sdc.PresetSDCGetServiceToscaModelGet;
+import org.onap.vid.model.asyncInstantiation.ServiceInfo;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import vid.automation.test.infra.ModelInfo;
+import vid.automation.test.model.JobStatus;
+import vid.automation.test.model.ServiceAction;
+import vid.automation.test.services.SimulatorApi;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
+import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys.SERVICE_NAME;
+import static org.onap.simulator.presetGenerator.presets.mso.PresetMSOServiceInstanceGen2WithNames.Keys.VNF_NAME;
+import static org.onap.vid.api.TestUtils.hasOrLacksOfEntry;
+import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertFalse;
+import static vid.automation.test.services.SimulatorApi.registerExpectationFromPreset;
+import static vid.automation.test.services.SimulatorApi.registerExpectationFromPresets;
+
+//CreateServiceWithFailedVnf is common for API test and UI test,
+//so if you change it, make sure both test are compatible with your changes
+public class CreateServiceWithFailedVnf {
+ private AsyncInstantiationBase asyncInstantiationBase;
+ private ImmutableMap<PresetMSOServiceInstanceGen2WithNames.Keys, String> names;
+ private List<PresetMSOBaseCreateInstancePost> createPresets;
+ private List<PresetMSOOrchestrationRequestGet> inProgressPresets;
+ private List<String> uuids;
+ private List<String> retryUuids;
+ private String originalJobId;
+ private String serviceInstanceName = TestUtils.generateRandomAlphaNumeric(10);
+ private ResourceIds firstIds = new ResourceIds();
+ private ResourceIds retryIds = new ResourceIds();
+ private String vnfEditedName = TestUtils.generateRandomAlphaNumeric(10);
+ ObjectMapper objectMapper = new ObjectMapper();
+ public final ModelInfo serviceComplexService = new ModelInfo("e3c34d88-a216-4f1d-a782-9af9f9588705", "0367689e-d41e-483f-b200-eab17e4a7f8d", "service-Complexservice-aLaCarte-csar-2.zip");
+
+ public CreateServiceWithFailedVnf(AsyncInstantiationBase asyncInstantiationALaCarteApiTest) {
+ this.asyncInstantiationBase = asyncInstantiationALaCarteApiTest;
+ }
+
+ public ImmutableMap<PresetMSOServiceInstanceGen2WithNames.Keys, String> getNames() {
+ return names;
+ }
+
+ public ResourceIds getFirstIds() {
+ return firstIds;
+ }
+
+ public static class ResourceIds {
+ public String serviceId =UUID.randomUUID().toString();
+ public String serviceReqId =UUID.randomUUID().toString();
+ public String vnfId =UUID.randomUUID().toString();
+ public String vnfReqId =UUID.randomUUID().toString();
+ }
+
+
+ public CreateServiceWithFailedVnf createServicesWithVnfCompletedWithError() {
+/*
+Legit Preset || deploy 1 Service, 1 VNF which will fail
+ -> JobStatus of service is COMPLETED_WITH_ERRORS, audit
+ is adequate; strict simulator comapre
+ */
+
+ names = ImmutableMap.of(SERVICE_NAME, serviceInstanceName, VNF_NAME, serviceInstanceName+"_vnf");
+
+
+
+ final String vnfFailedStatusMessage = "Vnf failed.";
+ createPresets = ImmutableList.of(
+ new PresetMSOCreateServiceInstanceGen2WithNamesAlacarteService(names, 0, firstIds.serviceReqId, firstIds.serviceId),
+ new PresetMSOCreateVNFInstanceOnlyRelatedServiceInstance(names.get(VNF_NAME),firstIds.vnfReqId , firstIds.serviceId, firstIds.vnfId, 0)
+ );
+ inProgressPresets = ImmutableList.of(
+ new PresetMSOOrchestrationRequestGet("COMPLETE", firstIds.serviceReqId),
+ new PresetMSOOrchestrationRequestGet("FAILED", firstIds.vnfReqId, vnfFailedStatusMessage)
+ );
+ List<BasePreset> presets = asyncInstantiationBase.getPresets(createPresets, inProgressPresets);
+
+ registerExpectationFromPresets(presets, SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET);
+ registerExpectationFromPreset(PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MDT1_TO_ATT_NC, SimulatorApi.RegistrationStrategy.APPEND);
+
+ uuids = asyncInstantiationBase.createBulkOfInstances(false, 1, names, AsyncInstantiationBase.CREATE_BULK_OF_ALACARTE_REQUEST_WITH_VNF);
+ return this;
+ }
+
+ public void firstTimeAssertion() {
+ assertThat(uuids, hasSize(1));
+ originalJobId = uuids.get(0);
+
+ asyncInstantiationBase.assertServiceInfoSpecific1(originalJobId, JobStatus.COMPLETED_WITH_ERRORS, names.get(SERVICE_NAME), "us16807000", firstIds.serviceId, ServiceAction.INSTANTIATE);
+ asyncInstantiationBase.assertAuditStatuses(originalJobId, asyncInstantiationBase.vidAuditStatusesCompletedWithErrors(originalJobId),null);
+ assertThat(SimulatorApi.retrieveRecordedRequestsPathCounter(), allOf(
+ hasOrLacksOfEntry(createPresets.get(0).getReqPath(), 1L),
+ hasOrLacksOfEntry(createPresets.get(1).getReqPath(), 1L),
+ hasOrLacksOfEntry(inProgressPresets.get(0).getReqPath(), 1L),
+ hasOrLacksOfEntry(inProgressPresets.get(1).getReqPath(), 1L)
+ ));
+ }
+
+ public String getBulkForRetry(){
+ final ResponseEntity<String> responseEntity= asyncInstantiationBase.getRetryBulk(originalJobId);
+ String expected = TestUtils.convertRequest(objectMapper, "asyncInstantiation/ServiceTreeForRetry_serviceInstance.json");
+ expected = expected
+ .replace("SERVICE_NAME", serviceInstanceName);
+ String originalResponse = responseEntity.getBody();
+ String responseToCompare = originalResponse.replaceFirst( "(instanceId\":\")(.*?)(\")", "$1INSTANCE_ID$3")
+ .replaceAll( "(trackById\":\")(.*?)(\")", "$1TRACK_BY_ID$3");
+ asyncInstantiationBase.assertJsonEquals(responseToCompare, expected);
+ return originalResponse;
+ }
+
+ public void getBulkForRetryNotFound() {
+ UUID jobId= UUID.randomUUID();
+ final ResponseEntity<String> response = asyncInstantiationBase.getRetryBulk(jobId.toString());
+ assertThat(response.getStatusCode(), is(HttpStatus.NOT_FOUND));
+ assertThat(response.getBody(),containsString("Failed to retrieve class org.onap.vid.dao.JobRequest with JOB_ID "+jobId+" from table. no resource found"));
+ }
+
+ private void secondRegistration(String vnfName) {
+ createPresets = ImmutableList.of(
+ new PresetMSOCreateVNFInstanceOnlyRelatedServiceInstance(vnfName, retryIds.vnfReqId, firstIds.serviceId, retryIds.vnfId, 0)
+ );
+ inProgressPresets = ImmutableList.of(
+ new PresetMSOOrchestrationRequestGet("COMPLETE", retryIds.vnfReqId)
+ );
+
+ registerExpectationFromPresets(asyncInstantiationBase.getPresets(createPresets, inProgressPresets), SimulatorApi.RegistrationStrategy.CLEAR_THEN_SET);
+ registerExpectationFromPresets(ImmutableList.of(
+ PresetAAIGetCloudOwnersByCloudRegionId.PRESET_MDT1_TO_ATT_NC,
+ new PresetSDCGetServiceMetadataGet(serviceComplexService),
+ new PresetSDCGetServiceToscaModelGet(serviceComplexService)),
+ SimulatorApi.RegistrationStrategy.APPEND);
+
+
+ }
+
+ public String deployService1FailedVnf(){
+ createServicesWithVnfCompletedWithError();
+ firstTimeAssertion();
+ return getBulkForRetry();
+ }
+
+ public void assertResourceAuditStatus(String bulkForRetry) {
+ String vnfTrackById = extractVnfTrackById(bulkForRetry);
+
+ Map<String, Object> auditStatus = (Map) asyncInstantiationBase.getResourceAuditInfo(vnfTrackById);
+ assertThat(auditStatus.get("jobStatus"), equalTo("FAILED"));
+ assertThat(auditStatus.get("additionalInfo"), equalTo("Vnf failed."));
+ assertThat(auditStatus.get("requestId"), equalTo(firstIds.vnfReqId));
+ }
+
+ private String extractVnfTrackById(String bulk) {
+ Map<String, Object> serviceInstantiation = null;
+ try {
+ serviceInstantiation = objectMapper.readValue(bulk, new TypeReference<Map<String, Object>>(){});
+ Map<String, Object> vnf = (Map) ((Map) serviceInstantiation.get("vnfs")).get("vSAMP12 1");
+ return vnf.get("trackById").toString();
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+
+ public void secondRegistration() {
+ secondRegistration(names.get(VNF_NAME));
+ }
+
+ public void retryJob() {
+ //retry the previous job
+ retryUuids = asyncInstantiationBase.retryJob(originalJobId);
+ }
+
+ public void retryJobWithOtherDataAndAssert(String requestBody){
+ retryUuids = asyncInstantiationBase.retryJobWithChangedData(originalJobId, requestBody);
+ retryAssertion();
+ simulatorCallsAssertion();
+ }
+
+ public String changeSomeDataAndRegisterToSimulator(String payload){
+ payload = payload.replace(names.get(VNF_NAME), vnfEditedName);
+ secondRegistration(vnfEditedName);
+ return payload;
+ }
+
+
+ public void retryAssertion() {
+
+ assertThat(retryUuids, Matchers.hasSize(1));
+ String retryJobId = retryUuids.get(0);
+ assertThat(retryJobId, not(equalTo(originalJobId)));
+ asyncInstantiationBase.assertServiceInfoSpecific1(retryJobId, JobStatus.COMPLETED, names.get(SERVICE_NAME), "us16807000", firstIds.serviceId, ServiceAction.UPDATE);
+
+ //make sure original job is retry is disabled.
+ Optional<ServiceInfo> optionalServiceInfo = asyncInstantiationBase.serviceListCall().getBody().stream().filter(si -> originalJobId.equals(si.jobId)).findFirst();
+ assertTrue(optionalServiceInfo.isPresent());
+ assertFalse(optionalServiceInfo.get().isRetryEnabled);
+ }
+
+ public void simulatorCallsAssertion() {
+ assertThat(SimulatorApi.retrieveRecordedRequestsPathCounter(), allOf(
+ hasOrLacksOfEntry(createPresets.get(0).getReqPath(), 1L),
+ hasOrLacksOfEntry(inProgressPresets.get(0).getReqPath(), 1L)
+ ));
+ }
+
+
+}
diff --git a/vid-automation/src/main/java/org/onap/vid/api/TestUtils.java b/vid-automation/src/main/java/org/onap/vid/api/TestUtils.java
new file mode 100644
index 000000000..a2fe82e9d
--- /dev/null
+++ b/vid-automation/src/main/java/org/onap/vid/api/TestUtils.java
@@ -0,0 +1,99 @@
+package org.onap.vid.api;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import org.apache.commons.text.RandomStringGenerator;
+import org.hamcrest.Matcher;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+import org.springframework.http.HttpStatus;
+
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Scanner;
+
+import static org.apache.commons.text.CharacterPredicates.DIGITS;
+import static org.apache.commons.text.CharacterPredicates.LETTERS;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.*;
+import static vid.automation.test.utils.RegExMatcher.matchesRegEx;
+
+public class TestUtils {
+
+ protected static ObjectMapper objectMapper = new ObjectMapper();
+
+ public static void assertStatusOK(Object request, WebTarget webTarget, Response response) throws IOException {
+ assertHttpStatus(request, webTarget, response, HttpStatus.OK);
+ }
+
+ public static void assertHttpStatus(Object request, WebTarget webTarget, Response response, HttpStatus exceptedHttpStatus) throws IOException {
+ objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
+
+ org.testng.Assert.assertEquals(response.getStatus(), exceptedHttpStatus.value(),
+ String.format("Failed post URI: %s with request %s. Got Status:%d and body: %s",
+ webTarget.getUri(),
+ objectMapper.writeValueAsString(request),
+ response.getStatus(),
+ objectMapper.writeValueAsString(response.getEntity())));
+ }
+
+ public static String convertRequest(ObjectMapper objectMapper, String msoRequestDetailsFileName) {
+
+ ClassLoader cl = TestUtils.class.getClassLoader();
+ ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
+ Resource[] resources;
+ try {
+ resources = resolver.getResources(msoRequestDetailsFileName);
+ //using InputStream and not file. see https://stackoverflow.com/questions/14876836/file-inside-jar-is-not-visible-for-spring/51131841#51131841
+ InputStream inputStream = resources[0].getInputStream();
+ String content = new Scanner(inputStream).useDelimiter("\\Z").next();
+ objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
+ return objectMapper.writeValueAsString(objectMapper.readValue(content, Object.class));
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String getNestedPropertyInMap(Object item, String path) {
+ return getNestedPropertyInMap(item, path, String.class, "/");
+ }
+
+ public static <T> T getNestedPropertyInMap(Object item, String path, Class<T> valueType) {
+ return getNestedPropertyInMap(item, path, valueType, "/");
+ }
+
+ /*
+ Use this method to extract item from Map that represent Json hierarchy (Map<String,Map>)
+ */
+ public static <T> T getNestedPropertyInMap(Object item, String path, Class<T> valueType, String delimeter) {
+ String[] pathes = path.split(delimeter);
+ return valueType.cast(getNestedPropertyInMap(item,pathes,0));
+ }
+
+ private static Object getNestedPropertyInMap(Object item, String[] pathes, int index) {
+ if (index==pathes.length) {
+ return item;
+ }
+ return getNestedPropertyInMap(((Map<String,Object>)item).get(pathes[index]), pathes, ++index);
+ }
+
+ static Matcher hasOrLacksOfEntry(String pathRegex, Long expectedCounter) {
+ return expectedCounter.equals(0L) ? not(hasKey(matchesRegEx(pathRegex))) : hasEntry(matchesRegEx(pathRegex), is(expectedCounter));
+ }
+
+ private static RandomStringGenerator generator = new RandomStringGenerator.Builder()
+ .withinRange('0', 'z')
+ .filteredBy(LETTERS, DIGITS)
+ .build();
+
+ public static String generateRandomAlphaNumeric(int length) {
+ return generator.generate(length);
+ }
+}