diff options
author | MatthieuGeerebaert <matthieu.geerebaert@orange.com> | 2018-03-28 13:36:26 +0200 |
---|---|---|
committer | MatthieuGeerebaert <matthieu.geerebaert@orange.com> | 2018-04-03 23:35:04 +0200 |
commit | 99bf586a6eb9799c4f33e43976d741f2807ea287 (patch) | |
tree | 817406c30c99f366c000afc3fe0963b6b32499e7 | |
parent | 65fd3da0ea090f3c1fc82cea0c49547dbf362fcf (diff) |
Add serviceCatalog rest services
- Add get and find serviceSpecification operations
- Add API exceptions management
- Consumes SDC apis
- Add tests
- Fix pom.xml conflict
Change-Id: Id103d83dc8a981885100daabe868cdf18a922975
Issue-ID: EXTAPI-39
Signed-off-by: MatthieuGeerebaert <matthieu.geerebaert@orange.com>
28 files changed, 2001 insertions, 59 deletions
@@ -20,10 +20,10 @@ <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - <nexusproxy>https://nexus.onap.org</nexusproxy> - <snapshotNexusPath>/content/repositories/snapshots/</snapshotNexusPath> - <releaseNexusPath>/content/repositories/releases/</releaseNexusPath> - <stagingNexusPath>/content/repositories/staging/</stagingNexusPath> + <nexusproxy>https://nexus.onap.org</nexusproxy> + <snapshotNexusPath>/content/repositories/snapshots/</snapshotNexusPath> + <releaseNexusPath>/content/repositories/releases/</releaseNexusPath> + <stagingNexusPath>/content/repositories/staging/</stagingNexusPath> <java.version>1.8</java.version> </properties> @@ -34,37 +34,37 @@ <url>http://download.java.net/maven/2/</url> <layout>default</layout> </repository> - <repository> - <id>ecomp-snapshots</id> - <name>Snapshot Repository</name> - <url>${nexusproxy}/${snapshotNexusPath}</url> - </repository> - <repository> - <id>ecomp-staging</id> - <name>Staging Repository</name> - <url>${nexusproxy}/${stagingNexusPath}</url> - </repository> + <repository> + <id>ecomp-snapshots</id> + <name>Snapshot Repository</name> + <url>${nexusproxy}/${snapshotNexusPath}</url> + </repository> + <repository> + <id>ecomp-staging</id> + <name>Staging Repository</name> + <url>${nexusproxy}/${stagingNexusPath}</url> + </repository> </repositories> - <distributionManagement> - <repository> - <id>ecomp-releases</id> - <name>Release Repository</name> - <url>${nexusproxy}/${releaseNexusPath}</url> - </repository> - <snapshotRepository> - <id>ecomp-snapshots</id> - <name>Snapshot Repository</name> - <url>${nexusproxy}/${snapshotNexusPath}</url> - </snapshotRepository> - </distributionManagement> - + <distributionManagement> + <repository> + <id>ecomp-releases</id> + <name>Release Repository</name> + <url>${nexusproxy}/${releaseNexusPath}</url> + </repository> + <snapshotRepository> + <id>ecomp-snapshots</id> + <name>Snapshot Repository</name> + <url>${nexusproxy}/${snapshotNexusPath}</url> + </snapshotRepository> + </distributionManagement> + <licenses> <license> <name>Apache2</name> <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> </license> - </licenses> + </licenses> <dependencies> @@ -90,17 +90,67 @@ <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency> - - <!-- test --> - + + <!-- jackson --> + + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-yaml</artifactId> + <version>2.8.0</version> + </dependency> + + <!-- jolt --> + + <dependency> + <groupId>com.bazaarvoice.jolt</groupId> + <artifactId>jolt-core</artifactId> + <version>0.1.0</version> + </dependency> + + <dependency> + <groupId>com.bazaarvoice.jolt</groupId> + <artifactId>json-utils</artifactId> + <version>0.1.0</version> + </dependency> + + <!-- test --> + <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> - + + <!-- wiremock --> + + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-contract-wiremock</artifactId> + <version>1.0.0.RELEASE</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>9.4.7.RC0</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlets</artifactId> + <scope>test</scope> + </dependency> + <!-- runtime dev --> - + <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> @@ -115,29 +165,29 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> - <plugin> - <groupId>org.sonatype.plugins</groupId> - <artifactId>nexus-staging-maven-plugin</artifactId> - <version>1.6.7</version> - <extensions>true</extensions> - <configuration> - <nexusUrl>${nexusproxy}</nexusUrl> - <stagingProfileId>176c31dfe190a</stagingProfileId> - <serverId>ecomp-staging</serverId> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-site-plugin</artifactId> - <version>3.6</version> - <dependencies> - <dependency> - <groupId>org.apache.maven.wagon</groupId> - <artifactId>wagon-webdav-jackrabbit</artifactId> - <version>2.10</version> - </dependency> - </dependencies> - </plugin> + <plugin> + <groupId>org.sonatype.plugins</groupId> + <artifactId>nexus-staging-maven-plugin</artifactId> + <version>1.6.7</version> + <extensions>true</extensions> + <configuration> + <nexusUrl>${nexusproxy}</nexusUrl> + <stagingProfileId>176c31dfe190a</stagingProfileId> + <serverId>ecomp-staging</serverId> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-site-plugin</artifactId> + <version>3.6</version> + <dependencies> + <dependency> + <groupId>org.apache.maven.wagon</groupId> + <artifactId>wagon-webdav-jackrabbit</artifactId> + <version>2.10</version> + </dependency> + </dependencies> + </plugin> </plugins> </build> </project> diff --git a/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java b/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java new file mode 100644 index 0000000..5ee6528 --- /dev/null +++ b/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java @@ -0,0 +1,29 @@ +package org.onap.nbi; + +/** + * Contains ONAP SDC and AAI urlPaths + * + */ +public final class OnapComponentsUrlPaths { + + private OnapComponentsUrlPaths() {} + + // SDC + public static final String SDC_ROOT_URL = "/sdc/v1/catalog/services/"; + public static final String SDC_GET_PATH = "/metadata"; + public static final String SDC_TOSCA_PATH = "/toscaModel"; + + // AAI + public static final String AAI_GET_TENANTS_PATH = + "/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/$cloudOwner/$lcpCloudRegionId/tenants"; + public static final String AAI_GET_CUSTOMER_PATH = "/aai/v11/business/customers/customer/"; + public static final String AAI_GET_SERVICES_FOR_CUSTOMER_PATH = + "/aai/v11/business/customers/customer/$customerId/service-subscriptions"; + public static final String AAI_PUT_SERVICE_FOR_CUSTOMER_PATH = + "/aai/v11/business/customers/customer/$customerId/service-subscriptions/service-subscription/"; + public static final String AAI_GET_SERVICE_FOR_CUSTOMER_PATH = + "/aai/v11/business/customers/customer/$customerId/service-subscriptions/service-subscription/$serviceSpecName/service-instances/service-instance/$serviceId"; + public static final String AAI_GET_SERVICE_INSTANCES_PATH = + "/aai/v11/business/customers/customer/$customerId/service-subscriptions/service-subscription/$serviceSpecName/service-instances/"; + +} diff --git a/src/main/java/org/onap/nbi/apis/RestConfiguration.java b/src/main/java/org/onap/nbi/apis/RestConfiguration.java new file mode 100644 index 0000000..8152d6f --- /dev/null +++ b/src/main/java/org/onap/nbi/apis/RestConfiguration.java @@ -0,0 +1,18 @@ +package org.onap.nbi.apis; + +import org.onap.nbi.exceptions.BackendErrorHandler; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestConfiguration { + + @Bean + public RestTemplate restTemplate(RestTemplateBuilder builder) { + RestTemplate restTemplate = builder.build(); + restTemplate.setErrorHandler(new BackendErrorHandler()); + return restTemplate; + } +} diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/SdcClient.java b/src/main/java/org/onap/nbi/apis/servicecatalog/SdcClient.java new file mode 100644 index 0000000..abc8bda --- /dev/null +++ b/src/main/java/org/onap/nbi/apis/servicecatalog/SdcClient.java @@ -0,0 +1,145 @@ +package org.onap.nbi.apis.servicecatalog; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.io.IOUtils; +import org.onap.nbi.OnapComponentsUrlPaths; +import org.onap.nbi.exceptions.BackendFunctionalException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +/** + * @author user + * + */ +@Service +public class SdcClient { + + public static final String HTTP_CALL_SDC_ON = "HTTP call SDC on "; + @Autowired + private RestTemplate restTemplate; + + @Value("${sdc.host}") + private String sdcHost; + + @Value("${sdc.header.ecompInstanceId}") + private String ecompInstanceId; + + @Value("${sdc.header.authorization}") + private String sdcHeaderAuthorization; + + private static final String HEADER_ECOMP_INSTANCE_ID = "x-ecomp-instanceid"; + private static final String HEADER_AUTHORIZATION = "Authorization"; + + private static final Logger LOGGER = LoggerFactory.getLogger(SdcClient.class); + + + public LinkedHashMap callGet(String id) { + StringBuilder callURL = new StringBuilder().append(sdcHost).append(OnapComponentsUrlPaths.SDC_ROOT_URL).append(id) + .append(OnapComponentsUrlPaths.SDC_GET_PATH); + + ResponseEntity<Object> response = callSdc(callURL.toString()); + return (LinkedHashMap) response.getBody(); + + } + + public List<LinkedHashMap> callFind(MultiValueMap<String, String> parametersMap) { + + UriComponentsBuilder callURL = UriComponentsBuilder.fromHttpUrl(sdcHost + OnapComponentsUrlPaths.SDC_ROOT_URL); + if (parametersMap != null) { + Map<String, String> stringStringMap = parametersMap.toSingleValueMap(); + for (String key : stringStringMap.keySet()) { + if (!key.equals("fields")) { + callURL.queryParam(key, stringStringMap.get(key)); + } + } + } + + ResponseEntity<Object> response = callSdc(callURL.build().encode().toUri().toString()); + return (List<LinkedHashMap>) response.getBody(); + + } + + + public File callGetWithAttachment(String toscaModelUrl) { + StringBuilder callURL = new StringBuilder().append(sdcHost).append(toscaModelUrl); + + String fileName = System.currentTimeMillis() + "tosca.csar"; + ResponseEntity<byte[]> response = callSdcWithAttachment(callURL.toString()); + File toscaFile = new File(fileName); + try { + FileOutputStream toscaFileStream = new FileOutputStream(toscaFile); + if (response != null) { + IOUtils.write(response.getBody(), toscaFileStream); + } + toscaFileStream.close(); + } catch (IOException e) { + LOGGER.error("cannot get TOSCA File for url " + toscaModelUrl); + } + return toscaFile; + + } + + private HttpEntity<String> buildRequestHeader() { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add(HEADER_ECOMP_INSTANCE_ID, ecompInstanceId); + httpHeaders.add(HEADER_AUTHORIZATION, sdcHeaderAuthorization); + HttpEntity<String> entity = new HttpEntity<>("parameters", httpHeaders); + + return entity; + } + + + private ResponseEntity<Object> callSdc(String callURL) { + ResponseEntity<Object> response = + restTemplate.exchange(callURL, HttpMethod.GET, buildRequestHeader(), Object.class); + LOGGER.debug("response body : " + response.getBody().toString()); + LOGGER.info("response status : " + response.getStatusCodeValue()); + loggDebugIfResponseKo(callURL, response); + return response; + } + + private void loggDebugIfResponseKo(String callURL, ResponseEntity<Object> response) { + if (!response.getStatusCode().equals(HttpStatus.OK)) { + LOGGER.warn(HTTP_CALL_SDC_ON + callURL + " returns " + response.getStatusCodeValue() + ", " + + response.getBody().toString()); + } + } + + private ResponseEntity<byte[]> callSdcWithAttachment(String callURL) { + try { + ResponseEntity<byte[]> response = + restTemplate.exchange(callURL.toString(), HttpMethod.GET, buildRequestHeader(), byte[].class); + LOGGER.info("response status : " + response.getStatusCodeValue()); + if (!response.getStatusCode().equals(HttpStatus.OK)) { + LOGGER.warn(HTTP_CALL_SDC_ON + callURL.toString() + " returns " + response.getStatusCodeValue() + ", " + + response.getBody().toString()); + } + return response; + + } catch (BackendFunctionalException e) { + LOGGER.error(HTTP_CALL_SDC_ON + callURL.toString() + " error " + e); + + return null; + } + } + + +} + + diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationResource.java b/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationResource.java new file mode 100644 index 0000000..512b088 --- /dev/null +++ b/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationResource.java @@ -0,0 +1,46 @@ +package org.onap.nbi.apis.servicecatalog; + +import java.util.LinkedHashMap; +import java.util.List; +import org.onap.nbi.commons.JsonRepresentation; +import org.onap.nbi.commons.Resource; +import org.onap.nbi.commons.ResourceManagement; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/serviceSpecification") +public class ServiceSpecificationResource extends ResourceManagement<Resource> { + + + @Autowired + ServiceSpecificationService serviceSpecificationService; + + @GetMapping(value = "/{serviceSpecId}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity<Object> getServiceSpecification(@PathVariable String serviceSpecId, + @RequestParam MultiValueMap<String, String> params) { + LinkedHashMap response = serviceSpecificationService.get(serviceSpecId); + JsonRepresentation filter = new JsonRepresentation(params); + if (response.get("serviceSpecCharacteristic") != null) { + return this.getResponse(response, filter); + } else { + return this.getPartialResponse(response, filter); + + } + } + + @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity<Object> findServiceSpecification(@RequestParam MultiValueMap<String, String> params) { + List<LinkedHashMap> response = serviceSpecificationService.find(params); + JsonRepresentation filter = new JsonRepresentation(params); + return this.findResponse(response, filter, null); + } + +} diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationService.java b/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationService.java new file mode 100644 index 0000000..3b56819 --- /dev/null +++ b/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationService.java @@ -0,0 +1,51 @@ +package org.onap.nbi.apis.servicecatalog; + +import java.util.LinkedHashMap; +import java.util.List; +import org.onap.nbi.apis.servicecatalog.jolt.FindServiceSpecJsonTransformer; +import org.onap.nbi.apis.servicecatalog.jolt.GetServiceSpecJsonTransformer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.MultiValueMap; + +@Service +public class ServiceSpecificationService { + + @Autowired + SdcClient sdcClient; + + @Autowired + GetServiceSpecJsonTransformer getServiceSpecJsonTransformer; + + @Autowired + FindServiceSpecJsonTransformer findServiceSpecJsonTransformer; + + @Autowired + ToscaInfosProcessor toscaInfosProcessor; + + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceSpecificationService.class); + + + public LinkedHashMap get(String serviceSpecId) { + LinkedHashMap sdcResponse = sdcClient.callGet(serviceSpecId); + LinkedHashMap serviceCatalogResponse = (LinkedHashMap) getServiceSpecJsonTransformer.transform(sdcResponse); + LinkedHashMap toscaInfosTopologyTemplate = toscaInfosProcessor.getToscaInfos(serviceCatalogResponse); + if (toscaInfosTopologyTemplate != null) { + LOGGER.debug("tosca file found, retrieving informations"); + toscaInfosProcessor.buildResponseWithToscaInfos(toscaInfosTopologyTemplate, serviceCatalogResponse); + } else { + LOGGER.debug("no tosca file found, partial response"); + } + return serviceCatalogResponse; + } + + + public List<LinkedHashMap> find(MultiValueMap<String, String> parametersMap) { + List<LinkedHashMap> sdcResponse = sdcClient.callFind(parametersMap); + List<LinkedHashMap> serviceCatalogResponse = + (List<LinkedHashMap>) findServiceSpecJsonTransformer.transform(sdcResponse); + return serviceCatalogResponse; + } +} diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/ToscaInfosProcessor.java b/src/main/java/org/onap/nbi/apis/servicecatalog/ToscaInfosProcessor.java new file mode 100644 index 0000000..4bfbd7b --- /dev/null +++ b/src/main/java/org/onap/nbi/apis/servicecatalog/ToscaInfosProcessor.java @@ -0,0 +1,249 @@ +package org.onap.nbi.apis.servicecatalog; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FileUtils; +import org.onap.nbi.exceptions.TechnicalException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; + +@Service +public class ToscaInfosProcessor { + + @Autowired + SdcClient sdcClient; + + final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); // jackson databind + + private static final Logger LOGGER = LoggerFactory.getLogger(ToscaInfosProcessor.class); + + public void buildResponseWithToscaInfos(LinkedHashMap toscaInfosTopologyTemplate, + LinkedHashMap serviceCatalogResponse) { + if (toscaInfosTopologyTemplate.get("inputs") != null) { + ArrayList serviceSpecCharacteristic = new ArrayList(); + LinkedHashMap toscaInfos = (LinkedHashMap) toscaInfosTopologyTemplate.get("inputs"); + for (Object key : toscaInfos.keySet()) { + String keyString = (String) key; + LinkedHashMap inputParameter = (LinkedHashMap) toscaInfos.get(key); + LinkedHashMap mapParameter = new LinkedHashMap(); + String parameterType = (String) inputParameter.get("type"); + mapParameter.put("name", keyString); + mapParameter.put("description", inputParameter.get("description")); + mapParameter.put("valueType", parameterType); + mapParameter.put("@type", "ONAPserviceCharacteristic"); + mapParameter.put("required", inputParameter.get("required")); + mapParameter.put("status", inputParameter.get("status")); + List<LinkedHashMap> serviceSpecCharacteristicValues = + buildServiceSpecCharacteristicsValues(inputParameter, parameterType); + mapParameter.put("serviceSpecCharacteristicValue", serviceSpecCharacteristicValues); + serviceSpecCharacteristic.add(mapParameter); + } + + serviceCatalogResponse.put("serviceSpecCharacteristic", serviceSpecCharacteristic); + } + LinkedHashMap node_templates = (LinkedHashMap) toscaInfosTopologyTemplate.get("node_templates"); + + List<LinkedHashMap> resourceSpecifications = + (List<LinkedHashMap>) serviceCatalogResponse.get("resourceSpecification"); + for (LinkedHashMap resourceSpecification : resourceSpecifications) { + String id = (String) resourceSpecification.get("id"); + LOGGER.debug("get tosca infos for service id: " + id); + LinkedHashMap toscaInfosFromResourceId = getToscaInfosFromResourceUUID(node_templates, id); + resourceSpecification.put("modelCustomizationId", toscaInfosFromResourceId.get("customizationUUID")); + resourceSpecification.put("modelCustomizationName", toscaInfosFromResourceId.get("name")); + + } + } + + private List<LinkedHashMap> buildServiceSpecCharacteristicsValues(LinkedHashMap parameter, String parameterType) { + List<LinkedHashMap> serviceSpecCharacteristicValues = new ArrayList<>(); + if (!"map".equalsIgnoreCase(parameterType) && !"list".equalsIgnoreCase(parameterType)) { + LOGGER.debug("get tosca infos for serviceSpecCharacteristicValues of type map or string : " + parameter); + Object aDefault = parameter.get("default"); + if (parameter.get("entry_schema") != null) { + ArrayList entry_schema = (ArrayList) parameter.get("entry_schema"); + if (CollectionUtils.isNotEmpty(entry_schema)) { + buildCharacteristicValuesFormShema(parameterType, serviceSpecCharacteristicValues, aDefault, + entry_schema); + } + } + } + return serviceSpecCharacteristicValues; + } + + private void buildCharacteristicValuesFormShema(String parameterType, + List<LinkedHashMap> serviceSpecCharacteristicValues, Object aDefault, ArrayList entry_schema) { + LinkedHashMap constraints = (LinkedHashMap) entry_schema.get(0); + if (constraints != null) { + ArrayList constraintsList = (ArrayList) constraints.get("constraints"); + if (CollectionUtils.isNotEmpty(constraintsList)) { + LinkedHashMap valuesMap = (LinkedHashMap) constraintsList.get(0); + if (valuesMap != null) { + List<Object> values = (List<Object>) valuesMap.get("valid_values"); + for (Object value : values) { + String stringValue = value.toString(); + LinkedHashMap serviceSpecCharacteristicValue = new LinkedHashMap(); + serviceSpecCharacteristicValue.put("isDefault", + aDefault != null && aDefault.toString().equals(stringValue)); + serviceSpecCharacteristicValue.put("value", stringValue); + serviceSpecCharacteristicValue.put("valueType", parameterType); + serviceSpecCharacteristicValues.add(serviceSpecCharacteristicValue); + } + } + } + } + } + + + private LinkedHashMap getToscaInfosFromResourceUUID(LinkedHashMap node_templates, String name) { + for (Object nodeTemplateObject : node_templates.values()) { + LinkedHashMap nodeTemplate = (LinkedHashMap) nodeTemplateObject; + LinkedHashMap metadata = (LinkedHashMap) nodeTemplate.get("metadata"); + String metadataUUID = (String) metadata.get("UUID"); + String metadataType = (String) metadata.get("type"); + if ("VF".equalsIgnoreCase(metadataType) && name.equalsIgnoreCase(metadataUUID)) { + return metadata; + } + } + return null; + } + + + public LinkedHashMap getToscaInfos(LinkedHashMap sdcResponse) { + String toscaModelUrl = (String) sdcResponse.get("toscaModelURL"); + String serviceId = (String) sdcResponse.get("uuid"); + File toscaFile = sdcClient.callGetWithAttachment(toscaModelUrl); + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + String tempFolderName = serviceId + timestamp; + File folderTemp = null; + LinkedHashMap topology_template = null; + try { + unZipArchive(toscaFile.getName(), tempFolderName); + folderTemp = new File(tempFolderName); + LOGGER.debug("temp folder for tosca files : " + folderTemp.getName()); + + LinkedHashMap toscaMetaFileHashMap = parseToscaFile(tempFolderName + "/TOSCA-Metadata/TOSCA.meta"); + if (toscaMetaFileHashMap.get("Entry-Definitions") == null) { + throw new NullPointerException("no Entry-Definitions node in TOSCA.meta"); + } + String toscaFilePath = (String) toscaMetaFileHashMap.get("Entry-Definitions"); + LinkedHashMap toscaFileHashMap = parseToscaFile(tempFolderName + "/" + toscaFilePath); + + if (toscaFileHashMap.get("topology_template") == null) { + throw new NullPointerException("no topology_template node in tosca file"); + } + topology_template = (LinkedHashMap) toscaFileHashMap.get("topology_template"); + + } catch (NullPointerException e) { + LOGGER.error("unable to parse tosca file for id : " + serviceId + ", " + e.getMessage()); + return null; + } finally { + try { + LOGGER.debug("deleting temp folder for tosca files : " + folderTemp.getName()); + FileUtils.deleteDirectory(folderTemp); + LOGGER.debug("deleting tosca archive : " + toscaFile.getName()); + FileUtils.forceDelete(toscaFile); + return topology_template; + } catch (IOException e) { + LOGGER.error("unable to delete temp directory tosca file for id : " + serviceId); + return null; + + } + } + } + + + private LinkedHashMap parseToscaFile(String fileName) { + + File toscaFile = new File(fileName); + if (toscaFile == null) { + throw new TechnicalException("unable to find file : " + fileName); + } + try { + return (LinkedHashMap) mapper.readValue(toscaFile, Object.class); + } catch (IOException e) { + LOGGER.error("unable to parse tosca file : " + fileName); + LOGGER.error(e.getMessage()); + throw new TechnicalException("Unable to parse tosca file : " + fileName); + + } catch (NullPointerException e) { + LOGGER.error("unable to find tosca file : " + fileName); + LOGGER.error(e.getMessage()); + throw new TechnicalException("unable to find tosca file : " + fileName); + } + } + + + /** + * Unzip it + * + * @param zipFile input zip file + * @param outputFolder zip file output folder + */ + private void unZipArchive(String zipFile, String outputFolder) { + + byte[] buffer = new byte[1024]; + + try { + + // create output directory is not exists + File folder = new File(outputFolder); + if (!folder.exists()) { + folder.mkdir(); + } + + // get the zip file content + try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { + // get the zipped file list entry + ZipEntry ze = zis.getNextEntry(); + + while (ze != null) { + + String fileName = ze.getName(); + File newFile = new File(outputFolder + File.separator + fileName); + + LOGGER.debug("File to unzip : " + newFile.getAbsoluteFile()); + + // create all non exists folders + // else you will hit FileNotFoundException for compressed folder + new File(newFile.getParent()).mkdirs(); + + try (FileOutputStream fos = new FileOutputStream(newFile)) { + + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + + fos.close(); + } + ze = zis.getNextEntry(); + } + + zis.closeEntry(); + zis.close(); + } + + LOGGER.debug("Done"); + + } catch (IOException ex) { + LOGGER.error("Error while unzipping ToscaModel archive from ONAP : " + ex.getMessage()); + throw new TechnicalException("Error while unzipping ToscaModel archive from ONAP"); + } + } + + +} diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/jolt/FindServiceSpecJsonTransformer.java b/src/main/java/org/onap/nbi/apis/servicecatalog/jolt/FindServiceSpecJsonTransformer.java new file mode 100644 index 0000000..b32f9fc --- /dev/null +++ b/src/main/java/org/onap/nbi/apis/servicecatalog/jolt/FindServiceSpecJsonTransformer.java @@ -0,0 +1,36 @@ +package org.onap.nbi.apis.servicecatalog.jolt; + +import com.bazaarvoice.jolt.Chainr; +import com.bazaarvoice.jolt.JsonUtils; +import com.bazaarvoice.jolt.exception.JoltException; +import org.onap.nbi.exceptions.TechnicalException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class FindServiceSpecJsonTransformer { + + private Chainr chainr; + + private static final Logger LOGGER = LoggerFactory.getLogger(FindServiceSpecJsonTransformer.class); + + public FindServiceSpecJsonTransformer() { + List<Object> specs = JsonUtils.classpathToList("/jolt/findServiceCatalog.json"); + this.chainr = Chainr.fromSpec(specs); + } + + public Object transform(Object serviceSpec) { + Object output = null; + try { + output = chainr.transform(serviceSpec); + } catch (JoltException joE) { + LOGGER.error("Unable to transform SDC response with JOLT Transformer : " + joE.getMessage()); + throw new TechnicalException("Error while parsing ONAP response"); + } + return output; + } + +} diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/jolt/GetServiceSpecJsonTransformer.java b/src/main/java/org/onap/nbi/apis/servicecatalog/jolt/GetServiceSpecJsonTransformer.java new file mode 100644 index 0000000..784ed6f --- /dev/null +++ b/src/main/java/org/onap/nbi/apis/servicecatalog/jolt/GetServiceSpecJsonTransformer.java @@ -0,0 +1,37 @@ +package org.onap.nbi.apis.servicecatalog.jolt; + +import com.bazaarvoice.jolt.Chainr; +import com.bazaarvoice.jolt.JsonUtils; +import com.bazaarvoice.jolt.exception.JoltException; +import org.onap.nbi.exceptions.TechnicalException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class GetServiceSpecJsonTransformer { + + private Chainr chainr; + + private static final Logger LOGGER = LoggerFactory.getLogger(GetServiceSpecJsonTransformer.class); + + + public GetServiceSpecJsonTransformer() { + List<Object> specs = JsonUtils.classpathToList("/jolt/getServiceCatalog.json"); + this.chainr = Chainr.fromSpec(specs); + } + + public Object transform(Object serviceSpec) { + Object output = null; + try { + output = chainr.transform(serviceSpec); + } catch (JoltException joE) { + LOGGER.error("Unable to transform SDC response with JOLT Transformer : " + joE.getMessage()); + throw new TechnicalException("Error while parsing ONAP response"); + } + return output; + } + +} diff --git a/src/main/java/org/onap/nbi/exceptions/ApiError.java b/src/main/java/org/onap/nbi/exceptions/ApiError.java new file mode 100644 index 0000000..5e030f8 --- /dev/null +++ b/src/main/java/org/onap/nbi/exceptions/ApiError.java @@ -0,0 +1,67 @@ +package org.onap.nbi.exceptions; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "Error", propOrder = { + "code", + "message", + "description", + "infoURL" +}) +public class ApiError { + @XmlElement(required = true) + protected String code; + @XmlElement(required = true) + protected String message; + @XmlElement(required = true) + private String description; + @XmlElement(required = true) + protected String infoURL; + + public ApiError() { + } + + public ApiError(String code, String message, String description, String infoURL) { + this.code = code; + this.message = message; + this.description = description; + this.infoURL = infoURL; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getInfoURL() { + return infoURL; + } + + public void setInfoURL(String infoURL) { + this.infoURL = infoURL; + } +} + diff --git a/src/main/java/org/onap/nbi/exceptions/ApiException.java b/src/main/java/org/onap/nbi/exceptions/ApiException.java new file mode 100644 index 0000000..d07d9db --- /dev/null +++ b/src/main/java/org/onap/nbi/exceptions/ApiException.java @@ -0,0 +1,33 @@ +package org.onap.nbi.exceptions; + +import java.io.Serializable; + +public class ApiException extends RuntimeException implements Serializable { + + protected final String localisationClass; + protected final String localisationMethod; + + public ApiException() { + super(); + localisationClass = ""; + localisationMethod = ""; + } + + public ApiException(String message) { + super(message); + localisationClass = ""; + localisationMethod = ""; + } + + public ApiException(String message, Throwable cause) { + super(message, cause); + localisationClass = ""; + localisationMethod = ""; + } + + public ApiException(Throwable cause) { + super(cause); + localisationClass = ""; + localisationMethod = ""; + } +} diff --git a/src/main/java/org/onap/nbi/exceptions/ApiExceptionHandler.java b/src/main/java/org/onap/nbi/exceptions/ApiExceptionHandler.java new file mode 100644 index 0000000..1f109cb --- /dev/null +++ b/src/main/java/org/onap/nbi/exceptions/ApiExceptionHandler.java @@ -0,0 +1,46 @@ +package org.onap.nbi.exceptions; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.client.RestClientException; + +@ControllerAdvice +public class ApiExceptionHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApiExceptionHandler.class); + + + @ExceptionHandler(BackendFunctionalException.class) + @ResponseBody + public ResponseEntity<ApiError> backendExceptionHandler(final BackendFunctionalException exception) { + ApiError apiError = new ApiError(String.valueOf(exception.getHttpStatus().value()), exception.getMessage(), "", ""); + return new ResponseEntity<ApiError>(apiError, exception.getHttpStatus()); + } + + @ExceptionHandler(TechnicalException.class) + @ResponseBody + public ResponseEntity<ApiError> technicalExceptionHandler(final TechnicalException exception) { + ApiError apiError = new ApiError(String.valueOf(exception.getHttpStatus().value()), exception.getMessage(), "", ""); + return new ResponseEntity<ApiError>(apiError, exception.getHttpStatus()); + } + + @ExceptionHandler(RestClientException.class) + @ResponseBody + public ResponseEntity<ApiError> RestClientExceptionHandler(final RestClientException exception) { + ApiError apiError = new ApiError("500", HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), "Unable to " + + "reach ONAP services", ""); + return new ResponseEntity<ApiError>(apiError, HttpStatus.INTERNAL_SERVER_ERROR); + } + + @ExceptionHandler(ValidationException.class) + @ResponseBody + public ResponseEntity<ApiError> ValidationExceptionHandler(final ValidationException exception) { + ApiError apiError = new ApiError("400", HttpStatus.BAD_REQUEST.getReasonPhrase(), exception.getMessages(), ""); + return new ResponseEntity<ApiError>(apiError, HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/src/main/java/org/onap/nbi/exceptions/BackendErrorHandler.java b/src/main/java/org/onap/nbi/exceptions/BackendErrorHandler.java new file mode 100644 index 0000000..34c4ac5 --- /dev/null +++ b/src/main/java/org/onap/nbi/exceptions/BackendErrorHandler.java @@ -0,0 +1,24 @@ +package org.onap.nbi.exceptions; + +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.ResponseErrorHandler; + +import java.io.IOException; + +public class BackendErrorHandler implements ResponseErrorHandler { + + private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler(); + + @Override + public boolean hasError(ClientHttpResponse response) throws IOException { + return errorHandler.hasError(response); + } + + @Override + public void handleError(ClientHttpResponse response) throws IOException { + if (response.getStatusCode() != null) { + throw new BackendFunctionalException(response.getStatusCode(), response.getStatusText()); + } + } +} diff --git a/src/main/java/org/onap/nbi/exceptions/BackendFunctionalException.java b/src/main/java/org/onap/nbi/exceptions/BackendFunctionalException.java new file mode 100644 index 0000000..176186f --- /dev/null +++ b/src/main/java/org/onap/nbi/exceptions/BackendFunctionalException.java @@ -0,0 +1,22 @@ +package org.onap.nbi.exceptions; + +import org.springframework.http.HttpStatus; + +public class BackendFunctionalException extends ApiException { + + private HttpStatus httpStatus; + + public BackendFunctionalException(HttpStatus httpStatus, String message) { + super(message); + this.httpStatus = httpStatus; + } + + public BackendFunctionalException() { + super(); + } + + public HttpStatus getHttpStatus() { + return httpStatus; + } + +}
\ No newline at end of file diff --git a/src/main/java/org/onap/nbi/exceptions/TechnicalException.java b/src/main/java/org/onap/nbi/exceptions/TechnicalException.java new file mode 100644 index 0000000..a2abe3e --- /dev/null +++ b/src/main/java/org/onap/nbi/exceptions/TechnicalException.java @@ -0,0 +1,26 @@ +package org.onap.nbi.exceptions; + +import org.springframework.http.HttpStatus; + +public class TechnicalException extends ApiException { + + private HttpStatus httpStatus; + + public TechnicalException(String message) { + super(message); + this.httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; + } + + public TechnicalException() { + super(); + } + + public HttpStatus getHttpStatus() { + return httpStatus; + } + + public void setHttpStatus(HttpStatus httpStatus) { + this.httpStatus = httpStatus; + } + +}
\ No newline at end of file diff --git a/src/main/java/org/onap/nbi/exceptions/ValidationException.java b/src/main/java/org/onap/nbi/exceptions/ValidationException.java new file mode 100644 index 0000000..316e8f2 --- /dev/null +++ b/src/main/java/org/onap/nbi/exceptions/ValidationException.java @@ -0,0 +1,32 @@ +package org.onap.nbi.exceptions; + +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; + +import java.util.List; + +public class ValidationException extends ApiException { + + private String messages; + + public ValidationException(List<ObjectError> listErrors) { + super(); + StringBuilder sb = new StringBuilder(); + for (ObjectError error : listErrors) { + if (error instanceof FieldError) { + sb.append(((FieldError) error).getField()) + .append(" ") + .append(((FieldError) error).getDefaultMessage()) + .append(". "); + } else { + sb.append(" ").append(error.getDefaultMessage()).append(". "); + } + } + messages = sb.toString(); + + } + + public String getMessages() { + return messages; + } +} diff --git a/src/main/resources/application-localhost.properties b/src/main/resources/application-localhost.properties new file mode 100644 index 0000000..58b13f6 --- /dev/null +++ b/src/main/resources/application-localhost.properties @@ -0,0 +1,7 @@ +# LOGGING +logging.level.org.onap.nbi=DEBUG + +# SDC +sdc.host=http://127.0.0.1:8090 +sdc.header.ecompInstanceId=Rene +sdc.header.authorization=Basic YWFpOktwOGJKNFNYc3pNMFdYbGhhazNlSGxjc2UyZ0F3ODR2YW9HR21KdlV5MlU= diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1d8ff27..10e0d7d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -3,4 +3,5 @@ server.contextPath=/nbi/api/v1 server.port = 8080 # LOGGING -logging.level.org.onap.nbi=WARN +logging.level.=WARN + diff --git a/src/main/resources/jolt/findServiceCatalog.json b/src/main/resources/jolt/findServiceCatalog.json new file mode 100644 index 0000000..ffe5fe3 --- /dev/null +++ b/src/main/resources/jolt/findServiceCatalog.json @@ -0,0 +1,28 @@ +[ + { + "operation": "shift", + "spec": { + "*": { + "uuid": "[&1].id", + "description": "[&1].description", + "name": "[&1].name", + "invariantUUID": "[&1].invariantUUID", + "category": "[&1].category", + "distributionStatus": "[&1].distributionStatus", + "version": "[&1].version", + "lifecycleState": "[&1].lifecycleStatus", + "lastUpdaterUserId": "[&1].relatedParty.id" + } + } + }, + { + "operation": "default", + "spec": { + "*": { + "relatedParty": { + "role": "lastUpdater" + } + } + } + } +]
\ No newline at end of file diff --git a/src/main/resources/jolt/getServiceCatalog.json b/src/main/resources/jolt/getServiceCatalog.json new file mode 100644 index 0000000..cac223e --- /dev/null +++ b/src/main/resources/jolt/getServiceCatalog.json @@ -0,0 +1,77 @@ +[ + { + "operation": "shift", + "spec": { + "uuid": "id", + "name": "name", + "description": "description", + "invariantUUID": "invariantUUID", + "toscaModelURL": "toscaModelURL", + "toscaResourceName": "toscaResourceName", + "category ": "category", + "subcategory": "subcategory", + "distributionStatus": "distributionStatus", + "version": "version", + "lifecycleState":"lifecycleStatus" , + "artifacts" : { + "*": { + "artifactUUID": "attachment[&1].id", + "artifactName": "attachment[&1].name", + "artifactDescription": "attachment[&1].description", + "artifactLabel": "attachment[&1].artifactLabel", + "artifactGroupType": "attachment[&1].artifactGroupType", + "artifactTimeout": "attachment[&1].artifactTimeout", + "artifactChecksum": "attachment[&1].artifactChecksum", + "artifactVersion": "attachment[&1].artifactVersion", + "generatedFromUUID": "attachment[&1].generatedFromUUID", + "artifactURL": "attachment[&1].url", + "artifactType": "attachment[&1].mimeType" + } + + }, + "lastUpdaterUserId" : "relatedParty.id", + "lastUpdaterFullName" : "relatedParty.name", + "resources" : { + "*": { + "resourceUUID": "resourceSpecification[&1].id", + "resourceVersion": "resourceSpecification[&1].version", + "resourceName": "resourceSpecification[&1].name", + "resourceInstanceName": "resourceSpecification[&1].instanceName", + "resourceInvariantUUID": "resourceSpecification[&1].resourceInvariantUUID", + "resourceType": "resourceSpecification[&1].resourceType" + } + + } + + + + } + }, + { + "operation": "modify-overwrite-beta", + "spec": { + "href": "=concat('serviceSpecification/',@(1,id))" + } + }, + { + "operation": "default", + "spec": { + "@type": "ONAPservice", + "attachment[]" : { + "*": { + "@type": "ONAPartifact" + } + + }, + "relatedParty" : { + "role": "lastUpdater" + }, + "resourceSpecification[]" : { + "*": { + "@type": "ONAPresource" + } + + } + } + } +]
\ No newline at end of file diff --git a/src/test/java/org/onap/nbi/apis/resources/ApiTest.java b/src/test/java/org/onap/nbi/apis/resources/ApiTest.java new file mode 100644 index 0000000..05d332c --- /dev/null +++ b/src/test/java/org/onap/nbi/apis/resources/ApiTest.java @@ -0,0 +1,89 @@ +package org.onap.nbi.apis.resources; + + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.nbi.apis.servicecatalog.ServiceSpecificationResource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import com.github.tomakehurst.wiremock.WireMockServer; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +public class ApiTest { + + @LocalServerPort + int randomServerPort; + + String realServerPort; + + + static public WireMockServer wireMockServer = new WireMockServer(8091); + + @Autowired + ServiceSpecificationResource serviceSpecificationResource; + + @BeforeClass + public static void setUp() throws Exception { + wireMockServer.start(); + } + + @AfterClass + public static void tearsDown() throws Exception { + wireMockServer.stop(); + + } + + @After + public void tearsDownUpPort() throws Exception { + wireMockServer.resetToDefaultMappings(); + } + + @Test + @Ignore + public void testServiceResourceGetCatalog() throws Exception { + + ResponseEntity<Object> resource = + serviceSpecificationResource.getServiceSpecification("1e3feeb0-8e36-46c6-862c-236d9c626439", null); + ServiceCatalogAssertions.assertGetServiceCatalog(resource); + + } + + @Test + public void testServiceCatalogGetResourceWithoutTosca() throws Exception { + + ResponseEntity<Object> resource = serviceSpecificationResource + .getServiceSpecification("1e3feeb0-8e36-46c6-862c-236d9c626439_withoutTosca", null); + ServiceCatalogAssertions.asserGetServiceCatalogWithoutTosca(resource); + + } + + @Test + public void testServiceCatalogFind() throws Exception { + + ResponseEntity<Object> resource = serviceSpecificationResource.findServiceSpecification(null); + ServiceCatalogAssertions.assertFindServiceCatalog(resource); + + } + + + @Test + public void testServiceCatalogFindWithFilter() throws Exception { + + MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); + params.add("fields", "name"); + ResponseEntity<Object> resource = serviceSpecificationResource.findServiceSpecification(params); + ServiceCatalogAssertions.assertFindServiceCatalogWIthFilter(resource); + + } + +} diff --git a/src/test/java/org/onap/nbi/apis/resources/ServiceCatalogAssertions.java b/src/test/java/org/onap/nbi/apis/resources/ServiceCatalogAssertions.java new file mode 100644 index 0000000..19e2a2a --- /dev/null +++ b/src/test/java/org/onap/nbi/apis/resources/ServiceCatalogAssertions.java @@ -0,0 +1,135 @@ +package org.onap.nbi.apis.resources; + + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import java.util.ArrayList; +import java.util.LinkedHashMap; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class ServiceCatalogAssertions { + + + public static void assertGetServiceCatalog(ResponseEntity<Object> resource) { + assertThat(resource.getStatusCode()).isEqualTo(HttpStatus.OK); + LinkedHashMap service = (LinkedHashMap) resource.getBody(); + assertThat(service.get("id")).isEqualTo("1e3feeb0-8e36-46c6-862c-236d9c626439"); + assertThat(service.get("name")).isEqualTo("vFW"); + assertThat(service.get("invariantUUID")).isEqualTo("b58a118e-eeb9-4f6e-bdca-e292f84d17df"); + assertThat(service.get("toscaModelURL")).isEqualTo("/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/toscaModel"); + assertThat(service.get("distributionStatus")).isEqualTo("DISTRIBUTED"); + assertThat(service.get("version")).isEqualTo("2.0"); + assertThat(service.get("lifecycleStatus")).isEqualTo("CERTIFIED"); + assertThat(service.get("@type")).isEqualTo("ONAPservice"); + assertThat(((ArrayList) service.get("attachment")).size()).isEqualTo(5); + LinkedHashMap relatedParty = (LinkedHashMap) service.get("relatedParty"); + assertThat(relatedParty.get("name")).isEqualTo("Joni Mitchell"); + assertThat(relatedParty.get("role")).isEqualTo("lastUpdater"); + + + assertThat(((ArrayList) service.get("resourceSpecification")).size()).isEqualTo(2); + LinkedHashMap resource1 = (LinkedHashMap) ((ArrayList) service.get("resourceSpecification")).get(0); + assertThat(resource1.get("name")).isEqualTo("vFW-vSINK"); + assertThat(resource1.get("instanceName")).isEqualTo("vFW-vSINK 0"); + assertThat(resource1.get("resourceInvariantUUID")).isEqualTo("18b90934-aa82-456f-938e-e74a07a426f3"); + assertThat(resource1.get("@type")).isEqualTo("ONAPresource"); + assertThat(resource1.get("modelCustomizationId")).isEqualTo("f7ae574e-fd5f-41e7-9b21-75e001561c96"); + assertThat(resource1.get("modelCustomizationName")).isEqualTo("vFW-vSINK"); + + assertThat(((ArrayList) service.get("serviceSpecCharacteristic")).size()).isEqualTo(4); + ArrayList serviceSPecCharacteristics = (ArrayList) service.get("serviceSpecCharacteristic"); + for (Object serviceSPecCharacteristic : serviceSPecCharacteristics) { + LinkedHashMap serviceSPecCharacteristicMap = (LinkedHashMap) serviceSPecCharacteristic; + if (serviceSPecCharacteristicMap.get("name").toString().equals("cpus")) { + assertThat(serviceSPecCharacteristicMap.get("valueType")).isEqualTo("integer"); + assertThat(serviceSPecCharacteristicMap.get("@type")).isEqualTo("ONAPserviceCharacteristic"); + ArrayList serviceSpecCharacteristicValues = (ArrayList) serviceSPecCharacteristicMap.get("serviceSpecCharacteristicValue"); + for (Object serviceSpecCharacteristicValue : serviceSpecCharacteristicValues) { + LinkedHashMap serviceSpecCharacteristicValueMap = (LinkedHashMap) serviceSpecCharacteristicValue; + if (serviceSpecCharacteristicValueMap.get("value").toString().equals("2")) { + assertThat(serviceSpecCharacteristicValueMap.get("isDefault")).isEqualTo(true); + assertThat(serviceSpecCharacteristicValueMap.get("valueType")).isEqualTo("integer"); + } else { + assertThat(serviceSpecCharacteristicValueMap.get("isDefault")).isEqualTo(false); + assertThat(serviceSpecCharacteristicValueMap.get("valueType")).isEqualTo("integer"); + } + } + } + } + } + + + + public static void asserGetServiceCatalogWithoutTosca(ResponseEntity<Object> resource) { + assertThat(resource.getStatusCode()).isEqualTo(HttpStatus.PARTIAL_CONTENT); + LinkedHashMap service = (LinkedHashMap) resource.getBody(); + assertThat(service.get("id")).isEqualTo("1e3feeb0-8e36-46c6-862c-236d9c626439"); + assertThat(service.get("name")).isEqualTo("vFW"); + assertThat(service.get("invariantUUID")).isEqualTo("b58a118e-eeb9-4f6e-bdca-e292f84d17df"); + assertThat(service.get("toscaModelURL")).isEqualTo("/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439toto/toscaModel"); + assertThat(service.get("distributionStatus")).isEqualTo("DISTRIBUTED"); + assertThat(service.get("version")).isEqualTo("2.0"); + assertThat(service.get("lifecycleStatus")).isEqualTo("CERTIFIED"); + assertThat(service.get("@type")).isEqualTo("ONAPservice"); + assertThat(((ArrayList) service.get("attachment")).size()).isEqualTo(5); + LinkedHashMap relatedParty = (LinkedHashMap) service.get("relatedParty"); + assertThat(relatedParty.get("name")).isEqualTo("Joni Mitchell"); + assertThat(relatedParty.get("role")).isEqualTo("lastUpdater"); + + + assertThat(((ArrayList) service.get("resourceSpecification")).size()).isEqualTo(2); + LinkedHashMap resource1 = (LinkedHashMap) ((ArrayList) service.get("resourceSpecification")).get(0); + assertThat(resource1.get("name")).isEqualTo("vFW-vSINK"); + assertThat(resource1.get("instanceName")).isEqualTo("vFW-vSINK 0"); + assertThat(resource1.get("resourceInvariantUUID")).isEqualTo("18b90934-aa82-456f-938e-e74a07a426f3"); + assertThat(resource1.get("@type")).isEqualTo("ONAPresource"); + assertThat(resource1.get("modelCustomizationId")).isNull(); + assertThat(resource1.get("modelCustomizationName")).isNull(); + + assertThat(service.get("serviceSpecCharacteristic")).isNull(); + } + + + + + public static void assertFindServiceCatalog(ResponseEntity<Object> resource) { + assertThat(resource.getStatusCode()).isEqualTo(HttpStatus.OK); + ArrayList body = (ArrayList) resource.getBody(); + assertThat(body.size()).isEqualTo(21); + LinkedHashMap service1 = (LinkedHashMap) body.get(0); + assertThat(service1.get("id")).isEqualTo("446afaf6-79b5-420e-aff8-7551b00bb510"); + assertThat(service1.get("name")).isEqualTo("FreeRadius-service"); + assertThat(service1.get("invariantUUID")).isEqualTo("7e4781e8-6c6e-41c5-b889-6a321d5f2490"); + assertThat(service1.get("category")).isEqualTo("Network L4+"); + assertThat(service1.get("distributionStatus")).isEqualTo("DISTRIBUTED"); + assertThat(service1.get("version")).isEqualTo("1.0"); + assertThat(service1.get("lifecycleStatus")).isEqualTo("CERTIFIED"); + LinkedHashMap relatedParty = (LinkedHashMap) service1.get("relatedParty"); + assertThat(relatedParty.get("role")).isEqualTo("lastUpdater"); + } + + + + public static void assertFindServiceCatalogWIthFilter(ResponseEntity<Object> resource) { + assertThat(resource.getStatusCode()).isEqualTo(HttpStatus.OK); + ArrayList body = (ArrayList) resource.getBody(); + assertThat(body.size()).isEqualTo(21); + + + ObjectNode service1 = (ObjectNode) body.get(0); + assertThat(service1.get("id")).isNull(); + assertThat(service1.get("name").asText()).isEqualTo("FreeRadius-service"); + assertThat(service1.get("invariantUUID")).isNull(); + assertThat(service1.get("category")).isNull(); + assertThat(service1.get("distributionStatus")).isNull(); + assertThat(service1.get("version")).isNull(); + assertThat(service1.get("lifecycleStatus")).isNull(); + assertThat(service1.get("relatedParty")).isNull(); + } + +} + diff --git a/src/test/java/org/onap/nbi/apis/status/StatusTest.java b/src/test/java/org/onap/nbi/apis/resources/StatusResourceTest.java index d262e15..40e11c2 100644 --- a/src/test/java/org/onap/nbi/apis/status/StatusTest.java +++ b/src/test/java/org/onap/nbi/apis/resources/StatusResourceTest.java @@ -1,10 +1,11 @@ -package org.onap.nbi.apis.status; +package org.onap.nbi.apis.resources; import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.onap.nbi.apis.status.StatusResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.HttpStatus; @@ -16,7 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class StatusTest { +public class StatusResourceTest { @Autowired StatusResource statusResource; diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..5d18ec8 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,13 @@ +# SERVER +server.contextPath=/nbi/api/v1 +server.port = 8080 + +# LOGGING +logging.level.org.onap.nbi=DEBUG +logging.level.org.springframework.cloud.contract.wiremock=DEBUG + +# SDC +sdc.host=http://127.0.0.1:8091 +sdc.header.ecompInstanceId=Rene +sdc.header.authorization=Basic YWFpOktwOGJKNFNYc3pNMFdYbGhhazNlSGxjc2UyZ0F3ODR2YW9HR21KdlV5MlU= + diff --git a/src/test/resources/mappings/sdc_find.json b/src/test/resources/mappings/sdc_find.json new file mode 100644 index 0000000..e992f2b --- /dev/null +++ b/src/test/resources/mappings/sdc_find.json @@ -0,0 +1,244 @@ +{ + "request": { + "method": "GET", + "urlPath": "/sdc/v1/catalog/services/" + }, + "response": { + "status": 200, + "jsonBody": [{ + "uuid": "446afaf6-79b5-420e-aff8-7551b00bb510", + "invariantUUID": "7e4781e8-6c6e-41c5-b889-6a321d5f2490", + "name": "FreeRadius-service", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/446afaf6-79b5-420e-aff8-7551b00bb510/toscaModel", + "category": "Network L4+", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "35911438-4621-439b-a23d-3e07680c724b", + "invariantUUID": "ca2f0af5-95e4-4058-b037-5c0de0f80bfa", + "name": "vIMS", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/35911438-4621-439b-a23d-3e07680c724b/toscaModel", + "category": "E2E Service", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "8cdc744a-9327-47cc-a9de-67d8d46b816f", + "invariantUUID": "d2b9c343-c41a-4f85-ae36-c53cd4b7abcc", + "name": "vIMSservice3", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/8cdc744a-9327-47cc-a9de-67d8d46b816f/toscaModel", + "category": "VoIP Call Control", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "fcea1d5b-c8de-4355-8fda-64e0d84494e6", + "invariantUUID": "b58a118e-eeb9-4f6e-bdca-e292f84d17df", + "name": "vFW-service-2VF-based", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/fcea1d5b-c8de-4355-8fda-64e0d84494e6/toscaModel", + "category": "Network Service", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "9d356a71-ac7a-40f0-b2b2-b302c8b4ef63", + "invariantUUID": "4526a034-e4fc-4ea3-87d0-8b8fca4a93b1", + "name": "serviceFRDBS", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/9d356a71-ac7a-40f0-b2b2-b302c8b4ef63/toscaModel", + "category": "Network L4+", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "b821e80a-40a5-4fab-ac5d-3d49a54c4db3", + "invariantUUID": "9765d74e-c8f2-4982-bc90-548c854cbde6", + "name": "EricDebeau", + "version": "0.1", + "toscaModelURL": "/sdc/v1/catalog/services/b821e80a-40a5-4fab-ac5d-3d49a54c4db3/toscaModel", + "category": "Network L4+", + "lifecycleState": "NOT_CERTIFIED_CHECKIN", + "lastUpdaterUserId": "cs0008", + "distributionStatus": "DISTRIBUTION_NOT_APPROVED" + }, + { + "uuid": "cc3ec088-227c-49e2-b4c3-237214b88c84", + "invariantUUID": "e1685613-136b-4990-a590-d0651a640a68", + "name": "vMRFaaS4", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/cc3ec088-227c-49e2-b4c3-237214b88c84/toscaModel", + "category": "Network Service", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "10be4044-8217-4397-8b62-85c58688d4ba", + "invariantUUID": "a62a335f-a6e3-40dd-8b60-de8410301240", + "name": "OPL_FWtest1_service", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/10be4044-8217-4397-8b62-85c58688d4ba/toscaModel", + "category": "Network L4+", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "3dd3923d-1681-4f5b-99bb-f695ab147004", + "invariantUUID": "026e8046-4d3a-41d9-b4c2-6793186fd83d", + "name": "vFW", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/3dd3923d-1681-4f5b-99bb-f695ab147004/toscaModel", + "category": "Network Service", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "d15de0e3-d8fe-4cc3-a0b1-809ea95cbac8", + "invariantUUID": "6046d5f5-b39e-4306-a47e-0762c88d8b93", + "name": "1f298e99-082b-4a7f-a579", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/d15de0e3-d8fe-4cc3-a0b1-809ea95cbac8/toscaModel", + "category": "Network L1-3", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "f5ab9333-692f-42bc-b5dc-3ed753aa0d14", + "invariantUUID": "83a9f465-24d2-4dd3-98b8-328481cf9340", + "name": "c55011b0-f26c-43dd-9a62", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/f5ab9333-692f-42bc-b5dc-3ed753aa0d14/toscaModel", + "category": "Network L1-3", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "33826edf-fddd-4891-b726-8f16ea0e020c", + "invariantUUID": "0475334e-e141-42b3-b3ee-4df049c3cd53", + "name": "ccfc0cb4-bdff-4ae2-aa0e", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/33826edf-fddd-4891-b726-8f16ea0e020c/toscaModel", + "category": "Network L1-3", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "340bf137-8c6c-4d5b-b185-19364dfc74ed", + "invariantUUID": "7e4781e8-6c6e-41c5-b889-6a321d5f2490", + "name": "FreeRadius-service", + "version": "2.0", + "toscaModelURL": "/sdc/v1/catalog/services/340bf137-8c6c-4d5b-b185-19364dfc74ed/toscaModel", + "category": "Network L4+", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "d0cac11e-332f-47e8-86d8-cb0b82655bb9", + "invariantUUID": "ca2f0af5-95e4-4058-b037-5c0de0f80bfa", + "name": "vIMS", + "version": "2.0", + "toscaModelURL": "/sdc/v1/catalog/services/d0cac11e-332f-47e8-86d8-cb0b82655bb9/toscaModel", + "category": "E2E Service", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "e245a0a2-34fc-46c7-912c-bd39305275c1", + "invariantUUID": "29db0b2c-a877-45e8-8175-4ac526d87eee", + "name": "vMRFaaS", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/e245a0a2-34fc-46c7-912c-bd39305275c1/toscaModel", + "category": "Network L4+", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "b9e06990-99e2-480f-96ac-c6e50c83f2bb", + "invariantUUID": "008943ad-73be-4d57-9105-962c4cb16a71", + "name": "vMRFaas2", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/b9e06990-99e2-480f-96ac-c6e50c83f2bb/toscaModel", + "category": "Network L4+", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "98d95267-5e0f-4531-abf8-f14b90031dc5", + "invariantUUID": "709d157b-52fb-4250-976e-7133dff5c347", + "name": "NewFreeRadius-service", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/98d95267-5e0f-4531-abf8-f14b90031dc5/toscaModel", + "category": "Network L4+", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "d8d2429b-0863-462c-adc7-cd38d77331ed", + "invariantUUID": "e1685613-136b-4990-a590-d0651a640a68", + "name": "vMRFaaS4", + "version": "1.1", + "toscaModelURL": "/sdc/v1/catalog/services/d8d2429b-0863-462c-adc7-cd38d77331ed/toscaModel", + "category": "Network Service", + "lifecycleState": "NOT_CERTIFIED_CHECKOUT", + "lastUpdaterUserId": "cs0008", + "distributionStatus": "DISTRIBUTION_NOT_APPROVED" + }, + { + "uuid": "9cfc73ad-795d-42ad-8a4f-54e6b3f33ef9", + "invariantUUID": "79f0574e-caf8-4bac-8189-909b2127e9e9", + "name": "vMRFaaS3", + "version": "1.0", + "toscaModelURL": "/sdc/v1/catalog/services/9cfc73ad-795d-42ad-8a4f-54e6b3f33ef9/toscaModel", + "category": "Network Service", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "af1ac9db-9d8b-4ca0-964c-58755826b59a", + "invariantUUID": "d2b9c343-c41a-4f85-ae36-c53cd4b7abcc", + "name": "vIMSservice3", + "version": "2.0", + "toscaModelURL": "/sdc/v1/catalog/services/af1ac9db-9d8b-4ca0-964c-58755826b59a/toscaModel", + "category": "VoIP Call Control", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + }, + { + "uuid": "1e3feeb0-8e36-46c6-862c-236d9c626439", + "invariantUUID": "b58a118e-eeb9-4f6e-bdca-e292f84d17df", + "name": "vFW-service-2VF-based", + "version": "2.0", + "toscaModelURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/toscaModel", + "category": "Network Service", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED" + } + ], + "headers": { + "Content-Type": "application/json" + } + } +} diff --git a/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439.json b/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439.json new file mode 100644 index 0000000..3aeff82 --- /dev/null +++ b/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439.json @@ -0,0 +1,213 @@ +{ + "request": { + "method": "GET", + "urlPath": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/metadata" + }, + "response": { + "status": 200, + "jsonBody": { + "uuid": "1e3feeb0-8e36-46c6-862c-236d9c626439", + "invariantUUID": "b58a118e-eeb9-4f6e-bdca-e292f84d17df", + "name": "vFW", + "version": "2.0", + "toscaModelURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/toscaModel", + "category": "Network Service", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED", + "lastUpdaterFullName": "Joni Mitchell", + "resources": [{ + "resourceInstanceName": "vFW-vSINK 0", + "resourceName": "vFW-vSINK", + "resourceInvariantUUID": "18b90934-aa82-456f-938e-e74a07a426f3", + "resourceVersion": "2.0", + "resoucreType": "VF", + "resourceUUID": "89a6b4c5-3973-4c19-b651-fae3713ca8d5", + "artifacts": [{ + "artifactName": "vf-license-model.xml", + "artifactType": "VF_LICENSE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/f6fa3f94-f5cd-4233-a7b2-b5e8dc2e1ec6", + "artifactDescription": "VF license file", + "artifactChecksum": "NDQ2NzIxNzgyMjZhNTc1NDNlMWU0ODI1ZmIyNjc3Zjg=", + "artifactUUID": "f6fa3f94-f5cd-4233-a7b2-b5e8dc2e1ec6", + "artifactVersion": "1", + "artifactLabel": "vflicense", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "vfwvsink0_modules.json", + "artifactType": "VF_MODULES_METADATA", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/d0aaecf9-6ffb-4b4b-81fd-c59c1e8e6fb6", + "artifactDescription": "Auto-generated VF Modules information artifact", + "artifactChecksum": "ZGIyOWY3YzE0MTM2MjlhMjY1ZjkzNDg3YjE2ZmQxY2Y=", + "artifactUUID": "d0aaecf9-6ffb-4b4b-81fd-c59c1e8e6fb6", + "artifactVersion": "1", + "artifactLabel": "vfModulesMetadata", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "base_vfw.yaml", + "artifactType": "HEAT", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/c94e8eec-b1a7-431c-ab6f-2fda5f0ee920", + "artifactDescription": "created from csar", + "artifactTimeout": 60, + "artifactChecksum": "YTY0MDg5ODUwZDE4YzQyYWI0NjE5Y2NjYmM3ZDg5ZGE=", + "artifactUUID": "c94e8eec-b1a7-431c-ab6f-2fda5f0ee920", + "artifactVersion": "4", + "artifactLabel": "heat1", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "vendor-license-model.xml", + "artifactType": "VENDOR_LICENSE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/423d2c66-6c3a-4257-9342-7b57ebf9dd54", + "artifactDescription": " Vendor license file", + "artifactChecksum": "YTNhYTc3ZGE4ZWViMmYzOThkOGQ3ZTVjZGNmNmU0ZmQ=", + "artifactUUID": "423d2c66-6c3a-4257-9342-7b57ebf9dd54", + "artifactVersion": "1", + "artifactLabel": "vendorlicense", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "base_vfw.env", + "artifactType": "HEAT_ENV", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/a1a58cc9-8225-4b6f-b81a-02fa3c7fb6ec", + "artifactDescription": "Auto-generated HEAT Environment deployment artifact", + "artifactChecksum": "ZmVkM2MwODhlZjcwNWY5MDk5ZGEyMjI5ZTAyYWRjNjY=", + "artifactUUID": "a1a58cc9-8225-4b6f-b81a-02fa3c7fb6ec", + "artifactVersion": "2", + "generatedFromUUID": "32591489-33c9-4461-a47c-7c463250788d.heat1", + "artifactLabel": "heat1env", + "artifactGroupType": "DEPLOYMENT" + } + ] + }, + { + "resourceInstanceName": "vPkG 0", + "resourceName": "vPkG", + "resourceInvariantUUID": "8d8a20c0-746c-4d5e-a1a2-fa49fa5786ad", + "resourceVersion": "2.0", + "resoucreType": "VF", + "resourceUUID": "31961e27-2a2c-4beb-87c9-bfe0067088f5", + "artifacts": [{ + "artifactName": "vf-license-model.xml", + "artifactType": "VF_LICENSE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/7af6cc3b-2ba3-4164-9d7d-65b3b46a71f4", + "artifactDescription": "VF license file", + "artifactChecksum": "MWM5NDlmNjdhZTdmZTA5MzIzY2RhYjcxZmFkYzQyZDM=", + "artifactUUID": "7af6cc3b-2ba3-4164-9d7d-65b3b46a71f4", + "artifactVersion": "1", + "artifactLabel": "vflicense", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "vpkg0_modules.json", + "artifactType": "VF_MODULES_METADATA", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/37b16173-bd54-447f-a5a2-1a5e24db8afb", + "artifactDescription": "Auto-generated VF Modules information artifact", + "artifactChecksum": "ZDA3MWQ3MTE3MTA1MzNkY2M1ODQ4YTUxN2YwMDk0MmM=", + "artifactUUID": "37b16173-bd54-447f-a5a2-1a5e24db8afb", + "artifactVersion": "1", + "artifactLabel": "vfModulesMetadata", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "base_vpkg.yaml", + "artifactType": "HEAT", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/43184998-c107-40a7-92f6-00ba74de8539", + "artifactDescription": "created from csar", + "artifactTimeout": 60, + "artifactChecksum": "NDZhY2U0YTExZjllNTFmZjc4ZTE4YzU2Zjk1ZDc2MWI=", + "artifactUUID": "43184998-c107-40a7-92f6-00ba74de8539", + "artifactVersion": "4", + "artifactLabel": "heat1", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "vendor-license-model.xml", + "artifactType": "VENDOR_LICENSE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/6cd5f968-20aa-4b86-9a50-97db5e4ca806", + "artifactDescription": " Vendor license file", + "artifactChecksum": "YTNhYTc3ZGE4ZWViMmYzOThkOGQ3ZTVjZGNmNmU0ZmQ=", + "artifactUUID": "6cd5f968-20aa-4b86-9a50-97db5e4ca806", + "artifactVersion": "1", + "artifactLabel": "vendorlicense", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "base_vpkg.env", + "artifactType": "HEAT_ENV", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/60944038-d382-4aa6-b387-7b87c9c9df19", + "artifactDescription": "Auto-generated HEAT Environment deployment artifact", + "artifactChecksum": "OGU0OGFlZTFiZDdhYmQ0MmM0MjAyY2U5YjljYWViYTA=", + "artifactUUID": "60944038-d382-4aa6-b387-7b87c9c9df19", + "artifactVersion": "2", + "generatedFromUUID": "0d3918df-ea14-4fc3-a5c9-34032eaae573.heat1", + "artifactLabel": "heat1env", + "artifactGroupType": "DEPLOYMENT" + } + ] + } + ], + "artifacts": [{ + "artifactName": "AAI-vFW-service-2VF-based-service-2.0.xml", + "artifactType": "MODEL_INVENTORY_PROFILE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/2e6cd967-93c2-4f53-82bd-c56ab98e8df7", + "artifactDescription": "AAI Service Model", + "artifactChecksum": "ZTY5ZTJmYTY4YzE2NGUxMTQxNWNkN2QzMmI4MWIzNDU=", + "artifactUUID": "2e6cd967-93c2-4f53-82bd-c56ab98e8df7", + "artifactVersion": "1", + "artifactLabel": "aaiservice1603481860", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "AAI-Vpkg..base_vpkg..module-0-resource-2.xml", + "artifactType": "MODEL_INVENTORY_PROFILE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/ad600a09-edde-4356-bb0a-9e638a671d06", + "artifactDescription": "AAI Resource Model", + "artifactChecksum": "MzQyMjczOGVmYzM1OWQ1NmFhZjBhOWUxM2JjMmYxZTQ=", + "artifactUUID": "ad600a09-edde-4356-bb0a-9e638a671d06", + "artifactVersion": "1", + "artifactLabel": "aairesource529289386", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "AAI-vFW-vSINK-resource-2.0.xml", + "artifactType": "MODEL_INVENTORY_PROFILE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/413a631e-69c4-453b-ab68-fac09b390259", + "artifactDescription": "AAI Resource Model", + "artifactChecksum": "ZWRmMzQzYzc0MThlYjQ1YjY2ZTFkYzJmMjAyNzQ1YWU=", + "artifactUUID": "413a631e-69c4-453b-ab68-fac09b390259", + "artifactVersion": "1", + "artifactLabel": "aairesource1461475898", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "AAI-vPkG-resource-2.0.xml", + "artifactType": "MODEL_INVENTORY_PROFILE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/aee30754-eec4-4820-ae3a-790b80b76e81", + "artifactDescription": "AAI Resource Model", + "artifactChecksum": "OGQ4ZTdhYjkyZDRkYmFiZTBhNWU4MDc4YTM2YjY1NmI=", + "artifactUUID": "aee30754-eec4-4820-ae3a-790b80b76e81", + "artifactVersion": "1", + "artifactLabel": "aairesource936479495", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "AAI-VfwVsink..base_vfw..module-0-resource-2.xml", + "artifactType": "MODEL_INVENTORY_PROFILE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/ac9a3bbf-a052-4176-abff-fe2d2741194a", + "artifactDescription": "AAI Resource Model", + "artifactChecksum": "OWIzNjVhNmI2ZWYyZThlMjk1NjA2MDFhZTU3MGQ0ZDU=", + "artifactUUID": "ac9a3bbf-a052-4176-abff-fe2d2741194a", + "artifactVersion": "1", + "artifactLabel": "aairesource1106409880", + "artifactGroupType": "DEPLOYMENT" + } + ] + }, + "headers": { + "Content-Type": "application/json" + } + } +}
\ No newline at end of file diff --git a/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_tosca.json b/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_tosca.json new file mode 100644 index 0000000..2090397 --- /dev/null +++ b/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_tosca.json @@ -0,0 +1,10 @@ +{ + "request": { + "method": "GET", + "urlPath": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/toscaModel" + }, + "response": { + "status": 200, + "bodyFileName": "response" + } +}
\ No newline at end of file diff --git a/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_withoutTosca.json b/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_withoutTosca.json new file mode 100644 index 0000000..567503a --- /dev/null +++ b/src/test/resources/mappings/sdc_get_1e3feeb0-8e36-46c6-862c-236d9c626439_withoutTosca.json @@ -0,0 +1,213 @@ +{ + "request": { + "method": "GET", + "urlPath": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439_withoutTosca/metadata" + }, + "response": { + "status": 200, + "jsonBody": { + "uuid": "1e3feeb0-8e36-46c6-862c-236d9c626439", + "invariantUUID": "b58a118e-eeb9-4f6e-bdca-e292f84d17df", + "name": "vFW", + "version": "2.0", + "toscaModelURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439toto/toscaModel", + "category": "Network Service", + "lifecycleState": "CERTIFIED", + "lastUpdaterUserId": "jm0007", + "distributionStatus": "DISTRIBUTED", + "lastUpdaterFullName": "Joni Mitchell", + "resources": [{ + "resourceInstanceName": "vFW-vSINK 0", + "resourceName": "vFW-vSINK", + "resourceInvariantUUID": "18b90934-aa82-456f-938e-e74a07a426f3", + "resourceVersion": "2.0", + "resoucreType": "VF", + "resourceUUID": "89a6b4c5-3973-4c19-b651-fae3713ca8d5", + "artifacts": [{ + "artifactName": "vf-license-model.xml", + "artifactType": "VF_LICENSE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/f6fa3f94-f5cd-4233-a7b2-b5e8dc2e1ec6", + "artifactDescription": "VF license file", + "artifactChecksum": "NDQ2NzIxNzgyMjZhNTc1NDNlMWU0ODI1ZmIyNjc3Zjg=", + "artifactUUID": "f6fa3f94-f5cd-4233-a7b2-b5e8dc2e1ec6", + "artifactVersion": "1", + "artifactLabel": "vflicense", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "vfwvsink0_modules.json", + "artifactType": "VF_MODULES_METADATA", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/d0aaecf9-6ffb-4b4b-81fd-c59c1e8e6fb6", + "artifactDescription": "Auto-generated VF Modules information artifact", + "artifactChecksum": "ZGIyOWY3YzE0MTM2MjlhMjY1ZjkzNDg3YjE2ZmQxY2Y=", + "artifactUUID": "d0aaecf9-6ffb-4b4b-81fd-c59c1e8e6fb6", + "artifactVersion": "1", + "artifactLabel": "vfModulesMetadata", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "base_vfw.yaml", + "artifactType": "HEAT", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/c94e8eec-b1a7-431c-ab6f-2fda5f0ee920", + "artifactDescription": "created from csar", + "artifactTimeout": 60, + "artifactChecksum": "YTY0MDg5ODUwZDE4YzQyYWI0NjE5Y2NjYmM3ZDg5ZGE=", + "artifactUUID": "c94e8eec-b1a7-431c-ab6f-2fda5f0ee920", + "artifactVersion": "4", + "artifactLabel": "heat1", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "vendor-license-model.xml", + "artifactType": "VENDOR_LICENSE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/423d2c66-6c3a-4257-9342-7b57ebf9dd54", + "artifactDescription": " Vendor license file", + "artifactChecksum": "YTNhYTc3ZGE4ZWViMmYzOThkOGQ3ZTVjZGNmNmU0ZmQ=", + "artifactUUID": "423d2c66-6c3a-4257-9342-7b57ebf9dd54", + "artifactVersion": "1", + "artifactLabel": "vendorlicense", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "base_vfw.env", + "artifactType": "HEAT_ENV", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vfwvsink0/artifacts/a1a58cc9-8225-4b6f-b81a-02fa3c7fb6ec", + "artifactDescription": "Auto-generated HEAT Environment deployment artifact", + "artifactChecksum": "ZmVkM2MwODhlZjcwNWY5MDk5ZGEyMjI5ZTAyYWRjNjY=", + "artifactUUID": "a1a58cc9-8225-4b6f-b81a-02fa3c7fb6ec", + "artifactVersion": "2", + "generatedFromUUID": "32591489-33c9-4461-a47c-7c463250788d.heat1", + "artifactLabel": "heat1env", + "artifactGroupType": "DEPLOYMENT" + } + ] + }, + { + "resourceInstanceName": "vPkG 0", + "resourceName": "vPkG", + "resourceInvariantUUID": "8d8a20c0-746c-4d5e-a1a2-fa49fa5786ad", + "resourceVersion": "2.0", + "resoucreType": "VF", + "resourceUUID": "31961e27-2a2c-4beb-87c9-bfe0067088f5", + "artifacts": [{ + "artifactName": "vf-license-model.xml", + "artifactType": "VF_LICENSE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/7af6cc3b-2ba3-4164-9d7d-65b3b46a71f4", + "artifactDescription": "VF license file", + "artifactChecksum": "MWM5NDlmNjdhZTdmZTA5MzIzY2RhYjcxZmFkYzQyZDM=", + "artifactUUID": "7af6cc3b-2ba3-4164-9d7d-65b3b46a71f4", + "artifactVersion": "1", + "artifactLabel": "vflicense", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "vpkg0_modules.json", + "artifactType": "VF_MODULES_METADATA", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/37b16173-bd54-447f-a5a2-1a5e24db8afb", + "artifactDescription": "Auto-generated VF Modules information artifact", + "artifactChecksum": "ZDA3MWQ3MTE3MTA1MzNkY2M1ODQ4YTUxN2YwMDk0MmM=", + "artifactUUID": "37b16173-bd54-447f-a5a2-1a5e24db8afb", + "artifactVersion": "1", + "artifactLabel": "vfModulesMetadata", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "base_vpkg.yaml", + "artifactType": "HEAT", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/43184998-c107-40a7-92f6-00ba74de8539", + "artifactDescription": "created from csar", + "artifactTimeout": 60, + "artifactChecksum": "NDZhY2U0YTExZjllNTFmZjc4ZTE4YzU2Zjk1ZDc2MWI=", + "artifactUUID": "43184998-c107-40a7-92f6-00ba74de8539", + "artifactVersion": "4", + "artifactLabel": "heat1", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "vendor-license-model.xml", + "artifactType": "VENDOR_LICENSE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/6cd5f968-20aa-4b86-9a50-97db5e4ca806", + "artifactDescription": " Vendor license file", + "artifactChecksum": "YTNhYTc3ZGE4ZWViMmYzOThkOGQ3ZTVjZGNmNmU0ZmQ=", + "artifactUUID": "6cd5f968-20aa-4b86-9a50-97db5e4ca806", + "artifactVersion": "1", + "artifactLabel": "vendorlicense", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "base_vpkg.env", + "artifactType": "HEAT_ENV", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/resourceInstances/vpkg0/artifacts/60944038-d382-4aa6-b387-7b87c9c9df19", + "artifactDescription": "Auto-generated HEAT Environment deployment artifact", + "artifactChecksum": "OGU0OGFlZTFiZDdhYmQ0MmM0MjAyY2U5YjljYWViYTA=", + "artifactUUID": "60944038-d382-4aa6-b387-7b87c9c9df19", + "artifactVersion": "2", + "generatedFromUUID": "0d3918df-ea14-4fc3-a5c9-34032eaae573.heat1", + "artifactLabel": "heat1env", + "artifactGroupType": "DEPLOYMENT" + } + ] + } + ], + "artifacts": [{ + "artifactName": "AAI-vFW-service-2VF-based-service-2.0.xml", + "artifactType": "MODEL_INVENTORY_PROFILE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/2e6cd967-93c2-4f53-82bd-c56ab98e8df7", + "artifactDescription": "AAI Service Model", + "artifactChecksum": "ZTY5ZTJmYTY4YzE2NGUxMTQxNWNkN2QzMmI4MWIzNDU=", + "artifactUUID": "2e6cd967-93c2-4f53-82bd-c56ab98e8df7", + "artifactVersion": "1", + "artifactLabel": "aaiservice1603481860", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "AAI-Vpkg..base_vpkg..module-0-resource-2.xml", + "artifactType": "MODEL_INVENTORY_PROFILE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/ad600a09-edde-4356-bb0a-9e638a671d06", + "artifactDescription": "AAI Resource Model", + "artifactChecksum": "MzQyMjczOGVmYzM1OWQ1NmFhZjBhOWUxM2JjMmYxZTQ=", + "artifactUUID": "ad600a09-edde-4356-bb0a-9e638a671d06", + "artifactVersion": "1", + "artifactLabel": "aairesource529289386", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "AAI-vFW-vSINK-resource-2.0.xml", + "artifactType": "MODEL_INVENTORY_PROFILE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/413a631e-69c4-453b-ab68-fac09b390259", + "artifactDescription": "AAI Resource Model", + "artifactChecksum": "ZWRmMzQzYzc0MThlYjQ1YjY2ZTFkYzJmMjAyNzQ1YWU=", + "artifactUUID": "413a631e-69c4-453b-ab68-fac09b390259", + "artifactVersion": "1", + "artifactLabel": "aairesource1461475898", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "AAI-vPkG-resource-2.0.xml", + "artifactType": "MODEL_INVENTORY_PROFILE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/aee30754-eec4-4820-ae3a-790b80b76e81", + "artifactDescription": "AAI Resource Model", + "artifactChecksum": "OGQ4ZTdhYjkyZDRkYmFiZTBhNWU4MDc4YTM2YjY1NmI=", + "artifactUUID": "aee30754-eec4-4820-ae3a-790b80b76e81", + "artifactVersion": "1", + "artifactLabel": "aairesource936479495", + "artifactGroupType": "DEPLOYMENT" + }, + { + "artifactName": "AAI-VfwVsink..base_vfw..module-0-resource-2.xml", + "artifactType": "MODEL_INVENTORY_PROFILE", + "artifactURL": "/sdc/v1/catalog/services/1e3feeb0-8e36-46c6-862c-236d9c626439/artifacts/ac9a3bbf-a052-4176-abff-fe2d2741194a", + "artifactDescription": "AAI Resource Model", + "artifactChecksum": "OWIzNjVhNmI2ZWYyZThlMjk1NjA2MDFhZTU3MGQ0ZDU=", + "artifactUUID": "ac9a3bbf-a052-4176-abff-fe2d2741194a", + "artifactVersion": "1", + "artifactLabel": "aairesource1106409880", + "artifactGroupType": "DEPLOYMENT" + } + ] + }, + "headers": { + "Content-Type": "application/json" + } + } +}
\ No newline at end of file |