diff options
121 files changed, 5866 insertions, 2759 deletions
diff --git a/dpo/data-formats/aai-interaction.json b/dpo/data-formats/aai-interaction.json new file mode 100644 index 00000000..6f6b76bb --- /dev/null +++ b/dpo/data-formats/aai-interaction.json @@ -0,0 +1,11 @@ +{ + "self": { + "name": "AAI_Interaction", + "version": "1.0.0", + "description": "Messages exchanged between a microservice and AAI" + }, + "dataformatversion": "1.0.0", + "unstructured": { + "encoding": "UTF-8" + } +}
\ No newline at end of file diff --git a/dpo/data-formats/pnf-reregistration.json b/dpo/data-formats/pnf-reregistration.json new file mode 100644 index 00000000..ae3a46db --- /dev/null +++ b/dpo/data-formats/pnf-reregistration.json @@ -0,0 +1,11 @@ +{ + "self": { + "name": "PNF_Reregistration_internal", + "version": "1.0.0", + "description": "Internal event sent by PRH for PNF re-registration" + }, + "dataformatversion": "1.0.0", + "unstructured": { + "encoding": "UTF-8" + } +}
\ No newline at end of file diff --git a/dpo/data-formats/prh.dataformatspec.json b/dpo/data-formats/prh.dataformatspec.json new file mode 100644 index 00000000..0cb2f005 --- /dev/null +++ b/dpo/data-formats/prh.dataformatspec.json @@ -0,0 +1,14 @@ +{ + "self": { + "name": "prh", + "version": "1.3.0", + "description": "Physical Resource Handler (PRH)" + }, + "dataformatversion": "1.0.0", + "reference": { + "name": "VES_specification", + "version": "7.1.0", + "format": "JSON", + "url": "https://git.onap.org/dcaegen2/collectors/ves/plain/dpo/data-formats/VES-7.30.1-dataformat.json" + } +}
\ No newline at end of file diff --git a/dpo/spec/prh.componentspec.json b/dpo/spec/prh.componentspec.json new file mode 100644 index 00000000..045ca11b --- /dev/null +++ b/dpo/spec/prh.componentspec.json @@ -0,0 +1,138 @@ +{ + "self": { + "version": "1.3.0", + "name": "dcaegen2-services-prh", + "description": "PNF Registration Handler", + "component_type": "docker" + }, + "streams": { + "subscribes": [ + { + "format": "prh", + "version": "1.0.0", + "config_key": "unauthenticated.VES_PNFREG_OUTPUT", + "type": "message_router" + } + ], + "publishes": [ + { + "format": "prh", + "version": "1.0.0", + "config_key": "unauthenticated.PNF_READY", + "type": "message_router" + }, + { + "format": "PNF_Reregistration_internal", + "version": "1.0.0", + "config_key": "unauthenticated.PNF_UPDATE", + "type": "message_router" + }, + { + "format": "AAI_Interaction", + "version": "1.0.0", + "config_key": "/aai/v12/network/pnfs/pnf/pnf_name", + "type": "message_router" + }, + { + "format": "AAI_Interaction", + "version": "1.0.0", + "config_key": "/aai/v12/network/pnfs/pnf/pnf_name", + "type": "message_router" + } + ] + }, + "services": { + "calls": [], + "provides": [] + }, + "parameters": [ + { + "name": "server.port", + "value": "8433", + "description": "PRH server port", + "sourced_at_deployment": false, + "policy_editable": false, + "designer_editable": false + }, + { + "name": "server.ssl.key-store-type", + "value": "PKCS12", + "description": "Key store type required for ssl", + "sourced_at_deployment": false, + "policy_editable": false, + "designer_editable": false + }, + { + "name": "server.ssl.key-store-password", + "value": "nokiapnf", + "description": "Key store password required for ssl", + "sourced_at_deployment": false, + "policy_editable": false, + "designer_editable": false + }, + { + "name": "server.ssl.key-store", + "value": "classpath:keystore-local", + "description": "Key store local required for ssl", + "sourced_at_deployment": false, + "policy_editable": false, + "designer_editable": false + }, + { + "name": "server.ssl.key-password", + "value": "nokiapnf", + "description": "Key password required for ssl", + "sourced_at_deployment": false, + "policy_editable": false, + "designer_editable": false + }, + { + "name": "server.ssl.keyAlias", + "value": "tomcat-localhost", + "description": "Key alias required for ssl", + "sourced_at_deployment": false, + "policy_editable": false, + "designer_editable": false + }, + { + "name": "consulHost", + "value": "10.42.111.9", + "description": "The host pointing to consul", + "sourced_at_deployment": false, + "policy_editable": false, + "designer_editable": false + }, + { + "name": "cbsName", + "value": "cbs", + "description": "The name of cbs", + "sourced_at_deployment": false, + "policy_editable": false, + "designer_editable": false + }, + { + "name": "appName", + "value": "dcae-prh", + "description": "The name of application", + "sourced_at_deployment": false, + "policy_editable": false, + "designer_editable": false + } + ], + "auxilary": { + "healthcheck": { + "type": "http", + "endpoint": "/heartbeat" + }, + "ports": [ + "8100:8100", + "8433:8433" + ] + }, + "artifacts": [ + { + "type": "docker image", + "uri": "nexus3.onap.org:10003/onap/org.onap.dcaegen2.services.prh.prh-app-server:1.3.0-SNAPSHOT" + } + ] +} @@ -1,4 +1,23 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ PNF-REGISTRATION-HANDLER + ~ ================================================================================ + ~ Copyright (C) 2018-2019 NOKIA Intellectual Property. All rights reserved. + ~ ================================================================================ + ~ 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========================================================= +--> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> @@ -7,13 +26,13 @@ <parent> <groupId>org.onap.oparent</groupId> <artifactId>oparent</artifactId> - <version>1.2.1</version> + <version>2.0.0</version> <relativePath/> </parent> <groupId>org.onap.dcaegen2.services</groupId> <artifactId>prh</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>1.3.1-SNAPSHOT</version> <name>dcaegen2-services-prh</name> <description>PNF Registration Handler</description> @@ -28,14 +47,11 @@ <properties> <java.version>8</java.version> - <immutables.version>2.5.6</immutables.version> - <spring.version>5.1.2.RELEASE</spring.version> - <spring-boot.version>2.1.0.RELEASE</spring-boot.version> - <tomcat.version>8.5.32</tomcat.version> - <slf4j.version>1.7.25</slf4j.version> - <junit-platform.version>1.1.0</junit-platform.version> - <jacoco.version>0.8.2</jacoco.version> - <sdk.version>1.1.0-SNAPSHOT</sdk.version> + <spring-boot.version>2.1.2.RELEASE</spring-boot.version> + <spring-cloud.version>Greenwich.SR1</spring-cloud.version> + <springfox.version>2.9.2</springfox.version> + <immutables.version>2.7.5</immutables.version> + <sdk.version>1.3.0</sdk.version> </properties> <modules> @@ -57,7 +73,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> - <version>3.7.0</version> + <version>3.8.0</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> @@ -74,33 +90,33 @@ <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-surefire-provider</artifactId> - <version>${junit-platform.version}</version> + <version>1.1.0</version> </dependency> </dependencies> </plugin> <plugin> - <groupId>com.spotify</groupId> - <artifactId>docker-maven-plugin</artifactId> - <version>1.1.1</version> + <groupId>pl.project13.maven</groupId> + <artifactId>git-commit-id-plugin</artifactId> + <version>3.0.0</version> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>3.0.0</version> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.1.2</version> </plugin> <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> - <version>${spring-boot.version}</version> - <executions> - <execution> - <goals> - <goal>repackage</goal> - </goals> - </execution> - </executions> + <groupId>io.fabric8</groupId> + <artifactId>docker-maven-plugin</artifactId> + <version>0.30.0</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <configuration> - <skip>true</skip> - </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> @@ -135,30 +151,42 @@ <artifactId>common-dependency</artifactId> <version>${sdk.version}</version> </dependency> + + <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-dependencies</artifactId> + <version>${spring-cloud.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-dependencies</artifactId> + <version>${spring-boot.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> - <version>2.8.0</version> + <version>${springfox.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> - <version>2.8.0</version> + <version>${springfox.version}</version> </dependency> <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-dependencies</artifactId> - <version>${spring-boot.version}</version> - <type>pom</type> - <scope>import</scope> + <groupId>org.immutables</groupId> + <artifactId>value</artifactId> + <version>${immutables.version}</version> </dependency> <dependency> - <groupId>org.testng</groupId> - <artifactId>testng</artifactId> - <version>6.14.2</version> - <scope>test</scope> + <groupId>org.immutables</groupId> + <artifactId>gson</artifactId> + <version>${immutables.version}</version> </dependency> </dependencies> </dependencyManagement> - </project> diff --git a/prh-app-server/Dockerfile b/prh-app-server/Dockerfile new file mode 100644 index 00000000..a72ab448 --- /dev/null +++ b/prh-app-server/Dockerfile @@ -0,0 +1,32 @@ +FROM openjdk:8-jre-alpine + +LABEL copyright="Copyright (C) 2018-2019 NOKIA" \ + license.name="The Apache Software License, Version 2.0" \ + license.url="http://www.apache.org/licenses/LICENSE-2.0" \ + maintainer="Nokia Wroclaw ONAP Team" + +RUN adduser -h ${docker.user.dir} -D ${docker.user.name}; \ + chmod -R a+w /var/log + +USER ${docker.user.name} +WORKDIR ${docker.user.dir} + +EXPOSE 8100 8433 +ENTRYPOINT ["java", "-jar", "${project.artifactId}-${project.version}.jar"] + +COPY ${project.build.directory}/${ext.dep.dir.path}/ ${ext.dep.dir.path}/ +COPY ${project.build.directory}/${int.dep.dir.path}/ ${int.dep.dir.path}/ +COPY ${project.build.directory}/${project.artifactId}-${project.version}.jar . + +LABEL git.branch="${git.branch}" \ + git.build.host="${git.build.host}" \ + git.build.time="${git.build.time}" \ + git.build.user.email="${git.build.user.email}" \ + git.build.user.name="${git.build.user.name}" \ + git.build.version="${git.build.version}" \ + git.closest.tag.name="${git.closest.tag.name}" \ + git.commit.id="${git.commit.id}" \ + git.commit.message.short="${git.commit.message.short}" \ + git.commit.time="${git.commit.time}" \ + git.commit.user.email="${git.commit.user.email}" \ + git.commit.user.name="${git.commit.user.name}" diff --git a/prh-app-server/pom.xml b/prh-app-server/pom.xml index f488ecbd..0944c50f 100644 --- a/prh-app-server/pom.xml +++ b/prh-app-server/pom.xml @@ -3,7 +3,7 @@ ~ ============LICENSE_START======================================================= ~ PNF-REGISTRATION-HANDLER ~ ================================================================================ - ~ Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + ~ Copyright (C) 2018-2019 NOKIA Intellectual Property. All rights reserved. ~ ================================================================================ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. @@ -17,16 +17,16 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. ~ ============LICENSE_END========================================================= - --> +--> <project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.dcaegen2.services</groupId> <artifactId>prh</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>1.3.1-SNAPSHOT</version> </parent> <groupId>org.onap.dcaegen2.services.prh</groupId> @@ -37,10 +37,14 @@ <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format> <prh.main.class>org.onap.dcaegen2.services.prh.MainApp</prh.main.class> - <dependency.dir.name>libs</dependency.dir.name> - <dependency.dir.location>${project.build.directory}/${dependency.dir.name}</dependency.dir.location> - <docker.artifact.dir>/opt</docker.artifact.dir> - <docker.image.name>onap/${project.groupId}.${project.artifactId}</docker.image.name> + <classpath.separator>@@</classpath.separator> + <dep.dir.name>libs</dep.dir.name> + <ext.dep.dir.path>${dep.dir.name}/external</ext.dep.dir.path> + <int.dep.dir.path>${dep.dir.name}/internal</int.dep.dir.path> + + <skipDocker>false</skipDocker> + <docker.user.name>prh</docker.user.name> + <docker.user.dir>/home/${docker.user.name}</docker.user.dir> </properties> <build> @@ -52,116 +56,171 @@ <plugins> <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <version>3.0.2</version> + <groupId>pl.project13.maven</groupId> + <artifactId>git-commit-id-plugin</artifactId> <configuration> - <archive> - <manifestEntries> - <Main-Class>${prh.main.class}</Main-Class> - <Build-Time>${maven.build.timestamp}</Build-Time> - </manifestEntries> - </archive> + <dateFormat>${maven.build.timestamp.format}</dateFormat> + <generateGitPropertiesFile>true</generateGitPropertiesFile> + <format>json</format> + <generateGitPropertiesFilename>${project.build.outputDirectory}/git_info.json</generateGitPropertiesFilename> </configuration> + <executions> + <execution> + <id>get-git-info</id> + <goals> + <goal>revision</goal> + </goals> + </execution> + </executions> </plugin> + <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <configuration> - <outputDirectory>${dependency.dir.location}</outputDirectory> - <includeScope>runtime</includeScope> <silent>true</silent> + <includeScope>runtime</includeScope> + <pathSeparator>${classpath.separator}</pathSeparator> </configuration> <executions> <execution> <id>copy-external-dependencies</id> - <phase>package</phase> + <phase>prepare-package</phase> <goals> <goal>copy-dependencies</goal> + <goal>build-classpath</goal> </goals> + <configuration> + <excludeGroupIds>${project.parent.groupId}</excludeGroupIds> + <outputDirectory>${project.build.directory}/${ext.dep.dir.path}</outputDirectory> + <prefix>./${ext.dep.dir.path}</prefix> + <outputProperty>classpath.external</outputProperty> + </configuration> </execution> - </executions> - </plugin> - <plugin> - <groupId>com.spotify</groupId> - <artifactId>docker-maven-plugin</artifactId> - <configuration> - <serverId>${onap.nexus.dockerregistry.daily}</serverId> - <imageName>${docker.image.name}</imageName> - <imageTags> - <tag>latest</tag> - </imageTags> - <baseImage>openjdk:8-jre-alpine</baseImage> - <exposes> - <expose>8100</expose> - <expose>8433</expose> - </exposes> - <entryPoint>java -cp ${docker.artifact.dir}/${dependency.dir.name}/*:${docker.artifact.dir}/${project.build.finalName}.jar ${prh.main.class}</entryPoint> - <resources> - <resource> - <directory>${dependency.dir.location}</directory> - <targetPath>${docker.artifact.dir}/${dependency.dir.name}</targetPath> - </resource> - <resource> - <directory>${project.build.directory}</directory> - <include>${project.build.finalName}.jar</include> - <targetPath>${docker.artifact.dir}</targetPath> - </resource> - </resources> - </configuration> - <executions> <execution> - <id>build-image</id> - <phase>package</phase> + <id>copy-internal-dependencies</id> + <phase>prepare-package</phase> <goals> - <goal>build</goal> + <goal>copy-dependencies</goal> + <goal>build-classpath</goal> </goals> + <configuration> + <includeGroupIds>${project.parent.groupId}</includeGroupIds> + <outputDirectory>${project.build.directory}/${int.dep.dir.path}</outputDirectory> + <prefix>./${int.dep.dir.path}</prefix> + <outputProperty>classpath.internal</outputProperty> + </configuration> </execution> + </executions> + </plugin> + + <plugin> <!-- workaround for MDEP-541 --> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> <execution> - <id>tag-and-push-image-latest</id> - <phase>deploy</phase> + <id>fix-classpath-separator</id> + <phase>prepare-package</phase> <goals> - <goal>tag</goal> + <goal>regex-properties</goal> </goals> <configuration> - <image>${docker.image.name}:latest</image> - <newName>${onap.nexus.dockerregistry.daily}/${docker.image.name}:latest</newName> - <pushImage>true</pushImage> + <regexPropertySettings> + <regexPropertySetting> + <name>classpath.external</name> + <value>${classpath.external}</value> + <regex>${classpath.separator}</regex> + <replacement xml:space="preserve"> </replacement> + </regexPropertySetting> + <regexPropertySetting> + <name>classpath.internal</name> + <value>${classpath.internal}</value> + <regex>${classpath.separator}</regex> + <replacement xml:space="preserve"> </replacement> + </regexPropertySetting> + </regexPropertySettings> </configuration> </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <configuration> + <archive> + <manifest> + <mainClass>${prh.main.class}</mainClass> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + <addBuildEnvironmentEntries>true</addBuildEnvironmentEntries> + <useUniqueVersions>false</useUniqueVersions> <!-- workaround for MJAR-156 --> + </manifest> + <manifestEntries> + <Class-Path>${classpath.external} ${classpath.internal}</Class-Path> + <Git-Branch>${git.branch}</Git-Branch> + <Git-Build-Host>${git.build.host}</Git-Build-Host> + <Git-Build-Time>${git.build.time}</Git-Build-Time> + <Git-Build-User-Email>${git.build.user.email}</Git-Build-User-Email> + <Git-Build-User-Name>${git.build.user.name}</Git-Build-User-Name> + <Git-Build-Version>${git.build.version}</Git-Build-Version> + <Git-Closest-Tag-Name>${git.closest.tag.name}</Git-Closest-Tag-Name> + <Git-Commit-Id>${git.commit.id}</Git-Commit-Id> + <Git-Commit-Message-Short>${git.commit.message.short}</Git-Commit-Message-Short> + <Git-Commit-Time>${git.commit.time}</Git-Commit-Time> + <Git-Commit-User-Email>${git.commit.user.email}</Git-Commit-User-Email> + <Git-Commit-User-Name>${git.commit.user.name}</Git-Commit-User-Name> + </manifestEntries> + </archive> + </configuration> + </plugin> + + <plugin> + <groupId>io.fabric8</groupId> + <artifactId>docker-maven-plugin</artifactId> + <configuration> + <skip>${skipDocker}</skip> + <images> + <image> + <name>onap/${project.groupId}.${project.artifactId}</name> + <registry>${onap.nexus.dockerregistry.daily}</registry> + <build> + <contextDir>${project.basedir}</contextDir> + <cleanup>none</cleanup> + <tags> + <tag>latest</tag> + <tag>${project.version}</tag> + <tag>${project.version}-${maven.build.timestamp}Z</tag> + </tags> + </build> + </image> + </images> + </configuration> + <!-- <executions> <execution> - <id>tag-and-push-image-with-version</id> - <phase>deploy</phase> + <id>docker-build-image</id> + <phase>package</phase> <goals> - <goal>tag</goal> + <goal>build</goal> </goals> - <configuration> - <image>${docker.image.name}:latest</image> - <newName>${onap.nexus.dockerregistry.daily}/${docker.image.name}:${project.version}</newName> - <pushImage>true</pushImage> - </configuration> </execution> <execution> - <id>tag-and-push-image-with-version-and-date</id> + <id>docker-push-image</id> <phase>deploy</phase> <goals> - <goal>tag</goal> + <goal>push</goal> </goals> - <configuration> - <image>${docker.image.name}:latest</image> - <newName>${onap.nexus.dockerregistry.daily}/${docker.image.name}:${project.version}-${maven.build.timestamp}Z</newName> - <pushImage>true</pushImage> - </configuration> </execution> </executions> + --> </plugin> </plugins> </build> + <dependencies> <dependency> <groupId>org.onap.dcaegen2.services.prh</groupId> <artifactId>prh-commons</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId> @@ -181,6 +240,10 @@ </dependency> <dependency> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-starter-config</artifactId> + </dependency> + <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> @@ -214,29 +277,51 @@ </dependency> <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-configuration-processor</artifactId> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + </dependency> + + <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> + <artifactId>mockito-junit-jupiter</artifactId> <scope>test</scope> </dependency> <dependency> - <groupId>org.testng</groupId> - <artifactId>testng</artifactId> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> <scope>test</scope> </dependency> <dependency> - <groupId>org.assertj</groupId> - <artifactId>assertj-core</artifactId> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> + <exclusions> + <exclusion> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-test</artifactId> + <groupId>org.springframework.cloud</groupId> + <artifactId>spring-cloud-contract-wiremock</artifactId> <scope>test</scope> + <exclusions> + <exclusion> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>io.projectreactor</groupId> diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsBootstrapConfiguration.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsBootstrapConfiguration.java new file mode 100644 index 00000000..f668a581 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsBootstrapConfiguration.java @@ -0,0 +1,58 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.bootstrap; + + +import org.onap.dcaegen2.services.prh.configuration.CbsConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(CbsProperties.class) +public class CbsBootstrapConfiguration { + private static final CbsConfiguration CBS_CONFIGURATION = new CbsConfiguration(); + + @Bean + public CbsProperties cbsProperties() { + return new CbsProperties(); + } + + @Bean + @ConditionalOnProperty(value = "cbs.enabled", matchIfMissing = true) + public CbsPropertySourceLocator cbsPropertySourceLocator( + CbsProperties cbsProperties, + CbsConfiguration cbsConfiguration) { + + return new CbsPropertySourceLocator( + cbsProperties, + new CbsJsonToPropertyMapConverter(), + new CbsClientConfigurationResolver(cbsProperties), + new CbsClientFactoryFacade(), + cbsConfiguration); + } + + @Bean + public CbsConfiguration cbsConfiguration() { + return CBS_CONFIGURATION; + } +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsClientConfigurationResolver.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsClientConfigurationResolver.java new file mode 100644 index 00000000..41389980 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsClientConfigurationResolver.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.bootstrap; + +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsClientConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class CbsClientConfigurationResolver { + + private static final Logger LOGGER = LoggerFactory.getLogger(CbsClientConfigurationResolver.class); + private final CbsProperties cbsProperties; + + CbsClientConfigurationResolver(CbsProperties cbsProperties) { + this.cbsProperties = cbsProperties; + } + + CbsClientConfiguration resolveCbsClientConfiguration() { + try { + return CbsClientConfiguration.fromEnvironment(); + } catch (Exception e) { + LOGGER.warn("Failed resolving CBS client configuration from system environments: " + e); + } + LOGGER.info("Falling back to use default CBS client configuration properties"); + return cbsProperties.toCbsClientConfiguration(); + } + +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsClientFactoryFacade.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsClientFactoryFacade.java new file mode 100644 index 00000000..a68a35c9 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsClientFactoryFacade.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.bootstrap; + +import org.jetbrains.annotations.NotNull; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsClient; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsClientFactory; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsClientConfiguration; +import reactor.core.publisher.Mono; + +class CbsClientFactoryFacade { + @NotNull + Mono<CbsClient> createCbsClient(CbsClientConfiguration cbsClientConfiguration) { + return CbsClientFactory.createCbsClient(cbsClientConfiguration); + } +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsJsonToPropertyMapConverter.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsJsonToPropertyMapConverter.java new file mode 100644 index 00000000..79bf4656 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsJsonToPropertyMapConverter.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.bootstrap; + +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; + +import java.util.Map; + +import static java.util.stream.Collectors.toMap; + +class CbsJsonToPropertyMapConverter { + + private static final String CBS_CONFIG_ROOT_PROPERTY = "config"; + + Map<String, Object> convertToMap(JsonObject jsonObject) { + verifyExpectedCbsJsonFormat(jsonObject); + JsonObject config = jsonObject.getAsJsonObject(CBS_CONFIG_ROOT_PROPERTY); + return config.entrySet().stream() + .filter(entry -> entry.getValue().isJsonPrimitive()) + .collect(toMap(Map.Entry::getKey, entry -> unpack(entry.getValue().getAsJsonPrimitive()))); + } + + private static void verifyExpectedCbsJsonFormat(JsonObject jsonObject) { + if (!jsonObject.has(CBS_CONFIG_ROOT_PROPERTY)) { + throw new IllegalArgumentException("Missing expected '" + CBS_CONFIG_ROOT_PROPERTY + "'" + + " property in json from CBS."); + } + } + + private Object unpack(JsonPrimitive value) { + if (value.isString()) { + return value.getAsString(); + } + if (value.isBoolean()) { + return value.getAsBoolean(); + } + if (value.isNumber()) { + return value.getAsLong(); + } + throw new IllegalArgumentException("Unexpected JsonPrimitive type found in configuration form CBS: " + value); + } + +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsProperties.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsProperties.java new file mode 100644 index 00000000..18d4021b --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsProperties.java @@ -0,0 +1,98 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.bootstrap; + + +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsClientConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.ImmutableCbsClientConfiguration; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +import java.time.Duration; + +@ConfigurationProperties("cbs") +public class CbsProperties { + + private Boolean enabled; + private Duration updatesInterval; + @NestedConfigurationProperty + private RetryProperties fetchRetries = new RetryProperties(); + private String hostname; + private Integer port; + private String appName; + + CbsClientConfiguration toCbsClientConfiguration() { + return ImmutableCbsClientConfiguration.builder() + .hostname(hostname) + .port(port) + .appName(appName) + .build(); + } + + public String getHostname() { + return hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public Duration getUpdatesInterval() { + return updatesInterval; + } + + public void setUpdatesInterval(Duration updatesInterval) { + this.updatesInterval = updatesInterval; + } + + public RetryProperties getFetchRetries() { + return fetchRetries; + } + + public void setFetchRetries(RetryProperties fetchRetries) { + this.fetchRetries = fetchRetries; + } + +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsPropertySourceLocator.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsPropertySourceLocator.java new file mode 100644 index 00000000..7b660202 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/CbsPropertySourceLocator.java @@ -0,0 +1,84 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.bootstrap; + +import com.google.gson.JsonObject; +import org.onap.dcaegen2.services.prh.configuration.CbsConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsRequests; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsClientConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.model.logging.RequestDiagnosticContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.bootstrap.config.PropertySourceLocator; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +import java.util.Map; + +public class CbsPropertySourceLocator implements PropertySourceLocator { + private static final Logger LOGGER = LoggerFactory.getLogger(CbsPropertySourceLocator.class); + + private final CbsProperties cbsProperties; + private final CbsJsonToPropertyMapConverter cbsJsonToPropertyMapConverter; + private final CbsClientConfigurationResolver cbsClientConfigurationResolver; + private final CbsClientFactoryFacade cbsClientFactoryFacade; + private final CbsConfiguration cbsConfiguration; + + public CbsPropertySourceLocator(CbsProperties cbsProperties, + CbsJsonToPropertyMapConverter cbsJsonToPropertyMapConverter, + CbsClientConfigurationResolver cbsClientConfigurationResolver, + CbsClientFactoryFacade cbsClientFactoryFacade, + CbsConfiguration cbsConfiguration) { + this.cbsProperties = cbsProperties; + this.cbsJsonToPropertyMapConverter = cbsJsonToPropertyMapConverter; + this.cbsClientConfigurationResolver = cbsClientConfigurationResolver; + this.cbsClientFactoryFacade = cbsClientFactoryFacade; + this.cbsConfiguration = cbsConfiguration; + } + + @Override + public PropertySource<?> locate(Environment environment) { + CbsClientConfiguration cbsClientConfiguration = cbsClientConfigurationResolver.resolveCbsClientConfiguration(); + LOGGER.info("Fetching configuration from Config Binding Service @ {}:{} for {}", + cbsClientConfiguration.hostname(), cbsClientConfiguration.port(), cbsClientConfiguration.appName()); + Map<String, Object> properties = cbsClientFactoryFacade.createCbsClient(cbsClientConfiguration) + .flatMap(cbsClient -> cbsClient.get(CbsRequests.getAll(RequestDiagnosticContext.create()))) + .doOnError(e -> LOGGER.warn("Failed fetching config properties from CBS - retrying...", e)) + .retryBackoff(cbsProperties.getFetchRetries().getMaxAttempts(), + cbsProperties.getFetchRetries().getFirstBackoff(), + cbsProperties.getFetchRetries().getMaxBackoff()) + .doOnNext(this::updateCbsConfig) + .map(cbsJsonToPropertyMapConverter::convertToMap) + .block(); + return new MapPropertySource("cbs", properties); + } + + private void updateCbsConfig(JsonObject jsonObject) { + try { + cbsConfiguration.parseCBSConfig(jsonObject); + } catch (Exception e) { + LOGGER.error("Failed parsing configuration from CBS", e); + throw e; + } + } + +} diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/logging/MdcVariables.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/RetryProperties.java index c6fc4592..44108a72 100644 --- a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/logging/MdcVariables.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/bootstrap/RetryProperties.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * PNF-REGISTRATION-HANDLER * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,27 +18,37 @@ * ============LICENSE_END========================================================= */ -package org.onap.dcaegen2.services.prh.model.logging; +package org.onap.dcaegen2.services.bootstrap; -import java.util.Map; -import org.slf4j.MDC; +import java.time.Duration; -public final class MdcVariables { +public class RetryProperties { - public static final String X_ONAP_REQUEST_ID = "X-ONAP-RequestID"; - public static final String X_INVOCATION_ID = "X-InvocationID"; - public static final String REQUEST_ID = "RequestID"; - public static final String INVOCATION_ID = "InvocationID"; - public static final String INSTANCE_UUID = "InstanceUUID"; - public static final String RESPONSE_CODE = "ResponseCode"; - public static final String SERVICE_NAME = "ServiceName"; + private Integer maxAttempts = 10; + private Duration firstBackoff = Duration.ofSeconds(3); + private Duration maxBackoff = Duration.ofSeconds(15); - private MdcVariables() { + public Integer getMaxAttempts() { + return maxAttempts; } - public static void setMdcContextMap(Map<String, String> mdcContextMap) { - if (mdcContextMap != null) { - MDC.setContextMap(mdcContextMap); - } + public void setMaxAttempts(Integer maxAttempts) { + this.maxAttempts = maxAttempts; + } + + public Duration getFirstBackoff() { + return firstBackoff; + } + + public void setFirstBackoff(Duration firstBackoff) { + this.firstBackoff = firstBackoff; + } + + public Duration getMaxBackoff() { + return maxBackoff; + } + + public void setMaxBackoff(Duration maxBackoff) { + this.maxBackoff = maxBackoff; } } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/MainApp.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/MainApp.java index a1fe5770..1d2a65d3 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/MainApp.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/MainApp.java @@ -20,27 +20,27 @@ package org.onap.dcaegen2.services.prh; -import static org.onap.dcaegen2.services.prh.model.logging.MdcVariables.INVOCATION_ID; -import static org.onap.dcaegen2.services.prh.model.logging.MdcVariables.REQUEST_ID; - import java.util.Map; import java.util.UUID; + import org.slf4j.MDC; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; +import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.INVOCATION_ID; + /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/23/18 */ @SpringBootApplication(exclude = {JacksonAutoConfiguration.class}) -@Configuration @EnableScheduling +@EnableConfigurationProperties public class MainApp { public static void main(String[] args) { @@ -49,7 +49,6 @@ public class MainApp { @Bean Map<String, String> mdcContextMap() { - MDC.put(REQUEST_ID, "SampleRequestID"); MDC.put(INVOCATION_ID, UUID.randomUUID().toString()); return MDC.getCopyOfContextMap(); } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AaiHttpClientConfig.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AaiHttpClientConfig.java new file mode 100644 index 00000000..e09322d3 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AaiHttpClientConfig.java @@ -0,0 +1,84 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.configuration; + +import java.nio.charset.StandardCharsets; +import java.util.function.BiFunction; +import org.onap.dcaegen2.services.prh.model.AaiJsonBodyBuilderImpl; +import org.onap.dcaegen2.services.prh.model.AaiPnfResultModel; +import org.onap.dcaegen2.services.prh.model.AaiServiceInstanceResultModel; +import org.onap.dcaegen2.services.prh.model.utils.PrhModelAwareGsonBuilder; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.AaiHttpClientFactory; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.AaiHttpClient; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.get.AaiGetServiceInstanceClient; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.get.AaiHttpGetClient; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.patch.AaiHttpPatchClient; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpResponse; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.RxHttpClient; +import org.onap.dcaegen2.services.sdk.rest.services.model.AaiModel; +import org.onap.dcaegen2.services.sdk.rest.services.model.AaiServiceInstanceQueryModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AaiHttpClientConfig { + @Autowired + private CbsConfiguration cbsConfiguration; + + @Bean + public AaiHttpClient<AaiModel, HttpResponse> getPatchClientFactory() { + return createLazyConfigClient( + (config, client) -> new AaiHttpPatchClient(config, new AaiJsonBodyBuilderImpl(), client)); + } + + @Bean + public AaiHttpClient<AaiServiceInstanceQueryModel, AaiServiceInstanceResultModel> getServiceInstanceClient() { + return createLazyConfigClient( + (config, client) -> new AaiGetServiceInstanceClient(config, client) + .map(httpResponse -> { + httpResponse.throwIfUnsuccessful(); + return httpResponse.bodyAsJson(StandardCharsets.UTF_8, + PrhModelAwareGsonBuilder.createGson(), AaiServiceInstanceResultModel.class); + })); + } + + @Bean + public AaiHttpClient<AaiModel, AaiPnfResultModel> getGetClient() { + return createLazyConfigClient( + (config, client) -> new AaiHttpGetClient(config, client) + .map(httpResponse -> { + httpResponse.throwIfUnsuccessful(); + return httpResponse.bodyAsJson(StandardCharsets.UTF_8, + PrhModelAwareGsonBuilder.createGson(), AaiPnfResultModel.class); + })); + } + + private <T, U> AaiHttpClient<T, U> createLazyConfigClient( + final BiFunction<AaiClientConfiguration, RxHttpClient, AaiHttpClient<T, U>> factoryMethod) { + + return x -> factoryMethod.apply( + cbsConfiguration.getAaiClientConfiguration(), + new AaiHttpClientFactory(cbsConfiguration.getAaiClientConfiguration()).build() + ).getAaiResponse(x); + } +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AppConfig.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AppConfig.java deleted file mode 100644 index 99886302..00000000 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AppConfig.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PNF-REGISTRATION-HANDLER - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.configuration; - -import java.util.Objects; -import java.util.Optional; -import java.util.function.Predicate; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.ImmutableAaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapPublisherConfiguration; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/9/18 - */ - -@Configuration -@EnableConfigurationProperties -public class AppConfig extends PrhAppConfig { - - private static Predicate<String> isEmpty = String::isEmpty; - @Value("${dmaap.dmaapConsumerConfiguration.dmaapHostName:}") - public String consumerDmaapHostName; - - @Value("${dmaap.dmaapConsumerConfiguration.dmaapPortNumber:}") - public Integer consumerDmaapPortNumber; - - @Value("${dmaap.dmaapConsumerConfiguration.dmaapTopicName:}") - public String consumerDmaapTopicName; - - @Value("${dmaap.dmaapConsumerConfiguration.dmaapProtocol:}") - public String consumerDmaapProtocol; - - @Value("${dmaap.dmaapConsumerConfiguration.dmaapUserName:}") - public String consumerDmaapUserName; - - @Value("${dmaap.dmaapConsumerConfiguration.dmaapUserPassword:}") - public String consumerDmaapUserPassword; - - @Value("${dmaap.dmaapConsumerConfiguration.dmaapContentType:}") - public String consumerDmaapContentType; - - @Value("${dmaap.dmaapConsumerConfiguration.consumerId:}") - public String consumerId; - - @Value("${dmaap.dmaapConsumerConfiguration.consumerGroup:}") - public String consumerGroup; - - @Value("${dmaap.dmaapConsumerConfiguration.timeoutMs:}") - public Integer consumerTimeoutMs; - - @Value("${dmaap.dmaapConsumerConfiguration.message-limit:}") - public Integer consumerMessageLimit; - - @Value("${dmaap.dmaapProducerConfiguration.dmaapHostName:}") - public String producerDmaapHostName; - - @Value("${dmaap.dmaapProducerConfiguration.dmaapPortNumber:}") - public Integer producerDmaapPortNumber; - - @Value("${dmaap.dmaapProducerConfiguration.dmaapTopicName:}") - public String producerDmaapTopicName; - - @Value("${dmaap.dmaapProducerConfiguration.dmaapProtocol:}") - public String producerDmaapProtocol; - - @Value("${dmaap.dmaapProducerConfiguration.dmaapUserName:}") - public String producerDmaapUserName; - - @Value("${dmaap.dmaapProducerConfiguration.dmaapUserPassword:}") - public String producerDmaapUserPassword; - - @Value("${dmaap.dmaapProducerConfiguration.dmaapContentType:}") - public String producerDmaapContentType; - - @Value("${aai.aaiClientConfiguration.aaiHost:}") - public String aaiHost; - - @Value("${aai.aaiClientConfiguration.aaiHostPortNumber:}") - public Integer aaiPort; - - @Value("${aai.aaiClientConfiguration.aaiProtocol:}") - public String aaiProtocol; - - @Value("${aai.aaiClientConfiguration.aaiUserName:}") - public String aaiUserName; - - @Value("${aai.aaiClientConfiguration.aaiUserPassword:}") - public String aaiUserPassword; - - @Value("${aai.aaiClientConfiguration.aaiIgnoreSslCertificateErrors:}") - public Boolean aaiIgnoreSslCertificateErrors; - - @Value("${aai.aaiClientConfiguration.aaiBasePath:}") - public String aaiBasePath; - - @Value("${aai.aaiClientConfiguration.aaiPnfPath:}") - public String aaiPnfPath; - - @Value("${security.trustStorePath:}") - public String trustStorePath; - - @Value("${security.trustStorePasswordPath:}") - public String trustStorePasswordPath; - - @Value("${security.keyStorePath:}") - public String keyStorePath; - - @Value("${security.keyStorePasswordPath:}") - public String keyStorePasswordPath; - - @Value("${security.enableAaiCertAuth:}") - public Boolean enableAaiCertAuth; - - @Value("${security.enableDmaapCertAuth:}") - public Boolean enableDmaapCertAuth; - - @Override - public DmaapConsumerConfiguration getDmaapConsumerConfiguration() { - if (noFileConfiguration(dmaapConsumerConfiguration)) { - return null; - } - return new ImmutableDmaapConsumerConfiguration.Builder() - .dmaapUserPassword( - Optional.ofNullable(consumerDmaapUserPassword).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.dmaapUserPassword())) - .dmaapUserName( - Optional.ofNullable(consumerDmaapUserName).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.dmaapUserName())) - .dmaapHostName( - Optional.ofNullable(consumerDmaapHostName).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.dmaapHostName())) - .dmaapPortNumber( - Optional.ofNullable(consumerDmaapPortNumber).filter(p -> !p.toString().isEmpty()) - .orElse(dmaapConsumerConfiguration.dmaapPortNumber())) - .dmaapProtocol( - Optional.ofNullable(consumerDmaapProtocol).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.dmaapProtocol())) - .dmaapContentType( - Optional.ofNullable(consumerDmaapContentType).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.dmaapContentType())) - .dmaapTopicName( - Optional.ofNullable(consumerDmaapTopicName).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.dmaapTopicName())) - .messageLimit( - Optional.ofNullable(consumerMessageLimit).filter(p -> !p.toString().isEmpty()) - .orElse(dmaapConsumerConfiguration.messageLimit())) - .timeoutMs(Optional.ofNullable(consumerTimeoutMs).filter(p -> !p.toString().isEmpty()) - .orElse(dmaapConsumerConfiguration.timeoutMs())) - .consumerGroup(Optional.ofNullable(consumerGroup).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.consumerGroup())) - .consumerId(Optional.ofNullable(consumerId).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.consumerId())) - .trustStorePath( - Optional.ofNullable(trustStorePath).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.trustStorePath())) - .trustStorePasswordPath( - Optional.ofNullable(trustStorePasswordPath).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.trustStorePasswordPath())) - .keyStorePath( - Optional.ofNullable(keyStorePath).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.keyStorePath())) - .keyStorePasswordPath( - Optional.ofNullable(keyStorePasswordPath).filter(isEmpty.negate()) - .orElse(dmaapConsumerConfiguration.keyStorePasswordPath())) - .enableDmaapCertAuth( - Optional.ofNullable(enableDmaapCertAuth).filter(p -> !p.toString().isEmpty()) - .orElse(dmaapConsumerConfiguration.enableDmaapCertAuth())) - .build(); - } - - @Override - public AaiClientConfiguration getAaiClientConfiguration() { - if (noFileConfiguration(aaiClientConfiguration)) { - return null; - } - return new ImmutableAaiClientConfiguration.Builder() - .aaiHost(Optional.ofNullable(aaiHost).filter(isEmpty.negate()).orElse(aaiClientConfiguration.aaiHost())) - .aaiPort( - Optional.ofNullable(aaiPort).filter(p -> !p.toString().isEmpty()) - .orElse(aaiClientConfiguration.aaiPort())) - .aaiIgnoreSslCertificateErrors( - Optional.ofNullable(aaiIgnoreSslCertificateErrors).filter(p -> !p.toString().isEmpty()) - .orElse(aaiClientConfiguration.aaiIgnoreSslCertificateErrors())) - .aaiProtocol( - Optional.ofNullable(aaiProtocol).filter(isEmpty.negate()).orElse(aaiClientConfiguration.aaiProtocol())) - .aaiUserName( - Optional.ofNullable(aaiUserName).filter(isEmpty.negate()).orElse(aaiClientConfiguration.aaiUserName())) - .aaiUserPassword(Optional.ofNullable(aaiUserPassword).filter(isEmpty.negate()) - .orElse(aaiClientConfiguration.aaiUserPassword())) - .aaiBasePath(Optional.ofNullable(aaiBasePath).filter(isEmpty.negate()) - .orElse(aaiClientConfiguration.aaiBasePath())) - .aaiPnfPath( - Optional.ofNullable(aaiPnfPath).filter(isEmpty.negate()).orElse(aaiClientConfiguration.aaiPnfPath())) - .aaiHeaders(aaiClientConfiguration.aaiHeaders()) - .trustStorePath( - Optional.ofNullable(trustStorePath).filter(isEmpty.negate()) - .orElse(aaiClientConfiguration.trustStorePath())) - .trustStorePasswordPath( - Optional.ofNullable(trustStorePasswordPath).filter(isEmpty.negate()) - .orElse(aaiClientConfiguration.trustStorePasswordPath())) - .keyStorePath( - Optional.ofNullable(keyStorePath).filter(isEmpty.negate()) - .orElse(aaiClientConfiguration.keyStorePath())) - .keyStorePasswordPath( - Optional.ofNullable(keyStorePasswordPath).filter(isEmpty.negate()) - .orElse(aaiClientConfiguration.keyStorePasswordPath())) - .enableAaiCertAuth( - Optional.ofNullable(enableAaiCertAuth).filter(p -> !p.toString().isEmpty()) - .orElse(aaiClientConfiguration.enableAaiCertAuth())) - .build(); - } - - @Override - public DmaapPublisherConfiguration getDmaapPublisherConfiguration() { - if (noFileConfiguration(dmaapPublisherConfiguration)) { - return null; - } - return new ImmutableDmaapPublisherConfiguration.Builder() - .dmaapContentType( - Optional.ofNullable(producerDmaapContentType).filter(isEmpty.negate()) - .orElse(dmaapPublisherConfiguration.dmaapContentType())) - .dmaapHostName( - Optional.ofNullable(producerDmaapHostName).filter(isEmpty.negate()) - .orElse(dmaapPublisherConfiguration.dmaapHostName())) - .dmaapPortNumber( - Optional.ofNullable(producerDmaapPortNumber).filter(p -> !p.toString().isEmpty()) - .orElse(dmaapPublisherConfiguration.dmaapPortNumber())) - .dmaapProtocol( - Optional.ofNullable(producerDmaapProtocol).filter(isEmpty.negate()) - .orElse(dmaapPublisherConfiguration.dmaapProtocol())) - .dmaapTopicName( - Optional.ofNullable(producerDmaapTopicName).filter(isEmpty.negate()) - .orElse(dmaapPublisherConfiguration.dmaapTopicName())) - .dmaapUserName( - Optional.ofNullable(producerDmaapUserName).filter(isEmpty.negate()) - .orElse(dmaapPublisherConfiguration.dmaapUserName())) - .dmaapUserPassword( - Optional.ofNullable(producerDmaapUserPassword).filter(isEmpty.negate()) - .orElse(dmaapPublisherConfiguration.dmaapUserPassword())) - .trustStorePath( - Optional.ofNullable(trustStorePath).filter(isEmpty.negate()) - .orElse(dmaapPublisherConfiguration.trustStorePath())) - .trustStorePasswordPath( - Optional.ofNullable(trustStorePasswordPath).filter(isEmpty.negate()) - .orElse(dmaapPublisherConfiguration.trustStorePasswordPath())) - .keyStorePath( - Optional.ofNullable(keyStorePath).filter(isEmpty.negate()) - .orElse(dmaapPublisherConfiguration.keyStorePath())) - .keyStorePasswordPath( - Optional.ofNullable(keyStorePasswordPath).filter(isEmpty.negate()) - .orElse(dmaapPublisherConfiguration.keyStorePasswordPath())) - .enableDmaapCertAuth( - Optional.ofNullable(enableDmaapCertAuth).filter(p -> !p.toString().isEmpty()) - .orElse(dmaapPublisherConfiguration.enableDmaapCertAuth())) - .build(); - } - - private boolean noFileConfiguration(Object object) { - return Objects.isNull(object); - } -} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CbsConfigRefreshScheduler.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CbsConfigRefreshScheduler.java new file mode 100644 index 00000000..d87f21ed --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CbsConfigRefreshScheduler.java @@ -0,0 +1,97 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.configuration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.context.environment.EnvironmentChangeEvent; +import org.springframework.cloud.context.refresh.ContextRefresher; +import org.springframework.context.event.EventListener; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; +import reactor.core.Disposable; +import reactor.core.publisher.Flux; +import reactor.core.scheduler.Scheduler; +import reactor.core.scheduler.Schedulers; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.time.Duration; + +@Component +public class CbsConfigRefreshScheduler { + + private static final Logger LOGGER = LoggerFactory.getLogger(CbsConfigRefreshScheduler.class); + private static final String CBS_UPDATES_INTERVAL_PROPERTY = "cbs.updates-interval"; + private static final Duration NO_UPDATES = Duration.ZERO; + + private final ContextRefresher contextRefresher; + private final Environment environment; + private final Scheduler scheduler; + private volatile Disposable refreshEventsStreamHandle; + + + public CbsConfigRefreshScheduler(ContextRefresher contextRefresher, Environment environment) { + this.contextRefresher = contextRefresher; + this.environment = environment; + this.scheduler = Schedulers.newElastic("conf-updates"); + } + + @PostConstruct + public void startPollingForCbsUpdates() { + startPollingForCbsUpdates(getCbsUpdatesInterval()); + } + + private void startPollingForCbsUpdates(Duration updatesInterval) { + if (!updatesInterval.equals(NO_UPDATES)) { + LOGGER.info("Configuring pulling for CBS updates in every {}", updatesInterval); + refreshEventsStreamHandle = Flux.interval(updatesInterval, scheduler) + .doOnNext(i -> { + LOGGER.debug("Requesting context refresh"); + contextRefresher.refresh(); + }) + .onErrorContinue((e, o) -> LOGGER.error("Failed fetching config updates from CBS", e)) + .subscribe(); + } + } + + @EventListener + public void onEnvironmentChanged(EnvironmentChangeEvent event) { + if (event.getKeys().contains(CBS_UPDATES_INTERVAL_PROPERTY)) { + LOGGER.info("CBS config polling interval changed to {}", environment.getProperty(CBS_UPDATES_INTERVAL_PROPERTY)); + stopPollingForCbsUpdates(); + startPollingForCbsUpdates(getCbsUpdatesInterval()); + } + } + + private Duration getCbsUpdatesInterval() { + return environment.getProperty(CBS_UPDATES_INTERVAL_PROPERTY, Duration.class, NO_UPDATES); + } + + @PreDestroy + private void stopPollingForCbsUpdates() { + if(refreshEventsStreamHandle != null) { + LOGGER.debug("Stopping pulling for CBS updates"); + refreshEventsStreamHandle.dispose(); + } + } + +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CbsConfiguration.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CbsConfiguration.java new file mode 100644 index 00000000..c1226359 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CbsConfiguration.java @@ -0,0 +1,93 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.configuration; + +import com.google.gson.JsonObject; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.DmaapClientFactory; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.MessageRouterPublisher; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.MessageRouterSubscriber; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterPublishRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterSubscribeRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Optional; + + +public class CbsConfiguration implements Config { + private static final Logger LOGGER = LoggerFactory.getLogger(CbsConfiguration.class); + private static final String CBS_CONFIG_MISSING = "CBS config missing"; + private AaiClientConfiguration aaiClientCBSConfiguration; + private MessageRouterPublisher messageRouterPublisher; + private MessageRouterSubscriber messageRouterSubscriber; + private MessageRouterPublishRequest messageRouterCBSPublishRequest; + private MessageRouterSubscribeRequest messageRouterCBSSubscribeRequest; + private MessageRouterPublishRequest messageRouterCBSUpdatePublishRequest; + + + public void parseCBSConfig(JsonObject jsonObject) { + LOGGER.info("Received application configuration: {}", jsonObject); + CbsContentParser consulConfigurationParser = new CbsContentParser(jsonObject); + + aaiClientCBSConfiguration = consulConfigurationParser.getAaiClientConfig(); + + messageRouterPublisher = DmaapClientFactory.createMessageRouterPublisher( + consulConfigurationParser.getMessageRouterPublisherConfig()); + messageRouterCBSPublishRequest = consulConfigurationParser.getMessageRouterPublishRequest(); + messageRouterCBSUpdatePublishRequest = consulConfigurationParser.getMessageRouterUpdatePublishRequest(); + + messageRouterSubscriber = DmaapClientFactory.createMessageRouterSubscriber( + consulConfigurationParser.getMessageRouterSubscriberConfig()); + messageRouterCBSSubscribeRequest = consulConfigurationParser.getMessageRouterSubscribeRequest(); + } + + + @Override + public MessageRouterPublisher getMessageRouterPublisher() { + return Optional.ofNullable(messageRouterPublisher).orElseThrow(() -> new RuntimeException(CBS_CONFIG_MISSING)); + } + + @Override + public MessageRouterSubscriber getMessageRouterSubscriber() { + return Optional.ofNullable(messageRouterSubscriber).orElseThrow(() -> new RuntimeException(CBS_CONFIG_MISSING)); + } + + @Override + public MessageRouterPublishRequest getMessageRouterPublishRequest() { + return Optional.ofNullable(messageRouterCBSPublishRequest).orElseThrow(() -> new RuntimeException(CBS_CONFIG_MISSING)); + } + + @Override + public MessageRouterPublishRequest getMessageRouterUpdatePublishRequest() { + return Optional.ofNullable(messageRouterCBSUpdatePublishRequest).orElseThrow(() -> new RuntimeException(CBS_CONFIG_MISSING)); + } + + @Override + public AaiClientConfiguration getAaiClientConfiguration() { + return Optional.ofNullable(aaiClientCBSConfiguration).orElseThrow(() -> new RuntimeException(CBS_CONFIG_MISSING)); + } + + @Override + public MessageRouterSubscribeRequest getMessageRouterSubscribeRequest() { + return Optional.ofNullable(messageRouterCBSSubscribeRequest).orElseThrow(() -> new RuntimeException(CBS_CONFIG_MISSING)); + } +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CbsContentParser.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CbsContentParser.java new file mode 100644 index 00000000..85b4c035 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CbsContentParser.java @@ -0,0 +1,142 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.configuration; + +import com.google.common.reflect.TypeToken; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.onap.dcaegen2.services.sdk.model.streams.RawDataStream; +import org.onap.dcaegen2.services.sdk.model.streams.dmaap.MessageRouterSink; +import org.onap.dcaegen2.services.sdk.model.streams.dmaap.MessageRouterSource; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.ImmutableAaiClientConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.streams.DataStreams; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.streams.StreamFromGsonParsers; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.ImmutableMessageRouterPublishRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.ImmutableMessageRouterSubscribeRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterPublishRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterSubscribeRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.config.ImmutableMessageRouterPublisherConfig; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.config.ImmutableMessageRouterSubscriberConfig; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.config.MessageRouterPublisherConfig; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.config.MessageRouterSubscriberConfig; +import org.onap.dcaegen2.services.sdk.security.ssl.ImmutableSecurityKeys; +import org.onap.dcaegen2.services.sdk.security.ssl.ImmutableSecurityKeysStore; +import org.onap.dcaegen2.services.sdk.security.ssl.Passwords; +import org.onap.dcaegen2.services.sdk.security.ssl.SecurityKeys; + +import java.nio.file.Paths; +import java.time.Duration; +import java.util.Map; + +import static org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.streams.StreamPredicates.streamWithName; + +/** + * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 8/21/18 + */ +class CbsContentParser { + private static final String SECURITY_TRUST_STORE_PATH = "security.trustStorePath"; + private static final String SECURITY_TRUST_STORE_PASS_PATH = "security.trustStorePasswordPath"; + private static final String SECURITY_KEY_STORE_PATH = "security.keyStorePath"; + private static final String SECURITY_KEY_STORE_PASS_PATH = "security.keyStorePasswordPath"; + private static final String CONFIG = "config"; + private static final String PNF_UPDATE = "pnf-update"; + private static final String PNF_READY = "pnf-ready"; + private static final String VES_REG_OUTPUT = "ves-reg-output"; + + private final JsonObject jsonObject; + + CbsContentParser(JsonObject jsonObject) { + this.jsonObject = jsonObject.getAsJsonObject(CONFIG); + } + + MessageRouterPublishRequest getMessageRouterPublishRequest() { + return getMessageRouterPublishRequest(PNF_READY); + } + + MessageRouterPublishRequest getMessageRouterUpdatePublishRequest() { + return getMessageRouterPublishRequest(PNF_UPDATE); + } + + private MessageRouterPublishRequest getMessageRouterPublishRequest(String streamName) { + RawDataStream<JsonObject> sink = DataStreams.namedSinks(jsonObject).find(streamWithName(streamName)).get(); + MessageRouterSink parsedSink = StreamFromGsonParsers.messageRouterSinkParser().unsafeParse(sink); + + return ImmutableMessageRouterPublishRequest.builder() + .sinkDefinition(parsedSink) + .build(); + } + + MessageRouterPublisherConfig getMessageRouterPublisherConfig() { + return ImmutableMessageRouterPublisherConfig.builder() + .securityKeys(isDmaapCertAuthEnabled(jsonObject) ? createSecurityKeys(jsonObject) : null) + .build(); + } + + MessageRouterSubscriberConfig getMessageRouterSubscriberConfig() { + return ImmutableMessageRouterSubscriberConfig.builder() + .securityKeys(isDmaapCertAuthEnabled(jsonObject) ? createSecurityKeys(jsonObject) : null) + .build(); + } + + private SecurityKeys createSecurityKeys(JsonObject config) { + return ImmutableSecurityKeys.builder() + .keyStore(ImmutableSecurityKeysStore.of(Paths.get(config.get(SECURITY_KEY_STORE_PATH).getAsString()))) + .keyStorePassword(Passwords.fromPath(Paths.get(config.get(SECURITY_KEY_STORE_PASS_PATH).getAsString()))) + .trustStore(ImmutableSecurityKeysStore.of(Paths.get(config.get(SECURITY_TRUST_STORE_PATH).getAsString()))) + .trustStorePassword(Passwords.fromPath(Paths.get(config.get(SECURITY_TRUST_STORE_PASS_PATH).getAsString()))) + .build(); + } + + private boolean isDmaapCertAuthEnabled(JsonObject config) { + return config.get("security.enableDmaapCertAuth").getAsBoolean(); + } + + AaiClientConfiguration getAaiClientConfig() { + return new ImmutableAaiClientConfiguration.Builder() + .pnfUrl(jsonObject.get("aai.aaiClientConfiguration.pnfUrl").getAsString()) + .aaiUserName(jsonObject.get("aai.aaiClientConfiguration.aaiUserName").getAsString()) + .aaiServiceInstancePath(jsonObject.get("aai.aaiClientConfiguration.aaiServiceInstancePath").getAsString()) + .aaiIgnoreSslCertificateErrors( + jsonObject.get("aai.aaiClientConfiguration.aaiIgnoreSslCertificateErrors").getAsBoolean()) + .aaiUserPassword(jsonObject.get("aai.aaiClientConfiguration.aaiUserPassword").getAsString()) + .trustStorePath(jsonObject.get(SECURITY_TRUST_STORE_PATH).getAsString()) + .trustStorePasswordPath(jsonObject.get(SECURITY_TRUST_STORE_PASS_PATH).getAsString()) + .keyStorePath(jsonObject.get(SECURITY_KEY_STORE_PATH).getAsString()) + .keyStorePasswordPath(jsonObject.get(SECURITY_KEY_STORE_PASS_PATH).getAsString()) + .enableAaiCertAuth(jsonObject.get("security.enableAaiCertAuth").getAsBoolean()) + .aaiHeaders(new Gson().fromJson(jsonObject.get("aai.aaiClientConfiguration.aaiHeaders"), + new TypeToken<Map<String, String>>(){}.getType())) + .build(); + } + + MessageRouterSubscribeRequest getMessageRouterSubscribeRequest() { + RawDataStream<JsonObject> source = DataStreams.namedSources(jsonObject).find(streamWithName(VES_REG_OUTPUT)).get(); + MessageRouterSource parsedSource = StreamFromGsonParsers.messageRouterSourceParser().unsafeParse(source); + + return ImmutableMessageRouterSubscribeRequest.builder() + .consumerGroup(jsonObject.get("dmaap.dmaapConsumerConfiguration.consumerGroup").getAsString()) + .sourceDefinition(parsedSource) + .consumerId(jsonObject.get("dmaap.dmaapConsumerConfiguration.consumerId").getAsString()) + .timeout(Duration.ofMillis(jsonObject.get("dmaap.dmaapConsumerConfiguration.timeoutMs").getAsLong())) + .build(); + } +}
\ No newline at end of file diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CloudConfigParser.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CloudConfigParser.java deleted file mode 100644 index 9d7b3396..00000000 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CloudConfigParser.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PNF-REGISTRATION-HANDLER - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.configuration; - -import com.google.gson.JsonObject; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.ImmutableAaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapPublisherConfiguration; - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 8/21/18 - */ -class CloudConfigParser { - - private static final String SECURITY_TRUST_STORE_PATH = "security.trustStorePath"; - private static final String SECURITY_TRUST_STORE_PASS_PATH = "security.trustStorePasswordPath"; - private static final String SECURITY_KEY_STORE_PATH = "security.keyStorePath"; - private static final String SECURITY_KEY_STORE_PASS_PATH = "security.keyStorePasswordPath"; - private final JsonObject jsonObject; - - CloudConfigParser(JsonObject jsonObject) { - this.jsonObject = jsonObject; - } - - DmaapPublisherConfiguration getDmaapPublisherConfig() { - return new ImmutableDmaapPublisherConfiguration.Builder() - .dmaapTopicName(jsonObject.get("dmaap.dmaapProducerConfiguration.dmaapTopicName").getAsString()) - .dmaapUserPassword(jsonObject.get("dmaap.dmaapProducerConfiguration.dmaapUserPassword").getAsString()) - .dmaapPortNumber(jsonObject.get("dmaap.dmaapProducerConfiguration.dmaapPortNumber").getAsInt()) - .dmaapProtocol(jsonObject.get("dmaap.dmaapProducerConfiguration.dmaapProtocol").getAsString()) - .dmaapContentType(jsonObject.get("dmaap.dmaapProducerConfiguration.dmaapContentType").getAsString()) - .dmaapHostName(jsonObject.get("dmaap.dmaapProducerConfiguration.dmaapHostName").getAsString()) - .dmaapUserName(jsonObject.get("dmaap.dmaapProducerConfiguration.dmaapUserName").getAsString()) - .trustStorePath(jsonObject.get(SECURITY_TRUST_STORE_PATH).getAsString()) - .trustStorePasswordPath(jsonObject.get(SECURITY_TRUST_STORE_PASS_PATH).getAsString()) - .keyStorePath(jsonObject.get(SECURITY_KEY_STORE_PATH).getAsString()) - .keyStorePasswordPath(jsonObject.get(SECURITY_KEY_STORE_PASS_PATH).getAsString()) - .enableDmaapCertAuth(jsonObject.get("security.enableDmaapCertAuth").getAsBoolean()) - .build(); - } - - AaiClientConfiguration getAaiClientConfig() { - return new ImmutableAaiClientConfiguration.Builder() - .aaiHost(jsonObject.get("aai.aaiClientConfiguration.aaiHost").getAsString()) - .aaiPort(jsonObject.get("aai.aaiClientConfiguration.aaiHostPortNumber").getAsInt()) - .aaiUserName(jsonObject.get("aai.aaiClientConfiguration.aaiUserName").getAsString()) - .aaiPnfPath(jsonObject.get("aai.aaiClientConfiguration.aaiPnfPath").getAsString()) - .aaiIgnoreSslCertificateErrors( - jsonObject.get("aai.aaiClientConfiguration.aaiIgnoreSslCertificateErrors").getAsBoolean()) - .aaiUserPassword(jsonObject.get("aai.aaiClientConfiguration.aaiUserPassword").getAsString()) - .aaiProtocol(jsonObject.get("aai.aaiClientConfiguration.aaiProtocol").getAsString()) - .aaiBasePath(jsonObject.get("aai.aaiClientConfiguration.aaiBasePath").getAsString()) - .trustStorePath(jsonObject.get(SECURITY_TRUST_STORE_PATH).getAsString()) - .trustStorePasswordPath(jsonObject.get(SECURITY_TRUST_STORE_PASS_PATH).getAsString()) - .keyStorePath(jsonObject.get(SECURITY_KEY_STORE_PATH).getAsString()) - .keyStorePasswordPath(jsonObject.get(SECURITY_KEY_STORE_PASS_PATH).getAsString()) - .enableAaiCertAuth(jsonObject.get("security.enableAaiCertAuth").getAsBoolean()) - .build(); - } - - DmaapConsumerConfiguration getDmaapConsumerConfig() { - return new ImmutableDmaapConsumerConfiguration.Builder() - .timeoutMs(jsonObject.get("dmaap.dmaapConsumerConfiguration.timeoutMs").getAsInt()) - .dmaapHostName(jsonObject.get("dmaap.dmaapConsumerConfiguration.dmaapHostName").getAsString()) - .dmaapUserName(jsonObject.get("dmaap.dmaapConsumerConfiguration.dmaapUserName").getAsString()) - .dmaapUserPassword(jsonObject.get("dmaap.dmaapConsumerConfiguration.dmaapUserPassword").getAsString()) - .dmaapTopicName(jsonObject.get("dmaap.dmaapConsumerConfiguration.dmaapTopicName").getAsString()) - .dmaapPortNumber(jsonObject.get("dmaap.dmaapConsumerConfiguration.dmaapPortNumber").getAsInt()) - .dmaapContentType(jsonObject.get("dmaap.dmaapConsumerConfiguration.dmaapContentType").getAsString()) - .messageLimit(jsonObject.get("dmaap.dmaapConsumerConfiguration.messageLimit").getAsInt()) - .dmaapProtocol(jsonObject.get("dmaap.dmaapConsumerConfiguration.dmaapProtocol").getAsString()) - .consumerId(jsonObject.get("dmaap.dmaapConsumerConfiguration.consumerId").getAsString()) - .consumerGroup(jsonObject.get("dmaap.dmaapConsumerConfiguration.consumerGroup").getAsString()) - .trustStorePath(jsonObject.get(SECURITY_TRUST_STORE_PATH).getAsString()) - .trustStorePasswordPath(jsonObject.get(SECURITY_TRUST_STORE_PASS_PATH).getAsString()) - .keyStorePath(jsonObject.get(SECURITY_KEY_STORE_PATH).getAsString()) - .keyStorePasswordPath(jsonObject.get(SECURITY_KEY_STORE_PASS_PATH).getAsString()) - .enableDmaapCertAuth(jsonObject.get("security.enableDmaapCertAuth").getAsBoolean()) - .build(); - } -}
\ No newline at end of file diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CloudConfiguration.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CloudConfiguration.java deleted file mode 100644 index 08c99621..00000000 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/CloudConfiguration.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PNF-REGISTRATION-HANDLER - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.configuration; - -import com.google.gson.JsonObject; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.ImmutableAaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.http.configuration.EnvProperties; -import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.providers.CloudConfigurationClient; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.*; -import org.springframework.scheduling.annotation.EnableScheduling; -import reactor.core.publisher.Flux; -import reactor.core.scheduler.Schedulers; - -import java.util.Optional; -import java.util.Properties; - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 8/9/18 - */ -@Configuration -@ComponentScan("org.onap.dcaegen2.services.sdk.rest.services.cbs.client.providers") -@EnableConfigurationProperties -@EnableScheduling -@Primary -public class CloudConfiguration extends AppConfig { - - private static final Logger LOGGER = LoggerFactory.getLogger(CloudConfiguration.class); - private CloudConfigurationClient prhConfigurationProvider; - - private AaiClientConfiguration aaiClientCloudConfiguration; - private DmaapPublisherConfiguration dmaapPublisherCloudConfiguration; - private DmaapConsumerConfiguration dmaapConsumerCloudConfiguration; - - @Value("#{systemEnvironment}") - private Properties systemEnvironment; - - - @Autowired - public void setThreadPoolTaskScheduler(CloudConfigurationClient prhConfigurationProvider) { - this.prhConfigurationProvider = prhConfigurationProvider; - } - - public void runTask() { - Flux.defer(() -> EnvironmentProcessor.evaluate(systemEnvironment)) - .subscribeOn(Schedulers.parallel()) - .subscribe(this::parsingConfigSuccess, this::parsingConfigError); - } - - private void parsingConfigError(Throwable throwable) { - LOGGER.warn("Failed to process system environments", throwable); - } - - private void cloudConfigError(Throwable throwable) { - LOGGER.warn("Failed to gather configuration from ConfigBindingService/Consul", throwable); - } - - private void parsingConfigSuccess(EnvProperties envProperties) { - LOGGER.debug("Fetching PRH configuration from ConfigBindingService/Consul"); - prhConfigurationProvider.callForServiceConfigurationReactive(envProperties) - .subscribe(this::parseCloudConfig, this::cloudConfigError); - } - - private void parseCloudConfig(JsonObject jsonObject) { - LOGGER.info("Received application configuration: {}", jsonObject); - CloudConfigParser cloudConfigParser = new CloudConfigParser(jsonObject); - dmaapPublisherCloudConfiguration = cloudConfigParser.getDmaapPublisherConfig(); - aaiClientCloudConfiguration = ImmutableAaiClientConfiguration.copyOf(cloudConfigParser.getAaiClientConfig()) - .withAaiHeaders(aaiClientConfiguration.aaiHeaders()); - dmaapConsumerCloudConfiguration = cloudConfigParser.getDmaapConsumerConfig(); - } - - @Override - public DmaapPublisherConfiguration getDmaapPublisherConfiguration() { - return Optional.ofNullable(dmaapPublisherCloudConfiguration).orElse(super.getDmaapPublisherConfiguration()); - } - - @Override - public AaiClientConfiguration getAaiClientConfiguration() { - return Optional.ofNullable(aaiClientCloudConfiguration).orElse(super.getAaiClientConfiguration()); - } - - @Override - public DmaapConsumerConfiguration getDmaapConsumerConfiguration() { - return Optional.ofNullable(dmaapConsumerCloudConfiguration).orElse(super.getDmaapConsumerConfiguration()); - } -} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/Config.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/Config.java index 613e9a83..5fe6d703 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/Config.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/Config.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * PNF-REGISTRATION-HANDLER * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 NOKIA Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,19 +21,25 @@ package org.onap.dcaegen2.services.prh.configuration; import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.MessageRouterPublisher; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.MessageRouterSubscriber; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterPublishRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterSubscribeRequest; /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/25/18 */ public interface Config { - DmaapConsumerConfiguration getDmaapConsumerConfiguration(); + MessageRouterSubscribeRequest getMessageRouterSubscribeRequest(); AaiClientConfiguration getAaiClientConfiguration(); - DmaapPublisherConfiguration getDmaapPublisherConfiguration(); + MessageRouterPublishRequest getMessageRouterPublishRequest(); - void initFileStreamReader(); + MessageRouterPublishRequest getMessageRouterUpdatePublishRequest(); + + MessageRouterPublisher getMessageRouterPublisher(); + + MessageRouterSubscriber getMessageRouterSubscriber(); } diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/ScheduleControllerSpy.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/DmaapPublisherTaskConfig.java index 2f7ff61c..e5eb1e66 100644 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/ScheduleControllerSpy.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/DmaapPublisherTaskConfig.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * PNF-REGISTRATION-HANDLER * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 NOKIA Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,39 +18,27 @@ * ============LICENSE_END========================================================= */ -package org.onap.dcaegen2.services.prh.tasks; - -import static org.mockito.Mockito.spy; - -import java.util.Map; +package org.onap.dcaegen2.services.prh.configuration; +import org.onap.dcaegen2.services.prh.tasks.DmaapPublisherTask; +import org.onap.dcaegen2.services.prh.tasks.DmaapPublisherTaskImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/5/18 - */ @Configuration -public class ScheduleControllerSpy { - - @Autowired - private DmaapConsumerTask dmaapConsumerTaskImplSpy; - - @Autowired - private DmaapPublisherTask dmaapPublisherTaskImplSpy; - +public class DmaapPublisherTaskConfig { + @Bean(name = "ReadyPublisherTask") @Autowired - private AaiProducerTask aaiPublisherTaskImplSpy; + public DmaapPublisherTask getReadyPublisherTask(Config config) { + return new DmaapPublisherTaskImpl( + config::getMessageRouterPublishRequest, config::getMessageRouterPublisher); + } + @Bean(name = "UpdatePublisherTask") @Autowired - private Map<String, String> mdcContextMap; - - @Bean - @Primary - public ScheduledTasks registerSimpleScheduledTask() { - return spy(new ScheduledTasks(dmaapConsumerTaskImplSpy, dmaapPublisherTaskImplSpy, aaiPublisherTaskImplSpy, - mdcContextMap)); + public DmaapPublisherTask getUpdatePublisherTask(Config config) { + return new DmaapPublisherTaskImpl( + config::getMessageRouterUpdatePublishRequest, config::getMessageRouterPublisher); } } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/EnvironmentProcessor.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/EnvironmentProcessor.java deleted file mode 100644 index 793fcc27..00000000 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/EnvironmentProcessor.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PNF-REGISTRATION-HANDLER - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.configuration; - -import org.onap.dcaegen2.services.prh.exceptions.EnvironmentLoaderException; -import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.http.configuration.EnvProperties; -import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.http.configuration.ImmutableEnvProperties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import reactor.core.publisher.Mono; - -import java.util.Optional; -import java.util.Properties; - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 8/10/18 - */ -final class EnvironmentProcessor { - - private static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentProcessor.class); - private static final int DEFAULT_CONSUL_PORT = 8500; - - private EnvironmentProcessor() { - } - - static Mono<EnvProperties> evaluate(Properties systemEnvironment) { - LOGGER.debug("Loading configuration from system environment variables"); - EnvProperties envProperties; - try { - envProperties = ImmutableEnvProperties.builder().consulHost(getConsulHost(systemEnvironment)) - .consulPort(getConsultPort(systemEnvironment)).cbsName(getConfigBindingService(systemEnvironment)) - .appName(getService(systemEnvironment)).build(); - } catch (EnvironmentLoaderException e) { - return Mono.error(e); - } - LOGGER.info("Evaluated system environment variables: {}", envProperties); - return Mono.just(envProperties); - } - - private static String getConsulHost(Properties systemEnvironments) throws EnvironmentLoaderException { - return Optional.ofNullable(systemEnvironments.getProperty("CONSUL_HOST")) - .orElseThrow(() -> new EnvironmentLoaderException("$CONSUL_HOST environment has not been defined")); - } - - private static Integer getConsultPort(Properties systemEnvironments) { - return Optional.ofNullable(systemEnvironments.getProperty("CONSUL_PORT")).map(Integer::valueOf) - .orElseGet(EnvironmentProcessor::getDefaultPortOfConsul); - } - - private static String getConfigBindingService(Properties systemEnvironments) throws EnvironmentLoaderException { - return Optional.ofNullable(systemEnvironments.getProperty("CONFIG_BINDING_SERVICE")) - .orElseThrow( - () -> new EnvironmentLoaderException("$CONFIG_BINDING_SERVICE environment has not been defined")); - } - - private static String getService(Properties systemEnvironments) throws EnvironmentLoaderException { - return Optional.ofNullable(Optional.ofNullable(systemEnvironments.getProperty("HOSTNAME")) - .orElse(systemEnvironments.getProperty("SERVICE_NAME"))) - .orElseThrow(() -> new EnvironmentLoaderException( - "Neither $HOSTNAME/$SERVICE_NAME have not been defined as system environment")); - } - - private static Integer getDefaultPortOfConsul() { - LOGGER.warn("$CONSUL_PORT environment has not been defined, using default port: {}", DEFAULT_CONSUL_PORT); - return DEFAULT_CONSUL_PORT; - } -} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfig.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfig.java index 612fab48..c21fd400 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfig.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfig.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * PNF-REGISTRATION-HANDLER * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 NOKIA Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,136 +20,38 @@ package org.onap.dcaegen2.services.prh.configuration; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonSyntaxException; -import com.google.gson.TypeAdapterFactory; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.ServiceLoader; -import javax.validation.constraints.NotNull; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Configuration; +import org.springframework.boot.context.event.ApplicationStartedEvent; +import org.springframework.context.event.EventListener; import org.springframework.core.io.Resource; +import org.springframework.stereotype.Component; +import org.springframework.util.StreamUtils; + +import java.io.IOException; +import java.nio.charset.Charset; /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/9/18 */ -@Configuration -@EnableConfigurationProperties -@ConfigurationProperties("app") -public abstract class PrhAppConfig implements Config { - - private static final String CONFIG = "configs"; - private static final String AAI = "aai"; - private static final String DMAAP = "dmaap"; - private static final String AAI_CONFIG = "aaiClientConfiguration"; - private static final String DMAAP_PRODUCER = "dmaapProducerConfiguration"; - private static final String DMAAP_CONSUMER = "dmaapConsumerConfiguration"; - private static final String SECURITY = "security"; - +@Component +public class PrhAppConfig { private static final Logger LOGGER = LoggerFactory.getLogger(PrhAppConfig.class); - AaiClientConfiguration aaiClientConfiguration; - - DmaapConsumerConfiguration dmaapConsumerConfiguration; - - DmaapPublisherConfiguration dmaapPublisherConfiguration; - - @Value("classpath:prh_endpoints.json") - private Resource resourceFile; - - @Override - public DmaapConsumerConfiguration getDmaapConsumerConfiguration() { - return dmaapConsumerConfiguration; - } - - @Override - public AaiClientConfiguration getAaiClientConfiguration() { - return aaiClientConfiguration; - } - - @Override - public DmaapPublisherConfiguration getDmaapPublisherConfiguration() { - return dmaapPublisherConfiguration; - } - - @Override - public void initFileStreamReader() { + @Value("classpath:git_info.json") + private Resource gitInfo; - GsonBuilder gsonBuilder = new GsonBuilder(); - ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory); - JsonParser parser = new JsonParser(); - - try (InputStream inputStream = resourceFile.getInputStream()) { - JsonElement rootElement = getJsonElement(parser, inputStream); - if (rootElement.isJsonObject()) { - deserializeAaiConfiguration(gsonBuilder, rootElement); - deserializeDmaapConsumerConfiguration(gsonBuilder, rootElement); - deserializeDmaapPublisherConfiguration(gsonBuilder, rootElement); - } - } - catch (IOException e) { - LOGGER.warn("Problem with file loading, file ", e); - } - } - - private void deserializeDmaapPublisherConfiguration(GsonBuilder gsonBuilder, JsonElement rootElement) { - dmaapPublisherConfiguration = deserializeType(gsonBuilder, concatenateJsonObjects( - rootElement.getAsJsonObject().getAsJsonObject(CONFIG).getAsJsonObject(DMAAP) - .getAsJsonObject(DMAAP_PRODUCER), - rootElement.getAsJsonObject().getAsJsonObject(CONFIG).getAsJsonObject(SECURITY)), - DmaapPublisherConfiguration.class); - } - - private void deserializeDmaapConsumerConfiguration(GsonBuilder gsonBuilder, JsonElement rootElement) { - dmaapConsumerConfiguration = deserializeType(gsonBuilder, concatenateJsonObjects( - rootElement.getAsJsonObject().getAsJsonObject(CONFIG).getAsJsonObject(DMAAP) - .getAsJsonObject(DMAAP_CONSUMER), - rootElement.getAsJsonObject().getAsJsonObject(CONFIG).getAsJsonObject(SECURITY)), - DmaapConsumerConfiguration.class); - } - - private void deserializeAaiConfiguration(GsonBuilder gsonBuilder, JsonElement rootElement) { - aaiClientConfiguration = deserializeType(gsonBuilder, concatenateJsonObjects( - rootElement.getAsJsonObject().getAsJsonObject(CONFIG).getAsJsonObject(AAI).getAsJsonObject(AAI_CONFIG), - rootElement.getAsJsonObject().getAsJsonObject(CONFIG).getAsJsonObject(SECURITY)), - AaiClientConfiguration.class); - } - - JsonElement getJsonElement(JsonParser parser, InputStream inputStream) { - return parser.parse(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); - } - - private JsonObject concatenateJsonObjects(JsonObject target, JsonObject source) { - source.entrySet() - .forEach(entry -> target.add(entry.getKey(), entry.getValue())); - return target; - } - private <T> T deserializeType(@NotNull GsonBuilder gsonBuilder, @NotNull JsonObject jsonObject, - @NotNull Class<T> type) { - try { - return gsonBuilder.create().fromJson(jsonObject, type); - } catch (JsonSyntaxException e) { - LOGGER.warn("Problem with Json deserialization", e); - return null; + @EventListener(ApplicationStartedEvent.class) + public void onApplicationStarted() throws IOException { + if(LOGGER.isDebugEnabled()) { + LOGGER.debug("Git info={}", StreamUtils.copyToString(gitInfo.getInputStream(), Charset.defaultCharset())); } } - void setResourceFile(Resource resourceFile) { - this.resourceFile = resourceFile; + public Resource getGitInfo() { + return gitInfo; } -}
\ No newline at end of file +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/HeartbeatController.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/AppInfoController.java index c09cc945..7475814f 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/HeartbeatController.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/AppInfoController.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * PNF-REGISTRATION-HANDLER * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 NOKIA Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,12 +24,14 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import org.onap.dcaegen2.services.prh.configuration.PrhAppConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; @@ -37,29 +39,28 @@ import reactor.core.publisher.Mono; * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/19/18 */ @RestController -@Api(value = "HeartbeatController", description = "Check liveness of PRH service") -public class HeartbeatController { +@Api(value = "AppInfoController", description = "Provides basic information about application") +public class AppInfoController { - private static final Logger LOGGER = LoggerFactory.getLogger(HeartbeatController.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AppInfoController.class); + private final PrhAppConfig config; - /** - * Endpoint for checking that PRH is alive. - * - * @return HTTP Status Code - */ - @RequestMapping(value = "heartbeat", method = RequestMethod.GET) - @ApiOperation(value = "Returns liveness of PRH service") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "PRH sevice is living"), - @ApiResponse(code = 401, message = "You are not authorized to view the resource"), - @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"), - @ApiResponse(code = 404, message = "The resource you were trying to reach is not found") - } - ) + public AppInfoController(PrhAppConfig config) { + this.config = config; + } + + @GetMapping(value = "heartbeat", produces = MediaType.TEXT_PLAIN_VALUE) + @ApiOperation("Returns liveness of PRH service") + @ApiResponses(@ApiResponse(code = 200, message = "Service is alive")) public Mono<ResponseEntity<String>> heartbeat() { - LOGGER.trace("Receiving heartbeat request"); - return Mono.defer(() -> - Mono.just(new ResponseEntity<>("alive", HttpStatus.OK)) + LOGGER.trace("Heartbeat request received"); + return Mono.defer(() -> Mono.just(new ResponseEntity<>("alive", HttpStatus.OK)) ); } -}
\ No newline at end of file + + @GetMapping(value = "version", produces = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation("Returns version information") + public Mono<Resource> version() { + return Mono.defer(() -> Mono.just(config.getGitInfo())); + } +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/ScheduleController.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/ScheduleController.java index aa913654..a0aa17e3 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/ScheduleController.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/controllers/ScheduleController.java @@ -60,15 +60,18 @@ public class ScheduleController { @ApiOperation(value = "Receiving stop scheduling worker request") public Mono<ResponseEntity<String>> stopTask() { LOGGER.trace("Receiving stop scheduling worker request"); - return scheduledTasksRunner.getResponseFromCancellationOfTasks(); + return Mono.defer(() -> { + scheduledTasksRunner.cancelTasks(); + return Mono.just(new ResponseEntity<>("PRH Service has been stopped!", HttpStatus.OK)); + } + ); } - @ApiOperation(value = "Sends success or error response on starting task execution") private ResponseEntity<String> createStartTaskResponse(boolean wasScheduled) { if (wasScheduled) { return new ResponseEntity<>("PRH Service has been started!", HttpStatus.CREATED); } else { - return new ResponseEntity<>("PRH Service is still running!", HttpStatus.NOT_ACCEPTABLE); + return new ResponseEntity<>("PRH Service is already running!", HttpStatus.NOT_ACCEPTABLE); } } } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/exceptions/EnvironmentLoaderException.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/exceptions/AaiFailureException.java index 5fef80d8..6741bb2d 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/exceptions/EnvironmentLoaderException.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/exceptions/AaiFailureException.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * PNF-REGISTRATION-HANDLER * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,12 +20,9 @@ package org.onap.dcaegen2.services.prh.exceptions; -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 8/10/18 - */ -public class EnvironmentLoaderException extends Exception { +public class AaiFailureException extends PrhTaskException { - public EnvironmentLoaderException(String message) { + public AaiFailureException(String message) { super(message); } } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/service/DmaapConsumerJsonParser.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/service/DmaapConsumerJsonParser.java index 4749b520..11939b53 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/service/DmaapConsumerJsonParser.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/service/DmaapConsumerJsonParser.java @@ -23,32 +23,57 @@ package org.onap.dcaegen2.services.prh.service; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import java.util.Optional; -import java.util.stream.StreamSupport; +import io.vavr.collection.List; import org.onap.dcaegen2.services.prh.exceptions.DmaapNotFoundException; import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; import org.onap.dcaegen2.services.prh.model.ImmutableConsumerDmaapModel; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterSubscribeResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.util.Optional; +import java.util.stream.StreamSupport; + +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.ADDITIONAL_FIELDS; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.COMMON_EVENT_HEADER; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.COMMON_FORMAT_FOR_JSON_OBJECT; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.COMMON_FORMAT_FOR_STRING; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.CORRELATION_ID; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.EQUIP_MODEL; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.EQUIP_TYPE; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.EQUIP_VENDOR; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.EVENT; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.NF_ROLE; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.OAM_IPV_4_ADDRESS; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.OAM_IPV_6_ADDRESS; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.PNF_REGISTRATION_FIELDS; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.SERIAL_NUMBER; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.SOURCE_NAME; +import static org.onap.dcaegen2.services.prh.service.PnfRegistrationFields.SW_VERSION; + /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/8/18 */ +@Component public class DmaapConsumerJsonParser { private static final Logger LOGGER = LoggerFactory.getLogger(DmaapConsumerJsonParser.class); - private static final String EVENT = "event"; - private static final String COMMON_EVENT_HEADER = "commonEventHeader"; - private static final String PNF_REGISTRATION_FIELDS = "pnfRegistrationFields"; - private static final String OAM_IPV_4_ADDRESS = "oamV4IpAddress"; - private static final String OAM_IPV_6_ADDRESS = "oamV6IpAddress"; - private static final String SOURCE_NAME = "sourceName"; - private static final String CORRELATION_ID = "correlationId"; + private String pnfSourceName; + private String pnfOamIpv4Address; + private String pnfOamIpv6Address; + private String pnfSerialNumberOptionalField; + private String pnfEquipVendorOptionalField; + private String pnfEquipModelOptionalField; + private String pnfEquipTypeOptionalField; + private String pnfNfRoleOptionalField; + private String pnfSwVersionOptionalField; + private JsonObject pnfAdditionalFields; /** * Extract info from string and create @see {@link org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel}. @@ -56,31 +81,24 @@ public class DmaapConsumerJsonParser { * @param monoMessage - results from DMaaP * @return reactive DMaaPModel */ - public Flux<ConsumerDmaapModel> getJsonObject(Mono<String> monoMessage) { - return monoMessage - .flatMapMany(this::getJsonParserMessage) - .flatMap(this::createJsonConsumerModel); + public Flux<ConsumerDmaapModel> getJsonObject(Mono<MessageRouterSubscribeResponse> monoMessage) { + return monoMessage.flatMapMany(msgRouterResponse -> getConsumerDmaapModelFromJsonArray(msgRouterResponse.items())); } - private Mono<JsonElement> getJsonParserMessage(String message) { - return StringUtils.isEmpty(message) ? logErrorAndReturnMonoEmpty("DmaaP response is empty") - : Mono.fromCallable(() -> new JsonParser().parse(message)); - } + private Flux<ConsumerDmaapModel> getConsumerDmaapModelFromJsonArray(List<JsonElement> items) { + LOGGER.debug("DmaapConsumerJsonParser input for parsing: {}", items); - private Flux<ConsumerDmaapModel> createJsonConsumerModel(JsonElement jsonElement) { - return jsonElement.isJsonObject() - ? create(Flux.defer(() -> Flux.just(jsonElement.getAsJsonObject()))) - : getConsumerDmaapModelFromJsonArray(jsonElement); - } - - private Flux<ConsumerDmaapModel> getConsumerDmaapModelFromJsonArray(JsonElement jsonElement) { + if (items.size() == 0) { + LOGGER.debug("Nothing to consume from DMaaP"); + return Flux.empty(); + } return create( - Flux.defer(() -> Flux.fromStream(StreamSupport.stream(jsonElement.getAsJsonArray().spliterator(), false) - .map(jsonElementFromArray -> getJsonObjectFromAnArray(jsonElementFromArray) - .orElseGet(JsonObject::new))))); + Flux.defer(() -> Flux.fromStream(StreamSupport.stream(items.spliterator(), false) + .map(jsonElementFromArray -> getJsonObjectFromAnArray(jsonElementFromArray) + .orElseGet(JsonObject::new))))); } - public Optional<JsonObject> getJsonObjectFromAnArray(JsonElement element) { + Optional<JsonObject> getJsonObjectFromAnArray(JsonElement element) { JsonParser jsonParser = new JsonParser(); return element.isJsonPrimitive() ? Optional.of(jsonParser.parse(element.getAsString()).getAsJsonObject()) : Optional.of(jsonParser.parse(element.toString()).getAsJsonObject()); @@ -94,43 +112,63 @@ public class DmaapConsumerJsonParser { } private Mono<ConsumerDmaapModel> transform(JsonObject responseFromDmaap) { - JsonObject commonEventHeader = responseFromDmaap.getAsJsonObject(EVENT) .getAsJsonObject(COMMON_EVENT_HEADER); JsonObject pnfRegistrationFields = responseFromDmaap.getAsJsonObject(EVENT) .getAsJsonObject(PNF_REGISTRATION_FIELDS); - String pnfSourceName = getValueFromJson(commonEventHeader, SOURCE_NAME); - String pnfOamIpv4Address = getValueFromJson(pnfRegistrationFields, OAM_IPV_4_ADDRESS); - String pnfOamIpv6Address = getValueFromJson(pnfRegistrationFields, OAM_IPV_6_ADDRESS); - - return (StringUtils.isEmpty(pnfSourceName) || !ipPropertiesNotEmpty(pnfOamIpv4Address, pnfOamIpv6Address)) + this.pnfSourceName = getValueFromJson(commonEventHeader, SOURCE_NAME); + this.pnfNfRoleOptionalField = getValueFromJson(commonEventHeader, NF_ROLE); + this.pnfOamIpv4Address = getValueFromJson(pnfRegistrationFields, OAM_IPV_4_ADDRESS); + this.pnfOamIpv6Address = getValueFromJson(pnfRegistrationFields, OAM_IPV_6_ADDRESS); + this.pnfSerialNumberOptionalField = getValueFromJson(pnfRegistrationFields, SERIAL_NUMBER); + this.pnfEquipVendorOptionalField = getValueFromJson(pnfRegistrationFields, EQUIP_VENDOR); + this.pnfEquipModelOptionalField = getValueFromJson(pnfRegistrationFields, EQUIP_MODEL); + this.pnfEquipTypeOptionalField = getValueFromJson(pnfRegistrationFields, EQUIP_TYPE); + this.pnfSwVersionOptionalField = getValueFromJson(pnfRegistrationFields, SW_VERSION); + this.pnfAdditionalFields = pnfRegistrationFields.getAsJsonObject(ADDITIONAL_FIELDS); + + return (StringUtils.isEmpty(pnfSourceName)) ? logErrorAndReturnMonoEmpty("Incorrect json, consumerDmaapModel can not be created: " - + printMessage(pnfSourceName, pnfOamIpv4Address, pnfOamIpv6Address)) : + + printMessage()) : Mono.just(ImmutableConsumerDmaapModel.builder() .correlationId(pnfSourceName) .ipv4(pnfOamIpv4Address) - .ipv6(pnfOamIpv6Address).build()); + .ipv6(pnfOamIpv6Address) + .serialNumber(pnfSerialNumberOptionalField) + .equipVendor(pnfEquipVendorOptionalField) + .equipModel(pnfEquipModelOptionalField) + .equipType(pnfEquipTypeOptionalField) + .nfRole(pnfNfRoleOptionalField) + .swVersion(pnfSwVersionOptionalField) + .additionalFields(pnfAdditionalFields).build()); } private String getValueFromJson(JsonObject jsonObject, String jsonKey) { return jsonObject.has(jsonKey) ? jsonObject.get(jsonKey).getAsString() : ""; } - private boolean ipPropertiesNotEmpty(String ipv4, String ipv6) { - return (!StringUtils.isEmpty(ipv4)) || !(StringUtils.isEmpty(ipv6)); - } - private boolean containsHeader(JsonObject jsonObject) { return jsonObject.has(EVENT) && jsonObject.getAsJsonObject(EVENT).has(PNF_REGISTRATION_FIELDS); } - private String printMessage(String sourceName, String oamIpv4Address, String oamIpv6Address) { + private String printMessage() { return String.format("%n{" - + "\"" + CORRELATION_ID + "\": \"%s\"," - + "\"" + OAM_IPV_4_ADDRESS + "\": \"%s\"," - + "\"" + OAM_IPV_6_ADDRESS + "\": \"%s\"" - + "%n}", sourceName, oamIpv4Address, oamIpv6Address); + + "\"" + CORRELATION_ID + COMMON_FORMAT_FOR_STRING + "," + + "\"" + OAM_IPV_4_ADDRESS + COMMON_FORMAT_FOR_STRING + "," + + "\"" + OAM_IPV_6_ADDRESS + COMMON_FORMAT_FOR_STRING + "," + + "\"" + SERIAL_NUMBER + COMMON_FORMAT_FOR_STRING + "," + + "\"" + EQUIP_VENDOR + COMMON_FORMAT_FOR_STRING + "," + + "\"" + EQUIP_MODEL + COMMON_FORMAT_FOR_STRING + "," + + "\"" + EQUIP_TYPE + COMMON_FORMAT_FOR_STRING + "," + + "\"" + NF_ROLE + COMMON_FORMAT_FOR_STRING + "," + + "\"" + SW_VERSION + COMMON_FORMAT_FOR_STRING + "," + + "\"" + ADDITIONAL_FIELDS + COMMON_FORMAT_FOR_JSON_OBJECT + + "%n}", this.pnfSourceName, this.pnfOamIpv4Address, this.pnfOamIpv6Address, + this.pnfSerialNumberOptionalField, this.pnfEquipVendorOptionalField, + this.pnfEquipModelOptionalField, this.pnfEquipTypeOptionalField, + this.pnfNfRoleOptionalField, this.pnfSwVersionOptionalField, this.pnfAdditionalFields + ); } private <T> Mono<T> logErrorAndReturnMonoEmpty(String messageForLogger) { diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/service/PnfRegistrationFields.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/service/PnfRegistrationFields.java new file mode 100644 index 00000000..a40795b1 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/service/PnfRegistrationFields.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + + +package org.onap.dcaegen2.services.prh.service; + +class PnfRegistrationFields { + + static final String COMMON_FORMAT_FOR_STRING = "\": \"%s\""; + static final String COMMON_FORMAT_FOR_JSON_OBJECT = "\": %s"; + static final String EVENT = "event"; + static final String COMMON_EVENT_HEADER = "commonEventHeader"; + static final String PNF_REGISTRATION_FIELDS = "pnfRegistrationFields"; + static final String OAM_IPV_4_ADDRESS = "oamV4IpAddress"; + static final String OAM_IPV_6_ADDRESS = "oamV6IpAddress"; + static final String SOURCE_NAME = "sourceName"; + static final String CORRELATION_ID = "correlationId"; + + // optional fields + static final String SERIAL_NUMBER = "serialNumber"; + static final String EQUIP_VENDOR = "vendorName"; + static final String EQUIP_MODEL = "modelNumber"; + static final String EQUIP_TYPE = "unitType"; + static final String NF_ROLE = "nfNamingCode"; + static final String SW_VERSION = "softwareVersion"; + static final String ADDITIONAL_FIELDS = "additionalFields"; + + private PnfRegistrationFields() {} +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTask.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTask.java index 8e31807a..123eb5a3 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTask.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTask.java @@ -20,34 +20,11 @@ package org.onap.dcaegen2.services.prh.tasks; -import javax.net.ssl.SSLException; -import org.onap.dcaegen2.services.prh.exceptions.AaiNotFoundException; import org.onap.dcaegen2.services.prh.exceptions.PrhTaskException; import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.AaiReactiveWebClientFactory; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.patch.AaiReactiveHttpPatchClient; - -import org.onap.dcaegen2.services.sdk.rest.services.ssl.SslFactory; -import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 - */ -public abstract class AaiProducerTask { - - abstract Mono<ConsumerDmaapModel> publish(ConsumerDmaapModel message) throws AaiNotFoundException; - - abstract AaiReactiveHttpPatchClient resolveClient() throws SSLException; - - protected abstract AaiClientConfiguration resolveConfiguration(); - - protected abstract Mono<ConsumerDmaapModel> execute(ConsumerDmaapModel consumerDmaapModel) - throws PrhTaskException, SSLException; - - WebClient buildWebClient() throws SSLException { - return new AaiReactiveWebClientFactory(new SslFactory(), resolveConfiguration()).build(); - } +@FunctionalInterface +interface AaiProducerTask { + Mono<ConsumerDmaapModel> execute(ConsumerDmaapModel consumerDmaapModel) throws PrhTaskException; } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTaskImpl.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTaskImpl.java index 905eb72b..7aaff47d 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTaskImpl.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTaskImpl.java @@ -20,17 +20,14 @@ package org.onap.dcaegen2.services.prh.tasks; -import javax.net.ssl.SSLException; -import org.onap.dcaegen2.services.prh.configuration.Config; import org.onap.dcaegen2.services.prh.exceptions.AaiNotFoundException; import org.onap.dcaegen2.services.prh.exceptions.DmaapNotFoundException; import org.onap.dcaegen2.services.prh.exceptions.PrhTaskException; import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; -import org.onap.dcaegen2.services.prh.model.JsonBodyBuilderImpl; import org.onap.dcaegen2.services.prh.model.utils.HttpUtils; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.patch.AaiReactiveHttpPatchClient; - +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.AaiHttpClient; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpResponse; +import org.onap.dcaegen2.services.sdk.rest.services.model.AaiModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -42,48 +39,33 @@ import reactor.core.publisher.Mono; * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 */ @Component -public class AaiProducerTaskImpl extends AaiProducerTask { +public class AaiProducerTaskImpl implements AaiProducerTask { private static final Logger LOGGER = LoggerFactory.getLogger(AaiProducerTaskImpl.class); - private final Config config; - private AaiReactiveHttpPatchClient aaiReactiveHttpPatchClient; + private final AaiHttpClient<AaiModel, HttpResponse> aaiHttpPatchClient; @Autowired - public AaiProducerTaskImpl(Config config) { - this.config = config; - } - - @Override - Mono<ConsumerDmaapModel> publish(ConsumerDmaapModel consumerDmaapModel) { - LOGGER.info("Publish to AAI DmaapModel"); - return aaiReactiveHttpPatchClient.getAaiProducerResponse(consumerDmaapModel) - .flatMap(response -> { - if (HttpUtils.isSuccessfulResponseCode(response.statusCode().value())) { - return Mono.just(consumerDmaapModel); - } - return Mono - .error(new AaiNotFoundException("Incorrect response code for continuation of tasks workflow")); - }); + public AaiProducerTaskImpl(final AaiHttpClient<AaiModel, HttpResponse> aaiHttpPatchClient) { + this.aaiHttpPatchClient = aaiHttpPatchClient; } - @Override - AaiReactiveHttpPatchClient resolveClient() throws SSLException { - return new AaiReactiveHttpPatchClient(resolveConfiguration(), new JsonBodyBuilderImpl()).createAaiWebClient(buildWebClient()); - } - - @Override - protected AaiClientConfiguration resolveConfiguration() { - return config.getAaiClientConfiguration(); + private Mono<ConsumerDmaapModel> publish(ConsumerDmaapModel consumerDmaapModel) { + Mono<HttpResponse> response = aaiHttpPatchClient.getAaiResponse(consumerDmaapModel); + return response.flatMap(r -> { + if (HttpUtils.isSuccessfulResponseCode(r.statusCode())) { + return Mono.just(consumerDmaapModel); + } + return Mono + .error(new AaiNotFoundException("Incorrect response code for continuation of tasks workflow" + r.statusCode())); + }); } @Override - protected Mono<ConsumerDmaapModel> execute(ConsumerDmaapModel consumerDmaapModel) - throws PrhTaskException, SSLException { + public Mono<ConsumerDmaapModel> execute(ConsumerDmaapModel consumerDmaapModel) throws PrhTaskException { if (consumerDmaapModel == null) { throw new DmaapNotFoundException("Invoked null object to DMaaP task"); } - aaiReactiveHttpPatchClient = resolveClient(); LOGGER.debug("Method called with arg {}", consumerDmaapModel); return publish(consumerDmaapModel); } diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/ServiceMockProvider.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiQueryTask.java index 2660e3e5..f1b900ac 100644 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/ServiceMockProvider.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiQueryTask.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * PROJECT + * PNF-REGISTRATION-HANDLER * ================================================================================ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. * ================================================================================ @@ -18,28 +18,12 @@ * ============LICENSE_END========================================================= */ -package org.onap.dcaegen2.services.prh.integration; +package org.onap.dcaegen2.services.prh.tasks; -import static org.mockito.Mockito.mock; +import org.onap.dcaegen2.services.sdk.rest.services.model.AaiModel; +import reactor.core.publisher.Mono; -import org.onap.dcaegen2.services.prh.configuration.PrhAppConfig; -import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 7/10/18 - */ -@Configuration -class ServiceMockProvider { - - @Bean - public PrhAppConfig getPrhAppConfig() { - return mock(PrhAppConfig.class); - } - - @Bean - public ConsumerDmaapModel getRequestDetails() { - return mock(ConsumerDmaapModel.class); - } +@FunctionalInterface +public interface AaiQueryTask { + Mono<Boolean> execute(final AaiModel aaiModel); } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiQueryTaskImpl.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiQueryTaskImpl.java new file mode 100644 index 00000000..ed0cbcd9 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiQueryTaskImpl.java @@ -0,0 +1,107 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.tasks; + +import org.onap.dcaegen2.services.prh.model.*; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.AaiHttpClient; +import org.onap.dcaegen2.services.sdk.rest.services.model.AaiModel; +import org.onap.dcaegen2.services.sdk.rest.services.model.AaiServiceInstanceQueryModel; +import org.onap.dcaegen2.services.sdk.rest.services.model.ImmutableAaiServiceInstanceQueryModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +@Component +public class AaiQueryTaskImpl implements AaiQueryTask { + static final String ACTIVE_STATUS = "Active"; + static final String RELATED_TO = "service-instance"; + static final String CUSTOMER = "customer.global-customer-id"; + static final String SERVICE_TYPE = "service-subscription.service-type"; + static final String SERVICE_INSTANCE_ID = "service-instance.service-instance-id"; + + private final AaiHttpClient<AaiModel, AaiPnfResultModel> getPnfModelClient; + private final AaiHttpClient<AaiServiceInstanceQueryModel, AaiServiceInstanceResultModel> getServiceClient; + + @Autowired + public AaiQueryTaskImpl( + final AaiHttpClient<AaiModel, AaiPnfResultModel> getPnfModelClient, + final AaiHttpClient<AaiServiceInstanceQueryModel, AaiServiceInstanceResultModel> getServiceClient) { + this.getPnfModelClient = getPnfModelClient; + this.getServiceClient = getServiceClient; + } + + @Override + public Mono<Boolean> execute(AaiModel aaiModel) { + return getPnfModelClient + .getAaiResponse(aaiModel) + .flatMap(this::checkIfPnfHasRelationToService) + .flatMap(getServiceClient::getAaiResponse) + .map(this::checkIfRelatedServiceInstanceIsActive) + .defaultIfEmpty(false); + } + + private Mono<AaiServiceInstanceQueryModel> checkIfPnfHasRelationToService(final AaiPnfResultModel model) { + return Mono + .justOrEmpty(model.getRelationshipList()) + .map(this::findRelatedTo) + .flatMap(Mono::justOrEmpty) + .map(RelationshipDict::getRelationshipData) + .flatMap(x -> { + final Optional<String> customer = findValue(x, CUSTOMER); + final Optional<String> serviceType = findValue(x, SERVICE_TYPE); + final Optional<String> serviceInstanceId= findValue(x, SERVICE_INSTANCE_ID); + + return customer.isPresent() && serviceType.isPresent() && serviceInstanceId.isPresent() + ? Mono.just(ImmutableAaiServiceInstanceQueryModel + .builder() + .customerId(customer.get()) + .serviceType(serviceType.get()) + .serviceInstanceId(serviceInstanceId.get()) + .build()) + : Mono.empty(); + }); + } + + private Boolean checkIfRelatedServiceInstanceIsActive(final AaiServiceInstanceResultModel model) { + return ACTIVE_STATUS.equalsIgnoreCase(model.getOrchestrationStatus()); + } + + private Optional<RelationshipDict> findRelatedTo(final Relationship data) { + return Optional.ofNullable(data.getRelationship()) + .map(Stream::of) + .orElseGet(Stream::empty) + .flatMap(List::stream) + .filter(x -> RELATED_TO.equals(x.getRelatedTo())) + .findFirst(); + } + + private Optional<String> findValue(final List<RelationshipData> data, final String key) { + return data + .stream() + .filter(y -> key.equals(y.getRelationshipKey())) + .findFirst() + .map(RelationshipData::getRelationshipValue); + } +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTask.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTask.java new file mode 100644 index 00000000..12e13140 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTask.java @@ -0,0 +1,29 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.tasks; + +import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; +import reactor.core.publisher.Mono; + +@FunctionalInterface +public interface BbsActionsTask { + Mono<ConsumerDmaapModel> execute(ConsumerDmaapModel consumerDmaapModel); +} diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTaskImpl.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTaskImpl.java new file mode 100644 index 00000000..8b893211 --- /dev/null +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTaskImpl.java @@ -0,0 +1,208 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.tasks; + +import static io.netty.handler.codec.http.HttpHeaders.Values.APPLICATION_JSON; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.http.HttpHeaders.CONTENT_TYPE; +import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.DELETE; +import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.GET; +import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.PUT; + +import com.google.gson.JsonObject; +import io.vavr.collection.HashMap; +import io.vavr.collection.Map; +import org.onap.dcaegen2.services.prh.configuration.Config; +import org.onap.dcaegen2.services.prh.exceptions.AaiFailureException; +import org.onap.dcaegen2.services.prh.model.AaiPnfResultModel; +import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; +import org.onap.dcaegen2.services.prh.model.ImmutableRelationshipDict; +import org.onap.dcaegen2.services.prh.model.Relationship; +import org.onap.dcaegen2.services.prh.model.RelationshipDict; +import org.onap.dcaegen2.services.prh.model.bbs.ImmutableLogicalLink; +import org.onap.dcaegen2.services.prh.model.bbs.LogicalLink; +import org.onap.dcaegen2.services.prh.model.utils.HttpUtils; +import org.onap.dcaegen2.services.prh.model.utils.PrhModelAwareGsonBuilder; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpResponse; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.ImmutableHttpRequest; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.RequestBody; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.RxHttpClient; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.RxHttpClientFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@Component +public class BbsActionsTaskImpl implements BbsActionsTask { + + private static final Logger LOGGER = LoggerFactory.getLogger(BbsActionsTaskImpl.class); + private static final String ATTACHMENT_POINT = "attachment-point"; + private static final String LOGICAL_LINK_URI = "/network/logical-links/logical-link"; + private static final String PNF_URI = "/network/pnfs/pnf"; + private static final String LINK_KEY = "logical-link.link-name"; + private static final String ERROR_PREFIX = "Incorrect response when performing BBS-related actions: "; + private static final String LOGICAL_LINK = "logical-link"; + + private final Config config; + private final RxHttpClient httpClient; + + @Autowired + BbsActionsTaskImpl(Config config) { + this(config, RxHttpClientFactory.createInsecure()); + } + + BbsActionsTaskImpl(Config config, RxHttpClient httpClient) { + this.config = config; + this.httpClient = httpClient; + } + + public Mono<ConsumerDmaapModel> execute(ConsumerDmaapModel consumerDmaapModel) { + JsonObject additionalFields = consumerDmaapModel.getAdditionalFields(); + if (additionalFields == null || !additionalFields.has(ATTACHMENT_POINT)) { + return Mono.just(consumerDmaapModel); + } + String linkName = additionalFields.get(ATTACHMENT_POINT).getAsString(); + if (linkName.isEmpty()) { + LOGGER.warn("Attachment point is empty! Ignore related actions."); + return Mono.just(consumerDmaapModel); + } + String pnfName = consumerDmaapModel.getCorrelationId(); + + return getLinksByPnf(pnfName) + .flatMap(x -> Flux.fromIterable(x.getRelationshipData())) + .filter(x -> LINK_KEY.equals(x.getRelationshipKey())) + .map(x -> x.getRelationshipValue()) + .flatMap(oldLinkName -> getLogicalLink(oldLinkName)) + .filter(oldLink -> oldLink.getLinkType().equals(ATTACHMENT_POINT)) + .flatMap(oldLink -> deleteLogicalLinkInAai(oldLink.getLinkName(), oldLink.getResourceVersion())) + .then(createLogicalLinkInAai(linkName, pnfName)) + .flatMap(response -> handleFinalResponse(response, consumerDmaapModel)); + } + + private Flux<RelationshipDict> getLinksByPnf(String pnfName) { + return httpClient.call(buildGetRequest(PNF_URI + "/" + pnfName)) + .flatMap(response -> handleResponse(response, "GET PNF request. Pnf name: " + pnfName)) + .map(httpResponse -> httpResponse.bodyAsJson(UTF_8, + PrhModelAwareGsonBuilder.createGson(), AaiPnfResultModel.class)) + .flatMapMany(pnfModel -> Flux.fromStream(pnfModel.getRelationshipList().getRelationship().stream())) + .filter(x -> LOGICAL_LINK.equals(x.getRelatedTo())); + } + + private Mono<LogicalLink> getLogicalLink(String linkName) { + ImmutableHttpRequest request = buildGetRequest(LOGICAL_LINK_URI + "/" + linkName); + return httpClient.call(request) + .flatMap(response -> handleResponse(response, "GET LogicalLink request. Link name: " + linkName)) + .map(httpResponse -> httpResponse.bodyAsJson(UTF_8, + PrhModelAwareGsonBuilder.createGson(), LogicalLink.class)); + } + + private Mono<HttpResponse> createLogicalLinkInAai(String linkName, String pnfName) { + ImmutableHttpRequest request = buildLogicalLinkPutRequest(linkName, pnfName); + LOGGER.debug("Creating logical link in AAI {} ", request); + return httpClient.call(request) + .flatMap(response -> handleResponse(response, "PUT LogicalLink request. Link name: " + linkName)); + } + + private Mono<HttpResponse> deleteLogicalLinkInAai(String linkName, String resourceVersion) { + ImmutableHttpRequest request = buildLogicalLinkDeleteRequest(linkName, resourceVersion); + LOGGER.debug("Deleting logical link in AAI {} ", request); + return httpClient.call(request) + .flatMap(response -> handleResponse(response, "DELETE LogicalLink request. Link name: " + linkName)); + } + + private ImmutableHttpRequest buildGetRequest(String path) { + String uri = buildUri(path); + Map<String, String> aaiHeaders = HashMap + .ofAll(config.getAaiClientConfiguration().aaiHeaders()); + + return ImmutableHttpRequest + .builder() + .method(GET) + .url(uri) + .customHeaders(aaiHeaders) + .build(); + } + + private ImmutableHttpRequest buildLogicalLinkPutRequest(String linkName, String pnfName) { + String uri = buildUri(LOGICAL_LINK_URI + "/" + linkName); + ImmutableLogicalLink logicalLink = prepareModelBuilder(linkName, pnfName).build(); + RequestBody requestBody = RequestBody.fromString(PrhModelAwareGsonBuilder.createGson().toJson(logicalLink)); + + // FIXME: AAI headers for PUT are different than PATCH (taken from prh_endpoints.json) + Map<String, String> aaiHeaders = HashMap + .ofAll(config.getAaiClientConfiguration().aaiHeaders()) + .put(CONTENT_TYPE, APPLICATION_JSON); + + return ImmutableHttpRequest + .builder() + .method(PUT) + .url(uri) + .body(requestBody) + .customHeaders(aaiHeaders) + .build(); + } + + private ImmutableHttpRequest buildLogicalLinkDeleteRequest(String linkName, String resourceVersion) { + String uri = buildUri(LOGICAL_LINK_URI + "/" + linkName + "?resource-version=" + resourceVersion); + + Map<String, String> aaiHeaders = HashMap + .ofAll(config.getAaiClientConfiguration().aaiHeaders()) + .put(CONTENT_TYPE, APPLICATION_JSON); + + return ImmutableHttpRequest + .builder() + .method(DELETE) + .url(uri) + .customHeaders(aaiHeaders) + .build(); + } + + private ImmutableLogicalLink.Builder prepareModelBuilder(String linkName, String pnfName) { + Relationship relationship = org.onap.dcaegen2.services.prh.model.ImmutableRelationship.builder() + .addRelationship( + ImmutableRelationshipDict.builder().relatedLink(PNF_URI + "/" + pnfName).build()).build(); + + return ImmutableLogicalLink + .builder() + .linkName(linkName) + .linkType(ATTACHMENT_POINT) + .relationshipList(relationship); + } + + private Mono<HttpResponse> handleResponse(HttpResponse response, String msg) { + return HttpUtils.isSuccessfulResponseCode(response.statusCode()) ? Mono.just(response) : + Mono.error(new AaiFailureException(ERROR_PREFIX + response.statusCode() + ". Occurred in " + msg)); + } + + private Mono<? extends ConsumerDmaapModel> handleFinalResponse( + HttpResponse response, ConsumerDmaapModel consumerDmaapModel) { + return HttpUtils.isSuccessfulResponseCode(response.statusCode()) + ? Mono.just(consumerDmaapModel) : Mono.error(new AaiFailureException(ERROR_PREFIX + response.statusCode())); + } + + private String buildUri(String path) { + return config.getAaiClientConfiguration().pnfUrl().replace(PNF_URI, path); + } +} + diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTask.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTask.java index e3ea8962..2deafd8d 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTask.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTask.java @@ -20,22 +20,14 @@ package org.onap.dcaegen2.services.prh.tasks; -import javax.net.ssl.SSLException; - import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPConsumerReactiveHttpClient; - import reactor.core.publisher.Flux; /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 */ +@FunctionalInterface interface DmaapConsumerTask { - - void initConfigs(); - - Flux<ConsumerDmaapModel> execute(String object) throws SSLException; - - DMaaPConsumerReactiveHttpClient resolveClient() throws SSLException; + Flux<ConsumerDmaapModel> execute(); } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTaskImpl.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTaskImpl.java index fd7bca1e..a990e502 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTaskImpl.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTaskImpl.java @@ -20,19 +20,15 @@ package org.onap.dcaegen2.services.prh.tasks; -import javax.net.ssl.SSLException; import org.onap.dcaegen2.services.prh.configuration.Config; import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; import org.onap.dcaegen2.services.prh.service.DmaapConsumerJsonParser; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.ConsumerReactiveHttpClientFactory; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPConsumerReactiveHttpClient; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPReactiveWebClientFactory; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.MessageRouterSubscriber; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterSubscribeRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterSubscribeResponse; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; /** @@ -41,39 +37,21 @@ import reactor.core.publisher.Flux; @Component public class DmaapConsumerTaskImpl implements DmaapConsumerTask { - private static final Logger LOGGER = LoggerFactory.getLogger(DmaapConsumerTaskImpl.class); private final Config config; private final DmaapConsumerJsonParser dmaapConsumerJsonParser; - private final ConsumerReactiveHttpClientFactory httpClientFactory; - @Autowired - public DmaapConsumerTaskImpl(Config config) { - this(config, new DmaapConsumerJsonParser(), - new ConsumerReactiveHttpClientFactory(new DMaaPReactiveWebClientFactory())); - } - DmaapConsumerTaskImpl(Config prhAppConfig, - DmaapConsumerJsonParser dmaapConsumerJsonParser, - ConsumerReactiveHttpClientFactory httpClientFactory) { + public DmaapConsumerTaskImpl(Config prhAppConfig, DmaapConsumerJsonParser dmaapConsumerJsonParser) { this.config = prhAppConfig; this.dmaapConsumerJsonParser = dmaapConsumerJsonParser; - this.httpClientFactory = httpClientFactory; } @Override - public void initConfigs() { - config.initFileStreamReader(); + public Flux<ConsumerDmaapModel> execute() { + MessageRouterSubscriber messageRouterSubscriber = config.getMessageRouterSubscriber(); + MessageRouterSubscribeRequest messageRouterSubscribeRequest = config.getMessageRouterSubscribeRequest(); + Mono<MessageRouterSubscribeResponse> response = messageRouterSubscriber.get(messageRouterSubscribeRequest); + return dmaapConsumerJsonParser.getJsonObject(response); } - @Override - public Flux<ConsumerDmaapModel> execute(String object) throws SSLException { - DMaaPConsumerReactiveHttpClient dmaaPConsumerReactiveHttpClient = resolveClient(); - LOGGER.debug("Method called with arg {}", object); - return dmaapConsumerJsonParser.getJsonObject(dmaaPConsumerReactiveHttpClient.getDMaaPConsumerResponse()); - } - - @Override - public DMaaPConsumerReactiveHttpClient resolveClient() throws SSLException { - return httpClientFactory.create(config.getDmaapConsumerConfiguration()); - } } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTask.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTask.java index 4d6c0f87..0cdc40ea 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTask.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTask.java @@ -22,17 +22,13 @@ package org.onap.dcaegen2.services.prh.tasks; import org.onap.dcaegen2.services.prh.exceptions.PrhTaskException; import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.DMaaPPublisherReactiveHttpClient; - -import org.springframework.http.ResponseEntity; -import reactor.core.publisher.Mono; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterPublishResponse; +import reactor.core.publisher.Flux; /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/23/18 */ -interface DmaapPublisherTask { - - Mono<ResponseEntity<String>> execute(ConsumerDmaapModel consumerDmaapModel) throws PrhTaskException; - - DMaaPPublisherReactiveHttpClient resolveClient(); +@FunctionalInterface +public interface DmaapPublisherTask { + Flux<MessageRouterPublishResponse> execute(ConsumerDmaapModel consumerDmaapModel) throws PrhTaskException; } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTaskImpl.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTaskImpl.java index 63e01c12..2890d195 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTaskImpl.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTaskImpl.java @@ -20,54 +20,46 @@ package org.onap.dcaegen2.services.prh.tasks; -import org.onap.dcaegen2.services.prh.configuration.Config; import org.onap.dcaegen2.services.prh.exceptions.DmaapNotFoundException; - import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; -import org.onap.dcaegen2.services.prh.model.JsonBodyBuilderImpl; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.DMaaPPublisherReactiveHttpClient; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.DmaaPRestTemplateFactory; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.PublisherReactiveHttpClientFactory; - +import org.onap.dcaegen2.services.prh.model.PnfReadyJsonBodyBuilder; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.MessageRouterPublisher; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterPublishRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterPublishResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; -import reactor.core.publisher.Mono; +import reactor.core.publisher.Flux; + +import java.util.function.Supplier; /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 */ -@Component public class DmaapPublisherTaskImpl implements DmaapPublisherTask { private static final Logger LOGGER = LoggerFactory.getLogger(DmaapPublisherTaskImpl.class); - private final Config config; - private final PublisherReactiveHttpClientFactory httpClientFactory; - @Autowired - public DmaapPublisherTaskImpl(Config config) { - this(config, new PublisherReactiveHttpClientFactory(new DmaaPRestTemplateFactory(),new JsonBodyBuilderImpl())); - } + private final Supplier<MessageRouterPublishRequest> publishRequestSupplier; + private final Supplier<MessageRouterPublisher> publisherSupplier; + private final PnfReadyJsonBodyBuilder pnfReadyJsonBodyBuilder = new PnfReadyJsonBodyBuilder(); - DmaapPublisherTaskImpl(Config config, PublisherReactiveHttpClientFactory httpClientFactory) { - this.config = config; - this.httpClientFactory = httpClientFactory; + + public DmaapPublisherTaskImpl(Supplier<MessageRouterPublishRequest> publishRequestSupplier, + Supplier<MessageRouterPublisher> publisherSupplier) { + this.publishRequestSupplier = publishRequestSupplier; + this.publisherSupplier = publisherSupplier; } @Override - public Mono<ResponseEntity<String>> execute(ConsumerDmaapModel consumerDmaapModel) throws DmaapNotFoundException { + public Flux<MessageRouterPublishResponse> execute(ConsumerDmaapModel consumerDmaapModel) throws DmaapNotFoundException { if (consumerDmaapModel == null) { throw new DmaapNotFoundException("Invoked null object to DMaaP task"); } - DMaaPPublisherReactiveHttpClient dmaapPublisherReactiveHttpClient = resolveClient(); LOGGER.info("Method called with arg {}", consumerDmaapModel); - return dmaapPublisherReactiveHttpClient.getDMaaPProducerResponse(consumerDmaapModel); - } - - @Override - public DMaaPPublisherReactiveHttpClient resolveClient() { - return httpClientFactory.create(config.getDmaapPublisherConfiguration()); + MessageRouterPublisher messageRouterPublisher = publisherSupplier.get(); + MessageRouterPublishRequest messageRouterPublishRequest = publishRequestSupplier.get(); + return messageRouterPublisher.put( + messageRouterPublishRequest, + Flux.just(pnfReadyJsonBodyBuilder.createJsonBody(consumerDmaapModel))); } }
\ No newline at end of file diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasks.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasks.java index 2924225b..74c6c426 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasks.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasks.java @@ -20,139 +20,176 @@ package org.onap.dcaegen2.services.prh.tasks; -import static org.onap.dcaegen2.services.prh.model.logging.MdcVariables.INSTANCE_UUID; -import static org.onap.dcaegen2.services.prh.model.logging.MdcVariables.RESPONSE_CODE; - -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.function.Predicate; -import javax.net.ssl.SSLException; import org.onap.dcaegen2.services.prh.exceptions.DmaapEmptyResponseException; import org.onap.dcaegen2.services.prh.exceptions.PrhTaskException; import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; -import org.onap.dcaegen2.services.prh.model.logging.MdcVariables; - +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterPublishResponse; +import org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.slf4j.Marker; import org.slf4j.MarkerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.function.Predicate; + +import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.INSTANCE_UUID; +import static org.onap.dcaegen2.services.sdk.rest.services.model.logging.MdcVariables.RESPONSE_CODE; + /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/23/18 */ @Component public class ScheduledTasks { - private static final Logger logger = LoggerFactory.getLogger(ScheduledTasks.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTasks.class); private static final Marker INVOKE = MarkerFactory.getMarker("INVOKE"); + private final DmaapConsumerTask dmaapConsumerTask; - private final DmaapPublisherTask dmaapProducerTask; + private final DmaapPublisherTask dmaapReadyProducerTask; + private final DmaapPublisherTask dmaapUpdateProducerTask; + private final AaiQueryTask aaiQueryTask; private final AaiProducerTask aaiProducerTask; + private final BbsActionsTask bbsActionsTask; private Map<String, String> mdcContextMap; /** * Constructor for tasks registration in PRHWorkflow. * - * @param dmaapConsumerTask - fist task - * @param dmaapPublisherTask - third task - * @param aaiPublisherTask - second task + * @param dmaapConsumerTask - fist task + * @param dmaapReadyPublisherTask - third task + * @param dmaapUpdatePublisherTask - fourth task + * @param aaiPublisherTask - second task */ @Autowired - public ScheduledTasks(DmaapConsumerTask dmaapConsumerTask, DmaapPublisherTask dmaapPublisherTask, - AaiProducerTask aaiPublisherTask, Map<String, String> mdcContextMap) { + public ScheduledTasks( + final DmaapConsumerTask dmaapConsumerTask, + @Qualifier("ReadyPublisherTask") final DmaapPublisherTask dmaapReadyPublisherTask, + @Qualifier("UpdatePublisherTask") final DmaapPublisherTask dmaapUpdatePublisherTask, + final AaiQueryTask aaiQueryTask, + final AaiProducerTask aaiPublisherTask, + final BbsActionsTask bbsActionsTask, + final Map<String, String> mdcContextMap) { this.dmaapConsumerTask = dmaapConsumerTask; - this.dmaapProducerTask = dmaapPublisherTask; + this.dmaapReadyProducerTask = dmaapReadyPublisherTask; + this.dmaapUpdateProducerTask = dmaapUpdatePublisherTask; + this.aaiQueryTask = aaiQueryTask; this.aaiProducerTask = aaiPublisherTask; + this.bbsActionsTask = bbsActionsTask; this.mdcContextMap = mdcContextMap; } + static class State { + public final ConsumerDmaapModel dmaapModel; + public final Boolean activationStatus; + + public State(final ConsumerDmaapModel dmaapModel, final Boolean activationStatus) { + this.dmaapModel = dmaapModel; + this.activationStatus = activationStatus; + } + } + /** * Main function for scheduling prhWorkflow. */ public void scheduleMainPrhEventTask() { MdcVariables.setMdcContextMap(mdcContextMap); try { - logger.trace("Execution of tasks was registered"); + LOGGER.trace("Execution of tasks was registered"); CountDownLatch mainCountDownLatch = new CountDownLatch(1); consumeFromDMaaPMessage() - .doOnError(DmaapEmptyResponseException.class, error -> - logger.warn("Nothing to consume from DMaaP") - ) - .flatMap(this::publishToAaiConfiguration) - .doOnError(exception -> - logger.warn("AAIProducerTask exception has been registered: ", exception)) - .onErrorResume(resumePrhPredicate(), exception -> Mono.empty()) - .flatMap(this::publishToDmaapConfiguration) - .doOnError(exception -> - logger.warn("DMaaPProducerTask exception has been registered: ", exception)) - .onErrorResume(resumePrhPredicate(), exception -> Mono.empty()) - .doOnTerminate(mainCountDownLatch::countDown) - .subscribe(this::onSuccess, this::onError, this::onComplete); + .doOnError(DmaapEmptyResponseException.class, error -> + LOGGER.warn("Nothing to consume from DMaaP") + ) + .flatMap(this::queryAaiForConfiguration) + .flatMap(this::publishToAaiConfiguration) + .flatMap(this::processAdditionalFields) + .flatMap(this::publishToDmaapConfiguration) + .onErrorResume(resumePrhPredicate(), exception -> Mono.empty()) + .doOnTerminate(mainCountDownLatch::countDown) + .subscribe(this::onSuccess, this::onError, this::onComplete); mainCountDownLatch.await(); } catch (InterruptedException e) { - logger.warn("Interruption problem on countDownLatch ", e); + LOGGER.warn("Interruption problem on countDownLatch ", e); Thread.currentThread().interrupt(); } } - private void onComplete() { - logger.info("PRH tasks have been completed"); + LOGGER.info("PRH tasks have been completed"); } - private void onSuccess(ResponseEntity<String> responseCode) { - MDC.put(RESPONSE_CODE, responseCode.getStatusCode().toString()); - logger.info("Prh consumed tasks successfully. HTTP Response code from DMaaPProducer {}", - responseCode.getStatusCode().value()); - MDC.remove(RESPONSE_CODE); + private void onSuccess(MessageRouterPublishResponse response) { + if (response.successful()) { + String statusCodeOk = HttpStatus.OK.name(); + MDC.put(RESPONSE_CODE, statusCodeOk); + LOGGER.info("Prh consumed tasks successfully. HTTP Response code from DMaaPProducer {}", statusCodeOk); + MDC.remove(RESPONSE_CODE); + } } private void onError(Throwable throwable) { if (!(throwable instanceof DmaapEmptyResponseException)) { - logger.warn("Chain of tasks have been aborted due to errors in PRH workflow", throwable); + LOGGER.warn("Chain of tasks have been aborted due to errors in PRH workflow", throwable); } } - private Flux<ConsumerDmaapModel> consumeFromDMaaPMessage() { return Flux.defer(() -> { MdcVariables.setMdcContextMap(mdcContextMap); MDC.put(INSTANCE_UUID, UUID.randomUUID().toString()); - logger.info(INVOKE, "Init configs"); - dmaapConsumerTask.initConfigs(); - return consumeFromDMaaP(); + LOGGER.info(INVOKE, "Init configs"); + return dmaapConsumerTask.execute(); }); } - private Flux<ConsumerDmaapModel> consumeFromDMaaP() { - try { - return dmaapConsumerTask.execute(""); - } catch (SSLException e) { - return Flux.error(e); - } + private Mono<State> queryAaiForConfiguration(final ConsumerDmaapModel monoDMaaPModel) { + return aaiQueryTask + .execute(monoDMaaPModel) + .map(x -> new State(monoDMaaPModel, x)); } - private Mono<ConsumerDmaapModel> publishToAaiConfiguration(ConsumerDmaapModel monoDMaaPModel) { + private Mono<State> publishToAaiConfiguration(final State state) { try { - return aaiProducerTask.execute(monoDMaaPModel); - } catch (PrhTaskException | SSLException e) { + return state.activationStatus + ? Mono.just(state) + : aaiProducerTask + .execute(state.dmaapModel) + .map(x -> state); + } catch (PrhTaskException e) { + LOGGER.warn("AAIProducerTask exception has been registered: ", e); return Mono.error(e); } } - private Mono<ResponseEntity<String>> publishToDmaapConfiguration(ConsumerDmaapModel monoAaiModel) { + private Mono<State> processAdditionalFields(final State state) { + if (state.activationStatus) { + LOGGER.debug("Re-registration - Logical links won't be updated."); + return Mono.just(state); + } + return bbsActionsTask.execute(state.dmaapModel).map(x -> state); + } + + private Flux<MessageRouterPublishResponse> publishToDmaapConfiguration(final State state) { try { - return dmaapProducerTask.execute(monoAaiModel); + if (state.activationStatus) { + LOGGER.debug("Re-registration - Using PNF_UPDATE DMaaP topic."); + return dmaapUpdateProducerTask.execute(state.dmaapModel); + } + return dmaapReadyProducerTask.execute(state.dmaapModel); } catch (PrhTaskException e) { - return Mono.error(e); + LOGGER.warn("DMaaPProducerTask exception has been registered: ", e); + return Flux.error(e); } } diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasksRunner.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasksRunner.java index 956ffead..25ed262e 100644 --- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasksRunner.java +++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasksRunner.java @@ -20,26 +20,20 @@ package org.onap.dcaegen2.services.prh.tasks; -import io.swagger.annotations.ApiOperation; import java.time.Duration; -import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ScheduledFuture; -import javax.annotation.PostConstruct; -import org.onap.dcaegen2.services.prh.configuration.CloudConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.Marker; import org.slf4j.MarkerFactory; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; +import org.springframework.context.event.EventListener; import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableScheduling; -import reactor.core.publisher.Mono; /** @@ -48,38 +42,30 @@ import reactor.core.publisher.Mono; @Configuration @EnableScheduling public class ScheduledTasksRunner { - private static final int SCHEDULING_DELAY_FOR_PRH_TASKS = 10; - private static final int SCHEDULING_REQUEST_FOR_CONFIGURATION_DELAY = 5; private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTasksRunner.class); private static final Marker ENTRY = MarkerFactory.getMarker("ENTRY"); private static volatile List<ScheduledFuture> scheduledPrhTaskFutureList = new ArrayList<>(); private final TaskScheduler taskScheduler; private final ScheduledTasks scheduledTask; - private final CloudConfiguration cloudConfiguration; - @Autowired - public ScheduledTasksRunner(TaskScheduler taskScheduler, - ScheduledTasks scheduledTask, - CloudConfiguration cloudConfiguration) { + public ScheduledTasksRunner(TaskScheduler taskScheduler, ScheduledTasks scheduledTask) { this.taskScheduler = taskScheduler; this.scheduledTask = scheduledTask; - this.cloudConfiguration = cloudConfiguration; + } + + @EventListener + public void onApplicationStartedEvent(ApplicationStartedEvent applicationStartedEvent) { + tryToStartTask(); } /** * Function which have to stop tasks execution. - * - * @return response entity about status of cancellation operation */ - @ApiOperation(value = "Get response on stopping task execution") - public synchronized Mono<ResponseEntity<String>> getResponseFromCancellationOfTasks() { + public synchronized void cancelTasks() { scheduledPrhTaskFutureList.forEach(x -> x.cancel(false)); scheduledPrhTaskFutureList.clear(); - return Mono.defer(() -> - Mono.just(new ResponseEntity<>("PRH Service has already been stopped!", HttpStatus.CREATED)) - ); } /** @@ -87,16 +73,10 @@ public class ScheduledTasksRunner { * * @return status of operation execution: true - started, false - not started */ - - @PostConstruct - @ApiOperation(value = "Start task if possible") public synchronized boolean tryToStartTask() { LOGGER.info(ENTRY, "Start scheduling PRH workflow"); if (scheduledPrhTaskFutureList.isEmpty()) { scheduledPrhTaskFutureList.add(taskScheduler - .scheduleAtFixedRate(cloudConfiguration::runTask, Instant.now(), - Duration.ofMinutes(SCHEDULING_REQUEST_FOR_CONFIGURATION_DELAY))); - scheduledPrhTaskFutureList.add(taskScheduler .scheduleWithFixedDelay(scheduledTask::scheduleMainPrhEventTask, Duration.ofSeconds(SCHEDULING_DELAY_FOR_PRH_TASKS))); return true; diff --git a/prh-app-server/src/main/resources/META-INF/spring.factories b/prh-app-server/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..78fde6e2 --- /dev/null +++ b/prh-app-server/src/main/resources/META-INF/spring.factories @@ -0,0 +1 @@ +org.springframework.cloud.bootstrap.BootstrapConfiguration=org.onap.dcaegen2.services.bootstrap.CbsBootstrapConfiguration
\ No newline at end of file diff --git a/prh-app-server/src/main/resources/application.yaml b/prh-app-server/src/main/resources/application.yaml index 88d1e401..2d244887 100644 --- a/prh-app-server/src/main/resources/application.yaml +++ b/prh-app-server/src/main/resources/application.yaml @@ -9,11 +9,17 @@ server: key-store: classpath:keystore-local key-password: nokiapnf keyAlias: tomcat-localhost + +management.endpoints.web.exposure.include: "loggers,refresh,env,health" + +--- +spring: + profiles: dev logging: level: - ROOT: ERROR - org.onap.dcaegen2.services.prh: INFO - reactor.ipc.netty.http.client: WARN - org.springframework: ERROR - org.springframework.data: ERROR - org.springframework.web.reactive: WARN + org.onap.dcaegen2.services.prh: debug + org.onap.dcaegen2.services.sdk: debug + +management.endpoints.web.exposure.include: "*" + + diff --git a/prh-app-server/src/main/resources/bootstrap.yaml b/prh-app-server/src/main/resources/bootstrap.yaml new file mode 100644 index 00000000..176c6bec --- /dev/null +++ b/prh-app-server/src/main/resources/bootstrap.yaml @@ -0,0 +1,23 @@ +spring: + application: + name: dcae-prh + + cloud: + config: + enabled: false + + +logging: + level: + org.springframework.boot.SpringApplication: warn + org.springframework.context.support.PostProcessorRegistrationDelegate: warn + +cbs: + hostname: cbs + port: 10000 + app-name: dcae-prh + updates-interval: 5m + fetch-retries: + max-attempts: 10 + first-backoff: 3s + max-backoff: 15s
\ No newline at end of file diff --git a/prh-app-server/src/main/resources/logback-spring.xml b/prh-app-server/src/main/resources/logback-spring.xml index d6a37ade..060cf6c5 100644 --- a/prh-app-server/src/main/resources/logback-spring.xml +++ b/prh-app-server/src/main/resources/logback-spring.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<configuration> +<configuration debug="false" scan="false"> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <property name="outputFilename" value="prh-app-server_output"/> <property name="logPath" value="/var/log/ONAP/prh/prh-app-server"/> @@ -16,8 +16,6 @@ |%replace(%replace(%marker){'\t','\\\\t'}){'\n','\\\\n'} |%thread |%n"/> - <variable name="logLevel" value="${LOG_LEVEL:-ERROR}"/> - <variable name="logLevelPrh" value="${PRH_LOG_LEVEL:-WARN}"/> <springProfile name="prod"> <appender class="ch.qos.logback.core.ConsoleAppender" name="CONSOLE" target="SYSTEM_OUT"> @@ -39,11 +37,20 @@ </rollingPolicy> </appender> - <logger name="org.onap.dcaegen2.services.prh" level="${logLevelPrh}"/> - - <root level="${logLevel}"> + <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="ROLLING-FILE"/> </root> </springProfile> + + <springProfile name="dev"> + <appender class="ch.qos.logback.core.ConsoleAppender" name="CONSOLE" target="SYSTEM_OUT"> + <encoder> + <pattern>${CONSOLE_LOG_PATTERN}</pattern> <!-- from org/springframework/boot/logging/logback/defaults.xml --> + </encoder> + </appender> + <root level="INFO"> + <appender-ref ref="CONSOLE"/> + </root> + </springProfile> </configuration> diff --git a/prh-app-server/src/main/resources/prh_endpoints.json b/prh-app-server/src/main/resources/prh_endpoints.json deleted file mode 100644 index 2e224833..00000000 --- a/prh-app-server/src/main/resources/prh_endpoints.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "configs": { - "dmaap": { - "dmaapConsumerConfiguration": { - "dmaapHostName": "localhost", - "dmaapPortNumber": 2222, - "dmaapTopicName": "/events/unauthenticated.VES_PNFREG_OUTPUT", - "dmaapProtocol": "http", - "dmaapUserName": "admin", - "dmaapUserPassword": "admin", - "dmaapContentType": "application/json", - "consumerId": "c12", - "consumerGroup": "OpenDcae-c12", - "timeoutMs": -1, - "messageLimit": 1 - }, - "dmaapProducerConfiguration": { - "dmaapHostName": "localhost", - "dmaapPortNumber": 2223, - "dmaapTopicName": "/events/unauthenticated.PNF_READY", - "dmaapProtocol": "http", - "dmaapUserName": "admin", - "dmaapUserPassword": "admin", - "dmaapContentType": "application/json" - } - }, - "aai": { - "aaiClientConfiguration": { - "aaiHost": "localhost", - "aaiPort": 8080, - "aaiProtocol": "https", - "aaiUserName": "AAI", - "aaiUserPassword": "AAI", - "aaiIgnoreSslCertificateErrors": true, - "aaiBasePath": "/aai/v12", - "aaiPnfPath": "/network/pnfs/pnf", - "aaiHeaders": { - "X-FromAppId": "prh", - "X-TransactionId": "9999", - "Accept": "application/json", - "Real-Time": "true", - "Content-Type": "application/merge-patch+json" - } - } - }, - "security": { - "trustStorePath" : "change it", - "trustStorePasswordPath" : "change it", - "keyStorePath" : "change it", - "keyStorePasswordPath" : "change it", - "enableAaiCertAuth" : "false", - "enableDmaapCertAuth" : "false" - } - } -}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/bootstrap/CbsClientConfigurationResolverTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/bootstrap/CbsClientConfigurationResolverTest.java new file mode 100644 index 00000000..87dd18ca --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/bootstrap/CbsClientConfigurationResolverTest.java @@ -0,0 +1,51 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.bootstrap; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsClientConfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +class CbsClientConfigurationResolverTest { + + private CbsProperties cbsProperties; + + @BeforeEach + void setUp() { + cbsProperties = new CbsProperties(); + cbsProperties.setHostname("some-cbs-host"); + cbsProperties.setPort(123); + cbsProperties.setAppName("client-app-name"); + } + + @Test + @DisabledIfEnvironmentVariable(named = "CONFIG_BINDING_SERVICE", matches = ".+") + void whenCbsEnvPropertiesAreNotePresentInEnvironment_ShouldFallbackToLoadingDefaultsFromCbsProperties() { + CbsClientConfiguration config = new CbsClientConfigurationResolver(cbsProperties).resolveCbsClientConfiguration(); + + assertThat(config.hostname()).isEqualTo(cbsProperties.getHostname()); + assertThat(config.port()).isEqualTo(cbsProperties.getPort()); + assertThat(config.appName()).isEqualTo(cbsProperties.getAppName()); + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/bootstrap/CbsJsonToPropertyMapConverterTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/bootstrap/CbsJsonToPropertyMapConverterTest.java new file mode 100644 index 00000000..55e1b014 --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/bootstrap/CbsJsonToPropertyMapConverterTest.java @@ -0,0 +1,80 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.bootstrap; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class CbsJsonToPropertyMapConverterTest { + + private static final JsonObject SOME_JSON_FROM_CBS = asJsonObject( + "{\n" + + " \"config\": {\n" + + " \"someStringProp\": \"foo\",\n" + + " \"someNumericalProp\": 123,\n" + + " \"someBooleanProp\": true,\n" + + " \"someArrayProp\": [],\n" + + " \"someObjectProp\": {\n" + + " \"bar\": \"baz\"\n" + + " }\n" + + " }\n" + + "}" + ); + + private CbsJsonToPropertyMapConverter cbsJsonToPropertyMapConverter = new CbsJsonToPropertyMapConverter(); + + @Test + void shouldExtractPrimitivePropertiesToSimpleJavaTypes() { + Map<String, Object> map = cbsJsonToPropertyMapConverter.convertToMap(SOME_JSON_FROM_CBS); + + assertThat(map).containsEntry("someStringProp", "foo"); + assertThat(map).containsEntry("someNumericalProp", 123L); + assertThat(map).containsEntry("someBooleanProp", true); + + } + + @Test + void shouldSkipComplexProperties() { + Map<String, Object> map = cbsJsonToPropertyMapConverter.convertToMap(SOME_JSON_FROM_CBS); + + assertThat(map).doesNotContainKeys("someObjectProp"); + assertThat(map).doesNotContainKeys("someArrayProp"); + } + + @Test + void shouldProduceDescriptiveExceptionInCaseExpectedRootElementInCbsJsonIsMissing() { + assertThatThrownBy(() -> cbsJsonToPropertyMapConverter.convertToMap(asJsonObject("{}"))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Missing expected 'config' property in json from CBS."); + } + + + private static JsonObject asJsonObject(String jsonString) { + return new JsonParser().parse(jsonString).getAsJsonObject(); + } + +}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/bootstrap/CbsPropertySourceLocatorTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/bootstrap/CbsPropertySourceLocatorTest.java new file mode 100644 index 00000000..faf1867a --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/bootstrap/CbsPropertySourceLocatorTest.java @@ -0,0 +1,164 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.bootstrap; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonObject; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.dcaegen2.services.prh.configuration.CbsConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsClient; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsRequests; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsClientConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsRequest; +import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.RequestPath; +import org.onap.dcaegen2.services.sdk.rest.services.model.logging.RequestDiagnosticContext; +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertySource; +import reactor.core.publisher.Mono; +import reactor.test.scheduler.VirtualTimeScheduler; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assumptions.assumeThat; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.*; + + +@ExtendWith(MockitoExtension.class) +class CbsPropertySourceLocatorTest { + + private static final RequestPath GET_ALL_REQUEST_PATH = CbsRequests.getAll(RequestDiagnosticContext.create()).requestPath(); + + private CbsProperties cbsProperties = new CbsProperties(); + @Mock + private CbsJsonToPropertyMapConverter cbsJsonToPropertyMapConverter; + @Mock + private CbsClientConfiguration cbsClientConfiguration; + @Mock + private CbsClientConfigurationResolver cbsClientConfigurationResolver; + @Mock + private CbsClientFactoryFacade cbsClientFactoryFacade; + @Mock + private CbsConfiguration cbsConfiguration; + @Mock + private Environment environment; + @Mock + private CbsClient cbsClient; + @Mock + private JsonObject cbsConfigJsonObject; + private Map<String, Object> cbsConfigMap = ImmutableMap.of("foo", "bar"); + + private VirtualTimeScheduler virtualTimeScheduler; + + private CbsPropertySourceLocator cbsPropertySourceLocator; + + + @BeforeEach + void setup() { + virtualTimeScheduler = VirtualTimeScheduler.getOrSet(); + + when(cbsClientConfigurationResolver.resolveCbsClientConfiguration()).thenReturn(cbsClientConfiguration); + when(cbsClientFactoryFacade.createCbsClient(cbsClientConfiguration)).thenReturn(Mono.just(cbsClient)); + + cbsPropertySourceLocator = new CbsPropertySourceLocator( + cbsProperties, cbsJsonToPropertyMapConverter, cbsClientConfigurationResolver, + cbsClientFactoryFacade, cbsConfiguration); + } + + @AfterEach + void cleanup() { + virtualTimeScheduler.dispose(); + } + + + @Test + void shouldBuildCbsPropertySourceBasedOnDataFetchedUsingCbsClient() { + when(cbsClient.get(argThat(request -> request.requestPath().equals(GET_ALL_REQUEST_PATH)))) + .thenReturn(Mono.just(cbsConfigJsonObject)); + when(cbsJsonToPropertyMapConverter.convertToMap(cbsConfigJsonObject)).thenReturn(cbsConfigMap); + + PropertySource<?> propertySource = cbsPropertySourceLocator.locate(environment); + + assertThat(propertySource).extracting(PropertySource::getName).isEqualTo("cbs"); + assertThat(propertySource).extracting(s -> s.getProperty("foo")).isEqualTo("bar"); + } + + + @Test + void shouldUpdateCbsConfigurationStateBasedOnDataFetchedUsingCbsClient() { + when(cbsClient.get(argThat(request -> request.requestPath().equals(GET_ALL_REQUEST_PATH)))) + .thenReturn(Mono.just(cbsConfigJsonObject)); + when(cbsJsonToPropertyMapConverter.convertToMap(cbsConfigJsonObject)).thenReturn(cbsConfigMap); + + cbsPropertySourceLocator.locate(environment); + + verify(cbsConfiguration).parseCBSConfig(cbsConfigJsonObject); + } + + + @Test + void shouldPropagateExceptionWhenCbsConfigurationParsingFails() { + when(cbsClient.get(any(CbsRequest.class))).thenReturn(Mono.just(cbsConfigJsonObject)); + + RuntimeException someCbsConfigParsingException = new RuntimeException("boom!"); + doThrow(someCbsConfigParsingException).when(cbsConfiguration).parseCBSConfig(cbsConfigJsonObject); + + assertThatThrownBy(() -> cbsPropertySourceLocator.locate(environment)) + .isSameAs(someCbsConfigParsingException); + } + + @Test + void shouldRetryFetchingConfigFromCbsInCaseOfFailure() { + assumeThat(cbsProperties.getFetchRetries().getMaxAttempts()).isGreaterThan(1); + when(cbsClient.get(any(CbsRequest.class))) + .thenReturn(Mono.defer(() -> { + virtualTimeScheduler.advanceTimeBy(cbsProperties.getFetchRetries().getMaxBackoff()); + return Mono.error(new RuntimeException("some connection failure")); + })) + .thenReturn(Mono.just(cbsConfigJsonObject)); + when(cbsJsonToPropertyMapConverter.convertToMap(cbsConfigJsonObject)).thenReturn(cbsConfigMap); + + PropertySource<?> propertySource = cbsPropertySourceLocator.locate(environment); + + assertThat(propertySource).extracting(s -> s.getProperty("foo")).isEqualTo("bar"); + } + + @Test + void shouldFailAfterExhaustingAllOfConfiguredRetryAttempts() { + assumeThat(cbsProperties.getFetchRetries().getMaxAttempts()).isGreaterThan(1); + when(cbsClient.get(any(CbsRequest.class))) + .thenReturn(Mono.defer(() -> { + virtualTimeScheduler.advanceTimeBy(cbsProperties.getFetchRetries().getMaxBackoff()); + return Mono.error(new RuntimeException("some connection failure")); + })); + + assertThatThrownBy(() -> cbsPropertySourceLocator.locate(environment)) + .hasMessageContaining("Retries exhausted") + .hasMessageContaining(cbsProperties.getFetchRetries().getMaxAttempts().toString()); + } +} diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/TestAppConfiguration.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/TestAppConfiguration.java index cdfffbd1..c11fe492 100644 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/TestAppConfiguration.java +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/TestAppConfiguration.java @@ -20,65 +20,57 @@ package org.onap.dcaegen2.services.prh; +import org.onap.dcaegen2.services.sdk.model.streams.dmaap.ImmutableMessageRouterSink; +import org.onap.dcaegen2.services.sdk.model.streams.dmaap.ImmutableMessageRouterSource; import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.ImmutableAaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapPublisherConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.ContentType; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.ImmutableMessageRouterPublishRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.ImmutableMessageRouterSubscribeRequest; + +import java.time.Duration; public class TestAppConfiguration { - public static ImmutableDmaapConsumerConfiguration createDefaultDmaapConsumerConfiguration() { - return new ImmutableDmaapConsumerConfiguration.Builder() + public static ImmutableMessageRouterSubscribeRequest createDefaultMessageRouterSubscribeRequest() { + return ImmutableMessageRouterSubscribeRequest.builder() .consumerGroup("OpenDCAE-c12") + .sourceDefinition(ImmutableMessageRouterSource.builder() + .name("the topic") + .topicUrl(String.format("http://%s:%d/events/TOPIC", "www", 1234)) + .build()) .consumerId("c12") - .dmaapContentType("application/json") - .dmaapHostName("message-router.onap.svc.cluster.local") - .dmaapPortNumber(3904) - .dmaapProtocol("http") - .dmaapUserName("admin") - .dmaapUserPassword("admin") - .trustStorePath("/opt/app/prh/local/org.onap.prh.trust.jks") - .trustStorePasswordPath("change_it") - .keyStorePath("/opt/app/prh/local/org.onap.prh.p12") - .keyStorePasswordPath("change_it") - .enableDmaapCertAuth(false) - .dmaapTopicName("/events/unauthenticated.SEC_OTHER_OUTPUT") - .timeoutMs(-1) - .messageLimit(-1) + .timeout(Duration.ofMillis(1)) .build(); } - public static ImmutableDmaapPublisherConfiguration createDefaultDmaapPublisherConfiguration() { - return new ImmutableDmaapPublisherConfiguration.Builder() - .dmaapContentType("application/json") - .dmaapHostName("message-router.onap.svc.cluster.local") - .dmaapPortNumber(3904) - .dmaapProtocol("http") - .dmaapUserName("admin") - .dmaapUserPassword("admin") - .trustStorePath("/opt/app/prh/local/org.onap.prh.trust.jks") - .trustStorePasswordPath("change_it") - .keyStorePath("/opt/app/prh/local/org.onap.prh.p12") - .keyStorePasswordPath("change_it") - .enableDmaapCertAuth(false) - .dmaapTopicName("/events/unauthenticated.PNF_READY") + public static ImmutableMessageRouterPublishRequest createDefaultMessageRouterPublishRequest() { + return ImmutableMessageRouterPublishRequest.builder() + .contentType(ContentType.APPLICATION_JSON) + .sinkDefinition(ImmutableMessageRouterSink.builder() + .name("the topic") + .topicUrl(String.format("http://%s:%d/events/TOPIC", "www", 1234)) + .build()) .build(); - } + + } public static ImmutableAaiClientConfiguration createDefaultAaiClientConfiguration() { return new ImmutableAaiClientConfiguration.Builder() - .aaiHost("aai.onap.svc.cluster.local") - .aaiPort(8443) - .aaiProtocol("https") + .pnfUrl("https://aai.onap.svc.cluster.local:8443/aai/v12/network/pnfs/pnf") .aaiUserName("AAI") .aaiUserPassword("AAI") .aaiIgnoreSslCertificateErrors(true) - .aaiBasePath("/aai/v12") - .aaiPnfPath("/network/pnfs/pnf") + .aaiServiceInstancePath("/business/customers/customer/${customer}/service-subscriptions/service-subscription/${serviceType}/service-instances/service-instance/${serviceInstanceId}") .trustStorePath("/opt/app/prh/local/org.onap.prh.trust.jks") .trustStorePasswordPath("change_it") .keyStorePath("/opt/app/prh/local/org.onap.prh.p12") .keyStorePasswordPath("change_it") .enableAaiCertAuth(false) + .putAaiHeaders("X-FromAppId","prh") + .putAaiHeaders("X-TransactionId","9999") + .putAaiHeaders("Accept","application/json") + .putAaiHeaders("Real-Time","true") + .putAaiHeaders("Authorization","Basic QUFJOkFBSQ==") .build(); } }
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/CbsConfigRefreshSchedulerTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/CbsConfigRefreshSchedulerTest.java new file mode 100644 index 00000000..7ea08aea --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/CbsConfigRefreshSchedulerTest.java @@ -0,0 +1,138 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.configuration; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.cloud.context.environment.EnvironmentChangeEvent; +import org.springframework.cloud.context.refresh.ContextRefresher; +import org.springframework.core.env.Environment; +import reactor.test.scheduler.VirtualTimeScheduler; + +import java.time.Duration; +import java.util.Collections; + +import static org.mockito.Mockito.*; + + +@ExtendWith(MockitoExtension.class) +class CbsConfigRefreshSchedulerTest { + + private static final Duration SOME_UPDATES_INTERVAL = Duration.ofMinutes(5); + private static final String CBS_UPDATES_INTERVAL_PROPERTY = "cbs.updates-interval"; + + @Mock + private ContextRefresher contextRefresher; + @Mock + private Environment environment; + + private VirtualTimeScheduler virtualTimeScheduler; + + private CbsConfigRefreshScheduler cbsConfigRefreshScheduler; + + + @BeforeEach + void setUp() { + virtualTimeScheduler = VirtualTimeScheduler.getOrSet(); + when(environment.getProperty(CBS_UPDATES_INTERVAL_PROPERTY, Duration.class, Duration.ZERO)) + .thenReturn(SOME_UPDATES_INTERVAL); + + cbsConfigRefreshScheduler = new CbsConfigRefreshScheduler(contextRefresher, environment); + } + + @AfterEach + void tearDown() { + virtualTimeScheduler.dispose(); + } + + @Test + void configRefreshUpdatesShouldBeFiredAccordingToConfiguredInterval() { + cbsConfigRefreshScheduler.startPollingForCbsUpdates(); + + verify(contextRefresher, times(0)).refresh(); + + virtualTimeScheduler.advanceTimeBy(SOME_UPDATES_INTERVAL); + verify(contextRefresher, times(1)).refresh(); + + virtualTimeScheduler.advanceTimeBy(SOME_UPDATES_INTERVAL); + verify(contextRefresher, times(2)).refresh(); + } + + @Test + void whenConfigUpdateIntervalIsSetToZero_UpdatesShouldNotBeExecuted() { + when(environment.getProperty(CBS_UPDATES_INTERVAL_PROPERTY, Duration.class, Duration.ZERO)) + .thenReturn(Duration.ZERO); + + cbsConfigRefreshScheduler.startPollingForCbsUpdates(); + + virtualTimeScheduler.advanceTimeBy(Duration.ofHours(10)); + + verifyZeroInteractions(contextRefresher); + } + + @Test + void whenUpdateFails_shouldContinueWithUpdateRequestsAccordingToConfiguredSchedule() { + when(contextRefresher.refresh()) + .thenThrow(new RuntimeException("kaboom!")) + .thenReturn(Collections.emptySet()); + + cbsConfigRefreshScheduler.startPollingForCbsUpdates(); + + virtualTimeScheduler.advanceTimeBy(SOME_UPDATES_INTERVAL.plus(SOME_UPDATES_INTERVAL)); + verify(contextRefresher, times(2)).refresh(); + } + + + @Test + void whenUpdatesIntervalIsChangedInEnvironment_UpdatesShouldBeRescheduled() { + when(environment.getProperty(CBS_UPDATES_INTERVAL_PROPERTY, Duration.class, Duration.ZERO)) + .thenReturn(Duration.ofMinutes(30)) + .thenReturn(Duration.ofSeconds(10)); + + cbsConfigRefreshScheduler.startPollingForCbsUpdates(); + + cbsConfigRefreshScheduler.onEnvironmentChanged( + new EnvironmentChangeEvent(Collections.singleton(CBS_UPDATES_INTERVAL_PROPERTY))); + + virtualTimeScheduler.advanceTimeBy(Duration.ofMinutes(1)); + + verify(contextRefresher, times(6)).refresh(); + } + + + @Test + void whenEnvironmentChangeDoesNotAffectUpdatesInterval_UpdatesScheduleShouldNotBeImpacted() { + cbsConfigRefreshScheduler.startPollingForCbsUpdates(); + + Duration envChangeDelay = Duration.ofMinutes(1); + virtualTimeScheduler.advanceTimeBy(envChangeDelay); + + cbsConfigRefreshScheduler.onEnvironmentChanged(new EnvironmentChangeEvent(Collections.emptySet())); + + virtualTimeScheduler.advanceTimeBy(SOME_UPDATES_INTERVAL.minus(envChangeDelay)); + + verify(contextRefresher).refresh(); + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/CbsConfigurationTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/CbsConfigurationTest.java new file mode 100644 index 00000000..7f5d26fc --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/CbsConfigurationTest.java @@ -0,0 +1,70 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.configuration; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.junit.jupiter.api.Test; + +import java.nio.file.Files; +import java.nio.file.Paths; + +import static java.lang.ClassLoader.getSystemResource; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class CbsConfigurationTest { + + private static final String EXPECTED_ERROR_MESSAGE_WHEN_CBS_CONFIG_IS_NOT_INITIALIZED = "CBS config missing"; + + @Test + void whenConfigurationIsNotInitializedBasedOnDataReceivedFromCbs_shouldThrowExceptionWithDescriptiveMessage() { + assertThatThrownBy(() -> new CbsConfiguration().getAaiClientConfiguration()) + .hasMessage(EXPECTED_ERROR_MESSAGE_WHEN_CBS_CONFIG_IS_NOT_INITIALIZED); + assertThatThrownBy(() -> new CbsConfiguration().getMessageRouterPublisher()) + .hasMessage(EXPECTED_ERROR_MESSAGE_WHEN_CBS_CONFIG_IS_NOT_INITIALIZED); + assertThatThrownBy(() -> new CbsConfiguration().getMessageRouterSubscriber()) + .hasMessage(EXPECTED_ERROR_MESSAGE_WHEN_CBS_CONFIG_IS_NOT_INITIALIZED); + assertThatThrownBy(() -> new CbsConfiguration().getMessageRouterSubscribeRequest()) + .hasMessage(EXPECTED_ERROR_MESSAGE_WHEN_CBS_CONFIG_IS_NOT_INITIALIZED); + assertThatThrownBy(() -> new CbsConfiguration().getMessageRouterPublishRequest()) + .hasMessage(EXPECTED_ERROR_MESSAGE_WHEN_CBS_CONFIG_IS_NOT_INITIALIZED); + assertThatThrownBy(() -> new CbsConfiguration().getMessageRouterUpdatePublishRequest()) + .hasMessage(EXPECTED_ERROR_MESSAGE_WHEN_CBS_CONFIG_IS_NOT_INITIALIZED); + } + + + @Test + void cbsConfigurationShouldExposeDataReceivedAsJsonFromCbs() throws Exception { + JsonObject cbsConfigJson = new Gson().fromJson(new String(Files.readAllBytes(Paths.get( + getSystemResource("configurationFromCbs.json").toURI()))), JsonObject.class); + CbsConfiguration cbsConfiguration = new CbsConfiguration(); + + cbsConfiguration.parseCBSConfig(cbsConfigJson); + + assertThat(cbsConfiguration.getAaiClientConfiguration()).isNotNull(); + assertThat(cbsConfiguration.getMessageRouterPublisher()).isNotNull(); + assertThat(cbsConfiguration.getMessageRouterSubscriber()).isNotNull(); + assertThat(cbsConfiguration.getMessageRouterPublishRequest()).isNotNull(); + assertThat(cbsConfiguration.getMessageRouterSubscribeRequest()).isNotNull(); + assertThat(cbsConfiguration.getMessageRouterUpdatePublishRequest()).isNotNull(); + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/CloudConfigParserTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/CloudConfigParserTest.java deleted file mode 100644 index 8f421034..00000000 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/CloudConfigParserTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PNF-REGISTRATION-HANDLER - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.configuration; - -import static java.lang.ClassLoader.getSystemResource; -import static org.assertj.core.api.Assertions.assertThat; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import java.nio.file.Files; -import java.nio.file.Paths; -import org.junit.jupiter.api.Test; -import org.onap.dcaegen2.services.prh.TestAppConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.ImmutableAaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.ImmutableDmaapPublisherConfiguration; - - -class CloudConfigParserTest { - - private final String correctJson = - new String(Files.readAllBytes(Paths.get(getSystemResource("flattened_configuration.json").toURI()))); - private final ImmutableAaiClientConfiguration correctAaiClientConfig = - TestAppConfiguration.createDefaultAaiClientConfiguration(); - private final ImmutableDmaapConsumerConfiguration correctDmaapConsumerConfig = - TestAppConfiguration.createDefaultDmaapConsumerConfiguration(); - private final ImmutableDmaapPublisherConfiguration correctDmaapPublisherConfig = - TestAppConfiguration.createDefaultDmaapPublisherConfiguration(); - private final CloudConfigParser cloudConfigParser = new CloudConfigParser( - new Gson().fromJson(correctJson, JsonObject.class)); - - CloudConfigParserTest() throws Exception { - } - - @Test - void shouldCreateAaiConfigurationCorrectly() { - // when - AaiClientConfiguration aaiClientConfig = cloudConfigParser.getAaiClientConfig(); - - // then - assertThat(aaiClientConfig).isNotNull(); - assertThat(aaiClientConfig).isEqualToComparingFieldByField(correctAaiClientConfig); - } - - - @Test - void shouldCreateDmaapConsumerConfigurationCorrectly() { - // when - DmaapConsumerConfiguration dmaapConsumerConfig = cloudConfigParser.getDmaapConsumerConfig(); - - // then - assertThat(dmaapConsumerConfig).isNotNull(); - assertThat(dmaapConsumerConfig).isEqualToComparingFieldByField(correctDmaapConsumerConfig); - } - - - @Test - void shouldCreateDmaapPublisherConfigurationCorrectly() { - // when - DmaapPublisherConfiguration dmaapPublisherConfig = cloudConfigParser.getDmaapPublisherConfig(); - - // then - assertThat(dmaapPublisherConfig).isNotNull(); - assertThat(dmaapPublisherConfig).isEqualToComparingFieldByField(correctDmaapPublisherConfig); - } -}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/ConsulConfigurationParserTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/ConsulConfigurationParserTest.java new file mode 100644 index 00000000..3a4db1dd --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/ConsulConfigurationParserTest.java @@ -0,0 +1,169 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.configuration; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.services.prh.TestAppConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.ImmutableAaiClientConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.ContentType; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterPublishRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterSubscribeRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.config.MessageRouterPublisherConfig; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.config.MessageRouterSubscriberConfig; +import org.onap.dcaegen2.services.sdk.security.ssl.SecurityKeys; + +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.Duration; + +import static java.lang.ClassLoader.getSystemResource; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeFalse; + + +class ConsulConfigurationParserTest { + + private final String correctJson = + new String(Files.readAllBytes(Paths.get(getSystemResource("configurationFromCbs.json").toURI()))); + private final ImmutableAaiClientConfiguration correctAaiClientConfig = + TestAppConfiguration.createDefaultAaiClientConfiguration(); + + private final JsonObject correctConfig = new Gson().fromJson(correctJson, JsonObject.class); + private final CbsContentParser consulConfigurationParser = new CbsContentParser(correctConfig); + + ConsulConfigurationParserTest() throws Exception { + } + + @Test + void shouldCreateAaiConfigurationCorrectly() { + // when + AaiClientConfiguration aaiClientConfig = consulConfigurationParser.getAaiClientConfig(); + + // then + assertThat(aaiClientConfig).isNotNull(); + assertThat(aaiClientConfig).isEqualToComparingFieldByField(correctAaiClientConfig); + } + + @Test + void shouldCreateMessageRouterSubscribeRequestCorrectly() { + // given + MessageRouterSubscribeRequest messageRouterSubscribeRequest = consulConfigurationParser.getMessageRouterSubscribeRequest(); + + // then + assertThat(messageRouterSubscribeRequest.sourceDefinition().topicUrl()).isEqualTo("http://dmaap-mr:2222/events/unauthenticated.VES_PNFREG_OUTPUT"); + assertThat(messageRouterSubscribeRequest.consumerGroup()).isEqualTo("OpenDCAE-c12"); + assertThat(messageRouterSubscribeRequest.consumerId()).isEqualTo("c12"); + assertThat(messageRouterSubscribeRequest.timeout()).isEqualTo(Duration.ofMillis(-1)); + } + + @Test + void shouldCreateMessageRouterPublishConfigurationCorrectly() { + // when + MessageRouterPublishRequest messageRouterPublishRequest = consulConfigurationParser.getMessageRouterPublishRequest(); + + // then + assertThat(messageRouterPublishRequest.contentType()).isEqualTo(ContentType.APPLICATION_JSON); + assertThat(messageRouterPublishRequest.sinkDefinition().topicUrl()).isEqualTo("http://dmaap-mr:2222/events/unauthenticated.PNF_READY"); + } + + @Test + void shouldCreateMessageRouterUpdatePublishConfigurationCorrectly() { + // when + MessageRouterPublishRequest messageRouterPublishRequest = consulConfigurationParser.getMessageRouterUpdatePublishRequest(); + + // then + assertThat(messageRouterPublishRequest.contentType()).isEqualTo(ContentType.APPLICATION_JSON); + assertThat(messageRouterPublishRequest.sinkDefinition().topicUrl()).isEqualTo("http://dmaap-mr:2222/events/unauthenticated.PNF_UPDATE"); + } + + @Test + void whenDmaapCertAuthIsDisabled_MessageRouterPublisherConfigSecurityKeysShouldBeIgnored() { + assumeFalse(correctConfig.getAsJsonObject("config").get("security.enableDmaapCertAuth").getAsBoolean()); + + MessageRouterPublisherConfig messageRouterPublisherConfig = consulConfigurationParser.getMessageRouterPublisherConfig(); + + assertThat(messageRouterPublisherConfig.securityKeys()).isNull(); + } + + @Test + void whenDmaapCertAuthIsDisabled_MessageRouterSubscriberConfigSecurityKeysShouldBeIgnored() { + assumeFalse(correctConfig.getAsJsonObject("config").get("security.enableDmaapCertAuth").getAsBoolean()); + + MessageRouterSubscriberConfig messageRouterSubscriberConfig = consulConfigurationParser.getMessageRouterSubscriberConfig(); + + assertThat(messageRouterSubscriberConfig.securityKeys()).isNull(); + } + + + @Test + void whenDmaapCertAuthIsEnabled_MessageRouterPublisherConfigSecurityKeysShouldBeLoaded() { + CbsContentParser consulConfigurationParser = new CbsContentParser(getConfigWithSslEnabled(correctJson)); + + MessageRouterPublisherConfig messageRouterPublisherConfig = consulConfigurationParser.getMessageRouterPublisherConfig(); + + verifySecurityKeys(messageRouterPublisherConfig.securityKeys()); + } + + + @Test + void whenDmaapCertAuthIsEnabled_MessageRouterSubscriberConfigSecurityKeysShouldBeLoaded() { + CbsContentParser consulConfigurationParser = new CbsContentParser(getConfigWithSslEnabled(correctJson)); + + MessageRouterSubscriberConfig messageRouterSubscriberConfig = consulConfigurationParser.getMessageRouterSubscriberConfig(); + + verifySecurityKeys(messageRouterSubscriberConfig.securityKeys()); + } + + private static void verifySecurityKeys(@Nullable SecurityKeys securityKeys) { + assertThat(securityKeys).isNotNull(); + assertThat(securityKeys.trustStore().path().endsWith("org.onap.dcae.trust.jks")).isTrue(); + assertThat(securityKeys.keyStore().path().endsWith("org.onap.dcae.jks")).isTrue(); + securityKeys.trustStorePassword().use(chars -> assertThat(new String(chars)).isEqualTo("*TQH?Lnszprs4LmlAj38yds(")); + securityKeys.keyStorePassword().use(chars -> assertThat(new String(chars)).isEqualTo("mYHC98!qX}7h?W}jRv}MIXTJ")); + } + + private static JsonObject getConfigWithSslEnabled(String configJsonString) { + JsonObject configJson = new Gson().fromJson(configJsonString, JsonObject.class); + JsonObject config = configJson.getAsJsonObject("config"); + config.addProperty("security.enableDmaapCertAuth", true); + config.addProperty("security.enableAaiCertAuth", true); + config.addProperty("security.trustStorePath", testResourceToPath("/org.onap.dcae.trust.jks")); + config.addProperty("security.trustStorePasswordPath", testResourceToPath("/truststore.password")); + config.addProperty("security.keyStorePath", testResourceToPath("/org.onap.dcae.jks")); + config.addProperty("security.keyStorePasswordPath", testResourceToPath("/keystore.password")); + return configJson; + } + + + private static String testResourceToPath(String resource) { + try { + return Paths.get(ConsulConfigurationParserTest.class.getResource(resource).toURI()).toString(); + } catch (URISyntaxException e) { + throw new RuntimeException("Failed resolving test resource path", e); + } + } + +}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfigTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfigTest.java deleted file mode 100644 index 42acc592..00000000 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfigTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PNF-REGISTRATION-HANDLER - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.configuration; - -import static java.lang.ClassLoader.getSystemResource; -import static java.nio.file.Files.readAllBytes; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Paths; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.onap.dcaegen2.services.prh.integration.junit5.mockito.MockitoExtension; -import org.springframework.core.io.InputStreamResource; -import org.springframework.core.io.Resource; - - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/9/18 - */ -@ExtendWith({MockitoExtension.class}) -class PrhAppConfigTest { - - private static final String CORRECT_CONFIG_FILE = "correct_config.json"; - private static final String INCORRECT_CONFIG_FILE = "incorrect_config.json"; - private static final String NOT_JSON_OBJECT_FILE = "not_json_object.json"; - private AppConfig appConfig; - - @BeforeEach - void setUp() { - appConfig = new AppConfig(); - } - - @Test - void whenTheConfigurationFits() throws Exception { - InputStream inputStream = createInputStream(CORRECT_CONFIG_FILE); - appConfig.setResourceFile(new InputStreamResource(inputStream)); - appConfig.initFileStreamReader(); - - assertNotNull(appConfig.getDmaapConsumerConfiguration()); - assertNotNull(appConfig.getDmaapPublisherConfiguration()); - assertNotNull(appConfig.getAaiClientConfiguration()); - } - - @Test - void whenFileDoesNotExist() throws Exception { - InputStream inputStream = createInputStream(CORRECT_CONFIG_FILE); - Resource resource = spy(new InputStreamResource(inputStream)); - when(resource.getInputStream()).thenThrow(new IOException()); - appConfig.setResourceFile(resource); - appConfig.initFileStreamReader(); - - assertNull(appConfig.getAaiClientConfiguration()); - assertNull(appConfig.getDmaapConsumerConfiguration()); - assertNull(appConfig.getDmaapPublisherConfiguration()); - } - - @Test - void whenFileExistsButDmaapPublisherJsonConfigurationIsIncorrect() throws Exception { - InputStream inputStream = createInputStream(INCORRECT_CONFIG_FILE); - appConfig.setResourceFile(new InputStreamResource(inputStream)); - appConfig.initFileStreamReader(); - - assertNotNull(appConfig.getAaiClientConfiguration()); - assertNotNull(appConfig.getDmaapConsumerConfiguration()); - assertNull(appConfig.getDmaapPublisherConfiguration()); - } - - @Test - void whenRootElementIsNotAJsonObject() throws Exception { - InputStream inputStream = createInputStream(NOT_JSON_OBJECT_FILE); - appConfig.setResourceFile(new InputStreamResource(inputStream)); - appConfig.initFileStreamReader(); - - - assertNull(appConfig.getAaiClientConfiguration()); - assertNull(appConfig.getDmaapConsumerConfiguration()); - assertNull(appConfig.getDmaapPublisherConfiguration()); - } - - private InputStream createInputStream(String jsonFile) throws Exception { - return new ByteArrayInputStream(readAllBytes(Paths.get(getSystemResource(jsonFile).toURI()))); - } -}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/controllers/AppInfoControllerTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/controllers/AppInfoControllerTest.java new file mode 100644 index 00000000..1dba66a1 --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/controllers/AppInfoControllerTest.java @@ -0,0 +1,69 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.controllers; + +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.services.prh.configuration.PrhAppConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.http.MediaType; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static org.mockito.Mockito.when; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@DirtiesContext +class AppInfoControllerTest { + + private static final String SAMPLE_GIT_INFO_CONTENT = "{ \"git.commit.id\" : \"37444e\" }"; + + @MockBean + private PrhAppConfig prhAppConfig; + + @Autowired + private WebTestClient webTestClient; + + @Test + void shouldProvideHeartbeatResponse() { + webTestClient + .get().uri("/heartbeat") + .accept(MediaType.TEXT_PLAIN) + .exchange() + .expectStatus().isOk() + .expectBody(String.class).isEqualTo("alive"); + } + + + @Test + void shouldProvideVersionInfo() { + when(prhAppConfig.getGitInfo()).thenReturn(new ByteArrayResource(SAMPLE_GIT_INFO_CONTENT.getBytes())); + + webTestClient + .get().uri("/version") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isOk() + .expectBody(String.class).isEqualTo(SAMPLE_GIT_INFO_CONTENT); + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/controllers/ScheduleControllerTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/controllers/ScheduleControllerTest.java new file mode 100644 index 00000000..ebdec09e --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/controllers/ScheduleControllerTest.java @@ -0,0 +1,75 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.controllers; + +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.services.prh.tasks.ScheduledTasksRunner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpStatus; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@DirtiesContext +class ScheduleControllerTest { + + @MockBean + private ScheduledTasksRunner scheduledTasksRunner; + + @Autowired + private WebTestClient webTestClient; + + @Test + void startEndpointShouldAllowStartingPrhTasks() { + when(scheduledTasksRunner.tryToStartTask()).thenReturn(true); + webTestClient + .get().uri("/start") + .exchange() + .expectStatus().isCreated() + .expectBody(String.class).isEqualTo("PRH Service has been started!"); + } + + @Test + void whenPrhTasksAreAlreadyStarted_shouldRespondThatRequestWasNotAccepted() { + when(scheduledTasksRunner.tryToStartTask()).thenReturn(false); + webTestClient + .get().uri("/start") + .exchange() + .expectStatus().isEqualTo(HttpStatus.NOT_ACCEPTABLE) + .expectBody(String.class).isEqualTo("PRH Service is already running!"); + } + + @Test + void stopEndpointShouldAllowStoppingPrhTasks() { + webTestClient + .get().uri("/stopPrh") + .exchange() + .expectStatus().isOk() + .expectBody(String.class).isEqualTo("PRH Service has been stopped!"); + + verify(scheduledTasksRunner).cancelTasks(); + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/PrhWorkflowIntegrationTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/PrhWorkflowIntegrationTest.java new file mode 100644 index 00000000..672cfc47 --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/PrhWorkflowIntegrationTest.java @@ -0,0 +1,124 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.integration; + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.jayway.jsonpath.JsonPath; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.services.prh.MainApp; +import org.onap.dcaegen2.services.prh.configuration.CbsConfiguration; +import org.onap.dcaegen2.services.prh.tasks.ScheduledTasks; +import org.onap.dcaegen2.services.prh.tasks.ScheduledTasksRunner; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import java.nio.file.Files; +import java.nio.file.Paths; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static java.lang.ClassLoader.getSystemResource; +import static java.util.Collections.singletonList; + + +@SpringBootTest +@AutoConfigureWireMock(port = 0) +class PrhWorkflowIntegrationTest { + + @Autowired + private ScheduledTasks scheduledTasks; + + @MockBean + private ScheduledTasksRunner scheduledTasksRunner; // just to disable scheduling - some configurability in ScheduledTaskRunner not to start tasks at app startup would be welcome + + + @Configuration + @Import(MainApp.class) + static class CbsConfigTestConfig { + + @Value("http://localhost:${wiremock.server.port}") + private String wiremockServerAddress; + + @Bean + public CbsConfiguration cbsConfiguration() { + JsonObject cbsConfigJson = new Gson().fromJson(getResourceContent("configurationFromCbs.json") + .replaceAll("https?://dmaap-mr[\\w.]*:\\d+", wiremockServerAddress) + .replaceAll("https?://aai[\\w.]*:\\d+", wiremockServerAddress), + JsonObject.class); + + CbsConfiguration cbsConfiguration = new CbsConfiguration(); + cbsConfiguration.parseCBSConfig(cbsConfigJson); + return cbsConfiguration; + } + } + + @BeforeEach + void resetWireMock() { + WireMock.reset(); + } + + + @Test + void whenThereAreNoEventsInDmaap_WorkflowShouldFinish() { + stubFor(get(urlEqualTo("/events/unauthenticated.VES_PNFREG_OUTPUT/OpenDCAE-c12/c12")) + .willReturn(aResponse().withBody("[]"))); + + scheduledTasks.scheduleMainPrhEventTask(); + + verify(0, anyRequestedFor(urlPathMatching("/aai.*"))); + verify(0, postRequestedFor(urlPathMatching("/events.*"))); + } + + + @Test + void whenThereIsAnEventsInDmaap_ShouldSendPnfReadyNotification() { + String event = getResourceContent("integration/event.json"); + String pnfName = JsonPath.read(event, "$.event.commonEventHeader.sourceName"); + + stubFor(get(urlEqualTo("/events/unauthenticated.VES_PNFREG_OUTPUT/OpenDCAE-c12/c12")) + .willReturn(ok().withBody(new Gson().toJson(singletonList(event))))); + stubFor(get(urlEqualTo("/aai/v12/network/pnfs/pnf/" + pnfName)).willReturn(ok().withBody("{}"))); + stubFor(patch(urlEqualTo("/aai/v12/network/pnfs/pnf/" + pnfName))); + stubFor(post(urlEqualTo("/events/unauthenticated.PNF_READY"))); + + scheduledTasks.scheduleMainPrhEventTask(); + + verify(1, postRequestedFor(urlEqualTo("/events/unauthenticated.PNF_READY")) + .withRequestBody(matchingJsonPath("$[0].correlationId", equalTo(pnfName)))); + } + + + private static String getResourceContent(String resourceName) { + try { + return new String(Files.readAllBytes(Paths.get(getSystemResource(resourceName).toURI()))); + } catch (Exception e) { + throw new RuntimeException("failed loading content of '" + resourceName + "'", e); + } + } +} diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/PrhWorkflowSchedulingIntegrationTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/PrhWorkflowSchedulingIntegrationTest.java new file mode 100644 index 00000000..44dcabfa --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/PrhWorkflowSchedulingIntegrationTest.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.integration; + +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.services.prh.tasks.ScheduledTasks; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import static org.mockito.Mockito.verify; + + +@SpringBootTest +class PrhWorkflowSchedulingIntegrationTest { + + @MockBean + private ScheduledTasks scheduledTasks; + + @Test + void prhWorkflowShouldBeExecutedRightAfterApplicationStart() { + verify(scheduledTasks).scheduleMainPrhEventTask(); + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/ScheduledXmlContextITest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/ScheduledXmlContextITest.java deleted file mode 100644 index 934f572f..00000000 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/ScheduledXmlContextITest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.integration; - -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.verify; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.onap.dcaegen2.services.prh.integration.junit5.mockito.MockitoExtension; -import org.onap.dcaegen2.services.prh.tasks.ScheduledTasks; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.test.context.testng.AbstractTestNGSpringContextTests; - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/27/18 - */ -@Configuration -@ComponentScan("org.onap.dcaegen2.services.sdk.rest.services.cbs.client.providers") -@ExtendWith({MockitoExtension.class, SpringExtension.class}) -@ContextConfiguration(locations = "classpath:scheduled-context.xml") -class ScheduledXmlContextITest extends AbstractTestNGSpringContextTests { - - private static final int WAIT_FOR_SCHEDULING = 1; - - @Autowired - private ScheduledTasks scheduledTask; - - @Test - void testScheduling() { - final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); - executorService.scheduleWithFixedDelay(this::verifyDmaapConsumerTask, 0, WAIT_FOR_SCHEDULING, TimeUnit.SECONDS); - } - - private void verifyDmaapConsumerTask() { - verify(scheduledTask, atLeast(1)).scheduleMainPrhEventTask(); - } -} diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/junit5/mockito/MockitoExtension.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/junit5/mockito/MockitoExtension.java deleted file mode 100644 index af9c2b44..00000000 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/integration/junit5/mockito/MockitoExtension.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.integration.junit5.mockito; - -import static org.mockito.Mockito.mock; - -import java.lang.reflect.Parameter; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.api.extension.ExtensionContext.Namespace; -import org.junit.jupiter.api.extension.ExtensionContext.Store; -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.api.extension.ParameterResolver; -import org.junit.jupiter.api.extension.TestInstancePostProcessor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/27/18 - * - * {@code MockitoExtension } showcases the {@link TestInstancePostProcessor} and {@link ParameterResolver} - * extension APIs of JUnit 5 by providing dependency injection support at the field level and at the method - * parameter level viaMockito 2.x's {@link Mock @Mock} annotation. - */ -public class MockitoExtension implements TestInstancePostProcessor, ParameterResolver { - - @Override - public void postProcessTestInstance(Object testInstance, ExtensionContext context) { - MockitoAnnotations.initMocks(testInstance); - } - - @Override - public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { - return parameterContext.getParameter().isAnnotationPresent(Mock.class); - } - - @Override - public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { - return getMock(parameterContext.getParameter(), extensionContext); - } - - private Object getMock(Parameter parameter, ExtensionContext extensionContext) { - Class<?> mockType = parameter.getType(); - Store mocks = extensionContext.getStore(Namespace.create(MockitoExtension.class, mockType)); - String mockName = getMockName(parameter); - - if (mockName != null) { - return mocks.getOrComputeIfAbsent(mockName, key -> mock(mockType, mockName)); - } else { - return mocks.getOrComputeIfAbsent(mockType.getCanonicalName(), key -> mock(mockType)); - } - } - - private String getMockName(Parameter parameter) { - String explicitMockName = parameter.getAnnotation(Mock.class).name().trim(); - if (!explicitMockName.isEmpty()) { - return explicitMockName; - } else if (parameter.isNamePresent()) { - return parameter.getName(); - } - return null; - } - - -} diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/service/DmaapConsumerJsonParserTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/service/DmaapConsumerJsonParserTest.java index 01ce7419..342460e3 100644 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/service/DmaapConsumerJsonParserTest.java +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/service/DmaapConsumerJsonParserTest.java @@ -20,210 +20,300 @@ package org.onap.dcaegen2.services.prh.service; -import static org.mockito.Mockito.spy; - import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import java.util.Optional; +import io.vavr.collection.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; import org.onap.dcaegen2.services.prh.model.ImmutableConsumerDmaapModel; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.ImmutableMessageRouterSubscribeResponse; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterSubscribeResponse; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import java.util.Optional; + +import static org.mockito.Mockito.spy; + /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/8/18 */ class DmaapConsumerJsonParserTest { + private JsonParser jsonParser = new JsonParser(); + @Test void whenPassingCorrectJson_validationNotThrowingAnException() { //given - String message = "[{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," + String message = "{\"event\": {" + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," + + " \"vendorName\": \"nokia\"," + " \"serialNumber\": \"QTFCOC540002E\"," + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," + " \"oamV4IpAddress\": \"10.16.123.234\"," + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" - + "}}}]"; + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {\"attachmentPoint\":\"bla-bla-30-3\",\"cvlan\":\"678\",\"svlan\":\"1005\"}" + + "}}}"; String parsed = "{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," + + " \"vendorName\": \"nokia\"," + " \"serialNumber\": \"QTFCOC540002E\"," + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," + " \"oamV4IpAddress\": \"10.16.123.234\"," + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {\"attachmentPoint\":\"bla-bla-30-3\",\"cvlan\":\"678\",\"svlan\":\"1005\"}" + "}}}"; - ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234") + JsonObject jsonObject = new JsonParser().parse("{\n" + + " \"attachmentPoint\": \"bla-bla-30-3\",\n" + + " \"cvlan\": \"678\",\n" + + " \"svlan\": \"1005\"\n" + + " }").getAsJsonObject(); + + ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder() + .ipv4("10.16.123.234") .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") - .correlationId("NOKQTFCOC540002E").build(); + .correlationId("NOKQTFCOC540002E") + .serialNumber("QTFCOC540002E") + .equipVendor("nokia") + .equipModel("3310") + .equipType("type") + .nfRole("gNB") + .swVersion("v4.5.0.1") + .additionalFields(jsonObject) + .build(); + + List<JsonElement> messageAsJsonElementList = List.of(message).map(jsonParser::parse); + MessageRouterSubscribeResponse response = ImmutableMessageRouterSubscribeResponse.builder().items(messageAsJsonElementList).build(); + //when DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); - JsonElement jsonElement = new JsonParser().parse(parsed); + JsonElement jsonElement = jsonParser.parse(parsed); Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); + ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser - .getJsonObject(Mono.just((message))).blockFirst(); + .getJsonObject(Mono.just((response))).blockFirst(); //then Assertions.assertNotNull(consumerDmaapModel); Assertions.assertEquals(expectedObject, consumerDmaapModel); } @Test - void whenPassingCorrectJsonWithoutIpv4_validationNotThrowingAnException() { + void whenPassingJsonWithoutAdditionalFields_validationNotThrowingAnException() { //given - String message = "[{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," + String message = "{\"event\": {" + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," + + " \"vendorName\": \"nokia\"," + " \"serialNumber\": \"QTFCOC540002E\"," + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," - + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" - + "}}}]"; + + " \"oamV4IpAddress\": \"10.16.123.234\"," + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"softwareVersion\": \"v4.5.0.1\"" + + "}}}"; String parsed = "{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," + + " \"vendorName\": \"nokia\"," + " \"serialNumber\": \"QTFCOC540002E\"," + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," - + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" + + " \"oamV4IpAddress\": \"10.16.123.234\"," + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"softwareVersion\": \"v4.5.0.1\"" + "}}}"; + ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder() + .correlationId("NOKQTFCOC540002E") + .serialNumber("QTFCOC540002E") + .ipv4("10.16.123.234") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .equipVendor("nokia") + .equipModel("3310") + .equipType("type") + .nfRole("gNB") + .swVersion("v4.5.0.1") + .build(); + List<JsonElement> messageAsJsonElementList = List.of(message).map(jsonParser::parse); + MessageRouterSubscribeResponse response = ImmutableMessageRouterSubscribeResponse.builder().items(messageAsJsonElementList).build(); //when DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); JsonElement jsonElement = new JsonParser().parse(parsed); Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); - dmaapConsumerJsonParser.getJsonObject(Mono.just((message))); - ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser.getJsonObject(Mono.just((message))) - .blockFirst(); + ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser + .getJsonObject(Mono.just((response))).blockFirst(); //then - ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder().ipv4("") - .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") - .correlationId("NOKQTFCOC540002E").build(); Assertions.assertNotNull(consumerDmaapModel); Assertions.assertEquals(expectedObject, consumerDmaapModel); } @Test - void whenPassingCorrectJsonWithoutIpv6_validationNotThrowingAnException() { + void whenPassingJsonWithEmptyAdditionalFields_validationNotThrowingAnException() { //given - String message = "[{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," + String message = "{\"event\": {" + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," + + " \"vendorName\": \"nokia\"," + " \"serialNumber\": \"QTFCOC540002E\"," + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," + + " \"softwareVersion\": \"v4.5.0.1\"," + " \"oamV4IpAddress\": \"10.16.123.234\"," - + " \"softwareVersion\": \"v4.5.0.1\"" - + "}}}]"; + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {}" + + "}}}"; String parsed = "{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," + + " \"vendorName\": \"nokia\"," + " \"serialNumber\": \"QTFCOC540002E\"," + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," + + " \"softwareVersion\": \"v4.5.0.1\"," + " \"oamV4IpAddress\": \"10.16.123.234\"," - + " \"softwareVersion\": \"v4.5.0.1\"" + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {}" + "}}}"; - ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234").ipv6("") - .correlationId("NOKQTFCOC540002E").build(); + ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder() + .correlationId("NOKQTFCOC540002E") + .serialNumber("QTFCOC540002E") + .ipv4("10.16.123.234") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .equipVendor("nokia") + .equipModel("3310") + .equipType("type") + .nfRole("gNB") + .swVersion("v4.5.0.1") + .additionalFields(new JsonObject()) + .build(); + + List<JsonElement> messageAsJsonElementList = List.of(message).map(jsonParser::parse); + MessageRouterSubscribeResponse response = ImmutableMessageRouterSubscribeResponse.builder().items(messageAsJsonElementList).build(); + //when DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); - JsonElement jsonElement = new JsonParser().parse(parsed); + JsonElement jsonElement = jsonParser.parse(parsed); Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); - ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser.getJsonObject(Mono.just((message))) - .blockFirst(); + + ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser + .getJsonObject(Mono.just((response))).blockFirst(); //then Assertions.assertNotNull(consumerDmaapModel); Assertions.assertEquals(expectedObject, consumerDmaapModel); } @Test - void whenPassingCorrectJsonWithoutIpv4andIpv6_validationAddingAnException() { + void whenPassingCorrectJsonWithoutIpv4andIpv6_validationNotThrowingAnException() { //given - String message = "[{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," + String message = "{\"event\": {" + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," + + " \"vendorName\": \"nokia\"," + " \"serialNumber\": \"QTFCOC540002E\"," + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," - + " \"softwareVersion\": \"v4.5.0.1\"" - + "}}}]"; + + " \"softwareVersion\": \"v4.5.0.1\"," + + " \"additionalFields\": {}" + + "}}}"; String parsed = "{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," + + " \"vendorName\": \"nokia\"," + " \"serialNumber\": \"QTFCOC540002E\"," + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," - + " \"softwareVersion\": \"v4.5.0.1\"" + + " \"softwareVersion\": \"v4.5.0.1\"," + + " \"additionalFields\": {}" + "}}}"; + ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder() + .correlationId("NOKQTFCOC540002E") + .serialNumber("QTFCOC540002E") + .ipv4("") + .ipv6("") + .equipVendor("nokia") + .equipModel("3310") + .equipType("type") + .nfRole("gNB") + .swVersion("v4.5.0.1") + .additionalFields(new JsonObject()) + .build(); + + List<JsonElement> messageAsJsonElementList = List.of(message).map(jsonParser::parse); + MessageRouterSubscribeResponse response = ImmutableMessageRouterSubscribeResponse.builder().items(messageAsJsonElementList).build(); + + //when DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); - JsonElement jsonElement = new JsonParser().parse(parsed); + JsonElement jsonElement = jsonParser.parse(parsed); Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); - StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(message))) - .expectSubscription().thenRequest(1).verifyComplete(); + ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser + .getJsonObject(Mono.just((response))).blockFirst(); + //then + Assertions.assertNotNull(consumerDmaapModel); + Assertions.assertEquals(expectedObject, consumerDmaapModel); } + @Test void whenPassingJsonWithoutMandatoryHeaderInformation_validationAddingAnException() { String parsed = "{\"event\": {" @@ -237,14 +327,17 @@ class DmaapConsumerJsonParserTest { + " \"lastServiceDate\": \"1535014037024\"," + " \"unitFamily\": \"BBU\"," + " \"vendorName\": \"Nokia\"," - + " \"softwareVersion\": \"v4.5.0.1\"" + + " \"softwareVersion\": \"v4.5.0.1\"," + + " \"oamV4IpAddress\": \"10.16.123.234\"," + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {}" + "}}}"; DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); - JsonElement jsonElement = new JsonParser().parse(parsed); + JsonElement jsonElement = jsonParser.parse(parsed); Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); - String incorrectMessage = "[{\"event\": {" + String incorrectMessage = "{\"event\": {" + "\"commonEventHeader\": {}," + "\"pnfRegistrationFields\": {" + " \"unitType\": \"AirScale\"," @@ -255,9 +348,16 @@ class DmaapConsumerJsonParserTest { + " \"lastServiceDate\": \"1535014037024\"," + " \"unitFamily\": \"BBU\"," + " \"vendorName\": \"Nokia\"," - + " \"softwareVersion\": \"v4.5.0.1\"" - + "}}}]"; - StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(incorrectMessage))) + + " \"softwareVersion\": \"v4.5.0.1\"," + + " \"oamV4IpAddress\": \"10.16.123.234\"," + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {}" + + "}}}"; + + List<JsonElement> incorrectMessageAsJsonElementList = List.of(incorrectMessage).map(jsonParser::parse); + MessageRouterSubscribeResponse response = ImmutableMessageRouterSubscribeResponse.builder().items(incorrectMessageAsJsonElementList).build(); + + StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(response))) .expectSubscription().thenRequest(1).verifyComplete(); } @@ -275,15 +375,16 @@ class DmaapConsumerJsonParserTest { + " \"unitFamily\": \"BBU\"," + " \"vendorName\": \"Nokia\"," + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {}" + "}}}"; DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); - JsonElement jsonElement = new JsonParser().parse(parsed); + JsonElement jsonElement = jsonParser.parse(parsed); Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); String jsonWithoutSourceName = - "[{\"event\": {" + "{\"event\": {" + "\"commonEventHeader\": {}," + "\"pnfRegistrationFields\": {" + " \"unitType\": \"AirScale\"," @@ -295,19 +396,24 @@ class DmaapConsumerJsonParserTest { + " \"unitFamily\": \"BBU\"," + " \"vendorName\": \"Nokia\"," + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" - + "}}}]"; + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {}" + + "}}}"; + + List<JsonElement> jsonWithoutSourceNameAsJsonElementList = List.of(jsonWithoutSourceName).map(jsonParser::parse); + MessageRouterSubscribeResponse response = ImmutableMessageRouterSubscribeResponse.builder().items(jsonWithoutSourceNameAsJsonElementList).build(); StepVerifier - .create(dmaapConsumerJsonParser.getJsonObject(Mono.just(jsonWithoutSourceName))) + .create(dmaapConsumerJsonParser.getJsonObject(Mono.just(response))) .expectSubscription().thenRequest(1) .verifyComplete(); + } @Test - void whenPassingJsonWithoutIpInformation_validationAddingAnException() { + void whenPassingJsonWithoutSourceNameValue_validationAddingAnException() { String parsed = "{\"event\": {" - + "\"commonEventHeader\": {\"sourceName\": \"NOKQTFCOC540002E\"}," + + "\"commonEventHeader\": {\"sourceName\": \"\"}," + "\"pnfRegistrationFields\": {" + " \"unitType\": \"AirScale\"," + " \"serialNumber\": \"QTFCOC540002E\"," @@ -318,37 +424,16 @@ class DmaapConsumerJsonParserTest { + " \"unitFamily\": \"BBU\"," + " \"vendorName\": \"Nokia\"," + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV4IpAddress\": \"\"," - + " \"oamV6IpAddress\": \"\"" + + " \"oamV4IpAddress\": \"10.16.123.234\"," + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {}" + "}}}"; DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); - JsonElement jsonElement = new JsonParser().parse(parsed); + JsonElement jsonElement = jsonParser.parse(parsed); Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); String jsonWithoutIpInformation = - "[{\"event\": {" - + "\"commonEventHeader\": {\"sourceName\": \"NOKQTFCOC540002E\"}," - + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," - + " \"serialNumber\": \"QTFCOC540002E\"," - + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," - + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," - + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV4IpAddress\": \"\"," - + " \"oamV6IpAddress\": \"\"" - + "}}}]"; - StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(jsonWithoutIpInformation))) - .expectSubscription().thenRequest(1).verifyComplete(); - } - - @Test - void whenPassingJsonWithoutSourceNameValue_validationAddingAnException() { - String parsed = "{\"event\": {" + "\"commonEventHeader\": {\"sourceName\": \"\"}," + "\"pnfRegistrationFields\": {" @@ -362,76 +447,204 @@ class DmaapConsumerJsonParserTest { + " \"vendorName\": \"Nokia\"," + " \"softwareVersion\": \"v4.5.0.1\"," + " \"oamV4IpAddress\": \"10.16.123.234\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {}" + "}}}"; + List<JsonElement> jsonWithoutIpInformationAsJsonElementList = List.of(jsonWithoutIpInformation).map(jsonParser::parse); + MessageRouterSubscribeResponse response = ImmutableMessageRouterSubscribeResponse.builder().items(jsonWithoutIpInformationAsJsonElementList).build(); + + StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(response))) + .expectSubscription().thenRequest(1).verifyComplete(); + } + + @Test + void whenPassingCorrectJsonWithoutIpv4_validationNotThrowingAnException() { + //given + String message = "{\"event\": {" + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + + "\"pnfRegistrationFields\": {" + + " \"vendorName\": \"nokia\"," + + " \"serialNumber\": \"QTFCOC540002E\"," + + " \"pnfRegistrationFieldsVersion\": \"2.0\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + + " \"unitFamily\": \"BBU\"," + + " \"softwareVersion\": \"v4.5.0.1\"," + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" + + "}}}"; + + String parsed = "{\"event\": {" + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + + "\"pnfRegistrationFields\": {" + + " \"vendorName\": \"nokia\"," + + " \"serialNumber\": \"QTFCOC540002E\"," + + " \"pnfRegistrationFieldsVersion\": \"2.0\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + + " \"unitFamily\": \"BBU\"," + + " \"softwareVersion\": \"v4.5.0.1\"," + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" + + "}}}"; + + List<JsonElement> messageAsJsonElementList = List.of(message).map(jsonParser::parse); + MessageRouterSubscribeResponse response = ImmutableMessageRouterSubscribeResponse.builder().items(messageAsJsonElementList).build(); + //when DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); - JsonElement jsonElement = new JsonParser().parse(parsed); + JsonElement jsonElement = jsonParser.parse(parsed); Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); - String jsonWithoutIpInformation = - "[{\"event\": {" - + "\"commonEventHeader\": {\"sourceName\": \"\"}," - + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," - + " \"serialNumber\": \"QTFCOC540002E\"," - + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," - + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," - + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV4IpAddress\": \"10.16.123.234\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" - + "}}}]"; - StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(jsonWithoutIpInformation))) - .expectSubscription().thenRequest(1).verifyComplete(); + + dmaapConsumerJsonParser.getJsonObject(Mono.just((response))); + ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser.getJsonObject(Mono.just(response)) + .blockFirst(); + //then + ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder() + .ipv4("") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .correlationId("NOKQTFCOC540002E") + .serialNumber("QTFCOC540002E") + .equipVendor("nokia") + .equipModel("3310") + .equipType("type") + .nfRole("gNB") + .swVersion("v4.5.0.1") + .build(); + Assertions.assertNotNull(consumerDmaapModel); + Assertions.assertEquals(expectedObject, consumerDmaapModel); + } @Test - void whenPassingCorrectJsoArraynWithoutIpv4_validationNotThrowingAnException() { + void whenPassingCorrectJsonWithoutIpv6_validationNotThrowingAnException() { //given - String message = "[{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," + String message = "{\"event\": {" + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," + + " \"vendorName\": \"nokia\"," + " \"serialNumber\": \"QTFCOC540002E\"," + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," + " \"oamV4IpAddress\": \"10.16.123.234\"," + + " \"softwareVersion\": \"v4.5.0.1\"" + + "}}}"; + + String parsed = "{\"event\": {" + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + + "\"pnfRegistrationFields\": {" + + " \"vendorName\": \"nokia\"," + + " \"serialNumber\": \"QTFCOC540002E\"," + + " \"pnfRegistrationFieldsVersion\": \"2.0\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + + " \"unitFamily\": \"BBU\"," + + " \"oamV4IpAddress\": \"10.16.123.234\"," + + " \"softwareVersion\": \"v4.5.0.1\"" + + "}}}"; + + ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder() + .ipv4("10.16.123.234") + .ipv6("") + .correlationId("NOKQTFCOC540002E") + .serialNumber("QTFCOC540002E") + .equipVendor("nokia") + .equipModel("3310") + .equipType("type") + .nfRole("gNB") + .swVersion("v4.5.0.1") + .build(); + + List<JsonElement> messageAsJsonElementList = List.of(message).map(jsonParser::parse); + MessageRouterSubscribeResponse response = ImmutableMessageRouterSubscribeResponse.builder().items(messageAsJsonElementList).build(); + + //when + DmaapConsumerJsonParser dmaapConsumerJsonParser = spy(new DmaapConsumerJsonParser()); + JsonElement jsonElement = jsonParser.parse(parsed); + Mockito.doReturn(Optional.of(jsonElement.getAsJsonObject())) + .when(dmaapConsumerJsonParser).getJsonObjectFromAnArray(jsonElement); + ConsumerDmaapModel consumerDmaapModel = dmaapConsumerJsonParser.getJsonObject(Mono.just(response)) + .blockFirst(); + + //then + Assertions.assertNotNull(consumerDmaapModel); + Assertions.assertEquals(expectedObject, consumerDmaapModel); + + } + + @Test + void whenPassingCorrectJsonArrayWithoutIpv4_validationNotThrowingAnException() { + //given + String message = "[{\"event\": {" + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + " }," + + "\"pnfRegistrationFields\": {" + + " \"vendorName\": \"nokia\"," + + " \"serialNumber\": \"QTFCOC540002E\"," + + " \"pnfRegistrationFieldsVersion\": \"2.0\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + + " \"unitFamily\": \"BBU\"," + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {}" + "}}}," - + "{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," + + " {\"event\": {" + + "\"commonEventHeader\": { " + + " \"sourceName\":\"NOKQTFCOC540002E\"," + + " \"nfNamingCode\":\"gNB\" " + + "}," + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," + + " \"vendorName\": \"nokia\"," + " \"serialNumber\": \"QTFCOC540002E\"," + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," + + " \"modelNumber\": \"3310\"," + + " \"unitType\": \"type\",\n" + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," - + " \"oamV4IpAddress\": \"10.16.123.234\"," + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" - + "}}}" - + "]"; + + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"," + + " \"additionalFields\": {}" + + "}}}]"; - ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234") + ConsumerDmaapModel expectedObject = ImmutableConsumerDmaapModel.builder() + .ipv4("") .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") - .correlationId("NOKQTFCOC540002E").build(); + .correlationId("NOKQTFCOC540002E") + .serialNumber("QTFCOC540002E") + .equipVendor("nokia") + .equipModel("3310") + .equipType("type") + .nfRole("gNB") + .swVersion("v4.5.0.1") + .additionalFields(new JsonObject()) + .build(); + + List<JsonElement> messageAsJsonElementList = List.empty(); + for(JsonElement el : jsonParser.parse(message).getAsJsonArray()) { + messageAsJsonElementList = messageAsJsonElementList.append(el); + } + + MessageRouterSubscribeResponse response = ImmutableMessageRouterSubscribeResponse.builder().items(messageAsJsonElementList).build(); + //when DmaapConsumerJsonParser dmaapConsumerJsonParser = new DmaapConsumerJsonParser(); //then - StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(message))) - .expectSubscription().expectNext(expectedObject).expectNext(expectedObject).verifyComplete(); + StepVerifier.create(dmaapConsumerJsonParser.getJsonObject(Mono.just(response))).expectSubscription().expectNext(expectedObject).expectNext(expectedObject).verifyComplete(); } } diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTaskImplTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTaskImplTest.java index 32e66386..0077a6a6 100644 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTaskImplTest.java +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTaskImplTest.java @@ -20,34 +20,28 @@ package org.onap.dcaegen2.services.prh.tasks; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - - -import javax.net.ssl.SSLException; +import com.google.gson.JsonObject; +import io.netty.handler.codec.http.HttpResponseStatus; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import org.onap.dcaegen2.services.prh.TestAppConfiguration; -import org.onap.dcaegen2.services.prh.configuration.AppConfig; +import org.onap.dcaegen2.services.prh.configuration.CbsConfiguration; import org.onap.dcaegen2.services.prh.exceptions.PrhTaskException; import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; import org.onap.dcaegen2.services.prh.model.ImmutableConsumerDmaapModel; import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.patch.AaiReactiveHttpPatchClient; - -import org.springframework.http.HttpStatus; -import org.springframework.web.reactive.function.client.ClientResponse; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.patch.AaiHttpPatchClient; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpResponse; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import javax.net.ssl.SSLException; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/14/18 */ @@ -56,26 +50,35 @@ class AaiProducerTaskImplTest { private ConsumerDmaapModel consumerDmaapModel; private AaiProducerTaskImpl aaiProducerTask; private AaiClientConfiguration aaiClientConfiguration; - private AaiReactiveHttpPatchClient aaiReactiveHttpPatchClient; - private AppConfig appConfig; - private ClientResponse clientResponse; + private AaiHttpPatchClient aaiReactiveHttpPatchClient; + private CbsConfiguration cbsConfiguration; + private HttpResponse clientResponse; @BeforeEach void setUp() { - clientResponse = mock(ClientResponse.class); + clientResponse = mock(HttpResponse.class); aaiClientConfiguration = TestAppConfiguration.createDefaultAaiClientConfiguration(); - consumerDmaapModel = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234") - .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") - .correlationId("NOKQTFCOC540002E").build(); - appConfig = mock(AppConfig.class); + consumerDmaapModel = ImmutableConsumerDmaapModel.builder() + .ipv4("10.16.123.234") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .correlationId("NOKQTFCOC540002E") + .serialNumber("QTFCOC540002E") + .equipVendor("nokia") + .equipModel("3310") + .equipType("type") + .nfRole("role") + .swVersion("v4.5.0.1") + .additionalFields(new JsonObject()) + .build(); + cbsConfiguration = mock(CbsConfiguration.class); } @Test void whenPassedObjectDoesntFit_ThrowsPrhTaskException() { //given/when/ - when(appConfig.getAaiClientConfiguration()).thenReturn(aaiClientConfiguration); - aaiProducerTask = new AaiProducerTaskImpl(appConfig); + when(cbsConfiguration.getAaiClientConfiguration()).thenReturn(aaiClientConfiguration); + aaiProducerTask = new AaiProducerTaskImpl(aaiReactiveHttpPatchClient); Executable executableCode = () -> aaiProducerTask.execute(null); //then @@ -86,11 +89,11 @@ class AaiProducerTaskImplTest { @Test void whenPassedObjectFits_ReturnsCorrectStatus() throws PrhTaskException, SSLException { //given/when - getAaiProducerTask_whenMockingResponseObject(200); + getAaiProducerTask_whenMockingResponseObject(HttpResponseStatus.OK); Mono<ConsumerDmaapModel> response = aaiProducerTask.execute(consumerDmaapModel); //then - verify(aaiReactiveHttpPatchClient, times(1)).getAaiProducerResponse(any()); + verify(aaiReactiveHttpPatchClient, times(1)).getAaiResponse(any()); verifyNoMoreInteractions(aaiReactiveHttpPatchClient); Assertions.assertEquals(consumerDmaapModel, response.block()); @@ -99,24 +102,22 @@ class AaiProducerTaskImplTest { @Test void whenPassedObjectFits_butIncorrectResponseReturns() throws PrhTaskException, SSLException { //given/when - getAaiProducerTask_whenMockingResponseObject(400); + getAaiProducerTask_whenMockingResponseObject(HttpResponseStatus.BAD_REQUEST); StepVerifier.create(aaiProducerTask.execute(consumerDmaapModel)).expectSubscription() .expectError(PrhTaskException.class).verify(); //then - verify(aaiReactiveHttpPatchClient, times(1)).getAaiProducerResponse(any()); + verify(aaiReactiveHttpPatchClient, times(1)).getAaiResponse(any()); verifyNoMoreInteractions(aaiReactiveHttpPatchClient); } - private void getAaiProducerTask_whenMockingResponseObject(int statusCode) throws SSLException { + private void getAaiProducerTask_whenMockingResponseObject(HttpResponseStatus httpResponseStatus) throws SSLException { //given - doReturn(HttpStatus.valueOf(statusCode)).when(clientResponse).statusCode(); - Mono<ClientResponse> clientResponseMono = Mono.just(clientResponse); - aaiReactiveHttpPatchClient = mock(AaiReactiveHttpPatchClient.class); - when(aaiReactiveHttpPatchClient.getAaiProducerResponse(any())) + doReturn(httpResponseStatus.code()).when(clientResponse).statusCode(); + Mono<HttpResponse> clientResponseMono = Mono.just(clientResponse); + aaiReactiveHttpPatchClient = mock(AaiHttpPatchClient.class); + when(aaiReactiveHttpPatchClient.getAaiResponse(any())) .thenReturn(clientResponseMono); - when(appConfig.getAaiClientConfiguration()).thenReturn(aaiClientConfiguration); - aaiProducerTask = spy(new AaiProducerTaskImpl(appConfig)); - when(aaiProducerTask.resolveConfiguration()).thenReturn(aaiClientConfiguration); - doReturn(aaiReactiveHttpPatchClient).when(aaiProducerTask).resolveClient(); + when(cbsConfiguration.getAaiClientConfiguration()).thenReturn(aaiClientConfiguration); + aaiProducerTask = spy(new AaiProducerTaskImpl(aaiReactiveHttpPatchClient)); } }
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/AaiPublisherTaskSpy.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/AaiPublisherTaskSpy.java deleted file mode 100644 index a63910c0..00000000 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/AaiPublisherTaskSpy.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.tasks; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; - -import javax.net.ssl.SSLException; -import org.onap.dcaegen2.services.prh.configuration.AppConfig; -import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.patch.AaiReactiveHttpPatchClient; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; - - - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 - */ -@Configuration -public class AaiPublisherTaskSpy { - - /** - * Mocking bean for tests. - * - * @return A&AI ProducerTask spy - */ - @Bean - @Primary - public AaiProducerTask registerSimpleAaiPublisherTask() throws SSLException { - AppConfig appConfig = spy(AppConfig.class); - ConsumerDmaapModel consumerDmaapModel = spy(ConsumerDmaapModel.class); - doReturn(mock(AaiClientConfiguration.class)).when(appConfig).getAaiClientConfiguration(); - AaiProducerTaskImpl aaiProducerTask = spy(new AaiProducerTaskImpl(appConfig)); - AaiReactiveHttpPatchClient aaiReactiveHttpPatchClient = mock(AaiReactiveHttpPatchClient.class); - doReturn(mock(AaiClientConfiguration.class)).when(aaiProducerTask).resolveConfiguration(); - doReturn(aaiReactiveHttpPatchClient).when(aaiProducerTask).resolveClient(); - return aaiProducerTask; - } -} diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/AaiQueryTaskImplTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/AaiQueryTaskImplTest.java new file mode 100644 index 00000000..512d1eda --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/AaiQueryTaskImplTest.java @@ -0,0 +1,206 @@ +/* + * ============LICENSE_START======================================================= + * PROJECT + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.tasks; + +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.dcaegen2.services.prh.model.AaiPnfResultModel; +import org.onap.dcaegen2.services.prh.model.AaiServiceInstanceResultModel; +import org.onap.dcaegen2.services.prh.model.ImmutableRelationshipData; +import org.onap.dcaegen2.services.prh.model.Relationship; +import org.onap.dcaegen2.services.prh.model.RelationshipData; +import org.onap.dcaegen2.services.prh.model.RelationshipDict; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.AaiHttpClient; +import org.onap.dcaegen2.services.sdk.rest.services.model.AaiModel; +import org.onap.dcaegen2.services.sdk.rest.services.model.AaiServiceInstanceQueryModel; +import reactor.core.publisher.Mono; + +import java.util.Collections; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class AaiQueryTaskImplTest { + @Mock + private AaiHttpClient<AaiModel, AaiPnfResultModel> getPnfModelClient; + + @Mock + private AaiHttpClient<AaiServiceInstanceQueryModel, AaiServiceInstanceResultModel> getServiceClient; + + @Mock + private AaiPnfResultModel pnfResultModel; + + @Mock + private Relationship pnfRelationships; + + @Mock + private RelationshipDict pnfRelation; + + @Mock + private AaiServiceInstanceResultModel serviceModel; + + private List<RelationshipData> allRelationData; + + private AaiQueryTask sut; + + private final AaiModel aaiModel = () -> "SomePNF"; + + @BeforeEach + void setUp() { + allRelationData = Lists.list( + ImmutableRelationshipData.builder() + .relationshipKey(AaiQueryTaskImpl.CUSTOMER).relationshipValue("Foo").build(), + ImmutableRelationshipData.builder() + .relationshipKey(AaiQueryTaskImpl.SERVICE_TYPE).relationshipValue("Bar").build(), + ImmutableRelationshipData.builder() + .relationshipKey(AaiQueryTaskImpl.SERVICE_INSTANCE_ID).relationshipValue("Baz").build() + ); + + sut = new AaiQueryTaskImpl(getPnfModelClient, getServiceClient); + } + + @Test + void whenPnfIsUnavailable_ShouldThrowException() { + //given + given(getPnfModelClient.getAaiResponse(aaiModel)).willReturn(Mono.error(new Exception("404"))); + + //when + final Mono<Boolean> task = sut.execute(aaiModel); + + //then + Assertions.assertThrows(Exception.class, task::block); + } + + @Test + void whenPnfIsAvailableButRelationshipIsNull_ShouldReturnFalse() { + //given + given(pnfResultModel.getRelationshipList()).willReturn(null); + + configurePnfClient(aaiModel, pnfResultModel); + + //when + final Mono<Boolean> task = sut.execute(aaiModel); + + //then + Assertions.assertFalse(task::block); + } + + @Test + void whenPnfIsAvailableButRelationshipIsEmpty_ShouldReturnFalse() { + //given + given(pnfRelationships.getRelationship()).willReturn(Collections.emptyList()); + given(pnfResultModel.getRelationshipList()).willReturn(pnfRelationships); + configurePnfClient(aaiModel, pnfResultModel); + + //when + final Mono<Boolean> task = sut.execute(aaiModel); + + //then + Assertions.assertFalse(task::block); + } + + @Test + void whenPnfIsAvailableButServiceRelationIsMissing_ShouldReturnFalse() { + //given + given(pnfRelation.getRelatedTo()).willReturn("some-other-relation"); + given(pnfRelationships.getRelationship()).willReturn(Collections.singletonList(pnfRelation)); + given(pnfResultModel.getRelationshipList()).willReturn(pnfRelationships); + + configurePnfClient(aaiModel, pnfResultModel); + + //when + final Mono<Boolean> task = sut.execute(aaiModel); + + //then + Assertions.assertFalse(task::block); + } + + @Test + void whenPnfIsAvailableButServiceRelationIsMissingRequiredKey_ShouldReturnFalse() { + //given + Collections.shuffle(allRelationData); + allRelationData.remove(0); + + given(pnfRelation.getRelatedTo()).willReturn(AaiQueryTaskImpl.RELATED_TO); + given(pnfRelation.getRelationshipData()).willReturn(allRelationData); + given(pnfRelationships.getRelationship()).willReturn(Collections.singletonList(pnfRelation)); + given(pnfResultModel.getRelationshipList()).willReturn(pnfRelationships); + + configurePnfClient(aaiModel, pnfResultModel); + + //when + final Mono<Boolean> task = sut.execute(aaiModel); + + //then + Assertions.assertFalse(task::block); + } + + @Test + void whenPnfIsAvailableAndServiceRelationIsCompleteButServiceIsInactive_ShouldReturnFalse() { + //given + given(serviceModel.getOrchestrationStatus()).willReturn("Inactive"); + given(getServiceClient.getAaiResponse(any())).willReturn(Mono.just(serviceModel)); + + given(pnfRelation.getRelatedTo()).willReturn(AaiQueryTaskImpl.RELATED_TO); + given(pnfRelation.getRelationshipData()).willReturn(allRelationData); + given(pnfRelationships.getRelationship()).willReturn(Collections.singletonList(pnfRelation)); + given(pnfResultModel.getRelationshipList()).willReturn(pnfRelationships); + + configurePnfClient(aaiModel, pnfResultModel); + + //when + final Mono<Boolean> task = sut.execute(aaiModel); + + //then + Assertions.assertFalse(task::block); + } + + @Test + void whenPnfIsAvailableAndServiceRelationIsCompleteButServiceIsActive_ShouldReturnFalse() { + //given + given(serviceModel.getOrchestrationStatus()).willReturn("Active"); + given(getServiceClient.getAaiResponse(any())).willReturn(Mono.just(serviceModel)); + + given(pnfRelation.getRelatedTo()).willReturn(AaiQueryTaskImpl.RELATED_TO); + given(pnfRelation.getRelationshipData()).willReturn(allRelationData); + given(pnfRelationships.getRelationship()).willReturn(Collections.singletonList(pnfRelation)); + given(pnfResultModel.getRelationshipList()).willReturn(pnfRelationships); + + configurePnfClient(aaiModel, pnfResultModel); + + //when + final Mono<Boolean> task = sut.execute(aaiModel); + + //then + Assertions.assertTrue(task::block); + } + + private void configurePnfClient(final AaiModel aaiModel, final AaiPnfResultModel pnfResultModel) { + given(getPnfModelClient.getAaiResponse(aaiModel)).willReturn(Mono.just(pnfResultModel)); + } +} diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTaskTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTaskTest.java new file mode 100644 index 00000000..1c5c3837 --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTaskTest.java @@ -0,0 +1,245 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.tasks; + +import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR; +import static io.netty.handler.codec.http.HttpResponseStatus.OK; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.DELETE; +import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.GET; +import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.PUT; + +import com.google.gson.JsonObject; +import io.netty.buffer.ByteBuf; +import io.netty.handler.codec.http.HttpResponseStatus; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Scanner; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; +import org.onap.dcaegen2.services.prh.TestAppConfiguration; +import org.onap.dcaegen2.services.prh.configuration.CbsConfiguration; +import org.onap.dcaegen2.services.prh.exceptions.AaiFailureException; +import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; +import org.onap.dcaegen2.services.prh.model.ImmutableConsumerDmaapModel; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpRequest; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpResponse; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.ImmutableHttpResponse; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.RxHttpClient; +import reactor.core.publisher.Mono; + +class BbsActionsTaskTest { + + private static final String AAI_URL = "https://aai.onap.svc.cluster.local:8443/aai/v12/network"; + private static final String PNF_URL = "/pnfs/pnf"; + private static final String LOGICAL_LINK_URL = "/logical-links/logical-link"; + private static final String ATTACHMENT_POINT = "attachment-point"; + + private static final String PNF_WITHOUT_LINK_JSON = "BbsActionsTaskTestFiles/pnfWithoutLinks.json"; + private static final String PNF_WITH_LINK_JSON = "BbsActionsTaskTestFiles/pnfWithLogicalLink.json"; + private static final String LOGICAL_LINK_JSON = "BbsActionsTaskTestFiles/oldLogicalLink.json"; + private static final String LOGICAL_LINK_BODY = "BbsActionsTaskTestFiles/logicalLinkBody.json"; + + + private CbsConfiguration cbsConfiguration = mock(CbsConfiguration.class); + private AaiClientConfiguration aaiClientConfiguration = TestAppConfiguration.createDefaultAaiClientConfiguration(); + private RxHttpClient httpClient = mock(RxHttpClient.class); + + private ClassLoader loader = getClass().getClassLoader(); + + @Test + void whenPassedObjectDoesntHaveAdditionalFields_ReturnPayloadTransparently() { + // given + given(cbsConfiguration.getAaiClientConfiguration()).willReturn(aaiClientConfiguration); + ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(null); + + // when + ConsumerDmaapModel result = new BbsActionsTaskImpl(cbsConfiguration, httpClient).execute(consumerDmaapModel).block(); + + // then + verifyZeroInteractions(httpClient); + assertThat(result).isEqualTo(consumerDmaapModel); + } + + @Test + void whenPassedObjectHasEmptyLogicalLink_ReturnPayloadTransparently() { + // given + given(cbsConfiguration.getAaiClientConfiguration()).willReturn(aaiClientConfiguration); + + JsonObject additionalFields = new JsonObject(); + additionalFields.addProperty(ATTACHMENT_POINT, ""); + ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields); + + // when + ConsumerDmaapModel result = new BbsActionsTaskImpl(cbsConfiguration, httpClient).execute(consumerDmaapModel).block(); + + // then + verifyZeroInteractions(httpClient); + assertThat(result).isEqualTo(consumerDmaapModel); + } + + @Test + void whenPassedObjectHasLogicalLink_and_pnfHasNoLogicalLink_createLogicalLink_and_associateWithPnf_and_ReturnPayloadTransparently() { + // given + given(cbsConfiguration.getAaiClientConfiguration()).willReturn(aaiClientConfiguration); + + JsonObject additionalFields = new JsonObject(); + String linkName = "some-link"; + additionalFields.addProperty(ATTACHMENT_POINT, linkName); + ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields); + + given(httpClient.call(any())) + .willReturn(Mono.just(buildAaiResponse(OK, getBodyJson(PNF_WITHOUT_LINK_JSON))), + Mono.just(buildAaiResponse(OK, ""))); + + // when + Mono<ConsumerDmaapModel> response = new BbsActionsTaskImpl(cbsConfiguration, httpClient).execute(consumerDmaapModel); + + // then + assertEquals(consumerDmaapModel, response.block()); + + ArgumentCaptor<HttpRequest> captor = ArgumentCaptor.forClass(HttpRequest.class); + verify(httpClient, times(2)).call(captor.capture()); + + List<HttpRequest> args = captor.getAllValues(); + assertEquals(2, args.size()); + + HttpRequest pnfGet = args.get(0); + HttpRequest linkPut = args.get(1); + + assertEquals(AAI_URL + PNF_URL + "/Nokia123", pnfGet.url()); + assertEquals(GET, pnfGet.method()); + assertEquals(AAI_URL + LOGICAL_LINK_URL + "/" + linkName, linkPut.url()); + assertEquals(PUT, linkPut.method()); + assertEquals(getBodyJson(LOGICAL_LINK_BODY), extractBodyFromRequest(linkPut)); + } + + @Test + void whenPassedObjectHasLogicalLink_and_pnfHasLogicalLink_deleteOldLogicalLink_and_createLogicalLink_and_associateWithPnf_and_ReturnPayloadTransparently() { + // given + given(cbsConfiguration.getAaiClientConfiguration()).willReturn(aaiClientConfiguration); + + JsonObject additionalFields = new JsonObject(); + String linkName = "some-link"; + additionalFields.addProperty(ATTACHMENT_POINT, linkName); + ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields); + + given(httpClient.call(any())) + .willReturn(Mono.just(buildAaiResponse(OK, getBodyJson(PNF_WITH_LINK_JSON))), + Mono.just(buildAaiResponse(OK, "")), + Mono.just(buildAaiResponse(OK, getBodyJson(LOGICAL_LINK_JSON))), + Mono.just(buildAaiResponse(OK, ""))); + + // when + Mono<ConsumerDmaapModel> response = new BbsActionsTaskImpl(cbsConfiguration, httpClient).execute(consumerDmaapModel); + + // then + assertEquals(consumerDmaapModel, response.block()); + + ArgumentCaptor<HttpRequest> captor = ArgumentCaptor.forClass(HttpRequest.class); + verify(httpClient, times(4)).call(captor.capture()); + + List<HttpRequest> args = captor.getAllValues(); + assertEquals(4, args.size()); + + HttpRequest pnfGet = args.get(0); + HttpRequest linkPut = args.get(1); + HttpRequest linkGet = args.get(2); + HttpRequest linkDelete = args.get(3); + + assertEquals(AAI_URL + PNF_URL + "/Nokia123", pnfGet.url()); + assertEquals(GET, pnfGet.method()); + assertEquals(AAI_URL + LOGICAL_LINK_URL + "/" + linkName, linkPut.url()); + assertEquals(PUT, linkPut.method()); + assertEquals(AAI_URL + LOGICAL_LINK_URL + "/" + linkName, linkGet.url()); + assertEquals(GET, linkGet.method()); + assertEquals(AAI_URL + LOGICAL_LINK_URL + "/" + linkName + "?resource-version=1560171816043", linkDelete.url()); + assertEquals(DELETE, linkDelete.method()); + assertEquals(getBodyJson(LOGICAL_LINK_BODY), extractBodyFromRequest(linkPut)); + } + + @Test + void whenPassedObjectHasLogicalLink_butAaiQueryFails_returnError() { + // given + given(cbsConfiguration.getAaiClientConfiguration()).willReturn(aaiClientConfiguration); + + JsonObject additionalFields = new JsonObject(); + String linkName = "some-link"; + additionalFields.addProperty(ATTACHMENT_POINT, linkName); + ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields); + + given(httpClient.call( + ArgumentMatchers.argThat(argument -> argument.url().equals(AAI_URL + PNF_URL + "/Nokia123") + || argument.url().equals(AAI_URL + LOGICAL_LINK_URL + "/" + linkName)))) + .willReturn(Mono.just(buildAaiResponse(INTERNAL_SERVER_ERROR, ""))); + + // when + Mono<ConsumerDmaapModel> response = new BbsActionsTaskImpl(cbsConfiguration, httpClient) + .execute(consumerDmaapModel); + + // then + assertThatThrownBy(response::block).hasCauseInstanceOf(AaiFailureException.class).hasMessage( + "org.onap.dcaegen2.services.prh.exceptions.AaiFailureException: " + + "Incorrect response when performing BBS-related actions: 500. Occurred in GET PNF request. Pnf name: Nokia123"); + } + + private ConsumerDmaapModel buildConsumerDmaapModel(JsonObject additionalFields) { + return ImmutableConsumerDmaapModel.builder() + .ipv4("10.16.123.234") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .correlationId("Nokia123") + .serialNumber("QTFCOC540002E") + .equipVendor("nokia") + .equipModel("3310") + .equipType("type") + .nfRole("role") + .swVersion("v4.5.0.1") + .additionalFields(additionalFields) + .build(); + } + + private HttpResponse buildAaiResponse(HttpResponseStatus status, String body) { + return ImmutableHttpResponse + .builder() + .statusCode(status.code()) + .url("") + .rawBody(body.getBytes()) + .build(); + } + + private String extractBodyFromRequest(HttpRequest request) { + return Mono.from(request.body().contents()).block().toString(StandardCharsets.UTF_8); + } + + private String getBodyJson(String filename) { + return new Scanner(loader.getResourceAsStream(filename)).useDelimiter("\\A").next(); + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTaskImplTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTaskImplTest.java deleted file mode 100644 index fc85b98b..00000000 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTaskImplTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PNF-REGISTRATION-HANDLER - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.tasks; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.onap.dcaegen2.services.prh.TestAppConfiguration.createDefaultDmaapConsumerConfiguration; - -import java.util.Optional; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.onap.dcaegen2.services.prh.configuration.AppConfig; -import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; -import org.onap.dcaegen2.services.prh.model.ImmutableConsumerDmaapModel; -import org.onap.dcaegen2.services.prh.service.DmaapConsumerJsonParser; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.ConsumerReactiveHttpClientFactory; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPConsumerReactiveHttpClient; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/17/18 - */ -class DmaapConsumerTaskImplTest { - - private static ConsumerDmaapModel consumerDmaapModel; - private static DmaapConsumerTaskImpl dmaapConsumerTask; - private static DMaaPConsumerReactiveHttpClient dMaaPConsumerReactiveHttpClient; - private static AppConfig appConfig; - private static DmaapConsumerConfiguration dmaapConsumerConfiguration; - private static String message; - - @BeforeAll - static void setUp() { - dmaapConsumerConfiguration = createDefaultDmaapConsumerConfiguration(); - - consumerDmaapModel = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234") - .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") - .correlationId("NOKQTFCOC540002E").build(); - appConfig = mock(AppConfig.class); - - message = "[{\"event\": {" - + "\"commonEventHeader\": { \"sourceName\":\"NOKQTFCOC540002E\"}," - + "\"pnfRegistrationFields\": {" - + " \"unitType\": \"AirScale\"," - + " \"serialNumber\": \"QTFCOC540002E\"," - + " \"pnfRegistrationFieldsVersion\": \"2.0\"," - + " \"manufactureDate\": \"1535014037024\"," - + " \"modelNumber\": \"7BEA\",\n" - + " \"lastServiceDate\": \"1535014037024\"," - + " \"unitFamily\": \"BBU\"," - + " \"vendorName\": \"Nokia\"," - + " \"oamV4IpAddress\": \"10.16.123.234\"," - + " \"softwareVersion\": \"v4.5.0.1\"," - + " \"oamV6IpAddress\": \"0:0:0:0:0:FFFF:0A10:7BEA\"" - + "}}}]"; - } - - @Test - void whenPassedObjectDoesntFit_DoesNotThrowPrhTaskException() throws Exception { - //given - prepareMocksForDmaapConsumer(Optional.empty()); - - //when - Flux<ConsumerDmaapModel> response = dmaapConsumerTask.execute("Sample input"); - - //then - verify(dMaaPConsumerReactiveHttpClient).getDMaaPConsumerResponse(); - assertNull(response.blockFirst()); - } - - @Test - void whenPassedObjectFits_ReturnsCorrectResponse() throws Exception { - //given - prepareMocksForDmaapConsumer(Optional.of(message)); - - //when - Flux<ConsumerDmaapModel> response = dmaapConsumerTask.execute("Sample input"); - - //then - verify(dMaaPConsumerReactiveHttpClient).getDMaaPConsumerResponse(); - assertEquals(consumerDmaapModel, response.blockFirst()); - } - - @Test - void whenInitConfigs_initStreamReader() { - //when - dmaapConsumerTask.initConfigs(); - - //then - verify(appConfig).initFileStreamReader(); - } - - private void prepareMocksForDmaapConsumer(Optional<String> message) throws Exception { - dMaaPConsumerReactiveHttpClient = mock(DMaaPConsumerReactiveHttpClient.class); - when(dMaaPConsumerReactiveHttpClient.getDMaaPConsumerResponse()).thenReturn(Mono.just(message.orElse(""))); - when(appConfig.getDmaapConsumerConfiguration()).thenReturn(dmaapConsumerConfiguration); - ConsumerReactiveHttpClientFactory httpClientFactory = mock(ConsumerReactiveHttpClientFactory.class); - doReturn(dMaaPConsumerReactiveHttpClient).when(httpClientFactory).create(dmaapConsumerConfiguration); - dmaapConsumerTask = new DmaapConsumerTaskImpl(appConfig, new DmaapConsumerJsonParser(), httpClientFactory); - } -}
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTaskSpy.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTaskSpy.java deleted file mode 100644 index cb31c86b..00000000 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapConsumerTaskSpy.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.tasks; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; - -import javax.net.ssl.SSLException; -import org.onap.dcaegen2.services.prh.configuration.AppConfig; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapConsumerConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.consumer.DMaaPConsumerReactiveHttpClient; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; - - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 3/27/18 - */ -@Configuration -public class DmaapConsumerTaskSpy { - - /** - * Mocking bean for tests. - * - * @return DMaaP ConsumerTask spy - */ - @Bean - @Primary - public DmaapConsumerTask registerSimpleDmaapConsumerTask() throws SSLException { - AppConfig appConfig = spy(AppConfig.class); - doReturn(mock(DmaapConsumerConfiguration.class)).when(appConfig).getDmaapConsumerConfiguration(); - DmaapConsumerTaskImpl dmaapConsumerTask = spy(new DmaapConsumerTaskImpl(appConfig)); - DMaaPConsumerReactiveHttpClient dmaapConsumerReactiveHttpClient = mock( - DMaaPConsumerReactiveHttpClient.class); - doReturn(dmaapConsumerReactiveHttpClient).when(dmaapConsumerTask).resolveClient(); - return dmaapConsumerTask; - } -} diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapProducerTaskSpy.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapProducerTaskSpy.java deleted file mode 100644 index 07cdc5d8..00000000 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapProducerTaskSpy.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.tasks; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; - -import org.onap.dcaegen2.services.prh.configuration.AppConfig; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.DMaaPPublisherReactiveHttpClient; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; - -/** - * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 4/13/18 - */ -@Configuration -public class DmaapProducerTaskSpy { - - /** - * Mocking bean for tests. - * - * @return DMaaP PublisherTask spy - */ - @Bean - @Primary - public DmaapPublisherTask registerSimpleDmaapPublisherTask() { - AppConfig appConfig = spy(AppConfig.class); - doReturn(mock(DmaapPublisherConfiguration.class)).when(appConfig).getDmaapPublisherConfiguration(); - DmaapPublisherTaskImpl dmaapPublisherTask = spy(new DmaapPublisherTaskImpl(appConfig)); - DMaaPPublisherReactiveHttpClient extendedDmaapProducerHttpClient = mock( - DMaaPPublisherReactiveHttpClient.class); - doReturn(extendedDmaapProducerHttpClient).when(dmaapPublisherTask).resolveClient(); - return dmaapPublisherTask; - } -} diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTaskImplTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTaskImplTest.java index f4a1c2e6..7e00a441 100644 --- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTaskImplTest.java +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/DmaapPublisherTaskImplTest.java @@ -20,108 +20,94 @@ package org.onap.dcaegen2.services.prh.tasks; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; -import static org.onap.dcaegen2.services.prh.TestAppConfiguration.createDefaultDmaapPublisherConfiguration; - -import org.junit.jupiter.api.BeforeAll; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.function.Executable; -import org.onap.dcaegen2.services.prh.configuration.AppConfig; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import org.onap.dcaegen2.services.prh.exceptions.DmaapNotFoundException; import org.onap.dcaegen2.services.prh.exceptions.PrhTaskException; -import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; import org.onap.dcaegen2.services.prh.model.ImmutableConsumerDmaapModel; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.config.DmaapPublisherConfiguration; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.DMaaPPublisherReactiveHttpClient; -import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.service.producer.PublisherReactiveHttpClientFactory; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import reactor.core.publisher.Mono; +import org.onap.dcaegen2.services.sdk.model.streams.dmaap.ImmutableMessageRouterSink; +import org.onap.dcaegen2.services.sdk.model.streams.dmaap.MessageRouterSink; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.MessageRouterPublisher; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.ImmutableMessageRouterPublishRequest; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.MessageRouterPublishRequest; +import reactor.core.publisher.Flux; import reactor.test.StepVerifier; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + /** * @author <a href="mailto:przemyslaw.wasala@nokia.com">Przemysław Wąsala</a> on 5/17/18 */ +@ExtendWith(MockitoExtension.class) class DmaapPublisherTaskImplTest { - private static ConsumerDmaapModel consumerDmaapModel; - private static DmaapPublisherTaskImpl dmaapPublisherTask; - private static DMaaPPublisherReactiveHttpClient dMaaPPublisherReactiveHttpClient; - private static AppConfig appConfig; - private static DmaapPublisherConfiguration dmaapPublisherConfiguration; + private DmaapPublisherTaskImpl dmaapPublisherTask; - @BeforeAll - static void setUp() { - dmaapPublisherConfiguration = createDefaultDmaapPublisherConfiguration(); - consumerDmaapModel = ImmutableConsumerDmaapModel.builder().ipv4("10.16.123.234") - .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") - .correlationId("NOKQTFCOC540002E").build(); - appConfig = mock(AppConfig.class); - } + private MessageRouterPublishRequest mrRequest = createMRRequest(); + + @Mock + private static MessageRouterPublisher messageRouterPublisher; + + @Captor + private ArgumentCaptor<Flux<JsonElement>> fluxCaptor; @Test - void whenPassedObjectDoesntFit_ThrowsPrhTaskException() { + void execute_whenPassedObjectDoesntFit_ThrowsPrhTaskException() { //given - when(appConfig.getDmaapPublisherConfiguration()).thenReturn(dmaapPublisherConfiguration); - dmaapPublisherTask = new DmaapPublisherTaskImpl(appConfig); - + dmaapPublisherTask = new DmaapPublisherTaskImpl(() -> mrRequest, () -> messageRouterPublisher); //when Executable executableFunction = () -> dmaapPublisherTask.execute(null); - //then assertThrows(PrhTaskException.class, executableFunction, "The specified parameter is incorrect"); } @Test - void whenPassedObjectFits_ReturnsCorrectStatus() throws PrhTaskException { + void execute_whenPassedObjectFits_ReturnsCorrectStatus() throws DmaapNotFoundException { //given - ResponseEntity<String> responseEntity = prepareMocksForTests(HttpStatus.OK.value()); - + dmaapPublisherTask = new DmaapPublisherTaskImpl(() -> mrRequest, () -> messageRouterPublisher); //when - when(responseEntity.getStatusCode()).thenReturn(HttpStatus.OK); - StepVerifier.create(dmaapPublisherTask.execute(consumerDmaapModel)).expectSubscription() - .expectNext(responseEntity).verifyComplete(); - + dmaapPublisherTask.execute(createConsumerDmaapModel()); //then - verify(dMaaPPublisherReactiveHttpClient, times(1)) - .getDMaaPProducerResponse(consumerDmaapModel); - verifyNoMoreInteractions(dMaaPPublisherReactiveHttpClient); - } - + verify(messageRouterPublisher).put(eq(mrRequest), fluxCaptor.capture()); - @Test - void whenPassedObjectFits_butIncorrectResponseReturns() throws DmaapNotFoundException { - //given - ResponseEntity<String> responseEntity = prepareMocksForTests(HttpStatus.UNAUTHORIZED.value()); + StepVerifier.create(fluxCaptor.getValue()) + .expectNext(new JsonParser().parse("{\"correlationId\":\"NOKQTFCOC540002E\"}")) + .verifyComplete(); + } - //when - when(responseEntity.getStatusCode()).thenReturn(HttpStatus.UNAUTHORIZED); - StepVerifier.create(dmaapPublisherTask.execute(consumerDmaapModel)).expectSubscription() - .expectNext(responseEntity).verifyComplete(); - //then - verify(dMaaPPublisherReactiveHttpClient, times(1)) - .getDMaaPProducerResponse(consumerDmaapModel); - verifyNoMoreInteractions(dMaaPPublisherReactiveHttpClient); + private ImmutableConsumerDmaapModel createConsumerDmaapModel() { + return ImmutableConsumerDmaapModel.builder() + .ipv4("10.16.123.234") + .ipv6("0:0:0:0:0:FFFF:0A10:7BEA") + .correlationId("NOKQTFCOC540002E") + .serialNumber("QTFCOC540002E") + .equipVendor("nokia") + .equipModel("3310") + .equipType("type") + .nfRole("gNB") + .swVersion("v4.5.0.1") + .additionalFields(null) + .build(); } + private MessageRouterPublishRequest createMRRequest() { + final MessageRouterSink sinkDefinition = ImmutableMessageRouterSink.builder() + .name("the topic") + .topicUrl("http://dmaap-mr:2222/events/unauthenticated.PNF_READY") + .build(); - private ResponseEntity<String> prepareMocksForTests(Integer httpResponseCode) { - ResponseEntity<String> responseEntity = mock(ResponseEntity.class); - when(responseEntity.getStatusCode()).thenReturn(HttpStatus.valueOf(httpResponseCode)); - dMaaPPublisherReactiveHttpClient = mock(DMaaPPublisherReactiveHttpClient.class); - when(dMaaPPublisherReactiveHttpClient.getDMaaPProducerResponse(any())) - .thenReturn(Mono.just(responseEntity)); - PublisherReactiveHttpClientFactory httpClientFactory = mock(PublisherReactiveHttpClientFactory.class); - doReturn(dMaaPPublisherReactiveHttpClient).when(httpClientFactory).create(dmaapPublisherConfiguration); - dmaapPublisherTask = new DmaapPublisherTaskImpl(appConfig, httpClientFactory); - return responseEntity; + return ImmutableMessageRouterPublishRequest.builder() + .sinkDefinition(sinkDefinition) + .build(); } }
\ No newline at end of file diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasksTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasksTest.java new file mode 100644 index 00000000..cefc5c76 --- /dev/null +++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasksTest.java @@ -0,0 +1,186 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ +package org.onap.dcaegen2.services.prh.tasks; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.dcaegen2.services.prh.exceptions.PrhTaskException; +import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel; +import org.onap.dcaegen2.services.prh.model.ImmutableConsumerDmaapModel; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import javax.net.ssl.SSLException; +import java.util.Collections; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class ScheduledTasksTest { + private final static ConsumerDmaapModel DMAAP_MODEL = + ImmutableConsumerDmaapModel + .builder() + .correlationId("SomeId") + .ipv4("ipv4") + .ipv6("ipv6") + .build(); + + @Mock + private DmaapPublisherTask readyPublisher; + + @Mock + private DmaapPublisherTask updatePublisher; + + @Mock + private DmaapConsumerTask consumer; + + @Mock + private BbsActionsTask bbsActions; + + @Mock + private AaiQueryTask aaiQuery; + + @Mock + private AaiProducerTask aaiProducer; + + private final Map<String, String> context = Collections.emptyMap(); + + private ScheduledTasks sut; + + @BeforeEach + void setUp() { + sut = new ScheduledTasks( + consumer, + readyPublisher, + updatePublisher, + aaiQuery, + aaiProducer, + bbsActions, + context); + } + + @Test + void whenEmptyResultFromDMaaPConsumer_NotActionShouldBePerformed() throws SSLException, PrhTaskException { + //given + given(consumer.execute()).willReturn(Flux.empty()); + + //when + sut.scheduleMainPrhEventTask(); + + //then + verifyThatPnfUpdateWasNotSentToAai(); + verifyIfLogicalLinkWasNotCreated(); + verifyThatPnfModelWasNotSentDmaapPnfReadyTopic(); + verifyThatPnfModelWasNotSentDmaapPnfUpdateTopic(); + } + + @Test + void whenPnfNotFoundInAai_NotActionShouldBePerformed() throws SSLException, PrhTaskException { + //given + given(consumer.execute()).willReturn(Flux.just(DMAAP_MODEL)); + given(aaiQuery.execute(any())).willReturn(Mono.error(new PrhTaskException("404 Not Found"))); + + //when + sut.scheduleMainPrhEventTask(); + + verifyThatPnfUpdateWasNotSentToAai(); + verifyIfLogicalLinkWasNotCreated(); + verifyThatPnfModelWasNotSentDmaapPnfReadyTopic(); + verifyThatPnfModelWasNotSentDmaapPnfUpdateTopic(); + } + + @Test + void whenPnfWithoutService_PatchToAaiAndPostToPnfReadyShouldBePerformed() throws SSLException, PrhTaskException { + //given + Mono<ConsumerDmaapModel> consumerModel = Mono.just(DMAAP_MODEL); + + given(aaiProducer.execute(DMAAP_MODEL)).willReturn(consumerModel); + given(bbsActions.execute(DMAAP_MODEL)).willReturn(consumerModel); + + + given(consumer.execute()).willReturn(Flux.just(DMAAP_MODEL)); + given(aaiQuery.execute(any())).willReturn(Mono.just(false)); + + //when + sut.scheduleMainPrhEventTask(); + + //then + verifyThatPnfUpdateWasSentToAai(); + verifyIfLogicalLinkWasCreated(); + verifyThatPnfModelWasSentDmaapPnfReadyTopic(); + verifyThatPnfModelWasNotSentDmaapPnfUpdateTopic(); + } + + @Test + void whenPnfHasActiveService_OnlyPostToPnfUpdateShouldBePerformed() throws SSLException, PrhTaskException { + //given + given(consumer.execute()).willReturn(Flux.just(DMAAP_MODEL)); + given(aaiQuery.execute(any())).willReturn(Mono.just(true)); + + //when + sut.scheduleMainPrhEventTask(); + + //then + verifyThatPnfUpdateWasNotSentToAai(); + verifyIfLogicalLinkWasNotCreated(); + verifyThatPnfModelWasNotSentDmaapPnfReadyTopic(); + verifyThatPnfModelWasSentDmaapPnfUpdateTopic(); + } + + private void verifyThatPnfModelWasNotSentDmaapPnfReadyTopic() throws PrhTaskException { + verify(readyPublisher, never()).execute(DMAAP_MODEL); + } + + private void verifyThatPnfModelWasNotSentDmaapPnfUpdateTopic() throws PrhTaskException { + verify(updatePublisher, never()).execute(DMAAP_MODEL); + } + + private void verifyThatPnfModelWasSentDmaapPnfReadyTopic() throws PrhTaskException { + verify(readyPublisher, atLeastOnce()).execute(DMAAP_MODEL); + } + + private void verifyThatPnfModelWasSentDmaapPnfUpdateTopic() throws PrhTaskException { + verify(updatePublisher, atLeastOnce()).execute(DMAAP_MODEL); + } + + private void verifyThatPnfUpdateWasNotSentToAai() throws PrhTaskException, SSLException { + verify(aaiProducer, never()).execute(DMAAP_MODEL); + } + + private void verifyThatPnfUpdateWasSentToAai() throws PrhTaskException, SSLException { + verify(aaiProducer, atLeastOnce()).execute(DMAAP_MODEL); + } + + private void verifyIfLogicalLinkWasCreated(){ + verify(bbsActions, atLeastOnce()).execute(DMAAP_MODEL); + } + + private void verifyIfLogicalLinkWasNotCreated(){ + verify(bbsActions, never()).execute(DMAAP_MODEL); + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/logicalLinkBody.json b/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/logicalLinkBody.json new file mode 100644 index 00000000..c73b93e5 --- /dev/null +++ b/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/logicalLinkBody.json @@ -0,0 +1 @@ +{"link-name":"some-link","link-type":"attachment-point","relationship-list":{"relationship":[{"related-link":"/network/pnfs/pnf/Nokia123","relationship-data":[]}]}}
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/oldLogicalLink.json b/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/oldLogicalLink.json new file mode 100644 index 00000000..7d3f02df --- /dev/null +++ b/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/oldLogicalLink.json @@ -0,0 +1,21 @@ +{ + "link-name": "some-link", + "in-maint": false, + "link-type": "attachment-point", + "resource-version": "1560171816043", + "relationship-list": { + "relationship": [ + { + "related-to": "pnf", + "relationship-label": "org.onap.relationships.inventory.BridgedTo", + "related-link": "/aai/v14/network/pnfs/pnf/Nokia123", + "relationship-data": [ + { + "relationship-key": "pnf.pnf-name", + "relationship-value": "Nokia123" + } + ] + } + ] + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/pnfWithLogicalLink.json b/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/pnfWithLogicalLink.json new file mode 100644 index 00000000..6f4690d6 --- /dev/null +++ b/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/pnfWithLogicalLink.json @@ -0,0 +1,25 @@ +{ + "pnf-name": "Nokia123", + "pnf-name2-source": "", + "pnf-id": "Nokia123", + "equip-type": "", + "equip-vendor": "", + "management-option": "", + "in-maint": false, + "resource-version": "1560153116694", + "relationship-list": { + "relationship": [ + { + "related-to": "logical-link", + "relationship-label": "org.onap.relationships.inventory.BridgedTo", + "related-link": "/aai/v14/network/logical-links/logical-link/some-link", + "relationship-data": [ + { + "relationship-key": "logical-link.link-name", + "relationship-value": "some-link" + } + ] + } + ] + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/pnfWithoutLinks.json b/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/pnfWithoutLinks.json new file mode 100644 index 00000000..1f614d40 --- /dev/null +++ b/prh-app-server/src/test/resources/BbsActionsTaskTestFiles/pnfWithoutLinks.json @@ -0,0 +1,10 @@ +{ + "pnf-name": "Nokia123", + "pnf-name2-source": "", + "pnf-id": "Nokia123", + "equip-type": "", + "equip-vendor": "", + "management-option": "", + "in-maint": false, + "resource-version": "1560153116694" +} diff --git a/prh-app-server/src/test/resources/application.yaml b/prh-app-server/src/test/resources/application.yaml new file mode 100644 index 00000000..fa7f11cf --- /dev/null +++ b/prh-app-server/src/test/resources/application.yaml @@ -0,0 +1,8 @@ +spring: + profiles: + active: prod + +logging: + level: + org.onap.dcaegen2.services.prh: debug + org.onap.dcaegen2.services.sdk: debug
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/bootstrap.yaml b/prh-app-server/src/test/resources/bootstrap.yaml new file mode 100644 index 00000000..46796cdc --- /dev/null +++ b/prh-app-server/src/test/resources/bootstrap.yaml @@ -0,0 +1,6 @@ +cbs: + enabled: false +spring: + cloud: + config: + enabled: false
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/configurationFromCbs.json b/prh-app-server/src/test/resources/configurationFromCbs.json new file mode 100644 index 00000000..d76aab4f --- /dev/null +++ b/prh-app-server/src/test/resources/configurationFromCbs.json @@ -0,0 +1,54 @@ +{ + "config":{ + "dmaap.dmaapConsumerConfiguration.dmaapUserName":"admin", + "dmaap.dmaapConsumerConfiguration.dmaapUserPassword":"admin", + "dmaap.dmaapConsumerConfiguration.consumerId":"c12", + "dmaap.dmaapConsumerConfiguration.consumerGroup":"OpenDCAE-c12", + "dmaap.dmaapConsumerConfiguration.timeoutMs":-1, + + "dmaap.dmaapProducerConfiguration.dmaapUserName":"admin", + "dmaap.dmaapProducerConfiguration.dmaapUserPassword":"admin", + "dmaap.dmaapUpdateProducerConfiguration.dmaapUserName":"admin", + "dmaap.dmaapUpdateProducerConfiguration.dmaapUserPassword":"admin", + "aai.aaiClientConfiguration.pnfUrl": "https://aai.onap.svc.cluster.local:8443/aai/v12/network/pnfs/pnf", + "aai.aaiClientConfiguration.aaiUserName":"AAI", + "aai.aaiClientConfiguration.aaiUserPassword":"AAI", + "aai.aaiClientConfiguration.aaiIgnoreSslCertificateErrors":true, + "aai.aaiClientConfiguration.aaiServiceInstancePath":"/business/customers/customer/${customer}/service-subscriptions/service-subscription/${serviceType}/service-instances/service-instance/${serviceInstanceId}", + "aai.aaiClientConfiguration.aaiHeaders":{ + "X-FromAppId":"prh", + "X-TransactionId":"9999", + "Accept":"application/json", + "Real-Time":"true", + "Authorization":"Basic QUFJOkFBSQ==" + }, + "security.trustStorePath":"/opt/app/prh/local/org.onap.prh.trust.jks", + "security.trustStorePasswordPath":"change_it", + "security.keyStorePath":"/opt/app/prh/local/org.onap.prh.p12", + "security.keyStorePasswordPath":"change_it", + "security.enableAaiCertAuth":false, + "security.enableDmaapCertAuth":false, + "streams_publishes":{ + "pnf-update":{ + "type": "message_router", + "dmaap_info":{ + "topic_url":"http://dmaap-mr:2222/events/unauthenticated.PNF_UPDATE" + } + }, + "pnf-ready":{ + "type": "message_router", + "dmaap_info":{ + "topic_url":"http://dmaap-mr:2222/events/unauthenticated.PNF_READY" + } + } + }, + "streams_subscribes":{ + "ves-reg-output":{ + "type": "message_router", + "dmaap_info":{ + "topic_url":"http://dmaap-mr:2222/events/unauthenticated.VES_PNFREG_OUTPUT" + } + } + } + } +}
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/correct_config.json b/prh-app-server/src/test/resources/correct_config.json deleted file mode 100644 index 5c80bc99..00000000 --- a/prh-app-server/src/test/resources/correct_config.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "configs": { - "aai": { - "aaiClientConfiguration": { - "aaiHost": "localhost", - "aaiPort": 8080, - "aaiIgnoreSslCertificateErrors": true, - "aaiProtocol": "https", - "aaiUserName": "admin", - "aaiUserPassword": "admin", - "aaiBasePath": "/aai/v11", - "aaiPnfPath": "/network/pnfs/pnf", - "aaiHeaders": { - "X-FromAppId": "prh", - "X-TransactionId": "9999", - "Accept": "application/json", - "Real-Time": "true", - "Content-Type": "application/merge-patch+json", - "Authorization": "Basic QUFJOkFBSQ==" - } - } - }, - "dmaap": { - "dmaapConsumerConfiguration": { - "consumerGroup": "other", - "consumerId": "1", - "dmaapContentType": "application/json", - "dmaapHostName": "localhost", - "dmaapPortNumber": 2222, - "dmaapProtocol": "http", - "dmaapTopicName": "temp", - "dmaapUserName": "admin", - "dmaapUserPassword": "admin", - "messageLimit": 1000, - "timeoutMs": 1000 - }, - "dmaapProducerConfiguration": { - "dmaapContentType": "application/json", - "dmaapHostName": "localhost", - "dmaapPortNumber": 2223, - "dmaapProtocol": "http", - "dmaapTopicName": "temp", - "dmaapUserName": "admin", - "dmaapUserPassword": "admin" - } - }, - "security": { - "trustStorePath": "/opt/app/prh/local/org.onap.prh.trust.jks", - "trustStorePasswordPath": "change it", - "keyStorePath": "/opt/app/prh/local/org.onap.prh.p12", - "keyStorePasswordPath": "change it", - "enableAaiCertAuth": "false", - "enableDmaapCertAuth": "false" - } - } -}
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/flattened_configuration.json b/prh-app-server/src/test/resources/flattened_configuration.json deleted file mode 100644 index f8def2ef..00000000 --- a/prh-app-server/src/test/resources/flattened_configuration.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "aai.aaiClientConfiguration.aaiIgnoreSslCertificateErrors": true, - "dmaap.dmaapProducerConfiguration.dmaapTopicName": "/events/unauthenticated.PNF_READY", - "dmaap.dmaapConsumerConfiguration.timeoutMs": -1, - "dmaap.dmaapConsumerConfiguration.dmaapHostName": "message-router.onap.svc.cluster.local", - "aai.aaiClientConfiguration.aaiPnfPath": "/network/pnfs/pnf", - "aai.aaiClientConfiguration.aaiUserPassword": "AAI", - "dmaap.dmaapConsumerConfiguration.dmaapUserName": "admin", - "aai.aaiClientConfiguration.aaiBasePath": "/aai/v12", - "dmaap.dmaapProducerConfiguration.dmaapPortNumber": 3904, - "aai.aaiClientConfiguration.aaiHost": "aai.onap.svc.cluster.local", - "dmaap.dmaapConsumerConfiguration.dmaapUserPassword": "admin", - "dmaap.dmaapProducerConfiguration.dmaapProtocol": "http", - "dmaap.dmaapProducerConfiguration.dmaapContentType": "application/json", - "dmaap.dmaapConsumerConfiguration.dmaapTopicName": "/events/unauthenticated.SEC_OTHER_OUTPUT", - "dmaap.dmaapConsumerConfiguration.dmaapPortNumber": 3904, - "dmaap.dmaapConsumerConfiguration.dmaapContentType": "application/json", - "dmaap.dmaapConsumerConfiguration.messageLimit": -1, - "dmaap.dmaapConsumerConfiguration.dmaapProtocol": "http", - "aai.aaiClientConfiguration.aaiUserName": "AAI", - "dmaap.dmaapConsumerConfiguration.consumerId": "c12", - "dmaap.dmaapProducerConfiguration.dmaapHostName": "message-router.onap.svc.cluster.local", - "aai.aaiClientConfiguration.aaiHostPortNumber": 8443, - "dmaap.dmaapConsumerConfiguration.consumerGroup": "OpenDCAE-c12", - "aai.aaiClientConfiguration.aaiProtocol": "https", - "dmaap.dmaapProducerConfiguration.dmaapUserName": "admin", - "dmaap.dmaapProducerConfiguration.dmaapUserPassword": "admin", - "security.trustStorePath": "/opt/app/prh/local/org.onap.prh.trust.jks", - "security.trustStorePasswordPath": "change_it", - "security.keyStorePath": "/opt/app/prh/local/org.onap.prh.p12", - "security.keyStorePasswordPath": "change_it", - "security.enableAaiCertAuth": false, - "security.enableDmaapCertAuth": false -}
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/incorrect_config.json b/prh-app-server/src/test/resources/incorrect_config.json deleted file mode 100644 index a682402d..00000000 --- a/prh-app-server/src/test/resources/incorrect_config.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "configs": { - "aai": { - "aaiClientConfiguration": { - "aaiHost": "localhost", - "aaiPort": 8080, - "aaiIgnoreSslCertificateErrors": true, - "aaiProtocol": "https", - "aaiUserName": "admin", - "aaiUserPassword": "admin", - "aaiBasePath": "/aai/v11", - "aaiPnfPath": "/network/pnfs/pnf", - "aaiHeaders": { - "X-FromAppId": "prh", - "X-TransactionId": "9999", - "Accept": "application/json", - "Real-Time": "true", - "Content-Type": "application/merge-patch+json", - "Authorization": "Basic QUFJOkFBSQ==" - } - } - }, - "dmaap": { - "dmaapConsumerConfiguration": { - "consumerGroup": "other", - "consumerId": "1", - "dmaapContentType": "application/json", - "dmaapHostName": "localhost", - "dmaapPortNumber": 2222, - "dmaapProtocol": "http", - "dmaapTopicName": "temp", - "dmaapUserName": "admin", - "dmaapUserPassword": "admin", - "messageLimit": 1000, - "timeoutMs": 1000 - }, - "dmaapProducerConfiguration": { - "dmaapContentType": "application/json", - "dmaapHostName": "localhost", - "dmaapPortNumber": 2223, - "dmaapProtocol": "http", - "dmaaptopicName": "temp", - "dmaapuserName": "admin", - "dmaapuserPassword": "admin" - } - }, - "security": { - "trustStorePath": "/opt/app/prh/local/org.onap.prh.trust.jks", - "trustStorePasswordPath": "change it", - "keyStorePath": "/opt/app/prh/local/org.onap.prh.p12", - "keyStorePasswordPath": "change it", - "enableAaiCertAuth": "false", - "enableDmaapCertAuth": "false" - } - } -}
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/integration/event.json b/prh-app-server/src/test/resources/integration/event.json new file mode 100644 index 00000000..3a768df2 --- /dev/null +++ b/prh-app-server/src/test/resources/integration/event.json @@ -0,0 +1,37 @@ +{ + "event": { + "commonEventHeader": { + "startEpochMicrosec": 1540212137393, + "sourceId": "val13", + "eventId": "registration_40212137", + "nfcNamingCode": "oam", + "internalHeaderFields": { + "collectorTimeStamp": "Mon, 10 22 2018 12:42:18 UTC" + }, + "eventType": "pnfRegistration", + "priority": "Normal", + "version": "4.0.1", + "reportingEntityName": "NOK6061ZW8", + "sequence": 0, + "domain": "pnfRegistration", + "lastEpochMicrosec": 1540212137393, + "eventName": "pnfRegistration_Nokia_5gDu", + "vesEventListenerVersion": "7.0.1", + "sourceName": "NOK6061ZW8", + "nfNamingCode": "gNB" + }, + "pnfRegistrationFields": { + "unitType": "val8", + "serialNumber": "6061ZW9", + "pnfRegistrationFieldsVersion": "2.0", + "manufactureDate": "1540212137393", + "modelNumber": "val6", + "lastServiceDate": "1540212137393", + "unitFamily": "BBU", + "vendorName": "Nokia", + "oamV4IpAddress": "val3", + "oamV6IpAddress": "val4", + "softwareVersion": "val7" + } + } +}
\ No newline at end of file diff --git a/prh-commons/src/test/resources/keystore.password b/prh-app-server/src/test/resources/keystore.password index 39823872..39823872 100644 --- a/prh-commons/src/test/resources/keystore.password +++ b/prh-app-server/src/test/resources/keystore.password diff --git a/prh-app-server/src/test/resources/logback-test.xml b/prh-app-server/src/test/resources/logback-test.xml index c1f00665..c8db899a 100644 --- a/prh-app-server/src/test/resources/logback-test.xml +++ b/prh-app-server/src/test/resources/logback-test.xml @@ -1,21 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ ===============================LICENSE_START====================================== - ~ Copyright © 2017 AT&T Intellectual Property. All rights reserved. - ~ ================================================================================ - ~ 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=========================================== - --> <configuration> - <root level="OFF"/> -</configuration> + <include resource="org/springframework/boot/logging/logback/defaults.xml" /> + <include resource="org/springframework/boot/logging/logback/console-appender.xml" /> + + <logger name="ROOT" level="WARN"> + <appender-ref ref="CONSOLE"/> + </logger> +</configuration>
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/prh-app-server/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000..ca6ee9ce --- /dev/null +++ b/prh-app-server/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline
\ No newline at end of file diff --git a/prh-app-server/src/test/resources/not_json_object.json b/prh-app-server/src/test/resources/not_json_object.json deleted file mode 100644 index f50456ee..00000000 --- a/prh-app-server/src/test/resources/not_json_object.json +++ /dev/null @@ -1 +0,0 @@ -["a", "d", "d"] diff --git a/prh-commons/src/test/resources/org.onap.dcae.jks b/prh-app-server/src/test/resources/org.onap.dcae.jks Binary files differindex e74ce64f..e74ce64f 100644 --- a/prh-commons/src/test/resources/org.onap.dcae.jks +++ b/prh-app-server/src/test/resources/org.onap.dcae.jks diff --git a/prh-commons/src/test/resources/org.onap.dcae.trust.jks b/prh-app-server/src/test/resources/org.onap.dcae.trust.jks Binary files differindex 10103cfb..10103cfb 100644 --- a/prh-commons/src/test/resources/org.onap.dcae.trust.jks +++ b/prh-app-server/src/test/resources/org.onap.dcae.trust.jks diff --git a/prh-app-server/src/test/resources/scheduled-context.xml b/prh-app-server/src/test/resources/scheduled-context.xml deleted file mode 100644 index 91919aa2..00000000 --- a/prh-app-server/src/test/resources/scheduled-context.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:task="http://www.springframework.org/schema/task" - xmlns:context="http://www.springframework.org/schema/context" - xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> - - <context:component-scan - base-package="org.onap.dcaegen2.services.prh"/> - <task:scheduled-tasks> - <task:scheduled ref="scheduleController" method="startTasks" - fixed-rate="1000"/> - </task:scheduled-tasks> -</beans> diff --git a/prh-commons/src/test/resources/truststore.password b/prh-app-server/src/test/resources/truststore.password index 168e64bd..168e64bd 100644 --- a/prh-commons/src/test/resources/truststore.password +++ b/prh-app-server/src/test/resources/truststore.password diff --git a/prh-commons/pom.xml b/prh-commons/pom.xml index e0d7e5b8..7c53880a 100644 --- a/prh-commons/pom.xml +++ b/prh-commons/pom.xml @@ -1,4 +1,23 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ PNF-REGISTRATION-HANDLER + ~ ================================================================================ + ~ Copyright (C) 2018-2019 NOKIA Intellectual Property. All rights reserved. + ~ ================================================================================ + ~ 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========================================================= +--> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> @@ -7,27 +26,23 @@ <parent> <groupId>org.onap.dcaegen2.services</groupId> <artifactId>prh</artifactId> - <version>1.2.0-SNAPSHOT</version> + <version>1.3.1-SNAPSHOT</version> </parent> <groupId>org.onap.dcaegen2.services.prh</groupId> <artifactId>prh-commons</artifactId> <packaging>jar</packaging> - <dependencies> <dependency> <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId> <artifactId>common-dependency</artifactId> </dependency> <dependency> - <groupId>ch.qos.logback</groupId> - <artifactId>logback-classic</artifactId> - </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>jul-to-slf4j</artifactId> + <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId> + <artifactId>aai-client</artifactId> </dependency> + <dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> @@ -43,13 +58,12 @@ <dependency> <groupId>org.immutables</groupId> <artifactId>value</artifactId> - <version>${immutables.version}</version> </dependency> <dependency> <groupId>org.immutables</groupId> <artifactId>gson</artifactId> - <version>${immutables.version}</version> </dependency> + <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> @@ -57,7 +71,12 @@ </dependency> <dependency> <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> + <artifactId>mockito-junit-jupiter</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> <scope>test</scope> </dependency> </dependencies> diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/AaiJsonBodyBuilderImpl.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/AaiJsonBodyBuilderImpl.java new file mode 100644 index 00000000..2be95ee3 --- /dev/null +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/AaiJsonBodyBuilderImpl.java @@ -0,0 +1,65 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model; + +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapterFactory; +import org.onap.dcaegen2.services.prh.model.ImmutableConsumerDmaapModel.Builder; +import org.onap.dcaegen2.services.sdk.rest.services.model.JsonBodyBuilder; + +import java.util.ServiceLoader; +import org.springframework.util.StringUtils; + + +public class AaiJsonBodyBuilderImpl implements JsonBodyBuilder<ConsumerDmaapModel> { + + /** + * Method for serialization object by GSON. + * + * @param consumerDmaapModel - object which will be serialized + * @return string from serialization + */ + public String createJsonBody(ConsumerDmaapModel consumerDmaapModel) { + GsonBuilder gsonBuilder = new GsonBuilder(); + ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory); + + Builder builder = ImmutableConsumerDmaapModel.builder() + .correlationId(consumerDmaapModel.getCorrelationId()) + .serialNumber(consumerDmaapModel.getSerialNumber()) + .equipVendor(consumerDmaapModel.getEquipVendor()) + .equipModel(consumerDmaapModel.getEquipModel()) + .equipType(consumerDmaapModel.getEquipType()) + .nfRole(consumerDmaapModel.getNfRole()) + .swVersion(consumerDmaapModel.getSwVersion()) + .additionalFields(consumerDmaapModel.getAdditionalFields()); + + String ipv4 = consumerDmaapModel.getIpv4(); + if (!StringUtils.isEmpty(ipv4)) { + builder.ipv4(ipv4); + } + String ipv6 = consumerDmaapModel.getIpv6(); + if (!StringUtils.isEmpty(ipv6)) { + builder.ipv6(ipv6); + } + + return gsonBuilder.create().toJson(builder.build()); + } +}
\ No newline at end of file diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/AaiPnfResultModel.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/AaiPnfResultModel.java new file mode 100644 index 00000000..424d7f83 --- /dev/null +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/AaiPnfResultModel.java @@ -0,0 +1,206 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model; + +import com.google.gson.annotations.SerializedName; +import org.immutables.gson.Gson; +import org.immutables.value.Value; +import org.springframework.lang.Nullable; + + +/** + * PNF represents a physical network function. typically equipment used in the D1 world. in 1607, this will be populated by SDN-C to represent a premises router that a uCPE connects to. But this can be used to represent any physical device that is not an AIC node or uCPE. ###### Related Nodes - TO complex( pnf LocatedIn complex, MANY2ONE) - TO instance-group( pnf MemberOf instance-group, MANY2MANY) - TO zone( pnf LocatedIn zone, MANY2ONE) - FROM configuration( configuration AppliesTo pnf, ONE2MANY) - FROM esr-thirdparty-sdnc( esr-thirdparty-sdnc AppliesTo pnf, ONE2MANY) - FROM generic-vnf( generic-vnf HostedOn pnf, MANY2MANY) - FROM lag-interface (CHILD of pnf, lag-interface BindsTo pnf, MANY2ONE)(1) - FROM logical-link( logical-link BridgedTo pnf, MANY2MANY) - FROM p-interface (CHILD of pnf, p-interface BindsTo pnf, MANY2ONE)(1) - FROM service-instance( service-instance ComposedOf pnf, ONE2MANY) -(1) IF this PNF node is deleted, this FROM node is DELETED also + */ +@Value.Immutable +@Gson.TypeAdapters(fieldNamingStrategy = true) +public interface AaiPnfResultModel { + + /** + * unique name of Physical Network Function. + **/ + @Nullable + @SerializedName("pnf-name") + String getPnfName(); + + /** + * name of Physical Network Function. + **/ + @Nullable + @SerializedName("pnf-name2") + String getPnfName2(); + + /** + * URL to endpoint where AAI can get more details. + **/ + @Nullable + @SerializedName("selflink") + String getSelflink(); + + /** + * source of name2 + **/ + @Nullable + @SerializedName("pnf-name2-source") + String getPnfName2Source(); + + /** + * id of pnf + **/ + @Nullable + @SerializedName("pnf-id") + String getPnfId(); + + /** + * Equipment type. Source of truth should define valid values. + **/ + @Nullable + @SerializedName("equip-type") + String getEquipType(); + + /** + * Equipment vendor. Source of truth should define valid values. + **/ + @Nullable + @SerializedName("equip-vendor") + String getEquipVendor(); + + /** + * Equipment model. Source of truth should define valid values. + **/ + @Nullable + @SerializedName("equip-model") + String getEquipModel(); + + /** + * identifier of managed by ATT or customer + **/ + @Nullable + @SerializedName("management-option") + String getManagementOption(); + + /** + * ipv4-oam-address with new naming convention for IP addresses + **/ + @Nullable + @SerializedName("ipaddress-v4-oam") + String getIpaddressV4Oam(); + + /** + * sw-version is the version of SW for the hosted application on the PNF. + **/ + @Nullable + @SerializedName("sw-version") + String getSwVersion(); + + /** + * Used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs. + **/ + @Nullable + @SerializedName("in-maint") + Boolean isInMaint(); + + /** + * ID of the physical frame (relay rack) where pnf is installed. + **/ + @Nullable + @SerializedName("frame-id") + String getFrameId(); + + /** + * Serial number of the device + **/ + @Nullable + @SerializedName("serial-number") + String getSerialNumber(); + + /** + * IPV4 Loopback 0 address + **/ + @Nullable + @SerializedName("ipaddress-v4-loopback-0") + String getIpaddressV4Loopback0(); + + /** + * IPV6 Loopback 0 address + **/ + @Nullable + @SerializedName("ipaddress-v6-loopback-0") + String getIpaddressV6Loopback0(); + + /** + * IPV4 AIM address + **/ + @Nullable + @SerializedName("ipaddress-v4-aim") + String getIpaddressV4Aim(); + + /** + * IPV6 AIM address + **/ + @Nullable + @SerializedName("ipaddress-v6-aim") + String getIpaddressV6Aim(); + + /** + * IPV6 OAM address + **/ + @Nullable + @SerializedName("ipaddress-v6-oam") + String getIpaddressV6Oam(); + + /** + * CANOPI's inventory status. Only set with values exactly as defined by CANOPI. + **/ + @Nullable + @SerializedName("inv-status") + String getInvStatus(); + + /** + * Used for optimistic concurrency. Must be empty on createGson, valid on update and delete. + **/ + @Nullable + @SerializedName("resource-version") + String getResourceVersion(); + + /** + * Prov Status of this device (not under canopi control) Valid values [PREPROV/NVTPROV/PROV] + **/ + @Nullable + @SerializedName("prov-status") + String getProvStatus(); + + /** + * Nf Role is the role performed by this instance in the network. + **/ + @Nullable + @SerializedName("nf-role") + String getNfRole(); + + /** + * Get relationshipList + **/ + @SerializedName("relationship-list") + @Value.Default + default Relationship getRelationshipList() { + return ImmutableRelationship.builder().build(); + } +} + diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/AaiServiceInstanceResultModel.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/AaiServiceInstanceResultModel.java new file mode 100644 index 00000000..67d6ff90 --- /dev/null +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/AaiServiceInstanceResultModel.java @@ -0,0 +1,209 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model; + +import com.google.gson.annotations.SerializedName; +import org.immutables.gson.Gson; +import org.immutables.value.Value; +import org.springframework.lang.Nullable; + +@Value.Immutable +@Gson.TypeAdapters(fieldNamingStrategy = true) +public interface AaiServiceInstanceResultModel { + + /** + * Uniquely identifies this instance of a service + **/ + @Nullable + @SerializedName("service-instance-id") + String getServiceInstanceId(); + + /** + * This field will store a name assigned to the service-instance. + **/ + @Nullable + @SerializedName("service-instance-name") + String getServiceInstanceName(); + + /** + * String capturing type of service. + **/ + @Nullable + @SerializedName("service-type") + String getServiceType(); + + /** + * String capturing the service role. + **/ + @Nullable + @SerializedName("service-role") + String getServiceRole(); + + /** + * This field will store the environment context assigned to the service-instance. + **/ + @Nullable + @SerializedName("environment-context") + String getEnvironmentContext(); + + /** + * This field will store the workload context assigned to the service-instance. + **/ + @Nullable + @SerializedName("workload-context") + String getWorkloadContext(); + + /** + * createGson time of Network Service. + **/ + @Nullable + @SerializedName("created-at") + String getCreatedAt(); + + /** + * last update of Network Service. + **/ + @Nullable + @SerializedName("updated-at") + String getUpdatedAt(); + + /** + * short description for service-instance. + **/ + @Nullable + @SerializedName("description") + String getDescription(); + + /** + * the ASDC model id for this resource or service model. + **/ + @Nullable + @SerializedName("model-invariant-id") + String getModelInvariantId(); + + /** + * the ASDC model version for this resource or service model. + **/ + @Nullable + @SerializedName("model-version-id") + String getModelVersionId(); + + /** + * the ASDC model version for this resource or service model. + **/ + @Nullable + @SerializedName("persona-model-version") + String getPersonaModelVersion(); + + /** + * the ASDC data dictionary widget model. This maps directly to the A&AI widget. + **/ + @Nullable + @SerializedName("widget-model-id") + String getWidgetModelId(); + + /** + * the ASDC data dictionary version of the widget model.This maps directly to the A&AI version of the widget. + **/ + @Nullable + @SerializedName("widget-model-version") + String getWidgetModelVersion(); + + /** + * Indicates the total bandwidth to be used for this service. + **/ + @Nullable + @SerializedName("bandwidth-total") + String getBandwidthTotal(); + + /** + * indicates the upstream bandwidth this service will use on the WAN1 port of the physical device. + **/ + @Nullable + @SerializedName("bandwidth-up-wan1") + String getBandwidthUpWan1(); + + /** + * indicates the downstream bandwidth this service will use on the WAN1 port of the physical device. + **/ + @Nullable + @SerializedName("bandwidth-down-wan1") + String getBandwidthDownWan1(); + + /** + * indicates the upstream bandwidth this service will use on the WAN2 port of the physical device. + **/ + @Nullable + @SerializedName("bandwidth-up-wan2") + String getBandwidthUpWan2(); + + /** + * indicates the downstream bandwidth this service will use on the WAN2 port of the physical device. + **/ + @Nullable + @SerializedName("bandwidth-down-wan2") + String getBandwidthDownWan2(); + + /** + * URL customers will use to access the vHN Portal. + **/ + @Nullable + @SerializedName("vhn-portal-url") + String getVhnPortalUrl(); + + /** + * An identifier that customers assign to the location where this service is being used. + **/ + @Nullable + @SerializedName("service-instance-location-id") + String getServiceInstanceLocationId(); + + /** + * Used for optimistic concurrency. Must be empty on createGson, valid on update and delete. + **/ + @Nullable + @SerializedName("resource-version") + String getResourceVersion(); + + /** + * Path to the controller object. + **/ + @Nullable + @SerializedName("selflink") + String getSelflink(); + + /** + * Orchestration status of this service. + **/ + @Nullable + @SerializedName("orchestration-status") + String getOrchestrationStatus(); + + /** + * Get relationshipList + **/ + @SerializedName("relationship-list") + @Value.Default + default Relationship getRelationshipList() { + return ImmutableRelationship.builder().build(); + } + +}
\ No newline at end of file diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/ConsumerDmaapModel.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/ConsumerDmaapModel.java index b2bac24c..b519c3a5 100644 --- a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/ConsumerDmaapModel.java +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/ConsumerDmaapModel.java @@ -20,7 +20,9 @@ package org.onap.dcaegen2.services.prh.model; +import com.google.gson.JsonObject; import com.google.gson.annotations.SerializedName; +import org.springframework.lang.Nullable; import org.immutables.gson.Gson; import org.immutables.value.Value; import org.onap.dcaegen2.services.sdk.rest.services.model.AaiModel; @@ -37,9 +39,39 @@ public interface ConsumerDmaapModel extends AaiModel, DmaapModel { @SerializedName(value = "correlationId", alternate = "correlationId") String getCorrelationId(); + @Nullable @SerializedName(value = "ipaddress-v4-oam", alternate = "ipaddress-v4-oam") String getIpv4(); + @Nullable @SerializedName(value = "ipaddress-v6-oam", alternate = "ipaddress-v6-oam") String getIpv6(); + + @Nullable + @SerializedName(value = "serial-number", alternate = "serial-number") + String getSerialNumber(); + + @Nullable + @SerializedName(value = "equip-vendor", alternate = "equip-vendor") + String getEquipVendor(); + + @Nullable + @SerializedName(value = "equip-model", alternate = "equip-model") + String getEquipModel(); + + @Nullable + @SerializedName(value = "equip-type", alternate = "equip-type") + String getEquipType(); + + @Nullable + @SerializedName(value = "nf-role", alternate = "nf-role") + String getNfRole(); + + @Nullable + @SerializedName(value = "sw-version", alternate = "sw-version") + String getSwVersion(); + + @Nullable + @SerializedName(value = "additionalFields", alternate = "additionalFields") + JsonObject getAdditionalFields(); } diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/JsonBodyBuilderImpl.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/PnfReadyJsonBodyBuilder.java index b504a4bd..b39c4690 100644 --- a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/JsonBodyBuilderImpl.java +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/PnfReadyJsonBodyBuilder.java @@ -20,16 +20,13 @@ package org.onap.dcaegen2.services.prh.model; -import com.google.gson.GsonBuilder; -import com.google.gson.TypeAdapterFactory; -import org.onap.dcaegen2.services.sdk.rest.services.model.JsonBodyBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.onap.dcaegen2.services.prh.model.ImmutableConsumerDmaapModel.Builder; +import org.onap.dcaegen2.services.prh.model.utils.PrhModelAwareGsonBuilder; -import java.util.ServiceLoader; - -public class JsonBodyBuilderImpl implements JsonBodyBuilder<ConsumerDmaapModel> { - - public JsonBodyBuilderImpl() {} +public class PnfReadyJsonBodyBuilder { /** * Method for serialization object by GSON. @@ -37,10 +34,14 @@ public class JsonBodyBuilderImpl implements JsonBodyBuilder<ConsumerDmaapModel> * @param consumerDmaapModel - object which will be serialized * @return string from serialization */ - public String createJsonBody(ConsumerDmaapModel consumerDmaapModel) { - GsonBuilder gsonBuilder = new GsonBuilder(); - ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory); - return gsonBuilder.create().toJson(ImmutableConsumerDmaapModel.builder().ipv4(consumerDmaapModel.getIpv4()) - .ipv6(consumerDmaapModel.getIpv6()).correlationId(consumerDmaapModel.getCorrelationId()).build()); + public JsonElement createJsonBody(ConsumerDmaapModel consumerDmaapModel) { + Builder builder = ImmutableConsumerDmaapModel.builder() + .correlationId(consumerDmaapModel.getCorrelationId()); + + JsonObject additionalFields = consumerDmaapModel.getAdditionalFields(); + if(additionalFields != null && !additionalFields.equals(new JsonObject())) { + builder.additionalFields(additionalFields); + } + return PrhModelAwareGsonBuilder.createGson().toJsonTree(builder.build()); } }
\ No newline at end of file diff --git a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/CommonFunctionsTest.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/Relationship.java index 86717d7e..d92b7c75 100644 --- a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/CommonFunctionsTest.java +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/Relationship.java @@ -20,16 +20,16 @@ package org.onap.dcaegen2.services.prh.model; -import static org.junit.jupiter.api.Assertions.assertEquals; +import com.google.gson.annotations.SerializedName; +import org.immutables.gson.Gson; +import org.immutables.value.Value; -import org.junit.jupiter.api.Test; +import java.util.List; -class CommonFunctionsTest { +@Value.Immutable +@Gson.TypeAdapters(fieldNamingStrategy = true) +public interface Relationship { - @Test - void createJsonBody_shouldReturnJsonInString() { - String expectedResult = "{\"correlationId\":\"NOKnhfsadhff\",\"ipaddress-v4-oam\":\"256.22.33.155\"" - + ",\"ipaddress-v6-oam\":\"200J:0db8:85a3:0000:0000:8a2e:0370:7334\"}"; - assertEquals(expectedResult, new JsonBodyBuilderImpl().createJsonBody(new ConsumerDmaapModelForUnitTest())); - } -} + @SerializedName("relationship") + List<RelationshipDict> getRelationship(); +}
\ No newline at end of file diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/ConsumerDmaapModelForUnitTest.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/RelationshipData.java index cbada731..4b1670c6 100644 --- a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/ConsumerDmaapModelForUnitTest.java +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/RelationshipData.java @@ -20,32 +20,30 @@ package org.onap.dcaegen2.services.prh.model; -public class ConsumerDmaapModelForUnitTest implements ConsumerDmaapModel { +import com.google.gson.annotations.SerializedName; +import org.immutables.gson.Gson; +import org.immutables.value.Value; - private final String correlationId; - private final String ipv4; - private final String ipv6; +/** + * RelationshipData + */ +@Value.Immutable +@Gson.TypeAdapters(fieldNamingStrategy = true) +public interface RelationshipData { /** - * Class for testing serialization of ConsumerDmaapModel. - */ - public ConsumerDmaapModelForUnitTest() { - this.correlationId = "NOKnhfsadhff"; - this.ipv4 = "256.22.33.155"; - this.ipv6 = "200J:0db8:85a3:0000:0000:8a2e:0370:7334"; - - } - - public String getCorrelationId() { - return correlationId; - } + * A keyword provided by A&AI to indicate an attribute. + * + * @return relationshipKey + **/ + @SerializedName("relationship-key") + String getRelationshipKey(); - public String getIpv4() { - return ipv4; - } - - public String getIpv6() { - return ipv6; - } - -} + /** + * Value of the attribute. + * + * @return relationshipValue + **/ + @SerializedName("relationship-value") + String getRelationshipValue(); +}
\ No newline at end of file diff --git a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/ConsumerDmaapModelTest.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/RelationshipDict.java index 4c4c345f..007f371b 100644 --- a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/ConsumerDmaapModelTest.java +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/RelationshipDict.java @@ -20,29 +20,49 @@ package org.onap.dcaegen2.services.prh.model; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -class ConsumerDmaapModelTest { - - @Test - void consumerDmaapModelBuilder_shouldBuildAnObject() { - - // When - // Given - String sourceName = "NOKnhfsadhff"; - String ipv4 = "11.22.33.155"; - String ipv6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; - ConsumerDmaapModel consumerDmaapModel = ImmutableConsumerDmaapModel.builder() - .correlationId(sourceName) - .ipv4(ipv4) - .ipv6(ipv6) - .build(); - - // Then - Assertions.assertNotNull(consumerDmaapModel); - Assertions.assertEquals(sourceName, consumerDmaapModel.getCorrelationId()); - Assertions.assertEquals(ipv4, consumerDmaapModel.getIpv4()); - Assertions.assertEquals(ipv6, consumerDmaapModel.getIpv6()); +import com.google.gson.annotations.SerializedName; +import org.immutables.gson.Gson; +import org.immutables.value.Value; +import org.springframework.lang.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * RelationshipDict + */ +@Value.Immutable +@Gson.TypeAdapters(fieldNamingStrategy = true) +public interface RelationshipDict { + + /** + * A keyword provided by A&AI to indicate type of node. + **/ + @Nullable + @SerializedName("related-to") + String getRelatedTo(); + + /** + * The edge label for this relationship. + **/ + @Nullable + @SerializedName("relationship-label") + String getRelationshipLabel(); + + /** + * URL to the object in A&AI. + **/ + @Nullable + @SerializedName("related-link") + String getRelatedLink(); + + /** + * relationship Data + **/ + @SerializedName("relationship-data") + @Value.Default + default List<RelationshipData> getRelationshipData() { + return Collections.emptyList(); } -} + +}
\ No newline at end of file diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/bbs/LogicalLink.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/bbs/LogicalLink.java new file mode 100644 index 00000000..3b3dce15 --- /dev/null +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/bbs/LogicalLink.java @@ -0,0 +1,49 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ +package org.onap.dcaegen2.services.prh.model.bbs; + +import com.google.gson.annotations.SerializedName; +import org.immutables.gson.Gson; +import org.immutables.value.Value; +import org.onap.dcaegen2.services.prh.model.ImmutableRelationship; +import org.onap.dcaegen2.services.prh.model.Relationship; +import org.onap.dcaegen2.services.sdk.rest.services.model.ClientModel; +import org.springframework.lang.Nullable; + +@Value.Immutable +@Gson.TypeAdapters(fieldNamingStrategy = true) +public interface LogicalLink extends ClientModel { + + @SerializedName(value = "link-name") + String getLinkName(); + + @SerializedName(value = "link-type") + String getLinkType(); + + @Nullable + @SerializedName(value = "resource-version") + String getResourceVersion(); + + @SerializedName("relationship-list") + @Value.Default + default Relationship getRelationshipList() { + return ImmutableRelationship.builder().build(); + } +} diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/NamedNode.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/NamedNode.java new file mode 100644 index 00000000..6329e7e0 --- /dev/null +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/NamedNode.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model.queries; + +import java.util.Map; +import org.immutables.value.Value; + +/** + * @see NamedNodeAdapter + * @see NamedNodes + */ +@Value.Immutable +public interface NamedNode { + String name(); + Map<String, Object> properties(); +}
\ No newline at end of file diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/NamedNodeAdapter.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/NamedNodeAdapter.java new file mode 100644 index 00000000..be6c8d5b --- /dev/null +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/NamedNodeAdapter.java @@ -0,0 +1,71 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model.queries; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import org.onap.dcaegen2.services.prh.model.queries.ImmutableNamedNode.Builder; + +/** + * @see NamedNode + * @see <a href="https://docs.onap.org/en/dublin/submodules/aai/aai-common.git/docs/AAI%20REST%20API%20Documentation/customQueries.html">AAI + * Custom queries</a></a> + */ +public class NamedNodeAdapter extends TypeAdapter<NamedNode> { + + @Override + public void write(JsonWriter jsonWriter, NamedNode namedNode) { + throw new UnsupportedOperationException("This model is read only!"); + } + + @Override + public NamedNode read(JsonReader jsonReader) throws IOException { + jsonReader.beginObject(); + Builder nodeBuilder = ImmutableNamedNode.builder().name(jsonReader.nextName()); + readProperties(jsonReader, nodeBuilder); + jsonReader.endObject(); + + return nodeBuilder.build(); + } + + private void readProperties(JsonReader jsonReader, Builder nodeBuilder) throws IOException { + jsonReader.beginObject(); + while (jsonReader.hasNext()) { + String key = jsonReader.nextName(); + switch (jsonReader.peek()) { + case STRING: + nodeBuilder.putProperties(key, jsonReader.nextString()); + break; + case NUMBER: + nodeBuilder.putProperties(key, jsonReader.nextInt()); + break; + case BOOLEAN: + nodeBuilder.putProperties(key, jsonReader.nextBoolean()); + break; + default: + jsonReader.skipValue(); + } + } + jsonReader.endObject(); + } +}
\ No newline at end of file diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/NamedNodes.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/NamedNodes.java new file mode 100644 index 00000000..6a463ddf --- /dev/null +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/NamedNodes.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model.queries; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import org.immutables.gson.Gson; +import org.immutables.value.Value; + +/** + * @see NamedNode + * @see PnfQuery + * @see <a href="https://docs.onap.org/en/dublin/submodules/aai/aai-common.git/docs/AAI%20REST%20API%20Documentation/customQueries.html">AAI + * Custom queries</a></a> + */ +@Value.Immutable +@Gson.TypeAdapters(fieldNamingStrategy = true) +public interface NamedNodes { + + @SerializedName(value = "results") + List<NamedNode> results(); +}
\ No newline at end of file diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/PnfQuery.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/PnfQuery.java new file mode 100644 index 00000000..7a9025aa --- /dev/null +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/queries/PnfQuery.java @@ -0,0 +1,54 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model.queries; + +import static java.util.Arrays.asList; +import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.PUT; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import org.onap.dcaegen2.services.sdk.rest.services.aai.client.service.http.Request; +import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod; + +/** + * @see NamedNodes + * @see <a href="https://docs.onap.org/en/dublin/submodules/aai/aai-common.git/docs/AAI%20REST%20API%20Documentation/customQueries.html">AAI + * Custom queries</a></a> + */ +public class PnfQuery implements Request { + + @SerializedName("start") + private final List<String> startNodes; + + public PnfQuery(String pnfName) { + this.startNodes = asList("/nodes/pnfs/pnf/" + pnfName); + } + + @Override + public HttpMethod method() { + return PUT; + } + + @Override + public String uri() { + return "/query?format=resource&subgraph=star&nodesOnly=true"; + } +}
\ No newline at end of file diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/utils/PrhModelAwareGsonBuilder.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/utils/PrhModelAwareGsonBuilder.java new file mode 100644 index 00000000..e01711a7 --- /dev/null +++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/model/utils/PrhModelAwareGsonBuilder.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapterFactory; +import java.util.ServiceLoader; +import org.onap.dcaegen2.services.prh.model.queries.NamedNode; +import org.onap.dcaegen2.services.prh.model.queries.NamedNodeAdapter; + +public final class PrhModelAwareGsonBuilder { + + private static final Iterable<TypeAdapterFactory> TYPE_ADAPTER_FACTORIES = + ServiceLoader.load(TypeAdapterFactory.class); + + public static Gson createGson() { + GsonBuilder gsonBuilder = new GsonBuilder(); + TYPE_ADAPTER_FACTORIES.forEach(gsonBuilder::registerTypeAdapterFactory); + gsonBuilder.registerTypeAdapter(NamedNode.class, new NamedNodeAdapter()); + return gsonBuilder.create(); + } +} diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/ssl/SslFactory.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/ssl/SslFactory.java deleted file mode 100644 index 60e1224e..00000000 --- a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/ssl/SslFactory.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PNF-REGISTRATION-HANDLER - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.ssl; - -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLException; -import javax.net.ssl.TrustManagerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SslFactory { - - private static final Logger LOGGER = LoggerFactory.getLogger(SslFactory.class); - - /** - * Function for creating secure ssl context. - * - * @param keyStorePath - path to file with keystore - * @param keyStorePasswordPath - path to file with keystore password - * @param trustStorePath - path to file with truststore - * @param trustStorePasswordPath - path to file with truststore password - * @return configured ssl context - */ - public SslContext createSecureContext(String keyStorePath, - String keyStorePasswordPath, - String trustStorePath, - String trustStorePasswordPath) throws SSLException { - LOGGER.info("Creating secure ssl context for: {} {}", keyStorePath, trustStorePath); - try { - return SslContextBuilder - .forClient() - .keyManager(keyManagerFactory(keyStorePath, loadPasswordFromFile(keyStorePasswordPath))) - .trustManager(trustManagerFactory(trustStorePath, loadPasswordFromFile(trustStorePasswordPath))) - .build(); - } catch (GeneralSecurityException | IOException ex) { - throw new SSLException(ex); - } - } - - /** - * Function for creating insecure ssl context. - * - * @return configured insecure ssl context - */ - public SslContext createInsecureContext() throws SSLException { - LOGGER.info("Creating insecure ssl context"); - return SslContextBuilder - .forClient() - .trustManager(InsecureTrustManagerFactory.INSTANCE) - .build(); - } - - private KeyManagerFactory keyManagerFactory(String path, String password) - throws GeneralSecurityException, IOException { - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(loadKeyStoreFromFile(path, password), - password.toCharArray()); - return kmf; - } - - private TrustManagerFactory trustManagerFactory(String path, String password) - throws GeneralSecurityException, IOException { - TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(loadKeyStoreFromFile(path, password)); - return tmf; - } - - private KeyStore loadKeyStoreFromFile(String path, String keyStorePassword) - throws GeneralSecurityException, IOException { - KeyStore ks = KeyStore.getInstance("jks"); - ks.load(getResource(path), keyStorePassword.toCharArray()); - return ks; - } - - private InputStream getResource(String path) throws FileNotFoundException { - return new FileInputStream(path); - } - - private String loadPasswordFromFile(String path) throws IOException { - return new String(Files.readAllBytes(Paths.get(path))); - } -} diff --git a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/AaiJsonBodyBuilderTest.java b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/AaiJsonBodyBuilderTest.java new file mode 100644 index 00000000..60ce520c --- /dev/null +++ b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/AaiJsonBodyBuilderTest.java @@ -0,0 +1,114 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.junit.jupiter.api.Test; + +class AaiJsonBodyBuilderTest { + + @Test + void createJsonBody_shouldReturnJsonInString() { + + ConsumerDmaapModel model = ImmutableConsumerDmaapModel.builder() + .correlationId("NOKnhfsadhff") + .ipv4("256.22.33.155") + .ipv6("200J:0db8:85a3:0000:0000:8a2e:0370:7334") + .serialNumber("1234") + .equipVendor("NOKIA") + .equipModel("3310") + .equipType("cell") + .nfRole("role") + .swVersion("1.2.3") + .build(); + + String expectedResult = "{" + + "\"correlationId\":\"NOKnhfsadhff\"," + + "\"ipaddress-v4-oam\":\"256.22.33.155\"," + + "\"ipaddress-v6-oam\":\"200J:0db8:85a3:0000:0000:8a2e:0370:7334\"," + + "\"serial-number\":\"1234\"," + + "\"equip-vendor\":\"NOKIA\"," + + "\"equip-model\":\"3310\"," + + "\"equip-type\":\"cell\"," + + "\"nf-role\":\"role\"," + + "\"sw-version\":\"1.2.3\"" + + "}"; + + assertEquals(expectedResult, new AaiJsonBodyBuilderImpl().createJsonBody(model)); + } + + @Test + void createJsonBodyWithoutIPs_shouldReturnJsonInString() { + + ConsumerDmaapModel model = ImmutableConsumerDmaapModel.builder() + .correlationId("NOKnhfsadhff") + .serialNumber("1234") + .equipVendor("NOKIA") + .equipModel("3310") + .equipType("cell") + .nfRole("role") + .swVersion("1.2.3") + .build(); + + String expectedResult = "{" + + "\"correlationId\":\"NOKnhfsadhff\"," + + "\"serial-number\":\"1234\"," + + "\"equip-vendor\":\"NOKIA\"," + + "\"equip-model\":\"3310\"," + + "\"equip-type\":\"cell\"," + + "\"nf-role\":\"role\"," + + "\"sw-version\":\"1.2.3\"" + + "}"; + + assertEquals(expectedResult, new AaiJsonBodyBuilderImpl().createJsonBody(model)); + } + + @Test + void createJsonBodyWithEmptyIPs_shouldReturnJsonInString() { + + ConsumerDmaapModel model = ImmutableConsumerDmaapModel.builder() + .correlationId("NOKnhfsadhff") + .ipv4("") + .ipv6("") + .serialNumber("1234") + .equipVendor("NOKIA") + .equipModel("3310") + .equipType("cell") + .nfRole("role") + .swVersion("1.2.3") + .build(); + + String expectedResult = "{" + + "\"correlationId\":\"NOKnhfsadhff\"," + + "\"serial-number\":\"1234\"," + + "\"equip-vendor\":\"NOKIA\"," + + "\"equip-model\":\"3310\"," + + "\"equip-type\":\"cell\"," + + "\"nf-role\":\"role\"," + + "\"sw-version\":\"1.2.3\"" + + "}"; + + assertEquals(expectedResult, new AaiJsonBodyBuilderImpl().createJsonBody(model)); + } +} diff --git a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/AaiPnfResultModelTest.java b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/AaiPnfResultModelTest.java new file mode 100644 index 00000000..3f396e82 --- /dev/null +++ b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/AaiPnfResultModelTest.java @@ -0,0 +1,87 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model; + +import com.google.gson.Gson; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.services.prh.model.utils.PrhModelAwareGsonBuilder; + +import java.io.InputStreamReader; +import java.util.Objects; + +import static org.assertj.core.api.Assertions.assertThat; + +class AaiPnfResultModelTest { + + @Test + void shouldParseAaiPnf() { + Gson gson = PrhModelAwareGsonBuilder.createGson(); + AaiPnfResultModel pnf = gson.fromJson(new InputStreamReader(Objects.requireNonNull( + ClassLoader.getSystemResourceAsStream("some_aai_pnf.json"))), AaiPnfResultModel.class); + + assertThat(pnf.getPnfName()).isEqualTo("some pnfName"); + assertThat(pnf.getPnfName2()).isEqualTo("some pnfName2"); + assertThat(pnf.getSelflink()).isEqualTo("some selflink"); + assertThat(pnf.getPnfName2Source()).isEqualTo("some pnfName2Source"); + assertThat(pnf.getPnfId()).isEqualTo("some pnfId"); + assertThat(pnf.getEquipType()).isEqualTo("some equipType"); + assertThat(pnf.getEquipVendor()).isEqualTo("some equipVendor"); + assertThat(pnf.getEquipModel()).isEqualTo("some equipModel"); + assertThat(pnf.getManagementOption()).isEqualTo("some managementOption"); + assertThat(pnf.getIpaddressV4Oam()).isEqualTo("some ipaddressV4Oam"); + assertThat(pnf.getSwVersion()).isEqualTo("some swVersion"); + assertThat(pnf.isInMaint()).isFalse(); + assertThat(pnf.getFrameId()).isEqualTo("some frameId"); + assertThat(pnf.getSerialNumber()).isEqualTo("some serialNumber"); + assertThat(pnf.getIpaddressV4Loopback0()).isEqualTo("some ipaddressV4Loopback0"); + assertThat(pnf.getIpaddressV6Loopback0()).isEqualTo("some ipaddressV6Loopback0"); + assertThat(pnf.getIpaddressV4Aim()).isEqualTo("some ipaddressV4Aim"); + assertThat(pnf.getIpaddressV6Aim()).isEqualTo("some ipaddressV6Aim"); + assertThat(pnf.getIpaddressV6Oam()).isEqualTo("some ipaddressV6Oam"); + assertThat(pnf.getInvStatus()).isEqualTo("some invStatus"); + assertThat(pnf.getResourceVersion()).isEqualTo("some resourceVersion"); + assertThat(pnf.getProvStatus()).isEqualTo("some provStatus"); + assertThat(pnf.getNfRole()).isEqualTo("some nfRole"); + + assertThat(pnf.getRelationshipList().getRelationship()).hasSize(1); + RelationshipDict relationshipDict = pnf.getRelationshipList().getRelationship().get(0); + assertThat(relationshipDict.getRelatedTo()).isEqualTo("some relatedTo"); + assertThat(relationshipDict.getRelationshipData()).hasSize(1); + RelationshipData relationshipData = relationshipDict.getRelationshipData().get(0); + assertThat(relationshipData.getRelationshipKey()).isEqualTo("some relationshipKey"); + assertThat(relationshipData.getRelationshipValue()).isEqualTo("some relationshipValue"); + } + + @Test + void shouldProvideEmptyRelationshipListForEmptyJson() { + Gson gson = PrhModelAwareGsonBuilder.createGson(); + AaiPnfResultModel pnf = gson.fromJson("{}", AaiPnfResultModel.class); + assertThat(pnf.getRelationshipList()).isNotNull(); + assertThat(pnf.getRelationshipList().getRelationship()).isEmpty(); + } + + @Test + void shouldIgnoreUnexpectedFieldsInJson() { + Gson gson = PrhModelAwareGsonBuilder.createGson(); + gson.fromJson("{\"foo\":\"bar\"}", AaiPnfResultModel.class); + } + +}
\ No newline at end of file diff --git a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/AaiServiceInstanceResultModelTest.java b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/AaiServiceInstanceResultModelTest.java new file mode 100644 index 00000000..5f9ca14d --- /dev/null +++ b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/AaiServiceInstanceResultModelTest.java @@ -0,0 +1,89 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model; + +import com.google.gson.Gson; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.services.prh.model.utils.PrhModelAwareGsonBuilder; + +import java.io.InputStreamReader; +import java.util.Objects; + +import static org.assertj.core.api.Assertions.assertThat; + +class AaiServiceInstanceResultModelTest { + + @Test + void shouldParseAaiServiceInstance() { + AaiServiceInstanceResultModel serviceInstance = PrhModelAwareGsonBuilder.createGson().fromJson( + new InputStreamReader(Objects.requireNonNull( + ClassLoader.getSystemResourceAsStream("some_aai_service_instance.json"))), + AaiServiceInstanceResultModel.class); + + assertThat(serviceInstance.getServiceInstanceId()).isEqualTo("some serviceInstanceId"); + assertThat(serviceInstance.getServiceInstanceName()).isEqualTo("some serviceInstanceName"); + assertThat(serviceInstance.getServiceType()).isEqualTo("some serviceType"); + assertThat(serviceInstance.getServiceRole()).isEqualTo("some serviceRole"); + assertThat(serviceInstance.getEnvironmentContext()).isEqualTo("some environmentContext"); + assertThat(serviceInstance.getWorkloadContext()).isEqualTo("some workloadContext"); + assertThat(serviceInstance.getCreatedAt()).isEqualTo("some createdAt"); + assertThat(serviceInstance.getUpdatedAt()).isEqualTo("some updatedAt"); + assertThat(serviceInstance.getDescription()).isEqualTo("some description"); + assertThat(serviceInstance.getModelInvariantId()).isEqualTo("some modelInvariantId"); + assertThat(serviceInstance.getModelVersionId()).isEqualTo("some modelVersionId"); + assertThat(serviceInstance.getPersonaModelVersion()).isEqualTo("some personaModelVersion"); + assertThat(serviceInstance.getWidgetModelId()).isEqualTo("some widgetModelId"); + assertThat(serviceInstance.getWidgetModelVersion()).isEqualTo("some widgetModelVersion"); + assertThat(serviceInstance.getBandwidthTotal()).isEqualTo("some bandwidthTotal"); + assertThat(serviceInstance.getBandwidthUpWan1()).isEqualTo("some bandwidthUpWan1"); + assertThat(serviceInstance.getBandwidthDownWan1()).isEqualTo("some bandwidthDownWan1"); + assertThat(serviceInstance.getBandwidthUpWan2()).isEqualTo("some bandwidthUpWan2"); + assertThat(serviceInstance.getBandwidthDownWan2()).isEqualTo("some bandwidthDownWan2"); + assertThat(serviceInstance.getVhnPortalUrl()).isEqualTo("some vhnPortalUrl"); + assertThat(serviceInstance.getServiceInstanceLocationId()).isEqualTo("some serviceInstanceLocationId"); + assertThat(serviceInstance.getResourceVersion()).isEqualTo("some resourceVersion"); + assertThat(serviceInstance.getSelflink()).isEqualTo("some selflink"); + assertThat(serviceInstance.getOrchestrationStatus()).isEqualTo("some orchestrationStatus"); + + RelationshipDict relationshipDict = serviceInstance.getRelationshipList().getRelationship().get(0); + assertThat(relationshipDict.getRelatedTo()).isEqualTo("some relatedTo"); + assertThat(relationshipDict.getRelationshipData()).hasSize(1); + RelationshipData relationshipData = relationshipDict.getRelationshipData().get(0); + assertThat(relationshipData.getRelationshipKey()).isEqualTo("some relationshipKey"); + assertThat(relationshipData.getRelationshipValue()).isEqualTo("some relationshipValue"); + } + + + @Test + void shouldProvideEmptyRelationshipListForEmptyJson() { + Gson gson = PrhModelAwareGsonBuilder.createGson(); + AaiServiceInstanceResultModel serviceInstance = gson.fromJson("{}", AaiServiceInstanceResultModel.class); + assertThat(serviceInstance.getRelationshipList()).isNotNull(); + assertThat(serviceInstance.getRelationshipList().getRelationship()).isEmpty(); + } + + @Test + void shouldIgnoreUnexpectedFieldsInJson() { + Gson gson = PrhModelAwareGsonBuilder.createGson(); + gson.fromJson("{\"foo\":\"bar\"}", AaiServiceInstanceResultModel.class); + } + +}
\ No newline at end of file diff --git a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/PnfReadyJsonBodyBuilderTest.java b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/PnfReadyJsonBodyBuilderTest.java new file mode 100644 index 00000000..769e1673 --- /dev/null +++ b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/PnfReadyJsonBodyBuilderTest.java @@ -0,0 +1,82 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.junit.jupiter.api.Test; + +class PnfReadyJsonBodyBuilderTest { + + @Test + void createJsonBody_shouldReturnJsonInString() { + + JsonObject jsonObject = parse("{\n" + + " \"attachmentPoint\": \"bla-bla-30-3\",\n" + + " \"cvlan\": \"678\",\n" + + " \"svlan\": \"1005\"\n" + + " }"); + + ConsumerDmaapModel model = ImmutableConsumerDmaapModel.builder() + .correlationId("NOKnhfsadhff") + .additionalFields(jsonObject) + .build(); + + JsonObject expectedResult = parse("{" + + "\"correlationId\":\"NOKnhfsadhff\"," + + "\"additionalFields\":{\"attachmentPoint\":\"bla-bla-30-3\",\"cvlan\":\"678\",\"svlan\":\"1005\"}" + + "}"); + + assertEquals(expectedResult, new PnfReadyJsonBodyBuilder().createJsonBody(model)); + } + + @Test + void createJsonBodyWithNullableFieldsNotSet_shouldReturnJsonInString() { + + ConsumerDmaapModel model = ImmutableConsumerDmaapModel.builder() + .correlationId("NOKnhfsadhff") + .build(); + + JsonObject expectedResult = parse("{\"correlationId\":\"NOKnhfsadhff\"}"); + + assertEquals(expectedResult, new PnfReadyJsonBodyBuilder().createJsonBody(model)); + } + + @Test + void createJsonBodyWithEmptyOptionalPnfRegistrationFields_shouldReturnJsonInString() { + JsonObject jsonObject = new JsonObject(); + + ConsumerDmaapModel model = ImmutableConsumerDmaapModel.builder() + .correlationId("NOKnhfsadhff") + .additionalFields(jsonObject) + .build(); + + JsonObject expectedResult = parse("{\"correlationId\":\"NOKnhfsadhff\"}"); + + assertEquals(expectedResult, new PnfReadyJsonBodyBuilder().createJsonBody(model)); + } + + private static JsonObject parse(String jsonString) { + return new JsonParser().parse(jsonString).getAsJsonObject(); + } +} diff --git a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/queries/NamedNodesTest.java b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/queries/NamedNodesTest.java new file mode 100644 index 00000000..0991d31f --- /dev/null +++ b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/queries/NamedNodesTest.java @@ -0,0 +1,58 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model.queries; + +import static java.util.Objects.requireNonNull; +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.Gson; +import java.io.InputStreamReader; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.services.prh.model.utils.PrhModelAwareGsonBuilder; + +class NamedNodesTest { + + @Test + void shouldParseJsonToNamedNodes() { + // given + InputStreamReader inputStream = getJsonFromFile("pnf_query_response.json"); + Gson gson = PrhModelAwareGsonBuilder.createGson(); + + // when + NamedNodes nodes = gson.fromJson(inputStream, NamedNodes.class); + + // then + assertThat(nodes.results().size()).isEqualTo(3); + assertThat(nodes.results().get(0)) + .matches(node -> "pnf".equals(node.name())) + .matches(node -> node.properties().get("pnf-name").equals("foo")); + assertThat(nodes.results().get(1)) + .matches(node -> "logical-link".equals(node.name())) + .matches(node -> node.properties().get("link-name").equals("bar")); + assertThat(nodes.results().get(2)) + .matches(node -> "service-instance".equals(node.name())) + .matches(node -> node.properties().get("service-instance-name").equals("baz")); + } + + private InputStreamReader getJsonFromFile(String file) { + return new InputStreamReader(requireNonNull(getClass().getClassLoader().getResourceAsStream(file))); + } +} diff --git a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/queries/PnfQueryTest.java b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/queries/PnfQueryTest.java new file mode 100644 index 00000000..0ab0b17b --- /dev/null +++ b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/model/queries/PnfQueryTest.java @@ -0,0 +1,55 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * 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========================================================= + */ + +package org.onap.dcaegen2.services.prh.model.queries; + +import static java.util.Objects.requireNonNull; +import static java.util.stream.Collectors.joining; +import static org.assertj.core.api.Assertions.assertThat; + +import com.google.gson.Gson; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import org.junit.jupiter.api.Test; +import org.onap.dcaegen2.services.prh.model.utils.PrhModelAwareGsonBuilder; + +class PnfQueryTest { + + @Test + void shouldParseToCorrectJson() throws IOException { + // given + PnfQuery pnfQuery = new PnfQuery("foo"); + + // when + Gson gson = PrhModelAwareGsonBuilder.createGson(); + + // then + String json = gson.toJson(pnfQuery); + assertThat(json).isEqualToIgnoringWhitespace(getJsonFromFile("pnf_query_request.json")); + } + + private String getJsonFromFile(String file) throws IOException { + try (BufferedReader br = new BufferedReader(new InputStreamReader( + requireNonNull(getClass().getClassLoader().getResourceAsStream(file))))) { + return br.lines().collect(joining(System.lineSeparator())); + } + } +}
\ No newline at end of file diff --git a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/ssl/SslFactoryTest.java b/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/ssl/SslFactoryTest.java deleted file mode 100644 index dbd63911..00000000 --- a/prh-commons/src/test/java/org/onap/dcaegen2/services/prh/ssl/SslFactoryTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PNF-REGISTRATION-HANDLER - * ================================================================================ - * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved. - * ================================================================================ - * 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========================================================= - */ - -package org.onap.dcaegen2.services.prh.ssl; - -import javax.net.ssl.SSLException; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - - -class SslFactoryTest { - - private static final String KEY_STORE = "org.onap.dcae.jks"; - private static final String KEYSTORE_PASSWORD = "keystore.password"; - private static final String TRUSTSTORE_PASSWORD = "truststore.password"; - private static final String TRUST_STORE = "org.onap.dcae.trust.jks"; - private SslFactory sslFactory = new SslFactory(); - - @Test - void shouldCreateInsecureContext() throws SSLException { - Assertions.assertNotNull(sslFactory.createInsecureContext()); - } - - @Test - void shouldCreateSecureContext() throws SSLException { - Assertions.assertNotNull(sslFactory.createSecureContext( - getPath(KEY_STORE), - getPath(KEYSTORE_PASSWORD), - getPath(TRUST_STORE), - getPath(TRUSTSTORE_PASSWORD))); - } - - @Test - void shouldThrowSslExceptionWhenKeystorePasswordIsIncorrect() { - Assertions.assertThrows(SSLException.class, () -> sslFactory.createSecureContext( - getPath(KEY_STORE), - getPath(TRUSTSTORE_PASSWORD), - getPath(TRUST_STORE), - getPath(TRUSTSTORE_PASSWORD))); - } - - private String getPath(String fileName) { - return this.getClass().getClassLoader().getResource(fileName).getPath(); - } -}
\ No newline at end of file diff --git a/prh-commons/src/test/resources/pnf_query_request.json b/prh-commons/src/test/resources/pnf_query_request.json new file mode 100644 index 00000000..2a171c76 --- /dev/null +++ b/prh-commons/src/test/resources/pnf_query_request.json @@ -0,0 +1,5 @@ +{ + "start": [ + "/nodes/pnfs/pnf/foo" + ] +}
\ No newline at end of file diff --git a/prh-commons/src/test/resources/pnf_query_response.json b/prh-commons/src/test/resources/pnf_query_response.json new file mode 100644 index 00000000..f74b37a6 --- /dev/null +++ b/prh-commons/src/test/resources/pnf_query_response.json @@ -0,0 +1,27 @@ +{ + "results": [ + { + "pnf": { + "pnf-name": "foo", + "in-maint": false, + "resource-version": "1559732370039" + } + }, + { + "logical-link": { + "link-name": "bar", + "in-maint": false, + "link-type": "attachment-point", + "resource-version": "1559805666899" + } + }, + { + "service-instance": { + "service-instance-id": "pnf-service-id", + "service-instance-name": "baz", + "resource-version": "1559732385933", + "orchestration-status": "ACTIVE" + } + } + ] +}
\ No newline at end of file diff --git a/prh-commons/src/test/resources/some_aai_pnf.json b/prh-commons/src/test/resources/some_aai_pnf.json new file mode 100644 index 00000000..ee158dff --- /dev/null +++ b/prh-commons/src/test/resources/some_aai_pnf.json @@ -0,0 +1,38 @@ +{ + "pnf-name": "some pnfName", + "pnf-name2": "some pnfName2", + "selflink": "some selflink", + "pnf-name2-source": "some pnfName2Source", + "pnf-id": "some pnfId", + "equip-type": "some equipType", + "equip-vendor": "some equipVendor", + "equip-model": "some equipModel", + "management-option": "some managementOption", + "ipaddress-v4-oam": "some ipaddressV4Oam", + "sw-version": "some swVersion", + "in-maint": false, + "frame-id": "some frameId", + "serial-number": "some serialNumber", + "ipaddress-v4-loopback-0": "some ipaddressV4Loopback0", + "ipaddress-v6-loopback-0": "some ipaddressV6Loopback0", + "ipaddress-v4-aim": "some ipaddressV4Aim", + "ipaddress-v6-aim": "some ipaddressV6Aim", + "ipaddress-v6-oam": "some ipaddressV6Oam", + "inv-status": "some invStatus", + "resource-version": "some resourceVersion", + "prov-status": "some provStatus", + "nf-role": "some nfRole", + "relationship-list": { + "relationship": [ + { + "related-to": "some relatedTo", + "relationship-data": [ + { + "relationship-key": "some relationshipKey", + "relationship-value": "some relationshipValue" + } + ] + } + ] + } +}
\ No newline at end of file diff --git a/prh-commons/src/test/resources/some_aai_service_instance.json b/prh-commons/src/test/resources/some_aai_service_instance.json new file mode 100644 index 00000000..31857314 --- /dev/null +++ b/prh-commons/src/test/resources/some_aai_service_instance.json @@ -0,0 +1,39 @@ +{ + "service-instance-id": "some serviceInstanceId", + "service-instance-name": "some serviceInstanceName", + "service-type": "some serviceType", + "service-role": "some serviceRole", + "environment-context": "some environmentContext", + "workload-context": "some workloadContext", + "created-at": "some createdAt", + "updated-at": "some updatedAt", + "description": "some description", + "model-invariant-id": "some modelInvariantId", + "model-version-id": "some modelVersionId", + "persona-model-version": "some personaModelVersion", + "widget-model-id": "some widgetModelId", + "widget-model-version": "some widgetModelVersion", + "bandwidth-total": "some bandwidthTotal", + "bandwidth-up-wan1": "some bandwidthUpWan1", + "bandwidth-down-wan1": "some bandwidthDownWan1", + "bandwidth-up-wan2": "some bandwidthUpWan2", + "bandwidth-down-wan2": "some bandwidthDownWan2", + "vhn-portal-url": "some vhnPortalUrl", + "service-instance-location-id": "some serviceInstanceLocationId", + "resource-version": "some resourceVersion", + "selflink": "some selflink", + "orchestration-status": "some orchestrationStatus", + "relationship-list": { + "relationship": [ + { + "related-to": "some relatedTo", + "relationship-data": [ + { + "relationship-key": "some relationshipKey", + "relationship-value": "some relationshipValue" + } + ] + } + ] + } +}
\ No newline at end of file diff --git a/swagger.yaml b/swagger.yaml deleted file mode 100644 index 37040bc8..00000000 --- a/swagger.yaml +++ /dev/null @@ -1,76 +0,0 @@ ---- -swagger: '2.0' -info: - description: This page lists all the rest apis for PRH app server. - version: '1.0' - title: PRH app server -host: localhost:8100 -basePath: "/" -tags: -- name: heartbeat-controller - description: Check liveness of PRH service -- name: schedule-controller - description: Schedule Controller -paths: - "/heartbeat": - get: - tags: - - heartbeat-controller - summary: Returns liveness of PRH service - operationId: heartbeatUsingGET - produces: - - "*/*" - responses: - '200': - description: PRH sevice is living - schema: - "$ref": "#/definitions/Mono«ResponseEntity«string»»" - '401': - description: You are not authorized to view the resource - '403': - description: Accessing the resource you were trying to reach is forbidden - '404': - description: The resource you were trying to reach is not found - "/start": - get: - tags: - - schedule-controller - summary: Start scheduling worker request - operationId: startTasksUsingGET - produces: - - "*/*" - responses: - '200': - description: OK - schema: - "$ref": "#/definitions/Mono«ResponseEntity«string»»" - '401': - description: Unauthorized - '403': - description: Forbidden - '404': - description: Not Found - "/stopPrh": - get: - tags: - - schedule-controller - summary: Stop scheduling worker request - operationId: stopTaskUsingGET - produces: - - "*/*" - responses: - '200': - description: OK - schema: - "$ref": "#/definitions/Mono«ResponseEntity«string»»" - '401': - description: Unauthorized - '403': - description: Forbidden - '404': - description: Not Found -definitions: - Mono«ResponseEntity«string»»: - type: object - title: Mono«ResponseEntity«string»» - diff --git a/version.properties b/version.properties index 07578e54..fee49286 100644 --- a/version.properties +++ b/version.properties @@ -1,6 +1,6 @@ -major=1
-minor=2
-patch=0
-base_version=${major}.${minor}.${patch}
-release_version=${base_version}
-snapshot_version=${base_version}-SNAPSHOT
+major=1 +minor=3 +patch=1 +base_version=${major}.${minor}.${patch} +release_version=${base_version} +snapshot_version=${base_version}-SNAPSHOT |