diff options
28 files changed, 822 insertions, 614 deletions
diff --git a/docs/configuration.rst b/docs/configuration.rst index 55c4751804..cf1bcd3220 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -1222,28 +1222,20 @@ BE-onboarding-configuration.yaml truststorePath: /config/truststore truststorePassword: <%= @cassandra_truststore_password %> - # External Testing Configuration - externalTestingConfig: - #configuration to make available to the front end of this feature - client: - enabled: true - #array of endpoints that SDC-BE should connect with for external testing - endpoints: - // ID for endpoint - - id: vtp - // what format of post request does the endpoint accept for runs - json or multi-part form - postStyle: application/json - // is this endpoint enabled or disabled. - enabled: false - // base URL for the endpoint - url: http://ec2-34-237-35-152.compute-1.amazonaws.com:9090 - // optional api key to pass in header to endpoint - apiKey: blahblahblah - - id: certifications repository - postStyle: application/json - url: http://ec2-34-237-35-152.compute-1.amazonaws.com:9090 - enabled: true - apiKey: blahblahblah2 +externaltesting-configuration.yaml +********************************** + +:: + + # configuration to make available to the front end of this feature + client: + enabled: true + # array of endpoints that SDC-BE should connect with for external testing + # id,label,enabled,url[,scenariofilter][,apikey] + endpoints: + - vtp:VTP,true,http://<hostname>[:<port>]/onapapi/vnfsdk-marketplace,c.* + - repository:Repository,false,http://<ovphostname>[:<ovpport>] + vnfrepo-configuration.yaml diff --git a/docs/consumedapis.rst b/docs/consumedapis.rst index 0e2380f197..8e70210918 100644 --- a/docs/consumedapis.rst +++ b/docs/consumedapis.rst @@ -19,4 +19,24 @@ SDC allows the user to choose packages from VNF-SDK and start the onboarding fro * - /onapapi/vnfsdk-marketplace/v1/PackageResource/csars - get all available csar package data * - /onapapi/vnfsdk-marketplace/v1/PackageResource/csars/{id}/files - - Download CSAR by id
\ No newline at end of file + - Download CSAR by id + + +SDC invokes Compliance Checks via VNF Test Platform (VTP) + +.. list-table:: + :widths: 60 40 + :header-rows: 1 + + * - URL + - Description + * - /vtp/scenarios + - retrieve list available test scenarios + * - /vtp/scenarios/{scenario}/testsuites + - retrieve a list of available test suites in given scenario + * - /vtp/scenarios/{scenario}/testcases + - retrieve a list of available test cases in a given scenario + * - /vtp/scenarios/{scenario}/testsuites/{testSuiteName}/testcases/{testCaseName} + - retrieve test case parameters such as inputs and outputs in a given scenario and test suite + * - /vtp/executions + - execute a list of test cases diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/main/java/org/openecomp/sdcrests/externaltesting/rest/ExternalTesting.java b/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/main/java/org/openecomp/sdcrests/externaltesting/rest/ExternalTesting.java index 14c45fbdbe..21cab55dc0 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/main/java/org/openecomp/sdcrests/externaltesting/rest/ExternalTesting.java +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/main/java/org/openecomp/sdcrests/externaltesting/rest/ExternalTesting.java @@ -17,6 +17,8 @@ package org.openecomp.sdcrests.externaltesting.rest; import io.swagger.annotations.Api; +import org.openecomp.core.externaltesting.api.ClientConfiguration; +import org.openecomp.core.externaltesting.api.RemoteTestingEndpointDefinition; import org.openecomp.core.externaltesting.api.VtpTestExecutionRequest; import org.springframework.validation.annotation.Validated; @@ -38,6 +40,10 @@ public interface ExternalTesting { @Path("/config") Response getConfig(); + @PUT + @Path("/config") + Response setConfig(ClientConfiguration config); + @GET @Path("/testcasetree") Response getTestCasesAsTree(); @@ -46,6 +52,10 @@ public interface ExternalTesting { @Path("/endpoints") Response getEndpoints(); + @PUT + @Path("/endpoints") + Response setEndpoints(List<RemoteTestingEndpointDefinition> endpoints); + @GET @Path("/endpoints/{endpointId}/scenarios") Response getScenarios(@PathParam("endpointId") String endpointId); diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/main/java/org/openecomp/sdcrests/externaltesting/rest/services/ExternalTestingImpl.java b/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/main/java/org/openecomp/sdcrests/externaltesting/rest/services/ExternalTestingImpl.java index 206eb4986b..4e8134ff69 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/main/java/org/openecomp/sdcrests/externaltesting/rest/services/ExternalTestingImpl.java +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/main/java/org/openecomp/sdcrests/externaltesting/rest/services/ExternalTestingImpl.java @@ -24,6 +24,7 @@ import org.openecomp.sdc.logging.api.LoggerFactory; import org.openecomp.sdcrests.externaltesting.rest.ExternalTesting; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import javax.inject.Named; @@ -62,6 +63,22 @@ public class ExternalTestingImpl implements ExternalTesting { } /** + * To enable automated functional testing, allow + * a put for the client configuration. + * @return JSON response content. + */ + @Override + public Response setConfig(ClientConfiguration config) { + try { + return Response.ok(testingManager.setConfig(config)).build(); + } + catch (ExternalTestingException e) { + return convertTestingException(e); + } + } + + + /** * Return the test tree structure created by the testing manager. * @return JSON response content. */ @@ -83,8 +100,22 @@ public class ExternalTestingImpl implements ExternalTesting { catch (ExternalTestingException e) { return convertTestingException(e); } + } + /** + * To enable automated functional testing, allow a put of the endpoints. + * @return JSON response content. + */ + @Override + public Response setEndpoints(List<RemoteTestingEndpointDefinition> endpoints) { + try { + return Response.ok(testingManager.setEndpoints(endpoints)).build(); + } + catch (ExternalTestingException e) { + return convertTestingException(e); + } } + @Override public Response getScenarios(String endpoint) { try { @@ -130,13 +161,12 @@ public class ExternalTestingImpl implements ExternalTesting { public Response execute(List<VtpTestExecutionRequest> req, String requestId) { try { List<VtpTestExecutionResponse> responses = testingManager.execute(req, requestId); - List<Integer> statuses = responses.stream().map(r-> Optional.ofNullable(r.getHttpStatus()).orElse(200)).distinct().collect(Collectors.toList()); + List<Integer> statuses = responses.stream().map(r-> Optional.ofNullable(r.getHttpStatus()).orElse(HttpStatus.OK.value())).distinct().collect(Collectors.toList()); if (statuses.size() == 1) { - // 1 status so use it... - return Response.status(statuses.get(0)).entity(responses).build(); + return Response.status(HttpStatus.OK.value()).entity(responses).build(); } else { - return Response.status(207).entity(responses).build(); + return Response.status(HttpStatus.MULTI_STATUS.value()).entity(responses).build(); } } catch (ExternalTestingException e) { @@ -156,9 +186,9 @@ public class ExternalTestingImpl implements ExternalTesting { private Response convertTestingException(ExternalTestingException e) { if (logger.isErrorEnabled()) { - logger.error("testing exception {} {} {}", e.getTitle(), e.getCode(), e.getDetail(), e); + logger.error("testing exception {} {} {}", e.getMessageCode(), e.getHttpStatus(), e.getDetail(), e); } - TestErrorBody body = new TestErrorBody(e.getTitle(), e.getCode(), e.getDetail()); - return Response.status(e.getCode()).entity(body).build(); + TestErrorBody body = new TestErrorBody(e.getMessageCode(), e.getHttpStatus(), e.getDetail()); + return Response.status(e.getHttpStatus()).entity(body).build(); } } diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/test/java/org/openecomp/sdcrests/externaltesting/rest/services/ApiTests.java b/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/test/java/org/openecomp/sdcrests/externaltesting/rest/services/ApiTests.java index d9da7e9006..411be2f150 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/test/java/org/openecomp/sdcrests/externaltesting/rest/services/ApiTests.java +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/externaltesting-rest/externaltesting-rest-services/src/test/java/org/openecomp/sdcrests/externaltesting/rest/services/ApiTests.java @@ -58,13 +58,23 @@ public class ApiTests { Assert.assertNotNull(testing.getTestCasesAsTree()); List<VtpTestExecutionRequest> requests = - Arrays.asList(new VtpTestExecutionRequest(), new VtpTestExecutionRequest()); + Arrays.asList(new VtpTestExecutionRequest(), new VtpTestExecutionRequest()); Assert.assertNotNull(testing.execute(requests, "requestId")); } class ApiTestExternalTestingManager implements ExternalTestingManager { @Override - public String getConfig() { + public ClientConfiguration getConfig() { + throw new ExternalTestingException(EXPECTED, 500, EXPECTED); + } + + @Override + public ClientConfiguration setConfig(ClientConfiguration config) { + throw new ExternalTestingException(EXPECTED, 500, EXPECTED); + } + + @Override + public List<RemoteTestingEndpointDefinition> setEndpoints(List<RemoteTestingEndpointDefinition> endpoints) { throw new ExternalTestingException(EXPECTED, 500, EXPECTED); } @@ -74,7 +84,7 @@ public class ApiTests { } @Override - public List<VtpNameDescriptionPair> getEndpoints() { + public List<RemoteTestingEndpointDefinition> getEndpoints() { throw new ExternalTestingException(EXPECTED, 500, EXPECTED); } @@ -177,7 +187,7 @@ public class ApiTests { } List<VtpTestExecutionRequest> requestsF = - Arrays.asList(new VtpTestExecutionRequest(), new VtpTestExecutionRequest()); + Arrays.asList(new VtpTestExecutionRequest(), new VtpTestExecutionRequest()); try { testingF.execute(requestsF, null); diff --git a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/beans-services.xml b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/beans-services.xml index e0e979142a..11c2cef4f3 100644 --- a/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/beans-services.xml +++ b/openecomp-be/api/openecomp-sdc-rest-webapp/onboarding-rest-war/src/main/webapp/WEB-INF/beans-services.xml @@ -45,7 +45,6 @@ <!-- External Testing Interface Beans --> <bean id = "externalTestingManager" class="org.openecomp.core.externaltesting.impl.ExternalTestingManagerImpl"/> - <bean id = "csarHandler" class="org.openecomp.core.externaltesting.impl.CsarMetadataVariableResolver"/> <!-- RESTful Services --> <jaxrs:server id="restContainer" address="/"> diff --git a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/attributes/default.rb b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/attributes/default.rb index 013a87d391..9865f8025e 100644 --- a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/attributes/default.rb +++ b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/attributes/default.rb @@ -18,3 +18,9 @@ default['cassandra']['cluster_name'] = "SDC-CS-" default['cassandra']['socket_read_timeout'] = 20000 default['cassandra']['socket_connect_timeout'] = 20000 default['cassandra']['titan_connection_timeout'] = 10000 + + +#ExternalTesting +default['EXTTEST']['ep1_config'] = "vtp,VTP,true,http://192.168.50.5:8702/onapapi/vnfsdk-marketplace,c.*" +default['EXTTEST']['ep2_config'] = "repository,Repository,false,,.*" + diff --git a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb index 6de66fbf4f..5f7e5e62ef 100644 --- a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb +++ b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/recipes/ON_5_setup_configuration.rb @@ -37,3 +37,17 @@ template "VnfrepoConfiguration" do :VNFREPO_PORT => node['VnfRepo']['vnfRepoPort'] }) end + + + +template "ExternalTestingConfiguration" do + path "#{ENV['JETTY_BASE']}/config/onboarding-be/externaltesting-configuration.yaml" + source "externaltesting-configuration.yaml.erb" + owner "jetty" + group "jetty" + mode "0755" + variables({ + :EP1_CONFIG => node['EXTTEST']['ep1_config'], + :EP2_CONFIG => node['EXTTEST']['ep2_config'] + }) +end diff --git a/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/externaltesting-configuration.yaml.erb b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/externaltesting-configuration.yaml.erb new file mode 100644 index 0000000000..599b5d40f7 --- /dev/null +++ b/openecomp-be/dist/sdc-onboard-backend-docker/artifacts/chef-repo/cookbooks/sdc-onboard-backend/templates/default/externaltesting-configuration.yaml.erb @@ -0,0 +1,5 @@ +client: + enabled: true +endpoints: + - <%= @EP1_CONFIG %> + - <%= @EP2_CONFIG %> diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ClientConfiguration.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/ClientConfiguration.java index 2787e7e97f..9269e8bf22 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ClientConfiguration.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/ClientConfiguration.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.openecomp.core.externaltesting.impl; +package org.openecomp.core.externaltesting.api; import lombok.Data; diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/ExternalTestingManager.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/ExternalTestingManager.java index dc9b09c767..ac2f7fcafa 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/ExternalTestingManager.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/ExternalTestingManager.java @@ -25,7 +25,12 @@ public interface ExternalTestingManager { * Return the configuration of this feature that we want to * expose to the client. Treated as a JSON blob for flexibility. */ - String getConfig(); + ClientConfiguration getConfig(); + + /** + * For testing purposes, set the client configuration. + */ + ClientConfiguration setConfig(ClientConfiguration config); /** * Build a tree of all test cases for the client including all @@ -35,9 +40,16 @@ public interface ExternalTestingManager { TestTreeNode getTestCasesAsTree(); /** - * Get a list of testing endpoints with name and description. + * Get a list of testing endpoints. + */ + List<RemoteTestingEndpointDefinition> getEndpoints(); + + + /** + * For functional testing purposes, allow the endpoint configuration + * to be provisioned to the BE. */ - List<VtpNameDescriptionPair> getEndpoints(); + List<RemoteTestingEndpointDefinition> setEndpoints(List<RemoteTestingEndpointDefinition> endpoints); /** * Get a list of scenarios from and endpoint. diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/RemoteTestingEndpointDefinition.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/RemoteTestingEndpointDefinition.java index 205ca29680..0d5c30d593 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/RemoteTestingEndpointDefinition.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/RemoteTestingEndpointDefinition.java @@ -14,23 +14,30 @@ * limitations under the License. */ -package org.openecomp.core.externaltesting.impl; +package org.openecomp.core.externaltesting.api; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import java.util.regex.Pattern; @Data -class RemoteTestingEndpointDefinition { +public class RemoteTestingEndpointDefinition { private boolean enabled; private String title; private String url; private String id; private String apiKey; private String scenarioFilter; + + // a compact way to specify and endpoint to ease docker configuration. + @JsonIgnore + private String config; + private Pattern scenarioFilterPattern; - Pattern getScenarioFilterPattern() { + @JsonIgnore + public Pattern getScenarioFilterPattern() { if ((scenarioFilterPattern == null) && (scenarioFilter != null)) { scenarioFilterPattern = Pattern.compile(scenarioFilter); } diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/TestTreeNode.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/TestTreeNode.java index 42fa330d33..1b75772476 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/TestTreeNode.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/api/TestTreeNode.java @@ -47,18 +47,4 @@ public class TestTreeNode extends VtpNameDescriptionPair { public TestTreeNode(String name, String description) { super(name, description); } - - public void addTest(VtpTestCase test) { - if (tests == null) { - tests = new ArrayList<>(); - } - tests.add(test); - } - - public void addChild(TestTreeNode child) { - if (children == null) { - children = new ArrayList<>(); - } - children.add(child); - } } diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/errors/ExternalTestingException.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/errors/ExternalTestingException.java index 33fa0f4477..3df64a40eb 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/errors/ExternalTestingException.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/main/java/org/openecomp/core/externaltesting/errors/ExternalTestingException.java @@ -26,21 +26,21 @@ public class ExternalTestingException extends RuntimeException { private static final long serialVersionUID = -4357810130868566088L; - private final String title; - private final int code; + private final String messageCode; + private final int httpStatus; private final String detail; - public ExternalTestingException(String title, int code, String detail) { - super(title); - this.title = title; - this.code = code; + public ExternalTestingException(String messageCode, int httpStatus, String detail) { + super(messageCode); + this.messageCode = messageCode; + this.httpStatus = httpStatus; this.detail = detail; } - public ExternalTestingException(String title, int code, String detail, Throwable parent) { - super(title, parent); - this.title = title; - this.code = code; + public ExternalTestingException(String messageCode, int httpStatus, String detail, Throwable parent) { + super(messageCode, parent); + this.messageCode = messageCode; + this.httpStatus = httpStatus; this.detail = detail; } diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/test/java/org/openecomp/core/externaltesting/api/ExecutionRequestTests.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/test/java/org/openecomp/core/externaltesting/api/ExecutionRequestTests.java index b10d3079d2..bfa07ecc0c 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/test/java/org/openecomp/core/externaltesting/api/ExecutionRequestTests.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-api/src/test/java/org/openecomp/core/externaltesting/api/ExecutionRequestTests.java @@ -98,13 +98,5 @@ public class ExecutionRequestTests { Assert.assertEquals(2, tree.getChildren().size()); Assert.assertEquals(0, tree.getTests().size()); - - TestTreeNode manual = new TestTreeNode("root", "Root"); - - manual.addChild(new TestTreeNode("child", "child")); - manual.addTest(new VtpTestCase()); - Assert.assertEquals(1, manual.getChildren().size()); - Assert.assertEquals(1, manual.getTests().size()); - } } diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/pom.xml b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/pom.xml index 7411cf5cc1..dca5f11857 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/pom.xml +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/pom.xml @@ -68,6 +68,11 @@ <version>${project.version}</version> </dependency> <dependency> + <groupId>org.openecomp.sdc.core</groupId> + <artifactId>openecomp-heat-lib</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> @@ -93,9 +98,9 @@ <version>${project.version}</version> </dependency> <dependency> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>${lombok.version}</version> + <groupId>org.openecomp.sdc.core</groupId> + <artifactId>openecomp-tosca-lib</artifactId> + <version>${project.version}</version> </dependency> <dependency> <groupId>org.codehaus.groovy</groupId> diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/CsarMetadataVariableResolver.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/CsarMetadataVariableResolver.java deleted file mode 100644 index 191fff0c6c..0000000000 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/CsarMetadataVariableResolver.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright © 2019 iconectiv - * - * 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.core.externaltesting.impl; - -import lombok.EqualsAndHashCode; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.openecomp.core.externaltesting.api.VtpTestExecutionRequest; -import org.openecomp.core.externaltesting.errors.ExternalTestingException; -import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager; -import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManagerFactory; -import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; -import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory; -import org.openecomp.sdc.versioning.VersioningManager; -import org.openecomp.sdc.versioning.VersioningManagerFactory; -import org.openecomp.sdc.versioning.dao.types.Version; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.util.MultiValueMap; - -import javax.annotation.PostConstruct; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * The CSAR Metadata variable resolver is responsible for processing of - * variables in the test request. It looks for variables with the "csar:" prefix - * and extracts the contents of the uploaded CSAR file for a VSP. - */ -public class CsarMetadataVariableResolver implements VariableResolver { - - private Logger logger = LoggerFactory.getLogger(CsarMetadataVariableResolver.class); - - static final String VSP_ID = "vspId"; - static final String VSP_VERSION = "vspVersion"; - static final String CSAR_PREFIX = "csar:"; - - private VersioningManager versioningManager; - private VendorSoftwareProductManager vendorSoftwareProductManager; - private OrchestrationTemplateCandidateManager candidateManager; - - CsarMetadataVariableResolver(VersioningManager versioningManager, - VendorSoftwareProductManager vendorSoftwareProductManager, - OrchestrationTemplateCandidateManager candidateManager) { - this(); - this.versioningManager = versioningManager; - this.vendorSoftwareProductManager = vendorSoftwareProductManager; - this.candidateManager = candidateManager; - } - - CsarMetadataVariableResolver() { - - } - - @PostConstruct - public void init() { - if (versioningManager == null) { - versioningManager = VersioningManagerFactory.getInstance().createInterface(); - } - if (vendorSoftwareProductManager == null) { - vendorSoftwareProductManager = - VspManagerFactory.getInstance().createInterface(); - } - if (candidateManager == null) { - candidateManager = - OrchestrationTemplateCandidateManagerFactory.getInstance().createInterface(); - } - } - - @Override - public boolean resolvesVariablesForRequest(VtpTestExecutionRequest requestItem) { - Map<String,String> params = requestItem.getParameters(); - - // no params, quickly return. - if (params == null) { - return false; - } - - // no match, quickly return - if (!params.containsKey(VSP_ID) || !params.containsKey(VSP_VERSION)) { - return false; - } - - return (params.keySet().stream().anyMatch(s -> StringUtils.startsWith(s, CSAR_PREFIX))); - } - - @Override - public void resolve(VtpTestExecutionRequest requestItem, MultiValueMap<String, Object> body) { - logger.debug("run {} variable resolver...", this.getClass().getSimpleName()); - Map<String,String> params = requestItem.getParameters(); - String vspId = params.get(VSP_ID); - String version = params.get(VSP_VERSION); - - try { - extractMetadata(requestItem, body, vspId, version); - } - catch (IOException ex) { - logger.error("metadata extraction failed", ex); - } - } - - /** - * Extract the metadata from the VSP CSAR file. - * @param requestItem item to add metadata to for processing - * @param vspId VSP identifier - * @param version VSP version - */ - @SuppressWarnings("WeakerAccess") - protected void extractMetadata(VtpTestExecutionRequest requestItem, MultiValueMap<String, Object> body, String vspId, String version) throws IOException { - - Version ver = new Version(version); - logger.debug("attempt to retrieve archive for VSP {} version {}", vspId, ver.getId()); - - Optional<Pair<String, byte[]>> ozip = candidateManager.get(vspId, new Version(version)); - if (!ozip.isPresent()) { - ozip = vendorSoftwareProductManager.get(vspId, ver); - } - - if (!ozip.isPresent()) { - List<Version> versions = versioningManager.list(vspId); - String knownVersions = versions - .stream() - .map(v -> String.format("%d.%d: %s (%s)", v.getMajor(), v.getMinor(), v.getStatus(), v.getId())) - .collect(Collectors.joining("\n")); - - String detail = String.format("Unable to find archive for VSP ID %s and Version %s. Known versions are:\n%s", - vspId, version, knownVersions); - - throw new ExternalTestingException("Archive Processing Failed", 500, detail); - } - - // safe here to do get. - Pair<String, byte[]> zip = ozip.get(); - processArchive(requestItem, body, zip.getRight()); - } - - @EqualsAndHashCode(callSuper = false) - private class NamedByteArrayResource extends ByteArrayResource { - private String filename; - private NamedByteArrayResource(byte[] bytes, String filename) { - super(bytes, filename); - this.filename = filename; - } - @Override - public String getFilename() { - return this.filename; - } - - } - - @SuppressWarnings("WeakerAccess") - protected void processArchive(VtpTestExecutionRequest requestItem, MultiValueMap<String, Object> body, byte[] zip) { - try { - ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(zip)); - ZipEntry entry; - while ((entry = zipStream.getNextEntry()) != null) { - String entryName = entry.getName(); - logger.debug("csar contains entry {}", entryName); - Map<String,String> params = requestItem.getParameters(); - params.forEach((key,val) -> { - if (key.startsWith(CSAR_PREFIX)) { - addToBody(requestItem, body, zipStream, entryName, key); - } - }); - } - } catch (IOException ex) { - logger.error("IO Exception parsing zip", ex); - } - } - - private void addToBody(VtpTestExecutionRequest requestItem, MultiValueMap<String, Object> body, ZipInputStream zipStream, String entryName, String key) { - String filename = key.substring(CSAR_PREFIX.length()); - logger.debug("match {} with {}", entryName, filename); - if (StringUtils.equals(entryName, filename)) { - try { - NamedByteArrayResource res = new NamedByteArrayResource(IOUtils.toByteArray(zipStream), filename); - body.add("file", res); - - // we've added the file to the body. need to replace the value in the request for this - // parameter to match the VTP requirement that it start with a file URL protocol handler. - requestItem.getParameters().put(key, "file://" + entryName); - - } catch (IOException ex) { - logger.error("failed to read zip entry content for {}", entryName, ex); - } - } - } -} diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java index 38fb11c6ae..bea31c14c3 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java @@ -16,20 +16,32 @@ package org.openecomp.core.externaltesting.impl; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.amdocs.zusammen.utils.fileutils.json.JsonUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; +import lombok.EqualsAndHashCode; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.onap.sdc.tosca.services.YamlUtil; import org.openecomp.core.externaltesting.api.*; import org.openecomp.core.externaltesting.errors.ExternalTestingException; +import org.openecomp.sdc.heat.datatypes.manifest.FileData; +import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent; +import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager; +import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManagerFactory; +import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; +import org.openecomp.sdc.vendorsoftwareproduct.VspManagerFactory; +import org.openecomp.sdc.versioning.VersioningManager; +import org.openecomp.sdc.versioning.VersioningManagerFactory; +import org.openecomp.sdc.versioning.dao.types.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.io.ByteArrayResource; import org.springframework.http.*; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.util.LinkedMultiValueMap; @@ -38,18 +50,23 @@ import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; +import org.yaml.snakeyaml.Yaml; import javax.annotation.PostConstruct; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; public class ExternalTestingManagerImpl implements ExternalTestingManager { private Logger logger = LoggerFactory.getLogger(ExternalTestingManagerImpl.class); + private static final String FILE_URL_PREFIX = "file://"; + private static final String MANIFEST_JSON = "MANIFEST.json"; private static final String HTTP_STATUS = "httpStatus"; private static final String CODE = "code"; private static final String ERROR = "error"; @@ -57,9 +74,6 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { private static final String DETAIL = "detail"; private static final String PATH = "path"; - private static final String CONFIG_FILE_PROPERTY = "configuration.yaml"; - private static final String CONFIG_SECTION = "externalTestingConfig"; - private static final String VTP_SCENARIOS_URI = "%s/v1/vtp/scenarios"; private static final String VTP_TESTSUITE_URI = "%s/v1/vtp/scenarios/%s/testsuites"; private static final String VTP_TESTCASES_URI = "%s/v1/vtp/scenarios/%s/testcases"; @@ -67,43 +81,123 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { private static final String VTP_EXECUTIONS_URI = "%s/v1/vtp/executions"; private static final String VTP_EXECUTION_URI = "%s/v1/vtp/executions/%s"; - private static final String INVALIDATE_STATE_ERROR = "Invalid State"; + private static final String INVALIDATE_STATE_ERROR_CODE = "SDC-TEST-001"; private static final String NO_ACCESS_CONFIGURATION_DEFINED = "No access configuration defined"; + private static final String NO_SUCH_ENDPOINT_ERROR_CODE = "SDC-TEST-002"; + private static final String ENDPOINT_ERROR_CODE = "SDC-TEST-003"; + private static final String TESTING_HTTP_ERROR_CODE = "SDC-TEST-004"; + private static final String SDC_RESOLVER_ERR = "SDC-TEST-005"; + + private static final String TOSCA_META = "TOSCA-Metadata/TOSCA.meta"; + private static final String MAIN_SERVICE_TEMPLATE_YAML_FILE_NAME = "MainServiceTemplate.yaml"; + private static final String TOSCA_META_ENTRY_DEFINITIONS="Entry-Definitions"; + static final String VSP_ID = "vspId"; + static final String VSP_VERSION = "vspVersion"; + + private static final String SDC_CSAR = "sdc-csar"; + private static final String SDC_HEAT = "sdc-heat"; + + + private VersioningManager versioningManager; + private VendorSoftwareProductManager vendorSoftwareProductManager; + private OrchestrationTemplateCandidateManager candidateManager; + private TestingAccessConfig accessConfig; - private Map<String, RemoteTestingEndpointDefinition> endpoints = new HashMap<>(); + private List<RemoteTestingEndpointDefinition> endpoints; private RestTemplate restTemplate; - private List<VariableResolver> variableResolvers; - - public ExternalTestingManagerImpl(@Autowired(required=false) List<VariableResolver> variableResolvers) { - this.variableResolvers = variableResolvers; - // nothing to do at the moment. + public ExternalTestingManagerImpl() { restTemplate = new RestTemplate(); } + ExternalTestingManagerImpl(VersioningManager versioningManager, + VendorSoftwareProductManager vendorSoftwareProductManager, + OrchestrationTemplateCandidateManager candidateManager) { + this(); + this.versioningManager = versioningManager; + this.vendorSoftwareProductManager = vendorSoftwareProductManager; + this.candidateManager = candidateManager; + } + /** * Read the configuration from the yaml file for this bean. If we get an exception during load, * don't force an error starting SDC but log a warning. Do no warm... */ @PostConstruct - public void loadConfig() { + public void init() { - String file = Objects.requireNonNull(System.getProperty(CONFIG_FILE_PROPERTY), - "Config file location must be specified via system property " + CONFIG_FILE_PROPERTY); - try { - Object rawConfig = getExternalTestingAccessConfiguration(file); - if (rawConfig != null) { - accessConfig = new ObjectMapper().convertValue(rawConfig, TestingAccessConfig.class); - accessConfig.getEndpoints() - .stream() - .filter(RemoteTestingEndpointDefinition::isEnabled) - .forEach(e -> endpoints.put(e.getId(), e)); + if (versioningManager == null) { + versioningManager = VersioningManagerFactory.getInstance().createInterface(); + } + if (vendorSoftwareProductManager == null) { + vendorSoftwareProductManager = + VspManagerFactory.getInstance().createInterface(); + } + if (candidateManager == null) { + candidateManager = + OrchestrationTemplateCandidateManagerFactory.getInstance().createInterface(); + } + + loadConfig(); + } + + private Stream<RemoteTestingEndpointDefinition> mapEndpointString(String ep) { + RemoteTestingEndpointDefinition rv = new RemoteTestingEndpointDefinition(); + String[] cfg = ep.split(","); + if (cfg.length < 4) { + logger.error("invalid endpoint definition {}", ep); + return Stream.empty(); + } + else { + rv.setId(cfg[0]); + rv.setTitle(cfg[1]); + rv.setEnabled("true".equals(cfg[2])); + rv.setUrl(cfg[3]); + if (cfg.length > 4) { + rv.setScenarioFilter(cfg[4]); + } + if (cfg.length > 5) { + rv.setApiKey(cfg[5]); + } + return Stream.of(rv); + } + } + + /** + * Load the configuration for this component. When the SDC onboarding backend + * runs, it gets a system property called config.location. We can use that + * to locate the config-externaltesting.yaml file. + */ + private void loadConfig() { + String loc = System.getProperty("config.location"); + File file = new File(loc, "externaltesting-configuration.yaml"); + try (InputStream fileInput = new FileInputStream(file)) { + YamlUtil yamlUtil = new YamlUtil(); + accessConfig = yamlUtil.yamlToObject(fileInput, TestingAccessConfig.class); + + if (logger.isInfoEnabled()) { + String s = new ObjectMapper().writeValueAsString(accessConfig); + logger.info("loaded external testing config {}", s); + } + + endpoints = accessConfig.getEndpoints().stream() + .flatMap(this::mapEndpointString) + .collect(Collectors.toList()); + + if (logger.isInfoEnabled()) { + String s = new ObjectMapper().writeValueAsString(endpoints); + logger.info("processed external testing config {}", s); } } catch (IOException ex) { - logger.warn("Unable to initialize external testing configuration. Add '" + CONFIG_SECTION + "' to configuration.yaml with url value. Feature will be hobbled with results hardcoded to empty values.", ex); + logger.error("failed to read external testing config. Disabling the feature", ex); + accessConfig = new TestingAccessConfig(); + accessConfig.setEndpoints(new ArrayList<>()); + accessConfig.setClient(new ClientConfiguration()); + accessConfig.getClient().setEnabled(false); + endpoints = new ArrayList<>(); } } @@ -112,7 +206,7 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { * expose to the client. Treated as a JSON blob for flexibility. */ @Override - public String getConfig() { + public ClientConfiguration getConfig() { ClientConfiguration cc = null; if (accessConfig != null) { cc = accessConfig.getClient(); @@ -121,24 +215,47 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { cc = new ClientConfiguration(); cc.setEnabled(false); } - try { - return new ObjectMapper().writeValueAsString(cc); - } catch (JsonProcessingException e) { - logger.error("failed to write client config", e); - return "{\"enabled\":false}"; + return cc; + } + + /** + * To allow for functional testing, we let a caller invoke + * a setConfig request to enable/disable the client. This + * new value is not persisted. + * @return new client configuration + */ + @Override + public ClientConfiguration setConfig(ClientConfiguration cc) { + if (accessConfig == null) { + accessConfig = new TestingAccessConfig(); } + accessConfig.setClient(cc); + return getConfig(); } + /** + * To allow for functional testing, we let a caller invoke + * a setEndpoints request to configure where the BE makes request to. + * @return new endpoint definitions. + */ + @Override + public List<RemoteTestingEndpointDefinition> setEndpoints(List<RemoteTestingEndpointDefinition> endpoints) { + this.endpoints = endpoints; + return this.getEndpoints(); + } + + + @Override public TestTreeNode getTestCasesAsTree() { TestTreeNode root = new TestTreeNode("root", "root"); // quick out in case of non-configured SDC - if (accessConfig == null) { + if (endpoints == null) { return root; } - for (RemoteTestingEndpointDefinition ep : accessConfig.getEndpoints()) { + for (RemoteTestingEndpointDefinition ep : endpoints) { if (ep.isEnabled()) { buildTreeFromEndpoint(ep, root); } @@ -208,19 +325,6 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { if (testcase.getScenario() == null) { testcase.setScenario(scenario); } - - // if no inputs, return. - if (testcase.getInputs() == null) { - return; - } - - // to work around a VTP limitation, - // any inputs that are marked as internal should not be sent to the client. - testcase.setInputs(testcase.getInputs() - .stream() - .filter(input -> (input.getMetadata() == null) || - (!input.getMetadata().containsKey("internal")) || - !"true".equals(input.getMetadata().get("internal").toString())).collect(Collectors.toList())); } /** @@ -260,11 +364,10 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { * Get the list of endpoints defined to the testing manager. * @return list of endpoints or empty list if the manager is not configured. */ - public List<VtpNameDescriptionPair> getEndpoints() { - if (accessConfig != null) { - return accessConfig.getEndpoints().stream() + public List<RemoteTestingEndpointDefinition> getEndpoints() { + if (endpoints != null) { + return endpoints.stream() .filter(RemoteTestingEndpointDefinition::isEnabled) - .map(e -> new VtpNameDescriptionPair(e.getId(), e.getTitle())) .collect(Collectors.toList()); } else { @@ -273,10 +376,9 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { } /** - * Get the list of scenarios at a given endpoint. + * Code shared by getScenarios and getTestSuites. */ - public List<VtpNameDescriptionPair> getScenarios(final String endpoint) { - String url = buildEndpointUrl(VTP_SCENARIOS_URI, endpoint, ArrayUtils.EMPTY_STRING_ARRAY); + private List<VtpNameDescriptionPair> returnNameDescriptionPairFromUrl(String url) { ParameterizedTypeReference<List<VtpNameDescriptionPair>> t = new ParameterizedTypeReference<List<VtpNameDescriptionPair>>() {}; List<VtpNameDescriptionPair> rv = proxyGetRequestToExternalTestingSite(url, t); if (rv == null) { @@ -286,16 +388,19 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { } /** + * Get the list of scenarios at a given endpoint. + */ + public List<VtpNameDescriptionPair> getScenarios(final String endpoint) { + String url = buildEndpointUrl(VTP_SCENARIOS_URI, endpoint, ArrayUtils.EMPTY_STRING_ARRAY); + return returnNameDescriptionPairFromUrl(url); + } + + /** * Get the list of test suites for an endpoint for the given scenario. */ public List<VtpNameDescriptionPair> getTestSuites(final String endpoint, final String scenario) { String url = buildEndpointUrl(VTP_TESTSUITE_URI, endpoint, new String[] {scenario}); - ParameterizedTypeReference<List<VtpNameDescriptionPair>> t = new ParameterizedTypeReference<List<VtpNameDescriptionPair>>() {}; - List<VtpNameDescriptionPair> rv = proxyGetRequestToExternalTestingSite(url, t); - if (rv == null) { - rv = new ArrayList<>(); - } - return rv; + return returnNameDescriptionPairFromUrl(url); } /** @@ -343,14 +448,14 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { * @return list of execution responses. */ private List<VtpTestExecutionResponse> execute(final String endpointName, final List<VtpTestExecutionRequest> testsToRun, String requestId) { - if (accessConfig == null) { - throw new ExternalTestingException(INVALIDATE_STATE_ERROR, 500, NO_ACCESS_CONFIGURATION_DEFINED); + if (endpoints == null) { + throw new ExternalTestingException(INVALIDATE_STATE_ERROR_CODE, 500, NO_ACCESS_CONFIGURATION_DEFINED); } - RemoteTestingEndpointDefinition endpoint = accessConfig.getEndpoints().stream() + RemoteTestingEndpointDefinition endpoint = endpoints.stream() .filter(e -> StringUtils.equals(endpointName, e.getId())) .findFirst() - .orElseThrow(() -> new ExternalTestingException("No such endpoint", 500, "No endpoint named " + endpointName + " is defined")); + .orElseThrow(() -> new ExternalTestingException(NO_SUCH_ENDPOINT_ERROR_CODE, 400, "No endpoint named " + endpointName + " is defined")); // if the endpoint requires an API key, specify it in the headers. HttpHeaders headers = new HttpHeaders(); @@ -361,30 +466,29 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { // build the body. MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); + + for(VtpTestExecutionRequest test: testsToRun) { + if ((test.getParameters() != null) && + (test.getParameters().containsKey(SDC_CSAR) || test.getParameters().containsKey(SDC_HEAT))) { + attachArchiveContent(test, body); + } + } + try { // remove the endpoint from the test request since that is a FE/BE attribute - // add the execution profile configured for the endpoint. - testsToRun.forEach(t -> { - t.setEndpoint(null); - t.setProfile(t.getScenario()); // VTP wants a profile. Use the scenario name. - }); + testsToRun.forEach(t -> t.setEndpoint(null)); body.add("executions", new ObjectMapper().writeValueAsString(testsToRun)); } - catch (Exception ex) { + catch (IOException ex) { logger.error("exception converting tests to string", ex); VtpTestExecutionResponse err = new VtpTestExecutionResponse(); err.setHttpStatus(500); - err.setCode("500"); + err.setCode(TESTING_HTTP_ERROR_CODE); err.setMessage("Execution failed due to " + ex.getMessage()); return Collections.singletonList(err); } - for(VtpTestExecutionRequest test: testsToRun) { - runVariableResolvers(test, body); - } - - // form and send request. HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers); String url = buildEndpointUrl(VTP_EXECUTIONS_URI, endpointName, ArrayUtils.EMPTY_STRING_ARRAY); @@ -399,13 +503,14 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { catch (ExternalTestingException ex) { logger.error("exception caught invoking endpoint {}", endpointName, ex); VtpTestExecutionResponse err = new VtpTestExecutionResponse(); - err.setHttpStatus(ex.getCode()); - err.setCode(""+ex.getCode()); - err.setMessage(ex.getTitle() + ": " + ex.getDetail()); + err.setHttpStatus(ex.getHttpStatus()); + err.setCode(TESTING_HTTP_ERROR_CODE); + err.setMessage(ex.getMessageCode() + ": " + ex.getDetail()); return Collections.singletonList(err); } } + /** * Execute tests splitting them across endpoints and collecting the results. * @param testsToRun list of tests to be executed. @@ -413,8 +518,8 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { */ @Override public List<VtpTestExecutionResponse> execute(final List<VtpTestExecutionRequest> testsToRun, String requestId) { - if (accessConfig == null) { - throw new ExternalTestingException(INVALIDATE_STATE_ERROR, 500, NO_ACCESS_CONFIGURATION_DEFINED); + if (endpoints == null) { + throw new ExternalTestingException(INVALIDATE_STATE_ERROR_CODE, 500, NO_ACCESS_CONFIGURATION_DEFINED); } // partition the requests by endpoint. @@ -428,36 +533,6 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { } /** - * Load the external testing access configuration from the SDC onboarding yaml configuration file. - * @param file filename to retrieve data from - * @return parsed YAML object - * @throws IOException thrown if failure in reading YAML content. - */ - private Object getExternalTestingAccessConfiguration(String file) throws IOException { - Map<?, ?> configuration = Objects.requireNonNull(readConfigurationFile(file), "Configuration cannot be empty"); - Object testingConfig = configuration.get(CONFIG_SECTION); - if (testingConfig == null) { - logger.warn("Unable to initialize external testing access configuration. Add 'testingConfig' to configuration.yaml with url value. Feature will be hobbled with results hardcoded to empty values."); - } - - return testingConfig; - } - - /** - * Load the onboarding yaml config file. - * @param file name of file to load - * @return map containing YAML properties. - * @throws IOException thrown in the event of YAML parse or IO failure. - */ - private static Map<?, ?> readConfigurationFile(String file) throws IOException { - try (InputStream fileInput = new FileInputStream(file)) { - YamlUtil yamlUtil = new YamlUtil(); - return yamlUtil.yamlToMap(fileInput); - } - } - - - /** * Return URL with endpoint url as prefix. * @param format format string. * @param endpointName endpoint to address @@ -465,17 +540,17 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { * @return qualified url. */ private String buildEndpointUrl(String format, String endpointName, String[] args) { - if (accessConfig != null) { - RemoteTestingEndpointDefinition ep = endpoints.values().stream() - .filter(e -> e.getId().equals(endpointName)) + if (endpoints != null) { + RemoteTestingEndpointDefinition ep = endpoints.stream() + .filter(e -> e.isEnabled() && e.getId().equals(endpointName)) .findFirst() - .orElseThrow(() -> new ExternalTestingException("No such endpoint", 500, "No endpoint named " + endpointName + " is defined") + .orElseThrow(() -> new ExternalTestingException(NO_SUCH_ENDPOINT_ERROR_CODE, 500, "No endpoint named " + endpointName + " is defined") ); Object[] newArgs = ArrayUtils.add(args, 0, ep.getUrl()); return String.format(format, newArgs); } - throw new ExternalTestingException(INVALIDATE_STATE_ERROR, 500, NO_ACCESS_CONFIGURATION_DEFINED); + throw new ExternalTestingException(INVALIDATE_STATE_ERROR_CODE, 500, NO_ACCESS_CONFIGURATION_DEFINED); } /** @@ -532,18 +607,18 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { } catch (JsonParseException e) { logger.warn("unexpected JSON response", e); - throw new ExternalTestingException(ex.getStatusText(), ex.getStatusCode().value(), ex.getResponseBodyAsString(), ex); + throw new ExternalTestingException(ENDPOINT_ERROR_CODE, ex.getStatusCode().value(), ex.getResponseBodyAsString(), ex); } } else { - throw new ExternalTestingException(ex.getStatusText(), ex.getStatusCode().value(), ex.getResponseBodyAsString(), ex); + throw new ExternalTestingException(ENDPOINT_ERROR_CODE, ex.getStatusCode().value(), ex.getResponseBodyAsString(), ex); } } catch (ResourceAccessException ex) { - throw new ExternalTestingException("IO Error at Endpoint", 500, ex.getMessage(), ex); + throw new ExternalTestingException(ENDPOINT_ERROR_CODE, 500, ex.getMessage(), ex); } catch (Exception ex) { - throw new ExternalTestingException(ex.getMessage(), 500, "Generic Exception", ex); + throw new ExternalTestingException(ENDPOINT_ERROR_CODE, 500, "Generic Exception " + ex.getMessage(), ex); } if (re != null) { logger.debug("http status of {} from external testing entity {}", re.getStatusCodeValue(), url); @@ -596,15 +671,263 @@ public class ExternalTestingManagerImpl implements ExternalTestingManager { return new ExternalTestingException(code, statusCode, message); } + void attachArchiveContent(VtpTestExecutionRequest test, MultiValueMap<String, Object> body) { + Map<String, String> params = test.getParameters(); + String vspId = params.get(VSP_ID); + String version = params.get(VSP_VERSION); + + try { + extractMetadata(test, body, vspId, version); + } catch (IOException ex) { + logger.error("metadata extraction failed", ex); + } + } + /** - * Resolve variables in the request calling the built-in variable resolvers. - * @param item test execution request item to be resolved. + * Extract the metadata from the VSP CSAR file. + * + * @param requestItem item to add metadata to for processing + * @param vspId VSP identifier + * @param version VSP version */ - private void runVariableResolvers(final VtpTestExecutionRequest item, final MultiValueMap<String, Object> body) { - variableResolvers.forEach(vr -> { - if (vr.resolvesVariablesForRequest(item)) { - vr.resolve(item, body); + private void extractMetadata(VtpTestExecutionRequest requestItem, MultiValueMap<String, Object> body, String vspId, String version) throws IOException { + + Version ver = new Version(version); + logger.debug("attempt to retrieve archive for VSP {} version {}", vspId, ver.getId()); + + Optional<Pair<String, byte[]>> ozip = candidateManager.get(vspId, ver); + if (!ozip.isPresent()) { + ozip = vendorSoftwareProductManager.get(vspId, ver); + } + + if (!ozip.isPresent()) { + List<Version> versions = versioningManager.list(vspId); + String knownVersions = versions + .stream() + .map(v -> String.format("%d.%d: %s (%s)", v.getMajor(), v.getMinor(), v.getStatus(), v.getId())) + .collect(Collectors.joining("\n")); + + String detail = String.format("Archive processing failed. Unable to find archive for VSP ID %s and Version %s. Known versions are:\n%s", + vspId, version, knownVersions); + + throw new ExternalTestingException(SDC_RESOLVER_ERR, 500, detail); + } + + // safe here to do get. + Pair<String, byte[]> zip = ozip.get(); + processArchive(requestItem, body, zip.getRight()); + } + + private void processArchive(final VtpTestExecutionRequest test, final MultiValueMap<String, Object> body, final byte[] zip) { + + // We need to make one pass through the zip input stream. Pull out files that match our expectations into a temporary + // map that we can process over. These are not huge files so we shouldn't need to worry about memory. + + List<String> extensions = Arrays.asList(".yaml", ".meta", ".yml", ".json", ".env"); + final Map<String, byte[]> contentWeCareAbout = extractRelevantContent(zip, extensions); + + // VTP does not support concurrent executions of the same test with the same associated file name. + // It writes files to /tmp and if we were to send two requests with the same file, the results are unpredictable. + String key = UUID.randomUUID().toString(); + key = key.substring(0, key.indexOf('-')); + + // if there's a MANIFEST.json file, we're dealing with a heat archive. + // otherwise, we will treat it as a CSAR. + if (contentWeCareAbout.containsKey(MANIFEST_JSON)) { + byte[] data = processHeatArchive(contentWeCareAbout); + if (data != null) { + body.add("file", new NamedByteArrayResource(data, key + ".heat.zip")); + test.getParameters().put(SDC_HEAT, FILE_URL_PREFIX + key + ".heat.zip"); } - }); + } + else { + byte[] data = processCsarArchive(contentWeCareAbout); + if ((data != null) && (data.length != 0)) { + body.add("file", new NamedByteArrayResource(data, key + ".csar.zip")); + test.getParameters().put(SDC_CSAR, FILE_URL_PREFIX + key + ".csar.zip"); + } + } + } + + /** + * Process the archive as a heat archive. Load the MANIFEST.json file and pull out the referenced + * heat and environment files. + * @param content relevant content from the heat archive. + * @return byte array of client to send to endpoint. + */ + private byte[] processHeatArchive(Map<String,byte[]> content) { + byte[] manifestBytes = content.get(MANIFEST_JSON); + ManifestContent manifest = JsonUtil.json2Object(new String(manifestBytes), ManifestContent.class); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try(ZipOutputStream zipOutput = new ZipOutputStream(baos)) { + for(FileData item : manifest.getData()) { + processManifestItem(item, zipOutput, content); + } + + return baos.toByteArray(); + } catch (IOException ex) { + logger.error("IO Exception parsing zip", ex); + throw new ExternalTestingException(SDC_RESOLVER_ERR, 500, ex.getMessage()); + } } + + private void processManifestItem(FileData item, ZipOutputStream zipOutput, Map<String,byte[]> contentMap) throws IOException { + if ((item.getType() == FileData.Type.HEAT) || (item.getType() == FileData.Type.HEAT_ENV)) { + byte[] content = contentMap.get(item.getFile()); + if (content == null) { + logger.warn("manifest included {} but not in content extracted", item.getFile()); + } + else { + ZipEntry zi = new ZipEntry(item.getFile()); + zipOutput.putNextEntry(zi); + zipOutput.write(content); + zipOutput.closeEntry(); + } + + // recurse + if (item.getData() != null) { + for(FileData subitem: item.getData()) { + processManifestItem(subitem, zipOutput, contentMap); + } + } + } + } + + /** + * Process the archive as a CSAR file. + * @param content relevant extracted content. + * @return byte array of client to send to endpoint. + */ + private byte[] processCsarArchive(Map<String,byte[]> content) { + // look for the entry point file. + String fileToGet = null; + if (content.containsKey(TOSCA_META)) { + fileToGet = getEntryDefinitionPointer(content.get(TOSCA_META)).orElse(null); + } + if (fileToGet == null) { + // fall back to the SDC standard location. not required to be here though... + fileToGet = MAIN_SERVICE_TEMPLATE_YAML_FILE_NAME; + } + + if (!content.containsKey(fileToGet)) { + // user story says to let the call to the VTP go through without the attachment. + return ArrayUtils.EMPTY_BYTE_ARRAY; + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try(ZipOutputStream zipOutput = new ZipOutputStream(baos)) { + processCsarArchiveEntry(fileToGet, zipOutput, content); + return baos.toByteArray(); + } catch (IOException ex) { + logger.error("IO Exception parsing zip", ex); + throw new ExternalTestingException(SDC_RESOLVER_ERR, 500, ex.getMessage()); + } + } + + /** + * Add the named file (if it exists) from the contentMap into the output zip to send to VTP. + * If the file is a yaml file, peek inside and also add any imported files. + * @param filename name to apply to the zip entry being created + * @param zipOutput zip output stream to append new entry to + * @param contentMap map of content we are processing + * @throws IOException thrown in the event of processing errors. + */ + private void processCsarArchiveEntry(String filename, ZipOutputStream zipOutput, Map<String, byte[]> contentMap) throws IOException { + byte[] content = contentMap.get(filename); + if (content == null) { + // no such content, just return. + return; + } + + ZipEntry zi = new ZipEntry(filename); + zipOutput.putNextEntry(zi); + zipOutput.write(content); + zipOutput.closeEntry(); + + // if this is a yaml file, we should peek inside for includes. + if (filename.endsWith(".yaml") || filename.endsWith(".yml")) { + Yaml yaml = new Yaml(); + @SuppressWarnings("unchecked") + Map<String, Object> yamlContent = (Map<String, Object>) yaml.load(new ByteArrayInputStream(content)); + if (!yamlContent.containsKey("imports")) { + return; + } + + Object imports = yamlContent.get("imports"); + if (imports instanceof ArrayList) { + @SuppressWarnings("unchecked") ArrayList<String> lst = (ArrayList<String>) imports; + for (String imp : lst) { + File f = new File(filename); + File impFile = new File(f.getParent(), imp); + logger.debug("look for import {} with {}", imp, impFile.getPath()); + processCsarArchiveEntry(impFile.getPath(), zipOutput, contentMap); + } + } + else { + logger.warn("archive {} contains imports but it is not an array. Unexpected, this is.", filename); + } + } + } + + private Optional<String> getEntryDefinitionPointer(byte[] toscaMetadataFile) { + try { + Properties p = new Properties(); + p.load(new ByteArrayInputStream(toscaMetadataFile)); + return Optional.ofNullable(p.getProperty(TOSCA_META_ENTRY_DEFINITIONS)); + } + catch (IOException ex) { + logger.error("failed to process tosca metadata file {}", TOSCA_META, ex); + } + + return Optional.empty(); + } + + /** + * We don't want to send the entire CSAR file to VTP. Here we take a pass through the + * archive (heat/csar) file and pull out the files we care about. + * @param zip csar/heat zip to iterate over + * @return relevant content from the archive file as a map. + */ + private Map<String, byte[]> extractRelevantContent(final byte[] zip, final List<String> extensions) { + final Map<String, byte[]> rv = new HashMap<>(); // FYI, rv = return value. + try (ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(zip))) { + ZipEntry entry; + while ((entry = zipStream.getNextEntry()) != null) { + final String entryName = entry.getName(); + + // NOTE: leaving this debugging in for dublin... + logger.debug("archive contains entry {}", entryName); + + int idx = entryName.lastIndexOf('.'); + if ((idx >= 0) && (extensions.contains(entryName.substring(idx)))) { + byte[] content = IOUtils.toByteArray(zipStream); + rv.put(entryName, content); + } + } + } + catch (IOException ex) { + logger.error("error encountered processing archive", ex); + throw new ExternalTestingException(SDC_RESOLVER_ERR, 500, ex.getMessage()); + } + return rv; + } + + /** + * We need to name the byte array we add to the multipart request sent to the VTP. + */ + @EqualsAndHashCode(callSuper = false) + protected class NamedByteArrayResource extends ByteArrayResource { + private String filename; + NamedByteArrayResource(byte[] bytes, String filename) { + super(bytes, filename); + this.filename = filename; + } + @Override + public String getFilename() { + return this.filename; + } + } + + }
\ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/TestingAccessConfig.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/TestingAccessConfig.java index f9df5ac81d..b6bcb45516 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/TestingAccessConfig.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/TestingAccessConfig.java @@ -17,14 +17,15 @@ package org.openecomp.core.externaltesting.impl; import lombok.Data; +import org.openecomp.core.externaltesting.api.ClientConfiguration; import java.util.List; -@SuppressWarnings({"unused", "WeakerAccess"}) +@SuppressWarnings("WeakerAccess") @Data public class TestingAccessConfig { private ClientConfiguration client; - private List<RemoteTestingEndpointDefinition> endpoints; + private List<String> endpoints; } diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/VariableResolver.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/VariableResolver.java deleted file mode 100644 index 3079898bff..0000000000 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/VariableResolver.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright © 2019 iconectiv - * - * 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.core.externaltesting.impl; - -import org.openecomp.core.externaltesting.api.VtpTestExecutionRequest; -import org.springframework.util.MultiValueMap; - -public interface VariableResolver { - - boolean resolvesVariablesForRequest(VtpTestExecutionRequest requestItem); - - void resolve(VtpTestExecutionRequest requestItem, MultiValueMap<String, Object> body); -} diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/externaltesting-configuration.yaml b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/externaltesting-configuration.yaml new file mode 100644 index 0000000000..5910ab5b44 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/externaltesting-configuration.yaml @@ -0,0 +1,5 @@ +client: + enabled: true +endpoints: + - vtp,VTP,true,http://bogus.ec2-34-237-35-152.compute-1.amazonaws.com,c.*,FOO + - repository,Repository,true,http://bogus.ec2-34-237-35-152.compute-1.amazonaws.com,.*
\ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/heat.zip b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/heat.zip Binary files differnew file mode 100644 index 0000000000..ac63ba6fc8 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/heat.zip diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/managertestconfiguration.yaml b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/managertestconfiguration.yaml deleted file mode 100644 index d65becedf9..0000000000 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/managertestconfiguration.yaml +++ /dev/null @@ -1,13 +0,0 @@ -externalTestingConfig: - client: - enabled: true - endpoints: - - id: vtp - enabled: true - url: http://bogus.ec2-34-237-35-152.compute-1.amazonaws.com - apiKey: FOOBAR - scenarioFilter: c.* - - id: repository - url: http://bogus.ec2-34-237-35-152.compute-1.amazonaws.com - enabled: true - apiKey: FOOBAR diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/testconfiguration.yaml b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/testconfiguration.yaml deleted file mode 100644 index 1bf800b8f2..0000000000 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/data/testconfiguration.yaml +++ /dev/null @@ -1,11 +0,0 @@ - client: - enabled: true - endpoints: - - id: vtp - enabled: false - url: http://bogus.ec2-34-237-35-152.compute-1.amazonaws.com - apiKey: FOOBAR - - id: repository - url: http://bogus.ec2-34-237-35-152.compute-1.amazonaws.com - enabled: true - apiKey: FOOBAR diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ConfigurationTests.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ConfigurationTests.java index 6b530daa09..103320f755 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ConfigurationTests.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ConfigurationTests.java @@ -20,6 +20,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Assert; import org.junit.Test; import org.onap.sdc.tosca.services.YamlUtil; +import org.openecomp.core.externaltesting.api.ClientConfiguration; +import org.openecomp.core.externaltesting.api.RemoteTestingEndpointDefinition; import java.io.File; import java.io.FileInputStream; @@ -40,7 +42,7 @@ public class ConfigurationTests { @Test public void testConfig() throws Exception { - try (InputStream fileInput = new FileInputStream(new File("src/test/data/testconfiguration.yaml"))) { + try (InputStream fileInput = new FileInputStream(new File("src/test/data/config-externaltesting.yaml"))) { YamlUtil yamlUtil = new YamlUtil(); Object raw = yamlUtil.yamlToMap(fileInput); TestingAccessConfig accessConfig = new ObjectMapper().convertValue(raw, TestingAccessConfig.class); diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/CsarMetadataVariableResolverTest.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/CsarMetadataVariableResolverTest.java deleted file mode 100644 index b8471eb77b..0000000000 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/CsarMetadataVariableResolverTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright © 2019 iconectiv - * - * 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.core.externaltesting.impl; - -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.openecomp.core.externaltesting.api.VtpTestExecutionRequest; -import org.openecomp.core.externaltesting.errors.ExternalTestingException; -import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager; -import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; -import org.openecomp.sdc.versioning.VersioningManager; -import org.springframework.core.io.ByteArrayResource; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; - -import java.io.FileInputStream; -import java.util.*; - -public class CsarMetadataVariableResolverTest { - - @Mock - private VersioningManager versioningManager; - - @Mock - private VendorSoftwareProductManager vendorSoftwareProductManager; - - @Mock - private OrchestrationTemplateCandidateManager candidateManager; - - @Test - public void testResolverResolves() throws Exception { - MockitoAnnotations.initMocks(this); - CsarMetadataVariableResolver resolver = new CsarMetadataVariableResolver(versioningManager, - vendorSoftwareProductManager, candidateManager); - resolver.init(); - - VtpTestExecutionRequest doesNotResolve = new VtpTestExecutionRequest(); - Assert.assertFalse("should not resolve empty request", resolver.resolvesVariablesForRequest(doesNotResolve)); - - doesNotResolve.setParameters(new HashMap<>()); - Assert.assertFalse("should not resolve empty parameters", resolver.resolvesVariablesForRequest(doesNotResolve)); - - - - VtpTestExecutionRequest resolves = new VtpTestExecutionRequest(); - resolves.setParameters(new HashMap<>()); - resolves.getParameters().put(CsarMetadataVariableResolver.VSP_VERSION, "1.0"); - resolves.getParameters().put(CsarMetadataVariableResolver.VSP_ID, "vspid"); - resolves.getParameters().put(CsarMetadataVariableResolver.CSAR_PREFIX + "MainServiceTemplate.yaml", ""); - Assert.assertTrue("should resolve", resolver.resolvesVariablesForRequest(resolves)); - - MultiValueMap<String,Object> fakeRequestBody = new LinkedMultiValueMap<>(); - - try { - resolver.resolve(resolves, fakeRequestBody); - } - catch (ExternalTestingException e) { - // exception expected. - } - - // test the metadata extraction on a know CSAR zip. - byte[] zip = IOUtils.toByteArray(new FileInputStream("src/test/data/csar.zip")); - resolver.processArchive(resolves, fakeRequestBody, zip); - Assert.assertTrue("body contains file", fakeRequestBody.containsKey("file")); - LinkedList ll = (LinkedList)fakeRequestBody.get("file"); - Assert.assertEquals("body contains one file", 1, ll.size()); - ByteArrayResource res = (ByteArrayResource)ll.get(0); - Assert.assertEquals("file should have matching name", "MainServiceTemplate.yaml", res.getFilename()); - - } -} diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTests.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTests.java index be328ea73f..2233f85ccf 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTests.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTests.java @@ -19,25 +19,30 @@ package org.openecomp.core.externaltesting.impl; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.tuple.Pair; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentMatchers; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; +import org.mockito.*; import org.mockito.junit.MockitoJUnitRunner; import org.openecomp.core.externaltesting.api.*; import org.openecomp.core.externaltesting.errors.ExternalTestingException; +import org.openecomp.sdc.vendorsoftwareproduct.OrchestrationTemplateCandidateManager; +import org.openecomp.sdc.vendorsoftwareproduct.VendorSoftwareProductManager; +import org.openecomp.sdc.versioning.VersioningManager; +import org.openecomp.sdc.versioning.dao.types.Version; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; -import org.springframework.util.MultiValueMap; +import org.springframework.util.LinkedMultiValueMap; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; import java.nio.charset.Charset; import java.util.*; @@ -48,36 +53,25 @@ public class ExternalTestingManagerImplTests { @Mock private RestTemplate restTemplate; - static { - System.setProperty("configuration.yaml", "src/test/data/testconfiguration.yaml"); - } - - class JUnitExternalTestingManagerImpl extends ExternalTestingManagerImpl { - JUnitExternalTestingManagerImpl() { - super(Collections.singletonList( - new VariableResolver() { - - @Override - public boolean resolvesVariablesForRequest(VtpTestExecutionRequest requestItem) { - return false; - } + @Mock + private VersioningManager versioningManager; - @Override - public void resolve(VtpTestExecutionRequest requestItem, MultiValueMap<String, Object> body) { + @Mock + private VendorSoftwareProductManager vendorSoftwareProductManager; - // unit test resolver does nothing for this case. See specific test for resolver. - } - })); - } - } + @Mock + private OrchestrationTemplateCandidateManager candidateManager; @InjectMocks - private ExternalTestingManager mgr = new JUnitExternalTestingManagerImpl(); + private ExternalTestingManagerImpl mgr = new ExternalTestingManagerImpl(); @SuppressWarnings("unchecked") - private ExternalTestingManager configTestManager(boolean loadConfig) throws IOException { + private ExternalTestingManagerImpl configTestManager(boolean loadConfig) throws IOException { + + MockitoAnnotations.initMocks(this); + if (loadConfig) { - ((ExternalTestingManagerImpl) mgr).loadConfig(); + mgr.init(); } ObjectMapper mapper = new ObjectMapper(); @@ -112,7 +106,55 @@ public class ExternalTestingManagerImplTests { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType("application/problem+json")); - HttpStatusCodeException missingException = new HttpServerErrorException(HttpStatus.NOT_FOUND, "Not Found", headers, notFound.getBytes(), Charset.defaultCharset()); + + byte[] csar = IOUtils.toByteArray(new FileInputStream("src/test/data/csar.zip")); + byte[] heat = IOUtils.toByteArray(new FileInputStream("src/test/data/heat.zip")); + + List<Version> versionList = new ArrayList<>(); + versionList.add(new Version(UUID.randomUUID().toString())); + + Mockito + .when(candidateManager.get( + ArgumentMatchers.contains("csar"), + ArgumentMatchers.any())) + .thenReturn(Optional.of(Pair.of("Processed.zip", csar))); + + Mockito + .when(candidateManager.get( + ArgumentMatchers.contains("heat"), + ArgumentMatchers.any())) + .thenReturn(Optional.empty()); + + Mockito + .when(vendorSoftwareProductManager.get( + ArgumentMatchers.contains("heat"), + ArgumentMatchers.any())) + .thenReturn(Optional.of(Pair.of("Processed.zip", heat))); + + + + Mockito + .when(vendorSoftwareProductManager.get( + ArgumentMatchers.contains("missing"), + ArgumentMatchers.any())) + .thenReturn(Optional.empty()); + + Mockito + .when(candidateManager.get( + ArgumentMatchers.contains("missing"), + ArgumentMatchers.any())) + .thenReturn(Optional.empty()); + + + Mockito + .when(versioningManager.list( + ArgumentMatchers.contains("missing"))) + .thenReturn(versionList); + + + + + Mockito .when(restTemplate.exchange( @@ -124,10 +166,10 @@ public class ExternalTestingManagerImplTests { Mockito .when(restTemplate.exchange( - ArgumentMatchers.endsWith("/testsuites"), - ArgumentMatchers.eq(HttpMethod.GET), - ArgumentMatchers.any(), - ArgumentMatchers.eq(listOfPairType))) + ArgumentMatchers.endsWith("/testsuites"), + ArgumentMatchers.eq(HttpMethod.GET), + ArgumentMatchers.any(), + ArgumentMatchers.eq(listOfPairType))) .thenReturn(new ResponseEntity(testSuites, HttpStatus.OK)); Mockito @@ -166,6 +208,8 @@ public class ExternalTestingManagerImplTests { ArgumentMatchers.eq(new ParameterizedTypeReference<VtpTestExecutionResponse>() {}))) .thenReturn(new ResponseEntity(priorExecution, HttpStatus.OK)); + + HttpStatusCodeException missingException = new HttpServerErrorException(HttpStatus.NOT_FOUND, "Not Found", headers, notFound.getBytes(), Charset.defaultCharset()); Mockito .when(restTemplate.exchange( ArgumentMatchers.endsWith("/missing"), @@ -174,6 +218,7 @@ public class ExternalTestingManagerImplTests { ArgumentMatchers.eq(caseType))) .thenThrow(missingException); + Mockito .when(restTemplate.exchange( ArgumentMatchers.endsWith("/sitedown"), @@ -182,18 +227,31 @@ public class ExternalTestingManagerImplTests { ArgumentMatchers.eq(caseType))) .thenThrow(new ResourceAccessException("Remote site is down")); + Mockito + .when(restTemplate.exchange( + ArgumentMatchers.endsWith("throwexception"), + ArgumentMatchers.eq(HttpMethod.POST), + ArgumentMatchers.any(), + ArgumentMatchers.eq(new ParameterizedTypeReference<List<VtpTestExecutionResponse>>() {}))) + .thenThrow(missingException); + + return mgr; } + @Before + public void setConfigLocation() { + System.setProperty("config.location", "src/test/data"); + } + @Test public void testManager() throws IOException { - System.setProperty("configuration.yaml", "src/test/data/managertestconfiguration.yaml"); ExternalTestingManager m = configTestManager(true); - String config = m.getConfig(); + ClientConfiguration config = m.getConfig(); Assert.assertNotNull(config); - List<VtpNameDescriptionPair> endpoints = m.getEndpoints(); + List<RemoteTestingEndpointDefinition> endpoints = m.getEndpoints(); Assert.assertEquals("two endpoints", 2, endpoints.size()); @@ -210,8 +268,8 @@ public class ExternalTestingManagerImplTests { catch (ExternalTestingException e) { // expecting this exception. Assert.assertNotNull(e.getDetail()); - Assert.assertNotEquals(0, e.getCode()); - Assert.assertNotNull(e.getTitle()); + Assert.assertNotEquals(0, e.getHttpStatus()); + Assert.assertNotNull(e.getMessageCode()); } // get a particular test case @@ -222,10 +280,14 @@ public class ExternalTestingManagerImplTests { catch (ExternalTestingException e) { // expecting this exception. Assert.assertNotNull(e.getDetail()); - Assert.assertNotEquals(0, e.getCode()); - Assert.assertNotNull(e.getTitle()); + Assert.assertNotEquals(0, e.getHttpStatus()); + Assert.assertNotNull(e.getMessageCode()); } + } + @Test + public void testManagerExecution() throws IOException { + ExternalTestingManager m = configTestManager(true); // execute a test. List<VtpTestExecutionRequest> requests = new ArrayList<>(); @@ -234,8 +296,8 @@ public class ExternalTestingManagerImplTests { requests.add(req); // send a request with the endpoint defined. - List<VtpTestExecutionResponse> responses = m.execute( requests, "rid"); - Assert.assertEquals(1,responses.size()); + List<VtpTestExecutionResponse> responses = m.execute(requests, "rid"); + Assert.assertEquals(1, responses.size()); // send a request for a prior execution. VtpTestExecutionResponse execRsp = m.getExecution("repository", "execId"); @@ -243,26 +305,67 @@ public class ExternalTestingManagerImplTests { } @Test + public void testMissingConfig() throws IOException { + // directory exists but no config file should be found here. + System.setProperty("config.location", "src/test"); + ExternalTestingManager m = configTestManager(true); + Assert.assertFalse("missing config client enabled false", m.getConfig().isEnabled()); + Assert.assertEquals("missing config no endpoints", 0, m.getEndpoints().size()); + } + + @Test + public void testMissingEndpoint() throws IOException { + ExternalTestingManager m = configTestManager(true); + + // execute a test. + List<VtpTestExecutionRequest> requests = new ArrayList<>(); + VtpTestExecutionRequest req = new VtpTestExecutionRequest(); + req.setEndpoint("repository"); + requests.add(req); + + // send a request with the endpoint defined. + try { + m.execute(requests, "throwexception"); + } + catch (ExternalTestingException e) { + // expected. + } + } + + + @Test + public void testManagerConfigOverrides() throws IOException { + ExternalTestingManager m = configTestManager(false); + + ClientConfiguration cc = new ClientConfiguration(); + cc.setEnabled(true); + m.setConfig(cc); + Assert.assertTrue(m.getConfig().isEnabled()); + + List<RemoteTestingEndpointDefinition> lst = new ArrayList<>(); + lst.add(new RemoteTestingEndpointDefinition()); + lst.get(0).setEnabled(true); + m.setEndpoints(lst); + Assert.assertEquals(1,m.getEndpoints().size()); + } + + @Test public void testManagerErrorCases() throws IOException { ExternalTestingManager m = configTestManager(false); - Map<String,Object> expectedEmptyConfig = new HashMap<>(); - expectedEmptyConfig.put("enabled", false); - String expected = new ObjectMapper().writeValueAsString(expectedEmptyConfig); - String emptyConfig = m.getConfig(); - Assert.assertEquals(expected, emptyConfig); - - try { - m.getEndpoints(); - Assert.assertTrue("should have exception here", true); - } - catch (ExternalTestingException e) { - // eat the exception cause this is what should happen. - } + ClientConfiguration emptyConfig = m.getConfig(); + Assert.assertFalse("empty configuration should have client enabled of false", emptyConfig.isEnabled()); + + try { + m.getEndpoints(); + Assert.assertTrue("should have exception here", true); } + catch (ExternalTestingException e) { + // eat the exception cause this is what should happen. + } + } @Test public void testExecutionDistribution() throws IOException { - System.setProperty("configuration.yaml", "src/test/data/managertestconfiguration.yaml"); ExternalTestingManager m = configTestManager(true); VtpTestExecutionRequest r1 = new VtpTestExecutionRequest(); @@ -280,4 +383,40 @@ public class ExternalTestingManagerImplTests { List<VtpTestExecutionResponse> results = m.execute(Arrays.asList(r1,r2,r3), "rid"); Assert.assertEquals("three in two out merged", 2, results.size()); } + + @Test + public void testArchiveProcessing() throws IOException { + ExternalTestingManagerImpl m = configTestManager(true); + VtpTestExecutionRequest r1 = new VtpTestExecutionRequest(); + r1.setScenario("scenario1"); + r1.setEndpoint("vtp"); + r1.setParameters(new HashMap<>()); + r1.getParameters().put(ExternalTestingManagerImpl.VSP_ID, "something.with.csar.content"); + r1.getParameters().put(ExternalTestingManagerImpl.VSP_VERSION, UUID.randomUUID().toString()); + + LinkedMultiValueMap<String,Object> body = new LinkedMultiValueMap<>(); + m.attachArchiveContent(r1, body); + + r1.setParameters(new HashMap<>()); + r1.getParameters().put(ExternalTestingManagerImpl.VSP_ID, "something.with.heat.content"); + r1.getParameters().put(ExternalTestingManagerImpl.VSP_VERSION, UUID.randomUUID().toString()); + + LinkedMultiValueMap<String,Object> body2 = new LinkedMultiValueMap<>(); + m.attachArchiveContent(r1, body2); + + // now, let's handle a missing archive. + r1.setParameters(new HashMap<>()); + r1.getParameters().put(ExternalTestingManagerImpl.VSP_ID, "something.with.missing.content"); + r1.getParameters().put(ExternalTestingManagerImpl.VSP_VERSION, UUID.randomUUID().toString()); + + LinkedMultiValueMap<String,Object> body3 = new LinkedMultiValueMap<>(); + try { + m.attachArchiveContent(r1, body3); + Assert.fail("expected to receive an exception here"); + } + catch (ExternalTestingException ex) { + Assert.assertEquals(500, ex.getHttpStatus()); + } + + } } diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingTestSuite.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingTestSuite.java index 31346a135e..d9e4612774 100644 --- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingTestSuite.java +++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingTestSuite.java @@ -21,7 +21,6 @@ import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ - CsarMetadataVariableResolverTest.class, ExternalTestingManagerImplTests.class, ConfigurationTests.class }) |