From e7c8c7299e656e3f7e2d8aca69d0aa9400903e60 Mon Sep 17 00:00:00 2001 From: vempo Date: Thu, 19 Jul 2018 18:46:10 +0300 Subject: [PATCH] Migrated VNF to JAX-RS HTTP client Change-Id: I8735839aeffe89c191df562732b8f5ab30a81444 Issue-ID: SDC-1278 Signed-off-by: vempo --- .../vnf-repository-rest-services/pom.xml | 101 +++--- .../sdcrests/vsp/rest/VnfPackageRepository.java | 31 +- .../rest/services/VnfPackageRepositoryImpl.java | 403 ++++++++++++++------- .../services/VnfPackageRepositoryImplTest.java | 171 +++++++++ .../src/test/resources/config-vnfrepo.yaml | 4 + 5 files changed, 532 insertions(+), 178 deletions(-) create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/services/VnfPackageRepositoryImplTest.java create mode 100644 openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/test/resources/config-vnfrepo.yaml diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/pom.xml b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/pom.xml index edc7b8bbca..d504f70f34 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/pom.xml +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/pom.xml @@ -1,4 +1,21 @@ + + 4.0.0 @@ -13,78 +30,72 @@ - org.springframework - spring-core - ${spring.framework.version} - - - org.springframework - spring-context - ${spring.framework.version} + javax.ws.rs + javax.ws.rs-api + ${ws.rs.version} + provided - org.springframework - spring-context-support - ${spring.framework.version} + io.swagger + swagger-annotations + ${swagger.version} org.springframework - spring-web + spring-context ${spring.framework.version} - org.springframework - spring-beans - ${spring.framework.version} + org.openecomp.sdc.onboarding + vendor-software-products-rest-services + ${project.version} - - - org.apache.cxf - cxf-rt-frontend-jaxrs - ${cxf.version} + org.onap.sdc.common + onap-configuration-management-api + ${project.version} - org.apache.httpcomponents - httpclient - ${http.client.version} - - - - - - javax.inject - javax.inject - ${javax.inject.version} - provided + org.onap.sdc.common + onap-configuration-management-core + ${project.version} + runtime org.openecomp.sdc - openecomp-sdc-common-rest + openecomp-sdc-logging-api ${project.version} org.openecomp.sdc - common-app-api + openecomp-sdc-logging-core ${project.version} + runtime - org.onap.sdc.common - onap-configuration-management-api - ${project.version} + org.apache.cxf + cxf-rt-rs-client + ${cxf.version} + runtime - org.onap.sdc.common - onap-configuration-management-core - ${project.version} - runtime + org.slf4j + slf4j-simple + ${slf4j.version} + test - org.openecomp.sdc.onboarding - vendor-software-products-rest-services - ${project.version} + junit + junit + ${junit.version} + test + + + com.github.tomakehurst + wiremock + 2.18.0 + test - diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/VnfPackageRepository.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/VnfPackageRepository.java index 32a2ef5539..8723bf2237 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/VnfPackageRepository.java +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/VnfPackageRepository.java @@ -16,20 +16,25 @@ package org.openecomp.sdcrests.vsp.rest; +import static org.openecomp.sdcrests.common.RestConstants.USER_ID_HEADER_PARAM; +import static org.openecomp.sdcrests.common.RestConstants.USER_MISSING_ERROR_MSG; + import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; -import org.openecomp.sdcrests.vendorsoftwareproducts.types.UploadFileResponseDto; -import org.springframework.validation.annotation.Validated; - +import java.io.File; import javax.validation.constraints.NotNull; -import javax.ws.rs.*; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.io.File; - -import static org.openecomp.sdcrests.common.RestConstants.USER_ID_HEADER_PARAM; -import static org.openecomp.sdcrests.common.RestConstants.USER_MISSING_ERROR_MSG; +import org.openecomp.sdcrests.vendorsoftwareproducts.types.UploadFileResponseDto; +import org.springframework.validation.annotation.Validated; @Path("/v1.0/vendor-software-products/{vspId}/versions/{versionId}/vnfrepository") @Produces(MediaType.APPLICATION_JSON) @@ -41,7 +46,8 @@ public interface VnfPackageRepository extends VspEntities { @GET @Path("/vnfpackages") @Produces(MediaType.APPLICATION_OCTET_STREAM) - @ApiOperation(value = "Get VNF packages from VNF Repository", notes = "Call VNF Repostory to get VNF package details", response = File.class) + @ApiOperation(value = "Get VNF packages from VNF Repository", + notes = "Call VNF Repository to get VNF package details", response = File.class) Response getVnfPackages(@PathParam("vspId") String vspId, @ApiParam(value = "Version Id") @PathParam("versionId") String versionId, @NotNull(message = USER_MISSING_ERROR_MSG) @HeaderParam(USER_ID_HEADER_PARAM) String user) throws Exception; @@ -49,7 +55,8 @@ public interface VnfPackageRepository extends VspEntities { @GET @Path("/vnfpackage/{csarId}/download") @Produces(MediaType.APPLICATION_OCTET_STREAM) - @ApiOperation(value = "Download VNF package from VNF Repository", notes = "Download VNF package from VNF repository and send to client", response = File.class) + @ApiOperation(value = "Download VNF package from VNF Repository", + notes = "Download VNF package from VNF repository and send to client", response = File.class) Response downloadVnfPackage(@PathParam("vspId") String vspId, @ApiParam(value = "Version Id") @PathParam("versionId") String versionId, @PathParam("csarId") String csarId, @@ -58,7 +65,9 @@ public interface VnfPackageRepository extends VspEntities { @POST @Path("/vnfpackage/{csarId}/import") @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Import VNF package from VNF Repository", notes = "Call VNF Repostory to download VNF package, validate it and send the response", response = UploadFileResponseDto.class) + @ApiOperation(value = "Import VNF package from VNF Repository", + notes = "Call VNF Repository to download VNF package, validate it and send the response", + response = UploadFileResponseDto.class) Response importVnfPackage(@PathParam("vspId") String vspId, @ApiParam(value = "Version Id") @PathParam("versionId") String versionId, @PathParam("csarId") String csarId, diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/services/VnfPackageRepositoryImpl.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/services/VnfPackageRepositoryImpl.java index 7905417a6c..be14c45dc4 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/services/VnfPackageRepositoryImpl.java +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/main/java/org/openecomp/sdcrests/vsp/rest/services/VnfPackageRepositoryImpl.java @@ -1,5 +1,6 @@ /* * Copyright 2017 Huawei Technologies Co., Ltd. + * Modifications Copyright 2018 European Support Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +17,34 @@ package org.openecomp.sdcrests.vsp.rest.services; -import org.apache.http.HttpStatus; -import org.onap.config.api.Configuration; +import static javax.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION; +import static org.openecomp.core.utilities.file.FileUtils.getFileExtension; +import static org.openecomp.core.utilities.file.FileUtils.getNetworkPackageName; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import javax.inject.Named; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Link; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; import org.onap.config.api.ConfigurationManager; -import org.openecomp.sdc.common.http.client.api.HttpRequest; -import org.openecomp.sdc.common.http.client.api.HttpResponse; +import org.openecomp.sdc.common.errors.CoreException; +import org.openecomp.sdc.common.errors.ErrorCode; +import org.openecomp.sdc.common.errors.ErrorCodeAndMessage; +import org.openecomp.sdc.common.errors.GeneralErrorBuilder; import org.openecomp.sdc.logging.api.Logger; import org.openecomp.sdc.logging.api.LoggerFactory; import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager; @@ -35,22 +59,14 @@ import org.openecomp.sdcrests.vsp.rest.mapping.MapUploadFileResponseToUploadFile import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; -import javax.inject.Named; -import javax.ws.rs.core.Response; -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - -import static javax.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION; -import static org.openecomp.core.utilities.file.FileUtils.getFileExtension; -import static org.openecomp.core.utilities.file.FileUtils.getNetworkPackageName; - /** - * The class implements the API interface with VNF Repository (VNFSDK) such as - * i) Get all the VNF Package Meta-data ii) Download the VNF Package iii) Import - * VNF package to SDC catalog (Download & validate) - * + * Enables integration API interface with VNF Repository (VNFSDK). + *
    + *
  1. Get all the VNF Package Meta-data.
  2. + *
  3. Download a VNF Package.
  4. + *
  5. Import a VNF package to SDC catalog (Download & validate).
  6. + *
+ * * @version Amsterdam release (ONAP 1.0) */ @Named @@ -60,163 +76,306 @@ public class VnfPackageRepositoryImpl implements VnfPackageRepository { private static final Logger LOGGER = LoggerFactory.getLogger(VnfPackageRepositoryImpl.class); - private static boolean initFlag = false; + private final Configuration config; - // Default VNF Repository configuration - private static final String CONFIG_NAMESPACE = "vnfrepo"; + public VnfPackageRepositoryImpl(Configuration config) { + this.config = config; + } - // Default address for VNF repository docker - private static final String DEF_DOCKER_COMPOSE_ADDR = "127.0.0.1"; + public VnfPackageRepositoryImpl() { + this(new FileConfiguration()); + } - private static String ipAddress = DEF_DOCKER_COMPOSE_ADDR; + @Override + public Response getVnfPackages(String vspId, String versionId, String user) { - // Default Download package URI and Get VNF package meta-data URI - - // configurable - private static String getVnfPkgUri = "/onapapi/vnfsdk-marketplace/v1/PackageResource/csars"; + LOGGER.debug("Get VNF Packages from Repository: {}", vspId); - private static String downldPkgUri = "/onapapi/vnfsdk-marketplace/v1/PackageResource/csars/%s/files"; + Client client = new SharedClient(); - // Default port for VNF Repository - private static String port = "8702"; + final String getVnfPackageUri = config.getGetUri(); - @Override - public Response getVnfPackages(String vspId, String versionId, String user) throws Exception { + try { - LOGGER.debug("Get VNF Packages from Repository:{}", vspId); + Response remoteResponse = client.target(getVnfPackageUri).request().get(); + if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) { + return handleUnexpectedStatus("querying VNF package metadata", getVnfPackageUri, remoteResponse); + } - // Step 1: Create REST client and configuration and prepare URI - init(); + LOGGER.debug("Response from VNF Repository: {}", remoteResponse); + return Response.ok(remoteResponse.readEntity(String.class)).build(); - // Step 2: Build URI based on the IP address and port allocated - HttpResponse rsp = HttpRequest.get(getVnfPkgUri); - if(HttpStatus.SC_OK != rsp.getStatusCode()) { - LOGGER.error("Failed to query VNF package metadata:uri={}, Response={}", getVnfPkgUri, rsp); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } finally { + client.close(); } - - // Step 3: Send the response to the client - LOGGER.debug("Response from VNF Repository: {}", rsp.getResponse()); - - return Response.ok(rsp.getResponse()).build(); } @Override - public Response importVnfPackage(String vspId, String versionId, String csarId, String user) throws Exception { + public Response importVnfPackage(String vspId, String versionId, String csarId, String user) { + + LOGGER.debug("Import VNF Packages from Repository: {}", csarId); + + final String downloadPackageUri = String.format(config.getDownloadUri(), csarId); + + Client client = new SharedClient(); + + try { - LOGGER.debug("Import VNF Packages from Repository:{}", csarId); + Response remoteResponse = client.target(downloadPackageUri).request().get(); + if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) { + return handleUnexpectedStatus("downloading VNF package", downloadPackageUri, remoteResponse); + } - // Step 1: Create REST client and configuration and prepare URI - init(); + LOGGER.debug("Response from VNF Repository for download package is success. URI={}", downloadPackageUri); + byte[] payload = remoteResponse.readEntity(String.class).getBytes(StandardCharsets.ISO_8859_1); + return uploadVnfPackage(vspId, versionId, csarId, payload); - // Step 2: Build URI based on the IP address and port allocated - String uri = String.format(downldPkgUri, csarId); - HttpResponse rsp = HttpRequest.get(uri); - if(HttpStatus.SC_OK != rsp.getStatusCode()) { - LOGGER.error("Failed to download package from VNF Repository:uri={}, Response={}", uri, rsp); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + } finally { + client.close(); } - LOGGER.debug("Response from VNF Repository for download package is success "); + } + + private Response uploadVnfPackage(String vspId, String versionId, String csarId, byte[] payload) { - // Step 3: Import the file to SDC and validate and send the response - try (InputStream fileStream = new BufferedInputStream( - new ByteArrayInputStream(rsp.getResponse().getBytes(StandardCharsets.ISO_8859_1)))) { + try (InputStream fileStream = new BufferedInputStream(new ByteArrayInputStream(payload))) { - String filename = "temp_" + csarId + ".csar"; OrchestrationTemplateCandidateManager candidateManager = OrchestrationTemplateCandidateManagerFactory.getInstance().createInterface(); - UploadFileResponse uploadFileResponse = candidateManager.upload(vspId, getVersion(vspId, versionId), - fileStream, getFileExtension(filename), getNetworkPackageName(filename)); - UploadFileResponseDto uploadFileResponseDto = new MapUploadFileResponseToUploadFileResponseDto() - .applyMapping(uploadFileResponse, UploadFileResponseDto.class); + String filename = formatFilename(csarId); + Version version = getVersion(vspId, versionId); + UploadFileResponse response = candidateManager.upload(vspId, version, fileStream, + getFileExtension(filename), getNetworkPackageName(filename)); - return Response.ok(uploadFileResponseDto).build(); - } catch(Exception e) { - // Exception while uploading file + UploadFileResponseDto uploadFileResponse = new MapUploadFileResponseToUploadFileResponseDto() + .applyMapping(response, UploadFileResponseDto.class); - LOGGER.error("Exception while uploading VNF package received from VNF Repository:", e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); + return Response.ok(uploadFileResponse).build(); + + } catch (Exception e) { + ErrorCode error = new GeneralErrorBuilder().build(); + LOGGER.error("Exception while uploading package received from VNF Repository", new CoreException(error, e)); + return generateInternalServerError(error); } } @Override - public Response downloadVnfPackage(String vspId, String versionId, String csarId, String user) throws Exception { + public Response downloadVnfPackage(String vspId, String versionId, String csarId, String user) { - LOGGER.debug("Download VNF Packages from Repository:csarId={}", csarId); + LOGGER.debug("Download VNF package from repository: csarId={}", csarId); - // Step 1: Create REST client and configuration and prepare URI - init(); + final String downloadPackageUri = String.format(config.getDownloadUri(), csarId); - // Step 2: Build URI based on the IP address and port allocated - String uri = String.format(downldPkgUri, csarId); - HttpResponse rsp = HttpRequest.get(uri); - if(HttpStatus.SC_OK != rsp.getStatusCode()) { - LOGGER.error("Failed to download package from VNF Repository:uri={}, Response={}", uri, rsp); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); - } + Client client = new SharedClient(); - // Step 3:Send response to the client - String filename = "temp_" + csarId + ".csar"; - Response.ResponseBuilder response = Response.ok(rsp.getResponse().getBytes(StandardCharsets.ISO_8859_1)); - response.header(CONTENT_DISPOSITION, "attachment; filename=" + filename); + try { - LOGGER.debug("Response from VNF Repository for download package is success "); + Response remoteResponse = client.target(downloadPackageUri).request().get(); + if (remoteResponse.getStatus() != Response.Status.OK.getStatusCode()) { + return handleUnexpectedStatus("downloading VNF package", downloadPackageUri, remoteResponse); + } + + byte[] payload = remoteResponse.readEntity(String.class).getBytes(StandardCharsets.ISO_8859_1); + Response.ResponseBuilder response = Response.ok(payload); + response.header(CONTENT_DISPOSITION, "attachment; filename=" + formatFilename(csarId)); - return response.build(); + LOGGER.debug("Response from VNF Repository for download package is success. URI={}", downloadPackageUri); + return response.build(); + + } finally { + client.close(); + } } private Version getVersion(String vspId, String versionId) { - // Get list of Versions from the rest call VersioningManager versioningManager = VersioningManagerFactory.getInstance().createInterface(); + return findVersion(versioningManager.list(vspId), versionId).orElse(new Version(versionId)); + } - // Find the corresponding version from versionId - return versioningManager.list(vspId).stream().filter(ver -> ver.getId() != versionId).findAny() - .orElse(new Version(versionId)); + Optional findVersion(List versions, String requestedVersion) { + return versions.stream().filter(ver -> Objects.equals(ver.getId(), requestedVersion)).findAny(); } - private static void setVnfRepoConfig() { + private static Response handleUnexpectedStatus(String action, String uri, Response response) { + ErrorCode error = new GeneralErrorBuilder().build(); + LOGGER.error("Unexpected response status while {}: URI={}, Response={}", action, uri, response, + new CoreException(error)); + return generateInternalServerError(error); + } - try { - // Step 1: Fetch the on-boarding configuration - Configuration config = ConfigurationManager.lookup(); + private static Response generateInternalServerError(ErrorCode error) { + ErrorCodeAndMessage payload = new ErrorCodeAndMessage(Response.Status.INTERNAL_SERVER_ERROR, error); + return Response.serverError().entity(payload).build(); + } - String vnfRepoHost = config.getAsString(CONFIG_NAMESPACE, "vnfRepoHost"); - if(null != vnfRepoHost) { - ipAddress = vnfRepoHost; - } + private static String formatFilename(String csarId) { + return "temp_" + csarId + ".csar"; + } - String vnfRepoPort = config.getAsString(CONFIG_NAMESPACE, "vnfRepoPort"); - if(null != vnfRepoPort) { - port = vnfRepoPort; - } + interface Configuration { - String getVnfUri = config.getAsString(CONFIG_NAMESPACE, "getVnfUri"); - if(null != getVnfUri) { - getVnfPkgUri = getVnfUri; - } + String getGetUri(); - String downloadVnfUri = config.getAsString(CONFIG_NAMESPACE, "downloadVnfUri"); - if(null != downloadVnfUri) { - downldPkgUri = downloadVnfUri; - } + String getDownloadUri(); + } + + private static class SharedClient implements Client { + + private static final Client CLIENT = ClientBuilder.newClient(); + + @Override + public void close() { + // do not close the shared client + } + + @Override + public WebTarget target(String uri) { + return CLIENT.target(uri); + } + + @Override + public WebTarget target(URI uri) { + return CLIENT.target(uri); + } + + @Override + public WebTarget target(UriBuilder uriBuilder) { + return CLIENT.target(uriBuilder); + } + + @Override + public WebTarget target(Link link) { + return CLIENT.target(link); + } + + @Override + public Invocation.Builder invocation(Link link) { + return CLIENT.invocation(link); + } + + @Override + public SSLContext getSslContext() { + return CLIENT.getSslContext(); + } + + @Override + public HostnameVerifier getHostnameVerifier() { + return CLIENT.getHostnameVerifier(); + } + + @Override + public javax.ws.rs.core.Configuration getConfiguration() { + return CLIENT.getConfiguration(); + } + + @Override + public Client property(String name, Object value) { + return CLIENT.property(name, value); + } + + @Override + public Client register(Class componentClass) { + return CLIENT.register(componentClass); + } + + @Override + public Client register(Class componentClass, int priority) { + return CLIENT.register(componentClass, priority); + } - } catch(Exception e) { - LOGGER.error("Failed to load configuration, Exception caught, using default configuration", e); + @Override + public Client register(Class componentClass, Class... contracts) { + return CLIENT.register(componentClass, contracts); } - getVnfPkgUri = - new StringBuilder("http://").append(ipAddress).append(":").append(port).append(getVnfPkgUri).toString(); + @Override + public Client register(Class componentClass, Map, Integer> contracts) { + return CLIENT.register(componentClass, contracts); + } + + @Override + public Client register(Object component) { + return CLIENT.register(component); + } + + @Override + public Client register(Object component, int priority) { + return CLIENT.register(component, priority); + } + + @Override + public Client register(Object component, Class... contracts) { + return CLIENT.register(component, contracts); + } - downldPkgUri = - new StringBuilder("http://").append(ipAddress).append(":").append(port).append(downldPkgUri).toString(); + @Override + public Client register(Object component, Map, Integer> contracts) { + return CLIENT.register(component, contracts); + } } - private static synchronized void init() throws Exception { - if(!initFlag) { - // Step 1: Initialize configuration - setVnfRepoConfig(); + static class FileConfiguration implements Configuration { + + @Override + public String getGetUri() { + return LazyFileConfiguration.INSTANCE.getGetUri(); + } + + @Override + public String getDownloadUri() { + return LazyFileConfiguration.INSTANCE.getDownloadUri(); + } + + private static class LazyFileConfiguration implements Configuration { + + private static final String CONFIG_NAMESPACE = "vnfrepo"; - initFlag = true; + private static final String DEFAULT_HOST = "localhost"; + private static final String DEFAULT_PORT = "8702"; + + private static final String DEFAULT_URI_PREFIX = "/onapapi/vnfsdk-marketplace/v1/PackageResource/csars"; + private static final String DEFAULT_LIST_URI = DEFAULT_URI_PREFIX + "/"; + private static final String DEFAULT_DOWNLOAD_URI = DEFAULT_URI_PREFIX + "/%s/files"; + + private static final LazyFileConfiguration INSTANCE = new LazyFileConfiguration(); + + private final String getUri; + private final String downloadUri; + + private LazyFileConfiguration() { + org.onap.config.api.Configuration config = ConfigurationManager.lookup(); + String host = readConfig(config, "vnfRepoHost", DEFAULT_HOST); + String port = readConfig(config, "vnfRepoPort", DEFAULT_PORT); + String listPackagesUri = readConfig(config, "getVnfUri", DEFAULT_LIST_URI); + String downloadPackageUri = readConfig(config, "downloadVnfUri", DEFAULT_DOWNLOAD_URI); + this.getUri = formatUri(host, port, listPackagesUri); + this.downloadUri = formatUri(host, port, downloadPackageUri); + } + + private String readConfig(org.onap.config.api.Configuration config, String key, String defaultValue) { + + try { + String value = config.getAsString(CONFIG_NAMESPACE, key); + return (value == null) ? defaultValue : value; + } catch (Exception e) { + LOGGER.error( + "Failed to read VNF repository configuration key '{}', default value '{}' will be used", + key, defaultValue, e); + return defaultValue; + } + } + + private static String formatUri(String host, String port, String path) { + return "http://" + host + ":" + port + (path.startsWith("/") ? path : "/" + path); + } + + public String getGetUri() { + return getUri; + } + + public String getDownloadUri() { + return downloadUri; + } } } } diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/services/VnfPackageRepositoryImplTest.java b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/services/VnfPackageRepositoryImplTest.java new file mode 100644 index 0000000000..b0f53bac34 --- /dev/null +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/test/java/org/openecomp/sdcrests/vsp/rest/services/VnfPackageRepositoryImplTest.java @@ -0,0 +1,171 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdcrests.vsp.rest.services; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import javax.ws.rs.core.Response; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.openecomp.sdc.versioning.dao.types.Version; + +/** + * Configuration testing. + * WireMock testing of remote calls. + * + * @author evitaliy + * @since 19 Jul 2018 + */ +public class VnfPackageRepositoryImplTest { + + private static final String GET_PATH = "/get"; + private static final String DOWNLOAD_PATH = "/download"; + + @ClassRule + public static final WireMockRule wireMockRule = new WireMockRule(wireMockConfig().dynamicPort()); + private static final String VSP = "anyVsp"; + private static final String VERSION = "anyVersion"; + private static final String USER = "anyUser"; + private static final String CSAR = "anyCsar"; + + private static VnfPackageRepositoryImpl.Configuration config; + + @BeforeClass + public static void initConfiguration() { + config = new DynamicConfiguration(wireMockRule.port()); + } + + @Test + public void versionFoundWhenInList() { + VnfPackageRepositoryImpl vnfRepository = new VnfPackageRepositoryImpl(); + List versions = Arrays.asList(new Version("1243"), new Version("3434"), new Version("398")); + assertTrue("Expected to find the version", vnfRepository.findVersion(versions, "3434").isPresent()); + } + + @Test + public void versionNotFoundWhenInList() { + VnfPackageRepositoryImpl vnfRepository = new VnfPackageRepositoryImpl(); + List versions = Collections.singletonList(new Version("1243")); + assertFalse("Did not expect to find the version", vnfRepository.findVersion(versions, "3434").isPresent()); + } + + @Test + public void configurationLoadedFromFile() { + final String prefix = "http://10.57.30.20:1111/"; + assertEquals(prefix + "download-vnf-31", new VnfPackageRepositoryImpl.FileConfiguration().getDownloadUri()); + assertEquals(prefix + "get-vnf-13", new VnfPackageRepositoryImpl.FileConfiguration().getGetUri()); + } + + @Test + public void listVnfsReturnsInternalServerErrorWhenRemoteClientError() { + stubFor(get(GET_PATH).willReturn(aResponse().withStatus(403))); + VnfPackageRepositoryImpl repository = new VnfPackageRepositoryImpl(config); + Response response = repository.getVnfPackages(VSP, VERSION, USER); + assertEquals(500, response.getStatus()); + verify(getRequestedFor(urlEqualTo(GET_PATH))); + } + + @Test + public void listVnfsReturnsInternalServerErrorWhenRemoteReturnsNotOk() { + stubFor(get(GET_PATH).willReturn(aResponse().withStatus(204))); + VnfPackageRepositoryImpl repository = new VnfPackageRepositoryImpl(config); + Response response = repository.getVnfPackages(VSP, VERSION, USER); + assertEquals(500, response.getStatus()); + verify(getRequestedFor(urlEqualTo(GET_PATH))); + } + + @Test + public void listVnfsReturnsUnchangedResponse() { + final String vnfList = "this is a response body for list of VNFs"; + stubFor(get(GET_PATH).willReturn(aResponse().withStatus(200).withBody(vnfList))); + VnfPackageRepositoryImpl repository = new VnfPackageRepositoryImpl(config); + Response response = repository.getVnfPackages(VSP, VERSION, USER); + assertEquals(200, response.getStatus()); + assertEquals(vnfList, response.getEntity()); + verify(getRequestedFor(urlEqualTo(GET_PATH))); + } + + @Test + public void downloadVnfsReturnsInternalServerErrorWhenRemoteClientError() { + stubFor(get(DOWNLOAD_PATH).willReturn(aResponse().withStatus(403))); + VnfPackageRepositoryImpl repository = new VnfPackageRepositoryImpl(config); + Response response = repository.downloadVnfPackage(VSP, VERSION, CSAR, USER); + assertEquals(500, response.getStatus()); + verify(getRequestedFor(urlEqualTo(DOWNLOAD_PATH))); + } + + @Test + public void downloadVnfsReturnsInternalServerErrorWhenRemoteReturnsNotOk() { + stubFor(get(DOWNLOAD_PATH).willReturn(aResponse().withStatus(204))); + VnfPackageRepositoryImpl repository = new VnfPackageRepositoryImpl(config); + Response response = repository.downloadVnfPackage(VSP, VERSION, CSAR, USER); + assertEquals(500, response.getStatus()); + verify(getRequestedFor(urlEqualTo(DOWNLOAD_PATH))); + } + + @Test + public void downloadVnfsReturnsUnchangedBytes() { + final byte[] body = "this is the content of a VNF archive (.csar) file".getBytes(StandardCharsets.ISO_8859_1); + stubFor(get(DOWNLOAD_PATH).willReturn(aResponse().withStatus(200).withBody(body))); + VnfPackageRepositoryImpl repository = new VnfPackageRepositoryImpl(config); + Response response = repository.downloadVnfPackage(VSP, VERSION, CSAR, USER); + assertEquals(200, response.getStatus()); + assertTrue(Arrays.equals(body, response.readEntity(byte[].class))); + assertNotNull(response.getHeaderString("Content-Disposition")); + verify(getRequestedFor(urlEqualTo(DOWNLOAD_PATH))); + } + + private static class DynamicConfiguration implements VnfPackageRepositoryImpl.Configuration { + + private final int port; + + private DynamicConfiguration(int port) { + this.port = port; + } + + @Override + public String getGetUri() { + return toUri(GET_PATH); + } + + @Override + public String getDownloadUri() { + return toUri(DOWNLOAD_PATH); + } + + private String toUri(String path) { + return "http://localhost:" + port + path; + } + } + +} \ No newline at end of file diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/test/resources/config-vnfrepo.yaml b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/test/resources/config-vnfrepo.yaml new file mode 100644 index 0000000000..8057053072 --- /dev/null +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/vendor-software-products-rest/vnf-repository-rest-services/src/test/resources/config-vnfrepo.yaml @@ -0,0 +1,4 @@ +vnfRepoPort: 1111 +vnfRepoHost: 10.57.30.20 +getVnfUri: get-vnf-13 +downloadVnfUri: download-vnf-31 \ No newline at end of file -- 2.16.6