From 1433a67a9e3dcad20d0dda8edcaad9403320f4f9 Mon Sep 17 00:00:00 2001 From: Edwin Lawrance Date: Fri, 22 Sep 2017 16:55:07 +0100 Subject: [PATCH] Initial code submit for Babel Change-Id: I3738ebe15eadbbd6d16e24e374c6e40c535b425d Issue-ID: AAI-46 Signed-off-by: Edwin Lawrance --- License.txt | 20 + ajsc-shared-config/README.txt | 8 + ajsc-shared-config/etc/aft.properties | 15 + .../etc/basic-logback_root_logger_level_off.xml | 87 ++++ ajsc-shared-config/etc/logback.xml | 212 ++++++++++ ajsc-shared-config/etc/spm2.jks | Bin 0 -> 62008 bytes antBuild/build.xml | 231 +++++++++++ appconfig-local/readme.txt | 1 + bundleconfig-local/README.txt | 2 + bundleconfig-local/RELEASE_NOTES.txt | 2 + .../etc/appprops/AAFUserRoles.properties | 13 + .../appprops/PostProcessorInterceptors.properties | 3 + .../appprops/PreProcessorInterceptors.properties | 4 + .../etc/appprops/app-intercepts.properties | 8 + .../etc/appprops/methodMapper.properties | 46 +++ .../etc/sysprops/sys-props.properties | 115 ++++++ pom.xml | 453 +++++++++++++++++++++ .../ajsc/babel_v1/babel/v1/conf/babel-beans.xml | 35 ++ src/main/ajsc/babel_v1/babel/v1/docs/README.txt | 1 + src/main/ajsc/babel_v1/babel/v1/lib/README.txt | 1 + src/main/ajsc/babel_v1/babel/v1/props/module.props | 1 + .../babel_v1/babel/v1/routes/babel-service.route | 4 + src/main/assemble/ajsc_module_assembly.xml | 69 ++++ src/main/assemble/ajsc_props_assembly.xml | 26 ++ src/main/assemble/ajsc_runtime_assembly.xml | 47 +++ src/main/bin/start.sh | 50 +++ src/main/config/ajsc-chef.jks | Bin 0 -> 5256 bytes src/main/config/ajsc-jetty.xml | 128 ++++++ src/main/config/ajsc-override-web.xml | 53 +++ src/main/config/ajscJetty.jks | Bin 0 -> 3736 bytes src/main/config/cadi.properties | 36 ++ src/main/config/jul-redirect.properties | 13 + src/main/config/keyfile | 27 ++ src/main/config/runner-web.xml | 97 +++++ src/main/docker/Dockerfile | 24 ++ .../java/org/onap/aai/auth/AAIAuthException.java | 39 ++ .../org/onap/aai/auth/AAIMicroServiceAuth.java | 121 ++++++ .../org/onap/aai/auth/AAIMicroServiceAuthCore.java | 287 +++++++++++++ src/main/java/org/onap/aai/auth/FileWatcher.java | 63 +++ .../org/onap/aai/babel/config/BabelAuthConfig.java | 51 +++ .../aai/babel/csar/CsarConverterException.java | 40 ++ .../onap/aai/babel/csar/CsarToXmlConverter.java | 88 ++++ .../csar/extractor/InvalidArchiveException.java | 50 +++ .../aai/babel/csar/extractor/YamlExtractor.java | 149 +++++++ .../onap/aai/babel/logging/ApplicationMsgs.java | 50 +++ .../babel/service/GenerateArtifactsService.java | 51 +++ .../service/GenerateArtifactsServiceImpl.java | 148 +++++++ .../onap/aai/babel/service/data/BabelArtifact.java | 63 +++ .../onap/aai/babel/service/data/BabelRequest.java | 53 +++ .../aai/babel/util/RequestValidationException.java | 42 ++ .../org/onap/aai/babel/util/RequestValidator.java | 50 +++ .../aai/babel/xml/generator/ArtifactGenerator.java | 39 ++ .../aai/babel/xml/generator/ModelGenerator.java | 136 +++++++ .../generator/XmlArtifactGenerationException.java | 40 ++ .../resources/babel-logging-resources.properties | 59 +++ ...ame__#__module.ajsc.namespace.version__.context | 1 + src/main/runtime/context/default#0.context | 1 + ...e.name__#__module.ajsc.namespace.version__.json | 1 + src/main/runtime/shiroRole/ajscadmin.json | 1 + ...ontextadmin#__module.ajsc.namespace.name__.json | 1 + .../runtime/shiroRole/contextadmin#default.json | 1 + src/main/runtime/shiroUser/ajsc.json | 1 + src/main/runtime/shiroUserRole/ajsc#ajscadmin.json | 1 + ...ontextadmin#__module.ajsc.namespace.name__.json | 1 + .../shiroUserRole/ajsc#contextadmin#default.json | 1 + .../org/onap/aai/babel/MicroServiceAuthTest.java | 211 ++++++++++ .../babel/csar/extractor/YamlExtractorTest.java | 141 +++++++ .../babel/csar/fixture/ArtifactInfoBuilder.java | 78 ++++ .../babel/csar/fixture/TestArtifactInfoImpl.java | 135 ++++++ .../aai/babel/service/CsarToXmlConverterTest.java | 170 ++++++++ .../service/TestGenerateArtifactsServiceImpl.java | 111 +++++ .../org/onap/aai/babel/util/ArtifactTestUtils.java | 100 +++++ .../onap/aai/babel/util/TestRequestValidator.java | 72 ++++ src/test/resources/artifact-generator.properties | 264 ++++++++++++ src/test/resources/auth/auth_policy.json | 55 +++ .../compressedArtifacts/noYmlFilesArchive.zip | Bin 0 -> 762 bytes .../service-SdWanServiceTest-csar.csar | Bin 0 -> 16003 bytes .../AAI-SD-WAN-Service-Test-service-1.0.xml | 69 ++++ .../AAI-SD-WAN-Test-VSP-resource-1.0.xml | 51 +++ ...AI-SdWanTestVsp..DUMMY..module-0-resource-2.xml | 123 ++++++ .../AAI-Tunnel_XConnTest-resource-2.0.xml | 69 ++++ .../resources/jsonFiles/invalid_csar_request.json | 3 + .../resources/jsonFiles/invalid_json_request.json | 3 + .../jsonFiles/missing_artifact_name_request.json | 3 + .../missing_artifact_version_request.json | 2 + .../resources/jsonFiles/missing_csar_request.json | 2 + src/test/resources/jsonFiles/success_request.json | 3 + src/test/resources/response/response.json | 1 + .../ymlFiles/resource-SdWanTestVsp-template.yml | 314 ++++++++++++++ .../ymlFiles/resource-TunnelXconntest-template.yml | 81 ++++ .../ymlFiles/service-SdWanServiceTest-template.yml | 270 ++++++++++++ 91 files changed, 5792 insertions(+) create mode 100644 License.txt create mode 100644 ajsc-shared-config/README.txt create mode 100644 ajsc-shared-config/etc/aft.properties create mode 100644 ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml create mode 100644 ajsc-shared-config/etc/logback.xml create mode 100644 ajsc-shared-config/etc/spm2.jks create mode 100644 antBuild/build.xml create mode 100644 appconfig-local/readme.txt create mode 100644 bundleconfig-local/README.txt create mode 100644 bundleconfig-local/RELEASE_NOTES.txt create mode 100644 bundleconfig-local/etc/appprops/AAFUserRoles.properties create mode 100644 bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties create mode 100644 bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties create mode 100644 bundleconfig-local/etc/appprops/app-intercepts.properties create mode 100644 bundleconfig-local/etc/appprops/methodMapper.properties create mode 100644 bundleconfig-local/etc/sysprops/sys-props.properties create mode 100644 pom.xml create mode 100644 src/main/ajsc/babel_v1/babel/v1/conf/babel-beans.xml create mode 100644 src/main/ajsc/babel_v1/babel/v1/docs/README.txt create mode 100644 src/main/ajsc/babel_v1/babel/v1/lib/README.txt create mode 100644 src/main/ajsc/babel_v1/babel/v1/props/module.props create mode 100644 src/main/ajsc/babel_v1/babel/v1/routes/babel-service.route create mode 100644 src/main/assemble/ajsc_module_assembly.xml create mode 100644 src/main/assemble/ajsc_props_assembly.xml create mode 100644 src/main/assemble/ajsc_runtime_assembly.xml create mode 100644 src/main/bin/start.sh create mode 100644 src/main/config/ajsc-chef.jks create mode 100644 src/main/config/ajsc-jetty.xml create mode 100644 src/main/config/ajsc-override-web.xml create mode 100644 src/main/config/ajscJetty.jks create mode 100644 src/main/config/cadi.properties create mode 100644 src/main/config/jul-redirect.properties create mode 100644 src/main/config/keyfile create mode 100644 src/main/config/runner-web.xml create mode 100644 src/main/docker/Dockerfile create mode 100644 src/main/java/org/onap/aai/auth/AAIAuthException.java create mode 100644 src/main/java/org/onap/aai/auth/AAIMicroServiceAuth.java create mode 100644 src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java create mode 100644 src/main/java/org/onap/aai/auth/FileWatcher.java create mode 100644 src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java create mode 100644 src/main/java/org/onap/aai/babel/csar/CsarConverterException.java create mode 100644 src/main/java/org/onap/aai/babel/csar/CsarToXmlConverter.java create mode 100644 src/main/java/org/onap/aai/babel/csar/extractor/InvalidArchiveException.java create mode 100644 src/main/java/org/onap/aai/babel/csar/extractor/YamlExtractor.java create mode 100644 src/main/java/org/onap/aai/babel/logging/ApplicationMsgs.java create mode 100644 src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java create mode 100644 src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java create mode 100644 src/main/java/org/onap/aai/babel/service/data/BabelArtifact.java create mode 100644 src/main/java/org/onap/aai/babel/service/data/BabelRequest.java create mode 100644 src/main/java/org/onap/aai/babel/util/RequestValidationException.java create mode 100644 src/main/java/org/onap/aai/babel/util/RequestValidator.java create mode 100644 src/main/java/org/onap/aai/babel/xml/generator/ArtifactGenerator.java create mode 100644 src/main/java/org/onap/aai/babel/xml/generator/ModelGenerator.java create mode 100644 src/main/java/org/onap/aai/babel/xml/generator/XmlArtifactGenerationException.java create mode 100644 src/main/resources/babel-logging-resources.properties create mode 100644 src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context create mode 100644 src/main/runtime/context/default#0.context create mode 100644 src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json create mode 100644 src/main/runtime/shiroRole/ajscadmin.json create mode 100644 src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json create mode 100644 src/main/runtime/shiroRole/contextadmin#default.json create mode 100644 src/main/runtime/shiroUser/ajsc.json create mode 100644 src/main/runtime/shiroUserRole/ajsc#ajscadmin.json create mode 100644 src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json create mode 100644 src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json create mode 100644 src/test/java/org/onap/aai/babel/MicroServiceAuthTest.java create mode 100644 src/test/java/org/onap/aai/babel/csar/extractor/YamlExtractorTest.java create mode 100644 src/test/java/org/onap/aai/babel/csar/fixture/ArtifactInfoBuilder.java create mode 100644 src/test/java/org/onap/aai/babel/csar/fixture/TestArtifactInfoImpl.java create mode 100644 src/test/java/org/onap/aai/babel/service/CsarToXmlConverterTest.java create mode 100644 src/test/java/org/onap/aai/babel/service/TestGenerateArtifactsServiceImpl.java create mode 100644 src/test/java/org/onap/aai/babel/util/ArtifactTestUtils.java create mode 100644 src/test/java/org/onap/aai/babel/util/TestRequestValidator.java create mode 100644 src/test/resources/artifact-generator.properties create mode 100644 src/test/resources/auth/auth_policy.json create mode 100644 src/test/resources/compressedArtifacts/noYmlFilesArchive.zip create mode 100644 src/test/resources/compressedArtifacts/service-SdWanServiceTest-csar.csar create mode 100644 src/test/resources/generatedXml/AAI-SD-WAN-Service-Test-service-1.0.xml create mode 100644 src/test/resources/generatedXml/AAI-SD-WAN-Test-VSP-resource-1.0.xml create mode 100644 src/test/resources/generatedXml/AAI-SdWanTestVsp..DUMMY..module-0-resource-2.xml create mode 100644 src/test/resources/generatedXml/AAI-Tunnel_XConnTest-resource-2.0.xml create mode 100644 src/test/resources/jsonFiles/invalid_csar_request.json create mode 100644 src/test/resources/jsonFiles/invalid_json_request.json create mode 100644 src/test/resources/jsonFiles/missing_artifact_name_request.json create mode 100644 src/test/resources/jsonFiles/missing_artifact_version_request.json create mode 100644 src/test/resources/jsonFiles/missing_csar_request.json create mode 100644 src/test/resources/jsonFiles/success_request.json create mode 100644 src/test/resources/response/response.json create mode 100644 src/test/resources/ymlFiles/resource-SdWanTestVsp-template.yml create mode 100644 src/test/resources/ymlFiles/resource-TunnelXconntest-template.yml create mode 100644 src/test/resources/ymlFiles/service-SdWanServiceTest-template.yml diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..3452576 --- /dev/null +++ b/License.txt @@ -0,0 +1,20 @@ +============LICENSE_START======================================================= +org.onap.aai +================================================================================ +Copyright © 2017 AT&T Intellectual Property. All rights reserved. +Copyright © 2017 European Software Marketing Ltd. +================================================================================ +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. +============LICENSE_END========================================================= + +ECOMP is a trademark and service mark of AT&T Intellectual Property. \ No newline at end of file diff --git a/ajsc-shared-config/README.txt b/ajsc-shared-config/README.txt new file mode 100644 index 0000000..e0f7ff1 --- /dev/null +++ b/ajsc-shared-config/README.txt @@ -0,0 +1,8 @@ +#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + +The ajsc-shared-config folder is included in the service project to provide the functionality of the AJSC_SHARED_CONFIG +location that will exist in CSI envs. This includes the logback.xml for logging configurations, and some csm related +artifacts necessary for proper functionality of the csm framework within the CSI env. Within the 2 profiles that can +be utilized to run the AJSC locally, "runLocal" and "runAjsc", the system propery, "AJSC_SHARED_CONFIG", has been set +to point to this directory. The files in this folder will NOT be copied/moved anywhere within the AJSC SWM package. These +files will already be in existence within the CSI env. \ No newline at end of file diff --git a/ajsc-shared-config/etc/aft.properties b/ajsc-shared-config/etc/aft.properties new file mode 100644 index 0000000..95c7762 --- /dev/null +++ b/ajsc-shared-config/etc/aft.properties @@ -0,0 +1,15 @@ +#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. +# Flow test 319 +# The DEFAULT setup for this file is for deployment to soa cloud node which will use the "bundleconfig/etc/spm2.jks" location +# For Testing Locally, you can set the system property, csiEnable=true, found within bundleconfig-local/etc/sysprops/sys-props.properties +# and switch com.att.aft.keyStore and com.att.aft.trustStore values commented out below to "ajsc-shared-config/etc/spm2.jks" + +#replace proper values for the dummy values. +com.att.aft.discovery.client.environment=TEST +com.att.aft.discovery.client.latitude=35.318900 +com.att.aft.discovery.client.longitude=-80.762200 +com.att.aft.alias=fusionbus +com.att.aft.keyStore=bundleconfig/etc/key.jks +com.att.aft.keyStorePassword=password +com.att.aft.trustStore=bundleconfig/etc/key.jks +com.att.aft.trustStorePassword=password diff --git a/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml b/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml new file mode 100644 index 0000000..4ebe2db --- /dev/null +++ b/ajsc-shared-config/etc/basic-logback_root_logger_level_off.xml @@ -0,0 +1,87 @@ + + + + + + ERROR + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n + + + + + + + DEBUG + + ${logDirectory}/info_ajsc.log + + ${logDirectory}/info_ajsc.%i.log.zip + + 1 + 9 + + + 5MB + + + "%d [%thread] %-5level %logger{1024} - %msg%n" + + + + + ERROR + + ${logDirectory}/error_ajsc.log + + ${logDirectory}/error_ajsc.%i.log.zip + + 1 + 9 + + + 5MB + + + + "%d [%thread] %-5level %logger{1024} - %msg%n" + + + + + + INFO + + localhost + USER + + AJSC_AUDIT: [%thread] [%logger] %msg + + + + INFO + + localhost + USER + + AJSC_AUDIT: [%thread] [%logger] mdc:[%mdc] %msg + + + + + + + + + diff --git a/ajsc-shared-config/etc/logback.xml b/ajsc-shared-config/etc/logback.xml new file mode 100644 index 0000000..7830b10 --- /dev/null +++ b/ajsc-shared-config/etc/logback.xml @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ${errorLogPattern} + + + + + + + + + + + ${logDirectory}/${generalLogName}.log + + ${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${errorLogPattern} + + + + + + INFO + + 256 + + + + + + + + ${logDirectory}/${auditLogName}.log + + ${logDirectory}/${auditLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${auditMetricPattern} + + + + 256 + + + + + ${logDirectory}/${metricsLogName}.log + + ${logDirectory}/${metricsLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + + ${auditMetricPattern} + + + + + + 256 + + + + + ${logDirectory}/${debugLogName}.log + + ${logDirectory}/${debugLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${errorLogPattern} + + + + + 256 + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ajsc-shared-config/etc/spm2.jks b/ajsc-shared-config/etc/spm2.jks new file mode 100644 index 0000000000000000000000000000000000000000..8ff2a00a105aab80a301cb1e67b567d272d71466 GIT binary patch literal 62008 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/appconfig-local/readme.txt b/appconfig-local/readme.txt new file mode 100644 index 0000000..79cf29e --- /dev/null +++ b/appconfig-local/readme.txt @@ -0,0 +1 @@ +Relevant configuration files need to be copied here to successfully run this service locally. \ No newline at end of file diff --git a/bundleconfig-local/README.txt b/bundleconfig-local/README.txt new file mode 100644 index 0000000..37f2670 --- /dev/null +++ b/bundleconfig-local/README.txt @@ -0,0 +1,2 @@ +#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. +The bundleconfig-local directory contains the necessary configuration files \ No newline at end of file diff --git a/bundleconfig-local/RELEASE_NOTES.txt b/bundleconfig-local/RELEASE_NOTES.txt new file mode 100644 index 0000000..3cc5590 --- /dev/null +++ b/bundleconfig-local/RELEASE_NOTES.txt @@ -0,0 +1,2 @@ +#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. +Place Release Notes here to provide updated Release information \ No newline at end of file diff --git a/bundleconfig-local/etc/appprops/AAFUserRoles.properties b/bundleconfig-local/etc/appprops/AAFUserRoles.properties new file mode 100644 index 0000000..adb7a10 --- /dev/null +++ b/bundleconfig-local/etc/appprops/AAFUserRoles.properties @@ -0,0 +1,13 @@ +#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + +#If using AAF for Role based authentication/authorization, define your routes/services which will utilize AAF. The AJSC will +#read this file and protect the routes given with the AAF role defined. + +#The following example would protect the JAXRS echo example service provided with the archetype. +#/services/${namespace}/v1/jaxrs-services/jaxrsExample/echo/*=com.att.ajsc.myper|mymachine|manage + +#The following example would protect ALL AJSC services running within your project. +#/**=com.att.ajsc.myperm|mymachine|manage + +#The following example would protect ALL REST services utilizing the Camel restlet routes. +#/rest/**=com.att.ajsc.myperm|mymachine|manage diff --git a/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties b/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties new file mode 100644 index 0000000..08ffefa --- /dev/null +++ b/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties @@ -0,0 +1,3 @@ +#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. +#This properties file is for defining any PostProcessorInterceptors that have been created for your AJSC service. + diff --git a/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties b/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties new file mode 100644 index 0000000..1383071 --- /dev/null +++ b/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties @@ -0,0 +1,4 @@ +#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. +#This properties file is for defining any PreProcessorInterceptors that have been created for your AJSC service. + +/**=com.att.ajsc.csi.restmethodmap.RestMethodMapInterceptor diff --git a/bundleconfig-local/etc/appprops/app-intercepts.properties b/bundleconfig-local/etc/appprops/app-intercepts.properties new file mode 100644 index 0000000..4dc09b9 --- /dev/null +++ b/bundleconfig-local/etc/appprops/app-intercepts.properties @@ -0,0 +1,8 @@ +#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. + +#This is where all your application intercept strategies must be configured. AJSC reads this property file and adds +#the list of intercepts specified here to the camel context. This can be useful for accessing every exchange object transferred from/to +#each endpoint in the request/response flow and can allow for more precise debugging and/or processing of the exchange. + +#e.g. +#intercepts=org.onap.aai.JaxrsEchoService,packagename.class1name,packagename.class2name diff --git a/bundleconfig-local/etc/appprops/methodMapper.properties b/bundleconfig-local/etc/appprops/methodMapper.properties new file mode 100644 index 0000000..45ab671 --- /dev/null +++ b/bundleconfig-local/etc/appprops/methodMapper.properties @@ -0,0 +1,46 @@ +// +//Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. +// Json object holds the method mapping.Update the JSON object with the proper route to logical mapping based +// on the example provided below : +// "helloWorld" = Service Name +// "method" = http method +// "url" = the url component from the route +// "logicalName"= When a combination of method and url from the route matches the json object , +// the logical name is put in the http header as "x-CSI-ServiceName" and "x-CSI-MethodName" +// "dme2url"= if provided it register the endpoint to GRM, it is optional. This is useful for JAX-RS services. + +{ + "helloWorld": [ + { + "method": "get", + "url": "/rest/babel/v1/helloWorld", + "logicalName": "GetMethod(Logical)" + }, + { + "method": "get", + "url": "/services/babel/v1/jaxrsExample/jaxrs-services/echo/{input}", + "logicalName": "GetJaxrsExampleEcho(Logical)", + "dme2url": "/services/babel/v1/jaxrsExample/jaxrs-services/echo/{input}" + }, + { + "method": "get", + "url": "/services/babel/v1/jaxrsExample/jaxrs-services/property/{fileName}/{input}", + "logicalName": "GetJaxrsExampleProperty(Logical)", + "dme2url": "/services/babel/v1/jaxrsExample/jaxrs-services/property/{fileName}/{input}" + } + ], + "errormessage": + [ + { + "method": "get", + "url": "/services/babel/v1/jaxrsExample/errormessage/emls", + "logicalName": "setCAETHeaders(Logical)" + }, + { + "method": "get", + "url": "/services/babel/v1/errorMessageLookupService2", + "logicalName": "setCAETHeaders(Logical)" + } + + ] +} \ No newline at end of file diff --git a/bundleconfig-local/etc/sysprops/sys-props.properties b/bundleconfig-local/etc/sysprops/sys-props.properties new file mode 100644 index 0000000..6657f45 --- /dev/null +++ b/bundleconfig-local/etc/sysprops/sys-props.properties @@ -0,0 +1,115 @@ +#Copyright (c) 2016 AT&T Intellectual Property. All rights reserved. +#This file is used for defining AJSC system properties for different configuration schemes and is necessary for the AJSC to run properly. +#The sys-props.properties file is used for running locally. The template.sys-props.properties file will be used when deployed +#to a SOA/CSI Cloud node. + +#AJSC System Properties. The following properties are required for ALL AJSC services. If you are adding System Properties for your +#particular service, please add them AFTER all AJSC related System Properties. + +#For Cadi Authorization, use value="authentication-scheme-1 +CadiAuthN=authentication-scheme-1 + +#For Basic Authorization, use value="authentication-scheme-1 +authN=authentication-scheme-2 + +#Persistence used for AJSC meta-data storage. For most environments, "file" should be used. +ajscPersistence=file + +#For Direct Invocation to be enabled (values=true/false) +directInvocationEnable=false + +# If using hawtio for local development, these properties will allow for faster server startup and usage for local development + +hawtio.authenticationEnabled=false +hawtio.config.pullOnStartup=false + +#Removes the extraneous restlet console output +org.restlet.engine.loggerFacadeClass=org.restlet.ext.slf4j.Slf4jLoggerFacade + +#server.host property to be enabled for local DME2 related testing +#server.host= + +#Enable/disable SSL (values=true/false). This property also determines which protocol to use (https if true, http otherwise), to register services into GRM through DME2. +enableSSL=true + + +#Enable/disable EJB Container +ENABLE_EJB=false + +#Enable/disable OSGI +isOSGIEnable=false + +#Generate/Skip api docs +isApiDoc=false + +#CSI related variables for CSM framework +csm.hostname=servername + + +#SOA_CLOUD_ENV is used to register your service with dme2 and can be turned off for local development (values=true/false). +SOA_CLOUD_ENV=false + +#CONTINUE_ON_LISTENER_EXCEPTION will exit the application if there is a DME2 exception at the time of registration. +CONTINUE_ON_LISTENER_EXCEPTION=false + +#Jetty Container ThreadCount Configuration Variables +AJSC_JETTY_ThreadCount_MIN=1 +AJSC_JETTY_ThreadCount_MAX=200 +AJSC_JETTY_IDLETIME_MAX=3000 + +#Camel Context level default threadPool Profile configuration +CAMEL_POOL_SIZE=10 +CAMEL_MAX_POOL_SIZE=20 +CAMEL_KEEP_ALIVE_TIME=60 +CAMEL_MAX_QUEUE_SIZE=1000 + +#GRM/DME2 System Properties +AFT_DME2_CONN_IDLE_TIMEOUTMS=5000 +AJSC_ENV=SOACLOUD + +SOACLOUD_NAMESPACE=com.att.ajsc +SOACLOUD_ENV_CONTEXT=DEV +SOACLOUD_PROTOCOL=http +SOACLOUD_ROUTE_OFFER=DEFAULT + +AFT_LATITUDE=23.4 +AFT_LONGITUDE=33.6 +AFT_ENVIRONMENT=AFTUAT + +#Restlet Component Default Properties +RESTLET_COMPONENT_CONTROLLER_DAEMON=true +RESTLET_COMPONENT_CONTROLLER_SLEEP_TIME_MS=100 +RESTLET_COMPONENT_INBOUND_BUFFER_SIZE=8192 +RESTLET_COMPONENT_MIN_THREADS=1 +RESTLET_COMPONENT_MAX_THREADS=10 +RESTLET_COMPONENT_LOW_THREADS=8 +RESTLET_COMPONENT_MAX_QUEUED=0 +RESTLET_COMPONENT_MAX_CONNECTIONS_PER_HOST=-1 +RESTLET_COMPONENT_MAX_TOTAL_CONNECTIONS=-1 +RESTLET_COMPONENT_OUTBOUND_BUFFER_SIZE=8192 +RESTLET_COMPONENT_PERSISTING_CONNECTIONS=true +RESTLET_COMPONENT_PIPELINING_CONNECTIONS=false +RESTLET_COMPONENT_THREAD_MAX_IDLE_TIME_MS=60000 +RESTLET_COMPONENT_USE_FORWARDED_HEADER=false +RESTLET_COMPONENT_REUSE_ADDRESS=true + +#Externalized jar and properties file location. In CSI environments, there are a few libs that have been externalized to aid +#in CSTEM maintenance of the versions of these libs. The most important to the AJSC is the DME2 lib. Not only is this lib necessary +#for proper registration of your AJSC service on a node, but it is also necessary for running locally as well. Another framework +#used in CSI envs is the CSM framework. These 2 framework libs are shown as "provided" dependencies within the pom.xml. These +#dependencies will be copied into the target/commonLibs folder with the normal "mvn clean package" goal of the AJSC. They will +#then be added to the classpath via AJSC_EXTERNAL_LIB_FOLDERS system property. Any files (mainly property files) that need +#to be on the classpath should be added to the AJSC_EXTERNAL_PROPERTIES_FOLDERS system property. The default scenario when +#testing your AJSC service locally will utilize the target/commonLibs directory for DME2 and CSM related artifacts and 2 +#default csm properties files will be used for local testing with anything CSM knorelated. +#NOTE: we are using maven-replacer-plugin to replace "(doubleUnderscore)basedir(doubleUnderscore)" with ${basedir} within the +#target directory for running locally. Multiple folder locations can be separated by the pipe ("|") character. +#Please, NOTE: for running locally, we are setting this system property in the antBuild/build.xml "runLocal" target and in the +#"runAjsc" profile within the pom.xml. This is to most effectively use maven variables (${basedir}, most specifically. Therefore, +#when running locally, the following 2 properties should be set within the profile(s) themselves. +#Example: target/commonLibs|target/otherLibs +#AJSC_EXTERNAL_LIB_FOLDERS=__basedir__/target/commonLibs +#AJSC_EXTERNAL_PROPERTIES_FOLDERS=__basedir__/ajsc-shared-config/etc +#End of AJSC System Properties + +#Service System Properties. Please, place any Service related System Properties below. \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..fc50e2c --- /dev/null +++ b/pom.xml @@ -0,0 +1,453 @@ + + 4.0.0 + + + ajsc-archetype-parent + com.att.ajsc + 2.0.0 + + org.onap.aai + babel + 1.0.0-SNAPSHOT + + + babel-service + v1 + 2.0.0 + /appl/${project.artifactId} + + + /appl/${project.artifactId}/${project.version} + ${basedir}/target/swm/package/nix/dist_files${distFilesRoot} + + + aaiadmin + aaiadmin + com.att.csid.lab + + + 9515 + 9516 + + workstation + DEV + google_checks.xml + https://nexus.onap.org + + + 1.1.0 + 3.6 + 1.14 + 1.1.0 + 1.6.1 + 2.8.1 + 1.3 + 3.21.0-GA + 1.1.9 + 1.10.19 + 1.6.2 + 1.1.32-SNAPSHOT + 1.18 + 0.7.9 + + + + + javax.ws.rs + javax.ws.rs-api + 2.0.1 + + + dom4j + dom4j + ${dom4j.version} + provided + + + + + org.onap.aai.logging-service + common-logging + ${common.logging.version} + + + org.hamcrest + hamcrest-library + 1.3 + test + + + com.google.code.gson + gson + 2.8.1 + + + ch.qos.logback + logback-core + ${logback.version} + + + + + org.apache.commons + commons-compress + ${commons-compress.version} + + + commons-io + commons-io + + + org.apache.commons + commons-lang3 + ${apache.lang3.version} + + + + + org.openecomp.sdc.common + openecomp-sdc-artifact-generator-core + ${aai.artifact.generator.version} + + + com.fasterxml.jackson.core + jackson-core + ${fasterxml.version} + + + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito + ${powermock.version} + test + + + org.powermock + powermock-module-javaagent + ${powermock.version} + test + + + org.powermock + powermock-module-junit4-rule-agent + ${powermock.version} + test + + + org.javassist + javassist + ${javaassist.version} + + + org.openecomp.sdc.sdc-distribution-client + sdc-distribution-client + ${sdc.distribution.client.version} + + + xmlunit + xmlunit + 1.6 + test + + + + + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + + + + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + + prepare-agent + + prepare-agent + + + + + report + package + + report + + + + + + + + org.codehaus.groovy + groovy-eclipse-compiler + 2.9.2-01 + + + org.apache.maven.plugins + maven-resources-plugin + 3.0.2 + + + copy-docker-file + package + + copy-resources + + + target + true + + + ${basedir}/src/main/docker + true + + **/* + + + + ${basedir}/src/main/bin/ + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + package + + jar + + + client + + **/babel/service/data/* + + + + + + + + + com.mycila + license-maven-plugin + 3.0 + +

License.txt
+ + src/main/java/** + src/test/java/** + + + + + + format + + process-sources + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + client + + + + + org.apache.maven.plugins + maven-site-plugin + 3.3 + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + + checkstyle + + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + false + 1 + + + + + + + + + + runAjsc + + initialize + + + org.codehaus.mojo + exec-maven-plugin + 1.3.2 + + + initialize + + java + + + false + true + java + com.att.ajsc.runner.Runner + + com.att.ajsc + ajsc-runner + + + ${basedir}/ajsc-shared-config/etc + + + + ${runAjscHome} + + + + + + AJSC_HOME + ${runAjscHome} + + + AJSC_HOME + ${runAjscHome} + + + AJSC_CONF_HOME + ${basedir}/bundleconfig-local + + + logback.configurationFile + ${basedir}/ajsc-shared-config/etc/logback.xml + + + AJSC_SHARED_CONFIG + ${basedir}/ajsc-shared-config + + + AJSC_EXTERNAL_LIB_FOLDERS + ${basedir}/target/commonLibs + + + AJSC_EXTERNAL_PROPERTIES_FOLDERS + ${basedir}/ajsc-shared-config/etc + + + + AJSC_SERVICE_NAMESPACE + ${module.ajsc.namespace.name} + + + AJSC_SERVICE_VERSION + ${module.ajsc.namespace.version} + + + SOACLOUD_SERVICE_VERSION + ${project.version} + + + server.port + ${serverPort} + + + CONFIG_HOME + ${basedir}/appconfig-local + + + artifactgenerator.config + ${basedir}/appconfig-local/artifact-generator.properties + + + + + + context=/ + port=${serverPort} + sslport=${sslport} + + + + + + java + + + + com.att.ajsc + ajsc-runner + ${ajscRuntimeVersion} + + + + + + + + + diff --git a/src/main/ajsc/babel_v1/babel/v1/conf/babel-beans.xml b/src/main/ajsc/babel_v1/babel/v1/conf/babel-beans.xml new file mode 100644 index 0000000..f4cc32c --- /dev/null +++ b/src/main/ajsc/babel_v1/babel/v1/conf/babel-beans.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/ajsc/babel_v1/babel/v1/docs/README.txt b/src/main/ajsc/babel_v1/babel/v1/docs/README.txt new file mode 100644 index 0000000..3707179 --- /dev/null +++ b/src/main/ajsc/babel_v1/babel/v1/docs/README.txt @@ -0,0 +1 @@ +Place any docs here that you want to access within the ajsc upon deployment of your service. diff --git a/src/main/ajsc/babel_v1/babel/v1/lib/README.txt b/src/main/ajsc/babel_v1/babel/v1/lib/README.txt new file mode 100644 index 0000000..639e21b --- /dev/null +++ b/src/main/ajsc/babel_v1/babel/v1/lib/README.txt @@ -0,0 +1 @@ +3rd party JAR's needed by your jars (if any) for a ajsc deployment package go here... \ No newline at end of file diff --git a/src/main/ajsc/babel_v1/babel/v1/props/module.props b/src/main/ajsc/babel_v1/babel/v1/props/module.props new file mode 100644 index 0000000..17ebc08 --- /dev/null +++ b/src/main/ajsc/babel_v1/babel/v1/props/module.props @@ -0,0 +1 @@ +EXAMPLE.PROPERTY=EXAMLE_VALUE \ No newline at end of file diff --git a/src/main/ajsc/babel_v1/babel/v1/routes/babel-service.route b/src/main/ajsc/babel_v1/babel/v1/routes/babel-service.route new file mode 100644 index 0000000..c12bc67 --- /dev/null +++ b/src/main/ajsc/babel_v1/babel/v1/routes/babel-service.route @@ -0,0 +1,4 @@ + + + + diff --git a/src/main/assemble/ajsc_module_assembly.xml b/src/main/assemble/ajsc_module_assembly.xml new file mode 100644 index 0000000..359f792 --- /dev/null +++ b/src/main/assemble/ajsc_module_assembly.xml @@ -0,0 +1,69 @@ + + + ${version} + false + + zip + + + + ${project.basedir}/target/versioned-ajsc/routes/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/routes/ + + *.route + + + + + + ${project.basedir}/target/versioned-ajsc/docs/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/docs/ + + *.* + + + + + + + ${project.basedir}/target/versioned-ajsc/lib/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/ + + *.jar + + + + + ${project.basedir}/target/versioned-ajsc/extJars/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/extJars/ + + *.jar + + + + + + ${project.basedir}/target/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/ + + *.jar + + + + + ${project.basedir}/target/versioned-ajsc/conf/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/conf/ + + *.* + + + + + + + diff --git a/src/main/assemble/ajsc_props_assembly.xml b/src/main/assemble/ajsc_props_assembly.xml new file mode 100644 index 0000000..6ee4093 --- /dev/null +++ b/src/main/assemble/ajsc_props_assembly.xml @@ -0,0 +1,26 @@ + + + ${version}_properties + false + + zip + + + + ${project.basedir}/target/versioned-ajsc/props + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/props/ + + *.props + + + + + + + + diff --git a/src/main/assemble/ajsc_runtime_assembly.xml b/src/main/assemble/ajsc_runtime_assembly.xml new file mode 100644 index 0000000..c86d265 --- /dev/null +++ b/src/main/assemble/ajsc_runtime_assembly.xml @@ -0,0 +1,47 @@ + + + runtimeEnvironment + false + + zip + + + + ${project.basedir}/target/versioned-runtime/context/ + runtime/context/ + + *.context + + + + ${project.basedir}/target/versioned-runtime/serviceProperties/ + runtime/serviceProperties/ + + *.props + + + ${project.basedir}/target/versioned-runtime/shiroRole + runtime/shiroRole/ + + *.json + + + ${project.basedir}/target/versioned-runtime/shiroUser + runtime/shiroUser/ + + *.json + + + ${project.basedir}/target/versioned-runtime/shiroUserRole + runtime/shiroUserRole + + *.json + + + + \ No newline at end of file diff --git a/src/main/bin/start.sh b/src/main/bin/start.sh new file mode 100644 index 0000000..1854884 --- /dev/null +++ b/src/main/bin/start.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +# ============LICENSE_START======================================================= +# org.onap.aai +# ================================================================================ +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# Copyright © 2017 European Software Marketing Ltd. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. + +BASEDIR="/opt/app/babel/" +AJSC_HOME="$BASEDIR" + +if [ -z "$CONFIG_HOME" ]; then + echo "CONFIG_HOME must be set in order to start up process" + exit 1 +fi + +CLASSPATH="$AJSC_HOME/lib/*" +CLASSPATH="$CLASSPATH:$AJSC_HOME/extJars/" +CLASSPATH="$CLASSPATH:$AJSC_HOME/etc/" +PROPS="-DAJSC_HOME=$AJSC_HOME" +PROPS="$PROPS -DAJSC_CONF_HOME=$BASEDIR/bundleconfig/" +PROPS="$PROPS -Dlogback.configurationFile=$BASEDIR/bundleconfig/etc/logback.xml" +PROPS="$PROPS -DAJSC_SHARED_CONFIG=$AJSC_CONF_HOME" +PROPS="$PROPS -DAJSC_SERVICE_NAMESPACE=babel" +PROPS="$PROPS -DAJSC_SERVICE_VERSION=v1" +PROPS="$PROPS -Dserver.port=9516" +PROPS="$PROPS -DCONFIG_HOME=$CONFIG_HOME" +PROPS="$PROPS -Dartifactgenerator.config=$CONFIG_HOME/artifact-generator.properties" +PROPS="$PROPS -DKEY_STORE_PASSWORD=$KEY_STORE_PASSWORD" +PROPS="$PROPS -DKEY_MANAGER_PASSWORD=$KEY_MANAGER_PASSWORD" +JVM_MAX_HEAP=${MAX_HEAP:-1024} + +echo $CLASSPATH + +exec java -Xmx${JVM_MAX_HEAP}m $PROPS -classpath $CLASSPATH com.att.ajsc.runner.Runner context=// sslport=9516 diff --git a/src/main/config/ajsc-chef.jks b/src/main/config/ajsc-chef.jks new file mode 100644 index 0000000000000000000000000000000000000000..aeca7700182fb1824b47fca285204122a879ff85 GIT binary patch literal 5256 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 literal 0 HcmV?d00001 diff --git a/src/main/config/ajsc-jetty.xml b/src/main/config/ajsc-jetty.xml new file mode 100644 index 0000000..68306d4 --- /dev/null +++ b/src/main/config/ajsc-jetty.xml @@ -0,0 +1,128 @@ + + + + + + + + true + + + /etc/runner-web.xml + /etc/ajsc-override-web.xml + true + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + /extApps + 10 + true + + + + + + + + + + + + + + + + + + + + + /auth/tomcat_keystore + + + + + + + + + + + true + true + + + + + + + + + + + + + http/1.1 + + + + + + + + + + + + + + + + + + + + + + 30000 + + + + + + + \ No newline at end of file diff --git a/src/main/config/ajsc-override-web.xml b/src/main/config/ajsc-override-web.xml new file mode 100644 index 0000000..84a7920 --- /dev/null +++ b/src/main/config/ajsc-override-web.xml @@ -0,0 +1,53 @@ + + + + + + InterceptorFilter + /services/* + + + InterceptorFilter + /rest/* + + + + springSecurityFilterChain + /* + + + + ManagementServlet + /mgmt + + + + RestletServlet + /rest/* + + + + CamelServlet + /services/* + + + + jsp + *.jsp + *.jspf + *.jspx + *.xsp + *.JSP + *.JSPF + *.JSPX + *.XSP + + + default + /* + + \ No newline at end of file diff --git a/src/main/config/ajscJetty.jks b/src/main/config/ajscJetty.jks new file mode 100644 index 0000000000000000000000000000000000000000..48cdbff4a8344b9bfa164b340c2fd3b4f7020c41 GIT binary patch literal 3736 zcmcIm`)`xy75+Zo;@EM*>Rd47o-~jPU}JKFn8b+*gxq6897y6^aPAj^NkW*tv>V%4 zyRF*Rc3M>xRjX8OrCU)iVyiZ!iWb^R6&;0+l1^fqRQ0F+3ws`)k1rMKualnhoO9my z^Y^~zyyrcizq$6eZyrKX6az#}iZwQUHo7o6AH_gG9_fKn6tm)nHbLC!7Kg3UqMFnS z!}nCxtZ~`P?CJNqmyXXx;aI2o792JhsgV548_!HZo2o&;_RpUv+ae~{GJf#q z!MdVh8R!xP4nfL{AQh4e5$xF~Iy}(66IPBsk$|-o5>E$Jn_VvLL1hkp0YpcwRi{JyRN4$I;F!}LQV-;fNJSJM_^pU+{Hynlzw2I@?=fy~jM<2ZK zYMg0YqvWj1I5XlGbA?L-Ou3FzW4(#FkNygOh_9TL3HA6+f68Y+hvRAh<;y5IQ>>7;EBd2S36TyJ}*wf9SB8?IRywf@kmB1)ixQLB5S$xjotN$7L)J zY8rA<+=HTYjwS9ruRHay3dFnnV`w8U64wb&uw;1R4}SN?zux3CtbXF@=fJ1(vcPqa z_;C=W8**~&SZ(DbJ;vQh0!~1fkCxM*20JtK!~~P zR{D;@%HsVhs$l7rP4gheg3(ed51PvZU835#YjL;8Y6yLur?!wkF7(58= z{_wy9!|lv~Yb65KL5G*4!sl1`j#<{vynA=Dxxo}@XUgDs8^-y1;PZ>^>`2=oGpxsM z2GiPBzwF|X@l=7rGcn#Ko?H3xV&1d1yKjJX)MhedfLR54xlO^@Vl$I}M!YN@Hoy`F z&O^9;mi{QqOxq>PdI;iy2;O@(8P1lLn{PU7EQ>&diCc!Szq%nhjAEU?{x0i*DFGG_ zBwui@T^nL}jqFcA#luwbKD$dcvm2KAIjA6Hh*Wq+d!vg*dnOIU1+`nh1Ev-nEWshD zi5~U)`}$zaSO!*ZKO2KJEVJOyHqd7mbf1X^_-gG7!Cg->P+uJziVp&?-E4Lh<7T!7 zTE}J!G3iMS#Mh=Cm#6bZ33u}nENn))zae|$7Y0^_fWIzbL1=Zmv8VAl3l40L&%-|CqzOtKIdAVhpm_jooBJElq=JFqjV2 z@v^!dHcKjlJput7HdVFb4^r4;cc)s6$4nNd;aKpYV|5x1`#oFmw+S;T&J=&B!`~J1 zd(!wC3^{C0qdye#IBae^eY?}t66^`+zR_v&9}Tv+^K%?F&px-;Q|GDn)>rR6A%2ag zM)UvA>myLL_`5>KUqGIVnvwjAs5)#0da42jPVN}&GM8>V0n=eCVQmHPzHDbtnq_eS zY;}k4yai^<2~zGq11`A3Is1@?xi+=$Na&vRSReQzet(b+d zr~LDZ!Kf+>uE<^B&O>qLrJJ%%nLH*zBM;=?KfN03=Z$6e5*Ty8t59%9l7*rw+jfN9 zmUJH;wrc^yteUGYfy#ueLwXT!ls`fcz3j_XfRey^6e+2yW?*8^z2Ar=h zvnn&#vUrn^L71LVrlOQ*|PW9frj&V8Ix8l3)CaF^zwDO~%1DUQGTe;RWhYSm*+l zN8zI>VTe_hLe2roM}OkE1N=7kiK%mgZoy#NyZwrcFj+i==)HHg$Ow3=w%0FS8TAIV d$UppJT1E%vmLWa}Z$I0*0!fDe1J|Dh{|_E2uSEa= literal 0 HcmV?d00001 diff --git a/src/main/config/cadi.properties b/src/main/config/cadi.properties new file mode 100644 index 0000000..d250fec --- /dev/null +++ b/src/main/config/cadi.properties @@ -0,0 +1,36 @@ +#This properties file is used for defining AAF properties related to the CADI framework. This file is used for running AAF framework + +#In order to test functionality of cadi-ajsc-plugin locally cross domain cookie. Cadi "should" find your hostname for you. +#However, we have seen some situations where this fails. A Local testing +#modification can include modifying your hosts file so that you can use "mywebserver.att.com" for your localhost in order +#to test/verify GLO functionality locally. If you are on a Windows machine, you will already have a machine name associated with +#it that will utilize an AT&T domain such as "sbc.com". You may need to add your domain to this as a comma separated list depending +#upon your particular machine domain. This property is commented out as cadi SHOULD find your machine name. With version 1.2.1 of cadi, +#it appears to resolve Mac machine names as well, now. But, this can be somewhat inconsistent depending on your specific working envrironment. +hostname=mywebserver.att.com + +#Setting csp_domain to PROD will allow for testing using your attuid and password through GLO. +csp_domain=PROD +csp_devl_localhost=true + +basic_realm=csp.att.com +#basic_realm=aaf.att.com +basic_warn=TRUE + +cadi_loglevel=WARN +cadi_keyfile=target/swm/package/nix/dist_files/appl/babel/etc/keyfile + +# Configure AAF +#These are dummy values add appropriate values required +aaf_url=url + +#AJSC - MECHID +#These are dummy values add appropriate values required +aaf_id=dummyid@ajsc.att.com +aaf_password=enc:277edqJCjT0RlUI3BtbDQa-3Ha-CQGd +aaf_timeout=5000 +aaf_clean_interval=30000 +aaf_user_expires=5000 +aaf_high_count=1000 + + diff --git a/src/main/config/jul-redirect.properties b/src/main/config/jul-redirect.properties new file mode 100644 index 0000000..8b6624d --- /dev/null +++ b/src/main/config/jul-redirect.properties @@ -0,0 +1,13 @@ + +# Bridge JUL->slf4j Logging Configuration File +# +# This file bridges the JUL logging infrastructure into +# SLF4J so JUL logs go to logback implementation provided +# in this project. SLF4J also captures log4j and has +# other framework options as well providing a common +# logging infrastructure for capturing all logs from different +# libraries using different frameworks in one place. + +# Global properties +handlers=org.slf4j.bridge.SLF4JBridgeHandler +.level= ALL diff --git a/src/main/config/keyfile b/src/main/config/keyfile new file mode 100644 index 0000000..882e86a --- /dev/null +++ b/src/main/config/keyfile @@ -0,0 +1,27 @@ +ZuIwp0TkyVPDeX1Up-8JtkMWvjsCpoiu1_VKeWrtrvxunvAke8_tiFyHPPyb2nkhepFYj6tXzpfS +rGz5XF_TH9NbsKaP8u0HV5clz2WriYQRvHS85vjY7hXxkpFuLb7zkLAPqTyIDpj7FiW61NzsRUAq +TM8jH16jr7mBNnb56w24mNGOwznMPcIZKcjgZU1ekaPDFpWyhQElU7Y0q_94P_Gkk45r66Hj22sU +OiOaaftmudZlswLw8-8Zaakqf2yW9HjMVfuYCwSodBHCW5rdB3Ctb5W36rnD_AQco3Ky2PgPmqvk +QkJYuUHpbuDqVHqLOajlKSIGMTIqAIBg51fRaaONtD-Q5xzY8E5wO1YWTLKcP5tsNvUpzM8Wu3NS +ynpGpUcvlTqWWsGzTbzOyamyKkdNdx97sSqjM25Zh1-ps48h6cddGYWpab7SUvqRCS11QBUyLTry +2iwTEHMhHRIbo7PO99ALQfuq9gI1zKGfurJdvLBeBaFs5SCF0AiCZ3WcDO8Rv3HpxVZ2_ShbDxb0 +eMoO6SotXu51fj8Y3-WqsfZziQyEsHyqpg5uQ6yUtz01h5YHLEoVuotF1U4agmQR6kEkYk-wNOiZ +v-8gaA9gtbLoAdKhuKFxQgQLNMf6GzVzZNujbmDzLoZAP_mXAv29aBPaf64Ugzv-Oa5GZdBgD-Xd +_pahML-ionw99r0TnkpShYmDqMKhMdjaP3m87WIAZkIB-L-VTyKcEsJ4340VSzCOsv3waiM0S89u +4cMcG5y-PLY8IoipIlLUPTWD3SjcQ9DV1Dt3T5KjdWLsj48D3W4K4e9PB8yxs0gtUjgVUR2_xEir +G5eDO9Ac1eHFWGDFFP0SgG-TbHJUKlvy9mwLzmU0fC3xPjhqmIr-v0HxF7HN-tmb1LHDorno8tSN +u7kUGcKSchIiFfvkd066crUb2mH7PnXTaWmAjyVj9VsBExFUYEdpHMAV4sAP9-RxZGDRt46UhrDK +QZvvNhBVyOEjHPHWI4vl1r1v8HNH1_2jZu5DVJWyHWR56aCo1lhFH9_X6UAHUHbnXViDONZOVXlT +9-WD0tk2zJGuwrhdZDAnPnAmjfwbwbpnr5Hmex1i1JiD7WVyP1kbfoej2TmdiYbxr9oBYaGQ29JI +aHod7MQCLtvL1z5XgnDPLZ4y3_9SbqHKYbNa8UgZkTLF5EacGThYVFDLA9cbafHDtR1kMGE3vv4D +EJ-0pAYTOGmKlVI7DwNyKsY9JTyudrxTqhOxi9jgcJNWiUaNe9yhL8Pyc2YBqUTTYhh_a2d1rvkZ +0Gh1crviVxqBrIkRKaMRXZ4f1vDLz-3NvG_vwPOo8WRFo5nGmSdTw7CjBaigJ_cYCfDhoP11pEnw +cndsZNcHs-v05LlxeIIMDD_f5Bvz-il_DLA4eK2HqgLdxh8ziSDl2azk14MJY4amzz6reEXUuKLV +RsZGf_jbDGKhE2HuDQ5ovoLOi4OqE1oRuqh-dGxitrYouP2SN1l_1tCEMRth86FMV-6AQtZsvdUo +y9MtQ7e35atjA8nHtgADlDTmJBKQiUHUsOZ77p1qp17HAFMovUkc739opfEYnKUn6Itpw5Ipm_Is +ra6chJUfMpOFof5rb5OjqFAN27c_-mPo1lQU3ndYlKGh_n5V8ufX6v2Yri8WzOPf6hjVYotkmoMP +NPAICDCB8W5ddBjsopzLVVEtaXDu9Qj6-zf77hT4iQ7rBd2Ner8iLqN3Kis0dvkNM3_uH8onau1G +Y_YYw7PPSZyd2S_7Dd6G-IG4ayO6e5DD6oUwwekyiQI_3rTXNa_wldGxqW9u818010ekE4Qdlfcj +beIn7fAeaOjReZ87hRgWyMs-EgTVHw8RL3yI_O6VvRTVRONRF1Y4C_-IYa8z-bfrwXx3BBd9TTgb +EnS9wVOyC2OgUN6BhPLGLhxzkJ05nEjizXEc9t5EPYoSRwesajGGrrG_0-qWbuU5hKLPLkyeJLHb +5HXOTVsrUR59Vov2M3_EswkxcImblox3k3VS2yihZMGyfqLzZIUXgd8ufkevKKU6DxwacGTb \ No newline at end of file diff --git a/src/main/config/runner-web.xml b/src/main/config/runner-web.xml new file mode 100644 index 0000000..b51aff4 --- /dev/null +++ b/src/main/config/runner-web.xml @@ -0,0 +1,97 @@ + + + + + + contextConfigLocation + /WEB-INF/spring-servlet.xml, + classpath:applicationContext.xml + + + + + spring.profiles.default + nooauth + + + + org.springframework.web.context.ContextLoaderListener + + + + ManagementServlet + ajsc.ManagementServlet + + + + + InterceptorFilter + ajsc.filters.InterceptorFilter + + preProcessor_interceptor_config_file + /etc/PreProcessorInterceptors.properties + + + postProcessor_interceptor_config_file + /etc/PostProcessorInterceptors.properties + + + + + + RestletServlet + ajsc.restlet.RestletSpringServlet + + org.restlet.component + restletComponent + + + + + CamelServlet + ajsc.servlet.AjscCamelServlet + + + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + + spring + org.springframework.web.servlet.DispatcherServlet + 1 + + + + + + + + jsp + org.apache.jasper.servlet.JspServlet + + + + + + + + + default + org.eclipse.jetty.servlet.DefaultServlet + + dirAllowed + true + + + + diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile new file mode 100644 index 0000000..6fac6e2 --- /dev/null +++ b/src/main/docker/Dockerfile @@ -0,0 +1,24 @@ +FROM ubuntu:14.04 + +ARG MICRO_HOME=/opt/app/babel +ARG BIN_HOME=$MICRO_HOME/bin + +RUN apt-get update + +# Install and setup java8 +RUN apt-get update && apt-get install -y software-properties-common +## sudo -E is required to preserve the environment. If you remove that line, it will most like freeze at this step +RUN sudo -E add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-8-jdk +## Setup JAVA_HOME, this is useful for docker commandline +ENV JAVA_HOME usr/lib/jvm/java-8-openjdk-amd64 +RUN export JAVA_HOME + +# Build up the deployment folder structure +RUN mkdir -p $MICRO_HOME +ADD swm/package/nix/dist_files/appl/babel/* $MICRO_HOME/ +RUN mkdir -p $BIN_HOME +COPY *.sh $BIN_HOME +RUN chmod 755 $BIN_HOME/* +RUN ln -s /logs $MICRO_HOME/logs + +CMD ["/opt/app/babel/bin/start.sh"] diff --git a/src/main/java/org/onap/aai/auth/AAIAuthException.java b/src/main/java/org/onap/aai/auth/AAIAuthException.java new file mode 100644 index 0000000..13593ab --- /dev/null +++ b/src/main/java/org/onap/aai/auth/AAIAuthException.java @@ -0,0 +1,39 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.auth; + +public class AAIAuthException extends Exception { + /** + * + */ + private static final long serialVersionUID = 1L; + + public AAIAuthException(String string) { + super(string); + } + + public AAIAuthException(String string, Exception e) { + super(string, e); + } + +} diff --git a/src/main/java/org/onap/aai/auth/AAIMicroServiceAuth.java b/src/main/java/org/onap/aai/auth/AAIMicroServiceAuth.java new file mode 100644 index 0000000..f678498 --- /dev/null +++ b/src/main/java/org/onap/aai/auth/AAIMicroServiceAuth.java @@ -0,0 +1,121 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.auth; + +import java.security.cert.X509Certificate; +import javax.inject.Inject; +import javax.security.auth.x500.X500Principal; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.HttpHeaders; +import org.onap.aai.babel.config.BabelAuthConfig; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; + + +/** + * Public class for authentication and authorization operations. Authorization is applied according to user and role + */ +public class AAIMicroServiceAuth { + + private static Logger applicationLogger = LoggerFactory.getInstance().getLogger(AAIMicroServiceAuth.class); + + private BabelAuthConfig babelAuthConfig; + + /** + * @param babelAuthConfig + * @throws AAIAuthException + */ + @Inject + public AAIMicroServiceAuth(final BabelAuthConfig babelAuthConfig) throws AAIAuthException { + this.babelAuthConfig = babelAuthConfig; + if (!babelAuthConfig.isAuthenticationDisable()) { + AAIMicroServiceAuthCore.init(babelAuthConfig.getAuthPolicyFile()); + } + } + + /** + * @param username + * @param policyFunction + * @return + * @throws AAIAuthException + */ + public boolean authorize(String username, String policyFunction) throws AAIAuthException { + return AAIMicroServiceAuthCore.authorize(username, policyFunction); + } + + /** + * @param authUser + * @param policyFunction + * @return + * @throws AAIAuthException + */ + public String authenticate(String authUser, String policyFunction) throws AAIAuthException { + if (authorize(authUser, policyFunction)) { + return "OK"; + } else { + return "AAI_9101"; + } + } + + /** + * @param headers + * @param req + * @param action + * @param apiPath + * @return + * @throws AAIAuthException + */ + public boolean validateRequest(HttpHeaders headers /* NOSONAR */, HttpServletRequest req, + AAIMicroServiceAuthCore.HTTP_METHODS action, String apiPath) throws AAIAuthException { + + applicationLogger.debug("validateRequest: " + apiPath); + applicationLogger + .debug("babelAuthConfig.isAuthenticationDisable(): " + babelAuthConfig.isAuthenticationDisable()); + + if (babelAuthConfig.isAuthenticationDisable()) { + return true; + } + + String[] ps = apiPath.split("/"); + String authPolicyFunctionName = ps[0]; + if (ps.length > 1 && authPolicyFunctionName.matches("v\\d+")) { + authPolicyFunctionName = ps[1]; + } + + String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); + String authUser = null; + + if (cipherSuite != null) { + X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); + X509Certificate clientCert = certChain[0]; + X500Principal subjectDN = clientCert.getSubjectX500Principal(); + authUser = subjectDN.toString(); + } + + if (authUser != null) { + return "OK".equals(authenticate(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName)); + } else { + return false; + } + } +} diff --git a/src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java b/src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java new file mode 100644 index 0000000..b148440 --- /dev/null +++ b/src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java @@ -0,0 +1,287 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.auth; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; + +/** + * Authentication and authorization by user and role. + * + */ +public class AAIMicroServiceAuthCore { + + private static Logger applicationLogger = LoggerFactory.getInstance().getLogger(AAIMicroServiceAuthCore.class); + + public static final String FILESEP = + (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator"); + public static final String APPCONFIG_DIR = (System.getProperty("CONFIG_HOME") == null) + ? System.getProperty("AJSC_HOME") + FILESEP + "appconfig" : System.getProperty("CONFIG_HOME"); + + private static String appConfigAuthDir = APPCONFIG_DIR + FILESEP + "auth"; + private static String defaultAuthFileName = appConfigAuthDir + FILESEP + "auth_policy.json"; + + private static boolean usersInitialized = false; + private static HashMap users; + private static boolean timerSet = false; + private static Timer timer = null; + private static String policyAuthFileName; + + public enum HTTP_METHODS { + GET, + PUT, + DELETE, + HEAD, + POST + } + + // Don't instantiate + private AAIMicroServiceAuthCore() {} + + public static String getDefaultAuthFileName() { + return defaultAuthFileName; + } + + public static void setDefaultAuthFileName(String defaultAuthFileName) { + AAIMicroServiceAuthCore.defaultAuthFileName = defaultAuthFileName; + } + + public static synchronized void init(String authPolicyFile) throws AAIAuthException { + + try { + policyAuthFileName = AAIMicroServiceAuthCore.getConfigFile(authPolicyFile); + } catch (IOException e) { + applicationLogger.debug("Exception while retrieving policy file."); + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + throw new AAIAuthException(e.getMessage()); + } + if (policyAuthFileName == null) { + throw new AAIAuthException("Auth policy file could not be found"); + } + AAIMicroServiceAuthCore.reloadUsers(); + + TimerTask task = new FileWatcher(new File(policyAuthFileName)) { + @Override + protected void onChange(File file) { + // here we implement the onChange + applicationLogger.debug("File " + file.getName() + " has been changed!"); + try { + AAIMicroServiceAuthCore.reloadUsers(); + } catch (AAIAuthException e) { + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + } + applicationLogger.debug("File " + file.getName() + " has been reloaded!"); + } + }; + + if (!timerSet) { + timerSet = true; + timer = new Timer(); + long period = TimeUnit.SECONDS.toMillis(1); + timer.schedule(task, new Date(), period); + applicationLogger.debug("Config Watcher Interval = " + period); + } + } + + public static void cleanup() { + timer.cancel(); + } + + public static String getConfigFile(String authPolicyFile) throws IOException { + File authFile = new File(authPolicyFile); + if (authFile.exists()) { + return authFile.getCanonicalPath(); + } + authFile = new File(appConfigAuthDir + FILESEP + authPolicyFile); + if (authFile.exists()) { + return authFile.getCanonicalPath(); + } + if (defaultAuthFileName != null) { + authFile = new File(defaultAuthFileName); + if (authFile.exists()) { + return defaultAuthFileName; + } + } + return null; + } + + public static synchronized void reloadUsers() throws AAIAuthException { + users = new HashMap<>(); + + ObjectMapper mapper = new ObjectMapper(); + try { + applicationLogger.debug("Reading from " + policyAuthFileName); + JsonNode rootNode = mapper.readTree(new File(policyAuthFileName)); + for (JsonNode roleNode : rootNode.path("roles")) { + String roleName = roleNode.path("name").asText(); + AAIAuthRole r = new AAIAuthRole(); + installFunctionOnRole(roleNode.path("functions"), roleName, r); + assignRoleToUsers(roleNode.path("users"), roleName, r); + } + } catch (FileNotFoundException e) { + throw new AAIAuthException("Auth policy file could not be found", e); + } catch (JsonProcessingException e) { + throw new AAIAuthException("Error processing Auth policy file ", e); + } catch (IOException e) { + throw new AAIAuthException("Error reading Auth policy file", e); + } + + usersInitialized = true; + } + + private static void installFunctionOnRole(JsonNode functionsNode, String roleName, AAIAuthRole r) { + for (JsonNode functionNode : functionsNode) { + String function = functionNode.path("name").asText(); + JsonNode methodsNode = functionNode.path("methods"); + boolean hasMethods = false; + for (JsonNode method_node : methodsNode) { + String methodName = method_node.path("name").asText(); + hasMethods = true; + String func = methodName + ":" + function; + applicationLogger.debug("Installing function " + func + " on role " + roleName); + r.addAllowedFunction(func); + } + + if (!hasMethods) { + for (HTTP_METHODS meth : HTTP_METHODS.values()) { + String func = meth.toString() + ":" + function; + applicationLogger.debug("Installing (all methods) " + func + " on role " + roleName); + r.addAllowedFunction(func); + } + } + } + } + + private static void assignRoleToUsers(JsonNode usersNode, String roleName, AAIAuthRole r) { + for (JsonNode userNode : usersNode) { + String name = userNode.path("username").asText().toLowerCase(); + AAIAuthUser user; + if (users.containsKey(name)) { + user = users.get(name); + } else { + user = new AAIAuthUser(); + } + applicationLogger.debug("Assigning " + roleName + " to user " + name); + user.setUser(name); + user.addRole(roleName, r); + users.put(name, user); + } + } + + public static class AAIAuthUser { + private String username; + private HashMap roles; + + public AAIAuthUser() { + this.roles = new HashMap<>(); + } + + public String getUser() { + return this.username; + } + + public Map getRoles() { + return this.roles; + } + + public void addRole(String roleName, AAIAuthRole r) { + this.roles.put(roleName, r); + } + + public boolean checkAllowed(String checkFunc) { + for (Entry role_entry : roles.entrySet()) { + AAIAuthRole role = role_entry.getValue(); + if (role.hasAllowedFunction(checkFunc)) { + return true; + } + } + return false; + } + + public void setUser(String myuser) { + this.username = myuser; + } + + } + + public static class AAIAuthRole { + + private List allowedFunctions; + + public AAIAuthRole() { + this.allowedFunctions = new ArrayList<>(); + } + + public void addAllowedFunction(String func) { + this.allowedFunctions.add(func); + } + + public void delAllowedFunction(String delFunc) { + if (this.allowedFunctions.contains(delFunc)) { + this.allowedFunctions.remove(delFunc); + } + } + + public boolean hasAllowedFunction(String afunc) { + return this.allowedFunctions.contains(afunc) ? true : false; + } + } + + public static boolean authorize(String username, String authFunction) throws AAIAuthException { + if (!usersInitialized || users == null) { + throw new AAIAuthException("Auth module not initialized"); + } + if (users.containsKey(username)) { + if (users.get(username).checkAllowed(authFunction)) { + logAuthenticationResult(username, authFunction, "AUTH ACCEPTED"); + return true; + } else { + logAuthenticationResult(username, authFunction, "AUTH FAILED"); + return false; + } + } else { + logAuthenticationResult(username, authFunction, "User not found"); + return false; + } + } + + private static void logAuthenticationResult(String username, String authFunction, String result) { + applicationLogger.debug(result + ": " + username + " on function " + authFunction); + } +} diff --git a/src/main/java/org/onap/aai/auth/FileWatcher.java b/src/main/java/org/onap/aai/auth/FileWatcher.java new file mode 100644 index 0000000..e3b9923 --- /dev/null +++ b/src/main/java/org/onap/aai/auth/FileWatcher.java @@ -0,0 +1,63 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.auth; + +import java.io.File; +import java.util.TimerTask; + +public abstract class FileWatcher extends TimerTask { + private long timeStamp; + private File file; + + /** + * Instantiates a new file watcher. + * + * @param file the file + */ + public FileWatcher(File file) { + this.file = file; + this.timeStamp = file.lastModified(); + } + + /** + * runs a timer task + * + * @see java.util.TimerTask.run + */ + @Override + public final void run() { + long newTimeStamp = file.lastModified(); + + if ((newTimeStamp - this.timeStamp) > 500) { + this.timeStamp = newTimeStamp; + onChange(file); + } + } + + /** + * On change. + * + * @param file the file + */ + protected abstract void onChange(File file); +} diff --git a/src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java b/src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java new file mode 100644 index 0000000..5fdc01f --- /dev/null +++ b/src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java @@ -0,0 +1,51 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.config; + +import org.springframework.beans.factory.annotation.Value; + +public class BabelAuthConfig { + + @Value("${auth.authentication.disable}") + private boolean authenticationDisable; + + @Value("${auth.policy.file}") + private String authPolicyFile; + + public boolean isAuthenticationDisable() { + return authenticationDisable; + } + + public void setAuthenticationDisable(boolean authenticationDisable) { + this.authenticationDisable = authenticationDisable; + } + + public String getAuthPolicyFile() { + return authPolicyFile; + } + + public void setAuthPolicyFile(String authPolicyFile) { + this.authPolicyFile = authPolicyFile; + } + +} diff --git a/src/main/java/org/onap/aai/babel/csar/CsarConverterException.java b/src/main/java/org/onap/aai/babel/csar/CsarConverterException.java new file mode 100644 index 0000000..b9316fc --- /dev/null +++ b/src/main/java/org/onap/aai/babel/csar/CsarConverterException.java @@ -0,0 +1,40 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar; + +/** + * This class represents an exception encountered when attempting to convert the yml files in a csar archive into xml. + */ +public class CsarConverterException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + public CsarConverterException(String message) { + super(message); + } +} diff --git a/src/main/java/org/onap/aai/babel/csar/CsarToXmlConverter.java b/src/main/java/org/onap/aai/babel/csar/CsarToXmlConverter.java new file mode 100644 index 0000000..55cf652 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/csar/CsarToXmlConverter.java @@ -0,0 +1,88 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar; + +import java.util.List; +import java.util.Objects; +import org.onap.aai.babel.csar.extractor.InvalidArchiveException; +import org.onap.aai.babel.csar.extractor.YamlExtractor; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.babel.xml.generator.XmlArtifactGenerationException; +import org.onap.aai.babel.xml.generator.ArtifactGenerator; +import org.onap.aai.babel.xml.generator.ModelGenerator; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; + +import org.openecomp.sdc.generator.data.Artifact; + +/** + * This class is responsible for converting content in a csar archive into one or more xml artifacts. + */ +public class CsarToXmlConverter { + private static Logger logger = LoggerFactory.getInstance().getLogger(CsarToXmlConverter.class); + + /** + * This method is responsible for extracting one or more yaml files from the given csarArtifact and then using them + * to generate xml artifacts. + * + * @param csarArchive the artifact that contains the csar archive to generate xml artifacts from + * @param name the name of the archive file + * @param version the version of the archive file + * @return List a list of generated xml artifacts + * @throws CsarConverterException if there is an error either extracting the yaml files or generating xml artifacts + */ + public List generateXmlFromCsar(byte[] csarArchive, String name, String version) + throws CsarConverterException { + validateArguments(csarArchive, name, version); + + logger.info(ApplicationMsgs.DISTRIBUTION_EVENT, + "Starting to process csarArchive to convert contents to xml artifacts"); + List xmlArtifacts; + + try { + logger.debug("Calling YamlExtractor to extract ymlFiles"); + List ymlFiles = YamlExtractor.extract(csarArchive, name, version); + + logger.debug("Calling XmlArtifactGenerator to generateXmlArtifacts"); + ArtifactGenerator modelGenerator = new ModelGenerator(); + xmlArtifacts = modelGenerator.generateArtifacts(ymlFiles); + + logger.debug(xmlArtifacts.size() + " xml artifacts have been generated"); + } catch (InvalidArchiveException e) { + throw new CsarConverterException( + "An error occurred trying to extract the yml files from the csar file : " + e); + } catch (XmlArtifactGenerationException e) { + throw new CsarConverterException( + "An error occurred trying to generate xml files from a collection of yml files : " + e); + } + + return xmlArtifacts; + } + + private void validateArguments(byte[] csarArchive, String name, String version) { + Objects.requireNonNull(csarArchive); + Objects.requireNonNull(name); + Objects.requireNonNull(version); + } +} diff --git a/src/main/java/org/onap/aai/babel/csar/extractor/InvalidArchiveException.java b/src/main/java/org/onap/aai/babel/csar/extractor/InvalidArchiveException.java new file mode 100644 index 0000000..aac893b --- /dev/null +++ b/src/main/java/org/onap/aai/babel/csar/extractor/InvalidArchiveException.java @@ -0,0 +1,50 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar.extractor; + +/** + * This class represents an exception encountered when processing an archive in memory. + */ +public class InvalidArchiveException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + InvalidArchiveException(String message) { + super(message); + } + + /** + * Constructor for an instance of this exception with a message and actual exception encountered. + * + * @param message information about the exception + * @param cause the actual exception that was encountered + */ + InvalidArchiveException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/aai/babel/csar/extractor/YamlExtractor.java b/src/main/java/org/onap/aai/babel/csar/extractor/YamlExtractor.java new file mode 100644 index 0000000..fb51933 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/csar/extractor/YamlExtractor.java @@ -0,0 +1,149 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar.extractor; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipFile; +import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.xml.generator.ModelGenerator; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.openecomp.sdc.generator.data.Artifact; +import org.yaml.snakeyaml.Yaml; + +/** + * The purpose of this class is to process a .csar file in the form of a byte array and extract yaml files from it. + * + * A .csar file is a compressed archive like a zip file and this class will treat the byte array as it if were a zip + * file. + */ +public class YamlExtractor { + private static Logger logger = LoggerFactory.getInstance().getLogger(YamlExtractor.class); + + private static final String TYPE = "type"; + private static final Pattern YAMLFILE_EXTENSION_REGEX = Pattern.compile("(?i).*\\.ya?ml$"); + private static final Set INVALID_TYPES = new HashSet<>(); + + static { + Collections.addAll(INVALID_TYPES, "CP", "VL", "VFC", "VFCMT", "ABSTRACT"); + } + + /** + * Private constructor + */ + private YamlExtractor() { + throw new IllegalAccessError("Utility class"); + } + + /** + * This method is responsible for filtering the contents of the supplied archive and returning a collection of + * {@link Artifact}s that represent the yml files that have been found in the archive.
+ *
+ * If the archive contains no yml files it will return an empty list.
+ * + * @param archive the zip file in the form of a byte array containing one or more yml files + * @param name the name of the archive file + * @param version the version of the archive file + * @return List collection of yml files found in the archive + * @throws InvalidArchiveException if an error occurs trying to extract the yml files from the archive, if the + * archive is not a zip file or there are no yml files + */ + public static List extract(byte[] archive, String name, String version) throws InvalidArchiveException { + validateRequest(archive, name, version); + + logger.info(ApplicationMsgs.DISTRIBUTION_EVENT, "Extracting CSAR archive: " + name); + + List ymlFiles = new ArrayList<>(); + try (SeekableInMemoryByteChannel inMemoryByteChannel = new SeekableInMemoryByteChannel(archive); + ZipFile zipFile = new ZipFile(inMemoryByteChannel)) { + for (Enumeration enumeration = zipFile.getEntries(); enumeration.hasMoreElements();) { + ZipArchiveEntry entry = enumeration.nextElement(); + if (fileShouldBeExtracted(zipFile, entry)) { + ymlFiles.add(ModelGenerator.createArtifact(IOUtils.toByteArray(zipFile.getInputStream(entry)), + entry.getName(), version)); + } + } + if (ymlFiles.isEmpty()) { + throw new InvalidArchiveException("No valid yml files were found in the csar file."); + } + } catch (IOException e) { + throw new InvalidArchiveException( + "An error occurred trying to create a ZipFile. Is the content being converted really a csar file?", + e); + } + + logger.debug(ApplicationMsgs.DISTRIBUTION_EVENT, ymlFiles.size() + " YAML files extracted."); + + return ymlFiles; + } + + private static void validateRequest(byte[] archive, String name, String version) throws InvalidArchiveException { + if (archive == null || archive.length == 0) { + throw new InvalidArchiveException("An archive must be supplied for processing."); + } else if (StringUtils.isBlank(name)) { + throw new InvalidArchiveException("The name of the archive must be supplied for processing."); + } else if (StringUtils.isBlank(version)) { + throw new InvalidArchiveException("The version must be supplied for processing."); + } + } + + @SuppressWarnings("unchecked") + private static boolean fileShouldBeExtracted(ZipFile zipFile, ZipArchiveEntry entry) throws IOException { + logger.debug(ApplicationMsgs.DISTRIBUTION_EVENT, "Checking if " + entry.getName() + " should be extracted..."); + + boolean extractFile = false; + if (YAMLFILE_EXTENSION_REGEX.matcher(entry.getName()).matches()) { + try { + Yaml yamlParser = new Yaml(); + HashMap yaml = + (LinkedHashMap) yamlParser.load(zipFile.getInputStream(entry)); + HashMap metadata = (LinkedHashMap) yaml.get("metadata"); + + extractFile = metadata != null && metadata.containsKey(TYPE) + && !INVALID_TYPES.contains(metadata.get(TYPE).toString().toUpperCase()) + && !metadata.get(TYPE).toString().isEmpty(); + } catch (Exception e) { + logger.error(ApplicationMsgs.DISTRIBUTION_EVENT, + "Unable to verify " + entry.getName() + " contains a valid resource type: " + e.getMessage()); + } + } + + logger.debug(ApplicationMsgs.DISTRIBUTION_EVENT, "Keeping file: " + entry.getName() + "? : " + extractFile); + + return extractFile; + } +} + diff --git a/src/main/java/org/onap/aai/babel/logging/ApplicationMsgs.java b/src/main/java/org/onap/aai/babel/logging/ApplicationMsgs.java new file mode 100644 index 0000000..9b9f9d5 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/logging/ApplicationMsgs.java @@ -0,0 +1,50 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.logging; + +import com.att.eelf.i18n.EELFResourceManager; +import org.onap.aai.cl.eelf.LogMessageEnum; + +public enum ApplicationMsgs implements LogMessageEnum { + //@formatter:off + /** + * Arguments: {0} = message. + */ + DISTRIBUTION_EVENT, + + PROCESS_REQUEST_ERROR, + + INVALID_CSAR_FILE, + + INVALID_REQUEST_JSON; + + //@formatter:on + + /** + * Static initializer to ensure the resource bundles for this class are loaded... Here this application loads + * messages from three bundles + */ + static { + EELFResourceManager.loadMessageBundle("babel-logging-resources"); + } +} diff --git a/src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java new file mode 100644 index 0000000..bb7b721 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsService.java @@ -0,0 +1,51 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.service; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import org.onap.aai.auth.AAIAuthException; + +/** + * Generate artifacts from the specified request content + */ +@Path("/") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public interface GenerateArtifactsService { + + @POST + @Path("/generateArtifacts") + Response generateArtifacts(@Context UriInfo uriInfo, @Context HttpHeaders headers, + @Context HttpServletRequest servletRequest, String request) throws AAIAuthException; + + +} diff --git a/src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java new file mode 100644 index 0000000..bdb45b5 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/service/GenerateArtifactsServiceImpl.java @@ -0,0 +1,148 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.service; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; +import java.util.Base64; +import java.util.List; +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; +import org.onap.aai.auth.AAIAuthException; +import org.onap.aai.auth.AAIMicroServiceAuth; +import org.onap.aai.auth.AAIMicroServiceAuthCore; +import org.onap.aai.babel.csar.CsarConverterException; +import org.onap.aai.babel.csar.CsarToXmlConverter; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.babel.service.data.BabelRequest; +import org.onap.aai.babel.util.RequestValidationException; +import org.onap.aai.babel.util.RequestValidator; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; + + +/** + * Generate SDC Artifacts by passing in a CSAR payload, Artifact Name and Artifact version + */ +public class GenerateArtifactsServiceImpl implements GenerateArtifactsService { + private static Logger applicationLogger = LoggerFactory.getInstance().getLogger(GenerateArtifactsServiceImpl.class); + + private AAIMicroServiceAuth aaiMicroServiceAuth; + + /** + * @param authorization + */ + @Inject + public GenerateArtifactsServiceImpl(final AAIMicroServiceAuth authorization) { + this.aaiMicroServiceAuth = authorization; + } + + /* + * (non-Javadoc) + * + * @see org.onap.aai.babel.service.GenerateArtifactsService#generateArtifacts(javax.ws.rs.core.UriInfo, + * javax.ws.rs.core.HttpHeaders, javax.servlet.http.HttpServletRequest, java.lang.String) + */ + @Override + public Response generateArtifacts(UriInfo uriInfo, HttpHeaders headers, HttpServletRequest servletRequest, + String requestBody) throws AAIAuthException { + applicationLogger.debug("Received request: " + requestBody); + + Response response; + try { + boolean authorized = aaiMicroServiceAuth.validateRequest(headers, servletRequest, + AAIMicroServiceAuthCore.HTTP_METHODS.POST, uriInfo.getPath(false)); + + response = authorized ? generateArtifacts(requestBody) + : buildResponse(Status.UNAUTHORIZED, "User not authorized to perform the operation."); + } catch (AAIAuthException e) { + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + throw e; + } + + applicationLogger.debug("Sending response: " + response.getStatus() + " " + response.getEntity().toString()); + return response; + } + + + /** + * Generate XML model artifacts from request body. + * + * @param requestBody the request body in JSON format + * @return response object containing the generated XML models + */ + protected Response generateArtifacts(String requestBody) { + Response response; + + try { + Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + + BabelRequest babelRequest = gson.fromJson(requestBody, BabelRequest.class); + RequestValidator.validateRequest(babelRequest); + byte[] csarFile = Base64.getDecoder().decode(babelRequest.getCsar()); + List xmlArtifacts = new CsarToXmlConverter().generateXmlFromCsar(csarFile, + babelRequest.getArtifactName(), babelRequest.getArtifactVersion()); + response = buildResponse(Status.OK, gson.toJson(xmlArtifacts)); + + } catch (JsonSyntaxException e) { + applicationLogger.error(ApplicationMsgs.INVALID_REQUEST_JSON, e); + response = buildResponse(Status.BAD_REQUEST, "Malformed request."); + } catch (CsarConverterException e) { + applicationLogger.error(ApplicationMsgs.INVALID_CSAR_FILE, e); + response = buildResponse(Status.INTERNAL_SERVER_ERROR, "Error converting CSAR artifact to XML model."); + } catch (RequestValidationException e) { + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + response = buildResponse(Status.BAD_REQUEST, e.getLocalizedMessage()); + } catch (Exception e) { + applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e); + response = buildResponse(Status.INTERNAL_SERVER_ERROR, + "Error while processing request. Please check the babel service logs for more details.\n"); + } + + return response; + } + + /** + * Helper method to create a REST response object. + * + * @param status response status code + * @param entity response payload + * @return + */ + private Response buildResponse(Status status, String entity) { + //@formatter:off + return Response + .status(status) + .entity(entity) + .type(MediaType.TEXT_PLAIN) + .build(); + //@formatter:on + } +} diff --git a/src/main/java/org/onap/aai/babel/service/data/BabelArtifact.java b/src/main/java/org/onap/aai/babel/service/data/BabelArtifact.java new file mode 100644 index 0000000..986aed9 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/service/data/BabelArtifact.java @@ -0,0 +1,63 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.service.data; + +/** + * Bean representing the return artifacts of the Babel microservice. + */ +public class BabelArtifact { + String name; + String type; + byte[] payload; + + public BabelArtifact(String name, String type, byte[] payload) { + super(); + this.name = name; + this.type = type; + this.payload = payload; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public byte[] getPayload() { + return payload; + } + + public void setPayload(byte[] payload) { + this.payload = payload; + } +} diff --git a/src/main/java/org/onap/aai/babel/service/data/BabelRequest.java b/src/main/java/org/onap/aai/babel/service/data/BabelRequest.java new file mode 100644 index 0000000..20a101f --- /dev/null +++ b/src/main/java/org/onap/aai/babel/service/data/BabelRequest.java @@ -0,0 +1,53 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.service.data; + +public class BabelRequest { + private String csar; + private String artifactVersion; + private String artifactName; + + public String getCsar() { + return csar; + } + + public void setCsar(String csar) { + this.csar = csar; + } + + public String getArtifactVersion() { + return artifactVersion; + } + + public void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + public String getArtifactName() { + return artifactName; + } + + public void setArtifactName(String artifactName) { + this.artifactName = artifactName; + } +} diff --git a/src/main/java/org/onap/aai/babel/util/RequestValidationException.java b/src/main/java/org/onap/aai/babel/util/RequestValidationException.java new file mode 100644 index 0000000..5e3be5e --- /dev/null +++ b/src/main/java/org/onap/aai/babel/util/RequestValidationException.java @@ -0,0 +1,42 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.util; + +/** + * This exception is thrown when the request fails validation. + */ +public class RequestValidationException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + public RequestValidationException(String message) { + super(message); + } +} + + diff --git a/src/main/java/org/onap/aai/babel/util/RequestValidator.java b/src/main/java/org/onap/aai/babel/util/RequestValidator.java new file mode 100644 index 0000000..ecc9d2b --- /dev/null +++ b/src/main/java/org/onap/aai/babel/util/RequestValidator.java @@ -0,0 +1,50 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.util; + +import org.onap.aai.babel.service.data.BabelRequest; + +public class RequestValidator { + + private RequestValidator() {} + + + /** + * Validates that the request body contains the required attributes + * + * @param request the request body to validate + */ + public static void validateRequest(BabelRequest request) throws RequestValidationException { + if (request.getCsar() == null) { + throw new RequestValidationException("No csar attribute found in the request body."); + } + + if (request.getArtifactVersion() == null) { + throw new RequestValidationException("No artifact version attribute found in the request body."); + } + + if (request.getArtifactName() == null) { + throw new RequestValidationException("No artifact name attribute found in the request body."); + } + } +} diff --git a/src/main/java/org/onap/aai/babel/xml/generator/ArtifactGenerator.java b/src/main/java/org/onap/aai/babel/xml/generator/ArtifactGenerator.java new file mode 100644 index 0000000..4fd51aa --- /dev/null +++ b/src/main/java/org/onap/aai/babel/xml/generator/ArtifactGenerator.java @@ -0,0 +1,39 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.xml.generator; + +import java.util.List; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.openecomp.sdc.generator.data.Artifact; + +public interface ArtifactGenerator { + + /** + * Generate a {@link List} of {@link BabelArtifact}s from the Artifacts obtained from the CSAR + * + * @param csarArtifacts artifacts obtained from the CSAR file + * @return generated {@link BabelArtifact}s + */ + List generateArtifacts(List csarArtifacts) throws XmlArtifactGenerationException; + +} diff --git a/src/main/java/org/onap/aai/babel/xml/generator/ModelGenerator.java b/src/main/java/org/onap/aai/babel/xml/generator/ModelGenerator.java new file mode 100644 index 0000000..c6def3d --- /dev/null +++ b/src/main/java/org/onap/aai/babel/xml/generator/ModelGenerator.java @@ -0,0 +1,136 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.xml.generator; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.onap.aai.babel.logging.ApplicationMsgs; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.openecomp.sdc.generator.data.AdditionalParams; +import org.openecomp.sdc.generator.data.Artifact; +import org.openecomp.sdc.generator.data.GenerationData; +import org.openecomp.sdc.generator.data.GeneratorUtil; +import org.openecomp.sdc.generator.data.GroupType; +import org.openecomp.sdc.generator.service.ArtifactGenerationService; + +/** + * This class is responsible for generating xml model artifacts from a collection of csar file artifacts + */ +public class ModelGenerator implements ArtifactGenerator { + + private static Logger logger = LoggerFactory.getInstance().getLogger(ModelGenerator.class); + + private static final String GENERATORCONFIG = "{\"artifactTypes\": [\"AAI\"]}"; + private static final Pattern UUID_NORMATIVE_NEW_VERSION = Pattern.compile("^\\d{1,}.0"); + private static final String VERSION_DELIMITER = "."; + private static final String VERSION_DELIMITER_REGEXP = "\\" + VERSION_DELIMITER; + private static final String DEFAULT_SERVICE_VERSION = "1.0"; + + /** + * Invokes the TOSCA artifact generator API with the input artifacts. + * + * @param csarArtifacts the input artifacts + * @return {@link List} of output artifacts + * @throws XmlArtifactGenerationException if there is an error trying to generate xml artifacts + */ + @Override + public List generateArtifacts(List csarArtifacts) throws XmlArtifactGenerationException { + logger.info(ApplicationMsgs.DISTRIBUTION_EVENT, + "Generating XML for " + csarArtifacts.size() + " CSAR artifacts."); + + // Get the service version to pass into the generator + String toscaVersion = csarArtifacts.get(0).getVersion(); + logger.debug( + "Getting the service version for Tosca Version of the yml file. The Tosca Version is " + toscaVersion); + String serviceVersion = getServiceVersion(toscaVersion); + logger.debug("The service version is " + serviceVersion); + Map additionalParams = new HashMap<>(); + additionalParams.put(AdditionalParams.ServiceVersion.getName(), serviceVersion); + + // Call ArtifactGenerator API + logger.debug("Obtaining instance of ArtifactGenerationService"); + ArtifactGenerationService generationService = ArtifactGenerationService.lookup(); + logger.debug("About to call generationService.generateArtifact()"); + GenerationData data = generationService.generateArtifact(csarArtifacts, GENERATORCONFIG, additionalParams); + logger.debug("Call generationService.generateArtifact() has finished"); + + // Convert results into BabelArtifacts + if (data.getErrorData().isEmpty()) { + return data.getResultData().stream().map(a -> new BabelArtifact(a.getName(), a.getType(), a.getPayload())) + .collect(Collectors.toList()); + } else { + throw new XmlArtifactGenerationException( + "Error occurred during artifact generation: " + data.getErrorData().toString()); + } + } + + /** + * Creates an instance of an input artifact for the generator. + * + * @param payload the payload downloaded from SDC + * @param artifactName name of the artifact to create + * @param artifactVersion version of the artifact to create + * @return an {@link Artifact} object constructed from the payload and artifactInfo + */ + public static Artifact createArtifact(byte[] payload, String artifactName, String artifactVersion) { + logger.info(ApplicationMsgs.DISTRIBUTION_EVENT, "Creating artifact for: " + artifactName); + + // Convert payload into an input Artifact + String checksum = GeneratorUtil.checkSum(payload); + byte[] encodedPayload = GeneratorUtil.encode(payload); + Artifact artifact = new Artifact("TOSCA", GroupType.DEPLOYMENT.name(), checksum, encodedPayload); + artifact.setName(artifactName); + artifact.setLabel(artifactName); + artifact.setDescription(artifactName); + artifact.setVersion(artifactVersion); + return artifact; + } + + private static String getServiceVersion(String artifactVersion) { + String serviceVersion; + + try { + if (UUID_NORMATIVE_NEW_VERSION.matcher(artifactVersion).matches()) { + serviceVersion = artifactVersion; + } else { + String[] versionParts = artifactVersion.split(VERSION_DELIMITER_REGEXP); + Integer majorVersion = Integer.parseInt(versionParts[0]); + + serviceVersion = (majorVersion + 1) + VERSION_DELIMITER + "0"; + } + } catch (Exception e) { + logger.warn(ApplicationMsgs.DISTRIBUTION_EVENT, + "Error generating service version from artifact version: " + artifactVersion + + ". Using default service version of: " + DEFAULT_SERVICE_VERSION + ". Error details: " + + e); + return DEFAULT_SERVICE_VERSION; + } + + return serviceVersion; + } +} diff --git a/src/main/java/org/onap/aai/babel/xml/generator/XmlArtifactGenerationException.java b/src/main/java/org/onap/aai/babel/xml/generator/XmlArtifactGenerationException.java new file mode 100644 index 0000000..bff6ab3 --- /dev/null +++ b/src/main/java/org/onap/aai/babel/xml/generator/XmlArtifactGenerationException.java @@ -0,0 +1,40 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.xml.generator; + +/** + * This class represents an exception encountered when generating an Artifact. + */ +public class XmlArtifactGenerationException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Constructor for an instance of this exception with just a message. + * + * @param message information about the exception + */ + public XmlArtifactGenerationException(String message) { + super(message); + } +} diff --git a/src/main/resources/babel-logging-resources.properties b/src/main/resources/babel-logging-resources.properties new file mode 100644 index 0000000..3cd23ab --- /dev/null +++ b/src/main/resources/babel-logging-resources.properties @@ -0,0 +1,59 @@ +### +# ============LICENSE_START======================================================= +# MODEL LOADER SERVICE +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# Copyright (C) 2017 European Software Marketing Ltd. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +#Resource key=Error Code|Message text|Resolution text |Description text +####### +#Newlines can be utilized to add some clarity ensuring continuing line +#has at least one leading space +#ResourceKey=\ +# ERR0000E\ +# Sample error msg txt\ +# Sample resolution msg\ +# Sample description txt +# +###### +#Error code classification category +#000 Info/Debug +#100 Permission errors +#200 Availability errors/Timeouts +#300 Data errors +#400 Schema Interface type/validation errors +#500 Business process errors +#900 Unknown errors +# +######################################################################## + +DISTRIBUTION_EVENT=\ + BABEL0001I|\ + Distribution event: {0}|\ + A distribution event was received from ASDC|\ + +PROCESS_REQUEST_ERROR=\ + BABEL0002E|\ + Error while processing REST request.|\ + +INVALID_REQUEST_JSON=\ + BABEL0003E|\ + Error while processing JSON in request body.|\ + +INVALID_CSAR_FILE=\ + BABEL0004E|\ + Error while processing CSAR file.|\ \ No newline at end of file diff --git a/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context b/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context new file mode 100644 index 0000000..8514196 --- /dev/null +++ b/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context @@ -0,0 +1 @@ +{"context":{"contextClass":"ajsc.Context","contextId":"__module_ajsc_namespace_name__:__module_ajsc_namespace_version__","contextName":"__module_ajsc_namespace_name__","contextVersion":"__module_ajsc_namespace_version__","description":"__module_ajsc_namespace_name__ Context"}} \ No newline at end of file diff --git a/src/main/runtime/context/default#0.context b/src/main/runtime/context/default#0.context new file mode 100644 index 0000000..d1b5ab4 --- /dev/null +++ b/src/main/runtime/context/default#0.context @@ -0,0 +1 @@ +{"context":{"contextClass":"ajsc.Context","contextId":"default:0","contextName":"default","contextVersion":"0","description":"Default Context"}} \ No newline at end of file diff --git a/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json b/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json new file mode 100644 index 0000000..d0954cf --- /dev/null +++ b/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json @@ -0,0 +1 @@ +{"deploymentPackage":{"Class":"ajsc.DeploymentPackage","Id":"__module.ajsc.namespace.name__:__module_ajsc_namespace_version__","namespace":"__module_ajsc_namespace_name__","namespaceVersion":"__module_ajsc_namespace_version__","description":"__module_ajsc_namespace_name__ __module_ajsc_namespace_version__ - default description","userId":"ajsc"}} \ No newline at end of file diff --git a/src/main/runtime/shiroRole/ajscadmin.json b/src/main/runtime/shiroRole/ajscadmin.json new file mode 100644 index 0000000..f5e981e --- /dev/null +++ b/src/main/runtime/shiroRole/ajscadmin.json @@ -0,0 +1 @@ +{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"ajscadmin","name":"ajscadmin","permissions":"[ajscadmin:*, ajsc:*]"} \ No newline at end of file diff --git a/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json b/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json new file mode 100644 index 0000000..2dae9f5 --- /dev/null +++ b/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json @@ -0,0 +1 @@ +{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"contextadmin:__module_ajsc_namespace_name__","name":"contextadmin:__module_ajsc_namespace_name__","permissions":"[]"} \ No newline at end of file diff --git a/src/main/runtime/shiroRole/contextadmin#default.json b/src/main/runtime/shiroRole/contextadmin#default.json new file mode 100644 index 0000000..5de814e --- /dev/null +++ b/src/main/runtime/shiroRole/contextadmin#default.json @@ -0,0 +1 @@ +{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"contextadmin:default","name":"contextadmin:default","permissions":"[]"} \ No newline at end of file diff --git a/src/main/runtime/shiroUser/ajsc.json b/src/main/runtime/shiroUser/ajsc.json new file mode 100644 index 0000000..f4c7855 --- /dev/null +++ b/src/main/runtime/shiroUser/ajsc.json @@ -0,0 +1 @@ +{"shiroUserClass":"ajsc.auth.ShiroUser","shiroUserId":"ajsc","passwordHash":"9471697417008c880720ba54c6038791ad7e98f3b88136fe34f4d31a462dd27a","permissions":"[*:*]","username":"ajsc"} \ No newline at end of file diff --git a/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json b/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json new file mode 100644 index 0000000..cb8d483 --- /dev/null +++ b/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json @@ -0,0 +1 @@ +{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:ajscadmin","roleId":"ajscadmin","userId":"ajsc"} \ No newline at end of file diff --git a/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json b/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json new file mode 100644 index 0000000..95d2361 --- /dev/null +++ b/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json @@ -0,0 +1 @@ +{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:contextadmin:__module_ajsc_namespace_name__","roleId":"contextadmin:__module_ajsc_namespace_name__","userId":"ajsc"} \ No newline at end of file diff --git a/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json b/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json new file mode 100644 index 0000000..2bd5063 --- /dev/null +++ b/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json @@ -0,0 +1 @@ +{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:contextadmin:default","roleId":"contextadmin:default","userId":"ajsc"} \ No newline at end of file diff --git a/src/test/java/org/onap/aai/babel/MicroServiceAuthTest.java b/src/test/java/org/onap/aai/babel/MicroServiceAuthTest.java new file mode 100644 index 0000000..f24cbf1 --- /dev/null +++ b/src/test/java/org/onap/aai/babel/MicroServiceAuthTest.java @@ -0,0 +1,211 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Test; +import org.onap.aai.auth.AAIAuthException; +import org.onap.aai.auth.AAIMicroServiceAuth; +import org.onap.aai.auth.AAIMicroServiceAuthCore; +import org.onap.aai.babel.config.BabelAuthConfig; +import org.springframework.mock.web.MockHttpServletRequest; + +/** + * Tests @{link AAIMicroServiceAuth} + */ + +public class MicroServiceAuthTest { + + private static final String VALID_ADMIN_USER = "cn=common-name, ou=org-unit, o=org, l=location, st=state, c=us"; + private static final String authPolicyFile = "auth_policy.json"; + + static { + System.setProperty("CONFIG_HOME", + System.getProperty("user.dir") + File.separator + "src/test/resources"); + } + + /** + * Temporarily invalidate the default policy file and then try to initialise the authorisation class using the name + * of a policy file that does not exist. + * + * @throws AAIAuthException + * @throws IOException + */ + @Test(expected = AAIAuthException.class) + public void missingPolicyFile() throws AAIAuthException, IOException { + String defaultFile = AAIMicroServiceAuthCore.getDefaultAuthFileName(); + try { + AAIMicroServiceAuthCore.setDefaultAuthFileName("invalid.default.file"); + BabelAuthConfig gapServiceAuthConfig = new BabelAuthConfig(); + gapServiceAuthConfig.setAuthPolicyFile("invalid.file.name"); + new AAIMicroServiceAuth(gapServiceAuthConfig); + } finally { + AAIMicroServiceAuthCore.setDefaultAuthFileName(defaultFile); + } + } + + /** + * Test loading of a temporary file created with the specified roles + * + * @throws AAIAuthException + * @throws IOException + * @throws JSONException + */ + @Test + public void createLocalAuthFile() throws AAIAuthException, IOException, JSONException { + JSONObject roles = createRoleObject("role", createUserObject("user"), createFunctionObject("func")); + AAIMicroServiceAuth auth = createAuthService(roles); + assertThat(auth.authorize("nosuchuser", "method:func"), is(false)); + assertThat(auth.authorize("user", "method:func"), is(true)); + } + + /** + * Test that the default policy file is loaded when a non-existent file is passed to the authorisation clas. + * + * @throws AAIAuthException + */ + @Test + public void createAuthFromDefaultFile() throws AAIAuthException { + BabelAuthConfig gapServiceAuthConfig = new BabelAuthConfig(); + gapServiceAuthConfig.setAuthPolicyFile("non-existent-file"); + AAIMicroServiceAuth auth = new AAIMicroServiceAuth(gapServiceAuthConfig); + // The default policy will have been loaded + assertAdminUserAuthorisation(auth, VALID_ADMIN_USER); + } + + /** + * Test loading of the policy file relative to CONFIG_HOME + * + * @throws AAIAuthException + */ + @Test + public void createAuth() throws AAIAuthException { + AAIMicroServiceAuth auth = createStandardAuth(); + assertAdminUserAuthorisation(auth, VALID_ADMIN_USER); + } + + @Test + public void testAuthUser() throws AAIAuthException { + AAIMicroServiceAuth auth = createStandardAuth(); + assertThat(auth.authenticate(VALID_ADMIN_USER, "GET:actions"), is(equalTo("OK"))); + assertThat(auth.authenticate(VALID_ADMIN_USER, "WRONG:action"), is(equalTo("AAI_9101"))); + } + + + + @Test + public void testValidateRequest() throws AAIAuthException { + AAIMicroServiceAuth auth = createStandardAuth(); + assertThat(auth.validateRequest(null, new MockHttpServletRequest(), null, "app/v1/gap"), is(false)); + } + + private AAIMicroServiceAuth createStandardAuth() throws AAIAuthException { + BabelAuthConfig gapServiceAuthConfig = new BabelAuthConfig(); + gapServiceAuthConfig.setAuthPolicyFile(authPolicyFile); + return new AAIMicroServiceAuth(gapServiceAuthConfig); + } + + /** + * @param rolesJson + * @return + * @throws IOException + * @throws AAIAuthException + */ + private AAIMicroServiceAuth createAuthService(JSONObject roles) throws IOException, AAIAuthException { + BabelAuthConfig babelAuthConfig = new BabelAuthConfig(); + File file = File.createTempFile("auth-policy", "json"); + file.deleteOnExit(); + FileWriter fileWriter = new FileWriter(file); + fileWriter.write(roles.toString()); + fileWriter.flush(); + fileWriter.close(); + + babelAuthConfig.setAuthPolicyFile(file.getAbsolutePath()); + return new AAIMicroServiceAuth(babelAuthConfig); + } + + /** + * Assert authorisation results for an admin user based on the test policy file + * + * @param auth + * @param adminUser + * @throws AAIAuthException + */ + private void assertAdminUserAuthorisation(AAIMicroServiceAuth auth, String adminUser) throws AAIAuthException { + assertThat(auth.authorize(adminUser, "GET:actions"), is(true)); + assertThat(auth.authorize(adminUser, "POST:actions"), is(true)); + assertThat(auth.authorize(adminUser, "PUT:actions"), is(true)); + assertThat(auth.authorize(adminUser, "DELETE:actions"), is(true)); + } + + private JSONArray createFunctionObject(String functionName) throws JSONException { + JSONArray functionsArray = new JSONArray(); + JSONObject func = new JSONObject(); + func.put("name", functionName); + func.put("methods", createMethodObject("method")); + functionsArray.put(func); + return functionsArray; + } + + private JSONArray createMethodObject(String methodName) throws JSONException { + JSONArray methodsArray = new JSONArray(); + JSONObject method = new JSONObject(); + method.put("name", methodName); + methodsArray.put(method); + return methodsArray; + } + + private JSONArray createUserObject(String username) throws JSONException { + JSONArray usersArray = new JSONArray(); + JSONObject user = new JSONObject(); + user.put("username", username); + usersArray.put(user); + return usersArray; + } + + private JSONObject createRoleObject(String roleName, JSONArray usersArray, JSONArray functionsArray) + throws JSONException { + JSONObject roles = new JSONObject(); + + JSONObject role = new JSONObject(); + role.put("name", roleName); + role.put("functions", functionsArray); + role.put("users", usersArray); + + JSONArray rolesArray = new JSONArray(); + rolesArray.put(role); + roles.put("roles", rolesArray); + + return roles; + } + +} diff --git a/src/test/java/org/onap/aai/babel/csar/extractor/YamlExtractorTest.java b/src/test/java/org/onap/aai/babel/csar/extractor/YamlExtractorTest.java new file mode 100644 index 0000000..54f4c65 --- /dev/null +++ b/src/test/java/org/onap/aai/babel/csar/extractor/YamlExtractorTest.java @@ -0,0 +1,141 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar.extractor; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.onap.aai.babel.util.ArtifactTestUtils; +import org.openecomp.sdc.generator.data.Artifact; + +/** + * Tests @see YamlExtractor + */ +public class YamlExtractorTest { + + private static final String FOO = "foo"; + private static final String SOME_BYTES = "just some bytes that will pass the firsts validation"; + private static final String SUPPLY_AN_ARCHIVE = "An archive must be supplied for processing."; + private static final String SUPPLY_NAME = "The name of the archive must be supplied for processing."; + private static final String SUPPLY_VERSION = "The version must be supplied for processing."; + + @Test + public void extract_nullContentSupplied() { + invalidArgumentsTest(null, FOO, FOO, SUPPLY_AN_ARCHIVE); + } + + private void invalidArgumentsTest(byte[] archive, String name, String version, String expectedErrorMessage) { + try { + YamlExtractor.extract(archive, name, version); + fail("An instance of InvalidArchiveException should have been thrown"); + } catch (Exception ex) { + assertTrue(ex instanceof InvalidArchiveException); + assertEquals(expectedErrorMessage, ex.getLocalizedMessage()); + } + } + + @Test + public void extract_emptyContentSupplied() { + invalidArgumentsTest(new byte[0], FOO, FOO, SUPPLY_AN_ARCHIVE); + } + + @Test + public void extract_nullNameSupplied() { + invalidArgumentsTest(SOME_BYTES.getBytes(), null, FOO, SUPPLY_NAME); + } + + @Test + public void extract_blankNameSupplied() { + invalidArgumentsTest("just some bytes that will pass the firsts validation".getBytes(), " \t ", FOO, + SUPPLY_NAME); + } + + @Test + public void extract_emptyNameSupplied() { + invalidArgumentsTest("just some bytes that will pass the firsts validation".getBytes(), "", FOO, SUPPLY_NAME); + } + + @Test + public void extract_nullVersionSupplied() { + invalidArgumentsTest("just some bytes that will pass the firsts validation".getBytes(), FOO, null, + SUPPLY_VERSION); + } + + @Test + public void extract_blankVersionSupplied() { + invalidArgumentsTest("just some bytes that will pass the firsts validation".getBytes(), FOO, " \t ", + SUPPLY_VERSION); + } + + @Test + public void extract_emptyVersionSupplied() { + invalidArgumentsTest("just some bytes that will pass the firsts validation".getBytes(), FOO, "", + SUPPLY_VERSION); + } + + @Test + public void extract_invalidContentSupplied() { + invalidArgumentsTest("This is a piece of nonsense and not a zip file".getBytes(), FOO, FOO, + "An error occurred trying to create a ZipFile. Is the content being converted really a csar file?"); + } + + @Test + public void extract_archiveContainsNoYmlFiles() throws IOException { + try { + YamlExtractor.extract(loadResource("compressedArtifacts/noYmlFilesArchive.zip"), "noYmlFilesArchive.zip", + "v1"); + fail("An instance of InvalidArchiveException should have been thrown."); + } catch (Exception e) { + assertTrue("An instance of InvalidArchiveException should have been thrown.", + e instanceof InvalidArchiveException); + assertEquals("Incorrect message was returned", "No valid yml files were found in the csar file.", + e.getMessage()); + } + } + + private byte[] loadResource(final String archiveName) throws IOException { + return IOUtils.toByteArray(YamlExtractor.class.getClassLoader().getResource(archiveName)); + } + + @Test + public void extract_archiveContainsThreeRelevantYmlFilesFromSdWanService() + throws IOException, InvalidArchiveException { + List ymlFiles = + YamlExtractor.extract(loadResource("compressedArtifacts/service-SdWanServiceTest-csar.csar"), + "service-SdWanServiceTest-csar.csar", "v1"); + + List payloads = new ArrayList<>(); + payloads.add("ymlFiles/resource-SdWanTestVsp-template.yml"); + payloads.add("ymlFiles/resource-TunnelXconntest-template.yml"); + payloads.add("ymlFiles/service-SdWanServiceTest-template.yml"); + + new ArtifactTestUtils().performYmlAsserts(ymlFiles, payloads); + } +} + diff --git a/src/test/java/org/onap/aai/babel/csar/fixture/ArtifactInfoBuilder.java b/src/test/java/org/onap/aai/babel/csar/fixture/ArtifactInfoBuilder.java new file mode 100644 index 0000000..0ff8fa1 --- /dev/null +++ b/src/test/java/org/onap/aai/babel/csar/fixture/ArtifactInfoBuilder.java @@ -0,0 +1,78 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar.fixture; + +import java.util.ArrayList; +import java.util.List; +import org.openecomp.sdc.api.notification.IArtifactInfo; + +/** + * This class builds an instance of IArtifactInfo for test purposes. + */ +public class ArtifactInfoBuilder { + + /** + * Builds an implementation of IArtifactInfo for test purposes. + *

+ * + * @param type type of artifact + * @param name name of artifact + * @param description description of artifact + * @param version version of artifact + * @return IArtifactInfo implementation of IArtifactInfo from given parameters for test purposes + */ + public static IArtifactInfo build(final String type, final String name, final String description, + final String version) { + IArtifactInfo artifact = new TestArtifactInfoImpl(); + + ((TestArtifactInfoImpl) artifact).setArtifactType(type); + ((TestArtifactInfoImpl) artifact).setArtifactName(name); + ((TestArtifactInfoImpl) artifact).setArtifactDescription(description); + ((TestArtifactInfoImpl) artifact).setArtifactVersion(version); + + return artifact; + } + + /** + * This method is responsible for building a collection of artifacts from a given set of info. + *

+ * The info supplied is a two dimensional array with each element of the first dimension representing a single + * artifact and each element of the second dimension represents a property of the artifact. + *

+ * The method will call {@link #build(String, String, String, String)} to build each element in the first dimension + * where the elements of the second dimension are the arguments to {@link #build(String, String, String, String)}. + *

+ * + * @param artifactInfoBits a two dimensional array of data used to build the artifacts + * @return List a list of artifacts built from the given array of info + */ + static List buildArtifacts(final String[][] artifactInfoBits) { + List artifacts = new ArrayList<>(); + + for (String[] artifactInfoBit : artifactInfoBits) { + artifacts.add(build(artifactInfoBit[0], artifactInfoBit[1], artifactInfoBit[2], artifactInfoBit[3])); + } + + return artifacts; + } +} diff --git a/src/test/java/org/onap/aai/babel/csar/fixture/TestArtifactInfoImpl.java b/src/test/java/org/onap/aai/babel/csar/fixture/TestArtifactInfoImpl.java new file mode 100644 index 0000000..bbf4a43 --- /dev/null +++ b/src/test/java/org/onap/aai/babel/csar/fixture/TestArtifactInfoImpl.java @@ -0,0 +1,135 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.csar.fixture; + +import org.openecomp.sdc.api.notification.IArtifactInfo; + +/** + * This class is an implementation of IArtifactInfo for test purposes. + */ +public class TestArtifactInfoImpl implements IArtifactInfo { + + private String artifactName; + private String artifactType; + private String artifactDescription; + private String artifactVersion; + + @Override + public String getArtifactName() { + return artifactName; + } + + void setArtifactName(String artifactName) { + this.artifactName = artifactName; + } + + @Override + public String getArtifactType() { + return artifactType; + } + + void setArtifactType(String artifactType) { + this.artifactType = artifactType; + } + + @Override + public String getArtifactURL() { + return null; + } + + @Override + public String getArtifactChecksum() { + return null; + } + + @Override + public String getArtifactDescription() { + return artifactDescription; + } + + void setArtifactDescription(String artifactDescription) { + this.artifactDescription = artifactDescription; + } + + @Override + public Integer getArtifactTimeout() { + return null; + } + + @Override + public String getArtifactVersion() { + return artifactVersion; + } + + void setArtifactVersion(String artifactVersion) { + this.artifactVersion = artifactVersion; + } + + @Override + public String getArtifactUUID() { + return null; + } + + @Override + public IArtifactInfo getGeneratedArtifact() { + return null; + } + + @Override + public java.util.List getRelatedArtifacts() { + return null; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + TestArtifactInfoImpl that = (TestArtifactInfoImpl) o; + + if (artifactName != null ? !artifactName.equals(that.artifactName) : that.artifactName != null) { + return false; + } + if (artifactType != null ? !artifactType.equals(that.artifactType) : that.artifactType != null) { + return false; + } + if (artifactDescription != null ? !artifactDescription.equals(that.artifactDescription) + : that.artifactDescription != null) { + return false; + } + return artifactVersion != null ? artifactVersion.equals(that.artifactVersion) : that.artifactVersion == null; + } + + @Override + public int hashCode() { + int result = artifactName != null ? artifactName.hashCode() : 0; + result = 31 * result + (artifactType != null ? artifactType.hashCode() : 0); + result = 31 * result + (artifactDescription != null ? artifactDescription.hashCode() : 0); + result = 31 * result + (artifactVersion != null ? artifactVersion.hashCode() : 0); + return result; + } +} diff --git a/src/test/java/org/onap/aai/babel/service/CsarToXmlConverterTest.java b/src/test/java/org/onap/aai/babel/service/CsarToXmlConverterTest.java new file mode 100644 index 0000000..5c1e213 --- /dev/null +++ b/src/test/java/org/onap/aai/babel/service/CsarToXmlConverterTest.java @@ -0,0 +1,170 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.service; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.custommonkey.xmlunit.XMLTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.onap.aai.babel.csar.CsarConverterException; +import org.onap.aai.babel.csar.CsarToXmlConverter; +import org.onap.aai.babel.service.data.BabelArtifact; +import org.onap.aai.babel.util.ArtifactTestUtils; +import org.onap.aai.babel.xml.generator.ModelGenerator; +import org.onap.aai.babel.xml.generator.XmlArtifactGenerationException; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.xml.sax.SAXException; + +/** + * Tests {@link CsarToXmlConverter} + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest(ModelGenerator.class) +public class CsarToXmlConverterTest extends XMLTestCase { + + private static final String NAME = "the_name_of_the_csar_file.csar"; + private static final String VERSION = "v1"; + + private CsarToXmlConverter converter; + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Before + public void setUp() { + converter = new CsarToXmlConverter(); + URL url = CsarToXmlConverterTest.class.getClassLoader().getResource("artifact-generator.properties"); + System.setProperty("artifactgenerator.config", url.getPath()); + } + + @After + public void tearDown() { + converter = null; + } + + @Test(expected = NullPointerException.class) + public void generateXmlFromCsar_nullArtifactSupplied() throws CsarConverterException { + converter.generateXmlFromCsar(null, null, null); + } + + @Test(expected = NullPointerException.class) + public void generateXmlFromCsar_missingName() throws CsarConverterException, IOException { + byte[] csarArchive = new ArtifactTestUtils().loadResource("compressedArtifacts/service-VscpaasTest-csar.csar"); + converter.generateXmlFromCsar(csarArchive, null, null); + } + + @Test(expected = NullPointerException.class) + public void generateXmlFromCsar_missingVersion() throws CsarConverterException, IOException { + byte[] csarArchive = new ArtifactTestUtils().loadResource("compressedArtifacts/service-VscpaasTest-csar.csar"); + converter.generateXmlFromCsar(csarArchive, NAME, null); + } + + @Test(expected = CsarConverterException.class) + public void generateXmlFromCsar_noPayloadExists() throws CsarConverterException { + converter.generateXmlFromCsar(new byte[0], NAME, VERSION); + } + + @Test(expected = CsarConverterException.class) + public void generateXmlFromCsar_csarFileHasNoYmlFiles() throws CsarConverterException, IOException { + byte[] csarArchive = new ArtifactTestUtils().loadResource("compressedArtifacts/noYmlFilesArchive.zip"); + converter.generateXmlFromCsar(csarArchive, "noYmlFilesArchive.zip", VERSION); + } + + @Test + public void generateXmlFromCsar_artifactgenerator_config_systemPropertyNotSet() + throws IOException, XmlArtifactGenerationException, CsarConverterException { + exception.expect(CsarConverterException.class); + exception.expectMessage("Cannot generate artifacts. artifactgenerator.config system property not configured"); + + byte[] csarArchive = + new ArtifactTestUtils().loadResource("compressedArtifacts/service-SdWanServiceTest-csar.csar"); + + // Unset the required system property + System.clearProperty("artifactgenerator.config"); + converter.generateXmlFromCsar(csarArchive, VERSION, "service-SdWanServiceTest-csar.csar"); + } + + @Test + public void generateXmlFromCsar() throws CsarConverterException, IOException, XmlArtifactGenerationException { + byte[] csarArchive = + new ArtifactTestUtils().loadResource("compressedArtifacts/service-SdWanServiceTest-csar.csar"); + + Map expectedXmlFiles = createExpectedXmlFiles(); + List generatedArtifacts = + converter.generateXmlFromCsar(csarArchive, VERSION, "service-SdWanServiceTest-csar.csar"); + + generatedArtifacts.forEach(ga -> { + try { + + String x1 = expectedXmlFiles.get(ga.getName()); + + String x2 = bytesToString(ga.getPayload()); + + assertXMLEqual("The content of " + ga.getName() + " must match the expected content", x1, x2); + + } catch (SAXException | IOException e) { + fail("There was an Exception parsing the XML: "+e.getMessage()); + } + }); + } + + public String bytesToString(byte[] source) { + ByteArrayInputStream bis = new ByteArrayInputStream(Base64.getDecoder().decode(source)); + + String result = new BufferedReader(new InputStreamReader(bis)).lines().collect(Collectors.joining("\n")); + + return result; + + } + + private Map createExpectedXmlFiles() throws IOException { + Map xml = new HashMap<>(); + + ArtifactTestUtils utils = new ArtifactTestUtils(); + + String[] filesToLoad = + {"AAI-SD-WAN-Service-Test-service-1.0.xml", "AAI-SdWanTestVsp..DUMMY..module-0-resource-2.xml", + "AAI-Tunnel_XConnTest-resource-2.0.xml", "AAI-SD-WAN-Test-VSP-resource-1.0.xml"}; + + for (String s : filesToLoad) { + xml.put(s, utils.loadResourceAsString("generatedXml/" + s)); + + } + + return xml; + } +} diff --git a/src/test/java/org/onap/aai/babel/service/TestGenerateArtifactsServiceImpl.java b/src/test/java/org/onap/aai/babel/service/TestGenerateArtifactsServiceImpl.java new file mode 100644 index 0000000..5d2309f --- /dev/null +++ b/src/test/java/org/onap/aai/babel/service/TestGenerateArtifactsServiceImpl.java @@ -0,0 +1,111 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.service; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.stream.Collectors; +import javax.ws.rs.core.Response; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Direct invocation of the generate artifacts service implementation + * + */ +public class TestGenerateArtifactsServiceImpl { + + @BeforeClass + public static void setup() { + URL url = TestGenerateArtifactsServiceImpl.class.getClassLoader().getResource("artifact-generator.properties"); + System.setProperty("artifactgenerator.config", url.getPath()); + } + + @Test + public void testGenerateArtifacts() throws Exception { + String jsonRequest = readstringFromFile("jsonFiles/success_request.json"); + Response response = processJsonRequest(jsonRequest); + assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode())); + assertThat(response.getEntity(), is(readstringFromFile("response/response.json"))); + } + + + @Test + public void testInvalidCsarFile() throws URISyntaxException, IOException{ + String jsonRequest = readstringFromFile("jsonFiles/invalid_csar_request.json"); + Response response = processJsonRequest(jsonRequest); + assertThat(response.getStatus(), is(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode())); + assertThat(response.getEntity(), is("Error converting CSAR artifact to XML model.")); + } + + @Test + public void testInvalidJsonFile() throws URISyntaxException, IOException{ + String jsonRequest = readstringFromFile("jsonFiles/invalid_json_request.json"); + Response response = processJsonRequest(jsonRequest); + assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode())); + assertThat(response.getEntity(), is("Malformed request.")); + } + + @Test + public void testMissingArtifactName() throws Exception { + String jsonRequest = readstringFromFile("jsonFiles/missing_artifact_name_request.json"); + Response response = processJsonRequest(jsonRequest); + assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode())); + assertThat(response.getEntity(), is("No artifact name attribute found in the request body." )); + } + + @Test + public void testMissingArtifactVersion() throws Exception { + String jsonRequest = readstringFromFile("jsonFiles/missing_artifact_version_request.json"); + Response response = processJsonRequest(jsonRequest); + assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode())); + assertThat(response.getEntity(), is("No artifact version attribute found in the request body.")); + } + + @Test + public void testMissingCsarFile() throws Exception { + String jsonRequest = readstringFromFile("jsonFiles/missing_csar_request.json"); + Response response = processJsonRequest(jsonRequest); + assertThat(response.getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode())); + assertThat(response.getEntity(), is("No csar attribute found in the request body.")); + } + + + private Response processJsonRequest(String jsonRequest) { + GenerateArtifactsServiceImpl service = new GenerateArtifactsServiceImpl(/* No authentiction required */ null); + return service.generateArtifacts(jsonRequest); + } + + private String readstringFromFile(String resourceFile) throws IOException, URISyntaxException { + return Files.lines(Paths.get(ClassLoader.getSystemResource(resourceFile).toURI())) + .collect(Collectors.joining()); + } + + +} diff --git a/src/test/java/org/onap/aai/babel/util/ArtifactTestUtils.java b/src/test/java/org/onap/aai/babel/util/ArtifactTestUtils.java new file mode 100644 index 0000000..74f0c0e --- /dev/null +++ b/src/test/java/org/onap/aai/babel/util/ArtifactTestUtils.java @@ -0,0 +1,100 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.util; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.google.common.base.Throwables; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Base64; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.apache.commons.io.IOUtils; +import org.openecomp.sdc.generator.data.Artifact; + +/** + * This class provides some utilities to assist with running tests. + */ +public class ArtifactTestUtils { + + public void performYmlAsserts(List toscaFiles, List ymlPayloadsToLoad) { + assertThat("An unexpected number of yml files have been extracted", toscaFiles.size(), + is(ymlPayloadsToLoad.size())); + + Set ymlPayloads = ymlPayloadsToLoad.stream().map(s -> { + try { + return loadResourceAsString(s); + } catch (IOException e) { + throw Throwables.propagate(e); + } + }).collect(Collectors.toSet()); + + toscaFiles.forEach(ts -> { + boolean payloadFound = false; + + String s = bytesToString(ts.getPayload()); + + for (String ymlPayload : ymlPayloads) { + String tscontent = ymlPayload; + + if (s.endsWith(tscontent)) { + payloadFound = true; + break; + } + } + assertThat("The content of each yml file must match the actual content of the file extracted (" + + ts.getName() + ")", payloadFound, is(true)); + }); + } + + public byte[] loadResource(String resourceName) throws IOException { + + return IOUtils.toByteArray(ArtifactTestUtils.class.getClassLoader().getResource(resourceName)); + } + + public String loadResourceAsString(String resourceName) throws IOException { + + InputStream is = ArtifactTestUtils.class.getClassLoader().getResource(resourceName).openStream(); + + String result = new BufferedReader(new InputStreamReader(is)).lines().collect(Collectors.joining("\n")); + + return result; + + } + + public String bytesToString(byte[] source) { + ByteArrayInputStream bis = new ByteArrayInputStream(Base64.getDecoder().decode(source)); + + String result = new BufferedReader(new InputStreamReader(bis)).lines().collect(Collectors.joining("\n")); + + return result; + + } + +} diff --git a/src/test/java/org/onap/aai/babel/util/TestRequestValidator.java b/src/test/java/org/onap/aai/babel/util/TestRequestValidator.java new file mode 100644 index 0000000..030c24d --- /dev/null +++ b/src/test/java/org/onap/aai/babel/util/TestRequestValidator.java @@ -0,0 +1,72 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 European Software Marketing Ltd. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + * + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.babel.util; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.babel.service.data.BabelRequest; + +public class TestRequestValidator { + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void testMissingArtifactNameExceptionThrown() throws Exception{ + exception.expect(RequestValidationException.class); + exception.expectMessage("No artifact name attribute found in the request body."); + + BabelRequest request = new BabelRequest(); + request.setCsar("UEsDBBQACAgIAGsrz0oAAAAAAAAAAAAAAAAJAAAAY3Nhci5tZXRhC3Z"); + request.setArtifactVersion("1.0"); + request.setArtifactName(null); + RequestValidator.validateRequest(request); + } + + + @Test + public void testMissingArtifactVersionExceptionThrown() throws Exception{ + exception.expect(RequestValidationException.class); + exception.expectMessage("No artifact version attribute found in the request body."); + + BabelRequest request = new BabelRequest(); + request.setCsar("UEsDBBQACAgIAGsrz0oAAAAAAAAAAAAAAAAJAAAAY3Nhci5tZXRhC3Z"); + request.setArtifactVersion(null); + request.setArtifactName("hello"); + RequestValidator.validateRequest(request); + } + + @Test + public void testMissingCsarFile() throws Exception{ + exception.expect(RequestValidationException.class); + exception.expectMessage("No csar attribute found in the request body."); + + BabelRequest request = new BabelRequest(); + request.setCsar(null); + request.setArtifactVersion("1.0"); + request.setArtifactName("hello"); + RequestValidator.validateRequest(request); + } + +} diff --git a/src/test/resources/artifact-generator.properties b/src/test/resources/artifact-generator.properties new file mode 100644 index 0000000..1d7e5fa --- /dev/null +++ b/src/test/resources/artifact-generator.properties @@ -0,0 +1,264 @@ +#action widget details +AAI.model-version-id.action=fd7fb09e-d930-41b9-b83f-cfde9df48640 +AAI.model-invariant-id.action=af593b4b-490e-4665-ad74-2f6351c0a7ce +#action-data widget details +AAI.model-invariant-id.action-data=9551346c-7d8b-4daf-9926-b93e96e2344a +AAI.model-version-id.action-data=2f80c596-27e5-4ca9-b5bb-e03a7fd4c0fd +#allotted-resource widget details +AAI.model-invariant-id.allotted-resource=f6d6a23d-a1a9-48ff-8419-b6530da2d381 +AAI.model-version-id.allotted-resource=7ad0915f-25c0-4a70-b9bc-185a75f87564 +#availability-zone widget details +AAI.model-version-id.availability-zone=6c092fb1-21b2-456b-9e01-67fb4de1896e +AAI.model-invariant-id.availability-zone=61b88c01-d819-41c0-8e21-7fd7ba47148e +#az-and-dvs-switches widget details +AAI.model-version-id.az-and-dvs-switches=b2dea88d-78a0-49bf-95c9-5819df08e966 +AAI.model-invariant-id.az-and-dvs-switches=53dc00d4-e6d9-48ec-b6cc-3d3797e9b896 +#class-of-service widget details +AAI.model-version-id.class-of-service=d2fb27cc-15eb-4c4e-828e-71d41aaecc5b +AAI.model-invariant-id.class-of-service=18094b19-d16d-4822-8acf-e92c6aefa178 +#cloud-region widget details +AAI.model-version-id.cloud-region=2a160989-b202-47dd-874b-4a0f275998f7 +AAI.model-invariant-id.cloud-region=425b2158-e51d-4509-9945-dad4556474a3 +#complex widget details +AAI.model-invariant-id.complex=af91c2f7-35fc-43cf-a13d-443f385b2353 +AAI.model-version-id.complex=3a8ab1ee-9220-4fe8-b89c-9251d160ddc2 +#connector widget details +AAI.model-version-id.connector=22104c9f-29fd-462f-be07-96cd6b46dd33 +AAI.model-invariant-id.connector=4c01c948-7607-4d66-8a6c-99c2c2717936 +#constrained-element-set widget details +AAI.model-invariant-id.constrained-element-set=c0292b4f-ee97-40cc-8c2e-f967c48f5701 +AAI.model-version-id.constrained-element-set=01102126-9c04-4a89-945b-b131e61e95d7 +#ctag-assignment widget details +AAI.model-version-id.ctag-assignment=44e5cb1f-0938-41aa-b766-d4595109fe89 +AAI.model-invariant-id.ctag-assignment=fcb8d46b-b656-4ad6-8fa4-22cef74b443f +#ctag-pool widget details +AAI.model-invariant-id.ctag-pool=46c51d4e-d67e-4a9c-b1f5-49b1e9c6fcaa +AAI.model-version-id.ctag-pool=2056c41f-23b9-4de7-9f50-819adad37d76 +#customer widget details +AAI.model-invariant-id.customer=c1d4305f-cdbd-4bbe-9069-a2f4978fd89e +AAI.model-version-id.customer=d4df5c27-98a1-4812-a8aa-c17f055b7a3f +#cvlan-tag-entry widget details +AAI.model-version-id.cvlan-tag-entry=c3878ffb-8d85-4114-bee6-e4074a9db10b +AAI.model-invariant-id.cvlan-tag-entry=245cf4b0-7cc5-4eea-bbd9-753e939adcab +#dvs-switch widget details +AAI.model-invariant-id.dvs-switch=98fbb471-1f86-428e-bd8a-c8a25de6fa23 +AAI.model-version-id.dvs-switch=4cb44ae8-e3ab-452a-9f95-bcc8a44c55ea +#edge-prop-names widget details +AAI.model-invariant-id.edge-prop-names=7a08cad4-8759-46a5-8245-095d1ba57ac6 +AAI.model-version-id.edge-prop-names=f0442326-8201-4d0e-857c-74b4ddcbfc9f +#element-choice-set widget details +AAI.model-invariant-id.element-choice-set=9a011958-7165-47a3-b872-00951d1f09ae +AAI.model-version-id.element-choice-set=af27fbfd-598d-44da-aeae-0f9d3a5fcd6a +#entitlement widget details +AAI.model-version-id.entitlement=7e27ba2e-b7db-4e13-9fae-d142152ef98a +AAI.model-invariant-id.entitlement=ae75b5a0-d5e1-4f3a-b8fb-37626a753da3 +#flavor widget details +AAI.model-invariant-id.flavor=bace8d1c-a261-4041-9e37-823117415d0f +AAI.model-version-id.flavor=36200fb5-f251-4f5d-a520-7c5ad5c2cd4b +#generic-vnf widget details +AAI.model-version-id.generic-vnf=93a6166f-b3d5-4f06-b4ba-aed48d009ad9 +AAI.model-invariant-id.generic-vnf=acc6edd8-a8d4-4b93-afaa-0994068be14c +#group-assignment widget details +AAI.model-invariant-id.group-assignment=7cc05f25-7ba2-42b7-a237-c5662a1689e1 +AAI.model-version-id.group-assignment=fe578080-ce19-4604-8760-fc264fbb2565 +#image widget details +AAI.model-version-id.image=f6a038c2-820c-42ba-8c2b-375e24e8f932 +AAI.model-invariant-id.image=3f4c7204-739b-4bbb-87a7-8a6856439c90 +#include-node-filter widget details +AAI.model-invariant-id.include-node-filter=2a2d8ad2-af0a-4e1f-9982-0c899e7dc827 +AAI.model-version-id.include-node-filter=f05f804d-7057-4ffe-bdc5-39f2f0c9c9fd +#instance-group widget details +AAI.model-version-id.instance-group=8e6ee9dc-9017-444a-83b3-219edb018128 +AAI.model-invariant-id.instance-group=3bf1e610-45f7-4ad6-b833-ca4c5ee6a3fd +#inventory-item widget details +AAI.model-invariant-id.inventory-item=cd57d844-9017-4078-aa19-926935a3d77c +AAI.model-version-id.inventory-item=69957f4a-2155-4b95-8d72-d6dd9b88b27b +#inventory-item-data widget details +AAI.model-version-id.inventory-item-data=0e54bb87-bd6e-4a2b-ad1c-6d935b87ae51 +AAI.model-invariant-id.inventory-item-data=87a383ae-cf03-432e-a9de-04e6a622d0fd +#ipsec-configuration widget details +AAI.model-invariant-id.ipsec-configuration=aca4c310-cb45-42bd-9f88-73e40ba7b962 +AAI.model-version-id.ipsec-configuration=d949fd10-36bf-408a-ac7a-cad5004d2e0d +#key-data widget details +AAI.model-version-id.key-data=c23ea04d-1a3b-453d-bc49-a6c783a5e92b +AAI.model-invariant-id.key-data=f5faa464-c2f2-4cc3-89d2-a90452dc3a07 +#l3-interface-ipv4-address-list widget details +AAI.model-version-id.l3-interface-ipv4-address-list=41e76b6f-1e06-4fd4-82cd-81c50fc4574b +AAI.model-invariant-id.l3-interface-ipv4-address-list=aad85df2-09be-40fa-b867-16415e4e10e2 +#l3-interface-ipv6-address-list widget details +AAI.model-invariant-id.l3-interface-ipv6-address-list=82966045-43ee-4982-8307-7e9610866140 +AAI.model-version-id.l3-interface-ipv6-address-list=d040621d-541a-477b-bb1b-a2b61b14e295 +#l3-network widget details +AAI.model-version-id.l3-network=9111f20f-e680-4001-b83f-19a2fc23bfc1 +AAI.model-invariant-id.l3-network=3d560d81-57d0-438b-a2a1-5334dba0651a +#lag-interface widget details +AAI.model-version-id.lag-interface=ce95f7c3-b61b-4758-ae9e-7e943b1c103d +AAI.model-invariant-id.lag-interface=e0ee9bde-c1fc-4651-a95d-8e0597bf7d70 +#lag-link widget details +AAI.model-version-id.lag-link=d29a087a-af59-4053-a3f8-0f95a92faa75 +AAI.model-invariant-id.lag-link=86ffe6e5-4d0e-4cec-80b5-5c38aa3eff98 +#license widget details +AAI.model-invariant-id.license=b9a9b337-1f86-42d3-b9f9-f987a089507c +AAI.model-version-id.license=6889274b-a1dc-40ab-9090-93677e13e2e6 +#license-key-resource widget details +AAI.model-invariant-id.license-key-resource=9022ebfe-b54f-4911-a6b2-8c3f5ec189b7 +AAI.model-version-id.license-key-resource=24b25f8c-b8bd-4c62-9421-87c12667aac9 +#l-interface widget details +AAI.model-version-id.l-interface=a32613fd-18b9-459e-aab8-fffb3912966a +AAI.model-invariant-id.l-interface=cea0a982-8d55-4093-921e-418fbccf7060 +#logical-link widget details +AAI.model-version-id.logical-link=a1481a38-f8ba-4ae4-bdf1-06c2c6af4c54 +AAI.model-invariant-id.logical-link=fe012535-2c31-4a39-a739-612374c638a0 +#metadatum widget details +AAI.model-invariant-id.metadatum=86dbb63a-265e-4614-993f-6771c30b56a5 +AAI.model-version-id.metadatum=6bae950e-8939-41d3-a6a7-251b03e4c1fc +#model widget details +AAI.model-invariant-id.model=06d1418a-5faa-452d-a94b-a2829df5f67b +AAI.model-version-id.model=1f51c05c-b164-4c27-9c03-5cbb239fd6be +#model-constraint widget details +AAI.model-invariant-id.model-constraint=c28966f3-e758-4483-b37b-a90b05d3dd33 +AAI.model-version-id.model-constraint=ad70dd19-f156-4fb5-a865-97b5563b0d37 +#model-element widget details +AAI.model-invariant-id.model-element=2076e726-3577-477a-a300-7fa65cd4df11 +AAI.model-version-id.model-element=753e813a-ba9e-4a1d-ab34-b2f6dc6eec0c +#multicast-configuration widget details +AAI.model-invariant-id.multicast-configuration=ea78c9e3-514d-4a0a-9162-13837fa54c35 +AAI.model-version-id.multicast-configuration=666a06ee-4b57-46df-bacf-908da8f10c3f +#named-query widget details +AAI.model-version-id.named-query=5c3b7c33-afa3-4be5-8da7-1a5ac6f99896 +AAI.model-invariant-id.named-query=80b712fd-0ad3-4180-a99c-8c995cf1cc32 +#named-query-element widget details +AAI.model-version-id.named-query-element=204c641a-3494-48c8-979a-86856f5fd32a +AAI.model-invariant-id.named-query-element=3c504d40-b847-424c-9d25-4fb7e0a3e994 +#network-policy widget details +AAI.model-invariant-id.network-policy=6aa05779-94d7-4d8b-9bee-59ef2ab0c246 +AAI.model-version-id.network-policy=a0ccd9dc-7062-4940-9bcc-e91dd28af510 +#network-profile widget details +AAI.model-version-id.network-profile=01f45471-4240-498c-a9e1-235dc0b8b4a6 +AAI.model-invariant-id.network-profile=2734b44a-b8a2-40f6-957d-6256589e5d00 +#newvce widget details +AAI.model-version-id.newvce=7c79e11f-a408-4593-aa86-ba948a1236af +AAI.model-invariant-id.newvce=4b05ec9c-c55d-4987-83ff-e08d6ddb694f +#oam-network widget details +AAI.model-invariant-id.oam-network=2851cf01-9c40-4064-87d4-6184a6fcff35 +AAI.model-version-id.oam-network=f4fb34f3-fd6e-4a8f-a3fb-4ab61a343b79 +#physical-link widget details +AAI.model-invariant-id.physical-link=c822d81f-822f-4304-9623-1025b53da568 +AAI.model-version-id.physical-link=9c523936-95b4-4d7f-9f53-6bdfe0cf2c05 +#p-interface widget details +AAI.model-invariant-id.p-interface=94043c37-4e73-439c-a790-0fdd697924cd +AAI.model-version-id.p-interface=d2cdb2d0-fc1f-4a57-a89e-591b1c4e3754 +#pnf widget details +AAI.model-version-id.pnf=e9f1fa7d-c839-418a-9601-03dc0d2ad687 +AAI.model-invariant-id.pnf=862b25a1-262a-4961-bdaa-cdc55d69785a +#port-group widget details +AAI.model-version-id.port-group=03e8bb6b-b48a-46ae-b5d4-e5af577e6844 +AAI.model-invariant-id.port-group=8ce940fb-55d7-4230-9e7f-a56cc2741f77 +#property-constraint widget details +AAI.model-version-id.property-constraint=81706bbd-981e-4362-ae20-995cbcb2d995 +AAI.model-invariant-id.property-constraint=f4a863c3-6886-470a-a6ae-05723837ea45 +#pserver widget details +AAI.model-invariant-id.pserver=6d932c8f-463b-4e76-83fb-87acfbaa2e2d +AAI.model-version-id.pserver=72f0d495-bc27-4653-9e1a-eef76bd34bc9 +#related-lookup widget details +AAI.model-invariant-id.related-lookup=468f6f5b-2996-41bb-b2a3-7cf9613ebb9b +AAI.model-version-id.related-lookup=0988bab5-bf4f-4938-a419-ab249867d12a +#reserved-prop-names widget details +AAI.model-invariant-id.reserved-prop-names=0c3e0ba3-618c-498d-9127-c8d42b00170f +AAI.model-version-id.reserved-prop-names=ac49d26d-9163-430e-934a-13b738a04f5c +#result-data widget details +AAI.model-version-id.result-data=4e9b50aa-5227-4f6f-b489-62e6bbc03c79 +AAI.model-invariant-id.result-data=ff656f23-6185-406f-9006-4b26834f3e1c +#route-table-reference widget details +AAI.model-version-id.route-table-reference=fed7e326-03a7-45ff-a3f2-471470d268c4 +AAI.model-invariant-id.route-table-reference=a8614b63-2636-4c4f-98df-fd448c4241db +#routing-instance widget details +AAI.model-invariant-id.routing-instance=1c2ded4f-8b01-4193-829c-966847dfec3e +AAI.model-version-id.routing-instance=3ccbcbc7-d19e-44d5-a52f-7e18aa8d69fa +#secondary-filter widget details +AAI.model-version-id.secondary-filter=1380619d-dd1a-4cec-b755-c6407833e065 +AAI.model-invariant-id.secondary-filter=738ff299-6290-4c00-8998-bd0e96a07b93 +#segmentation-assignment widget details +AAI.model-invariant-id.segmentation-assignment=6e814aee-46e1-4583-a9d4-0049bfd2b59b +AAI.model-version-id.segmentation-assignment=c5171ae0-44fb-4c04-b482-d56702241a44 +#service widget details +AAI.model-version-id.service=ecce2c42-3957-4ae0-9442-54bc6afe27b6 +AAI.model-invariant-id.service=07a3a60b-1b6c-4367-8173-8014386f89e3 +#service-capability widget details +AAI.model-invariant-id.service-capability=b1a7cc05-d19d-443b-a5d1-733e325c4232 +AAI.model-version-id.service-capability=f9cfec1b-18da-4bba-bd83-4b26cca115cd +#service-instance widget details +AAI.model-invariant-id.service-instance=82194af1-3c2c-485a-8f44-420e22a9eaa4 +AAI.model-version-id.service-instance=46b92144-923a-4d20-b85a-3cbd847668a9 +#service-subscription widget details +AAI.model-invariant-id.service-subscription=2e1a602a-acd8-4f78-94ff-618b802a303b +AAI.model-version-id.service-subscription=5e68299a-79f2-4bfb-8fbc-2bae877a2459 +#site-pair widget details +AAI.model-version-id.site-pair=7106bc02-6552-4fc3-8a56-4f3df9034531 +AAI.model-invariant-id.site-pair=db63f3e6-f8d1-484e-8d5e-191600b7914b +#site-pair-set widget details +AAI.model-invariant-id.site-pair-set=5d4dae3e-b402-4bfd-909e-ece12ff75d26 +AAI.model-version-id.site-pair-set=a5c6c1bc-dc38-468e-9459-bb08f87247df +#snapshot widget details +AAI.model-version-id.snapshot=962a7c8b-687f-4d32-a775-fe098e214bcd +AAI.model-invariant-id.snapshot=24de00ef-aead-4b52-995b-0adf8d4bd90d +#sriov-vf widget details +AAI.model-version-id.sriov-vf=1e8b331f-3d4a-4160-b7aa-f4d5a8916625 +AAI.model-invariant-id.sriov-vf=04b2935f-33c4-40a9-8af0-8b52690042dc +#start-node-filter widget details +AAI.model-version-id.start-node-filter=aad96fd3-e75f-42fc-9777-3450c36f1168 +AAI.model-invariant-id.start-node-filter=083093a3-e407-447a-ba5d-7583e4d23e1d +#subnet widget details +AAI.model-version-id.subnet=f902a6bc-6be4-4fe5-8458-a6ec0056b374 +AAI.model-invariant-id.subnet=1b2c9ba7-e449-4831-ba15-3073672f5ef2 +#tagged-inventory-item-list widget details +AAI.model-invariant-id.tagged-inventory-item-list=e78a7eaa-f65d-4919-9c2b-5b258c8c4d7e +AAI.model-version-id.tagged-inventory-item-list=c246f6e2-e3a1-4697-94c0-5672a7fbbf04 +#tenant widget details +AAI.model-invariant-id.tenant=97c26c99-6870-44c1-8a07-1d900d3f4ce6 +AAI.model-version-id.tenant=abcc54bc-bb74-49dc-9043-7f7171707545 +#tunnel-xconnect widget details +AAI.model-invariant-id.tunnel-xconnect=50b9e2fa-005c-4bbe-b651-3251dece4cd8 +AAI.model-version-id.tunnel-xconnect=e7cb4ca8-e1a5-4487-a716-4ae0bcd8aef5 +#update-node-key widget details +AAI.model-version-id.update-node-key=6004cfa6-eb6d-4062-971f-b1fde6b74aa0 +AAI.model-invariant-id.update-node-key=fe81c801-f65d-408a-b2b7-a729a18f8154 +#vce widget details +AAI.model-version-id.vce=b6cf54b5-ec45-43e1-be64-97b4e1513333 +AAI.model-invariant-id.vce=bab6dceb-e7e6-4301-a5e0-a7399b48d792 +#vf-module widget details +AAI.model-invariant-id.vf-module=ef86f9c5-2165-44f3-8fc3-96018b609ea5 +AAI.model-version-id.vf-module=c00563ae-812b-4e62-8330-7c4d0f47088a +#vig-server widget details +AAI.model-version-id.vig-server=8e8c22f1-fbdf-48ea-844c-8bdeb44e7b16 +AAI.model-invariant-id.vig-server=bed7c3b7-35d0-4cd9-abde-41b20e68b28e +#virtual-data-center widget details +AAI.model-invariant-id.virtual-data-center=5150abcf-0c5f-4593-9afe-a19c48fc4824 +AAI.model-version-id.virtual-data-center=6dd43ced-d789-47af-a759-d3abc14e3ac1 +#vlan widget details +AAI.model-version-id.vlan=257d88a5-a269-4c35-944f-aca04fbdb791 +AAI.model-invariant-id.vlan=d2b1eaf1-ae59-4116-9ee4-aa0179faa4f8 +#vnfc widget details +AAI.model-invariant-id.vnfc=96129eb9-f0de-4e05-8af2-73146473f766 +AAI.model-version-id.vnfc=5761e0a7-c6df-4d8a-9ebd-b8f445054dec +#vnf-image widget details +AAI.model-invariant-id.vnf-image=f9a628ff-7aa0-40e2-a93d-02d91c950982 +AAI.model-version-id.vnf-image=c4d3e747-ba4a-4b17-9896-94c6f18c19d3 +#volume widget details +AAI.model-version-id.volume=0fbe2e8f-4d91-4415-a772-88387049b38d +AAI.model-invariant-id.volume=ddd739b4-2b25-46c4-affc-41a32af5cc42 +#volume-group widget details +AAI.model-invariant-id.volume-group=fcec1b02-b2d0-4834-aef8-d71be04717dd +AAI.model-version-id.volume-group=99d44c90-1f61-4418-b9a6-56586bf38c79 +#vpe widget details +AAI.model-invariant-id.vpe=053ec3a7-5b72-492d-b54d-123805a9b967 +AAI.model-version-id.vpe=203817d3-829c-42d4-942d-2a935478e993 +#vpls-pe widget details +AAI.model-version-id.vpls-pe=b1566228-6785-4ce1-aea2-053736f80341 +AAI.model-invariant-id.vpls-pe=457ba89b-334c-4fbd-acc4-160ac0e0cdc0 +#vpn-binding widget details +AAI.model-invariant-id.vpn-binding=9e23b675-db2b-488b-b459-57aa9857baa0 +AAI.model-version-id.vpn-binding=21a146e5-9901-448c-9197-723076770119 +#vserver widget details +AAI.model-invariant-id.vserver=ff69d4e0-a8e8-4108-bdb0-dd63217e63c7 +AAI.model-version-id.vserver=8ecb2c5d-7176-4317-a255-26274edfdd53 \ No newline at end of file diff --git a/src/test/resources/auth/auth_policy.json b/src/test/resources/auth/auth_policy.json new file mode 100644 index 0000000..a0496b7 --- /dev/null +++ b/src/test/resources/auth/auth_policy.json @@ -0,0 +1,55 @@ +{"roles": [ + { + "name": "admin", + "functions": [ + { + "name": "actions", + "methods": [ + {"name": "GET"}, + {"name": "DELETE"}, + {"name": "PUT"} + ] + }, + { + "name": "getAndPublish", + "methods": [{"name": "POST"}] + } + ], + "users": [ + {"username": "CN=common-name, OU=org-unit, O=org, L=location, ST=state, C=US"}, + {"username": "CN=test, OU=qa, O=Test Ltd, L=London, ST=London, C=GB"} + ] + }, + { + "name": "ops", + "functions": [{ + "name": "actions", + "methods": [{"name": "POST"}] + }], + "users": [ + {"username": "CN=common-name, OU=org-unit, O=org, L=location, ST=state, C=US"}, + {"username": "CN=test, OU=qa, O=Test Ltd, L=London, ST=London, C=GB"} + ] + }, + { + "name": "basicauth", + "functions": [{ + "name": "util", + "methods": [{"name": "GET"}] + }], + "users": [{ + "user": "aai", + "pass": "OBF:1u2a1t2v1vgb1s3g1s3m1vgj1t3b1u30" + }] + }, + { + "name": "nofuncauth", + "functions": [{ + "name": "nofuncutil" + }], + "users": [{ + "user": "aai", + "pass": "OBF:1u2a1t2v1vgb1s3g1s3m1vgj1t3b1u30" + }] + } +]} diff --git a/src/test/resources/compressedArtifacts/noYmlFilesArchive.zip b/src/test/resources/compressedArtifacts/noYmlFilesArchive.zip new file mode 100644 index 0000000000000000000000000000000000000000..4fb37c27015f6af9d49ac82733c8682179c25f7b GIT binary patch literal 762 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 VpF|u00QjHX;!g?yg!`}2{|5>x2fP3P literal 0 HcmV?d00001 diff --git a/src/test/resources/generatedXml/AAI-SD-WAN-Service-Test-service-1.0.xml b/src/test/resources/generatedXml/AAI-SD-WAN-Service-Test-service-1.0.xml new file mode 100644 index 0000000..7748998 --- /dev/null +++ b/src/test/resources/generatedXml/AAI-SD-WAN-Service-Test-service-1.0.xml @@ -0,0 +1,69 @@ + + 1c111111-1111-1111-1111-111111111111 + service + + + 2c111111-1111-1111-1111-111111111111 + SD-WAN-Service-Test + 1.0 + SD-WAN-Service-Test + + + T + unbounded + + + T + unbounded + + + + model-ver + + model-ver.model-version-id + 2a111111-1111-1111-1111-111111111111 + + + model.model-invariant-id + 1a111111-1111-1111-1111-111111111111 + + + + + + T + unbounded + + + + model-ver + + model-ver.model-version-id + 2b111111-1111-1111-1111-111111111111 + + + model.model-invariant-id + 1b111111-1111-1111-1111-111111111111 + + + + + + + + model-ver + + model-ver.model-version-id + 46b92144-923a-4d20-b85a-3cbd847668a9 + + + model.model-invariant-id + 82194af1-3c2c-485a-8f44-420e22a9eaa4 + + + + + + + + diff --git a/src/test/resources/generatedXml/AAI-SD-WAN-Test-VSP-resource-1.0.xml b/src/test/resources/generatedXml/AAI-SD-WAN-Test-VSP-resource-1.0.xml new file mode 100644 index 0000000..1cd85e8 --- /dev/null +++ b/src/test/resources/generatedXml/AAI-SD-WAN-Test-VSP-resource-1.0.xml @@ -0,0 +1,51 @@ + + 1a111111-1111-1111-1111-111111111111 + resource + + + 2a111111-1111-1111-1111-111111111111 + SD-WAN-Test-VSP + 1.0 + SD-WAN-Test-VSP + + + T + unbounded + + + T + unbounded + + + + model-ver + + model-ver.model-version-id + 7a111111-1111-1111-1111-111111111111 + + + model.model-invariant-id + 6a111111-1111-1111-1111-111111111111 + + + + + + + + model-ver + + model-ver.model-version-id + 93a6166f-b3d5-4f06-b4ba-aed48d009ad9 + + + model.model-invariant-id + acc6edd8-a8d4-4b93-afaa-0994068be14c + + + + + + + + diff --git a/src/test/resources/generatedXml/AAI-SdWanTestVsp..DUMMY..module-0-resource-2.xml b/src/test/resources/generatedXml/AAI-SdWanTestVsp..DUMMY..module-0-resource-2.xml new file mode 100644 index 0000000..6e221ce --- /dev/null +++ b/src/test/resources/generatedXml/AAI-SdWanTestVsp..DUMMY..module-0-resource-2.xml @@ -0,0 +1,123 @@ + + 6a111111-1111-1111-1111-111111111111 + resource + + + 7a111111-1111-1111-1111-111111111111 + SdWanTestVsp..DUMMY..module-0 + 2 + + + T + unbounded + + + T + unbounded + + + F + unbounded + + + + model-ver + + model-ver.model-version-id + f6a038c2-820c-42ba-8c2b-375e24e8f932 + + + model.model-invariant-id + 3f4c7204-739b-4bbb-87a7-8a6856439c90 + + + + + + F + unbounded + + + + model-ver + + model-ver.model-version-id + abcc54bc-bb74-49dc-9043-7f7171707545 + + + model.model-invariant-id + 97c26c99-6870-44c1-8a07-1d900d3f4ce6 + + + + + + F + unbounded + + + + model-ver + + model-ver.model-version-id + 36200fb5-f251-4f5d-a520-7c5ad5c2cd4b + + + model.model-invariant-id + bace8d1c-a261-4041-9e37-823117415d0f + + + + + + T + unbounded + + + + model-ver + + model-ver.model-version-id + 5761e0a7-c6df-4d8a-9ebd-b8f445054dec + + + model.model-invariant-id + 96129eb9-f0de-4e05-8af2-73146473f766 + + + + + + + + model-ver + + model-ver.model-version-id + 8ecb2c5d-7176-4317-a255-26274edfdd53 + + + model.model-invariant-id + ff69d4e0-a8e8-4108-bdb0-dd63217e63c7 + + + + + + + + model-ver + + model-ver.model-version-id + c00563ae-812b-4e62-8330-7c4d0f47088a + + + model.model-invariant-id + ef86f9c5-2165-44f3-8fc3-96018b609ea5 + + + + + + + + diff --git a/src/test/resources/generatedXml/AAI-Tunnel_XConnTest-resource-2.0.xml b/src/test/resources/generatedXml/AAI-Tunnel_XConnTest-resource-2.0.xml new file mode 100644 index 0000000..ccecc80 --- /dev/null +++ b/src/test/resources/generatedXml/AAI-Tunnel_XConnTest-resource-2.0.xml @@ -0,0 +1,69 @@ + + 1b111111-1111-1111-1111-111111111111 + resource + + + 2b111111-1111-1111-1111-111111111111 + Tunnel_XConnTest + 2.0 + Tunnel_XConnTest + + + T + unbounded + + + F + unbounded + + + + model-ver + + model-ver.model-version-id + 7b111111-1111-1111-1111-111111111111 + + + model.model-invariant-id + 6b111111-1111-1111-1111-111111111111 + + + + + + T + unbounded + + + + model-ver + + model-ver.model-version-id + e7cb4ca8-e1a5-4487-a716-4ae0bcd8aef5 + + + model.model-invariant-id + 50b9e2fa-005c-4bbe-b651-3251dece4cd8 + + + + + + + + model-ver + + model-ver.model-version-id + 7ad0915f-25c0-4a70-b9bc-185a75f87564 + + + model.model-invariant-id + f6d6a23d-a1a9-48ff-8419-b6530da2d381 + + + + + + + + diff --git a/src/test/resources/jsonFiles/invalid_csar_request.json b/src/test/resources/jsonFiles/invalid_csar_request.json new file mode 100644 index 0000000..3742f36 --- /dev/null +++ b/src/test/resources/jsonFiles/invalid_csar_request.json @@ -0,0 +1,3 @@ +{"csar": "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SVBfTXV4X0RlbXV4LXVwZGF0ZWQtcmVzb3VyY2UtMS4wLnhtbFBLAQIUABQACAgIAP2uhEoPxTTMggIAAN4PAAA7AAAAAAAAAAAAAAAAADY3AABBcnRpZmFjdHMvQUFJLVR1bm5lbF9YQ29ubi1mb3ItREhWLVRlc3RpbmctcmVzb3VyY2UtMS4wLnhtbFBLAQIUABQACAgIAP2uhEott6ixQgIAAEULAAA5AAAAAAAAAAAAAAAAACE6AABBcnRpZmFjdHMvQUFJLVNlcnZpY2VfQWRtaW4tZm9yLURIVi1UZXN0LXJlc291cmNlLTEuMC54bWxQSwECFAAUAAgICAD9roRKhVs/IKwDAABhJQAAQAAAAAAAAAAAAAAAAADKPAAAQXJ0aWZhY3RzL0FBSS1WaG5mRm9yRTJlVGVzdC4uYmFzZV9URVNULi5tb2R1bGUtMC1yZXNvdXJjZS0yLnhtbFBLAQIUABQACAgIAP2uhEpIeXXPNgIAADELAAAwAAAAAAAAAAAAAAAAAORAAABBcnRpZmFjdHMvQUFJLXZITkYtZm9yLURIVi1UZXN0LXJlc291cmNlLTIuMC54bWxQSwUGAAAAAAwADACcBAAAeEMAAAAA", + "artifactVersion":"1.0", + "artifactName":"hello"} \ No newline at end of file diff --git a/src/test/resources/jsonFiles/invalid_json_request.json b/src/test/resources/jsonFiles/invalid_json_request.json new file mode 100644 index 0000000..4600202 --- /dev/null +++ b/src/test/resources/jsonFiles/invalid_json_request.json @@ -0,0 +1,3 @@ +{"csar": "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QUktSVBfTXV4X0RlbXV4LXVwZGF0ZWQtcmVzb3VyY2UtMS4wLnhtbFBLAQIUABQACAgIAP2uhEoPxTTMggIAAN4PAAA7AAAAAAAAAAAAAAAAADY3AABBcnRpZmFjdHMvQUFJLVR1bm5lbF9YQ29ubi1mb3ItREhWLVRlc3RpbmctcmVzb3VyY2UtMS4wLnhtbFBLAQIUABQACAgIAP2uhEott6ixQgIAAEULAAA5AAAAAAAAAAAAAAAAACE6AABBcnRpZmFjdHMvQUFJLVNlcnZpY2VfQWRtaW4tZm9yLURIVi1UZXN0LXJlc291cmNlLTEuMC54bWxQSwECFAAUAAgICAD9roRKhVs/IKwDAABhJQAAQAAAAAAAAAAAAAAAAADKPAAAQXJ0aWZhY3RzL0FBSS1WaG5mRm9yRTJlVGVzdC4uYmFzZV9URVNULi5tb2R1bGUtMC1yZXNvdXJjZS0yLnhtbFBLAQIUABQACAgIAP2uhEpIeXXPNgIAADELAAAwAAAAAAAAAAAAAAAAAORAAABBcnRpZmFjdHMvQUFJLXZITkYtZm9yLURIVi1UZXN0LXJlc291cmNlLTIuMC54bWxQSwUGAAAAAAwADACcBAAAeEMAAAAA", + "artifactVersion":"1.0", + "artifactName":"hello" \ No newline at end of file diff --git a/src/test/resources/jsonFiles/missing_artifact_name_request.json b/src/test/resources/jsonFiles/missing_artifact_name_request.json new file mode 100644 index 0000000..a5f4948 --- /dev/null +++ b/src/test/resources/jsonFiles/missing_artifact_name_request.json @@ -0,0 +1,3 @@ +{"csar": "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QUktSVBfTXV4X0RlbXV4LXVwZGF0ZWQtcmVzb3VyY2UtMS4wLnhtbFBLAQIUABQACAgIAP2uhEoPxTTMggIAAN4PAAA7AAAAAAAAAAAAAAAAADY3AABBcnRpZmFjdHMvQUFJLVR1bm5lbF9YQ29ubi1mb3ItREhWLVRlc3RpbmctcmVzb3VyY2UtMS4wLnhtbFBLAQIUABQACAgIAP2uhEott6ixQgIAAEULAAA5AAAAAAAAAAAAAAAAACE6AABBcnRpZmFjdHMvQUFJLVNlcnZpY2VfQWRtaW4tZm9yLURIVi1UZXN0LXJlc291cmNlLTEuMC54bWxQSwECFAAUAAgICAD9roRKhVs/IKwDAABhJQAAQAAAAAAAAAAAAAAAAADKPAAAQXJ0aWZhY3RzL0FBSS1WaG5mRm9yRTJlVGVzdC4uYmFzZV9URVNULi5tb2R1bGUtMC1yZXNvdXJjZS0yLnhtbFBLAQIUABQACAgIAP2uhEpIeXXPNgIAADELAAAwAAAAAAAAAAAAAAAAAORAAABBcnRpZmFjdHMvQUFJLXZITkYtZm9yLURIVi1UZXN0LXJlc291cmNlLTIuMC54bWxQSwUGAAAAAAwADACcBAAAeEMAAAAA", + "artifactVersion":"1.0" + } \ No newline at end of file diff --git a/src/test/resources/jsonFiles/missing_artifact_version_request.json b/src/test/resources/jsonFiles/missing_artifact_version_request.json new file mode 100644 index 0000000..cfde298 --- /dev/null +++ b/src/test/resources/jsonFiles/missing_artifact_version_request.json @@ -0,0 +1,2 @@ +{"csar": "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QUktSVBfTXV4X0RlbXV4LXVwZGF0ZWQtcmVzb3VyY2UtMS4wLnhtbFBLAQIUABQACAgIAP2uhEoPxTTMggIAAN4PAAA7AAAAAAAAAAAAAAAAADY3AABBcnRpZmFjdHMvQUFJLVR1bm5lbF9YQ29ubi1mb3ItREhWLVRlc3RpbmctcmVzb3VyY2UtMS4wLnhtbFBLAQIUABQACAgIAP2uhEott6ixQgIAAEULAAA5AAAAAAAAAAAAAAAAACE6AABBcnRpZmFjdHMvQUFJLVNlcnZpY2VfQWRtaW4tZm9yLURIVi1UZXN0LXJlc291cmNlLTEuMC54bWxQSwECFAAUAAgICAD9roRKhVs/IKwDAABhJQAAQAAAAAAAAAAAAAAAAADKPAAAQXJ0aWZhY3RzL0FBSS1WaG5mRm9yRTJlVGVzdC4uYmFzZV9URVNULi5tb2R1bGUtMC1yZXNvdXJjZS0yLnhtbFBLAQIUABQACAgIAP2uhEpIeXXPNgIAADELAAAwAAAAAAAAAAAAAAAAAORAAABBcnRpZmFjdHMvQUFJLXZITkYtZm9yLURIVi1UZXN0LXJlc291cmNlLTIuMC54bWxQSwUGAAAAAAwADACcBAAAeEMAAAAA", + "artifactName":"hello"} \ No newline at end of file diff --git a/src/test/resources/jsonFiles/missing_csar_request.json b/src/test/resources/jsonFiles/missing_csar_request.json new file mode 100644 index 0000000..e65eb4c --- /dev/null +++ b/src/test/resources/jsonFiles/missing_csar_request.json @@ -0,0 +1,2 @@ +{"artifactVersion":"1.0", + "artifactName":"hello"} \ No newline at end of file diff --git a/src/test/resources/jsonFiles/success_request.json b/src/test/resources/jsonFiles/success_request.json new file mode 100644 index 0000000..92fa93d --- /dev/null +++ b/src/test/resources/jsonFiles/success_request.json @@ -0,0 +1,3 @@ +{"csar": "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QUktSVBfTXV4X0RlbXV4LXVwZGF0ZWQtcmVzb3VyY2UtMS4wLnhtbFBLAQIUABQACAgIAP2uhEoPxTTMggIAAN4PAAA7AAAAAAAAAAAAAAAAADY3AABBcnRpZmFjdHMvQUFJLVR1bm5lbF9YQ29ubi1mb3ItREhWLVRlc3RpbmctcmVzb3VyY2UtMS4wLnhtbFBLAQIUABQACAgIAP2uhEott6ixQgIAAEULAAA5AAAAAAAAAAAAAAAAACE6AABBcnRpZmFjdHMvQUFJLVNlcnZpY2VfQWRtaW4tZm9yLURIVi1UZXN0LXJlc291cmNlLTEuMC54bWxQSwECFAAUAAgICAD9roRKhVs/IKwDAABhJQAAQAAAAAAAAAAAAAAAAADKPAAAQXJ0aWZhY3RzL0FBSS1WaG5mRm9yRTJlVGVzdC4uYmFzZV9URVNULi5tb2R1bGUtMC1yZXNvdXJjZS0yLnhtbFBLAQIUABQACAgIAP2uhEpIeXXPNgIAADELAAAwAAAAAAAAAAAAAAAAAORAAABBcnRpZmFjdHMvQUFJLXZITkYtZm9yLURIVi1UZXN0LXJlc291cmNlLTIuMC54bWxQSwUGAAAAAAwADACcBAAAeEMAAAAA", + "artifactVersion":"1.0", + "artifactName":"hello"} \ No newline at end of file diff --git a/src/test/resources/response/response.json b/src/test/resources/response/response.json new file mode 100644 index 0000000..8b98d17 --- /dev/null +++ b/src/test/resources/response/response.json @@ -0,0 +1 @@ +[{"name":"AAI-SD-WAN Service for Testing-service-1.0.xml","type":"MODEL_INVENTORY_PROFILE","payload":[80,71,49,118,90,71,86,115,73,72,104,116,98,71,53,122,80,83,74,111,100,72,82,119,79,105,56,118,98,51,74,110,76,109,57,119,90,87,53,108,89,50,57,116,99,67,53,104,89,87,107,117,97,87,53,50,90,87,53,48,98,51,74,53,76,51,89,120,77,67,73,43,67,105,65,103,73,67,65,56,98,87,57,107,90,87,119,116,97,87,53,50,89,88,74,112,89,87,53,48,76,87,108,107,80,106,77,120,90,68,86,105,78,109,69,119,76,84,81,48,78,84,81,116,78,71,85,122,77,121,48,53,89,84,99,53,76,87,82,105,89,84,65,52,77,122,103,52,78,109,77,53,90,68,119,118,98,87,57,107,90,87,119,116,97,87,53,50,89,88,74,112,89,87,53,48,76,87,108,107,80,103,111,103,73,67,65,103,80,71,49,118,90,71,86,115,76,88,82,53,99,71,85,43,99,50,86,121,100,109,108,106,90,84,119,118,98,87,57,107,90,87,119,116,100,72,108,119,90,84,52,75,73,67,65,103,73,68,120,116,98,50,82,108,98,67,49,50,90,88,74,122,80,103,111,103,73,67,65,103,73,67,65,103,73,68,120,116,98,50,82,108,98,67,49,50,90,88,73,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,68,120,116,98,50,82,108,98,67,49,50,90,88,74,122,97,87,57,117,76,87,108,107,80,106,81,50,78,68,65,120,90,87,86,106,76,84,77,49,89,109,81,116,78,71,85,53,78,105,49,104,90,68,66,107,76,84,65,122,78,84,90,109,90,106,90,105,79,71,77,52,90,68,119,118,98,87,57,107,90,87,119,116,100,109,86,121,99,50,108,118,98,105,49,112,90,68,52,75,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,80,71,49,118,90,71,86,115,76,87,53,104,98,87,85,43,85,48,81,116,86,48,70,79,73,70,78,108,99,110,90,112,89,50,85,103,90,109,57,121,73,70,82,108,99,51,82,112,98,109,99,56,76,50,49,118,90,71,86,115,76,87,53,104,98,87,85,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,68,120,116,98,50,82,108,98,67,49,50,90,88,74,122,97,87,57,117,80,106,69,117,77,68,119,118,98,87,57,107,90,87,119,116,100,109,86,121,99,50,108,118,98,106,52,75,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,80,71,49,118,90,71,86,115,76,87,82,108,99,50,78,121,97,88,66,48,97,87,57,117,80,108,78,69,76,86,100,66,84,105,66,84,90,88,74,50,97,87,78,108,73,71,90,118,99,105,66,69,83,70,89,103,86,71,86,122,100,71,108,117,90,121,66,112,98,105,66,70,77,107,85,56,76,50,49,118,90,71,86,115,76,87,82,108,99,50,78,121,97,88,66,48,97,87,57,117,80,103,111,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,98,87,57,107,90,87,119,116,90,87,120,108,98,87,86,117,100,72,77,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,98,87,57,107,90,87,119,116,90,87,120,108,98,87,86,117,100,68,52,75,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,98,109,86,51,76,87,82,104,100,71,69,116,90,71,86,115,76,87,90,115,89,87,99,43,86,68,119,118,98,109,86,51,76,87,82,104,100,71,69,116,90,71,86,115,76,87,90,115,89,87,99,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,80,71,78,104,99,109,82,112,98,109,70,115,97,88,82,53,80,110,86,117,89,109,57,49,98,109,82,108,90,68,119,118,89,50,70,121,90,71,108,117,89,87,120,112,100,72,107,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,80,71,49,118,90,71,86,115,76,87,86,115,90,87,49,108,98,110,82,122,76,122,52,75,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,99,109,86,115,89,88,82,112,98,50,53,122,97,71,108,119,76,87,120,112,99,51,81,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,68,120,121,90,87,120,104,100,71,108,118,98,110,78,111,97,88,65,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,99,109,86,115,89,88,82,108,90,67,49,48,98,122,53,116,98,50,82,108,98,67,49,50,90,88,73,56,76,51,74,108,98,71,70,48,90,87,81,116,100,71,56,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,99,109,86,115,89,88,82,112,98,50,53,122,97,71,108,119,76,87,82,104,100,71,69,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,80,72,74,108,98,71,70,48,97,87,57,117,99,50,104,112,99,67,49,114,90,88,107,43,98,87,57,107,90,87,119,116,100,109,86,121,76,109,49,118,90,71,86,115,76,88,90,108,99,110,78,112,98,50,52,116,97,87,81,56,76,51,74,108,98,71,70,48,97,87,57,117,99,50,104,112,99,67,49,114,90,88,107,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,80,72,74,108,98,71,70,48,97,87,57,117,99,50,104,112,99,67,49,50,89,87,120,49,90,84,52,48,78,109,73,53,77,106,69,48,78,67,48,53,77,106,78,104,76,84,82,107,77,106,65,116,89,106,103,49,89,83,48,122,89,50,74,107,79,68,81,51,78,106,89,52,89,84,107,56,76,51,74,108,98,71,70,48,97,87,57,117,99,50,104,112,99,67,49,50,89,87,120,49,90,84,52,75,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,68,119,118,99,109,86,115,89,88,82,112,98,50,53,122,97,71,108,119,76,87,82,104,100,71,69,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,99,109,86,115,89,88,82,112,98,50,53,122,97,71,108,119,76,87,82,104,100,71,69,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,80,72,74,108,98,71,70,48,97,87,57,117,99,50,104,112,99,67,49,114,90,88,107,43,98,87,57,107,90,87,119,117,98,87,57,107,90,87,119,116,97,87,53,50,89,88,74,112,89,87,53,48,76,87,108,107,80,67,57,121,90,87,120,104,100,71,108,118,98,110,78,111,97,88,65,116,97,50,86,53,80,103,111,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,68,120,121,90,87,120,104,100,71,108,118,98,110,78,111,97,88,65,116,100,109,70,115,100,87,85,43,79,68,73,120,79,84,82,104,90,106,69,116,77,50,77,121,89,121,48,48,79,68,86,104,76,84,104,109,78,68,81,116,78,68,73,119,90,84,73,121,89,84,108,108,89,87,69,48,80,67,57,121,90,87,120,104,100,71,108,118,98,110,78,111,97,88,65,116,100,109,70,115,100,87,85,43,67,105,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,76,51,74,108,98,71,70,48,97,87,57,117,99,50,104,112,99,67,49,107,89,88,82,104,80,103,111,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,76,51,74,108,98,71,70,48,97,87,57,117,99,50,104,112,99,68,52,75,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,76,51,74,108,98,71,70,48,97,87,57,117,99,50,104,112,99,67,49,115,97,88,78,48,80,103,111,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,103,80,67,57,116,98,50,82,108,98,67,49,108,98,71,86,116,90,87,53,48,80,103,111,103,73,67,65,103,73,67,65,103,73,67,65,103,73,67,65,56,76,50,49,118,90,71,86,115,76,87,86,115,90,87,49,108,98,110,82,122,80,103,111,103,73,67,65,103,73,67,65,103,73,68,119,118,98,87,57,107,90,87,119,116,100,109,86,121,80,103,111,103,73,67,65,103,80,67,57,116,98,50,82,108,98,67,49,50,90,88,74,122,80,103,111,56,76,50,49,118,90,71,86,115,80,103,61,61]}] \ No newline at end of file diff --git a/src/test/resources/ymlFiles/resource-SdWanTestVsp-template.yml b/src/test/resources/ymlFiles/resource-SdWanTestVsp-template.yml new file mode 100644 index 0000000..21e64fe --- /dev/null +++ b/src/test/resources/ymlFiles/resource-SdWanTestVsp-template.yml @@ -0,0 +1,314 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 +metadata: + invariantUUID: 1a111111-1111-1111-1111-111111111111 + UUID: 2a111111-1111-1111-1111-111111111111 + name: SD-WAN-Test-VSP + description: SD-WAN-Test-VSP + type: VF + category: Network L2-3 + subcategory: WAN Connectors + resourceVendor: SCP-Test-VLM + resourceVendorRelease: '1.0' +imports: +- nodes: + file: nodes.yml +- datatypes: + file: data.yml +- capabilities: + file: capabilities.yml +- relationships: + file: relationships.yml +- groups: + file: groups.yml +- policies: + file: policies.yml +- resource-SD-WAN-Test-VSP-interface: + file: resource-SdWanTestVsp-template-interface.yml +- resource-SdWanTestVsp.nodes.DUMMY_server: + file: resource-SdwantestvspNodesDummyServer-template.yml +topology_template: + inputs: + nf_naming: + type: org.openecomp.datatypes.Naming + nf_function: + type: string + nf_naming_code: + type: string + availability_zone_max_count: + type: integer + default: 1 + max_instances: + type: integer + nf_type: + type: string + DUMMY_flavor_name: + type: string + description: flavor name of PCRF PD instance + DUMMY_image_name: + type: string + description: PCRF PD image name + DUMMY_Role_net_name: + type: string + description: DUMMY network name + DUMMY_server_name: + type: string + description: PCRF PD server name + nf_role: + type: string + min_instances: + type: integer + DUMMY_vnf_id: + type: string + description: PCRF VNF Id + node_templates: + abstract_DUMMY_server: + type: org.openecomp.resource.vfc.SdWanTestVsp.abstract.nodes.DUMMY_server + metadata: + invariantUUID: 3a111111-1111-1111-1111-111111111111 + UUID: 4a111111-1111-1111-1111-111111111111 + customizationUUID: 5a111111-1111-1111-1111-111111111111 + version: '1.0' + name: SdWanTestVsp.nodes.DUMMY_server + description: Not reusable inner VFC + type: VFC + category: Generic + subcategory: Abstract + resourceVendor: SCP-Test-VLM + resourceVendorRelease: '1.0' + properties: + port_DUMMY_port_network: + - get_input: DUMMY_Role_net_name + index_value: 0 + port_DUMMY_port_ip_requirements: + - - ip_version: 4 + ip_count_required: + is_required: false + floating_ip_count_required: + is_required: false + vm_flavor_name: + get_input: DUMMY_flavor_name + service_template_filter: + substitute_service_template: Nested_DUMMY_serverServiceTemplate.yaml + count: '1' + port_DUMMY_port_network_role_tag: + - '"DUMMY_Role"' + vm_image_name: + get_input: DUMMY_image_name + vm_type_tag: DUMMY_server + min_instances: 0 + compute_DUMMY_server_metadata: + - vnf_id: + get_input: DUMMY_vnf_id + port_DUMMY_port_mac_requirements: + - mac_count_required: + is_required: false + compute_DUMMY_server_name: + - get_input: DUMMY_server_name + nfc_naming_code: DUMMY_server + groups: + SdWanTestVsp..DUMMY..module-0: + type: org.openecomp.groups.VfModule + members: + - abstract_DUMMY_server + metadata: + vfModuleModelName: SdWanTestVsp..DUMMY..module-0 + vfModuleModelInvariantUUID: 6a111111-1111-1111-1111-111111111111 + vfModuleModelUUID: 7a111111-1111-1111-1111-111111111111 + vfModuleModelVersion: '2' + properties: + min_vf_module_instances: 0 + vf_module_label: DUMMY + max_vf_module_instances: + vfc_list: + vf_module_type: Expansion + vf_module_description: + initial_count: 0 + volume_group: false + availability_zone_count: + DUMMY_group: + type: org.openecomp.groups.heat.HeatStack + members: + - abstract_DUMMY_server + metadata: + invariantUUID: 8a111111-1111-1111-1111-111111111111 + UUID: 9a111111-1111-1111-1111-111111111111 + version: '1' + name: DUMMY_group + substitution_mappings: + node_type: org.openecomp.resource.vf.SdWanTestVsp + capabilities: + abstract_dummy_server.instance_DUMMY_server: + - abstract_DUMMY_server + - instance_DUMMY_server + abstract_dummy_server.disk.device.write.bytes_DUMMY_server: + - abstract_DUMMY_server + - disk.device.write.bytes_DUMMY_server + abstract_dummy_server.disk.device.capacity_DUMMY_server: + - abstract_DUMMY_server + - disk.device.capacity_DUMMY_server + abstract_dummy_server.network.outgoing.bytes_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - network.outgoing.bytes_DUMMY_server_DUMMY_port + abstract_dummy_server.os_DUMMY_server: + - abstract_DUMMY_server + - os_DUMMY_server + abstract_dummy_server.host_DUMMY_server: + - abstract_DUMMY_server + - host_DUMMY_server + abstract_dummy_server.memory_DUMMY_server: + - abstract_DUMMY_server + - memory_DUMMY_server + abstract_dummy_server.disk.read.requests_DUMMY_server: + - abstract_DUMMY_server + - disk.read.requests_DUMMY_server + abstract_dummy_server.feature_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - feature_DUMMY_server_DUMMY_port + abstract_dummy_server.disk.device.write.requests.rate_DUMMY_server: + - abstract_DUMMY_server + - disk.device.write.requests.rate_DUMMY_server + abstract_dummy_server.disk.ephemeral.size_DUMMY_server: + - abstract_DUMMY_server + - disk.ephemeral.size_DUMMY_server + abstract_dummy_server.disk.allocation_DUMMY_server: + - abstract_DUMMY_server + - disk.allocation_DUMMY_server + abstract_dummy_server.feature: + - abstract_DUMMY_server + - feature + abstract_dummy_server.scalable_DUMMY_server: + - abstract_DUMMY_server + - scalable_DUMMY_server + abstract_dummy_server.network.incoming.packets.rate_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - network.incoming.packets.rate_DUMMY_server_DUMMY_port + abstract_dummy_server.binding_DUMMY_server: + - abstract_DUMMY_server + - binding_DUMMY_server + abstract_dummy_server.disk.iops_DUMMY_server: + - abstract_DUMMY_server + - disk.iops_DUMMY_server + abstract_dummy_server.network.incoming.bytes_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - network.incoming.bytes_DUMMY_server_DUMMY_port + abstract_dummy_server.disk.read.bytes_DUMMY_server: + - abstract_DUMMY_server + - disk.read.bytes_DUMMY_server + abstract_dummy_server.disk.write.bytes_DUMMY_server: + - abstract_DUMMY_server + - disk.write.bytes_DUMMY_server + abstract_dummy_server.cpu.delta_DUMMY_server: + - abstract_DUMMY_server + - cpu.delta_DUMMY_server + abstract_dummy_server.disk.capacity_DUMMY_server: + - abstract_DUMMY_server + - disk.capacity_DUMMY_server + abstract_dummy_server.network.incoming.packets_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - network.incoming.packets_DUMMY_server_DUMMY_port + abstract_dummy_server.cpu_DUMMY_server: + - abstract_DUMMY_server + - cpu_DUMMY_server + abstract_dummy_server.memory.resident_DUMMY_server: + - abstract_DUMMY_server + - memory.resident_DUMMY_server + abstract_dummy_server.disk.device.read.bytes_DUMMY_server: + - abstract_DUMMY_server + - disk.device.read.bytes_DUMMY_server + abstract_dummy_server.disk.device.write.bytes.rate_DUMMY_server: + - abstract_DUMMY_server + - disk.device.write.bytes.rate_DUMMY_server + abstract_dummy_server.disk.usage_DUMMY_server: + - abstract_DUMMY_server + - disk.usage_DUMMY_server + abstract_dummy_server.disk.write.requests_DUMMY_server: + - abstract_DUMMY_server + - disk.write.requests_DUMMY_server + abstract_dummy_server.endpoint_DUMMY_server: + - abstract_DUMMY_server + - endpoint_DUMMY_server + abstract_dummy_server.memory.usage_DUMMY_server: + - abstract_DUMMY_server + - memory.usage_DUMMY_server + abstract_dummy_server.disk.latency_DUMMY_server: + - abstract_DUMMY_server + - disk.latency_DUMMY_server + abstract_dummy_server.disk.write.requests.rate_DUMMY_server: + - abstract_DUMMY_server + - disk.write.requests.rate_DUMMY_server + abstract_dummy_server.disk.device.allocation_DUMMY_server: + - abstract_DUMMY_server + - disk.device.allocation_DUMMY_server + abstract_dummy_server.disk.device.read.requests.rate_DUMMY_server: + - abstract_DUMMY_server + - disk.device.read.requests.rate_DUMMY_server + abstract_dummy_server.disk.device.read.bytes.rate_DUMMY_server: + - abstract_DUMMY_server + - disk.device.read.bytes.rate_DUMMY_server + abstract_dummy_server.disk.device.usage_DUMMY_server: + - abstract_DUMMY_server + - disk.device.usage_DUMMY_server + abstract_dummy_server.disk.device.write.requests_DUMMY_server: + - abstract_DUMMY_server + - disk.device.write.requests_DUMMY_server + abstract_dummy_server.vcpus_DUMMY_server: + - abstract_DUMMY_server + - vcpus_DUMMY_server + abstract_dummy_server.disk.write.bytes.rate_DUMMY_server: + - abstract_DUMMY_server + - disk.write.bytes.rate_DUMMY_server + abstract_dummy_server.network.outgoing.bytes.rate_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - network.outgoing.bytes.rate_DUMMY_server_DUMMY_port + abstract_dummy_server.network.outpoing.packets_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - network.outpoing.packets_DUMMY_server_DUMMY_port + abstract_dummy_server.network.outgoing.packets.rate_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - network.outgoing.packets.rate_DUMMY_server_DUMMY_port + abstract_dummy_server.binding_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - binding_DUMMY_server_DUMMY_port + abstract_dummy_server.cpu_util_DUMMY_server: + - abstract_DUMMY_server + - cpu_util_DUMMY_server + abstract_dummy_server.attachment_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - attachment_DUMMY_server_DUMMY_port + abstract_dummy_server.disk.device.latency_DUMMY_server: + - abstract_DUMMY_server + - disk.device.latency_DUMMY_server + abstract_dummy_server.disk.root.size_DUMMY_server: + - abstract_DUMMY_server + - disk.root.size_DUMMY_server + abstract_dummy_server.disk.device.iops_DUMMY_server: + - abstract_DUMMY_server + - disk.device.iops_DUMMY_server + abstract_dummy_server.disk.read.bytes.rate_DUMMY_server: + - abstract_DUMMY_server + - disk.read.bytes.rate_DUMMY_server + abstract_dummy_server.feature_DUMMY_server: + - abstract_DUMMY_server + - feature_DUMMY_server + abstract_dummy_server.disk.device.read.requests_DUMMY_server: + - abstract_DUMMY_server + - disk.device.read.requests_DUMMY_server + abstract_dummy_server.network.incoming.bytes.rate_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - network.incoming.bytes.rate_DUMMY_server_DUMMY_port + requirements: + abstract_dummy_server.local_storage_DUMMY_server: + - abstract_DUMMY_server + - local_storage_DUMMY_server + abstract_dummy_server.dependency_DUMMY_server: + - abstract_DUMMY_server + - dependency_DUMMY_server + abstract_dummy_server.link_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - link_DUMMY_server_DUMMY_port + abstract_dummy_server.dependency_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - dependency_DUMMY_server_DUMMY_port + abstract_dummy_server.dependency: + - abstract_DUMMY_server + - dependency diff --git a/src/test/resources/ymlFiles/resource-TunnelXconntest-template.yml b/src/test/resources/ymlFiles/resource-TunnelXconntest-template.yml new file mode 100644 index 0000000..6179976 --- /dev/null +++ b/src/test/resources/ymlFiles/resource-TunnelXconntest-template.yml @@ -0,0 +1,81 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 +metadata: + invariantUUID: 1b111111-1111-1111-1111-111111111111 + UUID: 2b111111-1111-1111-1111-111111111111 + name: Tunnel_XConnTest + description: Tunnel_XConnTest + type: VF + category: Allotted Resource + subcategory: Tunnel XConnect + resourceVendor: '12345' + resourceVendorRelease: '1' +imports: +- nodes: + file: nodes.yml +- datatypes: + file: data.yml +- capabilities: + file: capabilities.yml +- relationships: + file: relationships.yml +- groups: + file: groups.yml +- policies: + file: policies.yml +- resource-Tunnel_XConnTest-interface: + file: resource-TunnelXconntest-template-interface.yml +- resource-Allotedresource: + file: resource-Allotedresource-template.yml +topology_template: + inputs: + nf_naming: + type: org.openecomp.datatypes.Naming + nf_naming_code: + type: string + nf_function: + type: string + availability_zone_max_count: + type: integer + default: 1 + nf_role: + type: string + max_instances: + type: integer + min_instances: + type: integer + nf_type: + type: string + node_templates: + Allotedresource 0: + type: org.openecomp.resource.vfc.AllottedResource1235 + metadata: + invariantUUID: 3b111111-1111-1111-1111-111111111111 + UUID: 4b111111-1111-1111-1111-111111111111 + customizationUUID: 5b111111-1111-1111-1111-111111111111 + version: '1.0' + name: Allotedresource + description: Allotedresource + type: VFC + category: Allotted Resource + subcategory: Allotted Resource + resourceVendor: '123' + resourceVendorRelease: '123' + properties: + providing_service_invariant_uuid: 6b111111-1111-1111-1111-111111111111 + providing_service_uuid: 7b111111-1111-1111-1111-111111111111 + providing_service_name: vVIGaaS-Test + max_instances: 1 + min_instances: 1 + substitution_mappings: + node_type: org.openecomp.resource.vf.TunnelXconntest + capabilities: + allotedresource0.feature: + - Allotedresource 0 + - feature + requirements: + allotedresource0.service_dependency: + - Allotedresource 0 + - service_dependency + allotedresource0.dependency: + - Allotedresource 0 + - dependency diff --git a/src/test/resources/ymlFiles/service-SdWanServiceTest-template.yml b/src/test/resources/ymlFiles/service-SdWanServiceTest-template.yml new file mode 100644 index 0000000..0d3494a --- /dev/null +++ b/src/test/resources/ymlFiles/service-SdWanServiceTest-template.yml @@ -0,0 +1,270 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 +metadata: + invariantUUID: 1c111111-1111-1111-1111-111111111111 + UUID: 2c111111-1111-1111-1111-111111111111 + name: SD-WAN-Service-Test + description: SD-WAN-Service-Test + type: Service + category: Network L1-3 + serviceEcompNaming: true + ecompGeneratedNaming: true + namingPolicy: '' +imports: +- nodes: + file: nodes.yml +- datatypes: + file: data.yml +- capabilities: + file: capabilities.yml +- relationships: + file: relationships.yml +- groups: + file: groups.yml +- policies: + file: policies.yml +- service-SD-WAN-Service-Test-interface: + file: service-SdWanServiceTest-template-interface.yml +- resource-SD-WAN-Test-VSP: + file: resource-SdWanTestVsp-template.yml +- resource-SD-WAN-Test-VSP-interface: + file: resource-SdWanTestVsp-template-interface.yml +- resource-Tunnel_XConnTest: + file: resource-TunnelXconntest-template.yml +- resource-Tunnel_XConnTest-interface: + file: resource-TunnelXconntest-template-interface.yml +topology_template: + node_templates: + SD-WAN-Test-VSP 0: + type: org.openecomp.resource.vf.SdWanTestVsp + metadata: + invariantUUID: 1a111111-1111-1111-1111-111111111111 + UUID: 2a111111-1111-1111-1111-111111111111 + customizationUUID: 3c111111-1111-1111-1111-111111111111 + version: '1.0' + name: SD-WAN-Test-VSP + description: SD-WAN-Test-VSP + type: VF + category: Network L2-3 + subcategory: WAN Connectors + resourceVendor: SCP-Test-VLM + resourceVendorRelease: '1.0' + Tunnel_XConnTest 0: + type: org.openecomp.resource.vf.TunnelXconntest + metadata: + invariantUUID: 1b111111-1111-1111-1111-111111111111 + UUID: 2b111111-1111-1111-1111-111111111111 + customizationUUID: 4c111111-1111-1111-1111-111111111111 + version: '2.0' + name: Tunnel_XConnTest + description: Tunnel_XConnTest + type: VF + category: Allotted Resource + subcategory: Tunnel XConnect + resourceVendor: '12345' + resourceVendorRelease: '1' + groups: + sdwantestvsp0..SdWanTestVsp..DUMMY..module-0: + type: org.openecomp.groups.VfModule + metadata: + vfModuleModelName: SdWanTestVsp..DUMMY..module-0 + vfModuleModelInvariantUUID: 6a111111-1111-1111-1111-111111111111 + vfModuleModelUUID: 5c111111-1111-1111-1111-111111111111 + vfModuleModelVersion: '2' + vfModuleModelCustomizationUUID: 6c111111-1111-1111-1111-111111111111 + properties: + min_vf_module_instances: 0 + vf_module_label: DUMMY + max_vf_module_instances: + vfc_list: + vf_module_type: Expansion + vf_module_description: + initial_count: 0 + volume_group: false + availability_zone_count: + substitution_mappings: + node_type: org.openecomp.service.SdWanServiceTest + capabilities: + sdwantestvsp0.abstract_dummy_server.attachment_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.attachment_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.memory.resident_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.memory.resident_DUMMY_server + sdwantestvsp0.abstract_dummy_server.instance_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.instance_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.root.size_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.root.size_DUMMY_server + sdwantestvsp0.abstract_dummy_server.feature_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.feature_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.device.write.requests.rate_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.write.requests.rate_DUMMY_server + sdwantestvsp0.abstract_dummy_server.network.outpoing.packets_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.network.outpoing.packets_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.network.outgoing.packets.rate_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.network.outgoing.packets.rate_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.disk.device.allocation_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.allocation_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.read.bytes_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.read.bytes_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.read.bytes.rate_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.read.bytes.rate_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.device.usage_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.usage_DUMMY_server + sdwantestvsp0.abstract_dummy_server.network.outgoing.bytes_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.network.outgoing.bytes_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.disk.device.write.bytes_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.write.bytes_DUMMY_server + sdwantestvsp0.abstract_dummy_server.host_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.host_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.write.requests.rate_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.write.requests.rate_DUMMY_server + sdwantestvsp0.abstract_dummy_server.binding_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.binding_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.device.latency_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.latency_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.write.bytes_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.write.bytes_DUMMY_server + sdwantestvsp0.abstract_dummy_server.os_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.os_DUMMY_server + sdwantestvsp0.abstract_dummy_server.network.incoming.bytes_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.network.incoming.bytes_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.disk.device.read.bytes.rate_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.read.bytes.rate_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.write.requests_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.write.requests_DUMMY_server + sdwantestvsp0.abstract_dummy_server.vcpus_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.vcpus_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.ephemeral.size_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.ephemeral.size_DUMMY_server + tunnel_xconntest0.allotedresource0.feature: + - Allotedresource 0 + - allotedresource0.feature + sdwantestvsp0.abstract_dummy_server.disk.device.read.requests_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.read.requests_DUMMY_server + sdwantestvsp0.abstract_dummy_server.binding_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.binding_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.disk.device.read.requests.rate_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.read.requests.rate_DUMMY_server + sdwantestvsp0.abstract_dummy_server.memory.usage_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.memory.usage_DUMMY_server + sdwantestvsp0.abstract_dummy_server.feature: + - abstract_DUMMY_server + - abstract_dummy_server.feature + sdwantestvsp0.abstract_dummy_server.disk.device.write.bytes.rate_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.write.bytes.rate_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.latency_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.latency_DUMMY_server + sdwantestvsp0.abstract_dummy_server.memory_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.memory_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.usage_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.usage_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.device.write.requests_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.write.requests_DUMMY_server + sdwantestvsp0.abstract_dummy_server.scalable_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.scalable_DUMMY_server + sdwantestvsp0.abstract_dummy_server.cpu_util_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.cpu_util_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.capacity_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.capacity_DUMMY_server + sdwantestvsp0.abstract_dummy_server.network.incoming.packets_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.network.incoming.packets_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.cpu.delta_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.cpu.delta_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.iops_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.iops_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.allocation_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.allocation_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.device.read.bytes_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.read.bytes_DUMMY_server + sdwantestvsp0.abstract_dummy_server.cpu_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.cpu_DUMMY_server + sdwantestvsp0.abstract_dummy_server.network.outgoing.bytes.rate_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.network.outgoing.bytes.rate_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.disk.read.requests_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.read.requests_DUMMY_server + sdwantestvsp0.abstract_dummy_server.network.incoming.packets.rate_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.network.incoming.packets.rate_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.network.incoming.bytes.rate_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.network.incoming.bytes.rate_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.feature_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.feature_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.disk.device.iops_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.iops_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.device.capacity_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.device.capacity_DUMMY_server + sdwantestvsp0.abstract_dummy_server.disk.write.bytes.rate_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.disk.write.bytes.rate_DUMMY_server + sdwantestvsp0.abstract_dummy_server.endpoint_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.endpoint_DUMMY_server + requirements: + sdwantestvsp0.abstract_dummy_server.dependency_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.dependency_DUMMY_server + tunnel_xconntest0.allotedresource0.service_dependency: + - Allotedresource 0 + - allotedresource0.service_dependency + tunnel_xconntest0.allotedresource0.dependency: + - Allotedresource 0 + - allotedresource0.dependency + sdwantestvsp0.abstract_dummy_server.dependency_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.dependency_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.link_DUMMY_server_DUMMY_port: + - abstract_DUMMY_server + - abstract_dummy_server.link_DUMMY_server_DUMMY_port + sdwantestvsp0.abstract_dummy_server.local_storage_DUMMY_server: + - abstract_DUMMY_server + - abstract_dummy_server.local_storage_DUMMY_server + sdwantestvsp0.abstract_dummy_server.dependency: + - abstract_DUMMY_server + - abstract_dummy_server.dependency -- 2.16.6