diff options
238 files changed, 14641 insertions, 5639 deletions
@@ -41,16 +41,6 @@ committers: company: 'IC' id: 'jackl' timezone: 'America/New_York' - - name: 'Remigiusz Janeczek' - email: 'remigiusz.janeczek@nokia.com' - company: 'Nokia' - id: 'rjanecze' - timezone: 'Europe/Warsaw' - - name: 'Joanna Jeremicz' - email: 'joanna.jeremicz@nokia.com' - company: 'Nokia' - id: 'joannajeremicz' - timezone: 'Europe/Warsaw' - name: 'Tomasz Wróbel' email: 'tomasz.wrobel@nokia.com' company: 'Nokia' @@ -59,8 +49,13 @@ committers: - name: 'Niranjana Y' email: 'niranjana.y60@wipro.com' company: 'Wipro' - id: 'niranjana.y60@wipro.com' + id: 'Niranjana' timezone: 'India/IST UTC+5:30' + - name: 'Shuting Qing' + email: 'qingshuting1@huawei.com' + company: 'Huawei' + id: 'mirandatsing' + timezone: 'China/Beijing UTC+8.00' tsc: approval: 'https://lists.onap.org/pipermail/onap-tsc' changes: @@ -118,3 +113,12 @@ tsc: - type: 'Addition' name: 'Niranjana Y' link: 'https://lists.onap.org/g/onap-tsc/message/8135' + - type: 'Removal' + name: 'Joanna Jeremicz' + link: 'https://lists.onap.org/g/onap-tsc/message/8524' + - type: 'Removal' + name: 'Remigiusz Janeczek' + link: 'https://lists.onap.org/g/onap-tsc/message/8871' + - type: 'Addition' + name: 'Shuting Qing' + link: 'https://lists.onap.org/g/onap-tsc/message/8974' diff --git a/components/bbs-event-processor/README.md b/components/bbs-event-processor/README.md index b4085f78..7aa5f9ac 100644 --- a/components/bbs-event-processor/README.md +++ b/components/bbs-event-processor/README.md @@ -1,3 +1,8 @@ +************************************************************ +This component has been deprecated with ONAP Jakarta release +See https://jira.onap.org/browse/DCAEGEN2-2974 for details. +************************************************************ + # BBS use case event processor --- @@ -74,4 +79,4 @@ Running with dev-mode of BBS-ep - **Execute just one polling for CPE authentication events** - POST http://<container_address>:8100/poll-cpe-authentication-events - **Change application logging level** - - POST http://<container_address>:8100/logging/{level}
\ No newline at end of file + - POST http://<container_address>:8100/logging/{level} diff --git a/components/datalake-handler/Changelog.md b/components/datalake-handler/Changelog.md new file mode 100644 index 00000000..247d41e1 --- /dev/null +++ b/components/datalake-handler/Changelog.md @@ -0,0 +1,22 @@ +# Change Log + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [1.1.2] +### Changed +* CodeCoverage improvement for dcaegen2-services-data-handler (DCAEGEN2-3161) + +## [1.1.1] 2022-09-14 +* DCAEGEN2-3004 - Fix DL-Admin Docker docker build issue + +## [1.0.0] 2019-08-01 +### Initial DL-Admin UI code +### Features +* add button component ([9e04f08](https://gerrit.onap.org/r/dcaegen2/services/commits/9e04f08)) +* add database to design module ([eba414f](https://gerrit.onap.org/r/dcaegen2/services/commits/eba414f)) +* change the structure of the project ([f761909](https://gerrit.onap.org/r/dcaegen2/services/commits/f761909)) +* new changes for design module ([c4c391b](https://gerrit.onap.org/r/dcaegen2/services/commits/c4c391b)) + diff --git a/components/datalake-handler/admin/Dockerfile b/components/datalake-handler/admin/Dockerfile index 6237741a..4c659598 100644 --- a/components/datalake-handler/admin/Dockerfile +++ b/components/datalake-handler/admin/Dockerfile @@ -1,9 +1,30 @@ +# ============LICENSE_START======================================================= +# Copyright (c) 2019 QCT. All rights reserved. +# Copyright (c) 2022 AT&T. 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. +# +# SPDX-License-Identifier: Apache-2.0 +# ============LICENSE_END========================================================= + FROM node:alpine AS builder MAINTAINER Ekko Chang <ekko.chang@qct.io> LABEL org.label-schema.docker.build="docker build -t dl-admin . --no-cache" \ org.label-schema.docker.run="docker run -p 80:80 --add-host=dl_feeder:your_feeder_ipaddress dl-admin" +ENV NODE_OPTIONS "--openssl-legacy-provider" + WORKDIR /app COPY ./src . COPY ./nginx . diff --git a/components/datalake-handler/admin/pom.xml b/components/datalake-handler/admin/pom.xml index 7cc30d78..305579d5 100644 --- a/components/datalake-handler/admin/pom.xml +++ b/components/datalake-handler/admin/pom.xml @@ -1,26 +1,42 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + Copyright (c) 2019 QCT. All rights reserved. + Copyright (c) 2022 AT&T. All rights reserved. + Copyright (C) 2022 Wipro Limited. 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"> - <modelVersion>4.0.0</modelVersion> + 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.components</groupId> - <artifactId>datalake-handler</artifactId> - <version>1.1.1-SNAPSHOT</version> - </parent> + <parent> + <groupId>org.onap.dcaegen2.services.components</groupId> + <artifactId>datalake-handler</artifactId> + <version>1.1.2-SNAPSHOT</version> + </parent> - <groupId>org.onap.dcaegen2.services.components.datalake-handler</groupId> - <artifactId>admin</artifactId> - <packaging>pom</packaging> - <properties> - <swagger.version>2.9.2</swagger.version> - <dockerfile-maven.version>1.4.5</dockerfile-maven.version> - <docker.image.path>onap/org.onap.dcaegen2.services.datalakeadminui</docker.image.path> - <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format> - </properties> - <name>DataLake Admin</name> - <build> + <groupId>org.onap.dcaegen2.services.components.datalake-handler</groupId> + <artifactId>admin</artifactId> + <packaging>pom</packaging> + <properties> + <swagger.version>2.9.2</swagger.version> + <dockerfile-maven.version>1.4.5</dockerfile-maven.version> + <docker.image.path>onap/org.onap.dcaegen2.services.datalakeadminui</docker.image.path> + <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format> + <onap-gerrit-review>-changelog-missing</onap-gerrit-review> + </properties> + <name>DataLake Admin</name> + <build> <plugins> <plugin> <groupId>com.spotify</groupId> @@ -30,58 +46,58 @@ <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> <tag>${project.version}</tag> <dockerfile>Dockerfile</dockerfile> - </configuration> - <executions> - <execution> - <id>build-datalake-admin-ui-image</id> - <phase>package</phase> - <goals> - <goal>build</goal> - </goals> - <configuration> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - <execution> - <id>tag-and-push-image-latest</id> - <phase>package</phase> - <goals> - <goal>tag</goal> - <goal>push</goal> - </goals> - <configuration> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <tag>latest</tag> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - <execution> - <id>tag-and-push-image-with-version</id> - <phase>package</phase> - <goals> - <goal>tag</goal> - <goal>push</goal> - </goals> - <configuration> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <tag>${project.version}</tag> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - <execution> - <id>tag-and-push-image-with-version-and-date</id> - <phase>package</phase> - <goals> - <goal>tag</goal> - <goal>push</goal> - </goals> - <configuration> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <tag>${project.version}-${maven.build.timestamp}Z</tag> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - </executions> + </configuration> + <executions> + <execution> + <id>build-datalake-admin-ui-image</id> + <phase>package</phase> + <goals> + <goal>build</goal> + </goals> + <configuration> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + <execution> + <id>tag-and-push-image-latest</id> + <phase>package</phase> + <goals> + <goal>tag</goal> + <goal>push</goal> + </goals> + <configuration> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <tag>latest</tag> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + <execution> + <id>tag-and-push-image-with-version</id> + <phase>package</phase> + <goals> + <goal>tag</goal> + <goal>push</goal> + </goals> + <configuration> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <tag>${project.version}</tag> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + <execution> + <id>tag-and-push-image-with-version-and-date</id> + <phase>package</phase> + <goals> + <goal>tag</goal> + <goal>push</goal> + </goals> + <configuration> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <tag>${project.version}-${maven.build.timestamp}Z</tag> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + </executions> <dependencies> <dependency> <groupId>javax.activation</groupId> diff --git a/components/datalake-handler/admin/src/CHANGELOG.md b/components/datalake-handler/admin/src/CHANGELOG.md deleted file mode 100644 index 0cf0870a..00000000 --- a/components/datalake-handler/admin/src/CHANGELOG.md +++ /dev/null @@ -1,11 +0,0 @@ -# [0.0.0](https://gerrit.onap.org/r/dcaegen2/services/compare/4.0.0-ONAP...0.0.0) (2019-08-01) - - -### Features - -* add button component ([9e04f08](https://gerrit.onap.org/r/dcaegen2/services/commits/9e04f08)) -* add database to design module ([eba414f](https://gerrit.onap.org/r/dcaegen2/services/commits/eba414f)) -* change the structure of the project ([f761909](https://gerrit.onap.org/r/dcaegen2/services/commits/f761909)) -* new changes for design module ([c4c391b](https://gerrit.onap.org/r/dcaegen2/services/commits/c4c391b)) - - diff --git a/components/datalake-handler/admin/src/package.json b/components/datalake-handler/admin/src/package.json index d4e0444c..30b9d88c 100644 --- a/components/datalake-handler/admin/src/package.json +++ b/components/datalake-handler/admin/src/package.json @@ -1,6 +1,6 @@ { "name": "DataLake-AdminUI", - "version": "0.0.0", + "version": "1.1.2", "scripts": { "ng": "ng", "start": "ng serve --host='0.0.0.0' --proxy-config proxy.conf.json", diff --git a/components/datalake-handler/collector/pom.xml b/components/datalake-handler/collector/pom.xml deleted file mode 100644 index a3eeff15..00000000 --- a/components/datalake-handler/collector/pom.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.onap.dcaegen2.services.components</groupId> - <artifactId>datalake-handler</artifactId> - <version>1.1.1-SNAPSHOT</version> - </parent> - - <groupId>org.onap.dcaegen2.services.components.datalake-handler</groupId> - <artifactId>collector</artifactId> - <packaging>pom</packaging> - <name>DataLake Collector</name> - - - -</project> diff --git a/components/datalake-handler/des/pom.xml b/components/datalake-handler/des/pom.xml index 87ae9443..64d382f1 100644 --- a/components/datalake-handler/des/pom.xml +++ b/components/datalake-handler/des/pom.xml @@ -2,7 +2,8 @@ <!-- ~ ============LICENSE_START======================================================= ~ Copyright (c) 2020 China Mobile. All rights reserved. - ~ ================================================================================ + ~ Copyright (C) 2022 Wipro Limited. 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 @@ -15,313 +16,275 @@ ~ 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"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.onap.dcaegen2.services.components</groupId> - <artifactId>datalake-handler</artifactId> - <version>1.1.1-SNAPSHOT</version> - </parent> - - <artifactId>des</artifactId> - <packaging>jar</packaging> - <name>DataLake Extraction Service</name> - - <properties> - <swagger.version>2.9.2</swagger.version> - <dockerfile-maven.version>1.4.10</dockerfile-maven.version> - <docker.image.path>onap/org.onap.dcaegen2.services.datalake.exposure.service</docker.image.path> - <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format> - </properties> - - <dependencies> - - <dependency> - <groupId>org.jdom</groupId> - <artifactId>jdom2</artifactId> - <version>2.0.6</version> - </dependency> - - <dependency> - <groupId>com.facebook.presto</groupId> - <artifactId>presto-jdbc</artifactId> - <version>0.240</version> - </dependency> - - <dependency> - <groupId>org.apache.hadoop</groupId> - <artifactId>hadoop-client</artifactId> - <version>${hadoop.version}</version> - </dependency> - - <dependency> - <groupId>org.postgresql</groupId> - <artifactId>postgresql</artifactId> - <version>42.2.18</version> - </dependency> - - <dependency> - <groupId>org.json</groupId> - <artifactId>json</artifactId> - <version>20190722</version> - </dependency> - - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient</artifactId> - <version>4.5.10</version> - </dependency> - - <dependency> - <groupId>org.apache.kafka</groupId> - <artifactId>kafka-clients</artifactId> - <version>2.3.1</version> - </dependency> - - <dependency> + 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.components</groupId> + <artifactId>datalake-handler</artifactId> + <version>1.1.2-SNAPSHOT</version> + </parent> + <artifactId>des</artifactId> + <packaging>jar</packaging> + <name>DataLake Extraction Service</name> + <properties> + <swagger.version>2.9.2</swagger.version> + <dockerfile-maven.version>1.4.10</dockerfile-maven.version> + <docker.image.path>onap/org.onap.dcaegen2.services.datalake.exposure.service</docker.image.path> + <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format> + <onap-gerrit-review>-changelog-missing</onap-gerrit-review> + </properties> + <dependencies> + <dependency> + <groupId>org.jdom</groupId> + <artifactId>jdom2</artifactId> + <version>2.0.6</version> + </dependency> + <dependency> + <groupId>com.facebook.presto</groupId> + <artifactId>presto-jdbc</artifactId> + <version>0.240</version> + </dependency> + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-client</artifactId> + <version>${hadoop.version}</version> + </dependency> + <dependency> + <groupId>org.postgresql</groupId> + <artifactId>postgresql</artifactId> + <version>42.2.18</version> + </dependency> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20190722</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.10</version> + </dependency> + <dependency> + <groupId>org.apache.kafka</groupId> + <artifactId>kafka-clients</artifactId> + <version>2.3.1</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <version>${springboot.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + <version>${springboot.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-jpa</artifactId> + <version>${springboot.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-couchbase</artifactId> + <version>${springboot.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <version>${springboot.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-configuration-processor</artifactId> + <version>${springboot.version}</version> + </dependency> + <dependency> + <groupId>org.elasticsearch.client</groupId> + <artifactId>elasticsearch-rest-high-level-client</artifactId> + <version>${elasticsearchjava.version}</version> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.6</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-yaml</artifactId> + <version>${jackson.version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-xml</artifactId> + <version>${jackson.version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>${jackson.version}</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.8.2</version> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.10</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>io.druid</groupId> + <artifactId>tranquility-core_2.11</artifactId> + <version>0.8.3</version> + </dependency> + <dependency> + <groupId>org.apache.velocity</groupId> + <artifactId>velocity-engine-core</artifactId> + <version>2.1</version> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-core</artifactId> + <version>5.3.7.Final</version> + </dependency> + <!-- jsr303 validation --> + <dependency> + <groupId>javax.validation</groupId> + <artifactId>validation-api</artifactId> + <version>2.0.1.Final</version> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-validator</artifactId> + <version>6.1.0.Final</version> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger2</artifactId> + <version>${swagger.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger-ui</artifactId> + <version>${swagger.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.mongodb</groupId> + <artifactId>mongo-java-driver</artifactId> + <version>${mongojava.version}</version> + </dependency> + <dependency> + <groupId>com.couchbase.mock</groupId> + <artifactId>CouchbaseMock</artifactId> + <version>1.5.22</version> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <version>2.8</version> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + <plugin> <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-web</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-actuator</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-jpa</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-couchbase</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-test</artifactId> - <version>${springboot.version}</version> - <scope>test</scope> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-configuration-processor</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.elasticsearch.client</groupId> - <artifactId>elasticsearch-rest-high-level-client</artifactId> - <version>${elasticsearchjava.version}</version> - </dependency> - - <dependency> - <groupId>commons-io</groupId> - <artifactId>commons-io</artifactId> - <version>2.6</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.dataformat</groupId> - <artifactId>jackson-dataformat-yaml</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.dataformat</groupId> - <artifactId>jackson-dataformat-xml</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-databind</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.google.code.gson</groupId> - <artifactId>gson</artifactId> - <version>2.8.2</version> - </dependency> - - <dependency> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>1.18.10</version> - <scope>provided</scope> - </dependency> - - <dependency> - <groupId>io.druid</groupId> - <artifactId>tranquility-core_2.11</artifactId> - <version>0.8.3</version> - </dependency> - - <dependency> - <groupId>org.apache.velocity</groupId> - <artifactId>velocity-engine-core</artifactId> - <version>2.1</version> - </dependency> - - - <dependency> - <groupId>org.hibernate</groupId> - <artifactId>hibernate-core</artifactId> - <version>5.3.7.Final</version> - </dependency> - - <!-- jsr303 validation --> - <dependency> - <groupId>javax.validation</groupId> - <artifactId>validation-api</artifactId> - <version>2.0.1.Final</version> - </dependency> - - <dependency> - <groupId>org.hibernate</groupId> - <artifactId>hibernate-validator</artifactId> - <version>6.1.0.Final</version> - </dependency> - - <dependency> - <groupId>io.springfox</groupId> - <artifactId>springfox-swagger2</artifactId> - <version>${swagger.version}</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>io.springfox</groupId> - <artifactId>springfox-swagger-ui</artifactId> - <version>${swagger.version}</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>org.mongodb</groupId> - <artifactId>mongo-java-driver</artifactId> - <version>${mongojava.version}</version> - </dependency> - - <dependency> - <groupId>com.couchbase.mock</groupId> - <artifactId>CouchbaseMock</artifactId> - <version>1.5.22</version> - <scope>test</scope> - </dependency> - - </dependencies> - - - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-deploy-plugin</artifactId> - <version>2.8</version> - <configuration> - <skip>true</skip> - </configuration> - </plugin> - - <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> - <configuration> - <classifier>execute</classifier> - <executions> - <execution> - <goals> - <goal>repackage</goal> - </goals> - </execution> - </executions> - </configuration> - </plugin> - <plugin> - <groupId>com.spotify</groupId> - <artifactId>dockerfile-maven-plugin</artifactId> - <version>${dockerfile-maven.version}</version> - <configuration> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <tag>${project.version}</tag> - <dockerfile>Dockerfile</dockerfile> - <buildArgs> - <JAR_FILE>${project.build.finalName}.jar</JAR_FILE> - </buildArgs> - </configuration> - <executions> - <execution> - <id>build-sl-des-image</id> - <phase>package</phase> - <goals> - <goal>build</goal> - </goals> - <configuration> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - <execution> - <id>tag-and-push-image-latest</id> - <phase>package</phase> - <goals> - <goal>tag</goal> - <goal>push</goal> - </goals> - <configuration> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <tag>latest</tag> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - <execution> - <id>tag-and-push-image-with-version</id> - <phase>package</phase> - <goals> - <goal>tag</goal> - <goal>push</goal> - </goals> - <configuration> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <tag>${project.version}</tag> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - <execution> - <id>tag-and-push-image-with-version-and-date</id> - <phase>package</phase> - <goals> - <goal>tag</goal> - <goal>push</goal> - </goals> - <configuration> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <tag>${project.version}-${maven.build.timestamp}Z</tag> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - </executions> - <dependencies> - <!-- To make this work on JDK 9+ --> - <dependency> - <groupId>javax.activation</groupId> - <artifactId>javax.activation-api</artifactId> - <version>1.2.0</version> - </dependency> - </dependencies> - </plugin> - </plugins> - </build> + <artifactId>spring-boot-maven-plugin</artifactId> + <configuration> + <classifier>execute</classifier> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + </execution> + </executions> + </configuration> + </plugin> + <plugin> + <groupId>com.spotify</groupId> + <artifactId>dockerfile-maven-plugin</artifactId> + <version>${dockerfile-maven.version}</version> + <configuration> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <tag>${project.version}</tag> + <dockerfile>Dockerfile</dockerfile> + <buildArgs> + <JAR_FILE>${project.build.finalName}.jar</JAR_FILE> + </buildArgs> + </configuration> + <executions> + <execution> + <id>build-sl-des-image</id> + <phase>package</phase> + <goals> + <goal>build</goal> + </goals> + <configuration> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + <execution> + <id>tag-and-push-image-latest</id> + <phase>package</phase> + <goals> + <goal>tag</goal> + <goal>push</goal> + </goals> + <configuration> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <tag>latest</tag> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + <execution> + <id>tag-and-push-image-with-version</id> + <phase>package</phase> + <goals> + <goal>tag</goal> + <goal>push</goal> + </goals> + <configuration> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <tag>${project.version}</tag> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + <execution> + <id>tag-and-push-image-with-version-and-date</id> + <phase>package</phase> + <goals> + <goal>tag</goal> + <goal>push</goal> + </goals> + <configuration> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <tag>${project.version}-${maven.build.timestamp}Z</tag> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + </executions> + <dependencies> + <!-- To make this work on JDK 9+ --> + <dependency> + <groupId>javax.activation</groupId> + <artifactId>javax.activation-api</artifactId> + <version>1.2.0</version> + </dependency> + </dependencies> + </plugin> + </plugins> + </build> </project> diff --git a/components/datalake-handler/des/src/test/java/org/onap/datalake/des/controller/DataExposureControllerTest.java b/components/datalake-handler/des/src/test/java/org/onap/datalake/des/controller/DataExposureControllerTest.java index 4cadc31d..c4abac98 100644 --- a/components/datalake-handler/des/src/test/java/org/onap/datalake/des/controller/DataExposureControllerTest.java +++ b/components/datalake-handler/des/src/test/java/org/onap/datalake/des/controller/DataExposureControllerTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE DES * ================================================================================ * Copyright (C) 2020 China Mobile. All rights reserved. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,20 +22,28 @@ package org.onap.datalake.des.controller; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; import java.io.IOException; import java.sql.SQLException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; - import javax.servlet.http.HttpServletResponse; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import org.onap.datalake.des.domain.DataExposure; +import org.onap.datalake.des.domain.Db; +import org.onap.datalake.des.domain.DbType; +import org.onap.datalake.des.dto.DataExposureConfig; import org.onap.datalake.des.repository.DataExposureRepository; +import org.onap.datalake.des.service.DataExposureService; import org.springframework.validation.BindingResult; /** @@ -54,16 +63,157 @@ public class DataExposureControllerTest { @Mock private BindingResult mockBindingResult; + @Mock + private DataExposureService dataExposureService; + + @InjectMocks + private DataExposureController dataExposureController; + + /** + * Generate data exposure config. + * + * @return DataExposureConfig object + * + */ + public DataExposureConfig getDataExposureConfig() { + DataExposureConfig dataExposureConfig = new DataExposureConfig(); + dataExposureConfig.setDbId(1); + dataExposureConfig.setId("1"); + dataExposureConfig.setNote("note"); + dataExposureConfig.setSqlTemplate("sqlTemplate"); + return dataExposureConfig; + } + + /** + * Generate data exposure. + * + * @return DataExposure object + * + */ + public DataExposure getDataExposure() { + DbType dbType = new DbType("ES", "Elasticsearch"); + Db db = new Db(); + db.setId(1); + db.setDbType(dbType); + db.setDatabase("Elasticsearch"); + + DataExposure dataExposure = new DataExposure(); + dataExposure.setId("1"); + dataExposure.setNote("note"); + dataExposure.setSqlTemplate("sqlTemplate"); + dataExposure.setDb(db); + return dataExposure; + } + @Test(expected = NullPointerException.class) - public void testServe() - throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, SQLException { + public void testServeNull() + throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, SQLException { DataExposureController dataExposureController = new DataExposureController(); String serviceId = "test"; - Map<String, String> requestMap = new HashMap<String, String>(); + Map < String, String > requestMap = new HashMap < String, String > (); requestMap.put("name", "oteNB5309"); - HashMap<String, Object> result = dataExposureController.serve(serviceId, requestMap, mockBindingResult, - httpServletResponse); + HashMap < String, Object > result = dataExposureController.serve(serviceId, requestMap, mockBindingResult, + httpServletResponse); assertEquals(null, result); when(mockBindingResult.hasErrors()).thenReturn(true); } + + @Test(expected = SQLException.class) + public void testServeException() + throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException, SQLException { + String serviceId = "test"; + Map < String, String > requestMap = new HashMap < String, String > (); + requestMap.put("name", "oteNB5309"); + + DataExposure dataExposure = getDataExposure(); + when(dataExposureService.getDataExposure(serviceId)).thenReturn(dataExposure); + dataExposureController.serve(serviceId, requestMap, mockBindingResult, + httpServletResponse); + } + + @Test + public void testQueryAllDataExposure() { + DataExposureConfig dataExposureConfig = getDataExposureConfig(); + List < DataExposureConfig > dataExposureList = new ArrayList < > (); + dataExposureList.add(dataExposureConfig); + when(dataExposureService.queryAllDataExposure()).thenReturn(dataExposureList); + assertEquals(dataExposureList, dataExposureController.queryAllDataExposure()); + } + + @Test + public void TestQueryAllDataExposureByIdNull() throws IOException { + when(dataExposureService.getDataExposureById("1")).thenReturn(null); + assertEquals(null, dataExposureController.queryAllDataExposure("1", httpServletResponse)); + } + + @Test + public void TestQueryAllDataExposureById() throws IOException { + DataExposure dataExposure = getDataExposure(); + when(dataExposureService.getDataExposureById("1")).thenReturn(dataExposure); + dataExposureController.queryAllDataExposure("1", httpServletResponse); + } + + @Test + public void testCreateDataExposureNull() throws IOException { + DataExposure dataExposure = getDataExposure(); + DataExposureConfig dataExposureConfig = getDataExposureConfig(); + when(dataExposureService.getDataExposureById("1")).thenReturn(dataExposure); + assertEquals(null, dataExposureController.createDataExposure(dataExposureConfig, mockBindingResult, httpServletResponse)); + } + + @Test + public void testCreateDataExposure() throws IOException { + DataExposure dataExposure = getDataExposure(); + DataExposureConfig dataExposureConfig = getDataExposureConfig(); + when(dataExposureService.getDataExposureById("1")).thenReturn(null); + when(dataExposureService.fillDataExposureConfiguration(dataExposureConfig)).thenReturn(dataExposure); + dataExposureController.createDataExposure(dataExposureConfig, mockBindingResult, httpServletResponse); + } + + @Test + public void testCreateDataExposureException() throws IOException { + DataExposureConfig dataExposureConfig = getDataExposureConfig(); + when(dataExposureService.getDataExposureById("1")).thenReturn(null); + when(dataExposureService.fillDataExposureConfiguration(dataExposureConfig)).thenThrow(NullPointerException.class); + assertEquals(null, dataExposureController.createDataExposure(dataExposureConfig, mockBindingResult, httpServletResponse)); + } + + @Test + public void testCreateDataExposureError() throws IOException { + DataExposureConfig dataExposureConfig = getDataExposureConfig(); + when(mockBindingResult.hasErrors()).thenReturn(true); + assertEquals(null, dataExposureController.createDataExposure(dataExposureConfig, mockBindingResult, httpServletResponse)); + } + + @Test + public void testUpdateDataExposureNull() throws IOException { + DataExposureConfig dataExposureConfig = getDataExposureConfig(); + when(dataExposureService.getDataExposureById("1")).thenReturn(null); + assertEquals(null, dataExposureController.updateDataExposure(dataExposureConfig, mockBindingResult, "1", httpServletResponse)); + } + + @Test + public void testUpdateDataExposure() throws IOException { + DataExposure dataExposure = getDataExposure(); + DataExposureConfig dataExposureConfig = getDataExposureConfig(); + when(dataExposureService.getDataExposureById("1")).thenReturn(dataExposure); + dataExposureController.updateDataExposure(dataExposureConfig, mockBindingResult, "1", httpServletResponse); + } + + @Test + public void testUpdateDataExposureException() throws IOException { + DataExposure dataExposure = getDataExposure(); + DataExposureConfig dataExposureConfig = getDataExposureConfig(); + when(dataExposureService.getDataExposureById("1")).thenReturn(dataExposure); + doThrow(NullPointerException.class).when(dataExposureService).fillDataExposureConfiguration(dataExposureConfig, dataExposure); + assertEquals(null, dataExposureController.updateDataExposure(dataExposureConfig, mockBindingResult, "1", httpServletResponse)); + } + + @Test + public void testUpdateDataExposureError() throws IOException { + DataExposureConfig dataExposureConfig = getDataExposureConfig(); + when(mockBindingResult.hasErrors()).thenReturn(true); + assertEquals(null, dataExposureController.updateDataExposure(dataExposureConfig, mockBindingResult, "1", httpServletResponse)); + } + } diff --git a/components/datalake-handler/des/src/test/java/org/onap/datalake/des/domain/DbTest.java b/components/datalake-handler/des/src/test/java/org/onap/datalake/des/domain/DbTest.java index cd5c6b4d..e6dba7f0 100644 --- a/components/datalake-handler/des/src/test/java/org/onap/datalake/des/domain/DbTest.java +++ b/components/datalake-handler/des/src/test/java/org/onap/datalake/des/domain/DbTest.java @@ -3,6 +3,7 @@ * ONAP : DataLake DES * ================================================================================ * Copyright 2020 China Mobile. All rights reserved. + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +24,7 @@ package org.onap.datalake.des.domain; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import org.junit.Test; @@ -74,5 +76,7 @@ public class DbTest { assertTrue("property2".equals(mongoDb2.getProperty2())); assertTrue("property3".equals(mongoDb2.getProperty3())); assertEquals(mongoDb2.getDbConfig().getHost(), mongoDb2.getHost()); + assertNotNull(mongoDb1.toString()); } + } diff --git a/components/datalake-handler/des/src/test/java/org/onap/datalake/des/domain/DbTypeTest.java b/components/datalake-handler/des/src/test/java/org/onap/datalake/des/domain/DbTypeTest.java index 4b83a03b..9f727c5c 100644 --- a/components/datalake-handler/des/src/test/java/org/onap/datalake/des/domain/DbTypeTest.java +++ b/components/datalake-handler/des/src/test/java/org/onap/datalake/des/domain/DbTypeTest.java @@ -3,6 +3,7 @@ * ONAP : DataLake DES * ================================================================================ * Copyright 2020 China Mobile. All rights reserved. + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,16 +38,18 @@ public class DbTypeTest { @Test public void test() { - DbType dbType = new DbType("ES","Elasticsearch"); + DbType dbType = new DbType("ES", "Elasticsearch"); - dbType.setTool(false); + dbType.setTool(false); assertNotNull(dbType.toString()); assertEquals(dbType, dbType); assertNotEquals(dbType, null); assertNotEquals(dbType, "ES"); - DbType dbType2 = new DbType("MONGO", "MongoDB"); + DbType dbType2 = new DbType(); + dbType2.setId("MONGO"); + dbType2.setName("MongoDB"); assertNotEquals(dbType, dbType2); assertNotNull(dbType.hashCode()); @@ -59,4 +62,4 @@ public class DbTypeTest { assertNull(dbType2.getDbs()); } -}
\ No newline at end of file +} diff --git a/components/datalake-handler/des/src/test/java/org/onap/datalake/des/dto/DbConfigTest.java b/components/datalake-handler/des/src/test/java/org/onap/datalake/des/dto/DbConfigTest.java index ee21f475..09f868f8 100644 --- a/components/datalake-handler/des/src/test/java/org/onap/datalake/des/dto/DbConfigTest.java +++ b/components/datalake-handler/des/src/test/java/org/onap/datalake/des/dto/DbConfigTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE DES * ================================================================================ * Copyright (C) 2020 China Mobile. All rights reserved. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,5 +54,7 @@ public class DbConfigTest { assertFalse("123".equals(dbConfig.getPort())); dbConfig.setPoperties("driver"); assertTrue("driver".equals(dbConfig.getPoperties())); + dbConfig.setDbTypeId("123"); + assertTrue("123".equals(dbConfig.getDbTypeId())); } } diff --git a/components/datalake-handler/des/src/test/java/org/onap/datalake/des/service/DataExposureServiceTest.java b/components/datalake-handler/des/src/test/java/org/onap/datalake/des/service/DataExposureServiceTest.java index 254afcb5..9671a94b 100644 --- a/components/datalake-handler/des/src/test/java/org/onap/datalake/des/service/DataExposureServiceTest.java +++ b/components/datalake-handler/des/src/test/java/org/onap/datalake/des/service/DataExposureServiceTest.java @@ -3,6 +3,7 @@ * ONAP : DataLake DES * ================================================================================ * Copyright 2020 China Mobile. All rights reserved. + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,11 +23,9 @@ package org.onap.datalake.des.service; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; - import java.util.ArrayList; import java.util.List; import java.util.Optional; - import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; @@ -40,7 +39,6 @@ import org.onap.datalake.des.dto.DbConfig; import org.onap.datalake.des.repository.DataExposureRepository; import org.onap.datalake.des.repository.DbRepository; import org.springframework.context.ApplicationContext; - /** * Test DB exposure Service. * @@ -100,6 +98,34 @@ public class DataExposureServiceTest { } @Test + public void testGetDataExposure() { + Db newdb = new Db(); + DbConfig dbConfig = getDbConfig(); + newdb.setName(dbConfig.getName()); + newdb.setHost(dbConfig.getHost()); + newdb.setPort(dbConfig.getPort()); + newdb.setEnabled(dbConfig.isEnabled()); + newdb.setLogin(dbConfig.getLogin()); + newdb.setPass(dbConfig.getPass()); + newdb.setEncrypt(dbConfig.isEncrypt()); + + DataExposure de = new DataExposure(); + de.setId("1"); + de.setNote("note"); + de.setSqlTemplate("sqlTemplate"); + de.setDb(newdb); + when(dataExposureRepository.findById("1")).thenReturn(Optional.of(de)); + assertEquals(de, dataExposureService.getDataExposure("1")); + } + + @Test + public void testGetDataExposureNull() { + Optional < DataExposure > de = Optional.ofNullable(null); + when(dataExposureRepository.findById(null)).thenReturn(de); + assertEquals(dataExposureService.getDataExposure(null), null); + } + + @Test public void testQueryAllDataExposure() { Db newdb = new Db(); DbConfig dbConfig = getDbConfig(); @@ -110,20 +136,56 @@ public class DataExposureServiceTest { newdb.setLogin(dbConfig.getLogin()); newdb.setPass(dbConfig.getPass()); newdb.setEncrypt(dbConfig.isEncrypt()); + DataExposureConfig deConfig = getDataExposureConfig(); DataExposure de = new DataExposure(); de.setDb(newdb); de.setId(deConfig.getId()); de.setNote(deConfig.getNote()); de.setSqlTemplate(deConfig.getSqlTemplate()); - List<DataExposure> deList = new ArrayList<>(); + List < DataExposure > deList = new ArrayList < > (); deList.add(de); when(dataExposureRepository.findAll()).thenReturn(deList); - List<DataExposureConfig> deConfigList = dataExposureService.queryAllDataExposure(); + List < DataExposureConfig > deConfigList = dataExposureService.queryAllDataExposure(); assertEquals(de.getId(), deConfigList.get(0).getId()); } @Test + public void testQueryAllDataExposureNull() { + List < DataExposure > deList = new ArrayList < > (); + when(dataExposureRepository.findAll()).thenReturn(deList); + assertEquals(dataExposureService.queryAllDataExposure(), deList); + } + + @Test + public void testGetDataExposureById() { + Db newdb = new Db(); + DbConfig dbConfig = getDbConfig(); + newdb.setName(dbConfig.getName()); + newdb.setHost(dbConfig.getHost()); + newdb.setPort(dbConfig.getPort()); + newdb.setEnabled(dbConfig.isEnabled()); + newdb.setLogin(dbConfig.getLogin()); + newdb.setPass(dbConfig.getPass()); + newdb.setEncrypt(dbConfig.isEncrypt()); + + DataExposure de = new DataExposure(); + de.setId("1"); + de.setNote("note"); + de.setSqlTemplate("sqlTemplate"); + de.setDb(newdb); + when(dataExposureRepository.findById("1")).thenReturn(Optional.of(de)); + assertEquals(de, dataExposureService.getDataExposureById("1")); + } + + @Test + public void testGetDataExposureByIdNull() { + Optional < DataExposure > de = Optional.ofNullable(null); + when(dataExposureRepository.findById(null)).thenReturn(de); + assertEquals(dataExposureService.getDataExposureById(null), null); + } + + @Test public void testFillDataExposureConfiguration() { Db newdb = new Db(); DbConfig dbConfig = getDbConfig(); @@ -153,6 +215,7 @@ public class DataExposureServiceTest { newdb.setEncrypt(dbConfig.isEncrypt()); DataExposureConfig deConfig = getDataExposureConfig(); when(dbRepository.findById(deConfig.getDbId())).thenReturn(Optional.of(newdb)); + DataExposure de = new DataExposure(); de.setDb(newdb); de.setId(deConfig.getId()); @@ -161,4 +224,20 @@ public class DataExposureServiceTest { dataExposureService.fillDataExposureConfiguration(deConfig, de); } + @Test(expected = IllegalArgumentException.class) + public void testFillDataExposureException() { + DataExposureConfig deConfig = getDataExposureConfig(); + deConfig.setDbId(null); + dataExposureService.fillDataExposureConfiguration(deConfig); + } + + @Test(expected = IllegalArgumentException.class) + public void testFillDataExposureIllegalArgumentException() { + DataExposureConfig deConfig = getDataExposureConfig(); + deConfig.setDbId(1); + Optional < Db > dbOptional = Optional.ofNullable(null); + when(dbRepository.findById(deConfig.getDbId())).thenReturn(dbOptional); + dataExposureService.fillDataExposureConfiguration(deConfig); + } + } diff --git a/components/datalake-handler/feeder/pom.xml b/components/datalake-handler/feeder/pom.xml index 49ad6094..312e8dcc 100644 --- a/components/datalake-handler/feeder/pom.xml +++ b/components/datalake-handler/feeder/pom.xml @@ -1,299 +1,319 @@ <?xml version="1.0" encoding="UTF-8"?> -<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"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.onap.dcaegen2.services.components</groupId> - <artifactId>datalake-handler</artifactId> - <version>1.1.1-SNAPSHOT</version> - </parent> - - <groupId>org.onap.dcaegen2.services.components.datalake-handler</groupId> - <artifactId>feeder</artifactId> - <packaging>jar</packaging> - <name>DataLake Feeder</name> - - <properties> - <swagger.version>2.9.2</swagger.version> - <dockerfile-maven.version>1.4.5</dockerfile-maven.version> - <docker.image.path>onap/org.onap.dcaegen2.services.datalakefeeder</docker.image.path> - <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format> - - </properties> - - <dependencies> - - <dependency> - <groupId>org.jdom</groupId> - <artifactId>jdom2</artifactId> - <version>2.0.6</version> - </dependency> - - <dependency> - <groupId>com.facebook.presto</groupId> - <artifactId>presto-jdbc</artifactId> - <version>0.229</version> - </dependency> - - <dependency> - <groupId>org.apache.hadoop</groupId> - <artifactId>hadoop-client</artifactId> - <version>${hadoop.version}</version> - </dependency> - - <dependency> - <groupId>org.postgresql</groupId> - <artifactId>postgresql</artifactId> - <version>42.2.18</version> +<!-- + ~ ============LICENSE_START======================================================= + ~ Copyright (C) 2018-2019 Huawei. All rights reserved. + ~ Copyright 2018 TechMahindra. All rights reserved. + ~ Copyright (C) 2019 QCT. All rights reserved. + ~ Copyright (c) 2019-2020 China Mobile. All rights reserved. + ~ Copyright (C) 2021-2022 Wipro Limited. 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"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.onap.dcaegen2.services.components</groupId> + <artifactId>datalake-handler</artifactId> + <version>1.1.2-SNAPSHOT</version> + </parent> + + <groupId>org.onap.dcaegen2.services.components.datalake-handler</groupId> + <artifactId>feeder</artifactId> + <packaging>jar</packaging> + <name>DataLake Feeder</name> + + <properties> + <swagger.version>2.9.2</swagger.version> + <dockerfile-maven.version>1.4.5</dockerfile-maven.version> + <docker.image.path>onap/org.onap.dcaegen2.services.datalakefeeder</docker.image.path> + <maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format> + <onap-gerrit-review>-changelog-missing</onap-gerrit-review> + </properties> + + <dependencies> + + <dependency> + <groupId>org.jdom</groupId> + <artifactId>jdom2</artifactId> + <version>2.0.6</version> + </dependency> + + <dependency> + <groupId>com.facebook.presto</groupId> + <artifactId>presto-jdbc</artifactId> + <version>0.229</version> + </dependency> + + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-client</artifactId> + <version>${hadoop.version}</version> + </dependency> + + <dependency> + <groupId>org.postgresql</groupId> + <artifactId>postgresql</artifactId> + <version>42.2.18</version> + </dependency> + + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20190722</version> + </dependency> + + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.10</version> + </dependency> + + <dependency> + <groupId>org.apache.kafka</groupId> + <artifactId>kafka-clients</artifactId> + <version>2.3.1</version> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <version>${springboot.version}</version> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + <version>${springboot.version}</version> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-jpa</artifactId> + <version>${springboot.version}</version> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-couchbase</artifactId> + <version>${springboot.version}</version> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <version>${springboot.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-configuration-processor</artifactId> + <version>${springboot.version}</version> + </dependency> + + <dependency> + <groupId>org.elasticsearch.client</groupId> + <artifactId>elasticsearch-rest-high-level-client</artifactId> + <version>${elasticsearchjava.version}</version> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.6</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-yaml</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-xml</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.8.2</version> + </dependency> + + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.10</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>io.druid</groupId> + <artifactId>tranquility-core_2.11</artifactId> + <version>0.8.3</version> + </dependency> + + <dependency> + <groupId>org.apache.velocity</groupId> + <artifactId>velocity-engine-core</artifactId> + <version>2.1</version> + </dependency> + + + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-core</artifactId> + <version>5.3.7.Final</version> + </dependency> + + <!-- jsr303 validation --> + <dependency> + <groupId>javax.validation</groupId> + <artifactId>validation-api</artifactId> + <version>2.0.1.Final</version> + </dependency> + + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-validator</artifactId> + <version>6.1.0.Final</version> + </dependency> + + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger2</artifactId> + <version>${swagger.version}</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger-ui</artifactId> + <version>${swagger.version}</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.mongodb</groupId> + <artifactId>mongo-java-driver</artifactId> + <version>${mongojava.version}</version> + </dependency> + <dependency> + <groupId>com.couchbase.mock</groupId> + <artifactId>CouchbaseMock</artifactId> + <version>1.5.22</version> + <scope>test</scope> + </dependency> + </dependencies> + + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <configuration> + <classifier>exec</classifier> + </configuration> + </plugin> + <plugin> + <groupId>com.spotify</groupId> + <artifactId>dockerfile-maven-plugin</artifactId> + <version>${dockerfile-maven.version}</version> + <configuration> + <!-- <username>docker</username> <password>docker</password> --> + <!-- repository>repo.treescale.com/moguobiao/datalake-feeder-maven</repository --> + <!-- repository>moguobiao/datalake-feeder-maven-spotify</repository --> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <!-- <repository>mizunoami123/dl-feeder</repository> --> + <tag>${project.version}</tag> + <dockerfile>Dockerfile</dockerfile> + <!-- useMavenSettingsForAuth>true</useMavenSettingsForAuth --> + <buildArgs> + <JAR_FILE>${project.build.finalName}.jar</JAR_FILE> + </buildArgs> + </configuration> + <executions> + <execution> + <id>build-sl-feeder-image</id> + <phase>package</phase> + <goals> + <goal>build</goal> + </goals> + <configuration> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + <execution> + <id>tag-and-push-image-latest</id> + <phase>package</phase> + <goals> + <goal>tag</goal> + <goal>push</goal> + </goals> + <configuration> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <tag>latest</tag> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + <execution> + <id>tag-and-push-image-with-version</id> + <phase>package</phase> + <goals> + <goal>tag</goal> + <goal>push</goal> + </goals> + <configuration> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <tag>${project.version}</tag> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + <execution> + <id>tag-and-push-image-with-version-and-date</id> + <phase>package</phase> + <goals> + <goal>tag</goal> + <goal>push</goal> + </goals> + <configuration> + <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> + <tag>${project.version}-${maven.build.timestamp}Z</tag> + <useMavenSettingsForAuth>true</useMavenSettingsForAuth> + </configuration> + </execution> + </executions> + <dependencies> + <!-- To make this work on JDK 9+ --> + <dependency> + <groupId>javax.activation</groupId> + <artifactId>javax.activation-api</artifactId> + <version>1.2.0</version> </dependency> - - <dependency> - <groupId>org.json</groupId> - <artifactId>json</artifactId> - <version>20190722</version> - </dependency> - - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient</artifactId> - <version>4.5.10</version> - </dependency> - - <dependency> - <groupId>org.apache.kafka</groupId> - <artifactId>kafka-clients</artifactId> - <version>2.3.1</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-web</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-actuator</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-jpa</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-couchbase</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-test</artifactId> - <version>${springboot.version}</version> - <scope>test</scope> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-configuration-processor</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.elasticsearch.client</groupId> - <artifactId>elasticsearch-rest-high-level-client</artifactId> - <version>${elasticsearchjava.version}</version> - </dependency> - - <dependency> - <groupId>commons-io</groupId> - <artifactId>commons-io</artifactId> - <version>2.6</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.dataformat</groupId> - <artifactId>jackson-dataformat-yaml</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.dataformat</groupId> - <artifactId>jackson-dataformat-xml</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-databind</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.google.code.gson</groupId> - <artifactId>gson</artifactId> - <version>2.8.2</version> - </dependency> - - <dependency> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>1.18.10</version> - <scope>provided</scope> - </dependency> - - <dependency> - <groupId>io.druid</groupId> - <artifactId>tranquility-core_2.11</artifactId> - <version>0.8.3</version> - </dependency> - - <dependency> - <groupId>org.apache.velocity</groupId> - <artifactId>velocity-engine-core</artifactId> - <version>2.1</version> - </dependency> - - - <dependency> - <groupId>org.hibernate</groupId> - <artifactId>hibernate-core</artifactId> - <version>5.3.7.Final</version> - </dependency> - - <!-- jsr303 validation --> - <dependency> - <groupId>javax.validation</groupId> - <artifactId>validation-api</artifactId> - <version>2.0.1.Final</version> - </dependency> - - <dependency> - <groupId>org.hibernate</groupId> - <artifactId>hibernate-validator</artifactId> - <version>6.1.0.Final</version> - </dependency> - - <dependency> - <groupId>io.springfox</groupId> - <artifactId>springfox-swagger2</artifactId> - <version>${swagger.version}</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>io.springfox</groupId> - <artifactId>springfox-swagger-ui</artifactId> - <version>${swagger.version}</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>org.mongodb</groupId> - <artifactId>mongo-java-driver</artifactId> - <version>${mongojava.version}</version> - </dependency> - <dependency> - <groupId>com.couchbase.mock</groupId> - <artifactId>CouchbaseMock</artifactId> - <version>1.5.22</version> - <scope>test</scope> - </dependency> - </dependencies> - - - <build> - <plugins> - <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> - <configuration> - <classifier>exec</classifier> - </configuration> - </plugin> - <plugin> - <groupId>com.spotify</groupId> - <artifactId>dockerfile-maven-plugin</artifactId> - <version>${dockerfile-maven.version}</version> - <configuration> - <!-- - <username>docker</username> - <password>docker</password> --> - <!-- repository>repo.treescale.com/moguobiao/datalake-feeder-maven</repository --> - <!-- repository>moguobiao/datalake-feeder-maven-spotify</repository --> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <!-- <repository>mizunoami123/dl-feeder</repository> --> - <tag>${project.version}</tag> - <dockerfile>Dockerfile</dockerfile> - <!-- useMavenSettingsForAuth>true</useMavenSettingsForAuth --> - <buildArgs> - <JAR_FILE>${project.build.finalName}.jar</JAR_FILE> - </buildArgs> - </configuration> - <executions> - <execution> - <id>build-sl-feeder-image</id> - <phase>package</phase> - <goals> - <goal>build</goal> - </goals> - <configuration> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - <execution> - <id>tag-and-push-image-latest</id> - <phase>package</phase> - <goals> - <goal>tag</goal> - <goal>push</goal> - </goals> - <configuration> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <tag>latest</tag> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - <execution> - <id>tag-and-push-image-with-version</id> - <phase>package</phase> - <goals> - <goal>tag</goal> - <goal>push</goal> - </goals> - <configuration> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <tag>${project.version}</tag> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - <execution> - <id>tag-and-push-image-with-version-and-date</id> - <phase>package</phase> - <goals> - <goal>tag</goal> - <goal>push</goal> - </goals> - <configuration> - <repository>${onap.nexus.dockerregistry.daily}/${docker.image.path}</repository> - <tag>${project.version}-${maven.build.timestamp}Z</tag> - <useMavenSettingsForAuth>true</useMavenSettingsForAuth> - </configuration> - </execution> - </executions> - <dependencies> - <!-- To make this work on JDK 9+ --> - <dependency> - <groupId>javax.activation</groupId> - <artifactId>javax.activation-api</artifactId> - <version>1.2.0</version> - </dependency> - </dependencies> - </plugin> - </plugins> - </build> + </dependencies> + </plugin> + </plugins> + </build> </project> diff --git a/components/datalake-handler/feeder/src/main/java/org/onap/datalake/feeder/service/KafkaService.java b/components/datalake-handler/feeder/src/main/java/org/onap/datalake/feeder/service/KafkaService.java index 2e959fa2..0e617f5e 100644 --- a/components/datalake-handler/feeder/src/main/java/org/onap/datalake/feeder/service/KafkaService.java +++ b/components/datalake-handler/feeder/src/main/java/org/onap/datalake/feeder/service/KafkaService.java @@ -3,6 +3,7 @@ * ONAP : DataLake * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,14 +21,15 @@ package org.onap.datalake.feeder.service; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; import org.onap.datalake.feeder.domain.Kafka; import org.onap.datalake.feeder.dto.KafkaConfig; import org.onap.datalake.feeder.repository.KafkaRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.*; - /** * Service for kafkas * @@ -41,15 +43,15 @@ public class KafkaService { public Kafka getKafkaById(int id) { - Optional<Kafka> ret = kafkaRepository.findById(id); + Optional < Kafka > ret = kafkaRepository.findById(id); return ret.isPresent() ? ret.get() : null; } - public List<KafkaConfig> getAllKafka() { + public List < KafkaConfig > getAllKafka() { - List<KafkaConfig> kafkaConfigList = new ArrayList<>(); - Iterable<Kafka> kafkaIterable = kafkaRepository.findAll(); - for(Kafka portal : kafkaIterable) { + List < KafkaConfig > kafkaConfigList = new ArrayList < > (); + Iterable < Kafka > kafkaIterable = kafkaRepository.findAll(); + for (Kafka portal: kafkaIterable) { kafkaConfigList.add(portal.getKafkaConfig()); } return kafkaConfigList; diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DbControllerTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DbControllerTest.java index 9318ee00..889821a6 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DbControllerTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DbControllerTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright (C) 2018-2019 Huawei. All rights reserved. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,9 +30,13 @@ import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; import org.onap.datalake.feeder.controller.domain.PostReturnBody; import org.onap.datalake.feeder.domain.Db; +import org.onap.datalake.feeder.domain.DbType; +import org.onap.datalake.feeder.domain.DesignType; import org.onap.datalake.feeder.domain.Topic; import org.onap.datalake.feeder.dto.DbConfig; import org.onap.datalake.feeder.repository.DbRepository; +import org.onap.datalake.feeder.repository.DbTypeRepository; +import org.onap.datalake.feeder.repository.DesignTypeRepository; import org.onap.datalake.feeder.service.DbService; import org.onap.datalake.feeder.util.TestUtil; import org.springframework.validation.BindingResult; @@ -62,11 +67,20 @@ public class DbControllerTest { private DbRepository dbRepository; @Mock + private DbTypeRepository dbTypeRepository; + + @Mock + private DesignTypeRepository designTypeRepository; + + @Mock private BindingResult mockBindingResult; @InjectMocks private DbService dbService1; - + + @InjectMocks + private DbController dbController; + public DbConfig getDbConfig() { DbConfig dbConfig = new DbConfig(); dbConfig.setId(1); @@ -77,16 +91,16 @@ public class DbControllerTest { dbConfig.setDatabase("Elecsticsearch"); dbConfig.setPort(123); dbConfig.setPoperties("driver"); - dbConfig.setDbTypeId("ES"); + dbConfig.setDbTypeId("ES"); return dbConfig; } public void setAccessPrivateFields(DbController dbController) throws NoSuchFieldException, - IllegalAccessException { - Field dbRepository1 = dbController.getClass().getDeclaredField("dbRepository"); - dbRepository1.setAccessible(true); - dbRepository1.set(dbController, dbRepository); - } + IllegalAccessException { + Field dbRepository1 = dbController.getClass().getDeclaredField("dbRepository"); + dbRepository1.setAccessible(true); + dbRepository1.set(dbController, dbRepository); + } @Before public void setupTest() { @@ -101,7 +115,7 @@ public class DbControllerTest { DbController dbController = new DbController(); DbConfig dbConfig = getDbConfig(); setAccessPrivateFields(dbController); - PostReturnBody<DbConfig> db = dbController.createDb(dbConfig, mockBindingResult, httpServletResponse); + PostReturnBody < DbConfig > db = dbController.createDb(dbConfig, mockBindingResult, httpServletResponse); assertEquals(200, db.getStatusCode()); when(mockBindingResult.hasErrors()).thenReturn(true); db = dbController.createDb(dbConfig, mockBindingResult, httpServletResponse); @@ -113,8 +127,8 @@ public class DbControllerTest { DbController dbController = new DbController(); DbConfig dbConfig = getDbConfig(); when(mockBindingResult.hasErrors()).thenReturn(true); - PostReturnBody<DbConfig> db = dbController.updateDb(dbConfig.getId(), dbConfig, mockBindingResult, - httpServletResponse); + PostReturnBody < DbConfig > db = dbController.updateDb(dbConfig.getId(), dbConfig, mockBindingResult, + httpServletResponse); assertEquals(null, db); //when(mockBindingResult.hasErrors()).thenReturn(false); setAccessPrivateFields(dbController); @@ -135,12 +149,12 @@ public class DbControllerTest { DbController dbController = new DbController(); String name = "Elecsticsearch"; int testId = 1234; - List<Db> dbs = new ArrayList<>(); + List < Db > dbs = new ArrayList < > (); dbs.add(TestUtil.newDb(name)); setAccessPrivateFields(dbController); when(dbRepository.findAll()).thenReturn(dbs); - List<Integer> list = dbController.list(); - for (int id : list) { + List < Integer > list = dbController.list(); + for (int id: list) { assertNotEquals(1234, id); } //dbController.deleteDb("Elecsticsearch", httpServletResponse); @@ -155,18 +169,18 @@ public class DbControllerTest { Topic topic = TestUtil.newTopic(topicName); topic.setEnabled(true); topic.setId(1); - Set<Topic> topics = new HashSet<>(); + Set < Topic > topics = new HashSet < > (); topics.add(topic); Db db1 = TestUtil.newDb(dbName); db1.setTopics(topics); setAccessPrivateFields(dbController); - Set<Topic> elecsticsearch = dbController.getDbTopics(dbName, httpServletResponse); + Set < Topic > elecsticsearch = dbController.getDbTopics(dbName, httpServletResponse); assertEquals(Collections.emptySet(), elecsticsearch); when(dbRepository.findByName(dbName)).thenReturn(db1); elecsticsearch = dbController.getDbTopics(dbName, httpServletResponse); - for (Topic anElecsticsearch : elecsticsearch) { - Topic tmp = TestUtil.newTopic(topicName); - tmp.setId(2); + for (Topic anElecsticsearch: elecsticsearch) { + Topic tmp = TestUtil.newTopic(topicName); + tmp.setId(2); assertNotEquals(tmp, anElecsticsearch); } //dbController.deleteDb(dbName, httpServletResponse); @@ -177,7 +191,7 @@ public class DbControllerTest { DbController dbController = new DbController(); DbConfig dbConfig = getDbConfig(); setAccessPrivateFields(dbController); - PostReturnBody<DbConfig> db = dbController.createDb(dbConfig, mockBindingResult, httpServletResponse); + PostReturnBody < DbConfig > db = dbController.createDb(dbConfig, mockBindingResult, httpServletResponse); assertNotNull(db); } @@ -185,8 +199,102 @@ public class DbControllerTest { public void testVerifyConnection() throws IOException { DbController dbController = new DbController(); DbConfig dbConfig = getDbConfig(); - PostReturnBody<DbConfig> dbConfigPostReturnBody = dbController.verifyDbConnection(dbConfig, httpServletResponse); + PostReturnBody < DbConfig > dbConfigPostReturnBody = dbController.verifyDbConnection(dbConfig, httpServletResponse); assertEquals(null, dbConfigPostReturnBody); } + @Test + public void testDeleteDbNull() throws IOException { + Optional < Db > dbOptional = Optional.ofNullable(null); + when(dbRepository.findById(1)).thenReturn(dbOptional); + dbController.deleteDb(1, httpServletResponse); + } + + @Test + public void deleteDbTest() throws IOException { + Db db = TestUtil.newDb("Elecsticsearch"); + Topic topic = TestUtil.newTopic("Elecsticsearch"); + topic.setEnabled(true); + topic.setId(1); + Set < Topic > topics = new HashSet < > (); + topics.add(topic); + db.setTopics(topics); + Optional < Db > dbOptional = Optional.ofNullable(db); + when(dbRepository.findById(1)).thenReturn(dbOptional); + dbController.deleteDb(1, httpServletResponse); + } + + @Test + public void testUpdateDbNull() throws IOException { + DbConfig dbConfig = getDbConfig(); + Db db = TestUtil.newDb("Elecsticsearch"); + Optional < Db > dbOptional = Optional.ofNullable(db); + when(dbRepository.findById(dbConfig.getId())).thenReturn(dbOptional); + dbController.updateDb(dbConfig.getId(), dbConfig, mockBindingResult, httpServletResponse); + } + + @Test + public void testDblistByTool() { + List < DbType > dbTypeList = new ArrayList < > (); + DbType dbType = new DbType("ES", "Elasticsearch"); + Set < Db > dbs = new HashSet < > (); + dbs.add(TestUtil.newDb("MongoDB")); + dbType.setDbs(dbs); + dbTypeList.add(dbType); + when(dbTypeRepository.findByTool(false)).thenReturn(dbTypeList); + dbController.dblistByTool(true); + } + + @Test + public void testListIdAndName() { + DesignType designType = new DesignType(); + DbType dbType = new DbType("ES", "Elasticsearch"); + Set < Db > dbs = new HashSet < > (); + dbs.add(TestUtil.newDb("MongoDB")); + dbType.setDbs(dbs); + designType.setName("Kibana"); + designType.setDbType(dbType); + when(designTypeRepository.findById("1")).thenReturn(Optional.of(designType)); + dbController.listIdAndName("1"); + } + + @Test + public void testCreateDbError() throws IOException { + when(mockBindingResult.hasErrors()).thenReturn(true); + assertEquals(null, dbController.createDb(getDbConfig(), mockBindingResult, httpServletResponse)); + } + + @Test(expected = NullPointerException.class) + public void testCreateDbException() throws IOException { + DbConfig dbConfig = getDbConfig(); + dbConfig.setDbTypeId(""); + dbController.createDb(dbConfig, mockBindingResult, httpServletResponse); + } + + @Test + public void createDbTest() throws IOException { + DbConfig dbConfig = getDbConfig(); + DbType dbType = new DbType("ES", "Elasticsearch"); + when(dbTypeRepository.findById(dbConfig.getDbTypeId())).thenReturn(Optional.of(dbType)); + dbController.createDb(dbConfig, mockBindingResult, httpServletResponse); + } + + @Test + public void testGetDb() throws IOException { + DbConfig elecsticsearch = dbController.getDb(1, httpServletResponse); + assertEquals(null, elecsticsearch); + } + + @Test + public void testGetDbTypes() throws IOException { + List < DbType > dbTypeList = new ArrayList < > (); + DbType dbType = new DbType("ES", "Elasticsearch"); + Set < Db > dbs = new HashSet < > (); + dbs.add(TestUtil.newDb("MongoDB")); + dbType.setDbs(dbs); + dbTypeList.add(dbType); + when(dbTypeRepository.findAll()).thenReturn(dbTypeList); + dbController.getDbTypes(httpServletResponse); + } + } diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DesignControllerTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DesignControllerTest.java index 4b933bee..ca670998 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DesignControllerTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DesignControllerTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,10 +30,12 @@ import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; import org.onap.datalake.feeder.config.ApplicationConfiguration; import org.onap.datalake.feeder.controller.domain.PostReturnBody; -import org.onap.datalake.feeder.domain.*; import org.onap.datalake.feeder.domain.Design; +import org.onap.datalake.feeder.domain.DesignType; +import org.onap.datalake.feeder.domain.TopicName; import org.onap.datalake.feeder.dto.DesignConfig; import org.onap.datalake.feeder.repository.DesignTypeRepository; +import org.onap.datalake.feeder.repository.TopicNameRepository; import org.onap.datalake.feeder.repository.DesignRepository; import org.onap.datalake.feeder.service.DesignService; import org.onap.datalake.feeder.service.TopicService; @@ -46,12 +49,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class DesignControllerTest { - + //static String Kibana_Dashboard_Import_Api = "/api/kibana/dashboards/import?exclude=index-pattern"; @Mock @@ -72,9 +77,14 @@ public class DesignControllerTest { @Mock private DesignTypeRepository designTypeRepository; - @InjectMocks + @Mock + private TopicNameRepository topicNameRepository; + + @Mock private DesignService designService; + @InjectMocks + private DesignController testDesignController; @Before public void setupTest() { @@ -85,40 +95,82 @@ public class DesignControllerTest { @Test public void testCreateDesign() throws NoSuchFieldException, IllegalAccessException, IOException { - DesignController testDesignController = new DesignController(); - setAccessPrivateFields(testDesignController); Design testDesign = fillDomain(); + DesignConfig designConfig = new DesignConfig(); + when(designService.fillDesignConfiguration(designConfig)).thenReturn(testDesign); + testDesignController.createDesign(designConfig, mockBindingResult, httpServletResponse); + } + + @Test + public void testCreateDesignNull() throws NoSuchFieldException, IllegalAccessException, IOException { + + DesignConfig designConfig = new DesignConfig(); + when(designService.fillDesignConfiguration(designConfig)).thenThrow(NullPointerException.class); + testDesignController.createDesign(designConfig, mockBindingResult, httpServletResponse); + } + + @Test + public void testCreateDesignError() throws NoSuchFieldException, IllegalAccessException, IOException { + + DesignConfig designConfig = new DesignConfig(); + when(mockBindingResult.hasErrors()).thenReturn(true); + assertEquals(null, testDesignController.createDesign(designConfig, mockBindingResult, httpServletResponse)); + } + + @Test + public void testUpdateDesignNull() throws NoSuchFieldException, IllegalAccessException, IOException { + + Design testDesign = fillDomain(); + Integer id = 1; //when(topicService.getTopic(0)).thenReturn(new Topic("unauthenticated.SEC_FAULT_OUTPUT")); -// when(designTypeRepository.findById("Kibana Dashboard")).thenReturn(Optional.of(testDesign.getDesignType())); - PostReturnBody<DesignConfig> postPortal = testDesignController.createDesign(testDesign.getDesignConfig(), mockBindingResult, httpServletResponse); + // when(designTypeRepository.findById("Kibana Dashboard")).thenReturn(Optional.of(testDesign.getDesignType())); + PostReturnBody < DesignConfig > postPortal = testDesignController.updateDesign(testDesign.getDesignConfig(), mockBindingResult, id, httpServletResponse); //assertEquals(postPortal.getStatusCode(), 200); assertNull(postPortal); } @Test + public void testUpdateDesignError() throws NoSuchFieldException, IllegalAccessException, IOException { + Design testDesign = fillDomain(); + Integer id = 1; + when(mockBindingResult.hasErrors()).thenReturn(true); + assertEquals(null, testDesignController.updateDesign(testDesign.getDesignConfig(), mockBindingResult, id, httpServletResponse)); + } + + @Test public void testUpdateDesign() throws NoSuchFieldException, IllegalAccessException, IOException { + Design testDesign = fillDomain(); + Integer id = 1; + when(designService.getDesign(id)).thenReturn(testDesign); + testDesignController.updateDesign(testDesign.getDesignConfig(), mockBindingResult, id, httpServletResponse); + } - DesignController testDesignController = new DesignController(); - setAccessPrivateFields(testDesignController); + @Test + public void testUpdateDesignException() throws NoSuchFieldException, IllegalAccessException, IOException { Design testDesign = fillDomain(); + DesignConfig designConfig = new DesignConfig(); Integer id = 1; - when(designRepository.findById(id)).thenReturn((Optional.of(testDesign))); - //when(topicService.getTopic(0)).thenReturn(new Topic("unauthenticated.SEC_FAULT_OUTPUT")); - // when(designTypeRepository.findById("Kibana Dashboard")).thenReturn(Optional.of(testDesign.getDesignType())); - PostReturnBody<DesignConfig> postPortal = testDesignController.updateDesign(testDesign.getDesignConfig(), mockBindingResult, id, httpServletResponse); - //assertEquals(postPortal.getStatusCode(), 200); - assertNull(postPortal); + when(designService.getDesign(id)).thenReturn(testDesign); + doThrow(NullPointerException.class).when(designService).fillDesignConfiguration(designConfig, testDesign); + testDesignController.updateDesign(designConfig, mockBindingResult, id, httpServletResponse); + } + + @Test + public void testDeleteDesignNull() throws NoSuchFieldException, IllegalAccessException, IOException { + + Design testDesign = fillDomain(); + Integer id = 1; + testDesign.setId(1); + testDesignController.deleteDesign(id, httpServletResponse); } @Test public void testDeleteDesign() throws NoSuchFieldException, IllegalAccessException, IOException { - DesignController testDesignController = new DesignController(); - setAccessPrivateFields(testDesignController); Design testDesign = fillDomain(); Integer id = 1; testDesign.setId(1); - when(designRepository.findById(id)).thenReturn((Optional.of(testDesign))); + when(designService.getDesign(id)).thenReturn(testDesign); testDesignController.deleteDesign(id, httpServletResponse); } @@ -128,22 +180,27 @@ public class DesignControllerTest { DesignController testDesignController = new DesignController(); setAccessPrivateFields(testDesignController); Design testDesign = fillDomain(); - List<Design> designList = new ArrayList<>(); + List < Design > designList = new ArrayList < > (); designList.add(testDesign); - when(designRepository.findAll()).thenReturn(designList); - assertEquals(1, testDesignController.queryAllDesign().size()); + assertEquals(0, testDesignController.queryAllDesign().size()); + } + + @Test + public void testDeployDesignNull() throws NoSuchFieldException, IllegalAccessException, IOException { + + Design testDesign = fillDomain(); + Integer id = 1; + testDesign.setId(1); + testDesignController.deployDesign(id, httpServletResponse); } - @Test(expected = NullPointerException.class) + @Test public void testDeployDesign() throws NoSuchFieldException, IllegalAccessException, IOException { - DesignController testDesignController = new DesignController(); - setAccessPrivateFields(testDesignController); Design testDesign = fillDomain(); Integer id = 1; testDesign.setId(1); - //when(applicationConfiguration.getKibanaDashboardImportApi()).thenReturn(Kibana_Dashboard_Import_Api); - when(designRepository.findById(id)).thenReturn((Optional.of(testDesign))); + when(designRepository.findById(id)).thenReturn(Optional.of(new Design())); testDesignController.deployDesign(id, httpServletResponse); } @@ -158,16 +215,18 @@ public class DesignControllerTest { } - public Design fillDomain(){ + public Design fillDomain() { Design design = new Design(); + design.setId(1); design.setName("Kibana"); design.setBody("jsonString"); design.setSubmitted(false); design.setNote("test"); DesignType designType = new DesignType(); + designType.setId("1"); designType.setName("Kibana Dashboard"); design.setDesignType(designType); design.setTopicName(new TopicName("unauthenticated.SEC_FAULT_OUTPUT")); return design; } -}
\ No newline at end of file +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DesignTypeControllerTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DesignTypeControllerTest.java index 91af11ca..531b0b28 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DesignTypeControllerTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/DesignTypeControllerTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,50 +25,51 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnitRunner; import org.onap.datalake.feeder.domain.DesignType; +import org.onap.datalake.feeder.dto.DesignTypeConfig; +import org.onap.datalake.feeder.repository.DesignTypeRepository; import org.onap.datalake.feeder.service.DesignTypeService; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class DesignTypeControllerTest { - @InjectMocks + @Mock + private DesignTypeRepository designTypeRepository; + + @Mock private DesignTypeService designTypeService; + @InjectMocks + private DesignTypeController designTypeController; + @Before public void setupTest() { MockitoAnnotations.initMocks(this); } - @Test(expected = NullPointerException.class) - public void getTemplateTypeName() throws NoSuchFieldException, IllegalAccessException { - - DesignTypeController testDesignTypeController = new DesignTypeController(); - setAccessPrivateFields(testDesignTypeController); - DesignType testDesignType = fillDomain(); - List<String> designTypeNamesList = new ArrayList<>(); - designTypeNamesList.add(testDesignType.getName()); - assertEquals(1, testDesignTypeController.getDesignType().size()); - } - - public void setAccessPrivateFields(DesignTypeController designTypeController) throws NoSuchFieldException, IllegalAccessException { - - Field testDesignTypeService = designTypeController.getClass().getDeclaredField("designTypeService"); - testDesignTypeService.setAccessible(true); - testDesignTypeService.set(designTypeController, designTypeService); - } - - - public DesignType fillDomain(){ + public DesignType fillDomain() { DesignType designType = new DesignType(); designType.setName("Kibana Dashboard"); return designType; } -}
\ No newline at end of file + + @Test + public void testGetDesignType() { + List < DesignTypeConfig > designTypeNamesList = new ArrayList < > (); + List < DesignType > designTypeList = new ArrayList < > (); + DesignType designType = fillDomain(); + designTypeList.add(designType); + when(designTypeService.getDesignTypes()).thenReturn(designTypeNamesList); + assertNotNull(designTypeController.getDesignType()); + } + +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/KafkaControllerTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/KafkaControllerTest.java index 06aa61db..fd685fef 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/KafkaControllerTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/KafkaControllerTest.java @@ -3,6 +3,7 @@ * ONAP : DataLake * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,7 +36,8 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @@ -68,17 +70,74 @@ public class KafkaControllerTest { when(kafkaService.getKafkaById(kafkaConfig.getId())).thenReturn(null).thenReturn(kafka); when(kafkaRepository.save(kafka)).thenReturn(null); when(kafkaService.fillKafkaConfiguration(kafkaConfig)).thenReturn(kafka); - when(mockBindingResult.hasErrors()).thenReturn(false,true,false,true); + when(mockBindingResult.hasErrors()).thenReturn(false, true, false, true); - kafkaController.createKafka(kafkaConfig,mockBindingResult,httpServletResponse); - kafkaController.createKafka(kafkaConfig,mockBindingResult,httpServletResponse); + kafkaController.createKafka(kafkaConfig, mockBindingResult, httpServletResponse); + kafkaController.createKafka(kafkaConfig, mockBindingResult, httpServletResponse); - kafkaController.updateKafka(kafkaConfig,mockBindingResult,id,httpServletResponse); - kafkaController.updateKafka(kafkaConfig,mockBindingResult,id,httpServletResponse); + kafkaController.updateKafka(kafkaConfig, mockBindingResult, id, httpServletResponse); + kafkaController.updateKafka(kafkaConfig, mockBindingResult, id, httpServletResponse); - kafkaController.deleteKafka(id,httpServletResponse); + kafkaController.deleteKafka(id, httpServletResponse); when(kafkaService.getAllKafka()).thenReturn(null); kafkaController.queryAllKafka(); } -}
\ No newline at end of file + + @Test + public void testCreateKafkaNull() throws IOException { + KafkaConfig kafkaConfig = new KafkaConfig(); + kafkaConfig.setId(1); + kafkaConfig.setName("123"); + when(kafkaService.getKafkaById(kafkaConfig.getId())).thenReturn(kafka); + assertEquals(null, kafkaController.createKafka(kafkaConfig, mockBindingResult, httpServletResponse)); + } + + @Test + public void testCreateKafkaException() throws IOException { + KafkaConfig kafkaConfig = new KafkaConfig(); + kafkaConfig.setId(1); + kafkaConfig.setName("123"); + when(kafkaService.getKafkaById(kafkaConfig.getId())).thenReturn(null); + when(kafkaService.fillKafkaConfiguration(kafkaConfig)).thenThrow(NullPointerException.class); + assertEquals(null, kafkaController.createKafka(kafkaConfig, mockBindingResult, httpServletResponse)); + } + + @Test + public void testUpdateKafkaNull() throws IOException { + KafkaConfig kafkaConfig = new KafkaConfig(); + kafkaConfig.setId(1); + kafkaConfig.setName("123"); + when(kafkaService.getKafkaById(kafkaConfig.getId())).thenReturn(null); + assertEquals(null, kafkaController.updateKafka(kafkaConfig, mockBindingResult, 1, httpServletResponse)); + } + + @Test + public void testUpdateKafkaException() throws IOException { + KafkaConfig kafkaConfig = new KafkaConfig(); + kafkaConfig.setId(1); + kafkaConfig.setName("123"); + when(kafkaService.getKafkaById(kafkaConfig.getId())).thenReturn(kafka); + doThrow(NullPointerException.class).when(kafkaService).fillKafkaConfiguration(kafkaConfig, kafka); + assertEquals(null, kafkaController.updateKafka(kafkaConfig, mockBindingResult, 1, httpServletResponse)); + } + + @Test + public void testDeleteKafkaNull() throws IOException { + when(kafkaService.getKafkaById(1)).thenReturn(null); + kafkaController.deleteKafka(1, httpServletResponse); + } + + @Test + public void testGetKafkaDetailNull() throws IOException { + when(kafkaService.getKafkaById(1)).thenReturn(null); + kafkaController.getKafkaDetail(1, httpServletResponse); + } + + @Test + public void testGetKafkaDetail() throws IOException { + when(kafkaService.getKafkaById(1)).thenReturn(kafka); + assertEquals(null, kafkaController.getKafkaDetail(1, httpServletResponse)); + } + +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/TopicControllerTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/TopicControllerTest.java index 988010ec..17107120 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/TopicControllerTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/TopicControllerTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright (C) 2018-2019 Huawei. All rights reserved. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,145 +28,185 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.onap.datalake.feeder.config.ApplicationConfiguration; import org.onap.datalake.feeder.controller.domain.PostReturnBody; +import org.onap.datalake.feeder.domain.Kafka; import org.onap.datalake.feeder.domain.Topic; import org.onap.datalake.feeder.dto.TopicConfig; +import org.onap.datalake.feeder.repository.KafkaRepository; import org.onap.datalake.feeder.repository.TopicNameRepository; import org.onap.datalake.feeder.repository.TopicRepository; import org.onap.datalake.feeder.service.DbService; import org.onap.datalake.feeder.service.DmaapService; import org.onap.datalake.feeder.service.TopicService; import org.onap.datalake.feeder.util.TestUtil; +import org.springframework.context.ApplicationContext; import org.springframework.validation.BindingResult; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class TopicControllerTest { - static String DEFAULT_TOPIC_NAME = "_DL_DEFAULT_"; + static String DEFAULT_TOPIC_NAME = "_DL_DEFAULT_"; - @Mock - private HttpServletResponse httpServletResponse; + @Mock + private HttpServletResponse httpServletResponse; - @Mock - private BindingResult mockBindingResult; + @Mock + private BindingResult mockBindingResult; - @Mock - private TopicRepository topicRepository; + @Mock + private TopicRepository topicRepository; - @Mock - private TopicService topicService; + @Mock + private TopicService topicService; - @Mock - private TopicNameRepository topicNameRepository; + @Mock + private TopicNameRepository topicNameRepository; + + @Mock + private KafkaRepository kafkaRepository; + + @InjectMocks + TopicController topicController; + + @Mock + private ApplicationConfiguration config; + + @Mock + private ApplicationContext context; + + @Mock + private DbService dbService; + + @Mock + private DmaapService dmaapService; + + @Before + public void setupTest() throws NoSuchFieldException, IllegalAccessException { + // While the default boolean return value for a mock is 'false', + // it's good to be explicit anyway: + when(mockBindingResult.hasErrors()).thenReturn(false); + } + + @Test + public void testListTopic() throws IOException, NoSuchFieldException, IllegalAccessException {} + + @Test + public void testCreateTopic() throws IOException { + Topic a = TestUtil.newTopic("a"); + a.setId(1); + a.setEnabled(true); + + TopicConfig ac = a.getTopicConfig(); + + when(topicService.fillTopicConfiguration(ac)).thenReturn(a); + PostReturnBody < TopicConfig > postTopic = topicController.createTopic(ac, mockBindingResult, httpServletResponse); + assertEquals(postTopic.getStatusCode(), 200); + + when(topicService.fillTopicConfiguration(ac)).thenReturn(a); + a.setTtl(0); + PostReturnBody < TopicConfig > postTopicConfig = topicController.createTopic(ac, mockBindingResult, httpServletResponse); + assertEquals(postTopicConfig.getStatusCode(), 200); + + when(mockBindingResult.hasErrors()).thenReturn(true); + PostReturnBody < TopicConfig > topicConfig = topicController.createTopic(ac, mockBindingResult, httpServletResponse); + assertEquals(null, topicConfig); + } + + @Test + public void testUpdateTopic() throws IOException { + Topic a = TestUtil.newTopic("a"); + a.setId(1); + a.setEnabled(true); + + TopicConfig ac = a.getTopicConfig(); + + when(topicService.getTopic(1)).thenReturn(a); + PostReturnBody < TopicConfig > postConfig1 = topicController.updateTopic(1, ac, mockBindingResult, httpServletResponse); + assertEquals(200, postConfig1.getStatusCode()); + TopicConfig ret = postConfig1.getReturnBody(); + assertEquals("a", ret.getName()); + assertEquals(true, ret.isEnabled()); + + topicController.updateTopic(0, ac, mockBindingResult, httpServletResponse); + + when(topicService.getTopic(1)).thenReturn(null); + topicController.updateTopic(1, ac, mockBindingResult, httpServletResponse); + + when(mockBindingResult.hasErrors()).thenReturn(true); + PostReturnBody < TopicConfig > postConfig2 = topicController.updateTopic(1, ac, mockBindingResult, httpServletResponse); + assertNull(postConfig2); + + } + + @Test + public void testGetTopic() throws IOException { + Topic a = TestUtil.newTopic("a"); + a.setId(1); + a.setEnabled(true); + + when(topicService.getTopic(1)).thenReturn(a); + TopicConfig ac = topicController.getTopic(1, httpServletResponse); + when(topicService.getTopic(1)).thenReturn(null); + ac = topicController.getTopic(1, httpServletResponse); + } + + @Test + public void testDeleteTopic() throws IOException { + Topic a = TestUtil.newTopic("a"); + a.setId(1); + a.setEnabled(true); + + when(topicService.getTopic(1)).thenReturn(a); + topicController.deleteTopic(1, httpServletResponse); + when(topicService.getTopic(1)).thenReturn(null); + topicController.deleteTopic(1, httpServletResponse); + } + + @Test + public void testList() { + ArrayList < Topic > topics = new ArrayList < > (); + topics.add(TestUtil.newTopic("a")); + topics.add(TestUtil.newTopic(DEFAULT_TOPIC_NAME)); + when(topicRepository.findAll()).thenReturn(topics); + + List < Integer > ids = topicController.list(); + for (Integer topic: ids) { + System.out.println(topic); + } + } + + @Test + public void testGetDefaultConfigNull() throws IOException { + Topic topic = null; + when(topicService.getDefaultTopicFromFeeder()).thenReturn(topic); + assertEquals(null, topicController.getDefaultConfig(httpServletResponse)); + } + + @Test + public void testGetDefaultConfig() throws IOException { + Topic topic = TestUtil.newTopic(DEFAULT_TOPIC_NAME); + when(topicService.getDefaultTopicFromFeeder()).thenReturn(topic); + assertEquals(topic.getName(), topicController.getDefaultConfig(httpServletResponse).getName()); + } + + @Test + public void testListDmaapTopics() { + Kafka kafka = TestUtil.newKafka("test"); + when(kafkaRepository.findById(1)).thenReturn(Optional.of(kafka)); + DmaapService dmaapService = mock(DmaapService.class); + when(context.getBean(DmaapService.class, kafka)).thenReturn(dmaapService); + when(dmaapService.getTopics()).thenReturn(null); + assertEquals(null, topicController.listDmaapTopics(1)); + } - @InjectMocks - TopicController topicController; - - @Mock - private ApplicationConfiguration config; - - @Mock - private DbService dbService; - - @Mock - private DmaapService dmaapService; - - @Before - public void setupTest() throws NoSuchFieldException, IllegalAccessException { - // While the default boolean return value for a mock is 'false', - // it's good to be explicit anyway: - when(mockBindingResult.hasErrors()).thenReturn(false); - } - - @Test - public void testListTopic() throws IOException, NoSuchFieldException, IllegalAccessException { - } - - @Test - public void testCreateTopic() throws IOException { - Topic a = TestUtil.newTopic("a"); - a.setId(1); - a.setEnabled(true); - - TopicConfig ac = a.getTopicConfig(); - - when(topicService.fillTopicConfiguration(ac)).thenReturn(a); - PostReturnBody<TopicConfig> postTopic = topicController.createTopic(ac, mockBindingResult, httpServletResponse); - assertEquals(postTopic.getStatusCode(), 200); - - when(mockBindingResult.hasErrors()).thenReturn(true); - PostReturnBody<TopicConfig> topicConfig = topicController.createTopic(ac, mockBindingResult, httpServletResponse); - assertEquals(null, topicConfig); - } - - @Test - public void testUpdateTopic() throws IOException { - Topic a = TestUtil.newTopic("a"); - a.setId(1); - a.setEnabled(true); - - TopicConfig ac = a.getTopicConfig(); - - when(topicService.getTopic(1)).thenReturn(a); - PostReturnBody<TopicConfig> postConfig1 = topicController.updateTopic(1, ac, mockBindingResult, httpServletResponse); - assertEquals(200, postConfig1.getStatusCode()); - TopicConfig ret = postConfig1.getReturnBody(); - assertEquals("a", ret.getName()); - assertEquals(true, ret.isEnabled()); - - topicController.updateTopic(0, ac, mockBindingResult, httpServletResponse); - - when(topicService.getTopic(1)).thenReturn(null); - topicController.updateTopic(1, ac, mockBindingResult, httpServletResponse); - - when(mockBindingResult.hasErrors()).thenReturn(true); - PostReturnBody<TopicConfig> postConfig2 = topicController.updateTopic(1, ac, mockBindingResult, httpServletResponse); - assertNull(postConfig2); - - } - - @Test - public void testGetTopic() throws IOException { - Topic a = TestUtil.newTopic("a"); - a.setId(1); - a.setEnabled(true); - - when(topicService.getTopic(1)).thenReturn(a); - TopicConfig ac = topicController.getTopic(1, httpServletResponse); - when(topicService.getTopic(1)).thenReturn(null); - ac = topicController.getTopic(1, httpServletResponse); - } - - @Test - public void testDeleteTopic() throws IOException { - Topic a = TestUtil.newTopic("a"); - a.setId(1); - a.setEnabled(true); - - when(topicService.getTopic(1)).thenReturn(a); - topicController.deleteTopic(1, httpServletResponse); - when(topicService.getTopic(1)).thenReturn(null); - topicController.deleteTopic(1, httpServletResponse); - } - - @Test - public void testList() { - ArrayList<Topic> topics = new ArrayList<>(); - topics.add(TestUtil.newTopic("a")); - topics.add(TestUtil.newTopic(DEFAULT_TOPIC_NAME)); - when(topicRepository.findAll()).thenReturn(topics); - - List<Integer> ids = topicController.list(); - for (Integer topic : ids) { - System.out.println(topic); - } - } } diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/TopicNameControllerTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/TopicNameControllerTest.java new file mode 100644 index 00000000..9ac5f1b3 --- /dev/null +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/controller/TopicNameControllerTest.java @@ -0,0 +1,67 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : DCAE + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.datalake.feeder.controller; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.datalake.feeder.domain.Topic; +import org.onap.datalake.feeder.domain.TopicName; +import org.onap.datalake.feeder.repository.TopicNameRepository; + +@RunWith(MockitoJUnitRunner.class) +public class TopicNameControllerTest { + + @Mock + private TopicNameRepository topicNameRepository; + + @InjectMocks + TopicNameController topicNameController; + + @Test + public void testList() throws IOException { + List < TopicName > topicNameList = new ArrayList < > (); + + TopicName topicName = new TopicName(); + topicName.setId("1"); + topicName.setDesigns(null); + Topic topic = new Topic(); + topic.setId(1); + Set < Topic > topics = new HashSet < > (); + topics.add(topic); + topicName.setTopics(topics); + topicNameList.add(topicName); + + when(topicNameRepository.findAll()).thenReturn(topicNameList); + List < String > retString = topicNameController.list(); + assertEquals("1", retString.get(0)); + + } + +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DbTypeTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DbTypeTest.java index 4a75df17..11432e16 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DbTypeTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DbTypeTest.java @@ -3,6 +3,7 @@ * ONAP : DataLake * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,20 +20,23 @@ */ package org.onap.datalake.feeder.domain; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import org.junit.Test; -import static org.junit.Assert.*; - public class DbTypeTest { @Test - public void test(){ - DbType dbType = new DbType("ES","Elasticsearch"); - + public void test() { + DbType dbType = new DbType("ES", "Elasticsearch"); + DbType dbType2 = new DbType("MONGO", "MongoDB"); - dbType.setTool(false); - + dbType.setTool(false); + assertNotNull(dbType.toString()); assertEquals(dbType, dbType); @@ -44,10 +48,10 @@ public class DbTypeTest { assertEquals("MongoDB", dbType2.getName()); dbType2.setName(null); dbType2.setDefaultPort(1); - assertTrue(1==dbType2.getDefaultPort()); + assertTrue(1 == dbType2.getDefaultPort()); dbType2.setDbs(null); assertNull(dbType2.getDbs()); } -}
\ No newline at end of file +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DesignTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DesignTest.java index de6fec27..efc49bf9 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DesignTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DesignTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +21,12 @@ package org.onap.datalake.feeder.domain; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import org.junit.Test; import org.onap.datalake.feeder.util.TestUtil; -import static org.junit.Assert.*; - public class DesignTest { @Test @@ -53,4 +55,4 @@ public class DesignTest { assertNull(design.getDbs()); } -}
\ No newline at end of file +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DesignTypeTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DesignTypeTest.java index e02c2d1c..da1c5ec1 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DesignTypeTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/domain/DesignTypeTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,10 +21,9 @@ package org.onap.datalake.feeder.domain; +import static org.junit.Assert.assertEquals; import org.junit.Test; -import static org.junit.Assert.*; - public class DesignTypeTest { @Test @@ -40,4 +40,4 @@ public class DesignTypeTest { designType.getDesigns(); designType.getDesignTypeConfig(); } -}
\ No newline at end of file +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/DesignConfigTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/DesignConfigTest.java index 22ebe4f1..6b0b006f 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/DesignConfigTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/DesignConfigTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,13 +21,13 @@ package org.onap.datalake.feeder.dto; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import org.junit.Test; import org.onap.datalake.feeder.domain.Design; import org.onap.datalake.feeder.domain.DesignType; import org.onap.datalake.feeder.domain.TopicName; -import static org.junit.Assert.*; - public class DesignConfigTest { @Test @@ -58,4 +59,4 @@ public class DesignConfigTest { assertEquals(testDesignConfig.getDesignType(), null); } -}
\ No newline at end of file +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/DesignTypeConfigTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/DesignTypeConfigTest.java new file mode 100644 index 00000000..a7253ae8 --- /dev/null +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/DesignTypeConfigTest.java @@ -0,0 +1,37 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : DCAE + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.datalake.feeder.dto; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class DesignTypeConfigTest { + + @Test + public void testDesignTypeConfig() { + DesignTypeConfig designTypeConfig = new DesignTypeConfig(); + designTypeConfig.setId("123"); + designTypeConfig.setName("test"); + assertEquals("123", designTypeConfig.getId()); + assertEquals("test", designTypeConfig.getName()); + } + +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/KafkaConfigTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/KafkaConfigTest.java index b2104177..2d38f532 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/KafkaConfigTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/dto/KafkaConfigTest.java @@ -3,6 +3,7 @@ * ONAP : DataLake * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,12 +20,12 @@ */ package org.onap.datalake.feeder.dto; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import org.junit.Test; import org.onap.datalake.feeder.domain.Kafka; import org.onap.datalake.feeder.util.TestUtil; -import static org.junit.Assert.*; - /** * Test Kafka * @@ -76,4 +77,4 @@ public class KafkaConfigTest { assertNotEquals(null, testKafkaConfig.getTimeout()); } -}
\ No newline at end of file +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/DesignServiceTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/DesignServiceTest.java index 65b373f5..cdc8c42a 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/DesignServiceTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/DesignServiceTest.java @@ -3,6 +3,7 @@ * ONAP : DCAE * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,11 +26,27 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.onap.datalake.feeder.config.ApplicationConfiguration; +import org.onap.datalake.feeder.domain.Db; import org.onap.datalake.feeder.domain.Design; import org.onap.datalake.feeder.domain.DesignType; +import org.onap.datalake.feeder.domain.TopicName; +import org.onap.datalake.feeder.dto.DesignConfig; +import org.onap.datalake.feeder.repository.DbRepository; +import org.onap.datalake.feeder.repository.DesignRepository; +import org.onap.datalake.feeder.repository.DesignTypeRepository; +import org.onap.datalake.feeder.repository.TopicNameRepository; +import org.onap.datalake.feeder.util.TestUtil; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.mockito.Mockito.when; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + @RunWith(MockitoJUnitRunner.class) public class DesignServiceTest { @@ -37,14 +54,26 @@ public class DesignServiceTest { private DesignType designType; @Mock + private DesignRepository designRepository; + + @Mock + private TopicNameRepository topicNameRepository; + + @Mock + private DbRepository dbRepository; + + @Mock private ApplicationConfiguration applicationConfiguration; + @Mock + private DesignTypeRepository designTypeRepository; + @InjectMocks private DesignService designService; @Test(expected = RuntimeException.class) - public void testDeploy() { - when(designType.getId()).thenReturn("KIBANA_DB","ES_MAPPING"); + public void testDeployException() { + when(designType.getId()).thenReturn("KIBANA_DB", "ES_MAPPING"); Design design = new Design(); design.setDesignType(designType); design.setBody("jsonString"); @@ -53,4 +82,96 @@ public class DesignServiceTest { designService.deploy(design); System.out.println(); } -}
\ No newline at end of file + + @Test + public void testFillDesignConfigurationNull() { + DesignConfig designConfig = new DesignConfig(); + designConfig.setTopicName("topic"); + designConfig.setDesignType("designType"); + TopicName topicName = new TopicName("test"); + Optional < TopicName > topicNameOptional = Optional.of(topicName); + when(topicNameRepository.findById(designConfig.getTopicName())).thenReturn(topicNameOptional); + when(designTypeRepository.findById(designConfig.getDesignType())).thenReturn(Optional.of(new DesignType())); + assertNull(designService.fillDesignConfiguration(designConfig).getName()); + } + + @Test + public void testFillDesignConfiguration() { + DesignConfig designConfig = new DesignConfig(); + designConfig.setTopicName("topic"); + designConfig.setDesignType("designType"); + + List < Integer > dbs = new ArrayList < > (); + dbs.add(1); + designConfig.setDbs(dbs); + when(topicNameRepository.findById(designConfig.getTopicName())).thenReturn(Optional.of(new TopicName())); + when(designTypeRepository.findById(designConfig.getDesignType())).thenReturn(Optional.of(new DesignType())); + when(dbRepository.findById(designConfig.getDbs().get(0))).thenReturn(Optional.of(new Db())); + designService.fillDesignConfiguration(designConfig).getName(); + } + + @Test(expected = IllegalArgumentException.class) + public void testFillDesign() { + Design design = new Design(); + design.setDesignType(designType); + DesignConfig designConfig = new DesignConfig(); + designService.fillDesignConfiguration(designConfig, design); + } + + @Test + public void testGetDesignNull() { + Optional < Design > testDesign = Optional.ofNullable(null); + when(designRepository.findById(1)).thenReturn(testDesign); + assertNull(designService.getDesign(1)); + } + + @Test + public void testDeploy() { + when(designType.getId()).thenReturn("KIBANA_DB"); + Design design = getDesign(); + assertNotNull(designService.deploy(design)); + } + + @Test + public void testDeployESMappingCase() { + when(designType.getId()).thenReturn("ES_MAPPING"); + Design design = getDesign(); + assertNotNull(designService.deploy(design)); + } + + @Test + public void testDeployDefault() { + when(designType.getId()).thenReturn("KIBANA_SEARCH"); + Design design = getDesign(); + assertNull(designService.deploy(design)); + } + + @Test(expected = NullPointerException.class) + public void testQueryAllDesignNull() { + when(designRepository.findAll()).thenReturn(null); + designService.queryAllDesign(); + } + + @Test + public void testQueryAllDesign() { + List < Design > designList = new ArrayList < > (); + Design design = getDesign(); + designList.add(design); + when(designRepository.findAll()).thenReturn(designList); + designService.queryAllDesign(); + } + + public Design getDesign() { + Design design = new Design(); + design.setDesignType(designType); + design.setBody("jsonString"); + design.setTopicName(new TopicName("1")); + Set < Db > dbs = new HashSet < > (); + Db db = TestUtil.newDb("MongoDB"); + db.setEnabled(true); + dbs.add(db); + design.setDbs(dbs); + return design; + } + +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/DesignTypeServiceTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/DesignTypeServiceTest.java index 5879deb6..28c84750 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/DesignTypeServiceTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/DesignTypeServiceTest.java @@ -3,6 +3,7 @@ * ONAP : DataLake * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,13 +26,11 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.onap.datalake.feeder.domain.DesignType; -import org.onap.datalake.feeder.dto.DesignTypeConfig; import org.onap.datalake.feeder.repository.DesignTypeRepository; - import java.util.ArrayList; import java.util.List; - -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @@ -44,16 +43,19 @@ public class DesignTypeServiceTest { private DesignTypeService designTypeService; @Test - public void testDesignTypeService(){ - List<DesignType> designTypeList = new ArrayList<>(); + public void testDesignTypeService() { + List < DesignType > designTypeList = new ArrayList < > (); DesignType designType = new DesignType(); designType.setName("test"); - //DesignTypeConfig designTypeConfig = new DesignTypeConfig(); - //designTypeConfig.setDesignType("test"); - //designTypeConfig.setDisplay("test"); designTypeList.add(designType); when(designTypeRepository.findAll()).thenReturn(designTypeList); assertNotNull(designTypeService.getDesignTypes()); } -}
\ No newline at end of file + @Test + public void testDesignTypeServiceNull() { + when(designTypeRepository.findAll()).thenReturn(null); + assertEquals(0, designTypeService.getDesignTypes().size()); + } + +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/KafkaServiceTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/KafkaServiceTest.java index 0274d309..2cb0740c 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/KafkaServiceTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/KafkaServiceTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,12 +29,11 @@ import org.mockito.junit.MockitoJUnitRunner; import org.onap.datalake.feeder.domain.Kafka; import org.onap.datalake.feeder.dto.KafkaConfig; import org.onap.datalake.feeder.repository.KafkaRepository; - import java.util.ArrayList; import java.util.List; import java.util.Optional; - -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @@ -67,4 +67,4 @@ public class KafkaServiceTest { kafkaService.fillKafkaConfiguration(kafkaConfig); } -}
\ No newline at end of file +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/PullServiceTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/PullServiceTest.java index d6298b87..f587f358 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/PullServiceTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/PullServiceTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,74 +28,72 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.onap.datalake.feeder.config.ApplicationConfiguration; import org.springframework.context.ApplicationContext; - import java.lang.reflect.Field; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.locks.ReentrantReadWriteLock; - -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class PullServiceTest { - @InjectMocks - private PullService pullService; + @InjectMocks + private PullService pullService; - @Mock - private ApplicationContext context; + @Mock + private ApplicationContext context; - @Mock - private ApplicationConfiguration config; + @Mock + private ApplicationConfiguration config; - @Mock - private ExecutorService executorService; + @Mock + private ExecutorService executorService; - @Mock - private List<Puller> consumers; + @Mock + private List < Puller > consumers; - @Test - public void isRunning() { - assertFalse(pullService.isRunning()); - } + @Test + public void isRunning() { + assertFalse(pullService.isRunning()); + } - @Test(expected = NullPointerException.class) - public void start() { - setRunning(false); - pullService.start(); - setRunning(true); - pullService.start(); - } + @Test(expected = NullPointerException.class) + public void start() { + setRunning(false); + pullService.start(); + setRunning(true); + pullService.start(); + } - @Test - public void shutdown() { - when(config.getShutdownLock()).thenReturn(new ReentrantReadWriteLock()); - setRunning(false); - pullService.shutdown(); - setRunning(true); - pullService.shutdown(); - } + @Test + public void shutdown() { + when(config.getShutdownLock()).thenReturn(new ReentrantReadWriteLock()); + setRunning(false); + pullService.shutdown(); + setRunning(true); + pullService.shutdown(); + } - private void setRunning(boolean running) { - Field configField; - try { - configField = PullService.class.getDeclaredField("isRunning"); - configField.setAccessible(true); - configField.set(pullService, running); - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + private void setRunning(boolean running) { + Field configField; + try { + configField = PullService.class.getDeclaredField("isRunning"); + configField.setAccessible(true); + configField.set(pullService, running); + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); - } catch (NoSuchFieldException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (SecurityException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -}
\ No newline at end of file + } catch (NoSuchFieldException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicConfigPollingServiceTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicConfigPollingServiceTest.java index bd26519b..e30aa7b8 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicConfigPollingServiceTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicConfigPollingServiceTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. *================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +22,7 @@ package org.onap.datalake.feeder.service; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; @@ -30,6 +32,7 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -40,6 +43,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.onap.datalake.feeder.config.ApplicationConfiguration; +import org.onap.datalake.feeder.domain.EffectiveTopic; import org.onap.datalake.feeder.domain.Kafka; import org.onap.datalake.feeder.util.TestUtil; @@ -51,73 +55,87 @@ import org.onap.datalake.feeder.util.TestUtil; */ @RunWith(MockitoJUnitRunner.class) public class TopicConfigPollingServiceTest { - @Mock - private ApplicationConfiguration config; - @Mock - private DmaapService dmaapService; + @Mock + private ApplicationConfiguration config; - @InjectMocks - private TopicConfigPollingService topicConfigPollingService = new TopicConfigPollingService(); + @Mock + private DmaapService dmaapService; - static String KAFKA_NAME = "kafka1"; + @Mock + private Map < Integer, Map < String, List < EffectiveTopic >>> effectiveTopicMap = new HashMap < > (); - @Before - public void init() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { - Method init = topicConfigPollingService.getClass().getDeclaredMethod("init"); - init.setAccessible(true); - init.invoke(topicConfigPollingService); + @InjectMocks + private TopicConfigPollingService topicConfigPollingService = new TopicConfigPollingService(); - Set<String> activeTopics = new HashSet<>(Arrays.asList("test")); - Map<Integer, Set<String>> activeTopicMap = new HashMap<>(); - activeTopicMap.put(1, activeTopics); + static String KAFKA_NAME = "kafka1"; - Field activeTopicsField = TopicConfigPollingService.class.getDeclaredField("activeTopicMap"); - activeTopicsField.setAccessible(true); - activeTopicsField.set(topicConfigPollingService, activeTopicMap); + @Before + public void init() + throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { + Method init = topicConfigPollingService.getClass().getDeclaredMethod("init"); + init.setAccessible(true); + init.invoke(topicConfigPollingService); - Method initMethod = TopicConfigPollingService.class.getDeclaredMethod("init"); - initMethod.setAccessible(true); - initMethod.invoke(topicConfigPollingService); - } + Set < String > activeTopics = new HashSet < > (Arrays.asList("test")); + Map < Integer, Set < String >> activeTopicMap = new HashMap < > (); + activeTopicMap.put(1, activeTopics); - @Test - public void testRun() throws InterruptedException { + Field activeTopicsField = TopicConfigPollingService.class.getDeclaredField("activeTopicMap"); + activeTopicsField.setAccessible(true); + activeTopicsField.set(topicConfigPollingService, activeTopicMap); - when(config.getCheckTopicInterval()).thenReturn(1L); + Method initMethod = TopicConfigPollingService.class.getDeclaredMethod("init"); + initMethod.setAccessible(true); + initMethod.invoke(topicConfigPollingService); + } - Thread thread = new Thread(topicConfigPollingService); - thread.start(); + @Test + public void testRun() throws InterruptedException { - Thread.sleep(50); - topicConfigPollingService.shutdown(); - thread.join(); + when(config.getCheckTopicInterval()).thenReturn(1L); - assertTrue(topicConfigPollingService.isActiveTopicsChanged(new Kafka())); - } + Thread thread = new Thread(topicConfigPollingService); + thread.start(); - @Test - public void testRunNoChange() throws InterruptedException { + Thread.sleep(50); + topicConfigPollingService.shutdown(); + thread.join(); - when(config.getCheckTopicInterval()).thenReturn(1L); + assertTrue(topicConfigPollingService.isActiveTopicsChanged(new Kafka())); + } - Thread thread = new Thread(topicConfigPollingService); - thread.start(); + @Test + public void testRunNoChange() throws InterruptedException { - Thread.sleep(50); - topicConfigPollingService.shutdown(); - thread.join(); + when(config.getCheckTopicInterval()).thenReturn(1L); - assertTrue(topicConfigPollingService.isActiveTopicsChanged(new Kafka())); - } + Thread thread = new Thread(topicConfigPollingService); + thread.start(); - @Test - public void testGet() { - Kafka kafka = TestUtil.newKafka(KAFKA_NAME); - kafka.setId(1); - //assertNull(topicConfigPollingService.getEffectiveTopic (kafka, "test")); - assertNotNull(topicConfigPollingService.getActiveTopics(kafka)); + Thread.sleep(50); + topicConfigPollingService.shutdown(); + thread.join(); - } + assertTrue(topicConfigPollingService.isActiveTopicsChanged(new Kafka())); + } -}
\ No newline at end of file + @Test + public void testGet() { + Kafka kafka = TestUtil.newKafka(KAFKA_NAME); + kafka.setId(1); + //assertNull(topicConfigPollingService.getEffectiveTopic (kafka, "test")); + assertNotNull(topicConfigPollingService.getActiveTopics(kafka)); + + } + + @Test + public void testGetEffectiveTopic() { + Kafka kafka = TestUtil.newKafka(KAFKA_NAME); + kafka.setId(1); + Map < String, List < EffectiveTopic >> effectiveTopicMapKafka = new HashMap < > (); + when(effectiveTopicMap.get(kafka.getId())).thenReturn(effectiveTopicMapKafka); + assertNull(topicConfigPollingService.getEffectiveTopic(kafka, "test")); + } + +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicNameServiceTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicNameServiceTest.java new file mode 100644 index 00000000..f040261c --- /dev/null +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicNameServiceTest.java @@ -0,0 +1,55 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : DCAE + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.datalake.feeder.service; + +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.datalake.feeder.domain.TopicName; +import org.onap.datalake.feeder.repository.TopicNameRepository; + +@RunWith(MockitoJUnitRunner.class) +public class TopicNameServiceTest { + + @Mock + private TopicNameRepository topicNameRepository; + + @InjectMocks + private TopicNameService topicNameService; + + @Test + public void testUpdate() { + List < TopicName > topicNameList = new ArrayList < > (); + topicNameList.add(new TopicName("test")); + Collection < String > allTopicNames = new ArrayList < > (); + allTopicNames.add("MONGODB"); + when(topicNameRepository.findAll()).thenReturn(topicNameList); + topicNameService.update(allTopicNames); + } + +} diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicServiceTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicServiceTest.java index eea47501..3c03f14e 100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicServiceTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/TopicServiceTest.java @@ -1,53 +1,51 @@ /* -* ============LICENSE_START======================================================= -* ONAP : DATALAKE -* ================================================================================ -* Copyright 2019 China Mobile -*================================================================================= -* 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========================================================= -*/ + * ============LICENSE_START======================================================= + * ONAP : DATALAKE + * ================================================================================ + * Copyright 2019 China Mobile + * Copyright (C) 2022 Wipro Limited. + *================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ package org.onap.datalake.feeder.service; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; -import org.elasticsearch.client.IndicesClient; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.client.indices.GetIndexRequest; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; import org.mockito.junit.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; import org.onap.datalake.feeder.config.ApplicationConfiguration; -import org.onap.datalake.feeder.domain.*; +import org.onap.datalake.feeder.domain.Db; +import org.onap.datalake.feeder.domain.DbType; +import org.onap.datalake.feeder.domain.Kafka; +import org.onap.datalake.feeder.domain.Topic; +import org.onap.datalake.feeder.domain.TopicName; import org.onap.datalake.feeder.dto.TopicConfig; -import org.onap.datalake.feeder.enumeration.DbTypeEnum; import org.onap.datalake.feeder.repository.DbRepository; +import org.onap.datalake.feeder.repository.KafkaRepository; import org.onap.datalake.feeder.repository.TopicNameRepository; import org.onap.datalake.feeder.repository.TopicRepository; import org.onap.datalake.feeder.service.db.ElasticsearchService; @@ -61,127 +59,210 @@ import org.onap.datalake.feeder.service.db.ElasticsearchService; @RunWith(MockitoJUnitRunner.class) public class TopicServiceTest { - static String DEFAULT_TOPIC_NAME = "_DL_DEFAULT_"; - - @Mock - private ApplicationConfiguration config; - - @Mock - private TopicRepository topicRepository; - - @Mock - private ElasticsearchService elasticsearchService; - - @Mock - private DbService dbService; - - @Mock - private DbRepository dbRepository; - - @Mock - private TopicNameRepository topicNameRepository; - - @InjectMocks - private TopicService topicService; - - @Test(expected = NullPointerException.class) - public void testGetTopic() throws IOException{ - List<Topic> topics = new ArrayList<>(); - Topic topic = new Topic(); - DbType dbType = new DbType(); - Set<Kafka> kafkas = new HashSet<>(); - Set<Db> dbs = new HashSet<>(); - Db db = new Db(); - db.setName("Elasticsearch"); - dbs.add(db); - - dbType.setId("ES"); - db.setDbType(dbType); - - Kafka kafka = new Kafka(); - kafka.setName("1234"); - kafkas.add(kafka); - - TopicName topicName = new TopicName(); - topicName.setId("1234"); - - topic.setTopicName(topicName); - topic.setKafkas(kafkas); - topic.setEnabled(true); - topic.setDbs(dbs); - topics.add(topic); - when(topicRepository.findAll()).thenReturn(topics); - when((ElasticsearchService)dbService.findDbStoreService(db)).thenReturn(new ElasticsearchService(db)); - topicService.findTopics(kafka,topicName.getId()); - topicService.getEnabledEffectiveTopic(kafka,topicName.getId(),true); - - } - @Test - public void testGetTopicNull() { - Topic topic = new Topic(); - TopicName topicName = new TopicName(); - topicName.setId("_DL_DEFAULT_"); - topic.setId(1234); - topic.setTopicName(topicName); - Optional<Topic> optional = Optional.of(topic); - when(topicRepository.findById(0)).thenReturn(optional); - when(config.getDefaultTopicName()).thenReturn("_DL_DEFAULT_"); - assertEquals(topic,topicService.getTopic(0)); - assertTrue(topicService.isDefaultTopic(topic)); - } - - @Test - public void testFillTopic(){ - TopicConfig tConfig = new TopicConfig(); - tConfig.setId(1234); - tConfig.setName("1234"); - tConfig.setLogin("1234"); - tConfig.setPassword("1234"); - tConfig.setEnabled(true); - tConfig.setSaveRaw(true); - tConfig.setDataFormat("1234"); - tConfig.setTtl(1234); - tConfig.setCorrelateClearedMessage(true); - tConfig.setMessageIdPath("1234"); - tConfig.setAggregateArrayPath("1234"); - tConfig.setFlattenArrayPath("1234"); - List<Integer> sinkdbs = new ArrayList<>(); - sinkdbs.add(1234); - tConfig.setSinkdbs(sinkdbs); - - Db db = new Db(); - db.setId(1234); - - TopicName topicName = new TopicName(); - topicName.setId("1234"); - - Optional<TopicName> optional = Optional.of(topicName); - when(dbRepository.findById(1234)).thenReturn(Optional.of(db)); - when(topicNameRepository.findById(tConfig.getName())).thenReturn(optional); - - topicService.fillTopicConfiguration(tConfig); - } + static String DEFAULT_TOPIC_NAME = "_DL_DEFAULT_"; -/* - @Test - public void testGetEffectiveTopic() throws IOException { - String name = "a"; - Topic topic = new Topic(name); - topic.setEnabled(true); - Set<Db> dbSet = new HashSet<>(); - dbSet.add(new Db("Elasticsearch")); - topic.setDbs(dbSet); - - when(config.getDefaultTopicName()).thenReturn(DEFAULT_TOPIC_NAME); - when(topicRepository.findById(DEFAULT_TOPIC_NAME)).thenReturn(Optional.of(topic)); - when(topicRepository.findById(name)).thenReturn(Optional.of(topic)); - when(topicRepository.findById(null)).thenReturn(Optional.empty()); - - assertEquals(topicService.getEffectiveTopic(name), topicService.getEffectiveTopic(name, false)); - - assertNotNull(topicService.getEffectiveTopic(null)); - - topicService.getEffectiveTopic(name, true); - } -*/ + @Mock + private ApplicationConfiguration config; + + @Mock + private TopicRepository topicRepository; + + @Mock + private ElasticsearchService elasticsearchService; + + @Mock + private DbService dbService; + + @Mock + private DbRepository dbRepository; + + @Mock + private TopicNameRepository topicNameRepository; + + @Mock + private KafkaRepository kafkaRepository; + + @InjectMocks + private TopicService topicService; + + @Test(expected = NullPointerException.class) + public void testGetTopicException() throws IOException { + List < Topic > topics = new ArrayList < > (); + Topic topic = new Topic(); + DbType dbType = new DbType(); + Set < Kafka > kafkas = new HashSet < > (); + Set < Db > dbs = new HashSet < > (); + Db db = new Db(); + db.setName("Elasticsearch"); + dbs.add(db); + + dbType.setId("ES"); + db.setDbType(dbType); + + Kafka kafka = new Kafka(); + kafka.setName("1234"); + kafkas.add(kafka); + + TopicName topicName = new TopicName(); + topicName.setId("1234"); + + topic.setTopicName(topicName); + topic.setKafkas(kafkas); + topic.setEnabled(true); + topic.setDbs(dbs); + topics.add(topic); + when(topicRepository.findAll()).thenReturn(topics); + when((ElasticsearchService) dbService.findDbStoreService(db)).thenReturn(new ElasticsearchService(db)); + topicService.findTopics(kafka, topicName.getId()); + topicService.getEnabledEffectiveTopic(kafka, topicName.getId(), true); + + } + + @Test + public void testGetTopic() throws IOException { + ArrayList < Topic > topics = new ArrayList < > (); + Topic topic = new Topic(); + Set < Kafka > kafkas = new HashSet < > (); + Kafka kafka = new Kafka(); + kafka.setName("1234"); + kafkas.add(kafka); + TopicName topicName = new TopicName(); + topicName.setId(DEFAULT_TOPIC_NAME); + topic.setTopicName(topicName); + topic.setKafkas(kafkas); + topics.add(topic); + when(topicRepository.findAll()).thenReturn(topics); + when(config.getDefaultTopicName()).thenReturn("_DL_DEFAULT_"); + topicService.getEnabledEffectiveTopic(new Kafka(), "test", true); + } + + @Test + public void testFindTopics() { + ArrayList < Topic > topics = new ArrayList < > (); + Topic topic = new Topic(); + Set < Kafka > kafkas = new HashSet < > (); + Kafka kafka = new Kafka(); + kafka.setName("1234"); + kafkas.add(kafka); + TopicName topicName = new TopicName(); + topicName.setId(DEFAULT_TOPIC_NAME); + topic.setTopicName(topicName); + topic.setKafkas(kafkas); + topics.add(topic); + when(topicRepository.findAll()).thenReturn(topics); + topicService.findTopics(kafka, topicName.getId()); + } + + @Test + public void testGetTopicNull() { + Topic topic = new Topic(); + TopicName topicName = new TopicName(); + topicName.setId("_DL_DEFAULT_"); + topic.setId(1234); + topic.setTopicName(topicName); + Optional < Topic > optional = Optional.of(topic); + when(topicRepository.findById(0)).thenReturn(optional); + when(config.getDefaultTopicName()).thenReturn("_DL_DEFAULT_"); + assertEquals(topic, topicService.getTopic(0)); + assertTrue(topicService.isDefaultTopic(topic)); + } + + @Test + public void testFillTopic() { + TopicConfig tConfig = new TopicConfig(); + tConfig.setId(1234); + tConfig.setName("1234"); + tConfig.setLogin("1234"); + tConfig.setPassword("1234"); + tConfig.setEnabled(true); + tConfig.setSaveRaw(true); + tConfig.setDataFormat("1234"); + tConfig.setTtl(1234); + tConfig.setCorrelateClearedMessage(true); + tConfig.setMessageIdPath("1234"); + tConfig.setAggregateArrayPath("1234"); + tConfig.setFlattenArrayPath("1234"); + List < Integer > sinkdbs = new ArrayList < > (); + sinkdbs.add(1234); + tConfig.setSinkdbs(sinkdbs); + List < Integer > kafkas = new ArrayList < > (); + kafkas.add(1); + tConfig.setKafkas(kafkas); + + Db db = new Db(); + db.setId(1234); + + TopicName topicName = new TopicName(); + topicName.setId("1234"); + + Optional < TopicName > optional = Optional.of(topicName); + when(dbRepository.findById(1234)).thenReturn(Optional.of(db)); + when(kafkaRepository.findById(1)).thenReturn(Optional.of(new Kafka())); + when(topicNameRepository.findById(tConfig.getName())).thenReturn(optional); + topicService.fillTopicConfiguration(tConfig); + } + + @Test + public void testGetDefaultTopicFromFeeder() { + when(topicRepository.findByTopicName_Id(config.getDefaultTopicName())).thenReturn(new Topic()); + topicService.getDefaultTopicFromFeeder(); + } + + @Test + public void testGetDefaultTopic() { + List < Topic > topics = new ArrayList < > (); + Topic topic = new Topic(); + DbType dbType = new DbType(); + Set < Kafka > kafkas = new HashSet < > (); + Set < Db > dbs = new HashSet < > (); + Db db = new Db(); + db.setName("Elasticsearch"); + dbs.add(db); + + dbType.setId("ES"); + db.setDbType(dbType); + + Kafka kafka = new Kafka(); + kafka.setName("1234"); + kafkas.add(kafka); + + TopicName topicName = new TopicName(); + topicName.setId(DEFAULT_TOPIC_NAME); + topic.setTopicName(topicName); + topic.setKafkas(kafkas); + topic.setEnabled(true); + topic.setDbs(dbs); + topics.add(topic); + when(config.getDefaultTopicName()).thenReturn(DEFAULT_TOPIC_NAME); + when(topicRepository.findAll()).thenReturn(topics); + topicService.getDefaultTopic(kafka); + } + + @Test + public void testIsDefaultTopic() { + assertEquals(false, topicService.isDefaultTopic(null)); + } + + /* + @Test + public void testGetEffectiveTopic() throws IOException { + String name = "a"; + Topic topic = new Topic(name); + topic.setEnabled(true); + Set<Db> dbSet = new HashSet<>(); + dbSet.add(new Db("Elasticsearch")); + topic.setDbs(dbSet); + + when(config.getDefaultTopicName()).thenReturn(DEFAULT_TOPIC_NAME); + when(topicRepository.findById(DEFAULT_TOPIC_NAME)).thenReturn(Optional.of(topic)); + when(topicRepository.findById(name)).thenReturn(Optional.of(topic)); + when(topicRepository.findById(null)).thenReturn(Optional.empty()); + + assertEquals(topicService.getEffectiveTopic(name), topicService.getEffectiveTopic(name, false)); + + assertNotNull(topicService.getEffectiveTopic(null)); + + topicService.getEffectiveTopic(name, true); + } + */ } diff --git a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/db/CouchbaseServiceTest.java b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/db/CouchbaseServiceTest.java index 2a7745b4..0abee7fc 100755..100644 --- a/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/db/CouchbaseServiceTest.java +++ b/components/datalake-handler/feeder/src/test/java/org/onap/datalake/feeder/service/db/CouchbaseServiceTest.java @@ -3,6 +3,7 @@ * ONAP : DATALAKE * ================================================================================ * Copyright (C) 2018-2019 Huawei. All rights reserved. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +21,12 @@ package org.onap.datalake.feeder.service.db; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.locks.ReentrantReadWriteLock; import org.jetbrains.annotations.NotNull; import org.json.JSONObject; @@ -29,6 +34,8 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.onap.datalake.feeder.config.ApplicationConfiguration; import org.onap.datalake.feeder.domain.Db; @@ -46,111 +53,129 @@ import com.couchbase.mock.client.MockClient; @RunWith(MockitoJUnitRunner.class) public class CouchbaseServiceTest { - protected final BucketConfiguration bucketConfiguration = new BucketConfiguration(); - protected MockClient mockClient; - protected CouchbaseMock couchbaseMock; - protected Cluster cluster; - protected com.couchbase.client.java.Bucket bucket; - protected int carrierPort; - protected int httpPort; - - protected void getPortInfo(String bucket) throws Exception { - httpPort = couchbaseMock.getHttpPort(); - carrierPort = couchbaseMock.getCarrierPort(bucket); - } - - protected void createMock(@NotNull String name, @NotNull String password) throws Exception { - bucketConfiguration.numNodes = 1; - bucketConfiguration.numReplicas = 1; - bucketConfiguration.numVBuckets = 1024; - bucketConfiguration.name = name; - bucketConfiguration.type = Bucket.BucketType.COUCHBASE; - bucketConfiguration.password = password; - ArrayList<BucketConfiguration> configList = new ArrayList<BucketConfiguration>(); - configList.add(bucketConfiguration); - couchbaseMock = new CouchbaseMock(0, configList); - couchbaseMock.start(); - couchbaseMock.waitForStartup(); - } - - protected void createClient() { - cluster = CouchbaseCluster.create(DefaultCouchbaseEnvironment.builder().bootstrapCarrierDirectPort(carrierPort).bootstrapHttpDirectPort(httpPort).build(), "couchbase://127.0.0.1"); - bucket = cluster.openBucket("default"); - } - - @Before - public void setUp() throws Exception { - createMock("default", ""); - getPortInfo("default"); - createClient(); - } - - @After - public void tearDown() { - if (cluster != null) { - cluster.disconnect(); - } - if (couchbaseMock != null) { - couchbaseMock.stop(); - } - if (mockClient != null) { - mockClient.shutdown(); - } - } - - @Test - public void testSaveJsonsWithTopicId() { - ApplicationConfiguration appConfig = new ApplicationConfiguration(); - appConfig.setTimestampLabel("datalake_ts_"); - - String text = "{ data: { data2 : { value : 'hello'}}}"; - - JSONObject json = new JSONObject(text); - - Topic topic = TestUtil.newTopic("test getMessageId"); - topic.setMessageIdPath("/data/data2/value"); - List<JSONObject> jsons = new ArrayList<>(); - json.put(appConfig.getTimestampLabel(), 1234); - jsons.add(json); - CouchbaseService couchbaseService = new CouchbaseService(new Db()); - couchbaseService.bucket = bucket; - couchbaseService.config = appConfig; - - couchbaseService.init(); - EffectiveTopic effectiveTopic = new EffectiveTopic(topic, "test"); - couchbaseService.saveJsons(effectiveTopic, jsons); - - } - - @Test - public void testSaveJsonsWithOutTopicId() { - ApplicationConfiguration appConfig = new ApplicationConfiguration(); - appConfig.setTimestampLabel("datalake_ts_"); - - String text = "{ data: { data2 : { value : 'hello'}}}"; - - JSONObject json = new JSONObject(text); - - Topic topic = TestUtil.newTopic("test getMessageId"); - List<JSONObject> jsons = new ArrayList<>(); - json.put(appConfig.getTimestampLabel(), 1234); - jsons.add(json); - CouchbaseService couchbaseService = new CouchbaseService(new Db()); - couchbaseService.bucket = bucket; - couchbaseService.config = appConfig; - - couchbaseService.init(); - EffectiveTopic effectiveTopic = new EffectiveTopic(topic, "test"); - couchbaseService.saveJsons(effectiveTopic, jsons); - } - - @Test - public void testCleanupBucket() { - // CouchbaseService couchbaseService = new CouchbaseService(new Db()); - // couchbaseService.bucket = bucket; - // ApplicationConfiguration appConfig = new ApplicationConfiguration(); - // couchbaseService.config = appConfig; - // couchbaseService.cleanUp(); - } - -}
\ No newline at end of file + protected final BucketConfiguration bucketConfiguration = new BucketConfiguration(); + protected MockClient mockClient; + protected CouchbaseMock couchbaseMock; + protected Cluster cluster; + protected com.couchbase.client.java.Bucket bucket; + protected int carrierPort; + protected int httpPort; + + @InjectMocks + private CouchbaseService couchbaseService; + + @Mock + private ApplicationConfiguration config; + + @Before + public void init() throws NoSuchFieldException, IllegalAccessException { + Db db = TestUtil.newDb("Couchbasedb"); + db.setDatabase("database"); + db.setLogin("login"); + couchbaseService = new CouchbaseService(db); + + Field configField = CouchbaseService.class.getDeclaredField("config"); + configField.setAccessible(true); + configField.set(couchbaseService, config); + couchbaseService.bucket = bucket; + couchbaseService.init(); + } + + protected void getPortInfo(String bucket) throws Exception { + httpPort = couchbaseMock.getHttpPort(); + carrierPort = couchbaseMock.getCarrierPort(bucket); + } + + protected void createMock(@NotNull String name, @NotNull String password) throws Exception { + bucketConfiguration.numNodes = 1; + bucketConfiguration.numReplicas = 1; + bucketConfiguration.numVBuckets = 1024; + bucketConfiguration.name = name; + bucketConfiguration.type = Bucket.BucketType.COUCHBASE; + bucketConfiguration.password = password; + ArrayList < BucketConfiguration > configList = new ArrayList < BucketConfiguration > (); + configList.add(bucketConfiguration); + couchbaseMock = new CouchbaseMock(0, configList); + couchbaseMock.start(); + couchbaseMock.waitForStartup(); + } + + protected void createClient() { + cluster = CouchbaseCluster.create(DefaultCouchbaseEnvironment.builder().bootstrapCarrierDirectPort(carrierPort) + .bootstrapHttpDirectPort(httpPort).build(), "couchbase://127.0.0.1"); + bucket = cluster.openBucket("default"); + } + + @Before + public void setUp() throws Exception { + createMock("default", ""); + getPortInfo("default"); + createClient(); + } + + @After + public void tearDown() { + if (cluster != null) { + cluster.disconnect(); + } + if (couchbaseMock != null) { + couchbaseMock.stop(); + } + if (mockClient != null) { + mockClient.shutdown(); + } + } + + @Test + public void testSaveJsonsWithTopicId() { + ApplicationConfiguration appConfig = new ApplicationConfiguration(); + appConfig.setTimestampLabel("datalake_ts_"); + + String text = "{ data: { data2 : { value : 'hello'}}}"; + + JSONObject json = new JSONObject(text); + + Topic topic = TestUtil.newTopic("test getMessageId"); + topic.setMessageIdPath("/data/data2/value"); + List < JSONObject > jsons = new ArrayList < > (); + json.put(appConfig.getTimestampLabel(), 1234); + jsons.add(json); + CouchbaseService couchbaseService = new CouchbaseService(new Db()); + couchbaseService.bucket = bucket; + couchbaseService.config = appConfig; + + couchbaseService.init(); + EffectiveTopic effectiveTopic = new EffectiveTopic(topic, "test"); + couchbaseService.saveJsons(effectiveTopic, jsons); + + } + + @Test + public void testSaveJsonsWithOutTopicId() { + ApplicationConfiguration appConfig = new ApplicationConfiguration(); + appConfig.setTimestampLabel("datalake_ts_"); + + String text = "{ data: { data2 : { value : 'hello'}}}"; + + JSONObject json = new JSONObject(text); + + Topic topic = TestUtil.newTopic("test getMessageId"); + List < JSONObject > jsons = new ArrayList < > (); + json.put(appConfig.getTimestampLabel(), 1234); + jsons.add(json); + CouchbaseService couchbaseService = new CouchbaseService(new Db()); + couchbaseService.bucket = bucket; + couchbaseService.config = appConfig; + + couchbaseService.init(); + EffectiveTopic effectiveTopic = new EffectiveTopic(topic, "test"); + couchbaseService.saveJsons(effectiveTopic, jsons); + } + + @Test + public void testCleanupBucket() { + when(config.getShutdownLock()).thenReturn(new ReentrantReadWriteLock()); + couchbaseService.cleanUp(); + } + +} diff --git a/components/datalake-handler/pom.xml b/components/datalake-handler/pom.xml index 2a45c023..0db38d14 100644 --- a/components/datalake-handler/pom.xml +++ b/components/datalake-handler/pom.xml @@ -1,267 +1,280 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- +============LICENSE_START======================================================= + Copyright (c) 2020 China Mobile. All rights reserved. + Copyright (C) 2022 Wipro Limited. 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"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.onap.oparent</groupId> - <artifactId>oparent</artifactId> - <version>2.0.0</version> - </parent> - - <groupId>org.onap.dcaegen2.services.components</groupId> - <artifactId>datalake-handler</artifactId> - <version>1.1.1-SNAPSHOT</version> - <packaging>pom</packaging> - - <name>dcaegen2-service-datalake-handler</name> - - <modules> - <module>feeder</module> - <module>admin</module> - <module>collector</module> - <module>des</module> - </modules> - - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - <java.version>11</java.version> - - <mongojava.version>3.10.1</mongojava.version> - <springboot.version>2.1.0.RELEASE</springboot.version> - <springcouchbase.version>3.1.2.RELEASE</springcouchbase.version> - <jackson.version>2.9.8</jackson.version> - <kafka.version>2.0.0</kafka.version> - <elasticsearchjava.version>7.1.1</elasticsearchjava.version> - <hadoop.version>3.2.0</hadoop.version> - - <sonar.coverage.jacoco.xmlReportPaths> - ${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml - </sonar.coverage.jacoco.xmlReportPaths> - </properties> - - <dependencyManagement> - <dependencies> - - <dependency> - <groupId>org.apache.hadoop</groupId> - <artifactId>hadoop-client</artifactId> - <version>${hadoop.version}</version> - </dependency> - - <dependency> - <groupId>org.mariadb.jdbc</groupId> - <artifactId>mariadb-java-client</artifactId> - <version>2.4.1</version> - </dependency> - - <dependency> - <groupId>commons-io</groupId> - <artifactId>commons-io</artifactId> - <version>2.6</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-core</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-annotations</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-databind</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.dataformat</groupId> - <artifactId>jackson-dataformat-yaml</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.fasterxml.jackson.dataformat</groupId> - <artifactId>jackson-dataformat-xml</artifactId> - <version>${jackson.version}</version> - </dependency> - - <dependency> - <groupId>com.google.code.gson</groupId> - <artifactId>gson</artifactId> - <version>2.8.2</version> - </dependency> - - <dependency> - <groupId>io.druid</groupId> - <artifactId>tranquility-core_2.11</artifactId> - <version>0.8.3</version> - </dependency> - - <dependency> - <groupId>javax.servlet</groupId> - <artifactId>javax.servlet-api</artifactId> - <version>4.0.1</version> - <!--scope>provided</scope --> - </dependency> - - <dependency> - <groupId>org.apache.kafka</groupId> - <artifactId>kafka-clients</artifactId> - <version>${kafka.version}</version> - </dependency> - - <dependency> - <groupId>org.apache.velocity</groupId> - <artifactId>velocity-engine-core</artifactId> - <version>2.0</version> - </dependency> - - <dependency> - <groupId>org.json</groupId> - <artifactId>json</artifactId> - <version>20180813</version> - </dependency> - - <dependency> - <groupId>org.mongodb</groupId> - <artifactId>mongo-java-driver</artifactId> - <version>${mongojava.version}</version> - </dependency> - - <dependency> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - <version>1.18.2</version> - </dependency> - - <dependency> - <groupId>org.springframework.data</groupId> - <artifactId>spring-data-couchbase</artifactId> - <version>${springcouchbase.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-web</artifactId> - <version>${springboot.version}</version> - </dependency> - - <!-- tag::actuator[] --> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-actuator</artifactId> - <version>${springboot.version}</version> - </dependency> - <!-- end::actuator[] --> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-jpa</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-couchbase</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-mongodb</artifactId> - <version>${springboot.version}</version> - </dependency> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-rest</artifactId> - <version>${springboot.version}</version> - </dependency> - <!-- tag::tests[] --> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-test</artifactId> - <version>${springboot.version}</version> - <scope>test</scope> - </dependency> - <!-- end::tests[] --> - - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-configuration-processor</artifactId> - <version>${springboot.version}</version> - <optional>true</optional> - </dependency> - - <dependency> - <groupId>org.elasticsearch.client</groupId> - <artifactId>elasticsearch-rest-high-level-client</artifactId> - <version>${elasticsearchjava.version}</version> - </dependency> - - </dependencies> - </dependencyManagement> - - <build> - <plugins> - <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> - <version>${springboot.version}</version> - <executions> - <execution> - <goals> - <goal>repackage</goal> - </goals> - </execution> - </executions> - </plugin> - - <plugin> - <artifactId>maven-failsafe-plugin</artifactId> - <executions> - <execution> - <goals> - <goal>integration-test</goal> - <goal>verify</goal> - </goals> - </execution> - </executions> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-eclipse-plugin</artifactId> - <configuration> - <downloadSources>true</downloadSources> - <downloadJavadocs>true</downloadJavadocs> - </configuration> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-deploy-plugin</artifactId> - <version>2.8</version> - <configuration> - <skip>true</skip> - </configuration> - </plugin> - - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.8.0</version> - </plugin> - - </plugins> - </build> + 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.oparent</groupId> + <artifactId>oparent</artifactId> + <version>2.0.0</version> + </parent> + + <groupId>org.onap.dcaegen2.services.components</groupId> + <artifactId>datalake-handler</artifactId> + <version>1.1.2-SNAPSHOT</version> + <packaging>pom</packaging> + + <name>dcaegen2-service-datalake-handler</name> + + <modules> + <module>feeder</module> + <module>admin</module> + <module>des</module> + </modules> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <java.version>11</java.version> + + <mongojava.version>3.10.1</mongojava.version> + <springboot.version>2.1.0.RELEASE</springboot.version> + <springcouchbase.version>3.1.2.RELEASE</springcouchbase.version> + <jackson.version>2.9.8</jackson.version> + <kafka.version>2.0.0</kafka.version> + <elasticsearchjava.version>7.1.1</elasticsearchjava.version> + <hadoop.version>3.2.0</hadoop.version> + + <sonar.coverage.jacoco.xmlReportPaths> + ${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml + </sonar.coverage.jacoco.xmlReportPaths> + </properties> + + <dependencyManagement> + <dependencies> + + <dependency> + <groupId>org.apache.hadoop</groupId> + <artifactId>hadoop-client</artifactId> + <version>${hadoop.version}</version> + </dependency> + + <dependency> + <groupId>org.mariadb.jdbc</groupId> + <artifactId>mariadb-java-client</artifactId> + <version>2.4.1</version> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.6</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-yaml</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-xml</artifactId> + <version>${jackson.version}</version> + </dependency> + + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.8.2</version> + </dependency> + + <dependency> + <groupId>io.druid</groupId> + <artifactId>tranquility-core_2.11</artifactId> + <version>0.8.3</version> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>4.0.1</version> + <!--scope>provided</scope --> + </dependency> + + <dependency> + <groupId>org.apache.kafka</groupId> + <artifactId>kafka-clients</artifactId> + <version>${kafka.version}</version> + </dependency> + + <dependency> + <groupId>org.apache.velocity</groupId> + <artifactId>velocity-engine-core</artifactId> + <version>2.0</version> + </dependency> + + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20180813</version> + </dependency> + + <dependency> + <groupId>org.mongodb</groupId> + <artifactId>mongo-java-driver</artifactId> + <version>${mongojava.version}</version> + </dependency> + + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.2</version> + </dependency> + + <dependency> + <groupId>org.springframework.data</groupId> + <artifactId>spring-data-couchbase</artifactId> + <version>${springcouchbase.version}</version> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <version>${springboot.version}</version> + </dependency> + + <!-- tag::actuator[] --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + <version>${springboot.version}</version> + </dependency> + <!-- end::actuator[] --> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-jpa</artifactId> + <version>${springboot.version}</version> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-couchbase</artifactId> + <version>${springboot.version}</version> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-mongodb</artifactId> + <version>${springboot.version}</version> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-rest</artifactId> + <version>${springboot.version}</version> + </dependency> + <!-- tag::tests[] --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <version>${springboot.version}</version> + <scope>test</scope> + </dependency> + <!-- end::tests[] --> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-configuration-processor</artifactId> + <version>${springboot.version}</version> + <optional>true</optional> + </dependency> + + <dependency> + <groupId>org.elasticsearch.client</groupId> + <artifactId>elasticsearch-rest-high-level-client</artifactId> + <version>${elasticsearchjava.version}</version> + </dependency> + + </dependencies> + </dependencyManagement> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <version>${springboot.version}</version> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-eclipse-plugin</artifactId> + <configuration> + <downloadSources>true</downloadSources> + <downloadJavadocs>true</downloadJavadocs> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <version>2.8</version> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.0</version> + </plugin> + + </plugins> + </build> </project> diff --git a/components/datalake-handler/version.properties b/components/datalake-handler/version.properties index 9461aa95..e6eb586c 100644 --- a/components/datalake-handler/version.properties +++ b/components/datalake-handler/version.properties @@ -1,6 +1,6 @@ major=1 minor=1 -patch=1 +patch=2 base_version=${major}.${minor}.${patch} release_version=${base_version} snapshot_version=${base_version}-SNAPSHOT diff --git a/components/kpi-computation-ms/Changelog.md b/components/kpi-computation-ms/Changelog.md index a094d17b..57c0611b 100644 --- a/components/kpi-computation-ms/Changelog.md +++ b/components/kpi-computation-ms/Changelog.md @@ -5,6 +5,38 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [1.2.0] +### Changed +* KPI MS - Vulnerability updates (DCAEGEN2-3354) + +## [1.0.11] +### Changed +* Fix bug in wrong SNSSAI value being appended with MeasType string (DCAEGEN2-3310) + +## [1.0.10] +### Changed +* Revert commit - KPI MS - Switch from Cambria library to dmaap-client library (dcaegen2/sdk) (DCAEGEN2-3180) + +## [1.0.9] +### Changed +* KPI MS - Vulnerability updates (DCAEGEN2-3216) + +## [1.0.8] +### Changed +* KPI MS - Switch from Cambria library to dmaap-client library (dcaegen2/sdk) (DCAEGEN2-3180) + +## [1.0.7] +### Changed +* Append SNSSAI with MeasType string and handle multiple operands (DCAEGEN2-3243) + +## [1.0.6] +### Changed +* CodeCoverage improvement for dcaegen2-services-kpi-computation-ms (DCAEGEN2-3162) + +## [1.0.5] +### Changed +* Enhancements to KPI Computation MS for Kohn Release (DCAEGEN2-3193) + ## [1.0.4] ### Changed * Fix security vulnerability issues (DCAEGEN2-3047) diff --git a/components/kpi-computation-ms/lombok.config b/components/kpi-computation-ms/lombok.config new file mode 100644 index 00000000..df71bb6a --- /dev/null +++ b/components/kpi-computation-ms/lombok.config @@ -0,0 +1,2 @@ +config.stopBubbling = true +lombok.addLombokGeneratedAnnotation = true diff --git a/components/kpi-computation-ms/pom.xml b/components/kpi-computation-ms/pom.xml index c67ece88..63070a63 100644 --- a/components/kpi-computation-ms/pom.xml +++ b/components/kpi-computation-ms/pom.xml @@ -3,6 +3,7 @@ ~ ============LICENSE_START======================================================= ~ Copyright (c) 2021 China Mobile. All rights reserved. ~ Copyright (c) 2021-2022 Wipro Limited. + ~ Copyright (C) 2023 Deutsche Telekom AG. 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. @@ -29,7 +30,7 @@ <groupId>org.onap.dcaegen2.services.components</groupId> <artifactId>kpi-ms</artifactId> - <version>1.0.4-SNAPSHOT</version> + <version>1.2.0-SNAPSHOT</version> <name>dcaegen2-services-kpi-computation-ms</name> <description>Kpi ms</description> <packaging>jar</packaging> @@ -51,11 +52,11 @@ ${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml </sonar.coverage.jacoco.xmlReportPaths> <lombok.version>1.18.4</lombok.version> - <undertow.version>2.2.14.Final</undertow.version> + <undertow.version>2.3.0.Final</undertow.version> <xml.version>2.3.1</xml.version> <jaxb.version>2.3.0.1</jaxb.version> <docker.repository>nexus3.onap.org:10003</docker.repository> - <spring.version>5.3.14</spring.version> + <spring.version>5.3.25</spring.version> <junit.version>5.3.2</junit.version> <mockito.version>2.23.4</mockito.version> <mockito-ju5-ext.version>2.23.4</mockito-ju5-ext.version> @@ -89,13 +90,13 @@ <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> - </dependency> + </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> - <dependency> + <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> @@ -111,7 +112,6 @@ <artifactId>cbs-client</artifactId> <version>${sdk.version}</version> </dependency> - <dependency> <groupId>org.onap.dcaegen2.services.sdk.security.crypt</groupId> <artifactId>crypt-password</artifactId> @@ -132,7 +132,7 @@ <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> - <version>2.12.6</version> + <version>2.14.1</version> </dependency> <dependency> <groupId>net.javacrumbs.json-unit</groupId> @@ -143,7 +143,7 @@ <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> - <version>2.11.0</version> + <version>2.14.1</version> </dependency> <dependency> <groupId>javax.json</groupId> @@ -161,23 +161,20 @@ </exclusion> </exclusions> </dependency> - <dependency> <groupId>org.functionaljava</groupId> <artifactId>functionaljava</artifactId> <version>3.0</version> </dependency> - <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> - <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> - <version>9.4.41.v20210516</version> + <version>11.0.12</version> </dependency> <dependency> <groupId>javax.xml.bind</groupId> @@ -235,7 +232,6 @@ <artifactId>commons-lang3</artifactId> <version>3.7</version> </dependency> - <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> @@ -248,7 +244,6 @@ <version>${mockito-ju5-ext.version}</version> <scope>test</scope> </dependency> - <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> @@ -297,11 +292,11 @@ <artifactId>openpojo</artifactId> <version>0.8.10</version> </dependency> - <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core --> + <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> - <version>1.2.10</version> + <version>1.4.5</version> </dependency> </dependencies> @@ -345,7 +340,6 @@ <directory>${project.basedir}</directory> </resource> </resources> - <runs> <!-- Maven is loosing file permissions during artifacts copy --> <run>export trustpass=`cat /opt/app/kpims/etc/cert/trust.pass`</run> diff --git a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/KpiComputation.java b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/KpiComputation.java index d3493528..4dd2601e 100644 --- a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/KpiComputation.java +++ b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/KpiComputation.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. * Copyright (C) 2021 Deutsche Telekom AG. All rights reserved. + * Copyright (C) 2022 Wipro Limited. 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,6 +22,7 @@ package org.onap.dcaegen2.kpi.computation; +import java.lang.String; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; @@ -28,7 +30,7 @@ import java.util.List; import java.util.LinkedList; import java.util.Map; import java.util.Optional; - +import java.util.stream.Collectors; import org.apache.commons.lang.StringUtils; import org.onap.dcaegen2.kpi.config.ControlLoopSchemaType; @@ -44,6 +46,7 @@ import org.onap.dcaegen2.kpi.models.Configuration; import org.onap.dcaegen2.kpi.models.MeasDataCollection; import org.onap.dcaegen2.kpi.models.MeasInfo; import org.onap.dcaegen2.kpi.models.MeasResult; +import org.onap.dcaegen2.kpi.models.MeasTypes; import org.onap.dcaegen2.kpi.models.MeasValues; import org.onap.dcaegen2.kpi.models.Perf3gppFields; import org.onap.dcaegen2.kpi.models.PerformanceEvent; @@ -62,6 +65,7 @@ import org.slf4j.LoggerFactory; public class KpiComputation { private static Logger logger = LoggerFactory.getLogger(KpiComputation.class); + String value = ""; /** * do KPI computation. @@ -103,6 +107,32 @@ public class KpiComputation { MeasDataCollection measDataCollection = Optional.of(pmEvent).map(PerformanceEvent::getPerf3gppFields) .map(Perf3gppFields::getMeasDataCollection) .orElseThrow(() -> new KpiComputationException("Required Field: MeasData not present")); + + List<MeasInfo> measInfoList = Optional.of(pmEvent).map(PerformanceEvent::getPerf3gppFields) + .map(Perf3gppFields::getMeasDataCollection) + .map(MeasDataCollection::getMeasInfoList) + .orElseThrow(() -> new KpiComputationException("Required Field: MeasInfoList not present")); + + + StringBuilder sb = new StringBuilder(); + for(MeasInfo measInfo: measInfoList){ + List<String> measTypes = measInfo.getMeasTypes().getMeasTypesList(); + if(!measTypes.isEmpty()){ + String anyString = measTypes.get(0); + if(anyString.contains(".")) + { + value = anyString.substring(anyString.lastIndexOf(".")+ 1); + logger.info("The value string is {}",value); + } + else { + logger.info( "MeasType does not contain Snssai separated by a dot"); + } + } + else{ + logger.info("MeasTypesList is empty"); + } + } + // Do computation for each KPI List<VesEvent> events = new LinkedList<>(); List<Kpi> kpis = methodForKpi.getKpis(); @@ -114,7 +144,12 @@ public class KpiComputation { } ControlLoopSchemaType schemaType = methodForKpi.getControlLoopSchemaType(); - String measType = k.getMeasType(); + sb.append(k.getMeasType()); + sb.append("."); + sb.append(value); + String measType = sb.toString(); + logger.info("measType is {}", measType); + Operation operation = k.getOperation(); List<VesEvent> kpiVesEvent = CommandHandler.handle(operation.value, pmEvent, schemaType, @@ -143,10 +178,9 @@ public class KpiComputation { flag = false; for (String operand : operands) { List<String> measTypesList = measInfo.getMeasTypes().getMeasTypesList(); - String measValue = measTypesList.stream() + List<String> measValue = measTypesList.stream() .filter(s -> StringUtils.substring(s, 0, operand.length()).equalsIgnoreCase(operand)) - .findFirst() - .orElse(null); + .collect(Collectors.toList()); if (measValue == null) { flag = true; } @@ -156,32 +190,35 @@ public class KpiComputation { curatedMeasInfoList.add(measInfo); } } - + for (String operand: operands) { String key = null; List<KpiOperand> kpiOperands = new ArrayList<>(); for (MeasInfo m: curatedMeasInfoList) { List<String> measTypesList = m.getMeasTypes().getMeasTypesList(); - String measValue = measTypesList.stream() + List<String> measValueList = measTypesList.stream() .filter(s -> StringUtils.substring(s, 0, operand.length()).equalsIgnoreCase(operand)) - .findFirst() - .orElse(null); - if (measValue != null) { + .collect(Collectors.toList()); + if (measValueList != null) { + for(String measValue:measValueList){ key = new StringBuilder().append(operand).toString(); - int index = measTypesList.indexOf(measValue); - MeasValues measValues = m.getMeasValuesList().stream().findFirst().orElse(null); - List<MeasResult> measResults = measValues.getMeasResults(); - String measObjInstId = measValues.getMeasObjInstId(); - MeasResult measResult = measResults.stream() - .filter(v -> v.getPvalue() == (index + 1)) - .findFirst() - .orElse(null); - if (measResult != null) { - KpiOperand newKpiOperand = new KpiOperand(measObjInstId, new BigDecimal(measResult.getSvalue())); - kpiOperands.add(newKpiOperand); - } else { - logger.info("measResults mis-matched - incorrect ves msg construction"); + int index = measTypesList.indexOf(measValue); + List<MeasValues> measValuesList = m.getMeasValuesList(); + for ( MeasValues measValues : measValuesList) { + List<MeasResult> measResults = measValues.getMeasResults(); + String measObjInstId = measValues.getMeasObjInstId(); + MeasResult measResult = measResults.stream() + .filter(v -> v.getPvalue() == (index + 1)) + .findFirst() + .orElse(null); + if (measResult != null) { + KpiOperand newKpiOperand = new KpiOperand(measObjInstId, new BigDecimal(measResult.getSvalue())); + kpiOperands.add(newKpiOperand); + } else { + logger.info("measResults mis-matched - incorrect ves msg construction"); + } } + } } } if (kpiOperands.size() <= 0) { diff --git a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/RatioKpiComputation.java b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/RatioKpiComputation.java index 96559a4c..8fbbb1d9 100644 --- a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/RatioKpiComputation.java +++ b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/RatioKpiComputation.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 Deutsche Telekom AG. All rights reserved. + * Copyright (C) 2022 Wipro Limited. 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. @@ -27,9 +28,11 @@ import java.util.List; import java.util.LinkedList; import java.util.ListIterator; import java.util.Map; +import java.util.Optional; import java.util.UUID; import org.onap.dcaegen2.kpi.config.ControlLoopSchemaType; +import org.onap.dcaegen2.kpi.exception.KpiComputationException; import org.onap.dcaegen2.kpi.models.CommonEventHeader; import org.onap.dcaegen2.kpi.models.KpiOperand; import org.onap.dcaegen2.kpi.models.MeasDataCollection; @@ -69,13 +72,67 @@ public class RatioKpiComputation extends BaseKpiComputation { while (listIteratorK1.hasNext()) { final KpiOperand myK1 = listIteratorK1.next(); final KpiOperand myK2 = listIteratorK2.next(); + + String value = myK1.getValue().toString(); + List<MeasInfo> measInfoList = Optional.of(pmEvent).map(PerformanceEvent::getPerf3gppFields) + .map(Perf3gppFields::getMeasDataCollection) + .map(MeasDataCollection::getMeasInfoList) + .orElseThrow(() -> new KpiComputationException("MeasInfoList not present")); + + int pValue = 0; + + for(MeasInfo meas: measInfoList){ + for(MeasValues measValue: meas.getMeasValuesList()){ + for(MeasResult measResult: measValue.getMeasResults()){ + String s = measResult.getSvalue(); + if(s.equalsIgnoreCase(value)){ + pValue = measResult.getPvalue(); + } + } + } + } + + String operand = null; + + for(MeasInfo measInfo: measInfoList){ + List<String> measTypesList = measInfo.getMeasTypes().getMeasTypesList(); + if(!measTypesList.isEmpty()){ + for(String s : measTypesList){ + int index = measTypesList.indexOf(s); + if( index == (pValue-1)){ + operand = s; + } + } + } + } + + String snssai = ""; + if(!operand.isEmpty() && operand.contains(".")){ + snssai = operand.substring(operand.lastIndexOf(".") + 1); + } + else{ + logger.info("operand is empty"); + } + + String meas = ""; + if(!measType.isEmpty()){ + meas = measType.substring( 0, measType.lastIndexOf(".") + 1); + } + else{ + logger.info("measType is empty"); + } + String measTypes = meas + snssai; + if (myK2.getValue().compareTo(BigDecimal.ZERO) != 0) { final BigDecimal result = myK1.getValue().multiply(new BigDecimal("100")) .divide(myK2.getValue(), 0, RoundingMode.HALF_UP); - vesEvents.add(generateVesEvent(pmEvent, schemaType.toString(), result, measType)); + vesEvents.add(generateVesEvent(pmEvent, schemaType.toString(), result, measTypes)); } } } + else { + throw new KpiComputationException("Insufficient number of operands to perform Ratio computation"); + } return vesEvents; } } diff --git a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/SumRatioKpiComputation.java b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/SumRatioKpiComputation.java index a031abde..1c7436aa 100644 --- a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/SumRatioKpiComputation.java +++ b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/computation/SumRatioKpiComputation.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2022 Deutsche Telekom AG. All rights reserved. +* Copyright (C) 2022 Wipro Limited. 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. @@ -29,6 +30,7 @@ import java.util.ListIterator; import java.util.Map; import org.onap.dcaegen2.kpi.config.ControlLoopSchemaType; +import org.onap.dcaegen2.kpi.exception.KpiComputationException; import org.onap.dcaegen2.kpi.models.CommonEventHeader; import org.onap.dcaegen2.kpi.models.KpiOperand; import org.onap.dcaegen2.kpi.models.MeasDataCollection; @@ -78,6 +80,9 @@ public class SumRatioKpiComputation extends BaseKpiComputation { BigDecimal result = sumK1.multiply(new BigDecimal("100")).divide(sumK2, 0, RoundingMode.HALF_UP); vesEvents.add(generateVesEvent(pmEvent, schemaType.toString(), result, measType)); } + else { + throw new KpiComputationException("Insufficient number of operands to perform SumRatio computation"); + } return vesEvents; } } diff --git a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/DmaapClient.java b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/DmaapClient.java index d6e17d62..4d48d975 100644 --- a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/DmaapClient.java +++ b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/DmaapClient.java @@ -1,6 +1,8 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. + * Copyright (C) 2022 Wipro Limited. + * Copyright (C) 2023 Deutsche Telekom AG. 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. @@ -27,7 +29,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import org.onap.dcaegen2.kpi.models.Configuration; import org.onap.dcaegen2.kpi.utils.DmaapUtils; diff --git a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/KpiDmaapClient.java b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/KpiDmaapClient.java index 5e8733e9..fb96787b 100644 --- a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/KpiDmaapClient.java +++ b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/KpiDmaapClient.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NewPmNotification.java b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NewPmNotification.java index fcd5e259..4102d60a 100644 --- a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NewPmNotification.java +++ b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NewPmNotification.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. + * Copyright (C) 2023 Deutsche Telekom AG. 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,7 +21,7 @@ package org.onap.dcaegen2.kpi.dmaap; -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct; import org.springframework.stereotype.Component; diff --git a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NotificationConsumer.java b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NotificationConsumer.java index d7e3376a..fbf8bc7e 100644 --- a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NotificationConsumer.java +++ b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NotificationConsumer.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NotificationProducer.java b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NotificationProducer.java index 628f3d0e..34255431 100644 --- a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NotificationProducer.java +++ b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/dmaap/NotificationProducer.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/utils/DmaapUtils.java b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/utils/DmaapUtils.java index bf252520..2f1e19cc 100644 --- a/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/utils/DmaapUtils.java +++ b/components/kpi-computation-ms/src/main/java/org/onap/dcaegen2/kpi/utils/DmaapUtils.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/computation/KpiComputationTest.java b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/computation/KpiComputationTest.java index 1ed65572..c5e0dc31 100644 --- a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/computation/KpiComputationTest.java +++ b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/computation/KpiComputationTest.java @@ -2,6 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. * Copyright (C) 2022 Deutsche Telekom AG. All rights reserved. + * Copyright (C) 2022 Wipro Limited. 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. @@ -25,12 +26,21 @@ import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.Spy; import org.onap.dcaegen2.kpi.computation.KpiComputation; +import org.onap.dcaegen2.kpi.exception.KpiComputationException; import org.onap.dcaegen2.kpi.models.Configuration; +import org.onap.dcaegen2.kpi.models.KpiOperand; +import org.onap.dcaegen2.kpi.models.MeasDataCollection; import org.onap.dcaegen2.kpi.models.VesEvent; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.reflect.Whitebox; import java.math.BigDecimal; import java.math.RoundingMode; @@ -40,15 +50,18 @@ public class KpiComputationTest { private static final String KPI_CONFIG_FILE = "kpi/kpi_config.json"; private static final String VES_MESSAGE_FILE = "kpi/ves_message.json"; private static final String KPI_CONFIG_RATIO_FILE = "kpi/kpi_config_ratio.json"; + private static final String KPI_CONFIG_SLICING_RATIO_FILE = "kpi/kpi_config_slicing.json"; private static final String KPI_CONFIG_SUMRATIO_FILE = "kpi/kpi_config_sumratio.json"; private static final String VES_MESSAGE_EMPTY_FILE = "kpi/ves_message_empty.json"; private static final String VES_MESSAGE_NULL_FILE = "kpi/ves_message_null.json"; + private static final String VES_MESSAGE_SLICING_FILE = "kpi/ves_message_slicing.json"; private static final String VES_MESSAGE_EVENTNAME_FILE = "kpi/ves_message_eventname.json"; + private static final String VES_MESSAGE_FIELD_MISSING ="kpi/ves_message_missing_field.json"; + private static final String VES_MESSAGE_MULTIPLESNSSAI_SLICING_FILE = "kpi/ves_message_slicing_multiplesnssai.json"; @Test public void testKpiComputation() { - String strKpiConfig = FileUtils.getFileContents(KPI_CONFIG_FILE); String vesMessage = FileUtils.getFileContents(VES_MESSAGE_FILE); @@ -75,6 +88,45 @@ public class KpiComputationTest { } @Test + public void testKpiComputationSlicingRatio() { + String strKpiConfigRatio = FileUtils.getFileContents(KPI_CONFIG_SLICING_RATIO_FILE); + String vesMessage = FileUtils.getFileContents(VES_MESSAGE_SLICING_FILE); + Configuration config = mock(Configuration.class); + when(config.getKpiConfig()).thenReturn(strKpiConfigRatio); + List<VesEvent> vesList = new KpiComputation().checkAndDoComputation(vesMessage, config); + VesEvent vesEvent = vesList.get(0); + assertEquals(vesEvent.getEvent().getPerf3gppFields().getMeasDataCollection().getMeasInfoList().get(0) + .getMeasValuesList().get(0).getMeasResults().get(0).getSvalue(), "158"); + } + + @Test + public void testKpiComputationSlicingMeasType() { + String strKpiConfigRatio = FileUtils.getFileContents(KPI_CONFIG_SLICING_RATIO_FILE); + String vesMessage = FileUtils.getFileContents(VES_MESSAGE_SLICING_FILE); + Configuration config = mock(Configuration.class); + when(config.getKpiConfig()).thenReturn(strKpiConfigRatio); + List<VesEvent> vesList = new KpiComputation().checkAndDoComputation(vesMessage, config); + VesEvent vesEvent = vesList.get(0); + assertEquals(vesEvent.getEvent().getPerf3gppFields().getMeasDataCollection().getMeasInfoList().get(0) + .getMeasTypes().getMeasTypesList().get(0), "PDUSessionEstSR.01-B989BD"); + } + + @Test + public void testKpiComputationSlicingMultipleSNSSAI() { + String strKpiConfigRatio = FileUtils.getFileContents(KPI_CONFIG_SLICING_RATIO_FILE); + String vesMessage = FileUtils.getFileContents(VES_MESSAGE_MULTIPLESNSSAI_SLICING_FILE); + Configuration config = mock(Configuration.class); + when(config.getKpiConfig()).thenReturn(strKpiConfigRatio); + List<VesEvent> vesList = new KpiComputation().checkAndDoComputation(vesMessage, config); + VesEvent vesEvent = vesList.get(0); + VesEvent anotherVesEvent = vesList.get(18); + assertEquals(vesEvent.getEvent().getPerf3gppFields().getMeasDataCollection().getMeasInfoList().get(0) + .getMeasTypes().getMeasTypesList().get(0), "PDUSessionEstSR.01-B989BD"); + assertEquals(anotherVesEvent.getEvent().getPerf3gppFields().getMeasDataCollection().getMeasInfoList().get(0) + .getMeasTypes().getMeasTypesList().get(0), "PDUSessionEstSR.01-B989BD"); + } + + @Test public void testKpiComputationSumRatio() { String strKpiConfigSumRatio = FileUtils.getFileContents(KPI_CONFIG_SUMRATIO_FILE); @@ -90,7 +142,6 @@ public class KpiComputationTest { @Test public void testKpiComputationSumRatioEmptyCheck() { String strKpiConfigSumRatio = FileUtils.getFileContents(KPI_CONFIG_SUMRATIO_FILE); - String vesMessage = FileUtils.getFileContents(VES_MESSAGE_EMPTY_FILE); Configuration config = mock(Configuration.class); when(config.getKpiConfig()).thenReturn(strKpiConfigSumRatio); @@ -119,5 +170,47 @@ public class KpiComputationTest { List<VesEvent> vesList = new KpiComputation().checkAndDoComputation(vesMessage, config); assertEquals(null, vesList); } + + @Test + public void testKpiComputationException() { + String strKpiConfigSumRatio = FileUtils.getFileContents(KPI_CONFIG_SUMRATIO_FILE); + String vesMessage = FileUtils.getFileContents(VES_MESSAGE_FIELD_MISSING); + Configuration config = mock(Configuration.class); + when(config.getKpiConfig()).thenReturn(strKpiConfigSumRatio); + KpiComputationException kpiException = Assertions.assertThrows(KpiComputationException.class, () -> { + List<VesEvent> vesList = new KpiComputation().checkAndDoComputation(vesMessage, config); + }); + Assertions.assertEquals("Required Field: EventName not present", kpiException.getMessage()); + } + @Test + public void testNullOperands() throws Exception { + Map<String, List<KpiOperand>> operands = null; + operands = Whitebox.invokeMethod(new KpiComputation(), "getOperands", new MeasDataCollection(), null); + Assertions.assertNull(operands); + } + @Test + public void testEmptyOperands() throws Exception { + Map<String, List<KpiOperand>> operands = null; + List<String> inputOperands = new ArrayList<String>(); + operands = Whitebox.invokeMethod(new KpiComputation(), "getOperands", new MeasDataCollection(), inputOperands); + Assertions.assertNull(operands); + } + @Test + public void testNullVESMessage() { + String strKpiConfigSumRatio = FileUtils.getFileContents(KPI_CONFIG_FILE); + Configuration config = mock(Configuration.class); + when(config.getKpiConfig()).thenReturn(strKpiConfigSumRatio); + List<VesEvent> vesList = new KpiComputation().checkAndDoComputation(null, config); + Assertions.assertNull(vesList); + } + @Test + public void testEmptyVESMessage() { + String strKpiConfigSumRatio = FileUtils.getFileContents(KPI_CONFIG_FILE); + Configuration config = mock(Configuration.class); + when(config.getKpiConfig()).thenReturn(strKpiConfigSumRatio); + String vesMessage = "{}"; + List<VesEvent> vesList = new KpiComputation().checkAndDoComputation(vesMessage, config); + Assertions.assertNull(vesList); + } } diff --git a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/controller/HealthCheckTest.java b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/controller/HealthCheckTest.java new file mode 100644 index 00000000..b0f2c0ef --- /dev/null +++ b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/controller/HealthCheckTest.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Wipro Limited. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.kpi.controller; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Spy; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +public class HealthCheckTest { + @Spy + HealthCheck healthCheck; + @Test + public void testHealthCheck(){ + ResponseEntity<HttpStatus> status = healthCheck.healthCheck(); + assertEquals(HttpStatus.OK, status.getStatusCode()); + } +} diff --git a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/DmaapClientTest.java b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/DmaapClientTest.java index 8020f938..f51bf241 100644 --- a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/DmaapClientTest.java +++ b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/DmaapClientTest.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/KpiDmaapClientTest.java b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/KpiDmaapClientTest.java index e8fd9925..bf5b6253 100644 --- a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/KpiDmaapClientTest.java +++ b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/KpiDmaapClientTest.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/NotificationConsumerTest.java b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/NotificationConsumerTest.java index 1d04a627..69d0daaa 100644 --- a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/NotificationConsumerTest.java +++ b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/NotificationConsumerTest.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/NotificationProducerTest.java b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/NotificationProducerTest.java index c835d49b..7ad5786c 100644 --- a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/NotificationProducerTest.java +++ b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/dmaap/NotificationProducerTest.java @@ -1,6 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2021 China Mobile. + * Copyright (C) 2022 Wipro Limited. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/models/ConfigPolicyTest.java b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/models/ConfigPolicyTest.java new file mode 100644 index 00000000..0d9bea09 --- /dev/null +++ b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/models/ConfigPolicyTest.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Wipro Limited. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dcaegen2.kpi.models; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.mockito.Spy; +public class ConfigPolicyTest { + @Spy + ConfigPolicy configPolicy; + @Test + public void testGetInstance() { + ConfigPolicy instance = ConfigPolicy.getInstance(); + assertNotNull(instance); + } + @Test + public void testGetInstanceIfNull() { + ConfigPolicy instance = ConfigPolicy.getInstance(); + instance = null; + ConfigPolicy instanceNew = ConfigPolicy.getInstance(); + assertNotNull(instanceNew); + } +} diff --git a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/models/ConfigurationTest.java b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/models/ConfigurationTest.java index efe84983..cc22ef13 100644 --- a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/models/ConfigurationTest.java +++ b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/models/ConfigurationTest.java @@ -1,8 +1,9 @@ /******************************************************************************* * ============LICENSE_START======================================================= - * slice-analysis-ms + * kpi-computation-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +24,7 @@ package org.onap.dcaegen2.kpi.models; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import java.util.ArrayList; import java.util.HashMap; @@ -32,10 +34,14 @@ import java.util.Map; import org.junit.Test; import org.onap.dcaegen2.kpi.computation.FileUtils; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + public class ConfigurationTest { Configuration configuration = Configuration.getInstance(); private static final String KPI_CONFIG_FILE = "kpi/kpi_config.json"; + private static final String CBS_CONFIG_FILE = "kpi/cbs_config4.json"; @Test public void configurationTest() { @@ -43,7 +49,6 @@ public class ConfigurationTest { List<String> list = new ArrayList<String>(); list.add("server"); Map<String, Object> subscribes = new HashMap<>(); - configuration.setStreamsSubscribes(subscribes); configuration.setStreamsPublishes(subscribes); configuration.setDmaapServers(list); @@ -61,7 +66,6 @@ public class ConfigurationTest { configuration.setEnablessl(true); configuration.setCbsPollingInterval(10); configuration.setKpiConfig("kpi config"); - assertEquals("cg", configuration.getCg()); assertEquals("cid", configuration.getCid()); assertEquals("user", configuration.getAafUsername()); @@ -72,17 +76,25 @@ public class ConfigurationTest { assertEquals("192.168.1.1", configuration.getHost()); assertEquals(21, configuration.getPort()); assertEquals("user", configuration.getUsername()); - assertEquals("password", configuration.getPassword()); - assertEquals("database", configuration.getDatabasename()); - assertEquals(true, configuration.isEnablessl()); - assertEquals("kpi config", configuration.getKpiConfig()); - assertEquals(10, configuration.getCbsPollingInterval()); + assertEquals("password", configuration.getPassword()); + assertEquals("database", configuration.getDatabasename()); + assertEquals(true, configuration.isEnablessl()); + assertEquals("kpi config", configuration.getKpiConfig()); + assertEquals(10, configuration.getCbsPollingInterval()); } - @Test public void updateConfigFromPolicyTest() { - String strKpiConfig = FileUtils.getFileContents(KPI_CONFIG_FILE); - configuration.setKpiConfig(strKpiConfig); - assertEquals(strKpiConfig, configuration.getKpiConfig()); + String strKpiConfig = FileUtils.getFileContents(KPI_CONFIG_FILE); + configuration.setKpiConfig(strKpiConfig); + assertEquals(strKpiConfig, configuration.getKpiConfig()); + } + @Test + public void testNullFields() { + String strCbsConfig = FileUtils.getFileContents(CBS_CONFIG_FILE); + JsonObject jsonObject = new JsonParser().parse(strCbsConfig).getAsJsonObject().getAsJsonObject("config"); + Configuration config = new Configuration(); + config.updateConfigurationFromJsonObject(jsonObject); + assertNull(config.getAafUsername()); + assertNull(config.getAafPassword()); } } diff --git a/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/utils/BeanUtilTest.java b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/utils/BeanUtilTest.java new file mode 100644 index 00000000..681091a2 --- /dev/null +++ b/components/kpi-computation-ms/src/test/java/org/onap/dcaegen2/kpi/utils/BeanUtilTest.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Wipro Limited. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.kpi.utils; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes=BeanUtil.class, loader=AnnotationConfigContextLoader.class) +public class BeanUtilTest { + @Test + public void testBeanUtils() { + assertNotNull(ApplicationContext.class); + } +} diff --git a/components/kpi-computation-ms/src/test/resources/kpi/RAN.xml b/components/kpi-computation-ms/src/test/resources/kpi/RAN.xml new file mode 100644 index 00000000..9b8da644 --- /dev/null +++ b/components/kpi-computation-ms/src/test/resources/kpi/RAN.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +~ ============LICENSE_START======================================================= +~ Copyright (c) 2022 Wipro Limited. 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========================================================= +--> +<measCollecFile xmlns="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec"> + <fileHeader dnPrefix="Prefix" fileFormatVersion="32.435 V10.0" vendorName="Acme Ltd"> + <fileSender localDn="cucpserver2"/> + <measCollec beginTime="2021-01-15T05:46:30.387"/> + </fileHeader> + <measData> + <managedElement localDn="cucpserver2" swVersion="r0.1"/> + <measInfo measInfoId="measInfoIsVal"> + <job jobId="7836"/> + <granPeriod duration="PT900S" endTime="2021-01-15T05:46:30.387"/> + <repPeriod duration="PT900S"/> + <measType p="1">SM.PduSessionCreationSucc.0011-0010</measType> + <measType p="2">SM.PduSessionCreationReq.0011-0010</measType> + <measType p="3">SM.PduSessionCreationFail.0</measType> + <measValue measObjLdn="10896"> + <r p="1">5813.0</r> + <r p="2">3679.0</r> + <r p="3">1333.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="10897"> + <r p="1">5637.0</r> + <r p="2">3406.0</r> + <r p="3">1333.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="11561"> + <r p="1">5130.0</r> + <r p="2">3083.0</r> + <r p="3">1333.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="11562"> + <r p="1">6020.0</r> + <r p="2">3956.0</r> + <r p="3">1333.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="11568"> + <r p="1">5527.0</r> + <r p="2">4117.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="11569"> + <r p="1">5086.0</r> + <r p="2">3206.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="13905"> + <r p="1">1655.0</r> + <r p="2">1183.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="13910"> + <r p="1">2587.0</r> + <r p="2">1900.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="14427"> + <r p="1">1668.0</r> + <r p="2">1217.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="14655"> + <r p="1">4904.0</r> + <r p="2">3155.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="14656"> + <r p="1">5357.0</r> + <r p="2">3577.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="15360"> + <r p="1">2177.0</r> + <r p="2">1438.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="15361"> + <r p="1">2480.0</r> + <r p="2">1615.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="15548"> + <r p="1">1730.0</r> + <r p="2">1174.0</r> + <suspect>false</suspect> + </measValue> + <measValue measObjLdn="15549"> + <r p="1">2227.0</r> + <r p="2">1341.0</r> + <suspect>false</suspect> + </measValue> + </measInfo> + </measData> + <fileFooter> + <measCollec endTime="2021-01-15T05:46:30.387"/> + </fileFooter> +</measCollecFile> diff --git a/components/kpi-computation-ms/src/test/resources/kpi/cbs_config4.json b/components/kpi-computation-ms/src/test/resources/kpi/cbs_config4.json new file mode 100644 index 00000000..b2649ec3 --- /dev/null +++ b/components/kpi-computation-ms/src/test/resources/kpi/cbs_config4.json @@ -0,0 +1,36 @@ +{ + "config": { + "pollingInterval": 20, + "cbsPollingInterval": 60, + "mongo.host": "192.168.225.61", + "cid": "kpi-cid", + "trust_store_pass_path": "/opt/app/kpims/etc/cert/trust.pass", + "cg": "kpi-cg", + "mongo.port": 27017, + "mongo.databasename": "datalake", + "streams_subscribes": { + "performance_management_topic": { + "aaf_password": "demo123456!", + "type": "message-router", + "dmaap_info": { + "topic_url": "https://message-router.onap.svc.cluster.local:3905/events/org.onap.dmaap.mr.PERFORMANCE_MEASUREMENTS" + }, + "aaf_username": "dcae@dcae.onap.org" + } + }, + "trust_store_path": "/opt/app/kpims/etc/cert/trust.jks", + "pollingTimeout": 60, + "streams_publishes": { + "kpi_topic": { + "aaf_password": "demo123456!", + "type": "message-router", + "dmaap_info": { + "topic_url": "https://message-router.onap.svc.cluster.local:3905/events/unauthenticated.DCAE_KPI_OUTPUT" + }, + "aaf_username": "dcae@dcae.onap.org" + } + }, + "kpi.policy": "{\"domain\":\"measurementsForKpi\",\"methodForKpi\":[{\"eventName\":\"perf3gpp_CORE-AMF_pmMeasResult\",\"controlLoopSchemaType\":\"SLICE\",\"policyScope\":\"resource=networkSlice;type=configuration\",\"policyName\":\"configuration.dcae.microservice.pm-mapper.xml\",\"policyVersion\":\"v0.0.1\",\"kpis\":[{\"measType\":\"AMFRegNbr\",\"operation\":\"SUM\",\"operands\":[\"RM.RegisteredSubNbrMean\"]}]},{\"eventName\":\"perf3gpp_AcmeNode-Acme_pmMeasResult\",\"controlLoopSchemaType\":\"SLICE\",\"policyScope\":\"resource=networkSlice;type=configuration\",\"policyName\":\"configuration.dcae.microservice.pm-mapper.xml\",\"policyVersion\":\"v0.0.1\",\"kpis\":[{\"measType\":\"UpstreamThr\",\"operation\":\"SUMRATIO\",\"operands\":[\"GTP.InDataOctN3UPF\",\"GTP.OutDataOctN3UPF\"]},{\"measType\":\"DownstreamThr\",\"operation\":\"SUMRATIO\",\"operands\":[\"GTP.InDataOctN3UPF\",\"GTP.OutDataOctN3UPF\"]}]}]}", + "dmaap.server": ["message-router"] + } +} diff --git a/components/kpi-computation-ms/src/test/resources/kpi/kpi_config_slicing.json b/components/kpi-computation-ms/src/test/resources/kpi/kpi_config_slicing.json new file mode 100644 index 00000000..bbc7fb2a --- /dev/null +++ b/components/kpi-computation-ms/src/test/resources/kpi/kpi_config_slicing.json @@ -0,0 +1,17 @@ +{ + "domain": "measurementsForKpi", + "methodForKpi": [{ + "eventName": "perf3gpp_CORE-cucpserver2_pmMeasResult", + "controlLoopSchemaType": "SLICE", + "policyScope": "resource=networkSlice;type=configuration", + "policyName": "configuration.dcae.microservice.pm-mapper.xml", + "policyVersion": "v0.0.1", + "kpis": [{ + "measType": "PDUSessionEstSR", + "operation": "RATIO", + "operands": ["SM.PduSessionCreationSucc","SM.PduSessionCreationReq"] + } + ] + } + ] +} diff --git a/components/kpi-computation-ms/src/test/resources/kpi/ves_message_missing_field.json b/components/kpi-computation-ms/src/test/resources/kpi/ves_message_missing_field.json new file mode 100644 index 00000000..9e8a56fb --- /dev/null +++ b/components/kpi-computation-ms/src/test/resources/kpi/ves_message_missing_field.json @@ -0,0 +1,82 @@ +{ + "event":{ + "commonEventHeader":{ + "domain":"perf3gpp", + "eventId":"14618daf-c0ce-4ccc-9169-9e1ac79971f2", + "sequence":0, + "sourceName":"oteNB5309", + "reportingEntityName":"", + "priority":"Normal", + "startEpochMicrosec":1591099200000, + "lastEpochMicrosec":1591100100000, + "version":"4.0", + "vesEventListenerVersion":"7.1", + "timeZoneOffset":"UTC+05:00" + }, + "perf3gppFields":{ + "perf3gppFieldsVersion":"1.0", + "measDataCollection":{ + "granularityPeriod":1591100100000, + "measuredEntityUserName":"", + "measuredEntityDn":"UPFMeasurement", + "measuredEntitySoftwareVersion":"r0.1", + "measInfoList":[ + { + "measInfoId":{ + "sMeasInfoId":"UPFFunction0" + }, + "measTypes":{ + "sMeasTypesList":[ + "GTP.InDataOctN3UPF.08_010101", + "GTP.OutDataOctN3UPF.08_010101" + ] + }, + "measValuesList":[ + { + "measObjInstId":"some measObjLdn", + "suspectFlag":"false", + "measResults":[ + { + "p":1, + "sValue":"10" + }, + { + "p":2, + "sValue":"20" + } + ] + } + ] + }, + { + "measInfoId":{ + "sMeasInfoId":"UPFFunction1" + }, + "measTypes":{ + "sMeasTypesList":[ + "GTP.InDataOctN3UPF.08_010101", + "GTP.OutDataOctN3UPF.08_010101" + ] + }, + "measValuesList":[ + { + "measObjInstId":"some measObjLdn", + "suspectFlag":"false", + "measResults":[ + { + "p":1, + "sValue":"30" + }, + { + "p":2, + "sValue":"40" + } + ] + } + ] + } + ] + } + } + } +} diff --git a/components/kpi-computation-ms/src/test/resources/kpi/ves_message_slicing.json b/components/kpi-computation-ms/src/test/resources/kpi/ves_message_slicing.json new file mode 100644 index 00000000..2081b06d --- /dev/null +++ b/components/kpi-computation-ms/src/test/resources/kpi/ves_message_slicing.json @@ -0,0 +1,270 @@ +{ + "event": { + "commonEventHeader": { + "domain": "perf3gpp", + "eventId": "243f63f4-bb54-4f65-8aab-d254cd5b026d", + "sequence": 0, + "eventName": "perf3gpp_CORE-cucpserver2_pmMeasResult", + "sourceName": "oteNB5309", + "reportingEntityName": "", + "priority": "Normal", + "startEpochMicrosec": 1610689590387, + "lastEpochMicrosec": 1610689590387, + "version": "4.0", + "vesEventListenerVersion": "7.1", + "timeZoneOffset": "UTC+05:00" + }, + "perf3gppFields": { + "perf3gppFieldsVersion": "1.0", + "measDataCollection": { + "granularityPeriod": 900, + "measuredEntityUserName": "", + "measuredEntityDn": "cucpserver2", + "measuredEntitySoftwareVersion": "r0.1", + "measInfoList": [ + { + "measInfoId": { + "sMeasInfoId": "measInfoIsVal" + }, + "measTypes": { + "sMeasTypesList": [ + "SM.PduSessionCreationSucc.01-B989BD", + "SM.PduSessionCreationReq.01-B989BD", + "SM.PduSessionCreationFail.0" + ] + }, + "measValuesList": [ + { + "measObjInstId": "10896", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "5813.0" + }, + { + "p": 2, + "sValue": "3679.0" + }, + { + "p": 3, + "sValue": "1333.0" + } + ] + }, + { + "measObjInstId": "10897", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "5637.0" + }, + { + "p": 2, + "sValue": "3406.0" + }, + { + "p": 3, + "sValue": "1333.0" + } + ] + }, + { + "measObjInstId": "11561", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "5130.0" + }, + { + "p": 2, + "sValue": "3083.0" + }, + { + "p": 3, + "sValue": "1333.0" + } + ] + }, + { + "measObjInstId": "11562", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "6020.0" + }, + { + "p": 2, + "sValue": "3956.0" + }, + { + "p": 3, + "sValue": "1333.0" + } + + ] + }, + { + "measObjInstId": "11568", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "5527.0" + }, + { + "p": 2, + "sValue": "4117.0" + } + ] + }, + { + "measObjInstId": "11569", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "5086.0" + }, + { + "p": 2, + "sValue": "3206.0" + } + ] + }, + { + "measObjInstId": "13905", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "1655.0" + }, + { + "p": 2, + "sValue": "1183.0" + } + ] + }, + { + "measObjInstId": "13910", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "2587.0" + }, + { + "p": 2, + "sValue": "1900.0" + } + ] + }, + { + "measObjInstId": "14427", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "1668.0" + }, + { + "p": 2, + "sValue": "1217.0" + } + ] + }, + { + "measObjInstId": "14655", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "4904.0" + }, + { + "p": 2, + "sValue": "3155.0" + } + ] + }, + { + "measObjInstId": "14656", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "5357.0" + }, + { + "p": 2, + "sValue": "3577.0" + } + ] + }, + { + "measObjInstId": "15360", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "2177.0" + }, + { + "p": 2, + "sValue": "1438.0" + } + ] + }, + { + "measObjInstId": "15361", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "2480.0" + }, + { + "p": 2, + "sValue": "1615.0" + } + ] + }, + { + "measObjInstId": "15548", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "1730.0" + }, + { + "p": 2, + "sValue": "1174.0" + } + ] + }, + { + "measObjInstId": "15549", + "suspectFlag": "false", + "measResults": [ + { + "p": 1, + "sValue": "2227.0" + }, + { + "p": 2, + "sValue": "1341.0" + } + ] + } + ] + } + ] + } + } + } +} diff --git a/components/kpi-computation-ms/src/test/resources/kpi/ves_message_slicing_multiplesnssai.json b/components/kpi-computation-ms/src/test/resources/kpi/ves_message_slicing_multiplesnssai.json new file mode 100644 index 00000000..1a3e5e87 --- /dev/null +++ b/components/kpi-computation-ms/src/test/resources/kpi/ves_message_slicing_multiplesnssai.json @@ -0,0 +1 @@ +{ "event": { "commonEventHeader": { "domain": "perf3gpp", "eventId": "42b8917b-aa11-49aa-84ca-084147ca7a3c", "sequence": 0, "eventName": "perf3gpp_CORE-cucpserver2_pmMeasResult", "sourceName": "oteNB5309", "reportingEntityName": "", "priority": "Normal", "startEpochMicrosec": 1606743157914, "lastEpochMicrosec": 1606743157915, "version": "4.0", "vesEventListenerVersion": "7.1", "timeZoneOffset": "UTC+05:00" }, "perf3gppFields": { "perf3gppFieldsVersion": "1.0", "measDataCollection": { "granularityPeriod": 900, "measuredEntityUserName": "", "measuredEntityDn": "cucpserver2", "measuredEntitySoftwareVersion": "r0.1", "measInfoList": [ { "measInfoId": { "sMeasInfoId": "measInfoIsVal" }, "measTypes": { "sMeasTypesList": [ "SM.PduSessionCreationReq.01-B989BD", "SM.PduSessionCreationSucc.01-B989BD", "SM.PduSessionCreationReq.01-B989BD", "SM.PduSessionCreationSucc.01-B989BD", "SM.PduSessionSetupFail.0" ] }, "measValuesList": [ { "measObjInstId": "10896", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "1400.0" }, { "p": 2, "sValue": "1008.0" }, { "p": 4, "sValue": "2853.0" }, { "p": 5, "sValue": "1819.0" }, { "p": 3, "sValue": "1297.0" } ] }, { "measObjInstId": "10897", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "1765.0" }, { "p": 2, "sValue": "1105.0" }, { "p": 4, "sValue": "2757.0" }, { "p": 5, "sValue": "1684.0" }, { "p": 3, "sValue": "1612.0" } ] }, { "measObjInstId": "11561", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "2113.0" }, { "p": 2, "sValue": "1442.0" }, { "p": 4, "sValue": "3550.0" }, { "p": 5, "sValue": "2298.0" }, { "p": 3, "sValue": "1731.0" } ] }, { "measObjInstId": "11562", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "1414.0" }, { "p": 2, "sValue": "1020.0" }, { "p": 4, "sValue": "2778.0" }, { "p": 5, "sValue": "1753.0" }, { "p": 3, "sValue": "1299.0" } ] }, { "measObjInstId": "11568", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "2338.0" }, { "p": 2, "sValue": "1469.0" }, { "p": 4, "sValue": "3140.0" }, { "p": 5, "sValue": "2264.0" }, { "p": 3, "sValue": "1635.0" } ] }, { "measObjInstId": "11569", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "2200.0" }, { "p": 2, "sValue": "1486.0" }, { "p": 4, "sValue": "2297.0" }, { "p": 5, "sValue": "1485.0" }, { "p": 3, "sValue": "1447.0" } ] }, { "measObjInstId": "13905", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "4541.0" }, { "p": 2, "sValue": "3054.0" }, { "p": 4, "sValue": "7301.0" }, { "p": 5, "sValue": "5351.0" }, { "p": 3, "sValue": "3209.0" } ] }, { "measObjInstId": "13910", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "4699.0" }, { "p": 2, "sValue": "3104.0" }, { "p": 4, "sValue": "7467.0" }, { "p": 5, "sValue": "5141.0" }, { "p": 3, "sValue": "3532.0" } ] }, { "measObjInstId": "14427", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "5840.0" }, { "p": 2, "sValue": "4264.0" }, { "p": 4, "sValue": "7445.0" }, { "p": 5, "sValue": "4974.0" }, { "p": 3, "sValue": "3746.0" } ] }, { "measObjInstId": "14655", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "2536.0" }, { "p": 2, "sValue": "1895.0" }, { "p": 4, "sValue": "3227.0" }, { "p": 5, "sValue": "2113.0" }, { "p": 3, "sValue": "1618.0" } ] }, { "measObjInstId": "14656", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "2322.0" }, { "p": 2, "sValue": "1520.0" }, { "p": 4, "sValue": "1889.0" }, { "p": 5, "sValue": "1212.0" }, { "p": 3, "sValue": "1374.0" } ] }, { "measObjInstId": "15360", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "5859.0" }, { "p": 2, "sValue": "3894.0" }, { "p": 4, "sValue": "6347.0" }, { "p": 5, "sValue": "3922.0" }, { "p": 3, "sValue": "4080.0" } ] }, { "measObjInstId": "15361", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "5753.0" }, { "p": 2, "sValue": "4194.0" }, { "p": 4, "sValue": "8075.0" }, { "p": 5, "sValue": "5585.0" }, { "p": 3, "sValue": "3746.0" } ] }, { "measObjInstId": "15548", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "4562.0" }, { "p": 2, "sValue": "2896.0" }, { "p": 4, "sValue": "6591.0" }, { "p": 5, "sValue": "4534.0" }, { "p": 3, "sValue": "3504.0" } ] }, { "measObjInstId": "15549", "suspectFlag": "false", "measResults": [ { "p": 1, "sValue": "4918.0" }, { "p": 2, "sValue": "3244.0" }, { "p": 4, "sValue": "6916.0" }, { "p": 5, "sValue": "4883.0" }, { "p": 3, "sValue": "3491.0" } ] } ] } ] } } }} diff --git a/components/kpi-computation-ms/version.properties b/components/kpi-computation-ms/version.properties index ada000a6..499327c8 100644 --- a/components/kpi-computation-ms/version.properties +++ b/components/kpi-computation-ms/version.properties @@ -3,6 +3,8 @@ # kpi-ms # ================================================================================ # Copyright (C) 2021 China Mobile. +# Copyright (C) 2022 Wipro Limited. All rights reserved. +# Copyright (C) 2023 Deutsche Telekom AG. 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. @@ -19,8 +21,8 @@ # ############################################################################### major=1 -minor=0 -patch=4 +minor=2 +patch=0 base_version=${major}.${minor}.${patch} release_version=${base_version} snapshot_version=${base_version}-SNAPSHOT diff --git a/components/pm-subscription-handler/.gitignore b/components/pm-subscription-handler/.gitignore index 98ba212b..80574918 100644 --- a/components/pm-subscription-handler/.gitignore +++ b/components/pm-subscription-handler/.gitignore @@ -1,4 +1,4 @@ -mvn-phase-lib.sh +#mvn-phase-lib.sh tox-local.ini *.wgn .pytest_cache/ diff --git a/components/pm-subscription-handler/Changelog.md b/components/pm-subscription-handler/Changelog.md index 00e97783..c768f38c 100755 --- a/components/pm-subscription-handler/Changelog.md +++ b/components/pm-subscription-handler/Changelog.md @@ -5,9 +5,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [2.2.3] +### Changed +* Fix dependencies and build script process (DCAEGEN2-3353) + +## [2.2.2] +### Changed +* Bug fix for Create MG (DCAEGEN2-3118) + +## [2.2.1] +### Changed +* Swagger Indentation Error (DCAEGEN2-3103) + ## [2.2.0] ### Changed * Update Filter API (DCAEGEN2-2922) +* Cleaning up old App Config, subscription handler and it's subsequent calls (DCAEGEN2-3085) +* Create Measurement Group API (DCAEGEN2-2920) ## [2.1.1] ### Changed diff --git a/components/pm-subscription-handler/Dockerfile b/components/pm-subscription-handler/Dockerfile index 9e3ebfe8..612b744f 100644 --- a/components/pm-subscription-handler/Dockerfile +++ b/components/pm-subscription-handler/Dockerfile @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2020 Nordix Foundation. +# Copyright (C) 2020-2023 Nordix Foundation. # Copyright 2020 Deutsche Telekom. All rights reserved. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,7 +17,7 @@ # SPDX-License-Identifier: Apache-2.0 # ============LICENSE_END===================================================== -FROM nexus3.onap.org:10001/onap/integration-python:8.0.0 as build +FROM nexus3.onap.org:10001/onap/integration-python:10.1.0 as build LABEL maintainer="lego@est.tech" USER root @@ -32,7 +32,7 @@ COPY requirements.txt ./ RUN pip install --prefix /opt -r requirements.txt --no-cache-dir # Second stage -FROM nexus3.onap.org:10001/onap/integration-python:8.0.0 +FROM nexus3.onap.org:10001/onap/integration-python:10.1.0 COPY --from=build /opt /opt @@ -43,7 +43,7 @@ ARG group=onap # set PATH & PYTHONPATH vars ENV APPDIR="/opt/app/pmsh" \ LD_LIBRARY_PATH=/opt/lib \ - PYTHONPATH=${APPDIR}/mod:/opt/lib/python3.9/site-packages \ + PYTHONPATH=${APPDIR}/mod:/opt/lib/python3.10/site-packages \ PATH=$PATH:${APPDIR}/bin \ LOGS_PATH="/var/log/ONAP/dcaegen2/services/pmsh" \ LOGGER_CONFIG="/opt/app/pmsh/log_config.yaml" diff --git a/components/pm-subscription-handler/mvn-phase-lib.sh b/components/pm-subscription-handler/mvn-phase-lib.sh new file mode 100644 index 00000000..58de1123 --- /dev/null +++ b/components/pm-subscription-handler/mvn-phase-lib.sh @@ -0,0 +1,553 @@ +#!/bin/bash +# ============LICENSE_START======================================================= +# Copyright (c) 2017-2023 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========================================================= + + +#MVN_PROJECT_MODULEID="$1" +#MVN_PHASE="$2" +#PROJECT_ROOT=$(dirname $0) + +FQDN="${MVN_PROJECT_GROUPID}.${MVN_PROJECT_ARTIFACTID}" +if [ "$MVN_PROJECT_MODULEID" == "__" ]; then + MVN_PROJECT_MODULEID="" +fi + +if [[ "$MVN_PROJECT_VERSION" == *SNAPSHOT ]]; then + echo "=> for SNAPSHOT artifact build" + MVN_DEPLOYMENT_TYPE='SNAPSHOT' +else + echo "=> for STAGING/RELEASE artifact build" + MVN_DEPLOYMENT_TYPE='STAGING' +fi +echo "MVN_DEPLOYMENT_TYPE is [$MVN_DEPLOYMENT_TYPE]" + + +TIMESTAMP=$(date +%C%y%m%dT%H%M%S) + +# expected environment variables +if [ -z "${MVN_NEXUSPROXY}" ]; then + echo "MVN_NEXUSPROXY environment variable not set. Cannot proceed" + exit +fi +MVN_NEXUSPROXY_HOST=$(echo "$MVN_NEXUSPROXY" |cut -f3 -d'/' | cut -f1 -d':') +echo "=> Nexus Proxy at $MVN_NEXUSPROXY_HOST, $MVN_NEXUSPROXY" + +if [ -z "$WORKSPACE" ]; then + WORKSPACE=$(pwd) +fi + +export SETTINGS_FILE=${SETTINGS_FILE:-$HOME/.m2/settings.xml} + +RELEASE_TAG=${MVN_RELEASE_TAG:-R11} +if [ "$RELEASE_TAG" == "R1" ]; then + unset RELEASE_TAG +fi + + +# mvn phase in life cycle +MVN_PHASE="$2" + +echo "MVN_RELEASE_TAG is [$MVN_RELEASE_TAG]" +echo "MVN_PROJECT_MODULEID is [$MVN_PROJECT_MODULEID]" +echo "MVN_PHASE is [$MVN_PHASE]" +echo "MVN_PROJECT_GROUPID is [$MVN_PROJECT_GROUPID]" +echo "MVN_PROJECT_ARTIFACTID is [$MVN_PROJECT_ARTIFACTID]" +echo "MVN_PROJECT_VERSION is [$MVN_PROJECT_VERSION]" +echo "MVN_NEXUSPROXY is [$MVN_NEXUSPROXY]" +echo "MVN_RAWREPO_BASEURL_UPLOAD is [$MVN_RAWREPO_BASEURL_UPLOAD]" +echo "MVN_RAWREPO_BASEURL_DOWNLOAD is [$MVN_RAWREPO_BASEURL_DOWNLOAD]" +MVN_RAWREPO_HOST=$(echo "$MVN_RAWREPO_BASEURL_UPLOAD" | cut -f3 -d'/' |cut -f1 -d':') +echo "MVN_RAWREPO_HOST is [$MVN_RAWREPO_HOST]" +echo "MVN_RAWREPO_SERVERID is [$MVN_RAWREPO_SERVERID]" +echo "MVN_DOCKERREGISTRY_SNAPSHOT is [$MVN_DOCKERREGISTRY_SNAPSHOT]" +echo "MVN_DOCKERREGISTRY_PUBLIC is [$MVN_DOCKERREGISTRY_PUBLIC]" +echo "MVN_DOCKERREGISTRY_RELEASE is [$MVN_DOCKERREGISTRY_RELEASE]" +echo "MVN_PYPISERVER_SERVERID [$MVN_PYPISERVER_SERVERID]" +echo "MVN_PYPISERVER_BASEURL is [$MVN_PYPISERVER_BASEURL]" + + + +clean_templated_files() +{ + TEMPLATE_FILES=$(find . -name "*-template") + for F in $TEMPLATE_FILES; do + F2=$(echo "$F" | sed 's/-template$//') + rm -f "$F2" + done +} +clean_tox_files() +{ + TOX_FILES=$(find . -name ".tox") + TOX_FILES="$TOX_FILES $(find . -name 'venv-tox')" + for F in $TOX_FILES; do + rm -rf "$F" + done +} + +expand_templates() +{ + set +x + # set up env variables, get ready for template resolution + # NOTE: CCSDK artifacts do not distinguish REALESE vs SNAPSHOTs + export ONAPTEMPLATE_RAWREPOURL_org_onap_ccsdk_platform_plugins_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.ccsdk.platform.plugins" + export ONAPTEMPLATE_RAWREPOURL_org_onap_ccsdk_platform_plugins_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.ccsdk.platform.plugins" + export ONAPTEMPLATE_RAWREPOURL_org_onap_ccsdk_platform_blueprints_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.ccsdk.platform.blueprints" + export ONAPTEMPLATE_RAWREPOURL_org_onap_ccsdk_platform_blueprints_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.ccsdk.platform.blueprints" + + + if [ -z "$RELEASE_TAG" ]; then + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2/releases" + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2/snapshots" + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_plugins_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.plugins/releases" + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_plugins_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.plugins/snapshots" + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_blueprints_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.blueprints/releases" + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_blueprints_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.blueprints/snapshots" + else + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2/$RELEASE_TAG" + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2/$RELEASE_TAG" + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_plugins_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.plugins/$RELEASE_TAG" + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_plugins_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.plugins/$RELEASE_TAG" + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_blueprints_releases="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.blueprints/$RELEASE_TAG" + export ONAPTEMPLATE_RAWREPOURL_org_onap_dcaegen2_platform_blueprints_snapshots="$MVN_RAWREPO_BASEURL_DOWNLOAD/org.onap.dcaegen2.platform.blueprints/$RELEASE_TAG" + fi + + + export ONAPTEMPLATE_PYPIURL_org_onap_dcaegen2="${MVN_PYPISERVER_BASEURL}" + + # docker registry templates are for poll, so use PUBLIC registry + export ONAPTEMPLATE_DOCKERREGURL_org_onap_dcaegen2_releases="${MVN_DOCKERREGISTRY_PUBLIC}" + export ONAPTEMPLATE_DOCKERREGURL_org_onap_dcaegen2_snapshots="${MVN_DOCKERREGISTRY_PUBLIC}" + + # Mvn repo + export ONAPTEMPLATE_MVN_org_onap_dcaegen2_analytics_tca_snapshots="${MVN_NEXUSPROXY}/service/local/repositories/snapshots/content/org/onap/dcaegen2/analytics/tca" + export ONAPTEMPLATE_MVN_org_onap_dcaegen2_analytics_tca_staging="${MVN_NEXUSPROXY}/service/local/repositories/staging/content/org/onap/dcaegen2/analytics/tca" + export ONAPTEMPLATE_MVN_org_onap_dcaegen2_analytics_tca_releases="${MVN_NEXUSPROXY}/service/local/repositories/releases/content/org/onap/dcaegen2/analytics/tca" + + + export ONAPTEMPLATE_STANDARD_INPUTS_TYPES=" # standard inputs list + centos7image_id: + type: string + ubuntu1604image_id: + type: string + flavor_id: + type: string + security_group: + type: string + public_net: + type: string + private_net: + type: string + openstack: {} + keypair: + type: string + key_filename: + type: string + location_prefix: + type: string + location_domain: + type: string + codesource_url: + type: string + codesource_version: + type: string" + + + TEMPLATES=$(env |grep ONAPTEMPLATE | sed 's/=.*//' | sort -u) + if [ -z "$TEMPLATES" ]; then + echo "No template variables found!" + return 0 + fi + + TEMPLATE_FILES=$(find . -name "*-template") + for F in $TEMPLATE_FILES; do + F2=$(echo "$F" | sed 's/-template$//') + cp -p "$F" "$F2" + chmod u+w "$F2" + + echo "====> Resolving the following template from environment variables " + echo "$TEMPLATES" + for KEY in $TEMPLATES; do + VALUE1=$(eval 'echo "$'"$KEY"'"' | sed 1q) + VALUE2=$(eval 'echo "$'"$KEY"'"' | sed -e 's/\//\\\//g' -e 's/$/\\/' -e '$s/\\$//') + + echo "======> Resolving template $KEY to value $VALUE1 for file $F2" + sed -i "s/{{[[:space:]]*$KEY[[:space:]]*}}/$VALUE2/g" "$F2" + done + done + echo "====> Done template resolving" +} + +test_templates() +{ + # make certain that the type references exist + TMP=$(mktemp) + trap 'rm -f $TMP' 0 1 2 3 15 + + echo Verify that all of the import URLs are correct + find . -name '*-template' | sed -e 's/-template$//' | + while read file + do + egrep '^ - .?https?://' < "$file" + done | awk '{print $2}' | sed -e 's/"//g' | sort -u | + while read url + do + curl -L -w '%{http_code}' -s -o /dev/null "$url" > "$TMP" + case $(< "$TMP") in + 2* ) ;; + * ) echo ">>>>>>>>>>>>>>>> $url not found <<<<<<<<<<<<<<<<" ;; + esac + done + + echo Verify that the inputs are correct + PATH=$PATH:$PWD/check-blueprint-vs-input/bin + find . -name '*-template' | sed -e 's/-template$//' | + while read blueprint + do + check-blueprint-vs-input -b "$blueprint" -i check-blueprint-vs-input/lib/sample-inputs.yaml || true + done +} + + +run_tox_test() +{ + set -e -x + CURDIR=$(pwd) + TOXINIS=$(find . -name "tox.ini") + for TOXINI in "${TOXINIS[@]}"; do + DIR=$(dirname "$TOXINI") + cd "${CURDIR}/${DIR}" + rm -rf ./venv-tox ./.tox + python3 -m venv ./venv-tox + source ./venv-tox/bin/activate + + #pip3 install pip==9.0.3 + pip3 install --upgrade argparse + #pip3 install tox==2.9.1 + if [ "$RUN_BLACK" = yes ] + then + pip3 install black + python3 -m black --line-length 120 --check . + fi + pip3 freeze + tox + deactivate + rm -rf ./venv-tox ./.tox + done +} + +build_wagons() +{ + rm -rf ./*.wgn venv-pkg + SETUPFILES=$(find . -name "setup.py") + + python3 -m venv ./venv-pkg + source ./venv-pkg/bin/activate + + pip3 install --upgrade pip + pip3 install wagon + + CURDIR=$(pwd) + for SETUPFILE in $SETUPFILES; do + PLUGIN_DIR=$(dirname "$SETUPFILE") + PLUGIN_NAME=$(grep 'name' "$SETUPFILE" | cut -f2 -d'=' | sed 's/[^0-9a-zA-Z\.]*//g') + PLUGIN_VERSION=$(grep 'version' "$SETUPFILE" | cut -f2 -d'=' | sed 's/[^0-9\.]*//g') + + echo "In $PLUGIN_DIR, build plugin $PLUGIN_NAME, version $PLUGIN_VERSION" + + wagon create -r "${PLUGIN_DIR}/requirements.txt" --format tar.gz "${PLUGIN_DIR}" + + PKG_FILE_NAMES=( "${PLUGIN_NAME}-${PLUGIN_VERSION}"*.wgn ) + echo Built package: "${PKG_FILE_NAMES[@]}" + cd "$CURDIR" + done + + deactivate + rm -rf venv-pkg +} + +build_archives_for_wagons() +{ + rm -rf ./*.tgz ./*.zip venv-pkg + + SETUPFILES=$(find "$(pwd)" -name "setup.py") + CURDIR=$(pwd) + for SETUPFILE in $SETUPFILES; do + PLUGIN_FULL_DIR=$(dirname "$SETUPFILE") + PLUGIN_BASE_DIR=$(basename "$PLUGIN_FULL_DIR") + PLUGIN_NAME=$(grep 'name' "$SETUPFILE" | cut -f2 -d'=' | sed 's/[^0-9a-zA-Z\.]*//g') + PLUGIN_VERSION=$(grep 'version' "$SETUPFILE" | cut -f2 -d'=' | sed 's/[^0-9\.]*//g') + + cd "${PLUGIN_FULL_DIR}"/.. + echo "In $(pwd), build plugin zip $PLUGIN_NAME, version $PLUGIN_VERSION" + + zip -r "${PLUGIN_NAME}-${PLUGIN_VERSION}.zip" "./${PLUGIN_BASE_DIR}" + tar -czvf "${PLUGIN_NAME}-${PLUGIN_VERSION}.tgz" "./${PLUGIN_BASE_DIR}" + + echo "Built archives for package ${PLUGIN_NAME}-${PLUGIN_VERSION} at $(pwd)" + cd "$CURDIR" + done +} + + +upload_raw_file() +{ + # Extract the username and password to the nexus repo from the settings file + USER=$(xpath -q -e "//servers/server[id='$MVN_RAWREPO_SERVERID']/username/text()" "$SETTINGS_FILE") + PASS=$(xpath -q -e "//servers/server[id='$MVN_RAWREPO_SERVERID']/password/text()" "$SETTINGS_FILE") + NETRC=$(mktemp) + echo "machine $MVN_RAWREPO_HOST login $USER password $PASS" > "$NETRC" + + REPO="$MVN_RAWREPO_BASEURL_UPLOAD" + + OUTPUT_FILE=$1 + EXT=$(echo "$OUTPUT_FILE" | rev |cut -f1 -d '.' |rev) + if [ "$EXT" == 'yaml' ]; then + OUTPUT_FILE_TYPE='text/x-yaml' + elif [ "$EXT" == 'sh' ]; then + OUTPUT_FILE_TYPE='text/x-shellscript' + elif [ "$EXT" == 'gz' ]; then + OUTPUT_FILE_TYPE='application/gzip' + elif [ "$EXT" == 'tgz' ]; then + OUTPUT_FILE_TYPE='application/gzip' + elif [ "$EXT" == 'zip' ]; then + OUTPUT_FILE_TYPE='application/zip' + elif [ "$EXT" == 'wgn' ]; then + OUTPUT_FILE_TYPE='application/gzip' + else + OUTPUT_FILE_TYPE='application/octet-stream' + fi + + # for multi module projects, the raw repo path must match with project name, not project + module + # FQDN is project + module + # GROUPID is project name + if [ "$MVN_PROJECT_ARTIFACTID" == "$MVN_PROJECT_MODULEID" ]; then + PROJECT_NAME=${MVN_PROJECT_GROUPID} + else + PROJECT_NAME=${FQDN} + fi + + if [ -z "$RELEASE_TAG" ]; then + SEND_TO="${REPO}/${PROJECT_NAME}" + else + SEND_TO="${REPO}/${PROJECT_NAME}/${RELEASE_TAG}" + fi + + if [ ! -z "$2" ]; then + SEND_TO="$SEND_TO/$2" + fi + + echo "Sending ${OUTPUT_FILE} to Nexus: ${SEND_TO}" + curl -vkn --netrc-file "${NETRC}" --upload-file "${OUTPUT_FILE}" -X PUT -H "Content-Type: $OUTPUT_FILE_TYPE" "${SEND_TO}/${OUTPUT_FILE}-${TIMESTAMP}" + curl -vkn --netrc-file "${NETRC}" --upload-file "${OUTPUT_FILE}" -X PUT -H "Content-Type: $OUTPUT_FILE_TYPE" "${SEND_TO}/${OUTPUT_FILE}" +} + +upload_wagon_archives() +{ + SETUPFILES=$(find "$(pwd)" -name "setup.py") + CURDIR=$(pwd) + for SETUPFILE in $SETUPFILES; do + PLUGIN_FULL_DIR=$(dirname "$SETUPFILE") + PLUGIN_BASE_DIR=$(basename "$PLUGIN_FULL_DIR") + PLUGIN_NAME=$(grep 'name' "$SETUPFILE" | cut -f2 -d'=' | sed 's/[^0-9a-zA-Z\.]*//g') + PLUGIN_VERSION=$(grep 'version' "$SETUPFILE" | cut -f2 -d'=' | sed 's/[^0-9\.]*//g') + + cd "${PLUGIN_FULL_DIR}"/.. + echo "In $(pwd), upload zip archive for $PLUGIN_NAME, version $PLUGIN_VERSION" + ARCHIVE_FILE_NAME="${PLUGIN_NAME}-${PLUGIN_VERSION}.zip" + if [ -z "$ARCHIVE_FILE_NAME" ]; then + echo "!!! No zip archive file found ${ARCHIVE_FILE_NAME}" + exit -1 + fi + upload_raw_file "${ARCHIVE_FILE_NAME}" "${PLUGIN_NAME}/${PLUGIN_VERSION}" + + echo "In $(pwd), upload tgz archive for $PLUGIN_NAME, version $PLUGIN_VERSION" + ARCHIVE_FILE_NAME="${PLUGIN_NAME}-${PLUGIN_VERSION}.tgz" + if [ -z "$ARCHIVE_FILE_NAME" ]; then + echo "!!! No tgz archive file found ${ARCHIVE_FILE_NAME}" + exit -1 + fi + upload_raw_file "${ARCHIVE_FILE_NAME}" "${PLUGIN_NAME}/${PLUGIN_VERSION}" + + cd "${CURDIR}" + done +} + +upload_wagons_and_type_yamls() +{ + SETUPFILES=$(find . -name "setup.py") + + CURDIR=$(pwd) + for SETUPFILE in $SETUPFILES; do + PLUGIN_DIR=$(dirname "$SETUPFILE") + PLUGIN_NAME=$(grep 'name' "$SETUPFILE" | cut -f2 -d'=' | sed 's/[^0-9a-zA-Z\.]*//g') + PLUGIN_VERSION=$(grep 'version' "$SETUPFILE" | cut -f2 -d'=' | sed 's/[^0-9\.]*//g') + PLUGIN_VERSION_MAJOR=$(echo "$PLUGIN_VERSION" | cut -f1 -d'.') + PLUGIN_VERSION_MAJOR_MINOR=$(echo "$PLUGIN_VERSION" | cut -f1-2 -d'.') + + echo "Found setup file in $PLUGIN_DIR, for plugin $PLUGIN_NAME version $PLUGIN_VERSION" + + TYPEFILE_NAME=$(grep -R "package_name:[[:space:]]*${PLUGIN_NAME}" | cut -f1 -d ':') + if [ -z "$TYPEFILE_NAME" ]; then + echo "!!! No typefile found with matching package name $PLUGIN_NAME" + exit -1 + fi + NEWFILENAME="${PLUGIN_NAME}"_types.yaml + if [ "$TYPEFILE_NAME" != "$NEWFILENAME" ]; then + echo "copy typefile to standard naming" + cp -f "$TYPEFILE_NAME" "$NEWFILENAME" + fi + + TYPEFILE_PACKAGE_VERSION=$(grep -R 'package_version' "$TYPEFILE_NAME" |cut -f2 -d ':' |sed -r 's/\s+//g') + WAGONFILE_NAME=$(ls -1 "${PLUGIN_NAME}"-"${TYPEFILE_PACKAGE_VERSION}"-*.wgn) + if [ -z "$WAGONFILE_NAME" ]; then + echo "!!! No wagonfile found with matching package name and version as required in typefile: " + echo " $TYPEFILE_NAME plugin $PLUGIN_NAME package version ${TYPEFILE_PACKAGE_VERSION}" + exit -1 + fi + + upload_raw_file "${NEWFILENAME}" "${PLUGIN_NAME}/${PLUGIN_VERSION}" + upload_raw_file "${WAGONFILE_NAME}" "${PLUGIN_NAME}/${PLUGIN_VERSION}" + + rm -r "$WAGONFILE_NAME" + if [ "$TYPEFILE_NAME" != "$NEWFILENAME" ]; then + rm -f "$NEWFILENAME" + fi + done +} + +upload_files_of_extension() +{ + FILES=$(ls -1 ./*."$1") + for F in $FILES ; do + upload_raw_file "$F" "$2" + done +} +upload_files_of_extension_recursively() +{ + FILES=$(find . -name "*.$1") + for F in $FILES ; do + upload_raw_file "$F" "$2" + done +} + + +generate_pypirc_then_publish() +{ + set +x + USER=$(xpath -e "//servers/server[id='$MVN_PYPISERVER_SERVERID']/username/text()" "$SETTINGS_FILE") + PASS=$(xpath -e "//servers/server[id='$MVN_PYPISERVER_SERVERID']/password/text()" "$SETTINGS_FILE") + + if [[ "$MVN_PYPISERVER_BASEURL" != */ ]]; then + MVN_PYPISERVER_BASEURL="${MVN_PYPISERVER_BASEURL}/" + fi + + + cat > ~/.pypirc <<EOL +[distutils] +index-servers = + $MVN_PYPISERVER_SERVERID + +[$MVN_PYPISERVER_SERVERID] +repository: $MVN_PYPISERVER_BASEURL +username: $USER +password: $PASS +EOL + + # this may fail if a package of same version exists + python setup.py sdist register -r "$MVN_PYPISERVER_SERVERID" upload -r "$MVN_PYPISERVER_SERVERID" + set -x +} + + + +# following the https://wiki.onap.org/display/DW/Independent+Versioning+and+Release+Process +#IndependentVersioningandReleaseProcess-StandardizedDockerTagging +build_and_push_docker() +{ + # Old tagging + #IMAGENAME="onap/${FQDN}.${MVN_PROJECT_MODULEID}" + # new tagging + ENDID=$(echo $FQDN | rev | cut -f1 -d '.' |rev) + if [ "$ENDID" == "${MVN_PROJECT_MODULEID}" ]; then + #IMAGENAME="onap/${FQDN/org.onap./}" + IMAGENAME="onap/${FQDN}" + else + #IMAGENAME="onap/${FQDN/org.onap./}.${MVN_PROJECT_MODULEID}" + IMAGENAME="onap/${FQDN}.${MVN_PROJECT_MODULEID}" + fi + + IMAGENAME=$(echo "$IMAGENAME" | sed -e 's/_*$//g' -e 's/\.*$//g') + IMAGENAME=$(echo "$IMAGENAME" | tr '[:upper:]' '[:lower:]') + + # use the major and minor version of the MVN artifact version as docker image version + VERSION="${MVN_PROJECT_VERSION//[^0-9.]/}" + VERSION2=$(echo "$VERSION" | cut -f1-2 -d'.') + + LFQI="${IMAGENAME}:${VERSION}-${TIMESTAMP}"Z + # build a docker image + docker build --rm -f ./Dockerfile -t "${LFQI}" ./ + + # all local builds push to SNAPSHOT repo + REPO="" + if [ $MVN_DEPLOYMENT_TYPE == "SNAPSHOT" ]; then + REPO=$MVN_DOCKERREGISTRY_SNAPSHOT + elif [ $MVN_DEPLOYMENT_TYPE == "STAGING" ]; then + REPO=$MVN_DOCKERREGISTRY_SNAPSHOT + else + echo "Fail to determine DEPLOYMENT_TYPE" + REPO=$MVN_DOCKERREGISTRY_SNAPSHOT + fi + echo "DEPLOYMENT_TYPE is: $MVN_DEPLOYMENT_TYPE, repo is $REPO" + + if [ ! -z "$REPO" ]; then + USER=$(xpath -e "//servers/server[id='$REPO']/username/text()" "$SETTINGS_FILE") + PASS=$(xpath -e "//servers/server[id='$REPO']/password/text()" "$SETTINGS_FILE") + if [ -z "$USER" ]; then + echo "Error: no user provided" + fi + if [ -z "$PASS" ]; then + echo "Error: no password provided" + fi + [ -z "$PASS" ] && PASS_PROVIDED="<empty>" || PASS_PROVIDED="<password>" + echo docker login "$REPO" -u "$USER" -p "$PASS_PROVIDED" + + set +x + docker login "$REPO" -u "$USER" -p "$PASS" + set -x + + # local tag is imagename:version-timestamp + OLDTAG="${LFQI}" + # three tags are pushed: + # {imagename}:{semver}-SNAPSHOT-{timestamp}Z this is what CIMAN-132 asks + # {imagename}:{semver} latest of current version, for testing + # {imagename}:latest latest of all, used mainly by csit + # LFQI="${IMAGENAME}:${VERSION}-${TIMESTAMP}"Z + + + + # Updating tags for ${REPO}/${IMAGENAME}:${VERSION} to include STAGING-latest; and adding new tag for major:minor-STAGING-latest + PUSHTAGS="${REPO}/${IMAGENAME}:${VERSION}-SNAPSHOT-${TIMESTAMP}Z ${REPO}/${IMAGENAME}:${VERSION2}-STAGING-latest ${REPO}/${IMAGENAME}:${VERSION}-STAGING-latest ${REPO}/${IMAGENAME}:latest" + + for NEWTAG in ${PUSHTAGS} + do + echo "tagging ${OLDTAG} to ${NEWTAG}" + docker tag "${OLDTAG}" "${NEWTAG}" + echo "pushing ${NEWTAG}" + docker push "${NEWTAG}" + OLDTAG="${NEWTAG}" + done + fi +} diff --git a/components/pm-subscription-handler/mvn-phase-script.sh b/components/pm-subscription-handler/mvn-phase-script.sh index f51fa1ca..9737db1a 100755 --- a/components/pm-subscription-handler/mvn-phase-script.sh +++ b/components/pm-subscription-handler/mvn-phase-script.sh @@ -1,6 +1,6 @@ #!/bin/bash # ============LICENSE_START======================================================= -# Copyright (C) 2019 Nordix Foundation. +# Copyright (C) 2019-2023 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ PROJECT_ROOT=$(dirname $0) echo "MVN_RELEASE_TAG is set to [$MVN_RELEASE_TAG]" -RELEASE_TAG=${MVN_RELEASE_TAG:-R6} +RELEASE_TAG=${MVN_RELEASE_TAG:-R11} if [[ "$RELEASE_TAG" != "R1" ]]; then RELEASE_TAGGED_DIR="${RELEASE_TAG}/" else diff --git a/components/pm-subscription-handler/pmsh_service/mod/__init__.py b/components/pm-subscription-handler/pmsh_service/mod/__init__.py index 1024417e..548670c3 100644 --- a/components/pm-subscription-handler/pmsh_service/mod/__init__.py +++ b/components/pm-subscription-handler/pmsh_service/mod/__init__.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2019-2021 Nordix Foundation. +# Copyright (C) 2019-2022 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ # # SPDX-License-Identifier: Apache-2.0 # ============LICENSE_END===================================================== -import logging as logging +import logging import os import pathlib import ssl @@ -26,6 +26,9 @@ from flask_sqlalchemy import SQLAlchemy from onaplogging import monkey from onaplogging.mdcContext import MDC from ruamel.yaml import YAML +import uuid +from functools import wraps +from os import getenv db = SQLAlchemy() basedir = os.path.abspath(os.path.dirname(__file__)) @@ -33,6 +36,22 @@ _connexion_app = None logger = logging.getLogger('onap_logger') +def mdc_handler(func): + @wraps(func) + def wrapper(*args, **kwargs): + request_id = str(uuid.uuid1()) + invocation_id = str(uuid.uuid1()) + MDC.put('ServiceName', getenv('HOSTNAME')) + MDC.put('RequestID', request_id) + MDC.put('InvocationID', invocation_id) + + kwargs['request_id'] = request_id + kwargs['invocation_id'] = invocation_id + return func(*args, **kwargs) + + return wrapper + + def _get_app(): global _connexion_app if not _connexion_app: diff --git a/components/pm-subscription-handler/pmsh_service/mod/aai_client.py b/components/pm-subscription-handler/pmsh_service/mod/aai_client.py index d2aeb0f0..437a18f0 100755 --- a/components/pm-subscription-handler/pmsh_service/mod/aai_client.py +++ b/components/pm-subscription-handler/pmsh_service/mod/aai_client.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2019-2021 Nordix Foundation. +# Copyright (C) 2019-2022 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,8 +20,7 @@ from os import environ import requests from requests.auth import HTTPBasicAuth import mod.network_function -import mod.pmsh_utils -from mod import logger +from mod import logger, mdc_handler def get_pmsh_nfs_from_aai(app_conf, nf_filter): @@ -68,8 +67,8 @@ def _get_all_aai_nf_data(app_conf): }""" params = {'format': 'simple', 'nodesOnly': 'true'} response = session.put(aai_named_query_endpoint, headers=headers, - auth=HTTPBasicAuth(app_conf.aaf_creds.get('aaf_id'), - app_conf.aaf_creds.get('aaf_pass')), + auth=HTTPBasicAuth(app_conf.aaf_id, + app_conf.aaf_pass), data=data, params=params, verify=(app_conf.ca_cert_path if app_conf.enable_tls else False), cert=((app_conf.cert_path, @@ -102,7 +101,7 @@ def _get_aai_service_url(): raise -@mod.pmsh_utils.mdc_handler +@mdc_handler def _get_aai_request_headers(**kwargs): return {'accept': 'application/json', 'content-type': 'application/json', @@ -160,28 +159,22 @@ def get_aai_model_data(app_conf, model_invariant_id, model_version_id, nf_name): Returns: json (dict): the sdnc_model json object. - - Raises: - Exception: if AAI model data cannot be retrieved. """ - try: - session = requests.Session() - aai_model_ver_endpoint = \ - f'{_get_aai_service_url()}/service-design-and-creation/models/model/' \ - f'{model_invariant_id}/model-vers/model-ver/{model_version_id}' - - logger.info(f'Fetching sdnc-model info for xNF: {nf_name} from AAI.') - headers = _get_aai_request_headers() - response = session.get(aai_model_ver_endpoint, headers=headers, - auth=HTTPBasicAuth(app_conf.aaf_creds.get('aaf_id'), - app_conf.aaf_creds.get('aaf_pass')), - verify=(app_conf.ca_cert_path if app_conf.enable_tls else False), - cert=((app_conf.cert_path, - app_conf.key_path) if app_conf.enable_tls else None)) - response.raise_for_status() - if response.ok: - data = json.loads(response.text) - logger.debug(f'Successfully fetched sdnc-model info from AAI: {data}') - return data - except Exception: - raise + session = requests.Session() + aai_model_ver_endpoint = \ + f'{_get_aai_service_url()}/service-design-and-creation/models/model/' \ + f'{model_invariant_id}/model-vers/model-ver/{model_version_id}' + + logger.info(f'Fetching sdnc-model info for xNF: {nf_name} from AAI.') + headers = _get_aai_request_headers() + response = session.get(aai_model_ver_endpoint, headers=headers, + auth=HTTPBasicAuth(app_conf.aaf_id, + app_conf.aaf_pass), + verify=(app_conf.ca_cert_path if app_conf.enable_tls else False), + cert=((app_conf.cert_path, + app_conf.key_path) if app_conf.enable_tls else None)) + response.raise_for_status() + if response.ok: + data = json.loads(response.text) + logger.debug(f'Successfully fetched sdnc-model info from AAI: {data}') + return data diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/controller.py b/components/pm-subscription-handler/pmsh_service/mod/api/controller.py index 57d3e021..1aad0519 100755 --- a/components/pm-subscription-handler/pmsh_service/mod/api/controller.py +++ b/components/pm-subscription-handler/pmsh_service/mod/api/controller.py @@ -22,7 +22,6 @@ from mod.api.services import subscription_service, measurement_group_service from connexion import NoContent from mod.api.custom_exception import InvalidDataException, DuplicateDataException, \ DataConflictException -from mod.subscription import AdministrativeState def status(): @@ -69,6 +68,58 @@ def post_subscription(body): return response +def post_meas_group(subscription_name, measurement_group_name, body): + """ + Creates a measurement group for a subscription + + Args: + subscription_name (String): Name of the subscription. + measurement_group_name (String): Name of the measurement group + body (dict): measurement group request body to save. + + Returns: + Success : NoContent, 201 + Invalid Data: Invalid message, 400 + Not Found: Subscription no found, 404 + Duplicate Data : Duplicate field detail, 409 + + Raises: + Error: If anything fails in the server. + """ + response = NoContent, HTTPStatus.CREATED.value + try: + subscription = subscription_service.query_subscription_by_name(subscription_name) + if subscription is not None: + try: + measurement_group_service.create_measurement_group(subscription, + measurement_group_name, body) + except DuplicateDataException as e: + logger.error(f'Failed to create measurement group for ' + f'{subscription_name} due to duplicate data: {e}', + exc_info=True) + response = e.args[0], HTTPStatus.CONFLICT.value + except InvalidDataException as e: + logger.error(f'Failed to create measurement group for ' + f'{subscription_name} due to invalid data: {e}', + exc_info=True) + response = e.args[0], HTTPStatus.BAD_REQUEST.value + except Exception as e: + logger.error(f'Failed to create measurement group due to exception {e}') + response = e.args[0], HTTPStatus.INTERNAL_SERVER_ERROR.value + else: + logger.error('queried subscription was un successful with the name: ' + f'{subscription_name}') + return {'error': 'Subscription was not defined with the name : ' + f'{subscription_name}'}, HTTPStatus.NOT_FOUND.value + + except Exception as exception: + logger.error(f'While querying the subscription with name: {subscription_name}, ' + f'it occurred the following exception "{exception}"') + return {'error': 'Request was not processed due to Exception : ' + f'{exception}'}, HTTPStatus.INTERNAL_SERVER_ERROR.value + return response + + def get_subscription_by_name(subscription_name): """ Retrieves subscription based on the name @@ -169,7 +220,8 @@ def delete_meas_group_by_name(subscription_name, measurement_group_name): measurement_group_administrative_status = \ measurement_group_service.query_get_meas_group_admin_status(subscription_name, measurement_group_name) - if measurement_group_administrative_status == AdministrativeState.LOCKED.value: + if measurement_group_administrative_status == \ + measurement_group_service.AdministrativeState.LOCKED.value: if measurement_group_service.query_to_delete_meas_group(subscription_name, measurement_group_name) == 1: return None, HTTPStatus.NO_CONTENT diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml b/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml index 1f24f171..b88b9bf9 100644 --- a/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml +++ b/components/pm-subscription-handler/pmsh_service/mod/api/pmsh_swagger.yml @@ -160,6 +160,37 @@ paths: description: Exception occurred while querying database /subscription/{subscription_name}/measurementGroups/{measurement_group_name}: + post: + description: Create a measurement group for a given subscription + operationId: mod.api.controller.post_meas_group + tags: + - "Measurement Group" + parameters: + - name : subscription_name + in: path + required: true + description: Name of the subscription + type: string + - name: measurement_group_name + in: path + required: true + description: Name of the measurement group + type: string + - name: "body" + in: "body" + required: true + schema: + $ref: "#/definitions/measurementGroup" + responses: + 201: + description: Successfully created measurement group + 404: + description: Subscription with the specified name not found + 409: + description: Duplicate data + 500: + description: Internal server error + get: description: Get the measurement group and associated network functions from PMSH by using sub name and meas group name diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py b/components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py index 07d1b642..9045ac66 100644 --- a/components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py +++ b/components/pm-subscription-handler/pmsh_service/mod/api/services/measurement_group_service.py @@ -16,15 +16,102 @@ # SPDX-License-Identifier: Apache-2.0 # ============LICENSE_END===================================================== -from mod.api.custom_exception import InvalidDataException, DataConflictException -from mod.api.db_models import MeasurementGroupModel, NfMeasureGroupRelationalModel, \ - SubscriptionModel +from mod.api.custom_exception import InvalidDataException, \ + DataConflictException, DuplicateDataException +from mod.api.db_models import MeasurementGroupModel, \ + NfMeasureGroupRelationalModel, SubscriptionModel from mod import db, logger from mod.api.services import nf_service, subscription_service from mod.network_function import NetworkFunction from mod.pmsh_config import MRTopic, AppConfig -from mod.subscription import AdministrativeState, SubNfState from sqlalchemy import or_ +from enum import Enum + + +class MgNfState(Enum): + PENDING_CREATE = 'PENDING_CREATE' + CREATE_FAILED = 'CREATE_FAILED' + CREATED = 'CREATED' + PENDING_DELETE = 'PENDING_DELETE' + DELETE_FAILED = 'DELETE_FAILED' + DELETED = 'DELETED' + + +class AdministrativeState(Enum): + UNLOCKED = 'UNLOCKED' + LOCKING = 'LOCKING' + LOCKED = 'LOCKED' + FILTERING = 'FILTERING' + + +mg_nf_states = { + AdministrativeState.LOCKED.value: { + 'success': MgNfState.DELETED, + 'failed': MgNfState.DELETE_FAILED + }, + AdministrativeState.UNLOCKED.value: { + 'success': MgNfState.CREATED, + 'failed': MgNfState.CREATE_FAILED + }, + AdministrativeState.LOCKING.value: { + 'success': MgNfState.DELETED, + 'failed': MgNfState.DELETE_FAILED + } +} + + +def create_measurement_group(subscription, measurement_group_name, body): + """ + Creates a measurement group for a subscription + + Args: + subscription (SubscriptionModel): Subscription. + measurement_group_name (String): Name of MeasGroup + body (dict): measurement group request body to save. + + """ + logger.info(f'Initiating create measurement group for: {measurement_group_name}') + check_duplication(subscription.subscription_name, measurement_group_name) + check_measurement_group_names_comply(measurement_group_name, body) + new_mg = [save_measurement_group(body["measurementGroup"], subscription.subscription_name)] + if body["measurementGroup"]["administrativeState"] == AdministrativeState.UNLOCKED.value: + filtered_nfs = nf_service.capture_filtered_nfs(subscription.subscription_name) + subscription_service.add_new_filtered_nfs(filtered_nfs, new_mg, subscription) + else: + logger.info(f'Measurement Group {measurement_group_name} is not in an unlocked state') + db.session.commit() + + +def check_measurement_group_names_comply(measurement_group_name, measurement_group): + """ + Check if measurement_group_name matches the name in the URI + + Args: + measurement_group_name (String): Name of the measurement group + measurement_group (dict): Measurement Group + + """ + logger.info("Checking names match") + if measurement_group_name != measurement_group["measurementGroup"]["measurementGroupName"]: + logger.info(f'Changing measurement_group_name in body to {measurement_group_name}') + measurement_group["measurementGroup"]["measurementGroupName"] = measurement_group_name + + +def check_duplication(subscription_name, measurement_group_name): + """ + Check if measurement group exists already + + Args: + measurement_group_name (String): Name of the measurement group + subscription_name (string) : subscription name to associate with measurement group. + + Raises: + DuplicateDataException: exception containing the detail on duplicate data field. + """ + logger.info(f"Checking that measurement group {measurement_group_name} does not exist") + if query_meas_group_by_name(subscription_name, measurement_group_name): + raise DuplicateDataException(f'Measurement Group Name: ' + f'{measurement_group_name} already exists.') def save_measurement_group(measurement_group, subscription_name): @@ -133,10 +220,6 @@ def delete_nf_to_measurement_group(nf_name, measurement_group_name, status): NfMeasureGroupRelationalModel.nf_name == nf_name).one_or_none() db.session.delete(nf_measurement_group_rel) db.session.commit() - nf_relations = NfMeasureGroupRelationalModel.query.filter( - NfMeasureGroupRelationalModel.nf_name == nf_name).all() - if not nf_relations: - NetworkFunction.delete(nf_name=nf_name) except Exception as e: logger.error(f'Failed to delete nf: {nf_name} for measurement group: ' f'{measurement_group_name} due to: {e}') @@ -229,7 +312,7 @@ def deactivate_nfs(sub_model, measurement_group, nf_meas_relations): logger.info(f'Saving measurement group to nf name, measure_grp_name: {nf.nf_name},' f'{measurement_group.measurement_group_name} with DELETE request') update_measurement_group_nf_status(measurement_group.measurement_group_name, - SubNfState.PENDING_DELETE.value, nf.nf_name) + MgNfState.PENDING_DELETE.value, nf.nf_name) try: network_function = NetworkFunction(**nf.serialize_meas_group_nfs()) logger.info(f'Publishing event for nf name, measure_grp_name: {nf.nf_name},' @@ -267,7 +350,7 @@ def activate_nfs(sub_model, measurement_group): apply_nf_status_to_measurement_group(nf.nf_name, measurement_group.measurement_group_name, - SubNfState.PENDING_CREATE.value) + MgNfState.PENDING_CREATE.value) db.session.commit() try: network_function = NetworkFunction(**nf.serialize_nf()) @@ -331,12 +414,12 @@ def filter_nf_to_meas_grp(nf_name, measurement_group_name, status): status (string): status of the network function for measurement group """ try: - if status == SubNfState.DELETED.value: + if status == MgNfState.DELETED.value: delete_nf_to_measurement_group(nf_name, measurement_group_name, - SubNfState.DELETED.value) - elif status == SubNfState.CREATED.value: + MgNfState.DELETED.value) + elif status == MgNfState.CREATED.value: update_measurement_group_nf_status(measurement_group_name, - SubNfState.CREATED.value, nf_name) + MgNfState.CREATED.value, nf_name) nf_measurement_group_rels = NfMeasureGroupRelationalModel.query.filter( NfMeasureGroupRelationalModel.measurement_grp_name == measurement_group_name, or_(NfMeasureGroupRelationalModel.nf_measure_grp_status.like('PENDING_%'), diff --git a/components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py b/components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py index 032fc4a0..6216a803 100644 --- a/components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py +++ b/components/pm-subscription-handler/pmsh_service/mod/api/services/subscription_service.py @@ -23,7 +23,6 @@ from mod.api.db_models import SubscriptionModel, NfSubRelationalModel, \ from mod.api.services import measurement_group_service, nf_service from mod.api.custom_exception import InvalidDataException, DuplicateDataException, \ DataConflictException -from mod.subscription import AdministrativeState, SubNfState from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import joinedload @@ -155,7 +154,7 @@ def apply_measurement_grp_to_nfs(filtered_nfs, unlocked_mgs): f'{measurement_group.measurement_group_name}') measurement_group_service.apply_nf_status_to_measurement_group( nf.nf_name, measurement_group.measurement_group_name, - SubNfState.PENDING_CREATE.value) + measurement_group_service.MgNfState.PENDING_CREATE.value) def check_missing_data(subscription): @@ -261,7 +260,7 @@ def save_subscription(subscription): SubscriptionModel(subscription_name=subscription["subscriptionName"], operational_policy_name=subscription["operationalPolicyName"], control_loop_name=control_loop_name, - status=AdministrativeState.LOCKED.value) + status=measurement_group_service.AdministrativeState.LOCKED.value) db.session.add(subscription_model) return subscription_model @@ -450,7 +449,7 @@ def get_unlocked_measurement_grps(sub_model): unlocked_mgs = [] for measurement_group in sub_model.measurement_groups: if measurement_group.administrative_state \ - == AdministrativeState.UNLOCKED.value: + == measurement_group_service.AdministrativeState.UNLOCKED.value: unlocked_mgs.append(measurement_group) else: logger.info(f'No nfs added as measure_grp_name: ' @@ -474,7 +473,8 @@ def delete_filtered_nfs(del_nfs, sub_model, unlocked_mgs): for mg in unlocked_mgs: MeasurementGroupModel.query.filter( MeasurementGroupModel.measurement_group_name == mg.measurement_group_name) \ - .update({MeasurementGroupModel.administrative_state: AdministrativeState. + .update({MeasurementGroupModel.administrative_state: + measurement_group_service.AdministrativeState. FILTERING.value}, synchronize_session='evaluate') db.session.commit() nf_meas_relations = NfMeasureGroupRelationalModel.query.filter( @@ -515,7 +515,9 @@ def validate_sub_mgs_state(sub_model): DataConflictException: contains details on conflicting status in measurement group """ mg_names_processing = [mg for mg in sub_model.measurement_groups - if mg.administrative_state in [AdministrativeState.FILTERING.value, + if mg.administrative_state in [measurement_group_service. + AdministrativeState.FILTERING.value, + measurement_group_service. AdministrativeState.LOCKING.value]] if mg_names_processing: raise DataConflictException('Cannot update filter as subscription: ' diff --git a/components/pm-subscription-handler/pmsh_service/mod/exit_handler.py b/components/pm-subscription-handler/pmsh_service/mod/exit_handler.py index 16223790..f558f365 100755 --- a/components/pm-subscription-handler/pmsh_service/mod/exit_handler.py +++ b/components/pm-subscription-handler/pmsh_service/mod/exit_handler.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2020-2022 Nordix Foundation. +# Copyright (C) 2020-2023 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ from mod import logger, db from mod.api.services import subscription_service, measurement_group_service -from mod.subscription import AdministrativeState +from mod.api.services.measurement_group_service import AdministrativeState class ExitHandler: @@ -49,7 +49,8 @@ class ExitHandler: logger.info(f'Cancelling thread {thread.name}') thread.cancel() logger.info('Closing all DB connections') - db.session.bind.dispose() + if db.session.bind is not None: + db.session.bind.dispose() db.session.close() db.engine.dispose() ExitHandler.shutdown_signal_received = True diff --git a/components/pm-subscription-handler/pmsh_service/mod/pmsh_config.py b/components/pm-subscription-handler/pmsh_service/mod/pmsh_config.py index 9c282ab7..295fc379 100644 --- a/components/pm-subscription-handler/pmsh_service/mod/pmsh_config.py +++ b/components/pm-subscription-handler/pmsh_service/mod/pmsh_config.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2021 Nordix Foundation. +# Copyright (C) 2021-2022 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,8 +28,7 @@ from onap_dcae_cbs_docker_client.client import get_all from requests.auth import HTTPBasicAuth from tenacity import wait_fixed, stop_after_attempt, retry, retry_if_exception_type -from mod import logger -from mod.pmsh_utils import mdc_handler +from mod import logger, mdc_handler @unique @@ -67,8 +66,6 @@ class AppConfig(metaclass=MetaSingleton): self.aaf_pass = app_config['config'].get('aaf_password') self.streams_publishes = app_config['config'].get('streams_publishes') self.streams_subscribes = app_config['config'].get('streams_subscribes') - # TODO: aaf_creds variable should be removed on code cleanup - self.aaf_creds = {'aaf_id': self.aaf_id, 'aaf_pass': self.aaf_pass} @staticmethod def get_instance(): @@ -94,7 +91,7 @@ class AppConfig(metaclass=MetaSingleton): return config except Exception as e: logger.error(f'Failed to get config from CBS: {e}', exc_info=True) - raise ValueError(e) + raise ValueError(e) from e @mdc_handler def publish_to_topic(self, mr_topic, event_json, **kwargs): @@ -104,22 +101,16 @@ class AppConfig(metaclass=MetaSingleton): Args: mr_topic (enum) : Message Router topic to publish. event_json (dict): the json data to be published. - - Raises: - Exception: if post request fails. """ - try: - session = requests.Session() - topic_url = self.streams_publishes[mr_topic].get('dmaap_info').get('topic_url') - headers = {'content-type': 'application/json', 'x-transactionid': kwargs['request_id'], - 'InvocationID': kwargs['invocation_id'], 'RequestID': kwargs['request_id']} - logger.info(f'Publishing event to MR topic: {topic_url}') - response = session.post(topic_url, headers=headers, - auth=HTTPBasicAuth(self.aaf_id, self.aaf_pass), json=event_json, - verify=(self.ca_cert_path if self.enable_tls else False)) - response.raise_for_status() - except Exception as e: - raise e + session = requests.Session() + topic_url = self.streams_publishes[mr_topic].get('dmaap_info').get('topic_url') + headers = {'content-type': 'application/json', 'x-transactionid': kwargs['request_id'], + 'InvocationID': kwargs['invocation_id'], 'RequestID': kwargs['request_id']} + logger.info(f'Publishing event to MR topic: {topic_url}') + response = session.post(topic_url, headers=headers, + auth=HTTPBasicAuth(self.aaf_id, self.aaf_pass), json=event_json, + verify=(self.ca_cert_path if self.enable_tls else False)) + response.raise_for_status() @mdc_handler def get_from_topic(self, mr_topic, consumer_id, consumer_group='dcae_pmsh_cg', timeout=5000, @@ -149,7 +140,6 @@ class AppConfig(metaclass=MetaSingleton): verify=(self.ca_cert_path if self.enable_tls else False)) if response.status_code == 503: logger.error(f'MR Service is unavailable at present: {response.content}') - pass response.raise_for_status() if response.ok: return response.json() diff --git a/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py b/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py deleted file mode 100755 index d1790bbb..00000000 --- a/components/pm-subscription-handler/pmsh_service/mod/pmsh_utils.py +++ /dev/null @@ -1,313 +0,0 @@ -# ============LICENSE_START=================================================== -# Copyright (C) 2019-2021 Nordix Foundation. -# ============================================================================ -# 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. -# -# SPDX-License-Identifier: Apache-2.0 -# ============LICENSE_END===================================================== -import json -import os -import uuid -from functools import wraps -from json import JSONDecodeError -from os import getenv -from threading import Timer - -import requests -from jsonschema import validate, ValidationError -from onap_dcae_cbs_docker_client.client import get_all -from onaplogging.mdcContext import MDC -from requests.auth import HTTPBasicAuth -from tenacity import wait_fixed, stop_after_attempt, retry, retry_if_exception_type - -from mod import logger -from mod.subscription import Subscription - - -def mdc_handler(func): - @wraps(func) - def wrapper(*args, **kwargs): - request_id = str(uuid.uuid1()) - invocation_id = str(uuid.uuid1()) - MDC.put('ServiceName', getenv('HOSTNAME')) - MDC.put('RequestID', request_id) - MDC.put('InvocationID', invocation_id) - - kwargs['request_id'] = request_id - kwargs['invocation_id'] = invocation_id - return func(*args, **kwargs) - - return wrapper - - -def _load_sub_schema_from_file(): - try: - with open(os.path.join(os.path.dirname(__file__), 'sub_schema.json')) as sub: - return json.load(sub) - except OSError as err: - logger.error(f'Failed to read sub schema file: {err}', exc_info=True) - except JSONDecodeError as json_err: - logger.error(f'sub schema file is not a valid JSON file: {json_err}', exc_info=True) - - -class AppConfig: - INSTANCE = None - - def __init__(self): - conf = self._get_pmsh_config() - self.aaf_creds = {'aaf_id': conf['config'].get('aaf_identity'), - 'aaf_pass': conf['config'].get('aaf_password')} - self.enable_tls = conf['config'].get('enable_tls') - self.ca_cert_path = conf['config'].get('ca_cert_path') - self.cert_path = conf['config'].get('cert_path') - self.key_path = conf['config'].get('key_path') - self.streams_subscribes = conf['config'].get('streams_subscribes') - self.streams_publishes = conf['config'].get('streams_publishes') - self.operational_policy_name = conf['config'].get('operational_policy_name') - self.control_loop_name = conf['config'].get('control_loop_name') - self.sub_schema = _load_sub_schema_from_file() - self.subscription = Subscription(self.control_loop_name, - self.operational_policy_name, - **conf['config']['pmsh_policy']['subscription']) - self.nf_filter = None - - def __new__(cls, *args, **kwargs): - if AppConfig.INSTANCE is None: - AppConfig.INSTANCE = super().__new__(cls, *args, **kwargs) - return AppConfig.INSTANCE - - @mdc_handler - @retry(wait=wait_fixed(5), stop=stop_after_attempt(5), - retry=retry_if_exception_type(ValueError)) - def _get_pmsh_config(self, **kwargs): - """ Retrieves PMSH's configuration from Config binding service. If a non-2xx response - is received, it retries after 2 seconds for 5 times before raising an exception. - - Returns: - dict: Dictionary representation of the the service configuration - - Raises: - Exception: If any error occurred pulling configuration from Config binding service. - """ - try: - logger.info('Attempting to fetch PMSH Configuration from CBS.') - config = get_all() - logger.info(f'Successfully fetched PMSH config from CBS: {config}') - return config - except Exception as e: - logger.error(f'Failed to get config from CBS: {e}', exc_info=True) - raise ValueError(e) - - def validate_sub_schema(self): - """ - Validates schema of PMSH subscription - - Raises: - ValidationError: If the PMSH subscription schema is invalid - """ - sub_data = self.subscription.__dict__ - validate(instance=sub_data, schema=self.sub_schema) - nf_filter = sub_data["nfFilter"] - if not [filter_name for filter_name, val in nf_filter.items() if len(val) > 0]: - raise ValidationError("At least one filter within nfFilter must not be empty") - logger.debug("Subscription schema is valid.") - - def refresh_config(self): - """ - Update the relevant attributes of the AppConfig object. - - Raises: - Exception: if cbs request fails. - """ - try: - app_conf = self._get_pmsh_config() - self.operational_policy_name = app_conf['config'].get('operational_policy_name') - self.control_loop_name = app_conf['config'].get('control_loop_name') - self.subscription = Subscription(self.control_loop_name, - self.operational_policy_name, - **app_conf['config']['pmsh_policy']['subscription']) - logger.info("AppConfig data has been refreshed") - except Exception: - logger.error('Failed to refresh PMSH AppConfig') - raise - - def get_mr_sub(self, sub_name): - """ - Returns the MrSub object requested. - - Args: - sub_name: the key of the subscriber object. - - Returns: - MrSub: an Instance of an `MrSub` <MrSub> Object. - - Raises: - KeyError: if the sub_name is not found. - """ - try: - return _MrSub(sub_name, self.aaf_creds, self.ca_cert_path, - self.enable_tls, self.cert_params, **self.streams_subscribes[sub_name]) - except KeyError as e: - logger.error(f'Failed to get MrSub {sub_name}: {e}', exc_info=True) - raise - - def get_mr_pub(self, pub_name): - """ - Returns the MrPub object requested. - - Args: - pub_name: the key of the publisher object. - - Returns: - MrPub: an Instance of an `MrPub` <MrPub> Object. - - Raises: - KeyError: if the sub_name is not found. - """ - try: - return _MrPub(pub_name, self.aaf_creds, self.ca_cert_path, - self.enable_tls, self.cert_params, **self.streams_publishes[pub_name]) - except KeyError as e: - logger.error(f'Failed to get MrPub {pub_name}: {e}', exc_info=True) - raise - - @property - def cert_params(self): - """ - Returns the tls artifact paths. - - Returns: - cert_path, key_path (tuple): the path to tls cert and key. - """ - return self.cert_path, self.key_path - - -class _DmaapMrClient: - def __init__(self, aaf_creds, ca_cert_path, enable_tls, cert_params, **kwargs): - """ - A DMaaP Message Router utility class. - Sub classes should be invoked via the AppConfig.get_mr_{pub|sub} only. - Args: - aaf_creds (dict): a dict of aaf secure credentials. - ca_cert_path (str): path to the ca certificate. - enable_tls (bool): TLS if True, else False - cert_params (tuple): client side (cert, key) tuple. - **kwargs: a dict of streams_{subscribes|publishes} data. - """ - self.topic_url = kwargs.get('dmaap_info').get('topic_url') - self.aaf_id = aaf_creds.get('aaf_id') - self.aaf_pass = aaf_creds.get('aaf_pass') - self.ca_cert_path = ca_cert_path - self.enable_tls = enable_tls - self.cert_params = cert_params - - -class _MrPub(_DmaapMrClient): - def __init__(self, pub_name, aaf_creds, ca_cert_path, enable_tls, cert_params, **kwargs): - self.pub_name = pub_name - super().__init__(aaf_creds, ca_cert_path, enable_tls, cert_params, **kwargs) - - @mdc_handler - def publish_to_topic(self, event_json, **kwargs): - """ - Publish the event to the DMaaP Message Router topic. - - Args: - event_json (dict): the json data to be published. - - Raises: - Exception: if post request fails. - """ - try: - session = requests.Session() - headers = {'content-type': 'application/json', 'x-transactionid': kwargs['request_id'], - 'InvocationID': kwargs['invocation_id'], - 'RequestID': kwargs['request_id'] - } - logger.info(f'Publishing event to {self.topic_url}') - response = session.post(self.topic_url, headers=headers, - auth=HTTPBasicAuth(self.aaf_id, self.aaf_pass), json=event_json, - verify=(self.ca_cert_path if self.enable_tls else False)) - response.raise_for_status() - except Exception as e: - raise e - - def publish_subscription_event_data(self, subscription, nf): - """ - Update the Subscription dict with xnf and policy name then publish to DMaaP MR topic. - - Args: - subscription (Subscription): the `Subscription` <Subscription> object. - nf (NetworkFunction): the NetworkFunction to include in the event. - """ - try: - subscription_event = subscription.prepare_subscription_event(nf) - logger.debug(f'Subscription event: {subscription_event}') - self.publish_to_topic(subscription_event) - except Exception as e: - logger.error(f'Failed to publish to topic {self.topic_url}: {e}', exc_info=True) - raise e - - -class _MrSub(_DmaapMrClient): - def __init__(self, sub_name, aaf_creds, ca_cert_path, enable_tls, cert_params, **kwargs): - self.sub_name = sub_name - super().__init__(aaf_creds, ca_cert_path, enable_tls, cert_params, **kwargs) - - @mdc_handler - def get_from_topic(self, consumer_id, consumer_group='dcae_pmsh_cg', timeout=1000, **kwargs): - """ - Returns the json data from the MrTopic. - - Args: - consumer_id (str): Within your subscribers group, a name that uniquely - identifies your subscribers process. - consumer_group (str): A name that uniquely identifies your subscribers. - timeout (int): The request timeout value in mSec. - - Returns: - list[str]: the json response from DMaaP Message Router topic. - """ - try: - session = requests.Session() - headers = {'accept': 'application/json', 'content-type': 'application/json', - 'InvocationID': kwargs['invocation_id'], - 'RequestID': kwargs['request_id']} - logger.info(f'Fetching messages from MR topic: {self.topic_url}') - response = session.get(f'{self.topic_url}/{consumer_group}/{consumer_id}' - f'?timeout={timeout}', - auth=HTTPBasicAuth(self.aaf_id, self.aaf_pass), headers=headers, - verify=(self.ca_cert_path if self.enable_tls else False)) - if response.status_code == 503: - logger.error(f'MR Service is unavailable at present: {response.content}') - pass - response.raise_for_status() - if response.ok: - return response.json() - except Exception as e: - logger.error(f'Failed to fetch message from MR: {e}', exc_info=True) - raise - - -class PeriodicTask(Timer): - """ - See :class:`Timer`. - """ - - def run(self): - self.function(*self.args, **self.kwargs) - while not self.finished.wait(self.interval): - try: - self.function(*self.args, **self.kwargs) - except Exception as e: - logger.error(f'Exception in thread: {self.name}: {e}', exc_info=True) diff --git a/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py b/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py index 5065ce8a..cfcda091 100644 --- a/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py +++ b/components/pm-subscription-handler/pmsh_service/mod/policy_response_handler.py @@ -16,9 +16,11 @@ # SPDX-License-Identifier: Apache-2.0 # ============LICENSE_END===================================================== import json + +from mod.api.services.measurement_group_service import mg_nf_states, \ + AdministrativeState, MgNfState from mod.pmsh_config import MRTopic, AppConfig from mod import logger -from mod.subscription import AdministrativeState, subscription_nf_states, SubNfState from mod.api.db_models import MeasurementGroupModel, NfMeasureGroupRelationalModel from mod.api.services import measurement_group_service @@ -96,12 +98,12 @@ class PolicyResponseHandler: NfMeasureGroupRelationalModel.measurement_grp_name == measurement_group_name, NfMeasureGroupRelationalModel.nf_name == nf_name ).one_or_none() - if nf_msg_rel.nf_measure_grp_status == SubNfState.PENDING_DELETE.value: + if nf_msg_rel.nf_measure_grp_status == MgNfState.PENDING_DELETE.value: administrative_state = AdministrativeState.LOCKING.value - elif nf_msg_rel.nf_measure_grp_status == SubNfState.PENDING_CREATE.value: + elif nf_msg_rel.nf_measure_grp_status == MgNfState.PENDING_CREATE.value: administrative_state = AdministrativeState.UNLOCKED.value - nf_measure_grp_status = (subscription_nf_states[administrative_state] + nf_measure_grp_status = (mg_nf_states[administrative_state] [response_message]).value policy_response_handle_functions[administrative_state][response_message]( measurement_group_name=measurement_group_name, status=nf_measure_grp_status, diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription.py b/components/pm-subscription-handler/pmsh_service/mod/subscription.py deleted file mode 100755 index ddb6e1f5..00000000 --- a/components/pm-subscription-handler/pmsh_service/mod/subscription.py +++ /dev/null @@ -1,295 +0,0 @@ -# ============LICENSE_START=================================================== -# Copyright (C) 2019-2022 Nordix Foundation. -# ============================================================================ -# 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. -# -# SPDX-License-Identifier: Apache-2.0 -# ============LICENSE_END===================================================== -from enum import Enum - -from mod import db, logger -from mod.api.db_models import SubscriptionModel, NfSubRelationalModel, NetworkFunctionModel - - -class SubNfState(Enum): - PENDING_CREATE = 'PENDING_CREATE' - CREATE_FAILED = 'CREATE_FAILED' - CREATED = 'CREATED' - PENDING_DELETE = 'PENDING_DELETE' - DELETE_FAILED = 'DELETE_FAILED' - DELETED = 'DELETED' - - -class AdministrativeState(Enum): - UNLOCKED = 'UNLOCKED' - LOCKING = 'LOCKING' - LOCKED = 'LOCKED' - FILTERING = 'FILTERING' - - -subscription_nf_states = { - AdministrativeState.LOCKED.value: { - 'success': SubNfState.DELETED, - 'failed': SubNfState.DELETE_FAILED - }, - AdministrativeState.UNLOCKED.value: { - 'success': SubNfState.CREATED, - 'failed': SubNfState.CREATE_FAILED - }, - AdministrativeState.LOCKING.value: { - 'success': SubNfState.DELETED, - 'failed': SubNfState.DELETE_FAILED - } -} - - -def _get_nf_objects(nf_sub_relationships): - nfs = [] - for nf_sub_entry in nf_sub_relationships: - nf_model_object = NetworkFunctionModel.query.filter( - NetworkFunctionModel.nf_name == nf_sub_entry.nf_name).one_or_none() - nfs.append(nf_model_object.to_nf()) - return nfs - - -class Subscription: - def __init__(self, control_loop_name, operational_policy_name, **kwargs): - self.subscriptionName = kwargs.get('subscriptionName') - self.administrativeState = kwargs.get('administrativeState') - self.fileBasedGP = kwargs.get('fileBasedGP') - self.fileLocation = kwargs.get('fileLocation') - self.nfFilter = kwargs.get('nfFilter') - self.measurementGroups = kwargs.get('measurementGroups') - self.control_loop_name = control_loop_name - self.operational_policy_name = operational_policy_name - self.create() - - def update_sub_params(self, admin_state, file_based_gp, file_location, meas_groups): - self.administrativeState = admin_state - self.fileBasedGP = file_based_gp - self.fileLocation = file_location - self.measurementGroups = meas_groups - - def create(self): - """ Creates a subscription database entry - - Returns: - Subscription object - """ - try: - existing_subscription = (SubscriptionModel.query.filter( - SubscriptionModel.subscription_name == self.subscriptionName).one_or_none()) - if existing_subscription is None: - new_subscription = \ - SubscriptionModel(subscription_name=self.subscriptionName, - operational_policy_name=self.operational_policy_name, - control_loop_name=self.control_loop_name, - status=AdministrativeState.LOCKED.value) - - db.session.add(new_subscription) - db.session.commit() - return new_subscription - else: - logger.debug(f'Subscription {self.subscriptionName} already exists,' - f' returning this subscription..') - return existing_subscription - except Exception as e: - logger.error(f'Failed to create subscription {self.subscriptionName} in the DB: {e}', - exc_info=True) - finally: - db.session.remove() - - def update_subscription_status(self): - """ Updates the status of subscription in subscription table """ - try: - SubscriptionModel.query.filter( - SubscriptionModel.subscription_name == self.subscriptionName) \ - .update({SubscriptionModel.status: self.administrativeState}, - synchronize_session='evaluate') - - db.session.commit() - except Exception as e: - logger.error(f'Failed to update status of subscription: {self.subscriptionName}: {e}', - exc_info=True) - finally: - db.session.remove() - - def prepare_subscription_event(self, nf): - """Prepare the sub event for publishing - - Args: - nf (NetworkFunction): the AAI nf. - - Returns: - dict: the Subscription event to be published. - """ - try: - clean_sub = \ - {k: v for k, v in self.__dict__.items() if - (k != 'nfFilter' and k != 'control_loop_name' and k != 'operational_policy_name')} - if self.administrativeState == AdministrativeState.LOCKING.value: - change_type = 'DELETE' - else: - change_type = 'CREATE' - - sub_event = { - 'nfName': nf.nf_name, - 'ipAddress': nf.ipv4_address if nf.ipv6_address in (None, '') else nf.ipv6_address, - 'blueprintName': nf.sdnc_model_name, - 'blueprintVersion': nf.sdnc_model_version, - 'operationalPolicyName': self.operational_policy_name, - 'changeType': change_type, - 'controlLoopName': self.control_loop_name, - 'subscription': clean_sub} - return sub_event - except Exception as e: - logger.error(f'Failed to prep Sub event for xNF {nf.nf_name}: {e}', exc_info=True) - raise - - def add_network_function_to_subscription(self, nf, sub_model): - """ Associates a network function to a Subscription - - Args: - sub_model(SubscriptionModel): The SubscriptionModel from the DB. - nf(NetworkFunction): A NetworkFunction object. - """ - try: - current_nf = nf.create() - existing_entry = NfSubRelationalModel.query.filter( - NfSubRelationalModel.subscription_name == self.subscriptionName, - NfSubRelationalModel.nf_name == current_nf.nf_name).one_or_none() - if existing_entry is None: - new_nf_sub = NfSubRelationalModel(self.subscriptionName, - nf.nf_name, SubNfState.PENDING_CREATE.value) - sub_model.nfs.append(new_nf_sub) - db.session.add(sub_model) - db.session.commit() - logger.info(f'Network function {current_nf.nf_name} added to Subscription ' - f'{self.subscriptionName}') - except Exception as e: - logger.error(f'Failed to add nf {nf.nf_name} to subscription ' - f'{self.subscriptionName}: {e}', exc_info=True) - logger.debug(f'Subscription {self.subscriptionName} now contains these XNFs:' - f'{[nf.nf_name for nf.nf_name in self.get_network_functions()]}') - - def get(self): - """ Retrieves a SubscriptionModel object - - Returns: - SubscriptionModel object else None - """ - sub_model = SubscriptionModel.query.filter( - SubscriptionModel.subscription_name == self.subscriptionName).one_or_none() - return sub_model - - def get_local_sub_admin_state(self): - """ Retrieves the subscription admin state - - Returns: - str: The admin state of the SubscriptionModel - """ - sub_model = SubscriptionModel.query.filter( - SubscriptionModel.subscription_name == self.subscriptionName).one_or_none() - db.session.remove() - return sub_model.status - - def create_subscription_on_nfs(self, nfs, mr_pub): - """ Publishes an event to create a Subscription on an nf - - Args: - nfs(list[NetworkFunction]): A list of NetworkFunction Objects. - mr_pub (_MrPub): MR publisher - """ - try: - existing_nfs = self.get_network_functions() - sub_model = self.get() - for nf in [new_nf for new_nf in nfs if new_nf not in existing_nfs]: - logger.info(f'Publishing event to create ' - f'Sub: {self.subscriptionName} on nf: {nf.nf_name}') - mr_pub.publish_subscription_event_data(self, nf) - self.add_network_function_to_subscription(nf, sub_model) - self.update_sub_nf_status(self.subscriptionName, SubNfState.PENDING_CREATE.value, - nf.nf_name) - except Exception as err: - raise Exception(f'Error publishing create event to MR: {err}') - - def delete_subscription_from_nfs(self, nfs, mr_pub): - """ Publishes an event to delete a Subscription from an nf - - Args: - nfs(list[NetworkFunction]): A list of NetworkFunction Objects. - mr_pub (_MrPub): MR publisher - """ - try: - for nf in nfs: - logger.debug(f'Publishing Event to delete ' - f'Sub: {self.subscriptionName} from the nf: {nf.nf_name}') - mr_pub.publish_subscription_event_data(self, nf) - self.update_sub_nf_status(self.subscriptionName, - SubNfState.PENDING_DELETE.value, - nf.nf_name) - except Exception as err: - raise Exception(f'Error publishing delete event to MR: {err}') - - @staticmethod - def get_all_nfs_subscription_relations(): - """ Retrieves all network function to subscription relations - - Returns: - list(NfSubRelationalModel): NetworkFunctions per Subscription list else empty - """ - nf_per_subscriptions = NfSubRelationalModel.query.all() - db.session.remove() - return nf_per_subscriptions - - @staticmethod - def update_sub_nf_status(subscription_name, status, nf_name): - """ Updates the status of the subscription for a particular nf - - Args: - subscription_name (str): The subscription name - nf_name (str): The network function name - status (str): Status of the subscription - """ - try: - NfSubRelationalModel.query.filter( - NfSubRelationalModel.subscription_name == subscription_name, - NfSubRelationalModel.nf_name == nf_name). \ - update({NfSubRelationalModel.nf_sub_status: status}, synchronize_session='evaluate') - db.session.commit() - except Exception as e: - logger.error(f'Failed to update status of nf: {nf_name} for subscription: ' - f'{subscription_name}: {e}', exc_info=True) - - def get_network_functions(self): - nf_sub_relationships = NfSubRelationalModel.query.filter( - NfSubRelationalModel.subscription_name == self.subscriptionName) - nfs = _get_nf_objects(nf_sub_relationships) - db.session.remove() - return nfs - - def get_delete_failed_nfs(self): - nf_sub_relationships = NfSubRelationalModel.query.filter( - NfSubRelationalModel.subscription_name == self.subscriptionName, - NfSubRelationalModel.nf_sub_status == SubNfState.DELETE_FAILED.value) - nfs = _get_nf_objects(nf_sub_relationships) - db.session.remove() - return nfs - - def get_delete_pending_nfs(self): - nf_sub_relationships = NfSubRelationalModel.query.filter( - NfSubRelationalModel.subscription_name == self.subscriptionName, - NfSubRelationalModel.nf_sub_status == SubNfState.PENDING_DELETE.value) - nfs = _get_nf_objects(nf_sub_relationships) - db.session.remove() - return nfs diff --git a/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py b/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py deleted file mode 100644 index 5fbb9a6c..00000000 --- a/components/pm-subscription-handler/pmsh_service/mod/subscription_handler.py +++ /dev/null @@ -1,118 +0,0 @@ -# ============LICENSE_START=================================================== -# Copyright (C) 2020-2021 Nordix Foundation. -# ============================================================================ -# 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. -# -# SPDX-License-Identifier: Apache-2.0 -# ============LICENSE_END===================================================== -from jsonschema import ValidationError - -from mod import logger, aai_client -from mod.network_function import NetworkFunctionFilter -from mod.subscription import AdministrativeState - - -class SubscriptionHandler: - def __init__(self, mr_pub, aai_sub, app, app_conf): - self.mr_pub = mr_pub - self.aai_sub = aai_sub - self.app = app - self.app_conf = app_conf - self.aai_event_thread = None - - def execute(self): - """ - Checks for changes of administrative state in config and proceeds to process - the Subscription if a change has occurred - """ - self.app.app_context().push() - try: - local_admin_state = self.app_conf.subscription.get_local_sub_admin_state() - if local_admin_state == AdministrativeState.LOCKING.value: - self._check_for_failed_nfs() - else: - self.app_conf.refresh_config() - self.app_conf.validate_sub_schema() - new_administrative_state = self.app_conf.subscription.administrativeState - if local_admin_state == new_administrative_state: - logger.info(f'Administrative State did not change in the app config: ' - f'{new_administrative_state}') - else: - self._check_state_change(local_admin_state, new_administrative_state) - except (ValidationError, TypeError) as err: - logger.error(f'Error occurred during validation of subscription schema {err}', - exc_info=True) - except Exception as err: - logger.error(f'Error occurred during the activation/deactivation process {err}', - exc_info=True) - - def _check_state_change(self, local_admin_state, new_administrative_state): - if new_administrative_state == AdministrativeState.UNLOCKED.value: - logger.info(f'Administrative State has changed from {local_admin_state} ' - f'to {new_administrative_state}.') - self._activate(new_administrative_state) - elif new_administrative_state == AdministrativeState.LOCKED.value: - logger.info(f'Administrative State has changed from {local_admin_state} ' - f'to {new_administrative_state}.') - self._deactivate() - else: - raise Exception(f'Invalid AdministrativeState: {new_administrative_state}') - - def _activate(self, new_administrative_state): - if not self.app_conf.nf_filter: - self.app_conf.nf_filter = NetworkFunctionFilter(**self.app_conf.subscription.nfFilter) - self.app_conf.subscription.update_sub_params(new_administrative_state, - self.app_conf.subscription.fileBasedGP, - self.app_conf.subscription.fileLocation, - self.app_conf.subscription.measurementGroups) - nfs_in_aai = aai_client.get_pmsh_nfs_from_aai(self.app_conf, self.app_conf.nf_filter) - self.app_conf.subscription.create_subscription_on_nfs(nfs_in_aai, self.mr_pub) - self.app_conf.subscription.update_subscription_status() - - def _deactivate(self): - nfs = self.app_conf.subscription.get_network_functions() - if nfs: - self.stop_aai_event_thread() - self.app_conf.subscription.administrativeState = AdministrativeState.LOCKING.value - logger.info('Subscription is now LOCKING/DEACTIVATING.') - self.app_conf.subscription.delete_subscription_from_nfs(nfs, self.mr_pub) - self.app_conf.subscription.update_subscription_status() - - def stop_aai_event_thread(self): - if self.aai_event_thread is not None: - self.aai_event_thread.cancel() - self.aai_event_thread = None - logger.info('Stopping polling for NFs events on AAI-EVENT topic in MR.') - - def _check_for_failed_nfs(self): - logger.info('Checking for DELETE_FAILED NFs before LOCKING Subscription.') - del_failed_nfs = self.app_conf.subscription.get_delete_failed_nfs() - if del_failed_nfs or self.app_conf.subscription.get_delete_pending_nfs(): - for nf in del_failed_nfs: - nf_model = nf.get(nf.nf_name) - if nf_model.retry_count < 3: - logger.info(f'Retry deletion of subscription ' - f'{self.app_conf.subscription.subscriptionName} ' - f'from NF: {nf.nf_name}') - self.app_conf.subscription.delete_subscription_from_nfs([nf], self.mr_pub) - nf.increment_retry_count() - else: - logger.error(f'Failed to delete the subscription ' - f'{self.app_conf.subscription.subscriptionName} ' - f'from NF: {nf.nf_name} after {nf_model.retry_count} ' - f'attempts. Removing NF from DB') - nf.delete(nf_name=nf.nf_name) - else: - logger.info('Proceeding to LOCKED adminState.') - self.app_conf.subscription.administrativeState = AdministrativeState.LOCKED.value - self.app_conf.subscription.update_subscription_status() diff --git a/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py b/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py index 1d8b0b34..fcddde6a 100755 --- a/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py +++ b/components/pm-subscription-handler/pmsh_service/pmsh_service_main.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2019-2022 Nordix Foundation. +# Copyright (C) 2019-2023 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,8 +21,22 @@ from mod.aai_event_handler import AAIEventHandler from mod import db, create_app, launch_api_server, logger from mod.exit_handler import ExitHandler from mod.pmsh_config import AppConfig -from mod.pmsh_utils import PeriodicTask from mod.policy_response_handler import PolicyResponseHandler +from threading import Timer + + +class PeriodicTask(Timer): + """ + See :class:`Timer`. + """ + + def run(self): + self.function(*self.args, **self.kwargs) + while not self.finished.wait(self.interval): + try: + self.function(*self.args, **self.kwargs) + except Exception as e: + logger.error(f'Exception in thread: {self.name}: {e}', exc_info=True) def main(): @@ -30,7 +44,7 @@ def main(): try: app = create_app() app.app_context().push() - db.create_all(app=app) + db.create_all() pmsh_app_conf = AppConfig() except Exception as e: logger.error(f'Failed to get config and create application: {e}', exc_info=True) diff --git a/components/pm-subscription-handler/pom.xml b/components/pm-subscription-handler/pom.xml index 88ae50d5..5e1ee0f9 100644 --- a/components/pm-subscription-handler/pom.xml +++ b/components/pm-subscription-handler/pom.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- # ============LICENSE_START======================================================= -# Copyright (C) 2019-2022 Nordix Foundation. +# Copyright (C) 2019-2023 Nordix Foundation. # Copyright 2020 Deutsche Telekom. All rights reserved. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); @@ -32,7 +32,7 @@ <groupId>org.onap.dcaegen2.services</groupId> <artifactId>pmsh</artifactId> <name>dcaegen2-services-pm-subscription-handler</name> - <version>2.2.0-SNAPSHOT</version> + <version>2.2.3-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <sonar.sources>.</sonar.sources> diff --git a/components/pm-subscription-handler/setup.py b/components/pm-subscription-handler/setup.py index a4a80efb..a50239dc 100644 --- a/components/pm-subscription-handler/setup.py +++ b/components/pm-subscription-handler/setup.py @@ -1,5 +1,5 @@ # ============LICENSE_START======================================================= -# Copyright (C) 2019-2022 Nordix Foundation. +# Copyright (C) 2019-2023 Nordix Foundation. # Copyright (C) 2021 AT&T Property. All rights reserved. # Copyright 2020 Deutsche Telekom. All rights reserved. # ================================================================================ @@ -22,7 +22,7 @@ from setuptools import setup, find_packages setup( name="pm_subscription_handler", - version="2.2.0", + version="2.2.3", packages=find_packages(), author="lego@est.tech", author_email="lego@est.tech", @@ -34,12 +34,11 @@ setup( "requests==2.22.0", "tenacity==6.0.0", "connexion==2.5.0", - "MarkupSafe==2.0.1", - "flask_sqlalchemy==2.4.1", - "Flask==1.1.4", + "flask_sqlalchemy==3.0.1", + "Flask==2.2", "tornado==6.1", "swagger-ui-bundle==0.0.6", - "psycopg2-binary==2.8.6", + "psycopg2-binary==2.9.5", "onap_dcae_cbs_docker_client==2.2.1", "onappylog==1.0.9", "ruamel.yaml==0.16.10", diff --git a/components/pm-subscription-handler/tests/base_setup.py b/components/pm-subscription-handler/tests/base_setup.py index 14f813d4..90919ff1 100755 --- a/components/pm-subscription-handler/tests/base_setup.py +++ b/components/pm-subscription-handler/tests/base_setup.py @@ -24,9 +24,7 @@ from unittest.mock import patch, MagicMock from mod import create_app, db from mod.api.db_models import NetworkFunctionFilterModel, MeasurementGroupModel, \ SubscriptionModel, NetworkFunctionModel, NfSubRelationalModel -from mod.network_function import NetworkFunctionFilter -from mod.pmsh_utils import AppConfig -from mod.pmsh_config import AppConfig as NewAppConfig +from mod.pmsh_config import AppConfig def get_pmsh_config(file_path='data/cbs_data_1.json'): @@ -124,16 +122,11 @@ class BaseClassSetup(TestCase): cls.app_context = cls.app.app_context() cls.app_context.push() - @patch('mod.pmsh_utils.AppConfig._get_pmsh_config', MagicMock(return_value=get_pmsh_config())) + @patch('mod.pmsh_config.AppConfig._get_config', MagicMock(return_value=get_pmsh_config())) def setUp(self): os.environ['AAI_SERVICE_PORT'] = '8443' db.create_all() self.app_conf = AppConfig() - self.app_conf.nf_filter = NetworkFunctionFilter(**self.app_conf.subscription.nfFilter) - - @patch('mod.pmsh_config.AppConfig._get_config', MagicMock(return_value=get_pmsh_config())) - def setUpAppConf(self): - self.pmsh_app_conf = NewAppConfig() def tearDown(self): db.drop_all() diff --git a/components/pm-subscription-handler/tests/data/cbs_data_1.json b/components/pm-subscription-handler/tests/data/cbs_data_1.json index f872bb50..6efda4f8 100644 --- a/components/pm-subscription-handler/tests/data/cbs_data_1.json +++ b/components/pm-subscription-handler/tests/data/cbs_data_1.json @@ -8,71 +8,6 @@ "key_path":"/opt/app/pmsh/etc/certs/key.pem", "ca_cert_path":"/opt/app/pmsh/etc/certs/cacert.pem", "enable_tls":"true", - "pmsh_policy":{ - "subscription":{ - "subscriptionName":"ExtraPM-All-gNB-R2B", - "administrativeState":"UNLOCKED", - "fileBasedGP":15, - "fileLocation":"\/pm\/pm.xml", - "nfFilter":{ - "nfNames":[ - "^pnf.*", - "^vnf.*" - ], - "modelInvariantIDs":[ - - ], - "modelVersionIDs":[ - - ], - "modelNames":[ - - ] - }, - "measurementGroups":[ - { - "measurementGroup":{ - "measurementTypes":[ - { - "measurementType":"countera" - }, - { - "measurementType":"counterb" - } - ], - "managedObjectDNsBasic":[ - { - "DN":"dna" - }, - { - "DN":"dnb" - } - ] - } - }, - { - "measurementGroup":{ - "measurementTypes":[ - { - "measurementType":"counterc" - }, - { - "measurementType":"counterd" - } - ], - "managedObjectDNsBasic":[ - { - "DN":"dnc" - }, - { - "DN":"dnd" - } - ] - } - } - ] - } - }, "streams_subscribes":{ "aai_subscriber":{ "type":"message_router", @@ -114,4 +49,4 @@ } } } -}
\ No newline at end of file +} diff --git a/components/pm-subscription-handler/tests/data/cbs_invalid_data.json b/components/pm-subscription-handler/tests/data/cbs_invalid_data.json deleted file mode 100644 index a6f63680..00000000 --- a/components/pm-subscription-handler/tests/data/cbs_invalid_data.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "config":{ - "control_loop_name":"pmsh-control-loop", - "operational_policy_name":"pmsh-operational-policy", - "aaf_password":"demo123456!", - "aaf_identity":"dcae@dcae.onap.org", - "cert_path":"/opt/app/pmsh/etc/certs/cert.pem", - "key_path":"/opt/app/pmsh/etc/certs/key.pem", - "ca_cert_path":"/opt/app/pmsh/etc/certs/cacert.pem", - "enable_tls":"true", - "pmsh_policy":{ - "subscription":{ - "subscriptionName":"ExtraPM-All-gNB-R2B", - "administrativeState":"UNLOCKED", - "fileBasedGP":15, - "fileLocation":"\/pm\/pm.xml", - "nfFilter":{ - "nfNames":[ - - ], - "modelInvariantIDs":[ - - ], - "modelVersionIDs":[ - - ], - "modelNames":[ - - ] - }, - "measurementGroups":[ - { - "measurementGroup":{ - "measurementTypes":[ - { - "measurementType":"countera" - }, - { - "measurementType":"counterb" - } - ], - "managedObjectDNsBasic":[ - { - "DN":"dna" - }, - { - "DN":"dnb" - } - ] - } - }, - { - "measurementGroup":{ - "measurementTypes":[ - { - "measurementType":"counterc" - }, - { - "measurementType":"counterd" - } - ], - "managedObjectDNsBasic":[ - { - "DN":"dnc" - }, - { - "DN":"dnd" - } - ] - } - } - ] - } - }, - "streams_subscribes":{ - "aai_subscriber":{ - "type":"message_router", - "dmaap_info":{ - "topic_url":"https://message-router:3905/events/AAI_EVENT", - "client_role":"org.onap.dcae.aaiSub", - "location":"san-francisco", - "client_id":"1575976809466" - } - }, - "policy_pm_subscriber":{ - "type":"message_router", - "dmaap_info":{ - "topic_url":"https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS", - "client_role":"org.onap.dcae.pmSubscriber", - "location":"san-francisco", - "client_id":"1575876809456" - } - } - }, - "streams_publishes":{ - "policy_pm_publisher":{ - "type":"message_router", - "dmaap_info":{ - "topic_url":"https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS", - "client_role":"org.onap.dcae.pmPublisher", - "location":"san-francisco", - "client_id":"1475976809466" - } - }, - "other_publisher":{ - "type":"message_router", - "dmaap_info":{ - "topic_url":"https://message-router:3905/events/org.onap.dmaap.mr.SOME_OTHER_TOPIC", - "client_role":"org.onap.dcae.pmControlPub", - "location":"san-francisco", - "client_id":"1875976809466" - } - } - } - } -}
\ No newline at end of file diff --git a/components/pm-subscription-handler/tests/data/pm_subscription_event.json b/components/pm-subscription-handler/tests/data/pm_subscription_event.json deleted file mode 100755 index 6a7fe340..00000000 --- a/components/pm-subscription-handler/tests/data/pm_subscription_event.json +++ /dev/null @@ -1,57 +0,0 @@ -{
- "nfName":"pnf_1",
- "blueprintName": "some-name",
- "blueprintVersion": "some-version",
- "operationalPolicyName":"pmsh-operational-policy",
- "changeType":"CREATE",
- "controlLoopName":"pmsh-control-loop",
- "ipAddress": "204.120.0.15",
- "subscription":{
- "subscriptionName":"ExtraPM-All-gNB-R2B",
- "administrativeState":"UNLOCKED",
- "fileBasedGP":15,
- "fileLocation":"/pm/pm.xml",
- "measurementGroups":[
- {
- "measurementGroup":{
- "measurementTypes":[
- {
- "measurementType":"countera"
- },
- {
- "measurementType":"counterb"
- }
- ],
- "managedObjectDNsBasic":[
- {
- "DN":"dna"
- },
- {
- "DN":"dnb"
- }
- ]
- }
- },
- {
- "measurementGroup":{
- "measurementTypes":[
- {
- "measurementType":"counterc"
- },
- {
- "measurementType":"counterd"
- }
- ],
- "managedObjectDNsBasic":[
- {
- "DN":"dnc"
- },
- {
- "DN":"dnd"
- }
- ]
- }
- }
- ]
- }
-}
diff --git a/components/pm-subscription-handler/tests/services/test_measurement_group_service.py b/components/pm-subscription-handler/tests/services/test_measurement_group_service.py index 1dbe84a9..f7b98a59 100644 --- a/components/pm-subscription-handler/tests/services/test_measurement_group_service.py +++ b/components/pm-subscription-handler/tests/services/test_measurement_group_service.py @@ -20,7 +20,9 @@ import json import os from unittest.mock import patch -from mod.api.custom_exception import InvalidDataException, DataConflictException +from mod.api.custom_exception import InvalidDataException, \ + DataConflictException, DuplicateDataException +from mod.api.services.measurement_group_service import MgNfState from mod.network_function import NetworkFunction, NetworkFunctionFilter from mod.pmsh_config import AppConfig from mod import db, aai_client @@ -29,13 +31,9 @@ from tests.base_setup import BaseClassSetup, create_subscription_data, \ from mod.api.services import measurement_group_service, nf_service from mod.api.db_models import MeasurementGroupModel, NfMeasureGroupRelationalModel, \ SubscriptionModel, NetworkFunctionModel -from mod.subscription import SubNfState class MeasurementGroupServiceTestCase(BaseClassSetup): - @classmethod - def setUpClass(cls): - super().setUpClass() def setUp(self): super().setUp() @@ -48,16 +46,9 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): 'r') as data: self.good_model_info = data.read() - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - @patch.object(AppConfig, 'publish_to_topic') def test_publish_measurement_group(self, mock_mr): - super().setUpAppConf() + super().setUp() nf_1 = NetworkFunction(**{'nf_name': 'pnf_1', 'ipv4_address': '204.120.0.15', 'ipv6_address': '2001:db8:3333:4444:5555:6666:7777:8888', @@ -104,38 +95,38 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): def test_apply_nf_to_measurement_group_status(self): measurement_group_service.apply_nf_status_to_measurement_group( - "pnf_test", "measure_grp_name", SubNfState.PENDING_CREATE.value) + "pnf_test", "measure_grp_name", MgNfState.PENDING_CREATE.value) db.session.commit() measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name', NfMeasureGroupRelationalModel.nf_name == 'pnf_test').one_or_none()) self.assertIsNotNone(measurement_grp_rel) self.assertEqual(measurement_grp_rel.nf_measure_grp_status, - SubNfState.PENDING_CREATE.value) + MgNfState.PENDING_CREATE.value) def test_update_measurement_group_nf_status(self): measurement_group_service.apply_nf_status_to_measurement_group( - "pnf_test", "measure_grp_name", SubNfState.PENDING_CREATE.value) + "pnf_test", "measure_grp_name", MgNfState.PENDING_CREATE.value) measurement_group_service.update_measurement_group_nf_status( - "measure_grp_name", SubNfState.CREATED.value, "pnf_test") + "measure_grp_name", MgNfState.CREATED.value, "pnf_test") db.session.commit() measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name', NfMeasureGroupRelationalModel.nf_name == 'pnf_test').one_or_none()) self.assertIsNotNone(measurement_grp_rel) self.assertEqual(measurement_grp_rel.nf_measure_grp_status, - SubNfState.CREATED.value) + MgNfState.CREATED.value) def test_delete_nf_to_measurement_group_without_nf_delete(self): nf = NetworkFunction(nf_name='pnf_test1') nf_service.save_nf(nf) db.session.commit() measurement_group_service.apply_nf_status_to_measurement_group( - "pnf_test1", "measure_grp_name1", SubNfState.PENDING_CREATE.value) + "pnf_test1", "measure_grp_name1", MgNfState.PENDING_CREATE.value) measurement_group_service.apply_nf_status_to_measurement_group( - "pnf_test1", "measure_grp_name2", SubNfState.PENDING_CREATE.value) + "pnf_test1", "measure_grp_name2", MgNfState.PENDING_CREATE.value) measurement_group_service.delete_nf_to_measurement_group( - "pnf_test1", "measure_grp_name1", SubNfState.DELETED.value) + "pnf_test1", "measure_grp_name1", MgNfState.DELETED.value) measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name1', NfMeasureGroupRelationalModel.nf_name == 'pnf_test1').one_or_none()) @@ -149,44 +140,35 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): nf_service.save_nf(nf) db.session.commit() measurement_group_service.apply_nf_status_to_measurement_group( - "pnf_test2", "measure_grp_name2", SubNfState.PENDING_CREATE.value) + "pnf_test2", "measure_grp_name2", MgNfState.PENDING_CREATE.value) measurement_group_service.delete_nf_to_measurement_group( - "pnf_test2", "measure_grp_name2", SubNfState.DELETED.value) + "pnf_test2", "measure_grp_name2", MgNfState.DELETED.value) measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name2', NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none()) self.assertIsNone(measurement_grp_rel) - network_function = (NetworkFunctionModel.query.filter( - NetworkFunctionModel.nf_name == 'pnf_test2').one_or_none()) - self.assertIsNone(network_function) @patch.object(NetworkFunction, 'delete') - @patch('mod.logger.error') - def test_delete_nf_to_measurement_group_failure(self, mock_logger, nf_delete_func): + def test_delete_nf_to_measurement_group_failure(self, nf_delete_func): nf = NetworkFunction(nf_name='pnf_test2') nf_service.save_nf(nf) db.session.commit() measurement_group_service.apply_nf_status_to_measurement_group( - "pnf_test2", "measure_grp_name2", SubNfState.PENDING_CREATE.value) + "pnf_test2", "measure_grp_name2", MgNfState.PENDING_CREATE.value) nf_delete_func.side_effect = Exception('delete failed') measurement_group_service.delete_nf_to_measurement_group( - "pnf_test2", "measure_grp_name2", SubNfState.DELETED.value) + "pnf_test2", "measure_grp_name2", MgNfState.DELETED.value) measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( NfMeasureGroupRelationalModel.measurement_grp_name == 'measure_grp_name2', NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none()) self.assertIsNone(measurement_grp_rel) - network_function = (NetworkFunctionModel.query.filter( - NetworkFunctionModel.nf_name == 'pnf_test2').one_or_none()) - self.assertIsNotNone(network_function) - mock_logger.assert_called_with('Failed to delete nf: pnf_test2 for ' - 'measurement group: measure_grp_name2 due to: delete failed') @patch.object(db.session, 'commit') @patch('mod.logger.error') def test_update_nf_to_measurement_group_failure(self, mock_logger, db_commit_call): db_commit_call.side_effect = Exception('update failed') measurement_group_service.update_measurement_group_nf_status( - "measure_grp_name2", SubNfState.CREATE_FAILED.value, "pnf_test2") + "measure_grp_name2", MgNfState.CREATE_FAILED.value, "pnf_test2") mock_logger.assert_called_with('Failed to update nf: pnf_test2 for ' 'measurement group: measure_grp_name2 due to: update failed') @@ -195,9 +177,8 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): subscription = subscription.replace('msrmt_grp_name', new_msrmt_grp_name) return subscription - @patch.object(AppConfig, 'publish_to_topic') - def test_update_admin_status_to_locking(self, mock_mr): - super().setUpAppConf() + def test_update_admin_status_to_locking(self): + super().setUp() sub = create_subscription_data('sub') nf_list = create_multiple_network_function_data(['pnf_101', 'pnf_102']) db.session.add(sub) @@ -206,7 +187,7 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): measurement_group_service. \ apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[0]. measurement_group_name, - SubNfState.CREATED.value) + MgNfState.CREATED.value) db.session.commit() measurement_group_service.update_admin_status(sub.measurement_groups[0], 'LOCKED') meas_grp = measurement_group_service.query_meas_group_by_name('sub', 'MG1') @@ -217,11 +198,10 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): NfMeasureGroupRelationalModel.measurement_grp_name == meas_grp.measurement_group_name)\ .all() for nf in meas_group_nfs: - self.assertEqual(nf.nf_measure_grp_status, SubNfState.PENDING_DELETE.value) + self.assertEqual(nf.nf_measure_grp_status, MgNfState.PENDING_DELETE.value) - @patch.object(AppConfig, 'publish_to_topic') - def test_update_admin_status_to_locked(self, mock_mr): - super().setUpAppConf() + def test_update_admin_status_to_locked(self): + super().setUp() sub = create_subscription_data('sub') db.session.add(sub) measurement_group_service.update_admin_status(sub.measurement_groups[0], 'LOCKED') @@ -230,15 +210,14 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): self.assertEqual(meas_grp.measurement_group_name, 'MG1') self.assertEqual(meas_grp.administrative_state, 'LOCKED') - @patch.object(AppConfig, 'publish_to_topic') @patch.object(aai_client, '_get_all_aai_nf_data') @patch.object(aai_client, 'get_aai_model_data') @patch.object(NetworkFunctionFilter, 'get_network_function_filter') def test_update_admin_status_to_unlocked_with_no_nfs(self, mock_filter_call, - mock_model_aai, mock_aai, mock_mr): + mock_model_aai, mock_aai): mock_aai.return_value = json.loads(self.aai_response_data) mock_model_aai.return_value = json.loads(self.good_model_info) - super().setUpAppConf() + super().setUp() sub = create_subscription_data('sub') sub.nfs = [] db.session.add(sub) @@ -253,17 +232,16 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): NfMeasureGroupRelationalModel.measurement_grp_name == meas_grp.measurement_group_name)\ .all() for nf in meas_group_nfs: - self.assertEqual(nf.nf_measure_grp_status, SubNfState.PENDING_CREATE.value) + self.assertEqual(nf.nf_measure_grp_status, MgNfState.PENDING_CREATE.value) - @patch.object(AppConfig, 'publish_to_topic') @patch.object(aai_client, '_get_all_aai_nf_data') @patch.object(aai_client, 'get_aai_model_data') @patch.object(NetworkFunctionFilter, 'get_network_function_filter') def test_update_admin_status_to_unlocking(self, mock_filter_call, - mock_model_aai, mock_aai, mock_mr): + mock_model_aai, mock_aai): mock_aai.return_value = json.loads(self.aai_response_data) mock_model_aai.return_value = json.loads(self.good_model_info) - super().setUpAppConf() + super().setUp() sub = create_subscription_data('sub') db.session.add(sub) db.session.commit() @@ -277,7 +255,7 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): NfMeasureGroupRelationalModel.measurement_grp_name == meas_grp.measurement_group_name)\ .all() for nf in meas_group_nfs: - self.assertEqual(nf.nf_measure_grp_status, SubNfState.PENDING_CREATE.value) + self.assertEqual(nf.nf_measure_grp_status, MgNfState.PENDING_CREATE.value) def test_update_admin_status_for_missing_measurement_group(self): try: @@ -287,7 +265,7 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): 'for admin status update') def test_update_admin_status_for_data_conflict(self): - super().setUpAppConf() + super().setUp() sub = create_subscription_data('sub1') sub.measurement_groups[0].administrative_state = 'LOCKING' try: @@ -298,7 +276,7 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): 'meas group name: MG1') def test_update_admin_status_for_same_state(self): - super().setUpAppConf() + super().setUp() sub = create_subscription_data('sub1') try: measurement_group_service.update_admin_status(sub.measurement_groups[0], 'UNLOCKED') @@ -317,17 +295,14 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): measurement_group_service. \ apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[1]. measurement_group_name, - SubNfState.PENDING_DELETE.value) + MgNfState.PENDING_DELETE.value) db.session.commit() measurement_group_service.lock_nf_to_meas_grp( - "pnf_101", "MG2", SubNfState.DELETED.value) + "pnf_101", "MG2", MgNfState.DELETED.value) measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2', NfMeasureGroupRelationalModel.nf_name == 'pnf_101').one_or_none()) self.assertIsNone(measurement_grp_rel) - network_function = (NetworkFunctionModel.query.filter( - NetworkFunctionModel.nf_name == 'pnf_101').one_or_none()) - self.assertIsNone(network_function) meas_grp = measurement_group_service.query_meas_group_by_name('sub', 'MG2') self.assertEqual(meas_grp.subscription_name, 'sub') self.assertEqual(meas_grp.measurement_group_name, 'MG2') @@ -343,21 +318,36 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): measurement_group_service. \ apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[1]. measurement_group_name, - SubNfState.PENDING_DELETE.value) + MgNfState.PENDING_DELETE.value) db.session.commit() measurement_group_service.lock_nf_to_meas_grp( - "pnf_101", "MG2", SubNfState.DELETED.value) + "pnf_101", "MG2", MgNfState.DELETED.value) measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2', NfMeasureGroupRelationalModel.nf_name == 'pnf_101').one_or_none()) self.assertIsNone(measurement_grp_rel) - network_function = (NetworkFunctionModel.query.filter( - NetworkFunctionModel.nf_name == 'pnf_101').one_or_none()) - self.assertIsNone(network_function) - meas_grp = measurement_group_service.query_meas_group_by_name('sub', 'MG2') - self.assertEqual(meas_grp.subscription_name, 'sub') - self.assertEqual(meas_grp.measurement_group_name, 'MG2') - self.assertEqual(meas_grp.administrative_state, 'LOCKING') + + def test_check_duplication_exception(self): + sub = create_subscription_data('sub') + db.session.add(sub) + try: + measurement_group_service.check_duplication('sub', 'MG1') + except DuplicateDataException as e: + self.assertEqual(e.args[0], 'Measurement Group Name: MG1 already exists.') + + def test_check_measurement_group_names_comply(self): + mg = {'measurementGroup': { + 'measurementGroupName': 'MG2', + 'administrativeState': 'UNLOCKED', + 'fileBasedGP': 15, + 'fileLocation': '/pm/pm.xml', + 'measurementTypes': '[{ "measurementType": "countera" }, ' + '{ "measurementType": "counterb" }]', + 'managedObjectDNsBasic': '[{ "DN":"dna"},{"DN":"dnb"}]'}} + try: + measurement_group_service.check_measurement_group_names_comply('MG1', mg) + except InvalidDataException as e: + self.assertEqual(e.args[0], 'Measurement Group Name in body does not match with URI') def test_filter_nf_to_meas_grp_for_delete(self): sub = create_subscription_data('sub') @@ -365,17 +355,16 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): nf = NetworkFunction(nf_name='pnf_test2') nf_service.save_nf(nf) measurement_group_service.apply_nf_status_to_measurement_group( - "pnf_test2", "MG2", SubNfState.PENDING_DELETE.value) + "pnf_test2", "MG2", MgNfState.PENDING_DELETE.value) db.session.commit() measurement_group_service.filter_nf_to_meas_grp( - "pnf_test2", "MG2", SubNfState.DELETED.value) + "pnf_test2", "MG2", MgNfState.DELETED.value) + measurement_group_service.filter_nf_to_meas_grp("pnf_test2", "MG2", + MgNfState.DELETED.value) measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2', NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none()) self.assertIsNone(measurement_grp_rel) - network_function = (NetworkFunctionModel.query.filter( - NetworkFunctionModel.nf_name == 'pnf_test2').one_or_none()) - self.assertIsNone(network_function) meas_grp = measurement_group_service.query_meas_group_by_name('sub', 'MG2') self.assertEqual(meas_grp.subscription_name, 'sub') self.assertEqual(meas_grp.measurement_group_name, 'MG2') @@ -387,10 +376,10 @@ class MeasurementGroupServiceTestCase(BaseClassSetup): nf = NetworkFunction(nf_name='pnf_test2') nf_service.save_nf(nf) measurement_group_service.apply_nf_status_to_measurement_group( - "pnf_test2", "MG2", SubNfState.PENDING_CREATE.value) + "pnf_test2", "MG2", MgNfState.PENDING_CREATE.value) db.session.commit() measurement_group_service.filter_nf_to_meas_grp( - "pnf_test2", "MG2", SubNfState.CREATED.value) + "pnf_test2", "MG2", MgNfState.CREATED.value) measurement_grp_rel = (NfMeasureGroupRelationalModel.query.filter( NfMeasureGroupRelationalModel.measurement_grp_name == 'MG2', NfMeasureGroupRelationalModel.nf_name == 'pnf_test2').one_or_none()) diff --git a/components/pm-subscription-handler/tests/services/test_nf_service.py b/components/pm-subscription-handler/tests/services/test_nf_service.py index d5824992..2297ff8d 100644 --- a/components/pm-subscription-handler/tests/services/test_nf_service.py +++ b/components/pm-subscription-handler/tests/services/test_nf_service.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2021 Nordix Foundation. +# Copyright (C) 2021-2022 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,9 +28,6 @@ from mod.network_function import NetworkFunctionFilter class NetworkFunctionServiceTestCase(BaseClassSetup): - @classmethod - def setUpClass(cls): - super().setUpClass() def setUp(self): super().setUp() @@ -44,13 +41,6 @@ class NetworkFunctionServiceTestCase(BaseClassSetup): 'r') as data: self.good_model_info = data.read() - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - def create_test_subs(self, new_sub_name, new_msrmt_grp_name): subscription = self.subscription_request.replace('ExtraPM-All-gNB-R2B', new_sub_name) subscription = subscription.replace('msrmt_grp_name', new_msrmt_grp_name) diff --git a/components/pm-subscription-handler/tests/services/test_subscription_service.py b/components/pm-subscription-handler/tests/services/test_subscription_service.py index a0f3297c..4129bd81 100644 --- a/components/pm-subscription-handler/tests/services/test_subscription_service.py +++ b/components/pm-subscription-handler/tests/services/test_subscription_service.py @@ -22,8 +22,8 @@ from unittest.mock import patch, MagicMock from mod.api.db_models import SubscriptionModel, MeasurementGroupModel, \ NfMeasureGroupRelationalModel, NetworkFunctionModel, NfSubRelationalModel, \ convert_db_string_to_list, NetworkFunctionFilterModel +from mod.api.services.measurement_group_service import MgNfState from mod.network_function import NetworkFunctionFilter -from mod.subscription import SubNfState from mod import aai_client, db from mod.api.custom_exception import DuplicateDataException, InvalidDataException, \ DataConflictException @@ -34,9 +34,6 @@ from tests.base_setup import create_multiple_subscription_data class SubscriptionServiceTestCase(BaseClassSetup): - @classmethod - def setUpClass(cls): - super().setUpClass() def setUp(self): super().setUp() @@ -49,13 +46,6 @@ class SubscriptionServiceTestCase(BaseClassSetup): 'r') as data: self.good_model_info = data.read() - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - def create_test_subs(self, new_sub_name, new_msrmt_grp_name): subscription = self.subscription_request.replace('ExtraPM-All-gNB-R2B', new_sub_name) subscription = subscription.replace('msrmt_grp_name', new_msrmt_grp_name) @@ -84,7 +74,7 @@ class SubscriptionServiceTestCase(BaseClassSetup): NfMeasureGroupRelationalModel.measurement_grp_name == 'msrmt_grp_name-new')).all() for pubslished_event in msr_grp_nf_rel: self.assertEqual(pubslished_event.nf_measure_grp_status, - SubNfState.PENDING_CREATE.value) + MgNfState.PENDING_CREATE.value) @patch('mod.api.services.subscription_service.save_nf_filter', MagicMock(return_value=None)) @patch.object(AppConfig, 'publish_to_topic') @@ -132,6 +122,9 @@ class SubscriptionServiceTestCase(BaseClassSetup): def test_perform_validation_existing_sub(self): try: + subscription = create_subscription_data('ExtraPM-All-gNB-R2B') + db.session.add(subscription) + db.session.commit() subscription_service.create_subscription(json.loads(self.subscription_request) ['subscription']) except DuplicateDataException as exception: @@ -341,10 +334,10 @@ class SubscriptionServiceTestCase(BaseClassSetup): "No value provided for measurement group name") def test_validate_nf_filter_with_no_filter_values(self): - nfFilter = '{"nfNames": [],"modelInvariantIDs": [], ' \ - '"modelVersionIDs": [],"modelNames": []}' + nf_filter = '{"nfNames": [],"modelInvariantIDs": [], ' \ + '"modelVersionIDs": [],"modelNames": []}' try: - subscription_service.validate_nf_filter(json.loads(nfFilter)) + subscription_service.validate_nf_filter(json.loads(nf_filter)) except InvalidDataException as invalidEx: self.assertEqual(invalidEx.args[0], "At least one filter within nfFilter must not be empty") @@ -423,10 +416,10 @@ class SubscriptionServiceTestCase(BaseClassSetup): self.assertEqual(len(meas_group_nfs), 2) self.assertEqual(meas_group_nfs[0].nf_name, 'pnf201') self.assertEqual(meas_group_nfs[0].nf_measure_grp_status, - SubNfState.PENDING_CREATE.value) + MgNfState.PENDING_CREATE.value) self.assertEqual(meas_group_nfs[1].nf_name, 'pnf_33_ericsson') self.assertEqual(meas_group_nfs[1].nf_measure_grp_status, - SubNfState.PENDING_CREATE.value) + MgNfState.PENDING_CREATE.value) meas_grp = measurement_group_service.query_meas_group_by_name('sub_01', 'msg_01') self.assertEqual(meas_grp.administrative_state, 'UNLOCKED') # Creating test data for update filter function @@ -442,13 +435,13 @@ class SubscriptionServiceTestCase(BaseClassSetup): .all() self.assertEqual(meas_group_nfs[0].nf_name, 'pnf201') self.assertEqual(meas_group_nfs[0].nf_measure_grp_status, - SubNfState.PENDING_DELETE.value) + MgNfState.PENDING_DELETE.value) self.assertEqual(meas_group_nfs[1].nf_name, 'pnf_33_ericsson') self.assertEqual(meas_group_nfs[1].nf_measure_grp_status, - SubNfState.PENDING_DELETE.value) + MgNfState.PENDING_DELETE.value) self.assertEqual(meas_group_nfs[2].nf_name, 'xnf111') self.assertEqual(meas_group_nfs[2].nf_measure_grp_status, - SubNfState.PENDING_CREATE.value) + MgNfState.PENDING_CREATE.value) meas_grp = measurement_group_service.query_meas_group_by_name('sub_01', 'msg_01') self.assertEqual(meas_grp.administrative_state, 'FILTERING') diff --git a/components/pm-subscription-handler/tests/test_aai_event_handler.py b/components/pm-subscription-handler/tests/test_aai_event_handler.py index 5fc38c52..ba0e5e9d 100755 --- a/components/pm-subscription-handler/tests/test_aai_event_handler.py +++ b/components/pm-subscription-handler/tests/test_aai_event_handler.py @@ -20,31 +20,26 @@ import json from os import path from unittest.mock import patch, MagicMock from mod.aai_event_handler import AAIEventHandler -from mod.api.db_models import NetworkFunctionModel, NetworkFunctionFilterModel, \ - MeasurementGroupModel, SubscriptionModel -from mod.subscription import AdministrativeState -from tests.base_setup import BaseClassSetup +from mod.api.db_models import NetworkFunctionModel +from tests.base_setup import BaseClassSetup, create_subscription_data from mod import db class AAIEventHandlerTest(BaseClassSetup): - @classmethod - def setUpClass(cls): - super().setUpClass() def setUp(self): super().setUp() - super().setUpAppConf() + subscription = create_subscription_data('aai_event_handler') + subscription.measurement_groups[1].administravtive_sate = 'UNLOCKED' + db.session.add(subscription) + db.session.add(subscription.measurement_groups[0]) + db.session.add(subscription.measurement_groups[1]) + db.session.add(subscription.network_filter) + db.session.add(subscription.nfs[0]) + db.session.commit() with open(path.join(path.dirname(__file__), 'data/mr_aai_events.json'), 'r') as data: self.mr_aai_events = json.load(data)["mr_response"] - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - @patch('mod.pmsh_config.AppConfig.get_from_topic') @patch('mod.network_function.NetworkFunction.set_nf_model_params') @patch('mod.network_function.NetworkFunction.delete') @@ -87,16 +82,14 @@ class AAIEventHandlerTest(BaseClassSetup): apply_nfs_to_measure_grp): mock_set_sdnc_params.return_value = True mr_aai_mock.return_value = self.mr_aai_events - aai_handler = AAIEventHandler(self.app) - subscription = SubscriptionModel(subscription_name='ExtraPM-All-gNB-R2B2', - operational_policy_name='operation_policy', - control_loop_name="control-loop", - status=AdministrativeState.UNLOCKED.value) - db.session.add(subscription) - db.session.commit() - generate_nf_filter_measure_grp('ExtraPM-All-gNB-R2B', 'msr_grp_name') - generate_nf_filter_measure_grp('ExtraPM-All-gNB-R2B2', 'msr_grp_name2') + nf_to_subscription = create_subscription_data('nf_to_subscription') + nf_to_subscription.measurement_groups[0].measurement_group_name = 'NF_MG_ONE' + nf_to_subscription.measurement_groups[1].measurement_group_name = 'NF_MG_TWO' + db.session.add(nf_to_subscription) + db.session.add(nf_to_subscription.measurement_groups[0]) + db.session.add(nf_to_subscription.network_filter) db.session.commit() + aai_handler = AAIEventHandler(self.app) aai_handler.execute() self.assertEqual(apply_nfs_to_measure_grp.call_count, 2) @@ -111,11 +104,9 @@ class AAIEventHandlerTest(BaseClassSetup): mr_aai_mock.return_value = self.mr_aai_events apply_nfs_to_measure_grp.side_effect = Exception("publish failed") aai_handler = AAIEventHandler(self.app) - generate_nf_filter_measure_grp('ExtraPM-All-gNB-R2B', 'msr_grp_name3') - db.session.commit() aai_handler.execute() mock_logger.assert_called_with('Failed to process AAI event for ' - 'subscription: ExtraPM-All-gNB-R2B ' + 'subscription: aai_event_handler ' 'due to: publish failed') @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None)) @@ -126,21 +117,5 @@ class AAIEventHandlerTest(BaseClassSetup): mock_set_sdnc_params.return_value = True mr_aai_mock.side_effect = Exception("AAI failure") aai_handler = AAIEventHandler(self.app) - generate_nf_filter_measure_grp('ExtraPM-All-gNB-R2B', 'msr_grp_name3') - db.session.commit() aai_handler.execute() mock_logger.assert_called_with('Failed to process AAI event due to: AAI failure') - - -def generate_nf_filter_measure_grp(sub_name, msg_name): - nf_filter = NetworkFunctionFilterModel( - subscription_name=sub_name, nf_names='{^pnf.*, ^vnf.*}', - model_invariant_ids='{}', - model_version_ids='{}', - model_names='{}') - measurement_group = MeasurementGroupModel( - subscription_name=sub_name, measurement_group_name=msg_name, - administrative_state='UNLOCKED', file_based_gp=15, file_location='pm.xml', - measurement_type=[], managed_object_dns_basic=[]) - db.session.add(nf_filter) - db.session.add(measurement_group) diff --git a/components/pm-subscription-handler/tests/test_aai_service.py b/components/pm-subscription-handler/tests/test_aai_service.py index 97f400c1..0d0bd962 100644 --- a/components/pm-subscription-handler/tests/test_aai_service.py +++ b/components/pm-subscription-handler/tests/test_aai_service.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2019-2021 Nordix Foundation. +# Copyright (C) 2019-2022 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the 'License'); # you may not use this file except in compliance with the License. @@ -23,30 +23,21 @@ from unittest.mock import patch import responses from requests import Session, HTTPError -import mod.aai_client as aai_client -from tests.base_setup import BaseClassSetup +from mod import aai_client +from mod.network_function import NetworkFunctionFilter +from tests.base_setup import BaseClassSetup, create_subscription_data class AaiClientTestCase(BaseClassSetup): - @classmethod - def setUpClass(cls): - super().setUpClass() - def setUp(self): super().setUp() + self.subscription = create_subscription_data('ExtraPM-All-gNB-R2B') with open(os.path.join(os.path.dirname(__file__), 'data/aai_xnfs.json'), 'r') as data: self.aai_response_data = data.read() with open(os.path.join(os.path.dirname(__file__), 'data/aai_model_info.json'), 'r') as data: self.good_model_info = data.read() - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - @patch('mod.network_function.NetworkFunction.set_nf_model_params') @patch.object(Session, 'get') @patch.object(Session, 'put') @@ -57,9 +48,10 @@ class AaiClientTestCase(BaseClassSetup): mock_get_session.return_value.status_code = 200 mock_get_session.return_value.text = self.good_model_info mock_get_sdnc_params.return_value = True - xnfs = aai_client.get_pmsh_nfs_from_aai(self.app_conf, self.app_conf.nf_filter) - self.assertEqual(self.app_conf.subscription.subscriptionName, 'ExtraPM-All-gNB-R2B') - self.assertEqual(self.app_conf.subscription.administrativeState, 'UNLOCKED') + nf_filter = NetworkFunctionFilter(**self.subscription.network_filter.serialize()) + xnfs = aai_client.get_pmsh_nfs_from_aai(self.app_conf, nf_filter) + self.assertEqual(self.subscription.subscription_name, 'ExtraPM-All-gNB-R2B') + self.assertEqual(self.subscription.measurement_groups[0].administrative_state, 'UNLOCKED') self.assertEqual(len(xnfs), 3) @patch.object(Session, 'put') @@ -67,7 +59,7 @@ class AaiClientTestCase(BaseClassSetup): mock_session.return_value.status_code = 404 with mock.patch('mod.aai_client._get_all_aai_nf_data', return_value=None): with self.assertRaises(RuntimeError): - aai_client.get_pmsh_nfs_from_aai(self.app_conf, self.app_conf.nf_filter) + aai_client.get_pmsh_nfs_from_aai(self.app_conf, self.subscription.network_filter) @responses.activate def test_aai_client_get_all_aai_xnf_data_not_found(self): diff --git a/components/pm-subscription-handler/tests/test_controller.py b/components/pm-subscription-handler/tests/test_controller.py index 7b0a8b19..ce540fb7 100755 --- a/components/pm-subscription-handler/tests/test_controller.py +++ b/components/pm-subscription-handler/tests/test_controller.py @@ -23,27 +23,23 @@ from http import HTTPStatus from mod import aai_client, db from mod.api.controller import status, post_subscription, get_subscription_by_name, \ get_subscriptions, get_meas_group_with_nfs, delete_subscription_by_name, update_admin_state, \ - delete_meas_group_by_name, put_nf_filter + delete_meas_group_by_name, post_meas_group, put_nf_filter from mod.api.services.measurement_group_service import query_meas_group_by_name from tests.base_setup import BaseClassSetup from mod.api.custom_exception import InvalidDataException, DataConflictException -from mod.api.db_models import SubscriptionModel, NfMeasureGroupRelationalModel -from mod.subscription import SubNfState +from mod.api.db_models import SubscriptionModel, \ + NfMeasureGroupRelationalModel, MeasurementGroupModel from mod.network_function import NetworkFunctionFilter from tests.base_setup import create_subscription_data, create_multiple_subscription_data, \ create_multiple_network_function_data from mod.api.services import measurement_group_service, nf_service, subscription_service +from mod.api.services.measurement_group_service import MgNfState class ControllerTestCase(BaseClassSetup): - @classmethod - def setUpClass(cls): - super().setUpClass() - def setUp(self): super().setUp() - super().setUpAppConf() with open(os.path.join(os.path.dirname(__file__), 'data/aai_xnfs.json'), 'r') as data: self.aai_response_data = data.read() with open(os.path.join(os.path.dirname(__file__), 'data/aai_model_info.json'), 'r') as data: @@ -52,13 +48,6 @@ class ControllerTestCase(BaseClassSetup): 'data/create_subscription_request.json'), 'r') as data: self.subscription_request = data.read() - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - def test_status_response_healthy(self): self.assertEqual(status()['status'], 'healthy') @@ -90,11 +79,14 @@ class ControllerTestCase(BaseClassSetup): NfMeasureGroupRelationalModel.measurement_grp_name == mes_grp_name)).all() for published_event in msr_grp_nf_rel: self.assertEqual(published_event.nf_measure_grp_status, - SubNfState.PENDING_CREATE.value) + MgNfState.PENDING_CREATE.value) self.assertEqual(response[1], 201) def test_post_subscription_duplicate_sub(self): # Posting the same subscription request stored in previous test to get duplicate response + subscription = create_subscription_data('ExtraPM-All-gNB-R2B') + db.session.add(subscription) + db.session.commit() response = post_subscription(json.loads(self.subscription_request)) self.assertEqual(response[1], 409) self.assertEqual(response[0], 'subscription Name: ExtraPM-All-gNB-R2B already exists.') @@ -185,7 +177,7 @@ class ControllerTestCase(BaseClassSetup): measurement_group_service. \ apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[0]. measurement_group_name, - SubNfState.PENDING_CREATE.value) + MgNfState.PENDING_CREATE.value) db.session.commit() mg_with_nfs, status_code = get_meas_group_with_nfs('sub1', 'MG1') self.assertEqual(status_code, HTTPStatus.OK.value) @@ -206,6 +198,38 @@ class ControllerTestCase(BaseClassSetup): error, status_code = get_meas_group_with_nfs('sub1', 'MG1') self.assertEqual(status_code, HTTPStatus.INTERNAL_SERVER_ERROR.value) + @patch.object(aai_client, '_get_all_aai_nf_data') + @patch.object(aai_client, 'get_aai_model_data') + def test_post_meas_group(self, mock_model_aai, mock_aai): + mock_aai.return_value = json.loads(self.aai_response_data) + mock_model_aai.return_value = json.loads(self.good_model_info) + subscription_data = create_subscription_data('Post_MG') + measurement_grp = {'measurementGroup': { + 'measurementGroupName': 'MG2', + 'administrativeState': 'UNLOCKED', + 'fileBasedGP': 15, + 'fileLocation': '/pm/pm.xml', + 'measurementTypes': '[{ "measurementType": "countera" }, ' + '{ "measurementType": "counterb" }]', + 'managedObjectDNsBasic': '[{ "DN":"dna"},{"DN":"dnb"}]'}} + db.session.add(subscription_data) + db.session.commit() + db.session.remove() + _, status_code = post_meas_group('Post_MG', 'MG3', measurement_grp) + self.assertEqual(status_code, 201) + + def test_post_meas_group_with_duplicate(self): + subscription_data = create_subscription_data('Post_MG') + measurement_grp = MeasurementGroupModel('Post_MG', 'MG1', 'UNLOCKED', 15, '/pm/pm.xml', + '[{ "measurementType": "countera" }, ' + '{ "measurementType": "counterb" }]', + '[{ "DN":"dna"},{"DN":"dnb"}]') + db.session.add(subscription_data) + db.session.commit() + db.session.remove() + _, status_code = post_meas_group('Post_MG', 'MG1', measurement_grp) + self.assertEqual(status_code, 409) + def test_delete_sub_when_state_unlocked(self): subscription_unlocked_data = create_subscription_data('MG_unlocked') subscription_unlocked_data.measurement_groups[0].measurement_group_name = 'unlock' @@ -305,7 +329,7 @@ class ControllerTestCase(BaseClassSetup): measurement_group_service. \ apply_nf_status_to_measurement_group(nf.nf_name, sub.measurement_groups[0]. measurement_group_name, - SubNfState.CREATED.value) + MgNfState.CREATED.value) db.session.commit() response = update_admin_state('sub1', 'MG1', {'administrativeState': 'LOCKED'}) self.assertEqual(response[1], HTTPStatus.OK.value) @@ -315,7 +339,7 @@ class ControllerTestCase(BaseClassSetup): self.assertEqual(mg_with_nfs['measurementGroupName'], 'MG1') self.assertEqual(mg_with_nfs['administrativeState'], 'LOCKING') for nf in mg_with_nfs['networkFunctions']: - self.assertEqual(nf['nfMgStatus'], SubNfState.PENDING_DELETE.value) + self.assertEqual(nf['nfMgStatus'], MgNfState.PENDING_DELETE.value) @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None)) @patch.object(aai_client, '_get_all_aai_nf_data') @@ -340,7 +364,7 @@ class ControllerTestCase(BaseClassSetup): self.assertEqual(mg_with_nfs['measurementGroupName'], 'MG2') self.assertEqual(mg_with_nfs['administrativeState'], 'UNLOCKED') for nf in mg_with_nfs['networkFunctions']: - self.assertEqual(nf['nfMgStatus'], SubNfState.PENDING_CREATE.value) + self.assertEqual(nf['nfMgStatus'], MgNfState.PENDING_CREATE.value) @patch('mod.api.services.measurement_group_service.update_admin_status', MagicMock(side_effect=InvalidDataException('Bad request'))) diff --git a/components/pm-subscription-handler/tests/test_exit_handler.py b/components/pm-subscription-handler/tests/test_exit_handler.py index c98be634..d88b4752 100755 --- a/components/pm-subscription-handler/tests/test_exit_handler.py +++ b/components/pm-subscription-handler/tests/test_exit_handler.py @@ -17,32 +17,31 @@ # ============LICENSE_END===================================================== import os from signal import SIGTERM, signal -from unittest.mock import patch +from unittest.mock import patch, MagicMock +from mod import db from mod.exit_handler import ExitHandler -from tests.base_setup import BaseClassSetup +from tests.base_setup import BaseClassSetup, create_subscription_data class ExitHandlerTests(BaseClassSetup): - @classmethod - def setUpClass(cls): - super().setUpClass() - - @patch('mod.pmsh_utils.PeriodicTask') - @patch('mod.pmsh_utils.PeriodicTask') + @patch('pmsh_service_main.PeriodicTask') + @patch('pmsh_service_main.PeriodicTask') def setUp(self, mock_periodic_task_aai, mock_periodic_task_policy): super().setUp() + subscription = create_subscription_data('aai_event_handler') + subscription.measurement_groups[1].administravtive_sate = 'UNLOCKED' + db.session.add(subscription) + db.session.add(subscription.measurement_groups[0]) + db.session.add(subscription.measurement_groups[1]) + db.session.add(subscription.network_filter) + db.session.add(subscription.nfs[0]) + db.session.commit() self.mock_aai_event_thread = mock_periodic_task_aai self.mock_policy_resp_handler_thread = mock_periodic_task_policy - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - + @patch('mod.pmsh_config.AppConfig.publish_to_topic', MagicMock(return_value=None)) def test_terminate_signal_successful(self): handler = ExitHandler(periodic_tasks=[self.mock_aai_event_thread, self.mock_policy_resp_handler_thread]) diff --git a/components/pm-subscription-handler/tests/test_network_function.py b/components/pm-subscription-handler/tests/test_network_function.py index 3e38b9c6..d80f2c40 100755 --- a/components/pm-subscription-handler/tests/test_network_function.py +++ b/components/pm-subscription-handler/tests/test_network_function.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2019-2021 Nordix Foundation. +# Copyright (C) 2019-2022 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ # ============LICENSE_END===================================================== import json import os -from unittest.mock import patch, Mock +from unittest.mock import patch from mod.network_function import NetworkFunction from tests.base_setup import BaseClassSetup @@ -25,10 +25,6 @@ from tests.base_setup import BaseClassSetup class NetworkFunctionTests(BaseClassSetup): - @classmethod - def setUpClass(cls): - super().setUpClass() - def setUp(self): super().setUp() self.nf_1 = NetworkFunction(sdnc_model_name='blah', sdnc_model_version=1.0, @@ -49,13 +45,6 @@ class NetworkFunctionTests(BaseClassSetup): 'data/aai_model_info_no_sdnc.json'), 'r') as data: self.bad_model_info = json.loads(data.read()) - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - def test_get_network_function(self): self.nf_1.create() nf = NetworkFunction.get('pnf_1') @@ -82,7 +71,7 @@ class NetworkFunctionTests(BaseClassSetup): def test_delete_network_function(self): for nf in [self.nf_1, self.nf_2]: - self.app_conf.subscription.add_network_function_to_subscription(nf, Mock()) + nf.create() nfs = NetworkFunction.get_all() self.assertEqual(2, len(nfs)) NetworkFunction.delete(nf_name=self.nf_1.nf_name) diff --git a/components/pm-subscription-handler/tests/test_pmsh_config.py b/components/pm-subscription-handler/tests/test_pmsh_config.py index deb867bf..84f86fb4 100644 --- a/components/pm-subscription-handler/tests/test_pmsh_config.py +++ b/components/pm-subscription-handler/tests/test_pmsh_config.py @@ -1,5 +1,5 @@ # ============LICENSE_START=================================================== -# Copyright (C) 2021 Nordix Foundation. +# Copyright (C) 2021-2022 Nordix Foundation. # ============================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ # # SPDX-License-Identifier: Apache-2.0 # ============LICENSE_END===================================================== -from unittest.mock import Mock, patch +from unittest.mock import patch import responses from requests import Session @@ -26,30 +26,15 @@ from tests.base_setup import BaseClassSetup class PmshConfigTestCase(BaseClassSetup): - @classmethod - def setUpClass(cls): - super().setUpClass() - - def setUp(self): - super().setUpAppConf() - self.mock_app = Mock() - - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - def test_config_get_aaf_creds(self): - self.assertEqual(self.pmsh_app_conf.enable_tls, 'true') - self.assertEqual(self.pmsh_app_conf.aaf_id, 'dcae@dcae.onap.org') - self.assertEqual(self.pmsh_app_conf.aaf_pass, 'demo123456!') + self.assertEqual(self.app_conf.enable_tls, 'true') + self.assertEqual(self.app_conf.aaf_id, 'dcae@dcae.onap.org') + self.assertEqual(self.app_conf.aaf_pass, 'demo123456!') def test_config_get_cert_data(self): - self.assertEqual(self.pmsh_app_conf.key_path, '/opt/app/pmsh/etc/certs/key.pem') - self.assertEqual(self.pmsh_app_conf.cert_path, '/opt/app/pmsh/etc/certs/cert.pem') - self.assertEqual(self.pmsh_app_conf.ca_cert_path, '/opt/app/pmsh/etc/certs/cacert.pem') + self.assertEqual(self.app_conf.key_path, '/opt/app/pmsh/etc/certs/key.pem') + self.assertEqual(self.app_conf.cert_path, '/opt/app/pmsh/etc/certs/cert.pem') + self.assertEqual(self.app_conf.ca_cert_path, '/opt/app/pmsh/etc/certs/cacert.pem') def test_singleton_instance_is_accessible_using_class_method(self): my_singleton_instance = AppConfig.get_instance() @@ -60,8 +45,8 @@ class PmshConfigTestCase(BaseClassSetup): def test_mr_pub_publish_to_topic_success(self, mock_session): mock_session.return_value.status_code = 200 with patch('requests.Session.post') as session_post_call: - self.pmsh_app_conf.publish_to_topic(MRTopic.POLICY_PM_PUBLISHER.value, - {"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"}) + self.app_conf.publish_to_topic(MRTopic.POLICY_PM_PUBLISHER.value, + {"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"}) session_post_call.assert_called_once() @responses.activate @@ -70,8 +55,8 @@ class PmshConfigTestCase(BaseClassSetup): 'https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS', json={"error": "Client Error"}, status=400) with self.assertRaises(Exception): - self.pmsh_app_conf.publish_to_topic(MRTopic.POLICY_PM_PUBLISHER.value, - {"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"}) + self.app_conf.publish_to_topic(MRTopic.POLICY_PM_PUBLISHER.value, + {"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"}) @responses.activate def test_mr_sub_get_from_topic_success(self): @@ -79,7 +64,7 @@ class PmshConfigTestCase(BaseClassSetup): 'https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS/' 'dcae_pmsh_cg/1?timeout=5000', json={"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"}, status=200) - mr_topic_data = self.pmsh_app_conf.get_from_topic(MRTopic.POLICY_PM_SUBSCRIBER.value, 1) + mr_topic_data = self.app_conf.get_from_topic(MRTopic.POLICY_PM_SUBSCRIBER.value, 1) self.assertIsNotNone(mr_topic_data) @responses.activate @@ -89,4 +74,4 @@ class PmshConfigTestCase(BaseClassSetup): 'dcae_pmsh_cg/1?timeout=5000', json={"key": "43c4ee19-6b8d-4279-a80f-c507850aae47"}, status=400) with self.assertRaises(Exception): - self.pmsh_app_conf.get_from_topic(MRTopic.POLICY_PM_SUBSCRIBER.value, 1) + self.app_conf.get_from_topic(MRTopic.POLICY_PM_SUBSCRIBER.value, 1) diff --git a/components/pm-subscription-handler/tests/test_pmsh_utils.py b/components/pm-subscription-handler/tests/test_pmsh_utils.py deleted file mode 100644 index 57f20ddf..00000000 --- a/components/pm-subscription-handler/tests/test_pmsh_utils.py +++ /dev/null @@ -1,245 +0,0 @@ -# ============LICENSE_START=================================================== -# Copyright (C) 2019-2021 Nordix Foundation. -# ============================================================================ -# 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. -# -# SPDX-License-Identifier: Apache-2.0 -# ============LICENSE_END===================================================== -from test.support import EnvironmentVarGuard -from unittest.mock import patch, Mock - -import responses -from jsonschema import ValidationError -from requests import Session -from tenacity import RetryError - -from mod import get_db_connection_url -from mod.network_function import NetworkFunction -from tests.base_setup import BaseClassSetup -from tests.base_setup import get_pmsh_config - - -class PmshUtilsTestCase(BaseClassSetup): - - @classmethod - def setUpClass(cls): - super().setUpClass() - - def setUp(self): - super().setUp() - self.mock_app = Mock() - - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - - def test_utils_get_mr_sub(self): - mr_policy_sub = self.app_conf.get_mr_sub('policy_pm_subscriber') - self.assertTrue(mr_policy_sub.aaf_id, 'dcae@dcae.onap.org') - - def test_utils_get_mr_sub_fails_with_invalid_name(self): - with self.assertRaises(KeyError): - self.app_conf.get_mr_sub('invalid_sub') - - def test_utils_get_mr_pub(self): - mr_policy_pub = self.app_conf.get_mr_pub('policy_pm_publisher') - self.assertTrue(mr_policy_pub.aaf_pass, 'demo123456!') - - def test_utils_get_mr_pub_fails_with_invalid_name(self): - with self.assertRaises(KeyError): - self.app_conf.get_mr_pub('invalid_pub') - - def test_utils_get_cert_data(self): - self.assertEqual(self.app_conf.cert_params, ('/opt/app/pmsh/etc/certs/cert.pem', - '/opt/app/pmsh/etc/certs/key.pem')) - - @patch.object(Session, 'post') - def test_mr_pub_publish_to_topic_success(self, mock_session): - mock_session.return_value.status_code = 200 - mr_policy_pub = self.app_conf.get_mr_pub('policy_pm_publisher') - with patch('requests.Session.post') as session_post_call: - mr_policy_pub.publish_to_topic({"dummy_val": "43c4ee19-6b8d-4279-a80f-c507850aae47"}) - session_post_call.assert_called_once() - - @responses.activate - def test_mr_pub_publish_to_topic_fail(self): - responses.add(responses.POST, - 'https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS', - json={'error': 'Client Error'}, status=400) - mr_policy_pub = self.app_conf.get_mr_pub('policy_pm_publisher') - with self.assertRaises(Exception): - mr_policy_pub.publish_to_topic({"dummy_val": "43c4ee19-6b8d-4279-a80f-c507850aae47"}) - - def test_mr_pub_publish_sub_event_data_success(self): - mr_policy_pub = self.app_conf.get_mr_pub('policy_pm_publisher') - with patch('mod.pmsh_utils._MrPub.publish_to_topic') as pub_to_topic_call: - mr_policy_pub.publish_subscription_event_data( - self.app_conf.subscription, - NetworkFunction(nf_name='pnf_1', - model_invariant_id='some-id', - model_version_id='some-id')) - pub_to_topic_call.assert_called_once() - - @responses.activate - def test_mr_sub_get_from_topic_success(self): - policy_mr_sub = self.app_conf.get_mr_sub('policy_pm_subscriber') - responses.add(responses.GET, - 'https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS/' - 'dcae_pmsh_cg/1?timeout=1000', - json={"dummy_val": "43c4ee19-6b8d-4279-a80f-c507850aae47"}, status=200) - mr_topic_data = policy_mr_sub.get_from_topic(1) - self.assertIsNotNone(mr_topic_data) - - @responses.activate - def test_mr_sub_get_from_topic_fail(self): - policy_mr_sub = self.app_conf.get_mr_sub('policy_pm_subscriber') - responses.add(responses.GET, - 'https://message-router:3905/events/org.onap.dmaap.mr.PM_SUBSCRIPTIONS/' - 'dcae_pmsh_cg/1?timeout=1000', - json={"dummy_val": "43c4ee19-6b8d-4279-a80f-c507850aae47"}, status=400) - with self.assertRaises(Exception): - policy_mr_sub.get_from_topic(1) - - def test_get_db_connection_url_success(self): - self.env = EnvironmentVarGuard() - self.env.set('PMSH_PG_URL', '1.2.3.4') - self.env.set('PMSH_PG_USERNAME', 'pmsh') - self.env.set('PMSH_PG_PASSWORD', 'pass') - db_url = get_db_connection_url() - self.assertEqual(db_url, 'postgresql+psycopg2://pmsh:pass@1.2.3.4:5432/pmsh') - - def test_get_db_connection_url_fail(self): - self.env = EnvironmentVarGuard() - self.env.set('PMSH_PG_USERNAME', 'pmsh') - self.env.set('PMSH_PG_PASSWORD', 'pass') - with self.assertRaises(Exception): - get_db_connection_url() - - @patch('mod.logger.info') - @patch('mod.pmsh_utils.get_all') - def test_refresh_config_success(self, mock_cbs_client_get_all, mock_logger): - mock_cbs_client_get_all.return_value = get_pmsh_config() - self.app_conf.refresh_config() - mock_logger.assert_called_with('AppConfig data has been refreshed') - - @patch('mod.logger.error') - @patch('mod.pmsh_utils.get_all') - def test_refresh_config_fail(self, mock_cbs_client_get_all, mock_logger): - mock_cbs_client_get_all.side_effect = ValueError - with self.assertRaises(RetryError): - self.app_conf.refresh_config() - mock_logger.assert_called_with('Failed to refresh PMSH AppConfig') - - @patch('mod.logger.debug') - def test_utils_validate_config_subscription(self, mock_logger): - self.app_conf.validate_sub_schema() - mock_logger.assert_called_with("Subscription schema is valid.") - - @patch('mod.logger.debug') - def test_utils_validate_config_subscription_administrativeState_locked(self, mock_logger): - self.app_conf.subscription.administrativeState = "LOCKED" - self.app_conf.validate_sub_schema() - mock_logger.assert_called_with("Subscription schema is valid.") - - def test_utils_validate_config_subscription_administrativeState_invalid_value(self): - self.app_conf.subscription.administrativeState = "FAILED" - with self.assertRaises(ValidationError): - self.app_conf.validate_sub_schema() - - def test_utils_validate_config_subscription_nfFilter_failed(self): - self.app_conf.subscription.nfFilter = {} - with self.assertRaises(ValidationError): - self.app_conf.validate_sub_schema() - - def test_utils_validate_config_subscription_nfFilter_not_empty(self): - self.app_conf.subscription.nfFilter = { - "nfNames": [ - - ], - "modelInvariantIDs": [ - - ], - "modelVersionIDs": [ - - ], - "modelNames": [ - - ] - } - with self.assertRaises(ValidationError): - self.app_conf.validate_sub_schema() - - @patch('mod.logger.debug') - def test_utils_validate_config_subscription_nfFilter_with_empty_property(self, mock_logger): - self.app_conf.subscription.nfFilter = { - "nfNames": [ - "^pnf.*", - "^vnf.*" - ], - "modelInvariantIDs": [ - "7129e420-d396-4efb-af02-6b83499b12f8" - ], - "modelVersionIDs": [ - - ], - "modelNames": [ - "pnf102" - ] - } - self.app_conf.validate_sub_schema() - mock_logger.assert_called_with("Subscription schema is valid.") - - def test_utils_validate_config_subscription_where_measurementTypes_is_empty(self): - self.app_conf.subscription.measurementGroups = [{ - "measurementGroup": { - "measurementTypes": [ - ], - "managedObjectDNsBasic": [ - { - "DN": "dna" - }, - { - "DN": "dnb" - } - ] - } - }] - with self.assertRaises(ValidationError): - self.app_conf.validate_sub_schema() - - def test_utils_validate_config_subscription_where_managedObjectDNsBasic_is_empty(self): - self.app_conf.subscription.measurementGroups = [{ - "measurementGroup": { - "measurementTypes": [ - { - "measurementType": "countera" - }, - { - "measurementType": "counterb" - } - ], - "managedObjectDNsBasic": [ - - ] - } - }] - with self.assertRaises(ValidationError): - self.app_conf.validate_sub_schema() - - def test_utils_validate_config_subscription_where_measurementGroups_is_empty(self): - self.app_conf.subscription.measurementGroups = [] - with self.assertRaises(ValidationError): - self.app_conf.validate_sub_schema() diff --git a/components/pm-subscription-handler/tests/test_policy_response_handler.py b/components/pm-subscription-handler/tests/test_policy_response_handler.py index d5ae5ce1..735e9381 100644 --- a/components/pm-subscription-handler/tests/test_policy_response_handler.py +++ b/components/pm-subscription-handler/tests/test_policy_response_handler.py @@ -18,32 +18,21 @@ from unittest.mock import patch, MagicMock from mod import db +from mod.api.services.measurement_group_service import MgNfState, AdministrativeState from mod.api.services import measurement_group_service from mod.network_function import NetworkFunction from mod.policy_response_handler import PolicyResponseHandler, policy_response_handle_functions -from mod.subscription import AdministrativeState, SubNfState from tests.base_setup import BaseClassSetup, create_subscription_data class PolicyResponseHandlerTest(BaseClassSetup): - @classmethod - def setUpClass(cls): - super().setUpClass() @patch('mod.create_app') def setUp(self, mock_app): super().setUp() - super().setUpAppConf() self.nf = NetworkFunction(nf_name='nf1') self.policy_response_handler = PolicyResponseHandler(mock_app) - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - @patch('mod.network_function.NetworkFunction.delete') def test_handle_response_locked_success(self, mock_delete): with patch.dict(policy_response_handle_functions, @@ -64,7 +53,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): self.nf.nf_name, 'failed') mock_update_sub_nf.assert_called_with( measurement_group_name='msr_grp_name', - status=SubNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name) + status=MgNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name) @patch('mod.network_function.NetworkFunction.delete') def test_handle_response_locking_success(self, mock_delete): @@ -86,7 +75,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): self.nf.nf_name, 'failed') mock_update_sub_nf.assert_called_with( measurement_group_name='msr_grp_name', - status=SubNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name) + status=MgNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name) @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') def test_handle_response_unlocked_success(self, mock_update_sub_nf): @@ -98,7 +87,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): self.nf.nf_name, 'success') mock_update_sub_nf.assert_called_with( measurement_group_name='msr_grp_name', - status=SubNfState.CREATED.value, nf_name=self.nf.nf_name) + status=MgNfState.CREATED.value, nf_name=self.nf.nf_name) @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') def test_handle_response_unlocked_success_filtering(self, mock_update_sub_nf): @@ -107,7 +96,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): sub = create_subscription_data('sub') db.session.add(sub) measurement_group_service.apply_nf_status_to_measurement_group( - self.nf.nf_name, "MG2", SubNfState.PENDING_CREATE.value) + self.nf.nf_name, "MG2", MgNfState.PENDING_CREATE.value) db.session.commit() self.policy_response_handler._handle_response( 'MG2', @@ -115,7 +104,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): self.nf.nf_name, 'success') mock_update_sub_nf.assert_called_with( measurement_group_name='MG2', - status=SubNfState.CREATED.value, nf_name=self.nf.nf_name) + status=MgNfState.CREATED.value, nf_name=self.nf.nf_name) @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') def test_handle_response_locking_success_filtering(self, mock_update_sub_nf): @@ -124,7 +113,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): sub = create_subscription_data('sub') db.session.add(sub) measurement_group_service.apply_nf_status_to_measurement_group( - self.nf.nf_name, "MG2", SubNfState.PENDING_DELETE.value) + self.nf.nf_name, "MG2", MgNfState.PENDING_DELETE.value) db.session.commit() self.policy_response_handler._handle_response( 'MG2', @@ -132,7 +121,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): self.nf.nf_name, 'success') mock_update_sub_nf.assert_called_with( measurement_group_name='MG2', - status=SubNfState.DELETED.value, nf_name=self.nf.nf_name) + status=MgNfState.DELETED.value, nf_name=self.nf.nf_name) @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') def test_handle_response_unlocked_failed(self, mock_update_sub_nf): @@ -144,7 +133,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): self.nf.nf_name, 'failed') mock_update_sub_nf.assert_called_with( measurement_group_name='msr_grp_name', - status=SubNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name) + status=MgNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name) @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') def test_handle_response_create_failed_filtering(self, mock_update_sub_nf): @@ -153,7 +142,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): sub = create_subscription_data('sub') db.session.add(sub) measurement_group_service.apply_nf_status_to_measurement_group( - self.nf.nf_name, "MG2", SubNfState.PENDING_CREATE.value) + self.nf.nf_name, "MG2", MgNfState.PENDING_CREATE.value) db.session.commit() self.policy_response_handler._handle_response( 'MG2', @@ -161,7 +150,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): self.nf.nf_name, 'failed') mock_update_sub_nf.assert_called_with( measurement_group_name='MG2', - status=SubNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name) + status=MgNfState.CREATE_FAILED.value, nf_name=self.nf.nf_name) @patch('mod.api.services.measurement_group_service.update_measurement_group_nf_status') def test_handle_response_delete_failed_filtering(self, mock_update_sub_nf): @@ -170,7 +159,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): sub = create_subscription_data('sub') db.session.add(sub) measurement_group_service.apply_nf_status_to_measurement_group( - self.nf.nf_name, "MG2", SubNfState.PENDING_DELETE.value) + self.nf.nf_name, "MG2", MgNfState.PENDING_DELETE.value) db.session.commit() self.policy_response_handler._handle_response( 'MG2', @@ -178,7 +167,7 @@ class PolicyResponseHandlerTest(BaseClassSetup): self.nf.nf_name, 'failed') mock_update_sub_nf.assert_called_with( measurement_group_name='MG2', - status=SubNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name) + status=MgNfState.DELETE_FAILED.value, nf_name=self.nf.nf_name) def test_handle_response_exception(self): self.assertRaises(Exception, self.policy_response_handler._handle_response, 'sub1', diff --git a/components/pm-subscription-handler/tests/test_subscription.py b/components/pm-subscription-handler/tests/test_subscription.py deleted file mode 100755 index 5c40c4fd..00000000 --- a/components/pm-subscription-handler/tests/test_subscription.py +++ /dev/null @@ -1,168 +0,0 @@ -# ============LICENSE_START=================================================== -# Copyright (C) 2019-2021 Nordix Foundation. -# ============================================================================ -# 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. -# -# SPDX-License-Identifier: Apache-2.0 -# ============LICENSE_END===================================================== -import json -import os -from unittest.mock import patch, Mock - -from requests import Session - -import mod.aai_client as aai_client -from mod.network_function import NetworkFunction -from mod.subscription import Subscription -from tests.base_setup import BaseClassSetup - - -class SubscriptionTest(BaseClassSetup): - - @classmethod - def setUpClass(cls): - super().setUpClass() - - @patch.object(Session, 'get') - @patch.object(Session, 'put') - def setUp(self, mock_session_put, mock_session_get): - super().setUp() - with open(os.path.join(os.path.dirname(__file__), 'data/aai_xnfs.json'), 'r') as data: - self.aai_response_data = data.read() - mock_session_put.return_value.status_code = 200 - mock_session_put.return_value.text = self.aai_response_data - with open(os.path.join(os.path.dirname(__file__), 'data/aai_model_info.json'), 'r') as data: - self.aai_model_data = data.read() - mock_session_get.return_value.status_code = 200 - mock_session_get.return_value.text = self.aai_model_data - self.mock_mr_sub = Mock() - self.mock_mr_pub = Mock() - self.app_conf.subscription.create() - self.xnfs = aai_client.get_pmsh_nfs_from_aai(self.app_conf, self.app_conf.nf_filter) - self.sub_model = self.app_conf.subscription.get() - - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - - def test_sub_measurement_group(self): - self.assertEqual(len(self.app_conf.subscription.measurementGroups), 2) - - def test_sub_file_location(self): - self.assertEqual(self.app_conf.subscription.fileLocation, '/pm/pm.xml') - - def test_get_subscription(self): - sub_name = 'ExtraPM-All-gNB-R2B' - new_sub = self.app_conf.subscription.get() - self.assertEqual(sub_name, new_sub.subscription_name) - - def test_get_nf_names_per_sub(self): - self.app_conf.subscription.add_network_function_to_subscription(list(self.xnfs)[0], - self.sub_model) - self.app_conf.subscription.add_network_function_to_subscription(list(self.xnfs)[1], - self.sub_model) - - def test_add_duplicate_network_functions_per_subscription(self): - self.app_conf.subscription.add_network_function_to_subscription(list(self.xnfs)[0], - self.sub_model) - nf_subs = Subscription.get_all_nfs_subscription_relations() - self.assertEqual(1, len(nf_subs)) - self.app_conf.subscription.add_network_function_to_subscription(list(self.xnfs)[0], - self.sub_model) - nf_subs = Subscription.get_all_nfs_subscription_relations() - self.assertEqual(1, len(nf_subs)) - - def test_update_subscription_status(self): - self.app_conf.subscription.administrativeState = 'new_status' - self.app_conf.subscription.update_subscription_status() - sub = self.app_conf.subscription.get() - - self.assertEqual('new_status', sub.status) - - def test_update_sub_nf_status(self): - sub_name = 'ExtraPM-All-gNB-R2B' - for nf in self.xnfs: - self.app_conf.subscription.add_network_function_to_subscription(nf, self.sub_model) - sub_nfs = Subscription.get_all_nfs_subscription_relations() - self.assertEqual('PENDING_CREATE', sub_nfs[0].nf_sub_status) - - Subscription.update_sub_nf_status(sub_name, 'Active', 'pnf_23') - sub_nfs = Subscription.get_all_nfs_subscription_relations() - self.assertEqual('PENDING_CREATE', sub_nfs[0].nf_sub_status) - self.assertEqual('PENDING_CREATE', sub_nfs[1].nf_sub_status) - - @patch('mod.subscription.Subscription.add_network_function_to_subscription') - @patch('mod.subscription.Subscription.update_sub_nf_status') - def test_process_activate_subscription(self, mock_update_sub_nf, mock_add_nfs): - self.app_conf.subscription.create_subscription_on_nfs([list(self.xnfs)[0]], - self.mock_mr_pub) - - mock_add_nfs.assert_called() - self.assertTrue(self.mock_mr_pub.publish_subscription_event_data.called) - mock_update_sub_nf.assert_called_with(self.app_conf.subscription.subscriptionName, - 'PENDING_CREATE', list(self.xnfs)[0].nf_name) - - @patch('mod.subscription.Subscription.get_network_functions') - @patch('mod.subscription.Subscription.update_sub_nf_status') - def test_process_deactivate_subscription(self, mock_update_sub_nf, mock_get_nfs): - self.app_conf.subscription.administrativeState = 'LOCKED' - mock_get_nfs.return_value = [list(self.xnfs)[0]] - self.app_conf.subscription.delete_subscription_from_nfs(self.xnfs, self.mock_mr_pub) - self.assertTrue(self.mock_mr_pub.publish_subscription_event_data.called) - self.assertEqual(mock_update_sub_nf.call_count, 3) - - def test_activate_subscription_exception(self): - self.assertRaises(Exception, self.app_conf.subscription.create_subscription_on_nfs, - [list(self.xnfs)[0]], 'not_mr_pub', 'app_config') - - def test_prepare_subscription_event(self): - with open(os.path.join(os.path.dirname(__file__), - 'data/pm_subscription_event.json'), 'r') as data: - expected_sub_event = json.load(data) - nf = NetworkFunction(nf_name='pnf_1', - ipv4_address='204.120.0.15', - ipv6_address='', - model_invariant_id='some-id', - model_version_id='some-id') - nf.sdnc_model_name = 'some-name' - nf.sdnc_model_version = 'some-version' - actual_sub_event = self.app_conf.subscription.prepare_subscription_event(nf) - print(actual_sub_event) - self.assertEqual(expected_sub_event, actual_sub_event) - - def test_prepare_subscription_event_with_ipv6(self): - with open(os.path.join(os.path.dirname(__file__), - 'data/pm_subscription_event.json'), 'r') as data: - expected_sub_event = json.load(data) - expected_sub_event['ipAddress'] = '2001:db8:3333:4444:5555:6666:7777:8888' - nf = NetworkFunction(nf_name='pnf_1', - ipv4_address='204.120.0.15', - ipv6_address='2001:db8:3333:4444:5555:6666:7777:8888', - model_invariant_id='some-id', - model_version_id='some-id') - nf.sdnc_model_name = 'some-name' - nf.sdnc_model_version = 'some-version' - actual_sub_event = self.app_conf.subscription.prepare_subscription_event(nf) - print(actual_sub_event) - self.assertEqual(expected_sub_event, actual_sub_event) - - def test_get_network_functions(self): - for nf in self.xnfs: - self.app_conf.subscription.add_network_function_to_subscription(nf, self.sub_model) - nfs = self.app_conf.subscription.get_network_functions() - - self.assertEqual(3, len(nfs)) - self.assertIsInstance(nfs[0], NetworkFunction) diff --git a/components/pm-subscription-handler/tests/test_subscription_handler.py b/components/pm-subscription-handler/tests/test_subscription_handler.py deleted file mode 100644 index 1843eb44..00000000 --- a/components/pm-subscription-handler/tests/test_subscription_handler.py +++ /dev/null @@ -1,181 +0,0 @@ -# ============LICENSE_START=================================================== -# Copyright (C) 2020-2021 Nordix Foundation. -# ============================================================================ -# 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. -# -# SPDX-License-Identifier: Apache-2.0 -# ============LICENSE_END===================================================== -from unittest.mock import patch, Mock, MagicMock - -from mod.api.db_models import NetworkFunctionModel -from mod.network_function import NetworkFunction -from mod.subscription import AdministrativeState -from mod.subscription_handler import SubscriptionHandler -from tests.base_setup import BaseClassSetup, get_pmsh_config - - -class SubscriptionHandlerTest(BaseClassSetup): - nfs = [ - NetworkFunction(nf_name='pnf_1', model_invariant_id='some-id', model_version_id='some-id'), - NetworkFunction(nf_name='pnf_2', model_invariant_id='some-id', model_version_id='some-id')] - - @classmethod - def setUpClass(cls): - super().setUpClass() - - @patch('mod.pmsh_utils._MrSub') - @patch('mod.pmsh_utils._MrPub') - def setUp(self, mock_mr_pub, mock_mr_sub): - super().setUp() - self.mock_mr_pub = mock_mr_pub - self.mock_mr_sub = mock_mr_sub - self.mock_policy_event_thread = Mock() - - def tearDown(self): - super().tearDown() - - @classmethod - def tearDownClass(cls): - super().tearDownClass() - - @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config())) - @patch('mod.subscription.Subscription.get_local_sub_admin_state') - @patch('mod.logger.info') - @patch('mod.aai_client.get_pmsh_nfs_from_aai') - def test_execute_no_change_of_state(self, mock_get_aai, mock_logger, mock_get_sub_status): - mock_get_sub_status.return_value = AdministrativeState.UNLOCKED.value - mock_get_aai.return_value = self.nfs - sub_handler = SubscriptionHandler(self.mock_mr_pub, - self.mock_mr_sub, self.app, self.app_conf) - sub_handler.execute() - mock_logger.assert_called_with('Administrative State did not change ' - 'in the app config: UNLOCKED') - - @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config())) - @patch('mod.subscription.Subscription.get_local_sub_admin_state') - @patch('mod.subscription.Subscription.create_subscription_on_nfs') - @patch('mod.aai_client.get_pmsh_nfs_from_aai') - def test_execute_change_of_state_to_unlocked(self, mock_get_aai, mock_activate_sub, - mock_get_sub_status): - mock_get_aai.return_value = self.nfs - mock_get_sub_status.return_value = AdministrativeState.LOCKED.value - sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app, - self.app_conf) - sub_handler.execute() - self.assertEqual(AdministrativeState.UNLOCKED.value, - self.app_conf.subscription.administrativeState) - mock_activate_sub.assert_called_with(self.nfs, self.mock_mr_pub) - - @patch('mod.subscription.Subscription.get_network_functions', MagicMock(return_value=nfs)) - @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config())) - @patch('mod.subscription.Subscription.get_local_sub_admin_state') - @patch('mod.subscription.Subscription.delete_subscription_from_nfs') - def test_execute_change_of_state_to_locked(self, mock_deactivate_sub, mock_get_sub_status): - mock_get_sub_status.return_value = AdministrativeState.UNLOCKED.value - self.app_conf.subscription.administrativeState = AdministrativeState.LOCKED.value - self.app_conf.subscription.update_subscription_status() - sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app, - self.app_conf) - sub_handler.execute() - mock_deactivate_sub.assert_called_with(self.nfs, self.mock_mr_pub) - - @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config())) - @patch('mod.subscription.Subscription.create_subscription_on_nfs') - @patch('mod.logger.error') - @patch('mod.aai_client.get_pmsh_nfs_from_aai') - def test_execute_exception(self, mock_get_aai, mock_logger, mock_activate_sub): - mock_get_aai.return_value = self.nfs - mock_activate_sub.side_effect = Exception - sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app, - self.app_conf) - sub_handler.execute() - mock_logger.assert_called_with('Error occurred during the activation/deactivation process ', - exc_info=True) - - @patch('mod.network_function.NetworkFunction.get', - MagicMock(return_value=NetworkFunctionModel(nf_name='pnf_1', - model_invariant_id='some-id', - model_version_id='some-id', - ipv4_address='ip_address4', - ipv6_address='ip_address6', - model_name='model_name', - sdnc_model_name='sdnc_model_name', - sdnc_model_version='sdnc_model_version'))) - @patch('mod.subscription.Subscription.get_delete_failed_nfs', MagicMock(return_value=nfs)) - @patch('mod.subscription.Subscription.get_network_functions', MagicMock(return_value=nfs)) - @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config())) - @patch('mod.subscription.Subscription.get_local_sub_admin_state') - @patch('mod.subscription.Subscription.delete_subscription_from_nfs') - @patch('mod.network_function.NetworkFunction.increment_retry_count') - def test_execute_change_of_state_to_locking_retry_delete(self, mock_retry_inc, mock_delete_sub, - mock_get_sub_status): - mock_get_sub_status.return_value = AdministrativeState.LOCKING.value - sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app, - self.app_conf) - sub_handler.execute() - self.assertEqual(mock_delete_sub.call_count, 2) - self.assertEqual(mock_retry_inc.call_count, 2) - - @patch('mod.subscription.Subscription.get_delete_failed_nfs', MagicMock(return_value=[])) - @patch('mod.subscription.Subscription.get_network_functions', MagicMock(return_value=nfs)) - @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config())) - @patch('mod.subscription.Subscription.get_local_sub_admin_state') - @patch('mod.subscription.Subscription.update_subscription_status') - def test_execute_change_of_state_to_locking_success(self, mock_update_sub, - mock_get_sub_status): - mock_get_sub_status.return_value = AdministrativeState.LOCKING.value - sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app, - self.app_conf) - sub_handler.execute() - mock_update_sub.assert_called_once() - - @patch('mod.network_function.NetworkFunction.get', - MagicMock(return_value=NetworkFunctionModel(nf_name='pnf_1', - model_invariant_id='some-id', - model_version_id='some-id', - ipv4_address='ip_address4', - ipv6_address='ip_address6', - model_name='model_name', - sdnc_model_name='sdnc_model_name', - sdnc_model_version='sdnc_model_version', - retry_count=3))) - @patch('mod.subscription.Subscription.get_delete_failed_nfs', MagicMock(return_value=[nfs[0]])) - @patch('mod.subscription.Subscription.get_network_functions', MagicMock(return_value=nfs[0])) - @patch('mod.pmsh_utils.AppConfig.refresh_config', MagicMock(return_value=get_pmsh_config())) - @patch('mod.subscription.Subscription.get_local_sub_admin_state') - @patch('mod.network_function.NetworkFunction.delete') - def test_execute_change_of_state_to_locking_retry_failed(self, mock_nf_del, - mock_get_sub_status): - mock_get_sub_status.return_value = AdministrativeState.LOCKING.value - sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app, - self.app_conf) - sub_handler.execute() - mock_nf_del.assert_called_once() - - @patch('mod.pmsh_utils.AppConfig._get_pmsh_config', - MagicMock(return_value=get_pmsh_config('data/cbs_invalid_data.json'))) - @patch('mod.subscription_handler.SubscriptionHandler._check_state_change') - def test_execute_invalid_schema(self, mock_change_state_check): - sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app, - self.app_conf) - sub_handler.execute() - mock_change_state_check.assert_not_called() - - @patch('mod.pmsh_utils.AppConfig._get_pmsh_config', - MagicMock(return_value=get_pmsh_config())) - @patch('mod.subscription_handler.SubscriptionHandler._check_state_change') - def test_execute_valid_schema(self, mock_change_state_check): - sub_handler = SubscriptionHandler(self.mock_mr_pub, self.mock_mr_sub, self.app, - self.app_conf) - sub_handler.execute() - mock_change_state_check.assert_called_once() diff --git a/components/pm-subscription-handler/tox.ini b/components/pm-subscription-handler/tox.ini index 38acbbb8..9ee1c7df 100644 --- a/components/pm-subscription-handler/tox.ini +++ b/components/pm-subscription-handler/tox.ini @@ -1,5 +1,5 @@ # ============LICENSE_START======================================================= -# Copyright (C) 2019 Nordix Foundation. +# Copyright (C) 2019-2023 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ # ============LICENSE_END========================================================= [tox] -envlist = flake8,py39 +envlist = flake8,py39,py310 skip_missing_interpreters = true [testenv] diff --git a/components/pm-subscription-handler/version.properties b/components/pm-subscription-handler/version.properties index 3ad2137c..cf8d147e 100644 --- a/components/pm-subscription-handler/version.properties +++ b/components/pm-subscription-handler/version.properties @@ -1,6 +1,6 @@ major=2 minor=2 -patch=0 +patch=3 base_version=${major}.${minor}.${patch} release_version=${base_version} snapshot_version=${base_version}-SNAPSHOT diff --git a/components/slice-analysis-ms/ChangeLog.md b/components/slice-analysis-ms/ChangeLog.md index fa59c34d..a85827e5 100644 --- a/components/slice-analysis-ms/ChangeLog.md +++ b/components/slice-analysis-ms/ChangeLog.md @@ -3,6 +3,59 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [1.2.1] - 2023/03/02 + - [DCAEGEN2-3358](https://jira.onap.org/browse/DCAEGEN2-3358) - slice-analysis-ms fails to start + +## [1.2.0] - 2023/02/22 + - [DCAEGEN2-3355](https://jira.onap.org/browse/DCAEGEN2-3355) - Slice-Analysis-Ms vulnerability updates + +## [1.1.5] - 2022/09/14 + - [DCAEGEN2-3221](https://jira.onap.org/browse/DCAEGEN2-3221) - Slice-Analysis-Ms vulnerability updates + + - [DCAEGEN2-3195](https://jira.onap.org/browse/DCAEGEN2-3195) - CCVPN Kohn Enhancements for Intent-based Cloud Leased Line and Transport Slicing + + - [DCAEGEN2-3239](https://jira.onap.org/browse/DCAEGEN2-3239) - Enhance BandwidthEvaluator to listen on user's bandwidth threshold + + - [DCAEGEN2-3238](https://jira.onap.org/browse/DCAEGEN2-3238) - Enhance BandwidthEvaluator in slice-analysis-ms to support detailed bandwidth adjustment + + - [DCAEGEN2-3255](https://jira.onap.org/browse/DCAEGEN2-3255) - Fix bug of application failed to start + + - [DCAEGEN2-3264](https://jira.onap.org/browse/DCAEGEN2-3264) - Fix bug that cll service instance info didn't get updated when a cll service is deleted + + - [DCAEGEN2-3240](https://jira.onap.org/browse/DCAEGEN2-3240) - Implement runtime service configuration + + - [DCAEGEN2-3273](https://jira.onap.org/browse/DCAEGEN2-3273) - Fix bug that config thread hang up when cbs policy is empty + + - [DCAEGEN2-3270](https://jira.onap.org/browse/DCAEGEN2-3270) - Dcae slicems startup error, breaking the circular dependency. + +## [1.1.4] - 2022/07/28 + - [DCAEGEN2-3120](https://jira.onap.org/browse/DCAEGEN2-3120) - Enhance sliceanalysis MS to use DCAE SDK dmaap-client lib + + - [DCAEGEN2-3157](https://jira.onap.org/browse/DCAEGEN2-3157) - CodeCoverage improvement for dcaegen2-services-slice-analysis-ms + + - [DCAEGEN2-3242](https://jira.onap.org/browse/DCAEGEN2-3242) - Fix bug in ConfigFectchFromCbs that fetch will get hung when policy config in pdp engine is empty + + - [DCAEGEN2-3245](https://jira.onap.org/browse/DCAEGEN2-3245) - Fix sent wrong dmaap message issue. + +## [1.1.3] - 2022/05/11 + - [DCAEGEN2-3156](https://jira.onap.org/browse/DCAEGEN2-3156) - Fix bug in fetching PM data from DES + +## [1.1.2] - 2022/05/01 + - [DCAEGEN2-3145](https://jira.onap.org/browse/DCAEGEN2-3145) - Filter RAN related service instances in AAI + + - [DCAEGEN2-3146](https://jira.onap.org/browse/DCAEGEN2-3146) - Fetch CU Cells instead of DU cells data for ML message processing + + - [DCAEGEN2-3147](https://jira.onap.org/browse/DCAEGEN2-3147) - Fix the message content that SLICEANALYSISMS sends to Policy for CCVPN bw adjustment and suppress exceptions and error in job builder + + - [DCAEGEN2-3143](https://jira.onap.org/browse/DCAEGEN2-3143) - Suppress exceptions and ERRORS in slice-analysis-ms job building + +## [1.1.1] - 2022/04/12 + - [DCAEGEN2-3142](https://jira.onap.org/browse/DCAEGEN2-3142) - Filter data from AAI to avoid possible exceptions, remove null parameters in policy payload and add logs + + - [DCAEGEN2-3141](https://jira.onap.org/browse/DCAEGEN2-3141) - Bugfix in DCAE-SliceAnalysisMs for IBN user-triggered CCVPN closed-loop + +## [1.1.0] - 2022/3/10 + - [DCAEGEN2-3063](https://jira.onap.org/browse/DCAEGEN2-3063) - IBN user-triggered CLoud Leased Line update and CCVPN closed-loop ## [1.0.7] - 2021/12/16 - [DCAEGEN2-2963](https://jira.onap.org/browse/DCAEGEN2-2963) - Use onap/integration-java11 image @@ -13,6 +66,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [DCAEGEN2-3054](https://jira.onap.org/browse/DCAEGEN2-3054) - Remove security vulnerabilities + - [DCAEGEN2-2942](https://jira.onap.org/browse/DCAEGEN2-2942) - Calculate slice utilization data + + - [DCAEGEN2-3034](https://jira.onap.org/browse/DCAEGEN2-3034) - Migrate SliceAnalysis MS to use unauthenticated topic + + - [DCAEGEN2-3100](https://jira.onap.org/browse/DCAEGEN2-3100) - Update onset message test data + ## [1.0.6] - 2021/08/28 - [DCAEGEN2-2885](https://jira.onap.org/browse/DCAEGEN2-2885) - DCAE SliceAnalysis MS - CPS Integration diff --git a/components/slice-analysis-ms/pom.xml b/components/slice-analysis-ms/pom.xml index f4fde501..6d4e8fcc 100644 --- a/components/slice-analysis-ms/pom.xml +++ b/components/slice-analysis-ms/pom.xml @@ -5,6 +5,10 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020-2022 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 CTC, Inc. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * Copyright (C) 2023 Deutsche Telekom AG. 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. @@ -33,14 +37,14 @@ </parent> <groupId>org.onap.dcaegen2.services.components</groupId> <artifactId>slice-analysis-ms</artifactId> - <version>1.0.7-SNAPSHOT</version> + <version>1.2.1-SNAPSHOT</version> <name>dcaegen2-services-slice-analysis-ms</name> <description>Network slice PM analyser</description> <packaging>jar</packaging> <properties> <java.version>11</java.version> <sdk.version>1.8.7</sdk.version> - <spring.version>5.3.14</spring.version> + <spring.version>5.3.25</spring.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> @@ -56,6 +60,11 @@ </sonar.coverage.jacoco.xmlReportPaths> </properties> <dependencies> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.9.0</version> + </dependency> <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-util --> <dependency> <groupId>org.apache.tomcat</groupId> @@ -103,6 +112,41 @@ <artifactId>spring-data-commons</artifactId> <version>2.2.0.RELEASE</version> </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.4</version> + </dependency> + <dependency> + <groupId>io.projectreactor</groupId> + <artifactId>reactor-core</artifactId> + <version>3.4.18</version> + </dependency> + <dependency> + <groupId>io.projectreactor</groupId> + <artifactId>reactor-test</artifactId> + <version>3.4.18</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.onap.dmaap.messagerouter.dmaapclient</groupId> + <artifactId>dmaapClient</artifactId> + <version>1.1.12</version> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + </exclusion> + <exclusion> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + </exclusion> + <exclusion> + <artifactId>apache-log4j-extras</artifactId> + <groupId>log4j</groupId> + </exclusion> + </exclusions> + </dependency> <!-- cbs client --> <dependency> <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId> @@ -110,6 +154,16 @@ <version>${sdk.version}</version> </dependency> <dependency> + <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId> + <artifactId>dmaap-client</artifactId> + <version>${sdk.version}</version> + </dependency> + <dependency> + <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId> + <artifactId>http-client</artifactId> + <version>${sdk.version}</version> + </dependency> + <dependency> <groupId>org.onap.dcaegen2.services.sdk.security.crypt</groupId> <artifactId>crypt-password</artifactId> <version>${sdk.version}</version> @@ -123,11 +177,6 @@ <scope>import</scope> </dependency> <dependency> - <groupId>com.att.nsa</groupId> - <artifactId>cambriaClient</artifactId> - <version>0.0.1</version> - </dependency> - <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> @@ -135,7 +184,7 @@ <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> - <version>2.12.6</version> + <version>2.14.1</version> </dependency> <dependency> <groupId>net.javacrumbs.json-unit</groupId> @@ -146,7 +195,7 @@ <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> - <version>2.12.6</version> + <version>2.14.1</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.json/javax.json-api --> <dependency> @@ -168,7 +217,7 @@ <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> - <version>42.2.13</version> + <version>42.5.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> @@ -246,7 +295,7 @@ <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> - <version>9.4.41.v20210516</version> + <version>11.0.12</version> </dependency> <!-- https://mvnrepository.com/artifact/org.webjars/bootstrap --> <dependency> @@ -269,7 +318,7 @@ <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> - <version>9.0.50</version> + <version>9.0.72</version> </dependency> <!-- https://mvnrepository.com/artifact/nl.jqno.equalsverifier/equalsverifier --> <dependency> @@ -281,7 +330,37 @@ <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> - <version>1.2.10</version> + <version>1.4.5</version> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>1.18.22</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId> + <artifactId>dmaap-client</artifactId> + <version>1.8.7</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.onap.dcaegen2.services.sdk.rest.services</groupId> + <artifactId>dmaap-client</artifactId> + <version>1.8.7</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>io.projectreactor</groupId> + <artifactId>reactor-core</artifactId> + <version>3.4.18</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.projectreactor</groupId> + <artifactId>reactor-core</artifactId> + <version>3.4.18</version> + <scope>compile</scope> </dependency> </dependencies> <build> diff --git a/components/slice-analysis-ms/src/main/docker/config/sliceanalysisms/config_all.json b/components/slice-analysis-ms/src/main/docker/config/sliceanalysisms/config_all.json index 21a82344..9e233536 100644 --- a/components/slice-analysis-ms/src/main/docker/config/sliceanalysisms/config_all.json +++ b/components/slice-analysis-ms/src/main/docker/config/sliceanalysisms/config_all.json @@ -5,7 +5,7 @@ "aaf_password": null, "type": "message-router", "dmaap_info": { - "topic_url": "https://message-router.onap.svc.cluster.local:3905/events/unauthenticated.VES_MEASUREMENT_OUTPUT", + "topic_url": "http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.PERFORMANCE_MEASUREMENTS", "client_role": "sliceanalysis-subscriber", "location": "onap", "client_id": "sdnr-sliceanalysis-1" @@ -16,12 +16,52 @@ "aaf_password": null, "type": "message-router", "dmaap_info": { - "topic_url": "https://message-router.onap.svc.cluster.local:3905/events/DCAE_CL_RSP", + "topic_url": "http://message-router.onap.svc.cluster.local:3904/events/DCAE_CL_RSP", "client_role": "sliceanalysis-subscriber", "location": "onap", "client_id": "sdnr-sliceanalysis-1" }, "aaf_username": null + }, + "intelligent_slicing_topic": { + "aaf_password": null, + "type": "message-router", + "dmaap_info": { + "topic_url": "http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.ML_RESPONSE_TOPIC", + "client_role": "sliceanalysis-subscriber", + "location": "onap", + "client_id": "sdnr-sliceanalysis-1" + }, + "aaf_username": null + }, + "ves_ccvpn_notification_topic": { + "aaf_password": null, + "type": "message-router", + "dmaap_info": { + "topic_url": "http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.VES_NOTIFICATION_OUTPUT", + "client_role": "sliceanalysis-subscriber", + "location": "onap", + "client_id": "sdnr-sliceanalysis-1" + }, + "aaf_username": null + }, + "aai_subscriber":{ + "type":"message_router", + "aaf_username": null, + "aaf_password": null, + "api_key" : null, + "api_secret" : null, + "servers" : ["message-router:3904"], + "consumer_group" : "dcae_ccvpn_cl", + "consumer_instance" : "dcae_ccvpn_cl_aaievent", + "fetch_timeout" : 15000, + "fetch_limit" : 100, + "dmaap_info":{ + "topic_url":"http://message-router:3904/events/AAI-EVENT", + "client_role":"org.onap.dcae.aaiSub", + "location":"onap", + "client_id":"sdnr-sliceanalysis-1" + } } }, "streams_publishes": { @@ -29,7 +69,7 @@ "aaf_password": null, "type": "message-router", "dmaap_info": { - "topic_url": "https://message-router.onap.svc.cluster.local:3905/events/unauthenticated.DCAE_CL_OUTPUT", + "topic_url": "http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.DCAE_CL_OUTPUT", "client_role": "sliceanalysis-subscriber", "location": "onap", "client_id": "sdnr-sliceanalysis-1" @@ -47,13 +87,48 @@ "cbsPollingInterval": 60, "sliceanalysisms.cg": "sliceanalysisms-cg", "sliceanalysisms.pollingInterval": 20, + "sliceanalysisms.samples": 3, + "sliceanalysisms.minPercentageChange": 5, + "sliceanalysisms.initialDelaySeconds": 300000, + "sliceanalysisms.pollingTimeout": 60, "sliceanalysisms.cid": "sliceanalysisms-cid", - "sliceanalysisms.configDb.service": "http://sdnc.onap:8181", + "sliceanalysisms.configDb.service": "http://configdb_sim:5000", + "sliceanalysisms.aai.url": "https://aai-resources:8447/aai/v21", + "sliceanalysisms.cps.url": "http://cps-tbdmt:8080/execute/ran-network", + "sliceanalysisms.configDbEnabled": "false", + "sliceanalysisms.rannfnssiDetailsTemplateId": "get-rannfnssiid-details", + "sliceanalysisms.desUrl": "http://dl-des:1681/datalake/v1/exposure/pm_data", + "sliceanalysisms.pmDataDurationInWeeks": 4, + "sliceanalysisms.vesNotifPollingInterval": 5, + "sliceanalysisms.vesNotifChangeIdentifier": "PM_BW_UPDATE", + "sliceanalysisms.vesNotifChangeType": "BandwidthChanged", + "sliceanalysisms.aaiNotif.targetAction" : "UPDATE", + "sliceanalysisms.aaiNotif.targetSource" : "UUI", + "sliceanalysisms.aaiNotif.targetEntity" : "service-instance", + "sliceanalysisms.ccvpnEvalInterval": 5, + "sliceanalysisms.ccvpnEvalPrecision": 100.0, + "sliceanalysisms.ccvpnEvalPeriodicCheckOn": true, + "sliceanalysisms.ccvpnEvalOnDemandCheckOn": true, + "sliceanalysisms.ccvpnEvalStrategy" : "FlexibleThresholdStrategy", + "sliceanalysisms.ccvpnEvalUpperThreshold": 0.8, + "sliceanalysisms.ccvpnEvalLowerThreshold": 0.3, "service_calls": { "policy-req": [] - } + }, + "trust_store_path": "/opt/app/sliceanalysisms/etc/cert/trust.jks", + "trust_store_pass_path": "/opt/app/sliceanalysisms/etc/cert/trust.pass" }, - "policies": { - + "policies": { + "event": { + "action": "gathered", + "timestamp": "2019-09-18T14:57:55.320Z", + "update_id": "dbb88da8-8df1-489d-b51d-8d5cbbfbcd99", + "policies_count": 1 + }, + "items": [ + { + "policyName": "com.Config_PCIMS_CONFIG_POLICY.1.xml" + } + ] } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/MainThread.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/MainThread.java index 57a831ea..44566637 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/MainThread.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/MainThread.java @@ -1,51 +1,55 @@ /******************************************************************************* * ============LICENSE_START======================================================= - * son-handler + * slice-analysis-ms * ================================================================================ * Copyright (C) 2019-2020 Wipro Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= - * + * *******************************************************************************/ package org.onap.slice.analysis.ms; +import org.onap.slice.analysis.ms.service.ConfigThread; import org.onap.slice.analysis.ms.service.ConsumerThread; import org.onap.slice.analysis.ms.service.PmThread; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** +/** * This class starts the pm thread and consumer thread */ public class MainThread { - private static Logger log = LoggerFactory.getLogger(MainThread.class); - - private MainThread() { - - } - - /** - * main thread initialization. - */ - public static void initiateThreads() { - log.debug("initializing Pm thread & Consumer thread"); - Thread pmThread = new Thread(new PmThread()); - pmThread.start(); - Thread consumerThread = new Thread(new ConsumerThread()); - consumerThread.start(); - } + private static Logger log = LoggerFactory.getLogger(MainThread.class); + + private MainThread() { + + } + + /** + * main thread initialization. + */ + public static void initiateThreads() { + log.debug("initializing Pm thread & Consumer thread"); + Thread pmThread = new Thread(new PmThread()); + pmThread.start(); + Thread consumerThread = new Thread(new ConsumerThread()); + consumerThread.start(); + Thread configThread = new Thread(new ConfigThread()); + configThread.start(); + } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/AaiInterface.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/aai/AaiInterface.java index 68b795b5..582916aa 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/AaiInterface.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/aai/AaiInterface.java @@ -2,7 +2,8 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2021 Wipro Limited. + * Copyright (C) 2021-2022 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,18 +20,20 @@ * *******************************************************************************/ -package org.onap.slice.analysis.ms.configdb; +package org.onap.slice.analysis.ms.aai; import java.util.Map; /** - * + * * Interface for AAI * */ public interface AaiInterface { - public Map<String, String> fetchServiceDetails(String snssai); - public Map<String, Integer> fetchCurrentConfigurationOfSlice(String snssai); -} + public Map<String, String> fetchServiceDetails(String snssai); + public Map<String, Integer> fetchCurrentConfigurationOfSlice(String snssai); + + public Map<String, Integer> fetchMaxBandwidthOfService(String serviceId); +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/aai/AaiService.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/aai/AaiService.java new file mode 100644 index 00000000..b68373d1 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/aai/AaiService.java @@ -0,0 +1,432 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2021-2022 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.aai; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import java.util.Set; +import org.json.JSONArray; +import org.json.JSONObject; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.models.aai.ServiceInstance; +import org.onap.slice.analysis.ms.restclients.AaiRestClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +/** + * + * Service for AAI interfaces + * + */ +@Service +public class AaiService implements AaiInterface { + + private static Logger log = LoggerFactory.getLogger(Configuration.class); + + @Autowired + AaiRestClient restclient; + + private static ObjectMapper objectMapper = new ObjectMapper(); + private static String globalSubscriberId; + private static String subscriptionServiceType; + private static String aaiBaseUrl = Configuration.getInstance().getAaiUrl(); + + /** + * Fetches the details of a service + * + * @param snssai SNSSAI ID + * @return responseMap contains service details + */ + public Map<String, String> fetchServiceDetails(String snssai) { + Map<String, String> responseMap = fetchSubscriberAndSubscriptionServiceType(); + String serviceReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId + + "/service-subscriptions/service-subscription/" + subscriptionServiceType + "/service-instances"; + log.info("serviceReqUrl {}", serviceReqUrl); + String serviceRole = "AN-NF"; + try { + String serviceInstance = + restclient.sendGetRequest(serviceReqUrl, new ParameterizedTypeReference<String>() {}).getBody(); + JSONObject serviceInstanceJson = new JSONObject(serviceInstance); + JSONArray serviceInstanceList = serviceInstanceJson.getJSONArray("service-instance"); + for (int i = 0; i < serviceInstanceList.length(); i++) { + JSONObject serviceObj = serviceInstanceList.getJSONObject(i); + if (serviceObj.has("environment-context") && serviceObj.getString("environment-context").equalsIgnoreCase(snssai) + && serviceObj.has("workload-context") && serviceObj.getString("workload-context").contains("AN") + && serviceObj.has("service-role") + && serviceObj.getString("service-role").contains("slice-profile")) { + responseMap.put("sliceProfileId", serviceObj.getString("service-instance-id")); + } + } + + String serviceRoleReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId + + "/service-subscriptions/service-subscription/" + subscriptionServiceType + + "/service-instances/?service-role=nssi&depth=2"; + log.info("serviceRoleReqUrl {}", serviceRoleReqUrl); + String serviceInstanceForServiceRole = + restclient.sendGetRequest(serviceRoleReqUrl, new ParameterizedTypeReference<String>() {}).getBody(); + JSONObject serviceInstanceForServiceRoleJson = new JSONObject(serviceInstanceForServiceRole); + JSONArray serviceInstanceListForServiceRole = + serviceInstanceForServiceRoleJson.getJSONArray("service-instance"); + for (int i = 0; i < serviceInstanceListForServiceRole.length(); i++) { + JSONObject serviceObj = serviceInstanceListForServiceRole.getJSONObject(i); + if (serviceObj.has("workload-context") && serviceObj.getString("workload-context").trim().equalsIgnoreCase(serviceRole)) { + responseMap.put("ranNFNSSIId", serviceObj.getString("service-instance-id")); + } + } + } catch (Exception e) { + log.info("Exception while fetching serviceDetails: " + e); + } + responseMap.put("sNSSAI", snssai); + log.info("subscriber details: " + responseMap); + return responseMap; + } + + /** + * fetch all valid cll instances + * @return + */ + public Set<String> fetchAllCllInstances() { + globalSubscriberId = "IBNCustomer"; + subscriptionServiceType = "IBN"; + String serviceReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId + + "/service-subscriptions/service-subscription/" + subscriptionServiceType + "/service-instances"; + log.info("serviceReqUrl {}", serviceReqUrl); + Set<String> cllInstances = new HashSet<>(); + try { + String serviceInstance = + restclient.sendGetRequest(serviceReqUrl, new ParameterizedTypeReference<String>() {}).getBody(); + log.debug("The service instance response msg are :{}", serviceInstance); + JSONObject serviceInstanceJson = new JSONObject(serviceInstance); + JSONArray serviceInstanceArray = serviceInstanceJson.getJSONArray("service-instance"); + for (int i = 0; i < serviceInstanceArray.length(); i++) { + JSONObject serviceObj = serviceInstanceArray.getJSONObject(i); + String serviceId = serviceObj.getString("service-instance-id"); + log.debug("Jsonobject {}", serviceObj); + if(serviceId.startsWith("cll")){ + cllInstances.add(serviceId); + log.debug("Add {} to latest service id list", serviceId); + } + } + return cllInstances; + } catch (Exception e) { + log.error("Exception while fetching serviceDetails: " + e); + } + return new HashSet<>(); + } + + /** + * Fetches the current configuration of a Slice from AAI + * + * @param snssai SNSSAI ID + * @return responseMap contains slice configuration + */ + public Map<String, Integer> fetchCurrentConfigurationOfSlice(String snssai) { + log.info("AAI fetch config Slice: " + aaiBaseUrl); + String serviceInstaneId = null; + String serviceReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId + + "/service-subscriptions/service-subscription/" + subscriptionServiceType + "/service-instances"; + log.info("serviceReqUrl {}", serviceReqUrl); + Map<String, Integer> responseMap = new HashMap<String, Integer>(); + try { + String serviceInstance = + restclient.sendGetRequest(serviceReqUrl, new ParameterizedTypeReference<String>() {}).getBody(); + JSONObject serviceInstanceJson = new JSONObject(serviceInstance); + + JSONArray serviceInstanceList = serviceInstanceJson.getJSONArray("service-instance"); + for (int i = 0; i < serviceInstanceList.length(); i++) { + JSONObject serviceObj = serviceInstanceList.getJSONObject(i); + if (serviceObj.has("environment-context") && serviceObj.getString("environment-context").equalsIgnoreCase(snssai) + && serviceObj.has("workload-context") && serviceObj.getString("workload-context").contains("AN") + && serviceObj.has("service-role") + && serviceObj.getString("service-role").contains("slice-profile-instance")) { + serviceInstaneId = serviceObj.getString("service-instance-id"); + } + } + + String sliceProfileReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId + + "/service-subscriptions/service-subscription/" + subscriptionServiceType + + "/service-instances/service-instance/" + serviceInstaneId + "/slice-profiles"; + log.info("sliceProfileReqUrl {}", sliceProfileReqUrl); + String sliceProfile = restclient + .sendGetRequest(sliceProfileReqUrl, new ParameterizedTypeReference<String>() {}).getBody(); + JSONObject sliceProfileJson = new JSONObject(sliceProfile); + JSONArray sliceProfileList = sliceProfileJson.getJSONArray("slice-profile"); + for (int i = 0; i < sliceProfileList.length(); i++) { + JSONObject sliceProfileObj = sliceProfileList.getJSONObject(i); + responseMap.put("dLThptPerSlice", sliceProfileObj.getInt("exp-data-rate-UL")); + responseMap.put("uLThptPerSlice", sliceProfileObj.getInt("exp-data-rate-DL")); + break; + } + log.info("Slice configuration: " + responseMap); + } catch (Exception e) { + log.info("AAI Slice: " + e); + } + return responseMap; + } + + /** + * Fetches the details of a subscriber and subscription Service + * + * @return responseMap contains details of subscriber and subscription service + */ + public Map<String, String> fetchSubscriberAndSubscriptionServiceType() { + + Map<String, String> responseMap = new HashMap<String, String>(); + + log.info("Get GlobalSubscriberId"); + String subscriberReqUrl = aaiBaseUrl + "/business/customers"; + log.info("subscriberReqUrl {}", subscriberReqUrl); + try { + String subscriberReq = + restclient.sendGetRequest(subscriberReqUrl, new ParameterizedTypeReference<String>() {}).getBody(); + JSONObject subscriberReqJson = new JSONObject(subscriberReq); + JSONArray subscriberReqJsonList = subscriberReqJson.getJSONArray("customer"); + for (int i = 0; i < subscriberReqJsonList.length(); i++) { + JSONObject subscriberReqObj = subscriberReqJsonList.getJSONObject(i); + globalSubscriberId = subscriberReqObj.getString("global-customer-id"); + responseMap.put("globalSubscriberId", globalSubscriberId); + break; + } + + log.info("Get subscriptionServiceType"); + String subscriptionServiceReqUrl = + aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId + "/service-subscriptions"; + log.info("subscriptionServiceReqUrl: {}", subscriptionServiceReqUrl); + String subscriptionService = restclient + .sendGetRequest(subscriptionServiceReqUrl, new ParameterizedTypeReference<String>() {}).getBody(); + JSONObject subscriptionServiceJson = new JSONObject(subscriptionService); + JSONArray subscriptionServiceListJson = subscriptionServiceJson.getJSONArray("service-subscription"); + for (int i = 0; i < subscriptionServiceListJson.length(); i++) { + JSONObject subscriptionServiceObj = subscriptionServiceListJson.getJSONObject(i); + subscriptionServiceType = subscriptionServiceObj.getString("service-type"); + responseMap.put("subscriptionServiceType", subscriptionServiceType); + break; + } + } catch (Exception e) { + log.info("Exception while fetching subscriber and subscription: " + e); + } + + log.info("responseMap: " + responseMap); + return responseMap; + + } + + /** + * Fetches the SNSSIs of a serviceInstanceId + * + * @param sliceInstanceId service instance ID + * @return snssaiList contains list of SNSSAIs + */ + public List<String> getSnssaiList(String sliceInstanceId) { + fetchSubscriberAndSubscriptionServiceType(); + List<String> allotedResource = new ArrayList<>(); + List<String> sliceProfileList = new ArrayList<>(); + List<String> snssaiList = new ArrayList<>(); + + log.info("fetch slice instance details"); + String serviceReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId + + "/service-subscriptions/service-subscription/" + subscriptionServiceType + + "/service-instances/service-instance/" + sliceInstanceId; + log.info("serviceReqUrl {}", serviceReqUrl); + try { + String serviceInstanceString = + restclient.sendGetRequest(serviceReqUrl, new ParameterizedTypeReference<String>() {}).getBody(); + ServiceInstance serviceInstance = objectMapper.readValue(serviceInstanceString, ServiceInstance.class); + if (serviceInstance.getServiceRole().equalsIgnoreCase("nsi")) { + serviceInstance.getRelationshipList().getRelationship().forEach(relationship -> { + if (Objects.nonNull(relationship.getRelatedTo()) && relationship.getRelatedTo().equalsIgnoreCase("allotted-resource")) { + relationship.getRelationshipData().forEach(data -> { + if (data.get("relationship-key").equalsIgnoreCase("service-instance.service-instance-id")) { + allotedResource.add(data.get("relationship-value")); + } + + }); + } + }); + + return fetchSnssaiOfSliceProfile(fetchSliceProfilesOfAllotedResourceData(allotedResource)); + + } + if (serviceInstance.getServiceRole().equalsIgnoreCase("nssi")) { + serviceInstance.getRelationshipList().getRelationship().forEach(relationship -> { + if (Objects.nonNull(relationship.getRelatedToProperty())) { + relationship.getRelatedToProperty().forEach(property -> { + if (property.get("property-value").contains("sliceprofile")) { + relationship.getRelationshipData().forEach(data -> { + if (data.get("relationship-key") + .equalsIgnoreCase("service-instance.service-instance-id")) { + sliceProfileList.add(data.get("relationship-value")); + } + + }); + + } + + }); + } + }); + return fetchSnssaiOfSliceProfile(sliceProfileList); + } + + } catch (Exception e) { + log.info("Exception while fetching snssaiList: " + e); + } + + return snssaiList; + + } + + /** + * Fetches the sliceProfileList of a AllotedResource + * + * @param allotedResourceList contains list of allotedResource IDs + * @return sliceProfilesList contains list of SliceProfiles + */ + public List<String> fetchSliceProfilesOfAllotedResourceData(List<String> allotedResourceList) { + + List<String> sliceProfileList = new ArrayList<>(); + + log.info("fetch Alloted Resource Data"); + + allotedResourceList.forEach(serviceInstanceId -> { + try { + String serviceReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId + + "/service-subscriptions/service-subscription/" + subscriptionServiceType + + "/service-instances/service-instance/" + serviceInstanceId; + log.info("serviceReqUrl {}", serviceReqUrl); + String serviceInstanceString = + restclient.sendGetRequest(serviceReqUrl, new ParameterizedTypeReference<String>() {}).getBody(); + ServiceInstance serviceInstance = objectMapper.readValue(serviceInstanceString, ServiceInstance.class); + + serviceInstance.getRelationshipList().getRelationship().forEach(relationship -> { + relationship.getRelatedToProperty().forEach(property -> { + if (property.get("property-value").contains("sliceprofile")) { + relationship.getRelationshipData().forEach(data -> { + if (data.get("relationship-key") + .equalsIgnoreCase("service-instance.service-instance-id")) { + sliceProfileList.add(data.get("relationship-value")); + } + + }); + + } + + }); + + }); + } catch (Exception e) { + log.info("Exception while fetching AllotedResourceData: " + e); + } + + }); + + log.info("sliceProfileList: " + sliceProfileList); + + return sliceProfileList; + + } + + /** + * Fetches the snssaiList of a SliceProfile + * + * @param sliceProfileList contains list of sliceProfile IDs + * @return snssaiList contains list of SNSSAIs + */ + public List<String> fetchSnssaiOfSliceProfile(List<String> sliceProfileList) { + List<String> snssaiList = new ArrayList<>(); + + log.info("fetch SliceProfile"); + sliceProfileList.forEach(serviceInstanceId -> { + String serviceReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId + + "/service-subscriptions/service-subscription/" + subscriptionServiceType + "/service-instances/" + + "service-instance/" + serviceInstanceId; + log.info("serviceReqUrl {}", serviceReqUrl); + try { + String serviceInstanceString = + restclient.sendGetRequest(serviceReqUrl, new ParameterizedTypeReference<String>() {}).getBody(); + ServiceInstance serviceInstance = objectMapper.readValue(serviceInstanceString, ServiceInstance.class); + + if (serviceInstance.getServiceRole().equalsIgnoreCase("slice-profile")) { + if (!snssaiList.contains(serviceInstance.getEnvironmentContext())) { + snssaiList.add(serviceInstance.getEnvironmentContext()); + } + } + + } catch (Exception e) { + log.info("Exception while fetching sliceProfile data: " + e); + } + + }); + log.info("snssaiList: " + snssaiList); + + return snssaiList; + + } + + /** + * Get network bandwidth attribute of an ethernet service. These data is inside a network policy whose + * etwork-policy-fqdn equals to provided service-instance-id + * @param serviceId target service instance id + * @return Map contains maxBandwidth value of given service-instance + */ + public Map<String, Integer> fetchMaxBandwidthOfService(String serviceId){ + log.info("Fetching max-bandwidth from AAI network-policy"); + String networkPolicyUrl = aaiBaseUrl + "/network/network-policies" + "?network-policy-fqdn=" + + serviceId; + Map<String, Integer> result = new HashMap<>(); + try { + ResponseEntity<String> resp = restclient.sendGetRequest(networkPolicyUrl, new ParameterizedTypeReference<String>() { + }); + log.debug("AaiService received {} : {}", resp.getStatusCodeValue(), resp.getBody()); + if (resp.getStatusCodeValue() == 200){ + String networkPolicy = resp.getBody(); + JSONObject networkPolicyJson = new JSONObject(networkPolicy); + JSONArray networkPolicyList = networkPolicyJson.optJSONArray("network-policy"); + if (networkPolicyList != null && networkPolicyList.length() > 0){ + JSONObject networkPolicyOjb = networkPolicyList.getJSONObject(0); + result.put("maxBandwidth", networkPolicyOjb.getInt("max-bandwidth")); + log.info("Successfully retrieved max bandwidth for service {}: {}", + serviceId, result.get("maxBandwidth")); + return result; + } + } + log.warn("Failed to retrieve max bandwidth for service {}, no such network-policy or no valid max-bandwidth " + + "associated", serviceId); + } catch (Exception e){ + log.warn("Error encountered when fetching maxbandwidth: " + e); + } + return new HashMap<String, Integer>(); + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/AaiService.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/AaiService.java deleted file mode 100644 index 16ff71a6..00000000 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/AaiService.java +++ /dev/null @@ -1,179 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * slice-analysis-ms - * ================================================================================ - * Copyright (C) 2021 Wipro Limited. - * ============================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - *******************************************************************************/ - -package org.onap.slice.analysis.ms.configdb; - -import java.util.HashMap; -import java.util.Map; - -import org.json.JSONArray; -import org.json.JSONObject; -import org.onap.slice.analysis.ms.models.Configuration; -import org.onap.slice.analysis.ms.restclients.AaiRestClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.stereotype.Service; - -/** - * - * Service for AAI interfaces - * - */ -@Service -public class AaiService implements AaiInterface { - - private static Logger log = LoggerFactory.getLogger(Configuration.class); - - @Autowired - AaiRestClient restclient; - private static String globalSubscriberId; - private static String subscriptionServiceType; - private static String aaiBaseUrl = Configuration.getInstance().getAaiUrl(); - - /** - * Fetches the details of a subscriber - */ - public Map<String, String> fetchServiceDetails(String snssai) { - log.info("AAI fetch service: "); - Map<String, String> responseMap = new HashMap<String, String>(); - - log.info("AAI getGlobalSubscriberId: "); - String subscriberReqUrl = aaiBaseUrl + "/business/customers"; - try { - String subscriberReq = restclient - .sendGetRequest(subscriberReqUrl, new ParameterizedTypeReference<String>() { - }).getBody(); - JSONObject subscriberReqJson = new JSONObject(subscriberReq); - JSONArray subscriberReqJsonList = subscriberReqJson.getJSONArray("customer"); - for (int i = 0; i < subscriberReqJsonList.length(); i++) { - JSONObject subscriberReqObj = subscriberReqJsonList.getJSONObject(i); - globalSubscriberId = subscriberReqObj.getString("global-customer-id"); - responseMap.put("globalSubscriberId", globalSubscriberId); - break; - } - } catch (Exception e) { - log.info("Exception while fetching getGlobalSubscriberId: " + e); - } - - String subscriptionServiceReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId - + "/service-subscriptions"; - try { - String subscriptionService = restclient - .sendGetRequest(subscriptionServiceReqUrl, new ParameterizedTypeReference<String>() { - }).getBody(); - JSONObject subscriptionServiceJson = new JSONObject(subscriptionService); - JSONArray subscriptionServiceListJson = subscriptionServiceJson.getJSONArray("service-subscription"); - for (int i = 0; i < subscriptionServiceListJson.length(); i++) { - JSONObject subscriptionServiceObj = subscriptionServiceListJson.getJSONObject(i); - subscriptionServiceType = subscriptionServiceObj.getString("service-type"); - responseMap.put("subscriptionServiceType", subscriptionServiceType); - break; - } - } catch (Exception e) { - log.info("Exception while fetching subscriptionService: " + e); - } - - String serviceReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId - + "/service-subscriptions/service-subscription/" + subscriptionServiceType + "/service-instances"; - String serviceRole = "AN-NF"; - try { - String serviceInstance = restclient.sendGetRequest(serviceReqUrl, new ParameterizedTypeReference<String>() { - }).getBody(); - JSONObject serviceInstanceJson = new JSONObject(serviceInstance); - JSONArray serviceInstanceList = serviceInstanceJson.getJSONArray("service-instance"); - for (int i = 0; i < serviceInstanceList.length(); i++) { - JSONObject serviceObj = serviceInstanceList.getJSONObject(i); - if (serviceObj.getString("environment-context").equalsIgnoreCase(snssai)) { - responseMap.put("sliceProfileId", serviceObj.getString("service-instance-id")); - } - } - - String serviceRoleReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId - + "/service-subscriptions/service-subscription/" + subscriptionServiceType - + "/service-instances/?service-role=nssi&depth=2"; - - String serviceInstanceForServiceRole = restclient - .sendGetRequest(serviceRoleReqUrl, new ParameterizedTypeReference<String>() { - }).getBody(); - JSONObject serviceInstanceForServiceRoleJson = new JSONObject(serviceInstanceForServiceRole); - JSONArray serviceInstanceListForServiceRole = serviceInstanceForServiceRoleJson - .getJSONArray("service-instance"); - for (int i = 0; i < serviceInstanceListForServiceRole.length(); i++) { - JSONObject serviceObj = serviceInstanceListForServiceRole.getJSONObject(i); - if (serviceObj.getString("workload-context").trim().equalsIgnoreCase(serviceRole)) { - responseMap.put("ranNFNSSIId", serviceObj.getString("service-instance-id")); - } - } - } catch (Exception e) { - log.info("Exception while fetching serviceDetails: " + e); - } - responseMap.put("sNSSAI", snssai); - log.info("subscriber details: " + responseMap); - return responseMap; - } - - /** - * Fetches the current configuration of an Slice from AAI - */ - public Map<String, Integer> fetchCurrentConfigurationOfSlice(String snssai) { - log.info("AAI fetch config Slice: " + aaiBaseUrl); - String serviceInstaneId = null; - String serviceReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId - + "/service-subscriptions/service-subscription/" + subscriptionServiceType + "/service-instances"; - Map<String, Integer> responseMap = new HashMap<String, Integer>(); - try { - String serviceInstance = restclient.sendGetRequest(serviceReqUrl, new ParameterizedTypeReference<String>() { - }).getBody(); - JSONObject serviceInstanceJson = new JSONObject(serviceInstance); - - JSONArray serviceInstanceList = serviceInstanceJson.getJSONArray("service-instance"); - for (int i = 0; i < serviceInstanceList.length(); i++) { - JSONObject serviceObj = serviceInstanceList.getJSONObject(i); - if (serviceObj.getString("environment-context").equalsIgnoreCase(snssai)) { - serviceInstaneId = serviceObj.getString("service-instance-id"); - } - } - - String sliceProfileReqUrl = aaiBaseUrl + "/business/customers/customer/" + globalSubscriberId - + "/service-subscriptions/service-subscription/" + subscriptionServiceType - + "/service-instances/service-instance/" + serviceInstaneId + "/slice-profiles"; - - String sliceProfile = restclient - .sendGetRequest(sliceProfileReqUrl, new ParameterizedTypeReference<String>() { - }).getBody(); - JSONObject sliceProfileJson = new JSONObject(sliceProfile); - JSONArray sliceProfileList = sliceProfileJson.getJSONArray("slice-profile"); - for (int i = 0; i < sliceProfileList.length(); i++) { - JSONObject sliceProfileObj = sliceProfileList.getJSONObject(i); - responseMap.put("dLThptPerSlice", sliceProfileObj.getInt("exp-data-rate-UL")); - responseMap.put("uLThptPerSlice", sliceProfileObj.getInt("exp-data-rate-DL")); - break; - } - log.info("Slice configuration: " + responseMap); - } catch (Exception e) { - log.info("AAI Slice: " + e); - } - return responseMap; - } -} - diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceService.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceService.java index 50a60ac3..3e41fbee 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceService.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceService.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -128,5 +128,24 @@ public class ConfigDbInterfaceService implements IConfigDbService { return response.getBody(); } + /** + * Fetches the CUCP Cells of an S-NSSAI from config DB + */ + public Map<String, List<String>> fetchCUCPCellsOfSnssai(String snssai){ + Map<String,List<String>> responseMap=new HashMap<>(); + String reqUrl=configDbBaseUrl+"/api/sdnc-config-db/v4/cucp-cell-list/"+snssai; + ResponseEntity<Map<String,List<CellsModel>>> response = restclient.sendGetRequest(reqUrl, new ParameterizedTypeReference<Map<String,List<CellsModel>>>() { + }); + + for (Map.Entry<String, List<CellsModel>> entry : response.getBody().entrySet()) { + List<String> cellslist=new ArrayList<>(); + for(CellsModel cellmodel:entry.getValue()) { + cellslist.add(cellmodel.getCellLocalId()); + } + responseMap.put(entry.getKey(), cellslist); + } + return responseMap; + } + } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/CpsService.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/CpsService.java deleted file mode 100644 index 389a75d9..00000000 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/CpsService.java +++ /dev/null @@ -1,137 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * slice-analysis-ms - * ================================================================================ - * Copyright (C) 2021 Wipro Limited. - * ============================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - *******************************************************************************/ -package org.onap.slice.analysis.ms.configdb; - -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.ArrayList; - -import org.json.JSONArray; -import org.json.JSONObject; -import org.onap.slice.analysis.ms.models.Configuration; -import org.onap.slice.analysis.ms.restclients.CpsRestClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.stereotype.Service; - -/** - * - * Service for CPS interfaces - * - */ -@Service -public class CpsService implements CpsInterface { - - private static Logger log = LoggerFactory.getLogger(CpsService.class); - - @Autowired - CpsRestClient restclient; - private static String cpsBaseUrl = Configuration.getInstance().getCpsUrl(); - - /** - * Fetches the current configuration of RIC from CPS - */ - public Map<String, Map<String, Object>> fetchCurrentConfigurationOfRIC(String snssai) { - Map<String, Map<String, Object>> responseMap = new HashMap<String, Map<String, Object>>(); - String reqUrl = cpsBaseUrl +"/get-nearrtric-config"; - log.info("fetching current configuration of RIC from Cps: {s-NSSAI: "+snssai+"}"); - String requestBody = "{\"inputParameters\": {\"sNssai\":"+JSONObject.quote(snssai)+"}}"; - try { - String response = restclient.sendPostRequest(reqUrl,requestBody, new ParameterizedTypeReference<String>() {}).getBody(); - JSONArray sliceArray = new JSONArray(response); - for (int i=0;i<sliceArray.length();i++) { - String nearRTTICid = sliceArray.getJSONObject(i).optString("idNearRTRIC"); - JSONArray pLMNInfoList = sliceArray.getJSONObject(i).getJSONObject("attributes").getJSONArray("pLMNInfoList"); - for (int j=0;j<pLMNInfoList.length();j++){ - JSONArray sNSSAIList = pLMNInfoList.getJSONObject(j).getJSONArray("sNSSAIList"); - for(int k=0;k<sNSSAIList.length();k++) { - Map<String,Object> map = new HashMap<String,Object>(); - JSONArray configDataArray = sNSSAIList.getJSONObject(k).getJSONArray("configData"); - for(int l=0;l<configDataArray.length();l++) { - JSONObject configData = configDataArray.getJSONObject(l); - map.put((String) configData.get("configParameter"), configData.get("configValue")); - } - responseMap.put(nearRTTICid, map); - } - } - } - }catch (Exception e) { - log.info("CPS fetches current configuration of RIC: " + e); - } - return responseMap; - } - - /** - * Fetches all the network functions of an S-NSSAI from CPS - */ - public List<String> fetchNetworkFunctionsOfSnssai(String snssai) { - List<String> responseList=new ArrayList<>(); - String reqUrl=cpsBaseUrl+"/get-gnbdufunction-by-snssai"; - log.info("fetching network functions of snssai from Cps: {s-NSSAI: "+snssai+"}"); - String requestBody = "{\"inputParameters\": {\"sNssai\":"+JSONObject.quote(snssai)+"}}"; - try { - String response=restclient.sendPostRequest(reqUrl,requestBody,new ParameterizedTypeReference<String>() {}).getBody(); - JSONArray networkFunctionJsonArry = new JSONArray(response); - for (int i=0;i<networkFunctionJsonArry.length();i++) { - JSONObject networkFunctionJson = networkFunctionJsonArry.getJSONObject(i); - responseList.add(networkFunctionJson.getJSONObject("attributes").optString("gNBDUId")); - } - } - catch (Exception e) { - log.info("Fetch network functions of S-NSSAI from CPS" + e); - } - return responseList; - } - - /** - * Fetches the RICS of an S-NSSAI from CPS - */ - public Map<String, List<String>> fetchRICsOfSnssai(String snssai) { - Map<String,List<String>> responseMap=new HashMap<>(); - String reqUrl=cpsBaseUrl + "/get-nrcelldu-by-snssai"; - log.info("fetching RIC of s-NSSAI from Cps: {s-NSSAI: "+snssai+"}"); - String requestBody = "{\"inputParameters\": {\"sNssai\":"+JSONObject.quote(snssai)+"}}"; - try { - String response=restclient.sendPostRequest(reqUrl,requestBody,new ParameterizedTypeReference<String>() {}).getBody(); - JSONArray sliceArray = new JSONArray(response); - for (int i=0;i<sliceArray.length();i++) { - String nearRTTICid = sliceArray.getJSONObject(i).optString("idNearRTRIC"); - JSONArray GNBDUFunctionArray = sliceArray.getJSONObject(i).getJSONArray("GNBDUFunction"); - for (int j=0;j<GNBDUFunctionArray.length();j++){ - JSONArray NRCellDUArray = GNBDUFunctionArray.getJSONObject(j).getJSONArray("NRCellDU"); - List<String> cellslist=new ArrayList<>(); - for(int k=0;k<NRCellDUArray.length();k++) { - cellslist.add(NRCellDUArray.getJSONObject(k).getJSONObject("attributes").optString("cellLocalId")); - } - responseMap.put(nearRTTICid,cellslist); - } - } - }catch (Exception e) { - log.info("Fetch RICS of S-NSSAI from CPS" + e); - } - return responseMap; - } -} - diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/IConfigDbService.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/IConfigDbService.java index 2b92b091..f34fcc9a 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/IConfigDbService.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/IConfigDbService.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,16 +25,17 @@ import java.util.List; import java.util.Map; /** - * + * * Interface for config db service * */ public interface IConfigDbService { - public Map<String, List<String>> fetchRICsOfSnssai(String snssai); - public List<String> fetchNetworkFunctionsOfSnssai(String snssai); - public Map<String, Integer> fetchCurrentConfigurationOfSlice(String snssai); - public Map<String, Map<String,Object>> fetchCurrentConfigurationOfRIC(String snssai); - public Map<String ,String> fetchServiceDetails(String snssai); + public Map<String, List<String>> fetchRICsOfSnssai(String snssai); + public List<String> fetchNetworkFunctionsOfSnssai(String snssai); + public Map<String, Integer> fetchCurrentConfigurationOfSlice(String snssai); + public Map<String, Map<String,Object>> fetchCurrentConfigurationOfRIC(String snssai); + public Map<String ,String> fetchServiceDetails(String snssai); + public Map<String, List<String>> fetchCUCPCellsOfSnssai(String snssai); } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbs.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbs.java index fbb47e32..e69d45f2 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbs.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbs.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,33 +83,36 @@ public class ConfigFetchFromCbs implements Runnable { // Create the client and use it to get the configuration final CbsRequest request = CbsRequests.getAll(diagnosticContext); return CbsClientFactory.createCbsClient(cbsClientConfiguration) - .flatMapMany(cbsClient -> cbsClient.updates(request, initialDelay, period)).subscribe(jsonObject -> { - log.info("configuration and policy from CBS {}", jsonObject); - JsonObject config = jsonObject.getAsJsonObject("config"); - Duration newPeriod = Duration.ofSeconds(config.get("cbsPollingInterval").getAsInt()); - if (!newPeriod.equals(period)) { - interval = newPeriod; - synchronized (this) { - this.notifyAll(); - } - + .flatMapMany(cbsClient -> cbsClient.updates(request, initialDelay, period)).subscribe(jsonObject -> { + log.info("configuration and policy from CBS {}", jsonObject); + JsonObject config = jsonObject.getAsJsonObject("config"); + Duration newPeriod = Duration.ofSeconds(config.get("cbsPollingInterval").getAsInt()); + if (!newPeriod.equals(period)) { + interval = newPeriod; + synchronized (this) { + this.notifyAll(); } - Configuration.getInstance().updateConfigurationFromJsonObject(config); - - Type mapType = new TypeToken<Map<String, Object>>() { - }.getType(); - if (jsonObject.getAsJsonObject("policies") != null) { + } + Configuration.getInstance().updateConfigurationFromJsonObject(config); + + Type mapType = new TypeToken<Map<String, Object>>() { + }.getType(); + if (jsonObject.getAsJsonObject("policies") != null) { + log.info("Policy file exist"); + if(jsonObject.getAsJsonObject("policies").getAsJsonArray("items").size() == 0) { + log.error("No policy in policy drool pdp engine, nothing to update."); + } else { JsonObject policyJson = jsonObject.getAsJsonObject("policies").getAsJsonArray("items").get(0) - .getAsJsonObject().getAsJsonObject("config"); + .getAsJsonObject().getAsJsonObject("config"); Map<String, Object> policy = new Gson().fromJson(policyJson, mapType); configPolicy.setConfig(policy); log.info("Config policy {}", configPolicy); } - }, throwable -> log.warn("Ooops", throwable)); + } + }, throwable -> log.warn("Ooops", throwable)); } - @Override public void run() { Boolean done = false; diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/SliceConfiguraton.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/SliceConfiguraton.java new file mode 100644 index 00000000..412d8d2c --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/controller/SliceConfiguraton.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.controller; + +import org.onap.slice.analysis.ms.models.SliceConfigRequest; +import org.onap.slice.analysis.ms.models.SliceConfigResponse; +import org.onap.slice.analysis.ms.service.SliceUtilization; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * This Controller provides slice configuration details + */ +@RestController +public class SliceConfiguraton { + + @Autowired + SliceUtilization sliceUtilization; + + /** + * This method provides the slice utilization details for requested slices. + * + * @param sliceConfigRequest contains sliceInstanceId + * @return sliceConfigResponse contains slice configuration details + */ + @GetMapping(value = "/api/v1/slices-config") + public ResponseEntity<SliceConfigResponse> sliceConfigRequest(@RequestBody SliceConfigRequest sliceConfigRequest) { + try { + SliceConfigResponse sliceConfigResponse = sliceUtilization.getSliceUtilizationData(sliceConfigRequest); + return new ResponseEntity<SliceConfigResponse>(sliceConfigResponse, HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); + } + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/cps/CpsInterface.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/cps/CpsInterface.java new file mode 100644 index 00000000..d6a187cb --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/cps/CpsInterface.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2021-2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.cps; + +import java.util.List; +import java.util.Map; + +/** + * + * Interface for CPS + * + */ +public interface CpsInterface { + + public Map<String, List<String>> fetchRICsOfSnssai(String snssai); + + public List<String> fetchNetworkFunctionsOfSnssai(String snssai); + + public Map<String, Map<String, Object>> fetchCurrentConfigurationOfRIC(String snssai); + + public Map<String, List<String>> fetchnrCellCUsOfSnssai(String snssai); + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/cps/CpsService.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/cps/CpsService.java new file mode 100644 index 00000000..a9562e58 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/cps/CpsService.java @@ -0,0 +1,182 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2021-2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.cps; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.restclients.CpsRestClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +/** + * + * Service for CPS interfaces + * + */ +@Service +public class CpsService implements CpsInterface { + + private static Logger log = LoggerFactory.getLogger(CpsService.class); + + @Autowired + CpsRestClient restclient; + private static String cpsBaseUrl = Configuration.getInstance().getCpsUrl(); + + /** + * Fetches the current configuration of RIC from CPS + */ + public Map<String, Map<String, Object>> fetchCurrentConfigurationOfRIC(String snssai) { + Map<String, Map<String, Object>> responseMap = new HashMap<String, Map<String, Object>>(); + String reqUrl = cpsBaseUrl + "/get-nearrtric-config"; + log.info("fetching current configuration of RIC from Cps: {s-NSSAI: " + snssai + "}"); + log.info("reqUrl {}", reqUrl); + String requestBody = "{\"inputParameters\": {\"sNssai\":" + JSONObject.quote(snssai) + "}}"; + log.info("requestBody {}", requestBody); + try { + String response = restclient + .sendPostRequest(reqUrl, requestBody, new ParameterizedTypeReference<String>() {}).getBody(); + JSONArray sliceArray = new JSONArray(response); + for (int i = 0; i < sliceArray.length(); i++) { + String nearRTTICid = sliceArray.getJSONObject(i).optString("idNearRTRIC"); + JSONArray pLMNInfoList = + sliceArray.getJSONObject(i).getJSONObject("attributes").getJSONArray("pLMNInfoList"); + for (int j = 0; j < pLMNInfoList.length(); j++) { + JSONArray sNSSAIList = pLMNInfoList.getJSONObject(j).getJSONArray("sNSSAIList"); + for (int k = 0; k < sNSSAIList.length(); k++) { + Map<String, Object> map = new HashMap<String, Object>(); + JSONArray configDataArray = sNSSAIList.getJSONObject(k).getJSONArray("configData"); + for (int l = 0; l < configDataArray.length(); l++) { + JSONObject configData = configDataArray.getJSONObject(l); + map.put((String) configData.get("configParameter"), configData.get("configValue")); + } + responseMap.put(nearRTTICid, map); + } + } + } + } catch (Exception e) { + log.info("CPS fetches current configuration of RIC: " + e); + } + return responseMap; + } + + /** + * Fetches all the network functions of an S-NSSAI from CPS + */ + public List<String> fetchNetworkFunctionsOfSnssai(String snssai) { + List<String> responseList = new ArrayList<>(); + String reqUrl = cpsBaseUrl + "/get-gnbdufunction-by-snssai"; + log.info("fetching network functions of snssai from Cps: {s-NSSAI: " + snssai + "}"); + log.info("reqUrl {}", reqUrl); + String requestBody = "{\"inputParameters\": {\"sNssai\":" + JSONObject.quote(snssai) + "}}"; + log.info("requestBody {}", requestBody); + try { + String response = restclient + .sendPostRequest(reqUrl, requestBody, new ParameterizedTypeReference<String>() {}).getBody(); + JSONArray networkFunctionJsonArry = new JSONArray(response); + for (int i = 0; i < networkFunctionJsonArry.length(); i++) { + JSONObject networkFunctionJson = networkFunctionJsonArry.getJSONObject(i); + responseList.add(networkFunctionJson.getJSONObject("attributes").optString("gNBDUId")); + } + } catch (Exception e) { + log.info("Fetch network functions of S-NSSAI from CPS" + e); + } + return responseList; + } + + /** + * Fetches the RICS of an S-NSSAI from CPS + */ + public Map<String, List<String>> fetchRICsOfSnssai(String snssai) { + Map<String, List<String>> responseMap = new HashMap<>(); + String reqUrl = cpsBaseUrl + "/get-nrcelldu-by-snssai"; + log.info("fetching RIC of s-NSSAI from Cps: {s-NSSAI: " + snssai + "}"); + log.info("reqUrl {}", reqUrl); + String requestBody = "{\"inputParameters\": {\"sNssai\":" + JSONObject.quote(snssai) + "}}"; + log.info("requestBody {}", requestBody); + try { + String response = restclient + .sendPostRequest(reqUrl, requestBody, new ParameterizedTypeReference<String>() {}).getBody(); + JSONArray sliceArray = new JSONArray(response); + for (int i = 0; i < sliceArray.length(); i++) { + String nearRTTICid = sliceArray.getJSONObject(i).optString("idNearRTRIC"); + JSONArray GNBDUFunctionArray = sliceArray.getJSONObject(i).getJSONArray("GNBDUFunction"); + for (int j = 0; j < GNBDUFunctionArray.length(); j++) { + JSONArray NRCellDUArray = GNBDUFunctionArray.getJSONObject(j).getJSONArray("NRCellDU"); + List<String> cellslist = new ArrayList<>(); + for (int k = 0; k < NRCellDUArray.length(); k++) { + cellslist.add( + NRCellDUArray.getJSONObject(k).getJSONObject("attributes").optString("cellLocalId")); + } + responseMap.put(nearRTTICid, cellslist); + } + } + } catch (Exception e) { + log.info("Fetch RICS of S-NSSAI from CPS" + e); + } + log.info("responseMap: {}", responseMap); + return responseMap; + } + + /** + * Fetches the NRCellCUs of an S-NSSAI from CPS + */ + public Map<String, List<String>> fetchnrCellCUsOfSnssai(String snssai) { + Map<String, List<String>> responseMap = new HashMap<>(); + String reqUrl = cpsBaseUrl + "/get-nearrtric-config"; + log.info("fetching NrCellCUs of s-NSSAI from Cps: {s-NSSAI: " + snssai + "}"); + log.info("reqUrl {}", reqUrl); + String requestBody = "{\"inputParameters\": {\"sNssai\":" + JSONObject.quote(snssai) + "}}"; + log.info("requestBody {}", requestBody); + try { + String response = restclient + .sendPostRequest(reqUrl, requestBody, new ParameterizedTypeReference<String>() {}).getBody(); + JSONArray sliceArray = new JSONArray(response); + for (int i = 0; i < sliceArray.length(); i++) { + String nearRTTICid = sliceArray.getJSONObject(i).optString("idNearRTRIC"); + JSONArray GNBCUCPFunctionArray = sliceArray.getJSONObject(i).getJSONArray("GNBCUCPFunction"); + for (int j = 0; j < GNBCUCPFunctionArray.length(); j++) { + JSONArray NRCellCUArray = GNBCUCPFunctionArray.getJSONObject(j).getJSONArray("NRCellCU"); + List<String> cellslist = new ArrayList<>(); + for (int k = 0; k < NRCellCUArray.length(); k++) { + cellslist.add( + NRCellCUArray.getJSONObject(k).getJSONObject("attributes").optString("cellLocalId")); + } + responseMap.put(nearRTTICid, cellslist); + } + } + } catch (Exception e) { + log.info("Exception: {}", e); + } + log.info("responseMap: {}", responseMap); + return responseMap; + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/AaiEventNotificationCallback.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/AaiEventNotificationCallback.java new file mode 100644 index 00000000..292cf6ae --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/AaiEventNotificationCallback.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.dmaap; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.service.ccvpn.BandwidthEvaluator; +import org.onap.slice.analysis.ms.service.ccvpn.Event; +import org.onap.slice.analysis.ms.service.ccvpn.SimpleEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +/** + * Handles AAI-EVENT from dmaap + */ +@Component +public class AaiEventNotificationCallback implements NotificationCallback { + + private static Logger logger = LoggerFactory.getLogger(AaiEventNotificationCallback.class); + private static final String EVENT_HEADER = "event-header"; + private static final String ACTION = "action"; + private static final String ENTITY_TYPE = "entity-type"; + private static final String SOURCE_NAME = "source-name"; + private static final String ENTITY = "entity"; + private final JsonParser parser = new JsonParser(); + private Configuration configuration; + private String aaiNotifTargetAction; + private String aaiNotifTargetSource; + private String aaiNotifTargetEntity; + + @Autowired + BandwidthEvaluator bandwidthEvaluator; + + @PostConstruct + public void init(){ + configuration = Configuration.getInstance(); + aaiNotifTargetAction = configuration.getAaiNotifTargetAction(); + aaiNotifTargetSource = configuration.getAaiNotifTargetSource(); + aaiNotifTargetEntity = configuration.getAaiNotifTargetEntity(); + } + + @Override + public void activateCallBack(String msg) { + handleNotification(msg); + } + + private void handleNotification(String msg) { + JsonElement jsonElement = parser.parse(msg); + if (jsonElement.isJsonObject()){ + //handle a single AAI_EVENT + logger.debug("Handle a single aai-event"); + handleMsgJsonObject(jsonElement.getAsJsonObject()); + } else if (jsonElement.isJsonArray()){ + //handle a series of AAI_EVENT + logger.debug("Handle a series of aai-event"); + JsonArray jsonArray = jsonElement.getAsJsonArray(); + for (int i=0,e=jsonArray.size(); i<e; i++){ + if (jsonArray.get(i).isJsonPrimitive()){ + // Deal with a batch of event message + handleNotification(jsonArray.get(i).getAsString()); + } else { + handleMsgJsonObject(jsonArray.get(i).getAsJsonObject()); + } + + } + } + } + + private void handleMsgJsonObject(JsonObject jsonObject){ + JsonObject header = jsonObject.get(EVENT_HEADER).getAsJsonObject(); + if (!header.has(ACTION) || !isValid(header, ACTION, aaiNotifTargetAction)){ + return; + } + if (!header.has(ENTITY_TYPE) || !header.get(ENTITY_TYPE).getAsString().equals(aaiNotifTargetEntity)){ + return; + } + if (!header.has(SOURCE_NAME) || !header.get(SOURCE_NAME).getAsString().equals(aaiNotifTargetSource)){ + return; + } + JsonObject entity = jsonObject.get(ENTITY).getAsJsonObject(); + JsonObject body = getNestedJsonObject(entity, aaiNotifTargetEntity); + logger.info("AAI-EVENT entity object {}", body); + if (body == null){ + return; + } + Event event = new SimpleEvent<>(SimpleEvent.Type.ONDEMAND_CHECK, body); + bandwidthEvaluator.post(event); + } + + private JsonObject getNestedJsonObject(JsonObject obj, String target){ + for (String k: obj.keySet()){ + if (k.equals(target)){ + //Found it; + return obj.getAsJsonArray(k).get(0).getAsJsonObject(); + } + if (obj.get(k).isJsonObject()) { + return getNestedJsonObject(obj.getAsJsonObject(k), target); + } else if (obj.get(k).isJsonArray()){ + JsonElement tmp = obj.getAsJsonArray(k).get(0); + if (tmp.isJsonObject()){ + return getNestedJsonObject(tmp.getAsJsonObject(), target); + } + } + } + return null; + } + + // make sure dmaap mesg header is expected type and valid; + private boolean isValid(JsonObject header, String targetKey, String allowed){ + boolean valid = false; + String[] allowedArr = allowed.split("\\|"); + String targetVal= header.get(targetKey).getAsString(); + for (String al: allowedArr){ + valid |= targetVal.equals(al); + } + return valid; + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/DmaapClient.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/DmaapClient.java index 6e0f4f27..6e4dbe18 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/DmaapClient.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/DmaapClient.java @@ -3,6 +3,8 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 CTC, Inc. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,37 +30,41 @@ import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; +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.slice.analysis.ms.models.Configuration; -import org.onap.slice.analysis.ms.utils.DmaapUtils; +import org.onap.slice.analysis.ms.utils.DcaeDmaapUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.att.nsa.cambria.client.CambriaConsumer; - /** - * This class initializes and starts the dmaap client + * This class initializes and starts the dmaap client * to listen on application required dmaap events */ @Component public class DmaapClient { + private static final String AAI_SUBSCRIBER = "aai_subscriber"; private Configuration configuration; private static Logger log = LoggerFactory.getLogger(DmaapClient.class); - private DmaapUtils dmaapUtils; - @Autowired private IntelligentSlicingCallback intelligentSlicingCallback; + @Autowired + private VesNotificationCallback vesNotificationCallback; + + @Autowired + private AaiEventNotificationCallback aaiEventNotificationCallback; + /** * init dmaap client. */ @PostConstruct public void initClient() { log.debug("initializing client"); - dmaapUtils = new DmaapUtils(); configuration = Configuration.getInstance(); if (log.isDebugEnabled()) { log.debug(configuration.toString()); @@ -74,54 +80,72 @@ public class DmaapClient { public synchronized void startClient() { Map<String, Object> streamSubscribes = configuration.getStreamsSubscribes(); - + String pmTopicUrl = ((Map<String, String>) ((Map<String, Object>) streamSubscribes .get("performance_management_topic")).get("dmaap_info")).get("topic_url"); - String[] pmTopicSplit = pmTopicUrl.split("\\/"); - String pmTopic = pmTopicSplit[pmTopicSplit.length - 1]; - log.debug("pm topic : {}", pmTopic); - + String policyResponseTopicUrl = ((Map<String, String>) ((Map<String, Object>) streamSubscribes .get("dcae_cl_response_topic")).get("dmaap_info")).get("topic_url"); - String[] policyResponseTopicUrlSplit = policyResponseTopicUrl.split("\\/"); - String policyResponseTopic = policyResponseTopicUrlSplit[policyResponseTopicUrlSplit.length - 1]; - log.debug("policyResponse Topic : {}", policyResponseTopic); - + String intelligentSlicingTopicUrl = ((Map<String, String>) ((Map<String, Object>) streamSubscribes .get("intelligent_slicing_topic")).get("dmaap_info")).get("topic_url"); - String[] intelligentSlicingTopicSplit = intelligentSlicingTopicUrl.split("\\/"); - String intelligentSlicingTopic = intelligentSlicingTopicSplit[intelligentSlicingTopicSplit.length - 1]; - log.debug("intelligent slicing topic : {}", pmTopic); - - CambriaConsumer pmNotifCambriaConsumer = dmaapUtils.buildConsumer(configuration, pmTopic); - CambriaConsumer policyResponseCambriaConsumer = dmaapUtils.buildConsumer(configuration, policyResponseTopic); - CambriaConsumer intelligentSlicingCambriaConsumer = dmaapUtils.buildConsumer(configuration, intelligentSlicingTopic); + + // Parsing ccvpn notification topic + String ccvpnNotiTopicUrl = ((Map<String, String>) ((Map<String, Object>) streamSubscribes + .get("ves_ccvpn_notification_topic")).get("dmaap_info")).get("topic_url"); + + MessageRouterSubscriber pmNotifSubscriber = DcaeDmaapUtil.buildSubscriber(); + MessageRouterSubscribeRequest pmNotifReqest = DcaeDmaapUtil.buildSubscriberRequest("performance_management_topic", pmTopicUrl); + + MessageRouterSubscriber policyNotifSubscriber = DcaeDmaapUtil.buildSubscriber(); + MessageRouterSubscribeRequest policyNotifReqest = DcaeDmaapUtil.buildSubscriberRequest("dcae_cl_response_topic", policyResponseTopicUrl); + + MessageRouterSubscriber intelligentSlicingSubscriber = DcaeDmaapUtil.buildSubscriber(); + MessageRouterSubscribeRequest intelligentSlicingReqest = DcaeDmaapUtil.buildSubscriberRequest("intelligent_slicing_topic", intelligentSlicingTopicUrl); + + MessageRouterSubscriber ccvpnNotiSubscriber = DcaeDmaapUtil.buildSubscriber(); + MessageRouterSubscribeRequest ccvpnNotiReqest = DcaeDmaapUtil.buildSubscriberRequest("ves_ccvpn_notification_topic", ccvpnNotiTopicUrl); ScheduledExecutorService executorPool; // create notification consumers for PM - NotificationConsumer pmNotificationConsumer = new NotificationConsumer(pmNotifCambriaConsumer, + NotificationConsumer pmNotificationConsumer = new NotificationConsumer(pmNotifSubscriber, pmNotifReqest, new PmNotificationCallback()); // start pm notification consumer threads executorPool = Executors.newScheduledThreadPool(10); executorPool.scheduleAtFixedRate(pmNotificationConsumer, 0, configuration.getPollingInterval(), TimeUnit.SECONDS); - + // create notification consumers for Policy - NotificationConsumer policyNotificationConsumer = new NotificationConsumer(policyResponseCambriaConsumer, - new PolicyNotificationCallback()); - // start policy notification consumer threads - executorPool = Executors.newScheduledThreadPool(10); - executorPool.scheduleAtFixedRate(policyNotificationConsumer, 0, configuration.getPollingInterval(), - TimeUnit.SECONDS); - - // create notification consumers for ML MS - NotificationConsumer intelligentSlicingConsumer = new NotificationConsumer(intelligentSlicingCambriaConsumer, - intelligentSlicingCallback); - // start intelligent Slicing notification consumer threads - executorPool = Executors.newScheduledThreadPool(10); - executorPool.scheduleAtFixedRate(intelligentSlicingConsumer, 0, configuration.getPollingInterval(), - TimeUnit.SECONDS); + NotificationConsumer policyNotificationConsumer = new NotificationConsumer(policyNotifSubscriber, policyNotifReqest, + new PolicyNotificationCallback()); + // start policy notification consumer threads + executorPool = Executors.newScheduledThreadPool(10); + executorPool.scheduleAtFixedRate(policyNotificationConsumer, 0, configuration.getPollingInterval(), + TimeUnit.SECONDS); + + // create notification consumers for ML MS + NotificationConsumer intelligentSlicingConsumer = new NotificationConsumer(intelligentSlicingSubscriber, intelligentSlicingReqest, + intelligentSlicingCallback); + // start intelligent Slicing notification consumer threads + executorPool = Executors.newScheduledThreadPool(10); + executorPool.scheduleAtFixedRate(intelligentSlicingConsumer, 0, configuration.getPollingInterval(), + TimeUnit.SECONDS); + + // create notification consumers for ccvpn close-loop PM + NotificationConsumer ccvpnNotiConsumer = new NotificationConsumer(ccvpnNotiSubscriber, ccvpnNotiReqest, + vesNotificationCallback); + executorPool = Executors.newScheduledThreadPool(1); + executorPool.scheduleWithFixedDelay(ccvpnNotiConsumer, 0, configuration.getVesNotifPollingInterval(), + TimeUnit.SECONDS); + + // start AAI-EVENT dmaap topic monitor + MRTopicMonitor mrTopicMonitor = getMRTopicMonitor(); + mrTopicMonitor.start(); + } + + public MRTopicMonitor getMRTopicMonitor() { + return new MRTopicMonitor(AAI_SUBSCRIBER, aaiEventNotificationCallback); } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/MRTopicMonitor.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/MRTopicMonitor.java new file mode 100644 index 00000000..f3330dc3 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/MRTopicMonitor.java @@ -0,0 +1,236 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 CTC, Inc. + * ================================================================================ + * 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.slice.analysis.ms.dmaap; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.vavr.collection.List; +import lombok.Getter; +import lombok.NonNull; +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.onap.slice.analysis.ms.models.Configuration; + +import org.onap.slice.analysis.ms.utils.DcaeDmaapUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * This is a Dmaap message-router topic monitor. + * It takes advantage of AT&T's dmaap-client's long-polling implementation, this monitor constantly fetch/refetch target msg topic. + * So that new msg can be notified almost immediately. This is the major different from previous implementation. + */ +public class MRTopicMonitor implements Runnable { + + private final String name; + private volatile boolean running = false; + private Configuration configuration; + private static Logger logger = LoggerFactory.getLogger(MRTopicMonitor.class); + private static int DEFAULT_TIMEOUT_MS_FETCH = 15000; + private MRConsumerWrapper consumerWrapper; + private NotificationCallback callback; + + /** + * Constructor + * @param name name of topic subscriber in config + * @param callback callbackfunction for received message + */ + public MRTopicMonitor(String name, NotificationCallback callback){ + this.name = name; + this.callback = callback; + } + + /** + * Start the monitoring thread + */ + public void start(){ + logger.info("Starting Dmaap Bus Monitor"); + configuration = Configuration.getInstance(); + + Map<String, Object> streamSubscribes = configuration.getStreamsSubscribes(); + Map<String, Object> topicParamsJson = (Map<String, Object>) streamSubscribes.get(name); + JsonObject jsonObject = (new Gson()).toJsonTree(topicParamsJson).getAsJsonObject(); + consumerWrapper = buildConsumerWrapper(jsonObject); + running = true; + Executor executor = Executors.newSingleThreadExecutor(); + executor.execute(this); + } + + /** + * Main loop that keep fetching and processing + */ + @Override + public void run(){ + while (running){ + try { + logger.debug("Topic: {} getting new msg...", name); + List<JsonElement> dmaapMsgs = consumerWrapper.fetch(); + for (JsonElement msg : dmaapMsgs){ + logger.debug("Received message: {}" + + "\r\n and processing start", msg); + process(msg.toString()); + } + } catch (IOException | RuntimeException e){ + logger.error("fetchMessage encountered error: {}", e); + } + } + logger.info("{}: exiting thread", this); + } + + /** + * Stop the monitor + */ + public void stop(){ + logger.info("{}: exiting", this); + running = false; + this.consumerWrapper.close(); + this.consumerWrapper = null; + } + + private void process(String msg) { + try { + callback.activateCallBack(msg); + } catch (Exception e){ + logger.error("process message encountered error: {}", e); + } + } + + private List<JsonElement> fetch() throws IOException { + return this.consumerWrapper.fetch(); + } + + private MRConsumerWrapper buildConsumerWrapper(@NonNull JsonObject topicParamsJson ) + throws IllegalArgumentException { + MRTopicParams topicParams = MRTopicParams.builder().buildFromConfigJson(topicParamsJson).build(); + return new MRConsumerWrapper(topicParams); + } + + /** + * Wrapper class of DmaapClient (package org.onap.dmaap.mr.client) + * A polling fashion dmaap consumer, whose #fetch() sleep a certain time when connection fails, otherwise keep retryiny. + * It supports both https and http protocols. + */ + private class MRConsumerWrapper { + /** + * Name of the "protocol" property. + */ + protected static final String PROTOCOL_PROP = "Protocol"; + /** + * Fetch timeout. + */ + protected int fetchTimeout; + + /** + * Time to sleep on a fetch failure. + */ + @Getter + private final int sleepTime; + + /** + * Counted down when {@link #close()} is invoked. + */ + private final CountDownLatch closeCondition = new CountDownLatch(1); + + protected MessageRouterSubscriber subscriber; + protected MessageRouterSubscribeRequest request; + + /** + * Constructs the object. + * + * @param MRTopicParams parameters for the bus topic + */ + protected MRConsumerWrapper(MRTopicParams MRTopicParams) { + this.fetchTimeout = MRTopicParams.getFetchTimeout(); + + if (this.fetchTimeout <= 0) { + this.sleepTime = DEFAULT_TIMEOUT_MS_FETCH; + } else { + // don't sleep too long, even if fetch timeout is large + this.sleepTime = Math.min(this.fetchTimeout, DEFAULT_TIMEOUT_MS_FETCH); + } + + if (MRTopicParams.isTopicInvalid()) { + throw new IllegalArgumentException("No topic for DMaaP"); + } + + if (MRTopicParams.isServersInvalid()) { + throw new IllegalArgumentException("Must provide at least one host for HTTP AAF"); + } + + try{ + this.subscriber = DcaeDmaapUtil.buildSubscriber(); + this.request = DcaeDmaapUtil.buildSubscriberRequest("aai_subscriber", MRTopicParams.getTopic()); + + } catch (Exception e) { + throw new IllegalArgumentException("Illegal MrConsumer parameters"); + } + + } + + /** + * Try fetch new message. But backoff for some sleepTime when connection fails. + * @return + * @throws IOException + */ + public List<JsonElement> fetch() throws IOException { + Mono<MessageRouterSubscribeResponse> responses = this.subscriber.get(this.request); + MessageRouterSubscribeResponse resp = responses.block(); + List<JsonElement> list = resp.items(); + return list; + + } + + /** + * Causes the thread to sleep; invoked after fetch() fails. If the consumer is closed, + * or the thread is interrupted, then this will return immediately. + */ + protected void sleepAfterFetchFailure() { + try { + logger.info("{}: backoff for {}ms", this, sleepTime); + if (this.closeCondition.await(this.sleepTime, TimeUnit.MILLISECONDS)) { + logger.info("{}: closed while handling fetch error", this); + } + + } catch (InterruptedException e) { + logger.warn("{}: interrupted while handling fetch error", this, e); + Thread.currentThread().interrupt(); + } + } + + /** + * Close the dmaap client and this thread + */ + public void close() { + this.closeCondition.countDown(); + } + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/MRTopicParams.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/MRTopicParams.java new file mode 100644 index 00000000..26f16baf --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/MRTopicParams.java @@ -0,0 +1,376 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2018-2019, 2021 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019 Nordix Foundation. + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 CTC, Inc. + * ================================================================================ + * 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.slice.analysis.ms.dmaap; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Partially copied from Onap Policy + * policy/common/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicParams.java + * Modified to fit this project. + * Member variables of this Params class are as follows. + * + * <p>servers DMaaP servers + * topic DMaaP Topic to be monitored + * apiKey DMaaP API Key (optional) + * apiSecret DMaaP API Secret (optional) + * consumerGroup DMaaP Reader Consumer Group + * consumerInstance DMaaP Reader Instance + * fetchTimeout DMaaP fetch timeout + * fetchLimit DMaaP fetch limit + * environment DME2 Environment + * aftEnvironment DME2 AFT Environment + * partner DME2 Partner + * latitude DME2 Latitude + * longitude DME2 Longitude + * additionalProps Additional properties to pass to DME2 + * useHttps does connection use HTTPS? + * allowSelfSignedCerts are self-signed certificates allow + */ +@Getter +@Setter +public class MRTopicParams { + + private int port; + private List<String> servers; + private Map<String, String> additionalProps; + private String topic; + private String effectiveTopic; + private String apiKey; + private String apiSecret; + private String consumerGroup; + private String consumerInstance; + private int fetchTimeout; + private int fetchLimit; + private boolean useHttps; + private boolean allowSelfSignedCerts; + private boolean managed; + + private String userName; + private String password; + private String environment; + private String aftEnvironment; + private String partner; + private String latitude; + private String longitude; + private String partitionId; + private String clientName; + private String hostname; + private String basePath; + @Getter + private String serializationProvider; + + public static TopicParamsBuilder builder() { + return new TopicParamsBuilder(); + } + + /** + * Methods to Check if the property is INVALID. + */ + + public boolean isEnvironmentInvalid() { + return StringUtils.isBlank(environment); + } + + public boolean isAftEnvironmentInvalid() { + return StringUtils.isBlank(aftEnvironment); + } + + public boolean isLatitudeInvalid() { + return StringUtils.isBlank(latitude); + } + + public boolean isLongitudeInvalid() { + return StringUtils.isBlank(longitude); + } + + public boolean isConsumerInstanceInvalid() { + return StringUtils.isBlank(consumerInstance); + } + + public boolean isConsumerGroupInvalid() { + return StringUtils.isBlank(consumerGroup); + } + + public boolean isClientNameInvalid() { + return StringUtils.isBlank(clientName); + } + + public boolean isPartnerInvalid() { + return StringUtils.isBlank(partner); + } + + public boolean isServersInvalid() { + return (servers == null || servers.isEmpty() + || (servers.size() == 1 && ("".equals(servers.get(0))))); + } + + public boolean isTopicInvalid() { + return StringUtils.isBlank(topic); + } + + public boolean isPartitionIdInvalid() { + return StringUtils.isBlank(partitionId); + } + + public boolean isHostnameInvalid() { + return StringUtils.isBlank(hostname); + } + + public boolean isPortInvalid() { + return (port <= 0 || port >= 65535); + } + + /** + * Methods to Check if the property is Valid. + */ + + public boolean isApiKeyValid() { + return StringUtils.isNotBlank(apiKey); + } + + public boolean isApiSecretValid() { + return StringUtils.isNotBlank(apiSecret); + } + + public boolean isUserNameValid() { + return StringUtils.isNotBlank(userName); + } + + public boolean isPasswordValid() { + return StringUtils.isNotBlank(password); + } + + public boolean isAdditionalPropsValid() { + return additionalProps != null; + } + + @NoArgsConstructor(access = AccessLevel.PRIVATE) + public static class TopicParamsBuilder { + + final MRTopicParams params = new MRTopicParams(); + + public TopicParamsBuilder servers(List<String> servers) { + this.params.servers = servers; + return this; + } + + public TopicParamsBuilder topic(String topic) { + this.params.topic = topic; + return this; + } + + public TopicParamsBuilder effectiveTopic(String effectiveTopic) { + this.params.effectiveTopic = effectiveTopic; + return this; + } + + public TopicParamsBuilder apiKey(String apiKey) { + this.params.apiKey = apiKey; + return this; + } + + public TopicParamsBuilder apiSecret(String apiSecret) { + this.params.apiSecret = apiSecret; + return this; + } + + public TopicParamsBuilder consumerGroup(String consumerGroup) { + this.params.consumerGroup = consumerGroup; + return this; + } + + public TopicParamsBuilder consumerInstance(String consumerInstance) { + this.params.consumerInstance = consumerInstance; + return this; + } + + public TopicParamsBuilder fetchTimeout(int fetchTimeout) { + this.params.fetchTimeout = fetchTimeout; + return this; + } + + public TopicParamsBuilder fetchLimit(int fetchLimit) { + this.params.fetchLimit = fetchLimit; + return this; + } + + public TopicParamsBuilder useHttps(boolean useHttps) { + this.params.useHttps = useHttps; + return this; + } + + public TopicParamsBuilder allowSelfSignedCerts(boolean allowSelfSignedCerts) { + this.params.allowSelfSignedCerts = allowSelfSignedCerts; + return this; + } + + public TopicParamsBuilder userName(String userName) { + this.params.userName = userName; + return this; + } + + public TopicParamsBuilder password(String password) { + this.params.password = password; + return this; + } + + public TopicParamsBuilder environment(String environment) { + this.params.environment = environment; + return this; + } + + public TopicParamsBuilder aftEnvironment(String aftEnvironment) { + this.params.aftEnvironment = aftEnvironment; + return this; + } + + public TopicParamsBuilder partner(String partner) { + this.params.partner = partner; + return this; + } + + public TopicParamsBuilder latitude(String latitude) { + this.params.latitude = latitude; + return this; + } + + public TopicParamsBuilder longitude(String longitude) { + this.params.longitude = longitude; + return this; + } + + public TopicParamsBuilder additionalProps(Map<String, String> additionalProps) { + this.params.additionalProps = additionalProps; + return this; + } + + public TopicParamsBuilder partitionId(String partitionId) { + this.params.partitionId = partitionId; + return this; + } + + public MRTopicParams build() { + return params; + } + + public TopicParamsBuilder buildFromConfigJson(JsonObject jsonObject) { + String consumerGroup = null; + String consumerInstance = null; + String aafUsername = null; + String aafPassword = null; + List<String> servers = new ArrayList<>(); + String topic = null; + boolean useHttps = false; + int fetchTimeout = -1; + int fetchLimit = -1; + + if (jsonObject.has("consumer_group") && !jsonObject.get("consumer_group").isJsonNull()) { + consumerGroup = jsonObject.get("consumer_group").getAsString(); + } + if (jsonObject.has("consumer_instance") && !jsonObject.get("consumer_instance").isJsonNull()) { + consumerInstance = jsonObject.get("consumer_instance").getAsString(); + } + if (jsonObject.has("aaf_username") && !jsonObject.get("aaf_username").isJsonNull()) { + aafUsername = jsonObject.get("aaf_username").getAsString(); + } + if (jsonObject.has("aaf_password") && !jsonObject.get("aaf_password").isJsonNull()) { + aafPassword = jsonObject.get("aaf_password").getAsString(); + } + if (jsonObject.has("fetch_timeout") && !jsonObject.get("fetch_timeout").isJsonNull()) { + fetchTimeout = jsonObject.get("fetch_timeout").getAsInt(); + } + if (jsonObject.has("fetch_limit") && !jsonObject.get("fetch_limit").isJsonNull()) { + fetchLimit = jsonObject.get("fetch_limit").getAsInt(); + } + if (jsonObject.has("servers") && !jsonObject.get("servers").isJsonNull()) { + JsonArray jsonArray = jsonObject.get("servers").getAsJsonArray(); + servers = new ArrayList<>(); + for (int i=0, e=jsonArray.size(); i<e; i++){ + servers.add(jsonArray.get(i).getAsString()); + } + } + + String topicUrl = jsonObject.get("dmaap_info").getAsJsonObject().get("topic_url").getAsString(); + if (topicUrl.startsWith("https")){ + useHttps = true; + } + String[] pmTopicSplit = topicUrl.split("\\/"); + topic = pmTopicSplit[pmTopicSplit.length - 1]; + + this.params.topic = topicUrl; + this.params.servers = servers; + this.params.consumerGroup = consumerGroup; + this.params.consumerInstance = consumerInstance; + this.params.password = aafPassword; + this.params.userName = aafUsername; + this.params.fetchTimeout = fetchTimeout; + this.params.fetchLimit = fetchLimit; + this.params.useHttps = useHttps; + return this; + } + + public TopicParamsBuilder managed(boolean managed) { + this.params.managed = managed; + return this; + } + + public TopicParamsBuilder hostname(String hostname) { + this.params.hostname = hostname; + return this; + } + + public TopicParamsBuilder clientName(String clientName) { + this.params.clientName = clientName; + return this; + } + + public TopicParamsBuilder port(int port) { + this.params.port = port; + return this; + } + + public TopicParamsBuilder basePath(String basePath) { + this.params.basePath = basePath; + return this; + } + + public TopicParamsBuilder serializationProvider(String serializationProvider) { + this.params.serializationProvider = serializationProvider; + return this; + } + + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/NotificationConsumer.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/NotificationConsumer.java index b605264c..b17eb182 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/NotificationConsumer.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/NotificationConsumer.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,10 +22,14 @@ package org.onap.slice.analysis.ms.dmaap; -import com.att.nsa.cambria.client.CambriaConsumer; - +import com.google.gson.JsonElement; +import io.vavr.collection.List; +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.slf4j.Logger; import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; /** * Consume Notifications from DMAAP events @@ -32,15 +37,17 @@ import org.slf4j.LoggerFactory; public class NotificationConsumer implements Runnable { private static Logger log = LoggerFactory.getLogger(NotificationConsumer.class); - private CambriaConsumer cambriaConsumer; private NotificationCallback notificationCallback; + private MessageRouterSubscriber subscriber; + private MessageRouterSubscribeRequest request; /** * Parameterized Constructor. */ - public NotificationConsumer(CambriaConsumer cambriaConsumer, NotificationCallback notificationCallback) { + public NotificationConsumer(MessageRouterSubscriber subscriber, MessageRouterSubscribeRequest request, NotificationCallback notificationCallback) { super(); - this.cambriaConsumer = cambriaConsumer; + this.subscriber = subscriber; + this.request = request; this.notificationCallback = notificationCallback; } @@ -50,9 +57,14 @@ public class NotificationConsumer implements Runnable { @Override public void run() { try { - Iterable<String> msgs = cambriaConsumer.fetch(); - for (String msg : msgs) { - log.debug(msg); + Mono<MessageRouterSubscribeResponse> responses = this.subscriber.get(this.request); + + MessageRouterSubscribeResponse resp = responses.block(); + log.debug(resp.toString()); + + List<JsonElement> list = resp.items(); + for(int i=0; i<list.size(); i++){ + String msg = list.get(i).toString(); notificationCallback.activateCallBack(msg); } } catch (Exception e) { diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/NotificationProducer.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/NotificationProducer.java index ce362019..66e5d5df 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/NotificationProducer.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/NotificationProducer.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,30 +22,39 @@ package org.onap.slice.analysis.ms.dmaap; -import com.att.nsa.cambria.client.CambriaBatchingPublisher; - +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; import java.io.IOException; +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 reactor.core.publisher.Flux; /** * Produces Notification on DMAAP events */ public class NotificationProducer { - private CambriaBatchingPublisher cambriaBatchingPublisher; + private MessageRouterPublisher publisher; + private MessageRouterPublishRequest request; /** * Parameterized constructor. */ - public NotificationProducer(CambriaBatchingPublisher cambriaBatchingPublisher) { + public NotificationProducer(MessageRouterPublisher publisher, MessageRouterPublishRequest request) { super(); - this.cambriaBatchingPublisher = cambriaBatchingPublisher; + this.publisher = publisher; + this.request = request; } /** * sends notification to dmaap. */ - public int sendNotification(String msg) throws IOException { - return cambriaBatchingPublisher.send("", msg); + public void sendNotification(String msg) throws IOException { + JsonElement jsonElement = JsonParser.parseString(msg); + Flux<JsonElement> singleMessage = Flux.just(jsonElement); + Flux<MessageRouterPublishResponse> result = this.publisher.put(request, singleMessage); + result.then().block(); } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/PolicyDmaapClient.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/PolicyDmaapClient.java index 06604040..04ee151f 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/PolicyDmaapClient.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/PolicyDmaapClient.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,24 +22,22 @@ package org.onap.slice.analysis.ms.dmaap; -import com.att.nsa.cambria.client.CambriaBatchingPublisher; import java.io.IOException; import java.util.Map; +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.slice.analysis.ms.models.Configuration; -import org.onap.slice.analysis.ms.utils.DmaapUtils; +import org.onap.slice.analysis.ms.utils.DcaeDmaapUtil; /** * Client class to handle Policy interactions */ public class PolicyDmaapClient { - private DmaapUtils dmaapUtils; - private Configuration configuration; - public PolicyDmaapClient(DmaapUtils dmaapUtils, Configuration configuration) { - this.dmaapUtils = dmaapUtils; + public PolicyDmaapClient(Configuration configuration) { this.configuration = configuration; } @@ -50,14 +49,11 @@ public class PolicyDmaapClient { Map<String, Object> streamsPublishes = configuration.getStreamsPublishes(); String policyTopicUrl = ((Map<String, String>) ((Map<String, Object>) streamsPublishes.get("CL_topic")) .get("dmaap_info")).get("topic_url"); - String[] policyTopicSplit = policyTopicUrl.split("\\/"); - String policyTopic = policyTopicSplit[policyTopicSplit.length - 1]; - CambriaBatchingPublisher cambriaBatchingPublisher; try { + MessageRouterPublisher publisher = DcaeDmaapUtil.buildPublisher(); + MessageRouterPublishRequest request = DcaeDmaapUtil.buildPublisherRequest("CL_topic", policyTopicUrl); - cambriaBatchingPublisher = dmaapUtils.buildPublisher(configuration, policyTopic); - - NotificationProducer notificationProducer = new NotificationProducer(cambriaBatchingPublisher); + NotificationProducer notificationProducer = new NotificationProducer(publisher, request); notificationProducer.sendNotification(msg); } catch (IOException e) { return false; diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/VesNotificationCallback.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/VesNotificationCallback.java new file mode 100644 index 00000000..fff156cc --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/dmaap/VesNotificationCallback.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.dmaap; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Set; +import org.onap.slice.analysis.ms.aai.AaiService; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.models.vesnotification.NotificationFields; + +import org.onap.slice.analysis.ms.service.ccvpn.CCVPNPmDatastore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.io.IOException; + +/** + * Handles Notification on dmaap for ves notification events + */ +@Component +public class VesNotificationCallback implements NotificationCallback { + + private Configuration configuration; + private String NOTIFICATIONFIELDS = "notificationFields"; + private String EVENT = "event"; + private String vesNotifChangeIdentifier; + private String vesNotfiChangeType; + + @Autowired + CCVPNPmDatastore ccvpnPmDatastore; + + @Autowired + AaiService aaiService; + + private static Logger log = LoggerFactory.getLogger(VesNotificationCallback.class); + + /** + * init ves callback; load configuration. + */ + @PostConstruct + public void init(){ + configuration = Configuration.getInstance(); + vesNotifChangeIdentifier = configuration.getVesNotifChangeIdentifier(); + vesNotfiChangeType = configuration.getVesNotifChangeType(); + } + + /** + * Triggers on handleNofitication method + * @param msg incoming message + */ + @Override + public void activateCallBack(String msg) { + handleNotification(msg); + } + + /** + * Parse Performance dmaap notification and save to DB + * @param msg incoming message + */ + private void handleNotification(String msg) { + log.info("Message received from VES : {}" ,msg); + ObjectMapper obj = new ObjectMapper(); + NotificationFields output = null; + String notifChangeIdentifier = ""; + String notifChangeType = ""; + String cllId = null; + String uniId = null; + String bw = null; + try { + updateCllInstance(); + JsonNode node = obj.readTree(msg); + JsonNode notificationNode = node.get(EVENT).get(NOTIFICATIONFIELDS); + output = obj.treeToValue(notificationNode, NotificationFields.class); + //Filter out target notification changeIdentifier and changeType + notifChangeIdentifier = output.getChangeIdentifier(); + notifChangeType = output.getChangeType(); + if (notifChangeType.equals(vesNotfiChangeType) + && notifChangeIdentifier.equals(vesNotifChangeIdentifier)) { + cllId = output.getArrayOfNamedHashMap().get(0).getHashMap().getCllId(); + uniId = output.getArrayOfNamedHashMap().get(0).getHashMap().getUniId(); + bw = output.getArrayOfNamedHashMap().get(0).getHashMap().getBandwidthValue(); + } + } + catch (IOException e) { + log.error("Error converting VES msg to object, {}", e.getMessage()); + } + if (cllId != null && uniId != null && bw != null){ + log.debug("new bandwidth data -- serviceId: {}, uniId: {}, bw: {}", cllId, uniId, bw); + ccvpnPmDatastore.addUsedBwToEndpoint(cllId, uniId, bw); + } + } + + /** + * Get latest services list, and update local related variables. + */ + public void updateCllInstance(){ + Set<String> instances = aaiService.fetchAllCllInstances(); + log.debug("All valid instances are {}", instances); + ccvpnPmDatastore.updateCllInstances(instances); + } + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/exception/CpsClientException.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/exception/CpsClientException.java new file mode 100644 index 00000000..9a993d12 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/exception/CpsClientException.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.exception; + +/** + * CpsClientException is thown when expected response is not received from CPS + */ +public class CpsClientException extends Exception { + + private static final long serialVersionUID = 1L; + + public CpsClientException(final String exception) { + super(exception); + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/exception/DesClientException.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/exception/DesClientException.java new file mode 100644 index 00000000..7356b0b2 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/exception/DesClientException.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.exception; + +/** + * DesClientException is thown when expected response is not received from DES + */ +public class DesClientException extends Exception { + + private static final long serialVersionUID = 1L; + + public DesClientException(final String exception) { + super(exception); + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/AggregatedConfig.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/AggregatedConfig.java new file mode 100644 index 00000000..b754f641 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/AggregatedConfig.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.models; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * AggregatedConfig contains slice utilization data + */ +@Data +@NoArgsConstructor +public class AggregatedConfig { + + Integer dLThptPerSlice; + + Integer uLThptPerSlice; + + Integer maxNumberOfConns; +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/Configuration.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/Configuration.java index 60f52f0f..c1599517 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/Configuration.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/Configuration.java @@ -2,7 +2,9 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,298 +23,184 @@ package org.onap.slice.analysis.ms.models; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; + import java.lang.reflect.Type; import java.util.List; import java.util.Map; import java.util.Objects; +import lombok.Getter; +import lombok.Setter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.reflect.TypeToken; - /** * Model class for the application Configuration */ +@Getter +@Setter public class Configuration { - private static Logger log = LoggerFactory.getLogger(Configuration.class); - - private static Configuration instance = null; - private String pgHost; - private int pgPort; - private String pgUsername; - private String pgPassword; - private List<String> dmaapServers; - private String configDbService; - private String cpsUrl; - private String aaiUrl; - private Boolean configDbEnabled; - private String cg; - private String cid; - private int pollingInterval; - private int pollingTimeout; - private String aafUsername; - private String aafPassword; - private Map<String, Object> streamsSubscribes; - private Map<String, Object> streamsPublishes; - private int samples; - private int minPercentageChange; - private long initialDelaySeconds; - - /** - * Check if topic is secure. - */ - public boolean isSecured() { - return (aafUsername != null); - - } - - public String getAafUsername() { - return aafUsername; - } - - public void setAafUsername(String aafUsername) { - this.aafUsername = aafUsername; - } - - public String getAafPassword() { - return aafPassword; - } - - public void setAafPassword(String aafPassword) { - this.aafPassword = aafPassword; - } - - public Map<String, Object> getStreamsSubscribes() { - return streamsSubscribes; - } - - public void setStreamsSubscribes(Map<String, Object> streamsSubscribes) { - this.streamsSubscribes = streamsSubscribes; - } - - public Map<String, Object> getStreamsPublishes() { - return streamsPublishes; - } - - public void setStreamsPublishes(Map<String, Object> streamsPublishes) { - this.streamsPublishes = streamsPublishes; - } - - protected Configuration() { - - } - - /** - * Get instance of class. - */ - public static Configuration getInstance() { - if (instance == null) { - instance = new Configuration(); - } - return instance; - } - - public String getCg() { - return cg; - } - - public void setCg(String cg) { - this.cg = cg; - } - - public String getCid() { - return cid; - } - - public void setCid(String cid) { - this.cid = cid; - } - - public int getPollingInterval() { - return pollingInterval; - } - - public void setPollingInterval(int pollingInterval) { - this.pollingInterval = pollingInterval; - } - - public int getPollingTimeout() { - return pollingTimeout; - } - - public void setPollingTimeout(int pollingTimeout) { - this.pollingTimeout = pollingTimeout; - } - - public String getPgHost() { - return pgHost; - } - - public void setPgHost(String pgHost) { - this.pgHost = pgHost; - } - - public int getPgPort() { - return pgPort; - } - - public void setPgPort(int pgPort) { - this.pgPort = pgPort; - } - - public String getPgUsername() { - return pgUsername; - } - - public void setPgUsername(String pgUsername) { - this.pgUsername = pgUsername; - } - - public String getPgPassword() { - return pgPassword; - } - - public void setPgPassword(String pgPassword) { - this.pgPassword = pgPassword; - } - - public List<String> getDmaapServers() { - return dmaapServers; - } - - public void setDmaapServers(List<String> dmaapServers) { - this.dmaapServers = dmaapServers; - } - - public String getConfigDbService() { - return configDbService; - } - - public void setConfigDbService(String configDbService) { - this.configDbService = configDbService; - } - - public String getCpsUrl() { - return cpsUrl; - } - - public void setCpsUrl(String cpsUrl) { - this.cpsUrl = cpsUrl; - } - - public String getAaiUrl() { - return aaiUrl; - } - - public void setAaiUrl(String aaiUrl) { - this.aaiUrl = aaiUrl; - } - - public Boolean getConfigDbEnabled() { - return configDbEnabled; - } - - public void setConfigDbEnabled(Boolean configDbEnabled) { - this.configDbEnabled = configDbEnabled; - } - - public int getSamples() { - return samples; - } - - public void setSamples(int samples) { - this.samples = samples; - } - - public int getMinPercentageChange() { - return minPercentageChange; - } - - public void setMinPercentageChange(int minPercentageChange) { - this.minPercentageChange = minPercentageChange; - } - - public long getInitialDelaySeconds() { - return initialDelaySeconds; - } - - public void setInitialDelaySeconds(long initialDelaySeconds) { - this.initialDelaySeconds = initialDelaySeconds; - } - - @Override - public String toString() { - return "Configuration [pgHost=" + pgHost + ", pgPort=" + pgPort + ", pgUsername=" + pgUsername + ", pgPassword=" - + pgPassword + ", dmaapServers=" + dmaapServers + ", configDbService=" + configDbService + ", cpsUrl=" - + cpsUrl + ", aaiUrl=" + aaiUrl + ", configDbEnabled=" + configDbEnabled + ", cg=" + cg + ", cid=" + cid + ", pollingInterval=" + pollingInterval + ", pollingTimeout=" - + pollingTimeout + ", aafUsername=" + aafUsername + ", aafPassword=" + aafPassword - + ", streamsSubscribes=" + streamsSubscribes + ", streamsPublishes=" + streamsPublishes + ", samples=" - + samples + ", minPercentageChange=" + minPercentageChange + ", initialDelaySeconds=" - + initialDelaySeconds + "]"; - } - - /** - * updates application configuration. - */ - public void updateConfigurationFromJsonObject(JsonObject jsonObject) { - - log.info("Updating configuration from CBS"); - - Type mapType = new TypeToken<Map<String, Object>>() { - }.getType(); - - JsonObject subscribes = jsonObject.getAsJsonObject("streams_subscribes"); - streamsSubscribes = new Gson().fromJson(subscribes, mapType); - - JsonObject publishes = jsonObject.getAsJsonObject("streams_publishes"); - streamsPublishes = new Gson().fromJson(publishes, mapType); - - pgPort = jsonObject.get("postgres.port").getAsInt(); - pollingInterval = jsonObject.get("sliceanalysisms.pollingInterval").getAsInt(); - pgPassword = jsonObject.get("postgres.password").getAsString(); - pgUsername = jsonObject.get("postgres.username").getAsString(); - pgHost = jsonObject.get("postgres.host").getAsString(); - - JsonArray servers = jsonObject.getAsJsonArray("sliceanalysisms.dmaap.server"); - Type listType = new TypeToken<List<String>>() { - }.getType(); - dmaapServers = new Gson().fromJson(servers, listType); - - cg = jsonObject.get("sliceanalysisms.cg").getAsString(); - cid = jsonObject.get("sliceanalysisms.cid").getAsString(); - configDbService = jsonObject.get("sliceanalysisms.configDb.service").getAsString(); - configDbEnabled = jsonObject.get("sliceanalysisms.configDbEnabled").getAsBoolean(); - - pollingTimeout = jsonObject.get("sliceanalysisms.pollingTimeout").getAsInt(); - samples = jsonObject.get("sliceanalysisms.samples").getAsInt(); - minPercentageChange = jsonObject.get("sliceanalysisms.minPercentageChange").getAsInt(); - initialDelaySeconds = jsonObject.get("sliceanalysisms.initialDelaySeconds").getAsLong(); - - if (Objects.isNull(jsonObject.get("aafUsername"))) { - aafUsername = null; - } else { - aafUsername = jsonObject.get("aafUsername").getAsString(); - } - if (Objects.isNull(jsonObject.get("aafPassword"))) { - aafPassword = null; - } else { - aafPassword = jsonObject.get("aafPassword").getAsString(); - } - if (Objects.isNull(jsonObject.get("sliceanalysisms.aai.url"))) { - aaiUrl = null; - } else { - aaiUrl = jsonObject.get("sliceanalysisms.aai.url").getAsString(); - } - if (Objects.isNull(jsonObject.get("sliceanalysisms.cps.url"))) { - cpsUrl = null; - } else { - cpsUrl = jsonObject.get("sliceanalysisms.cps.url").getAsString(); - } - log.info("configuration from CBS {}", this); - } + private static Logger log = LoggerFactory.getLogger(Configuration.class); + + private static Configuration instance = null; + private String pgHost; + private int pgPort; + private String pgUsername; + private String pgPassword; + private List<String> dmaapServers; + private String configDbService; + private String cpsUrl; + private String aaiUrl; + private Boolean configDbEnabled; + private String cg; + private String cid; + private int pollingInterval; + private int pollingTimeout; + private String aafUsername; + private String aafPassword; + private Map<String, Object> streamsSubscribes; + private Map<String, Object> streamsPublishes; + private int samples; + private int minPercentageChange; + private long initialDelaySeconds; + private String rannfnssiDetailsTemplateId; + private String desUrl; + private int pmDataDurationInWeeks; + private int vesNotifPollingInterval; + private String vesNotifChangeIdentifier; + private String vesNotifChangeType; + private int ccvpnEvalInterval; + private double ccvpnEvalUpperThreshold; + private double ccvpnEvalLowerThreshold; + private double ccvpnEvalPrecision; + private String aaiNotifTargetAction; + private String aaiNotifTargetSource; + private String aaiNotifTargetEntity; + private boolean ccvpnEvalPeriodicCheckOn; + private boolean ccvpnEvalOnDemandCheckOn; + private String ccvpnEvalStrategy; + + /** + * No args constructor + */ + protected Configuration() { + } + + /** + * Get instance of class. + */ + public static Configuration getInstance() { + if (instance == null) { + instance = new Configuration(); + } + return instance; + } + + /** + * Check if topic is secure. + */ + public boolean isSecured() { + return (aafUsername != null); + } + + @Override + public String toString() { + return "Configuration [pgHost=" + pgHost + ", pgPort=" + pgPort + ", pgUsername=" + pgUsername + + ", dmaapServers=" + dmaapServers + ", configDbService=" + configDbService + ", cpsUrl=" + + cpsUrl + ", aaiUrl=" + aaiUrl + ", configDbEnabled=" + configDbEnabled + ", cg=" + cg + ", cid=" + cid + + ", pollingInterval=" + pollingInterval + ", pollingTimeout=" + pollingTimeout + ", aafUsername=" + + aafUsername + ", streamsSubscribes=" + streamsSubscribes + + ", streamsPublishes=" + streamsPublishes + ", samples=" + samples + ", minPercentageChange=" + + minPercentageChange + ", initialDelaySeconds=" + initialDelaySeconds + ", rannfnssiDetailsTemplateId=" + + rannfnssiDetailsTemplateId + ", desUrl=" + desUrl + ", pmDataDurationInWeeks=" + pmDataDurationInWeeks + + ", vesNotifPollingInterval=" + vesNotifPollingInterval + ", vesNotifChangeIdentifier=" + + vesNotifChangeIdentifier + ", vesNotifChangeIdentifier=" + vesNotifChangeType + ", ccvpnEvalInterval=" + + ccvpnEvalInterval + ", ccvpnEvalUpperThreshold=" + ccvpnEvalUpperThreshold + ", ccvpnEvalLowerThreshold=" + + ccvpnEvalLowerThreshold + ", ccvpnEvalPrecision=" + ccvpnEvalPrecision + ", aaiNotifTargetAction=" + + aaiNotifTargetAction + ", aaiNotifTargetSource=" + aaiNotifTargetSource + ", aaiNotifTargetEntity=" + + aaiNotifTargetEntity + ", ccvpnEvalPeriodicCheckOn=" + ccvpnEvalPeriodicCheckOn + + ", ccvpnEvalOnDemandCheckOn=" + ccvpnEvalOnDemandCheckOn + ", ccvpnEvalStrategy=" + ccvpnEvalStrategy + "]"; + } + + /** + * updates application configuration. + */ + public void updateConfigurationFromJsonObject(JsonObject jsonObject) { + + log.info("Updating configuration from CBS"); + + Type mapType = new TypeToken<Map<String, Object>>() { + }.getType(); + + JsonObject subscribes = jsonObject.getAsJsonObject("streams_subscribes"); + streamsSubscribes = new Gson().fromJson(subscribes, mapType); + + JsonObject publishes = jsonObject.getAsJsonObject("streams_publishes"); + streamsPublishes = new Gson().fromJson(publishes, mapType); + + pgPort = jsonObject.get("postgres.port").getAsInt(); + pollingInterval = jsonObject.get("sliceanalysisms.pollingInterval").getAsInt(); + pgPassword = jsonObject.get("postgres.password").getAsString(); + pgUsername = jsonObject.get("postgres.username").getAsString(); + pgHost = jsonObject.get("postgres.host").getAsString(); + + JsonArray servers = jsonObject.getAsJsonArray("sliceanalysisms.dmaap.server"); + Type listType = new TypeToken<List<String>>() { + }.getType(); + dmaapServers = new Gson().fromJson(servers, listType); + + cg = jsonObject.get("sliceanalysisms.cg").getAsString(); + cid = jsonObject.get("sliceanalysisms.cid").getAsString(); + configDbService = jsonObject.get("sliceanalysisms.configDb.service").getAsString(); + configDbEnabled = jsonObject.get("sliceanalysisms.configDbEnabled").getAsBoolean(); + + pollingTimeout = jsonObject.get("sliceanalysisms.pollingTimeout").getAsInt(); + samples = jsonObject.get("sliceanalysisms.samples").getAsInt(); + minPercentageChange = jsonObject.get("sliceanalysisms.minPercentageChange").getAsInt(); + initialDelaySeconds = jsonObject.get("sliceanalysisms.initialDelaySeconds").getAsLong(); + rannfnssiDetailsTemplateId = jsonObject.get("sliceanalysisms.rannfnssiDetailsTemplateId").getAsString(); + desUrl = jsonObject.get("sliceanalysisms.desUrl").getAsString(); + pmDataDurationInWeeks = jsonObject.get("sliceanalysisms.pmDataDurationInWeeks").getAsInt(); + + vesNotifChangeIdentifier = jsonObject.get("sliceanalysisms.vesNotifChangeIdentifier").getAsString(); + vesNotifChangeType = jsonObject.get("sliceanalysisms.vesNotifChangeType").getAsString(); + vesNotifPollingInterval = jsonObject.get("sliceanalysisms.vesNotifPollingInterval").getAsInt(); + + aaiNotifTargetAction = jsonObject.get("sliceanalysisms.aaiNotif.targetAction").getAsString(); + aaiNotifTargetSource = jsonObject.get("sliceanalysisms.aaiNotif.targetSource").getAsString(); + aaiNotifTargetEntity = jsonObject.get("sliceanalysisms.aaiNotif.targetEntity").getAsString(); + ccvpnEvalInterval = jsonObject.get("sliceanalysisms.ccvpnEvalInterval").getAsInt(); + ccvpnEvalUpperThreshold = jsonObject.get("sliceanalysisms.ccvpnEvalUpperThreshold").getAsDouble(); + ccvpnEvalLowerThreshold = jsonObject.get("sliceanalysisms.ccvpnEvalLowerThreshold").getAsDouble(); + ccvpnEvalPrecision = jsonObject.get("sliceanalysisms.ccvpnEvalPrecision").getAsDouble(); + ccvpnEvalPeriodicCheckOn = jsonObject.get("sliceanalysisms.ccvpnEvalPeriodicCheckOn").getAsBoolean(); + ccvpnEvalOnDemandCheckOn = jsonObject.get("sliceanalysisms.ccvpnEvalOnDemandCheckOn").getAsBoolean(); + ccvpnEvalStrategy = jsonObject.get("sliceanalysisms.ccvpnEvalStrategy").getAsString(); + + if (Objects.isNull(jsonObject.get("aafUsername"))) { + aafUsername = null; + } else { + aafUsername = jsonObject.get("aafUsername").getAsString(); + } + if (Objects.isNull(jsonObject.get("aafPassword"))) { + aafPassword = null; + } else { + aafPassword = jsonObject.get("aafPassword").getAsString(); + } + if (Objects.isNull(jsonObject.get("sliceanalysisms.aai.url"))) { + aaiUrl = null; + } else { + aaiUrl = jsonObject.get("sliceanalysisms.aai.url").getAsString(); + } + if (Objects.isNull(jsonObject.get("sliceanalysisms.cps.url"))) { + cpsUrl = null; + } else { + cpsUrl = jsonObject.get("sliceanalysisms.cps.url").getAsString(); + } + log.info("configuration from CBS has been updated to {}", this); + } } - diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/SliceConfigDetails.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/SliceConfigDetails.java new file mode 100644 index 00000000..5f8b7434 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/SliceConfigDetails.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.models; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * SliceConfigDetails contains slice utilization data for requested slice + */ +@Data +@NoArgsConstructor +public class SliceConfigDetails { + + String sliceIdentifiers; + AggregatedConfig aggregatedConfig; +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/SliceConfigRequest.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/SliceConfigRequest.java new file mode 100644 index 00000000..aefbdd38 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/SliceConfigRequest.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.models; + +import java.util.List; + +import javax.validation.constraints.NotEmpty; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Request body to get slice utilization data + */ +@Data +@NoArgsConstructor +public class SliceConfigRequest { + + @NotEmpty(message = "Slice Identifier missing") + List<String> sliceIdentifiers; + @NotEmpty(message = "Config Param missing") + List<String> configParams; +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/CpsInterface.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/SliceConfigResponse.java index ef6211c4..18d28ca2 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/configdb/CpsInterface.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/SliceConfigResponse.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2021 Wipro Limited. + * Copyright (C) 2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,21 +19,20 @@ * *******************************************************************************/ -package org.onap.slice.analysis.ms.configdb; +package org.onap.slice.analysis.ms.models; import java.util.List; -import java.util.Map; + +import lombok.Data; +import lombok.NoArgsConstructor; /** - * - * Interface for CPS - * + * SliceConfigResponse contains slice utilization data for requested slices */ -public interface CpsInterface { +@Data +@NoArgsConstructor +public class SliceConfigResponse { - public Map<String, List<String>> fetchRICsOfSnssai(String snssai); - public List<String> fetchNetworkFunctionsOfSnssai(String snssai); - public Map<String, Map<String,Object>> fetchCurrentConfigurationOfRIC(String snssai); - -} + List<SliceConfigDetails> sliceConfigDetails; +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/aai/Relationship.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/aai/Relationship.java new file mode 100644 index 00000000..f4acc08b --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/aai/Relationship.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.models.aai; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; +import java.util.Map; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Model for receiving Relationship data of a service from AAI + */ +@Data +@NoArgsConstructor +public class Relationship { + + @JsonProperty("related-to") + private String relatedTo; + @JsonProperty("relationship-label") + private String relationshipLabel; + @JsonProperty("related-link") + private String relatedLink; + @JsonProperty("relationship-data") + private List<Map<String, String>> relationshipData; + @JsonProperty("related-to-property") + private List<Map<String, String>> relatedToProperty; + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/aai/RelationshipList.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/aai/RelationshipList.java new file mode 100644 index 00000000..1cda2ae5 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/aai/RelationshipList.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.models.aai; + +import java.util.List; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Model for receiving RelationshipList data of a service from AAI + */ +@Data +@NoArgsConstructor +public class RelationshipList { + + List<Relationship> relationship; + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/aai/ServiceInstance.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/aai/ServiceInstance.java new file mode 100644 index 00000000..ecb2c4cd --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/aai/ServiceInstance.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.models.aai; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Model for receiving ServiceInstance data from AAI + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@Data +@NoArgsConstructor +public class ServiceInstance { + + @JsonProperty("service-instance-id") + private String serviceInstanceId; + @JsonProperty("service-instance-name") + private String serviceInstanceName; + @JsonProperty("service-type;") + private String serviceType; + @JsonProperty("service-role") + private String serviceRole; + @JsonProperty("environment-context") + private String environmentContext; + @JsonProperty("workload-context") + private String workloadContext; + @JsonProperty("orchestration-status") + private String orchestrationStatus; + @JsonProperty("relationship-list") + private RelationshipList relationshipList; + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/AAI.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/AAI.java index 9083ff40..3d0caa57 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/AAI.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/AAI.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,41 +22,72 @@ package org.onap.slice.analysis.ms.models.policy; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -/** +/** * Model class for the AAI Object */ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AAI { - @JsonProperty("vserver.is-closed-loop-disabled") - private String vserverIsClosedLoopDisabled; - @JsonProperty("vserver.prov-status") - private String vserverProvStatus; - @JsonProperty("generic-vnf.vnf-id") - private String vServerVNFId; - - public String getVserverIsClosedLoopDisabled() { - return vserverIsClosedLoopDisabled; - } - - public void setVserverIsClosedLoopDisabled(String vserverIsClosedLoopDisabled) { - this.vserverIsClosedLoopDisabled = vserverIsClosedLoopDisabled; - } - - public String getVserverProvStatus() { - return vserverProvStatus; - } - - public void setVserverProvStatus(String vserverProvStatus) { - this.vserverProvStatus = vserverProvStatus; - } - - public String getvServerVNFId() { - return vServerVNFId; - } - - public void setvServerVNFId(String vServerVNFId) { - this.vServerVNFId = vServerVNFId; - } - + @JsonProperty("vserver.is-closed-loop-disabled") + private String vserverIsClosedLoopDisabled; + @JsonProperty("vserver.prov-status") + private String vserverProvStatus; + @JsonProperty("generic-vnf.vnf-id") + private String genericVnfVNFId; + @JsonProperty("generic-vnf.is-closed-loop-disabled") + private String genericVnfIsClosedLoopDisabled; + @JsonProperty("generic-vnf.prov-status") + private String genericVnfProvStatus; + @JsonProperty("generic-vnf.vnf-name") + private String genericVnfVnfName; + + public String getVserverIsClosedLoopDisabled() { + return vserverIsClosedLoopDisabled; + } + + public void setVserverIsClosedLoopDisabled(String vserverIsClosedLoopDisabled) { + this.vserverIsClosedLoopDisabled = vserverIsClosedLoopDisabled; + } + + public String getVserverProvStatus() { + return vserverProvStatus; + } + + public void setVserverProvStatus(String vserverProvStatus) { + this.vserverProvStatus = vserverProvStatus; + } + + public String getGenericVnfVNFId() { + return genericVnfVNFId; + } + + public void setGenericVnfVNFId(String genericVnfVNFId) { + this.genericVnfVNFId = genericVnfVNFId; + } + + public String getGenericVnfProvStatus() { + return genericVnfProvStatus; + } + + public void setGenericVnfProvStatus(String genericVnfProvStatus) { + this.genericVnfProvStatus = genericVnfProvStatus; + } + + public String getGenericVnfIsClosedLoopDisabled() { + return genericVnfIsClosedLoopDisabled; + } + + public void setGenericVnfIsClosedLoopDisabled(String genericVnfIsClosedLoopDisabled) { + this.genericVnfIsClosedLoopDisabled = genericVnfIsClosedLoopDisabled; + } + + public String getGenericVnfVnfName() { + return genericVnfVnfName; + } + + public void setGenericVnfVnfName(String genericVnfVnfName) { + this.genericVnfVnfName = genericVnfVnfName; + } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/AdditionalProperties.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/AdditionalProperties.java index 24c1dd2f..30d1b357 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/AdditionalProperties.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/AdditionalProperties.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,54 +22,76 @@ package org.onap.slice.analysis.ms.models.policy; +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.ArrayList; import java.util.List; import java.util.Map; -/** - * Model class for the AdditionalProperties Object +/** + * Model class for the AdditionalProperties Object */ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdditionalProperties<T> { - private String modifyAction; - private List<String> snssaiList; - private String sliceProfileId; - private T resourceConfig; - private Map<String, String> nsiInfo; - private String scriptName; - public String getModifyAction() { - return modifyAction; - } - public void setModifyAction(String modifyAction) { - this.modifyAction = modifyAction; - } - public List<String> getSnssaiList() { - return snssaiList; - } - public void setSnssaiList(List<String> snssaiList) { - this.snssaiList = snssaiList; - } - public String getSliceProfileId() { - return sliceProfileId; - } - public void setSliceProfileId(String sliceProfileId) { - this.sliceProfileId = sliceProfileId; - } - public T getResourceConfig() { - return resourceConfig; - } - public void setResourceConfig(T resourceConfig) { - this.resourceConfig = resourceConfig; - } - public Map<String, String> getNsiInfo() { - return nsiInfo; - } - public void setNsiInfo(Map<String, String> nsiInfo) { - this.nsiInfo = nsiInfo; - } - public String getScriptName() { - return scriptName; - } - public void setScriptName(String scriptName) { - this.scriptName = scriptName; - } + private String modifyAction; + private List<String> snssaiList; + private String sliceProfileId; + private T resourceConfig; + private Map<String, String> nsiInfo; + private String scriptName; + // Extra attributes for CCVPN CloseLoop + private String enableSdnc; + private List<TransportNetwork> transportNetworks; + public String getModifyAction() { + return modifyAction; + } + public void setModifyAction(String modifyAction) { + this.modifyAction = modifyAction; + } + public List<String> getSnssaiList() { + return snssaiList; + } + public void setSnssaiList(List<String> snssaiList) { + this.snssaiList = snssaiList; + } + public String getSliceProfileId() { + return sliceProfileId; + } + public void setSliceProfileId(String sliceProfileId) { + this.sliceProfileId = sliceProfileId; + } + public T getResourceConfig() { + return resourceConfig; + } + public void setResourceConfig(T resourceConfig) { + this.resourceConfig = resourceConfig; + } + public Map<String, String> getNsiInfo() { + return nsiInfo; + } + public void setNsiInfo(Map<String, String> nsiInfo) { + this.nsiInfo = nsiInfo; + } + public String getScriptName() { + return scriptName; + } + public void setScriptName(String scriptName) { + this.scriptName = scriptName; + } + // Extra attributes setter/getter for CCVPN CloseLoop + public String getEnableSdnc() { + return enableSdnc; + } + + public void setEnableSdnc(String enableSdnc) { + this.enableSdnc = enableSdnc; + } + + public List<TransportNetwork> getTransportNetworks() { + return transportNetworks; + } + + public void setTransportNetworks(List<TransportNetwork> transportNetworks) { + this.transportNetworks = transportNetworks; + } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/Payload.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/Payload.java index d96850cb..e0460407 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/Payload.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/Payload.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,64 +21,93 @@ *******************************************************************************/ package org.onap.slice.analysis.ms.models.policy; -/** - * Model class for the Paylaod Object +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * Model class for the Paylaod Object */ +@JsonInclude(JsonInclude.Include.NON_NULL) public class Payload { - private String name; - private String serviceInstanceID; - private String globalSubscriberId; - private String subscriptionServiceType; - private String networkType; - private AdditionalProperties<?> additionalProperties; + private String name; + private String serviceInstanceID; + private String globalSubscriberId; + private String subscriptionServiceType; + private String networkType; + private AdditionalProperties<?> additionalProperties; + private String serviceType; + private String modelInvariantUuid; + private String modelUuid; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getServiceInstanceID() { + return serviceInstanceID; + } + + public void setServiceInstanceID(String serviceInstanceId) { + this.serviceInstanceID = serviceInstanceId; + } + + public String getGlobalSubscriberId() { + return globalSubscriberId; + } - public String getName() { - return name; - } + public void setGlobalSubscriberId(String globalSubscriberId) { + this.globalSubscriberId = globalSubscriberId; + } - public void setName(String name) { - this.name = name; - } + public String getSubscriptionServiceType() { + return subscriptionServiceType; + } - public String getServiceInstanceID() { - return serviceInstanceID; - } + public void setSubscriptionServiceType(String subscriptionServiceType) { + this.subscriptionServiceType = subscriptionServiceType; + } - public void setServiceInstanceID(String serviceInstanceId) { - this.serviceInstanceID = serviceInstanceId; - } + public String getNetworkType() { + return networkType; + } - public String getGlobalSubscriberId() { - return globalSubscriberId; - } + public void setNetworkType(String networkType) { + this.networkType = networkType; + } - public void setGlobalSubscriberId(String globalSubscriberId) { - this.globalSubscriberId = globalSubscriberId; - } + public AdditionalProperties<?> getAdditionalProperties() { + return additionalProperties; + } - public String getSubscriptionServiceType() { - return subscriptionServiceType; - } + public void setAdditionalProperties(AdditionalProperties<?> additionalProperties) { + this.additionalProperties = additionalProperties; + } - public void setSubscriptionServiceType(String subscriptionServiceType) { - this.subscriptionServiceType = subscriptionServiceType; - } + public String getServiceType() { + return serviceType; + } - public String getNetworkType() { - return networkType; - } + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } - public void setNetworkType(String networkType) { - this.networkType = networkType; - } + public String getModelInvariantUuid() { + return modelInvariantUuid; + } - public AdditionalProperties<?> getAdditionalProperties() { - return additionalProperties; - } + public void setModelInvariantUuid(String modelInvariantUuid) { + this.modelInvariantUuid = modelInvariantUuid; + } - public void setAdditionalProperties(AdditionalProperties<?> additionalProperties) { - this.additionalProperties = additionalProperties; - } + public String getModelUuid() { + return modelUuid; + } + public void setModelUuid(String modelUuid) { + this.modelUuid = modelUuid; + } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/Sla.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/Sla.java new file mode 100644 index 00000000..2d6451aa --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/Sla.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.models.policy; + +/** + * Model class for payload.additionalProperties.transportNetworks.sla + */ +public class Sla { + + private int latency; + private int maxBandwidth; + + /** + * No args constructor for use in serialization + * + */ + public Sla() { + } + + /** + * + * @param maxBandwidth + * @param latency + */ + public Sla(int latency, int maxBandwidth) { + super(); + this.latency = latency; + this.maxBandwidth = maxBandwidth; + } + + public int getLatency() { + return latency; + } + + public void setLatency(int latency) { + this.latency = latency; + } + + public int getMaxBandwidth() { + return maxBandwidth; + } + + public void setMaxBandwidth(int maxBandwidth) { + this.maxBandwidth = maxBandwidth; + } + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/TransportNetwork.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/TransportNetwork.java new file mode 100644 index 00000000..46881806 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/policy/TransportNetwork.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.models.policy; + +/** + * Model class TransportNetwork inside payload.additionalProperties for CCVPN closeLoop + */ +public class TransportNetwork { + + private String id; + private Sla sla; + + /** + * No args constructor for use in serialization + * + */ + public TransportNetwork() { + } + + /** + * + * @param sla + * @param id + */ + public TransportNetwork(String id, Sla sla) { + this.id = id; + this.sla = sla; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Sla getSla() { + return sla; + } + + public void setSla(Sla sla) { + this.sla = sla; + } + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/vesnotification/ArrayOfNamedHashMap.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/vesnotification/ArrayOfNamedHashMap.java new file mode 100644 index 00000000..fcf7eb09 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/vesnotification/ArrayOfNamedHashMap.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.models.vesnotification; + +import javax.annotation.Generated; + +/** + * Model class for Ves ccvpnNotification.arrayOfNamedHashMap + */ +@Generated("jsonschema2pojo") +public class ArrayOfNamedHashMap { + + private String name; + private HashMap hashMap; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public HashMap getHashMap() { + return hashMap; + } + + public void setHashMap(HashMap hashMap) { + this.hashMap = hashMap; + } + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/vesnotification/HashMap.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/vesnotification/HashMap.java new file mode 100644 index 00000000..e26f402c --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/vesnotification/HashMap.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.models.vesnotification; + +import javax.annotation.Generated; + +/** + * Model class for Ves ccvpnNotification.arrayOfNamedHashMap.hashMap + */ +@Generated("jsonschema2pojo") +public class HashMap { + + private String cllId; + private String uniId; + private String bandwidthValue; + private String time; + + public String getCllId() { + return cllId; + } + + public void setCllId(String cllId) { + this.cllId = cllId; + } + + public String getUniId() { + return uniId; + } + + public void setUniId(String uniId) { + this.uniId = uniId; + } + + public String getBandwidthValue() { + return bandwidthValue; + } + + public void setBandwidthValue(String bandwidthValue) { + this.bandwidthValue = bandwidthValue; + } + + public String getTime() { + return time; + } + + public void setTime(String time) { + this.time = time; + } + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/vesnotification/NotificationFields.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/vesnotification/NotificationFields.java new file mode 100644 index 00000000..28509a6b --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/models/vesnotification/NotificationFields.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.models.vesnotification; + +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Generated; + +/** + * Model class for Ves notification message + */ +@Generated("jsonschema2pojo") +public class NotificationFields { + + private String changeIdentifier; + private String changeType; + private String notificationFieldsVersion; + private List<ArrayOfNamedHashMap> arrayOfNamedHashMap = new ArrayList<ArrayOfNamedHashMap>(); + + public String getChangeIdentifier() { + return changeIdentifier; + } + + public void setChangeIdentifier(String changeIdentifier) { + this.changeIdentifier = changeIdentifier; + } + + public String getChangeType() { + return changeType; + } + + public void setChangeType(String changeType) { + this.changeType = changeType; + } + + public String getNotificationFieldsVersion() { + return notificationFieldsVersion; + } + + public void setNotificationFieldsVersion(String notificationFieldsVersion) { + this.notificationFieldsVersion = notificationFieldsVersion; + } + + public List<ArrayOfNamedHashMap> getArrayOfNamedHashMap() { + return arrayOfNamedHashMap; + } + + public void setArrayOfNamedHashMap(List<ArrayOfNamedHashMap> arrayOfNamedHashMap) { + this.arrayOfNamedHashMap = arrayOfNamedHashMap; + } + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/restclients/DesRestClient.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/restclients/DesRestClient.java new file mode 100644 index 00000000..5d29af3a --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/restclients/DesRestClient.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.restclients; + +import java.util.Collections; + +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; + +/** + * This class represents rest client for DES interfaces + */ +@Component +public class DesRestClient extends RestClient { + + public DesRestClient() { + super(); + } + + /** + * Send Post Request to DES + */ + + public <T> ResponseEntity<T> sendPostRequest(String requestUrl, String requestBody, + ParameterizedTypeReference<T> responseType) { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setContentType(MediaType.APPLICATION_JSON); + return super.sendPostRequest(headers, requestUrl, requestBody, responseType); + } + + /** + * Send Get Request to DES + */ + + public <T> ResponseEntity<T> sendGetRequest(String requestUrl, ParameterizedTypeReference<T> responseType) { + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setContentType(MediaType.APPLICATION_JSON); + return super.sendGetRequest(headers, requestUrl, responseType); + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConfigThread.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConfigThread.java new file mode 100644 index 00000000..88477eb0 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConfigThread.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.service; + +import org.onap.slice.analysis.ms.models.ConfigPolicy; +import org.onap.slice.analysis.ms.service.ccvpn.CCVPNPmDatastore; +import org.onap.slice.analysis.ms.utils.BeanUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This thread is used to convert ccvpn runtime configurations from policy to our local memory CCVPNPmDatastore + */ +public class ConfigThread extends Thread{ + + CCVPNPmDatastore ccvpnPmDatastore = BeanUtil.getBean(CCVPNPmDatastore.class); + private static Logger log = LoggerFactory.getLogger(ConfigThread.class); + + public ConfigThread () { + super(); + } + + public void run() { + log.info("Config Thread is starting..."); + boolean done = false; + while(!done) { + try { + Thread.sleep(1000); + ConfigPolicy configPolicy = ConfigPolicy.getInstance(); + if(configPolicy != null && configPolicy.getConfig() != null) { + String cllId = null; + Boolean clBwAssuranceStatus = null; + int originalBw = 0; + if(configPolicy.getConfig().containsKey("cllId")){ + cllId = String.valueOf(configPolicy.getConfig().get("cllId")); + } + if(configPolicy.getConfig().containsKey("closedLoopStatus")){ + clBwAssuranceStatus = String.valueOf(configPolicy.getConfig().get("closedLoopStatus")).equalsIgnoreCase("true"); + } + if(configPolicy.getConfig().containsKey("originalBw")){ + originalBw = Integer.parseInt(String.valueOf(configPolicy.getConfig().get("originalBw"))); + } + if(cllId!=null && clBwAssuranceStatus!=null){ + ccvpnPmDatastore.updateConfigFromPolicy(cllId, clBwAssuranceStatus, originalBw); + } + } else { + log.error("Config policy is empty, nothing to update."); + } + + } catch (Exception e) { + log.error("Exception in Config Thread ", e); + done = true; + } + } + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConsumerThread.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConsumerThread.java index 6098142e..5dcd9189 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConsumerThread.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ConsumerThread.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,95 +24,93 @@ package org.onap.slice.analysis.ms.service; import java.util.List; import java.util.Objects; -import org.onap.slice.analysis.ms.configdb.CpsInterface; import org.onap.slice.analysis.ms.configdb.IConfigDbService; +import org.onap.slice.analysis.ms.cps.CpsInterface; import org.onap.slice.analysis.ms.models.Configuration; import org.onap.slice.analysis.ms.models.SubCounter; import org.onap.slice.analysis.ms.utils.BeanUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** +/** * This Thread class consumes message from pm data queue and sends onset message to policy */ public class ConsumerThread extends Thread { - private static Logger log = LoggerFactory.getLogger(ConsumerThread.class); - private PmDataQueue pmDataQueue; - private IConfigDbService configDbService; - private SnssaiSamplesProcessor snssaiSamplesProcessor; - private CpsInterface cpsInterface; - private long initialDelaySec; - private int samples; + private static Logger log = LoggerFactory.getLogger(ConsumerThread.class); + private PmDataQueue pmDataQueue; + private IConfigDbService configDbService; + private SnssaiSamplesProcessor snssaiSamplesProcessor; + private CpsInterface cpsInterface; + private long initialDelaySec; + private int samples; - /** - * Default constructor. - */ - public ConsumerThread() { - super(); - this.pmDataQueue = BeanUtil.getBean(PmDataQueue.class); - this.configDbService = BeanUtil.getBean(IConfigDbService.class); - this.initialDelaySec = Configuration.getInstance().getInitialDelaySeconds(); - this.samples = Configuration.getInstance().getSamples(); - this.cpsInterface = BeanUtil.getBean(CpsInterface.class); - } + /** + * Default constructor. + */ + public ConsumerThread() { + super(); + this.pmDataQueue = BeanUtil.getBean(PmDataQueue.class); + this.configDbService = BeanUtil.getBean(IConfigDbService.class); + this.initialDelaySec = Configuration.getInstance().getInitialDelaySeconds(); + this.samples = Configuration.getInstance().getSamples(); + this.cpsInterface = BeanUtil.getBean(CpsInterface.class); + } - /** - * Consumes data from PM data queue, process the data and sends onset message to policy if needed - */ - @Override - public void run() { - Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true - : Configuration.getInstance().getConfigDbEnabled(); - boolean done = false; - boolean result = false; - String snssai = ""; - List<String> nfs = null; - while (!done) { - try { - Thread.sleep(initialDelaySec); - log.info("Starting Consumer Thread"); - snssai = pmDataQueue.getSnnsaiFromQueue(); - if (!snssai.equals("")) { - log.info("Consumer thread processing data for s-nssai {}",snssai); - try { - if (isConfigDbEnabled) { - nfs = configDbService.fetchNetworkFunctionsOfSnssai(snssai); - } - else { - nfs = cpsInterface.fetchNetworkFunctionsOfSnssai(snssai); - } - } - catch(Exception e) { - pmDataQueue.putSnssaiToQueue(snssai); - log.error("Exception caught while fetching nfs of snssai {}, {}", snssai, e.getMessage()); - } - if(nfs != null && checkForEnoughSamples(nfs, snssai)) { - this.snssaiSamplesProcessor = BeanUtil.getBean(SnssaiSamplesProcessor.class); - result = snssaiSamplesProcessor.processSamplesOfSnnsai(snssai, nfs); - if(!result) { - log.info("Not enough samples to process for {}",snssai); - pmDataQueue.putSnssaiToQueue(snssai); - } - } - } - } catch (Exception e) { - log.error("Exception in Consumer Thread, {}", e.getMessage()); - done = true; - } - } - } + /** + * Consumes data from PM data queue, process the data and sends onset message to policy if needed + */ + @Override + public void run() { + Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true + : Configuration.getInstance().getConfigDbEnabled(); + boolean done = false; + boolean result = false; + String snssai = ""; + List<String> nfs = null; + while (!done) { + try { + Thread.sleep(initialDelaySec); + log.info("Starting Consumer Thread"); + snssai = pmDataQueue.getSnnsaiFromQueue(); + if (!snssai.equals("")) { + log.info("Consumer thread processing data for s-nssai {}", snssai); + try { + if (isConfigDbEnabled) { + nfs = configDbService.fetchNetworkFunctionsOfSnssai(snssai); + } else { + nfs = cpsInterface.fetchNetworkFunctionsOfSnssai(snssai); + } + } catch (Exception e) { + pmDataQueue.putSnssaiToQueue(snssai); + log.error("Exception caught while fetching nfs of snssai {}, {}", snssai, e.getMessage()); + } + if (nfs != null && checkForEnoughSamples(nfs, snssai)) { + this.snssaiSamplesProcessor = BeanUtil.getBean(SnssaiSamplesProcessor.class); + result = snssaiSamplesProcessor.processSamplesOfSnnsai(snssai, nfs); + if (!result) { + log.info("Not enough samples to process for {}", snssai); + pmDataQueue.putSnssaiToQueue(snssai); + } + } + } + } catch (Exception e) { + log.error("Exception in Consumer Thread, {}", e.getMessage()); + done = true; + } + } + } /** * Checks whether enough samples are available for the network functions */ - public boolean checkForEnoughSamples(List<String> nfs, String snssai) { - for(String nf : nfs) { - if(! pmDataQueue.checkSamplesInQueue(new SubCounter(nf, snssai), samples)) { - log.info("Not enough samples to process for network function {} of snssai {}", nf, snssai); - pmDataQueue.putSnssaiToQueue(snssai); - return false; - } - } - return true; - } + public boolean checkForEnoughSamples(List<String> nfs, String snssai) { + for (String nf : nfs) { + if (!pmDataQueue.checkSamplesInQueue(new SubCounter(nf, snssai), samples)) { + log.info("Not enough samples to process for network function {} of snssai {}", nf, snssai); + pmDataQueue.putSnssaiToQueue(snssai); + return false; + } + } + return true; + } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/MLMessageProcessor.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/MLMessageProcessor.java index 8bc7b0d5..d1d2a152 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/MLMessageProcessor.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/MLMessageProcessor.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,9 +25,9 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import org.onap.slice.analysis.ms.configdb.AaiInterface; -import org.onap.slice.analysis.ms.configdb.CpsInterface; +import org.onap.slice.analysis.ms.aai.AaiInterface; import org.onap.slice.analysis.ms.configdb.IConfigDbService; +import org.onap.slice.analysis.ms.cps.CpsInterface; import org.onap.slice.analysis.ms.models.CUModel; import org.onap.slice.analysis.ms.models.Configuration; import org.onap.slice.analysis.ms.models.MLOutputModel; @@ -44,51 +44,49 @@ import org.springframework.stereotype.Component; @Component @Scope("prototype") public class MLMessageProcessor { - private static Logger log = LoggerFactory.getLogger(MLMessageProcessor.class); + private static Logger log = LoggerFactory.getLogger(MLMessageProcessor.class); - @Autowired - private IConfigDbService configDbService; + @Autowired + private IConfigDbService configDbService; - @Autowired - private PolicyService policyService; + @Autowired + private PolicyService policyService; - @Autowired - private AaiInterface aaiInterface; + @Autowired + private AaiInterface aaiInterface; - @Autowired - private CpsInterface cpsInterface; + @Autowired + private CpsInterface cpsInterface; - public void processMLMsg(MLOutputModel mlOutputMsg) { - Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true - : Configuration.getInstance().getConfigDbEnabled(); - Map<String, List<String>> ricToCellMapping = null; - Map<String, String> serviceDetails = null; - String snssai = mlOutputMsg.getSnssai(); - List<CUModel> cuData = mlOutputMsg.getData(); - if (isConfigDbEnabled) { - ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai); - } else { - ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai); - } - log.debug("RIC to cell mapping of S-NSSAI {} is {}", snssai, ricToCellMapping); - for (CUModel cuModel : cuData) { - String cellId = String.valueOf(cuModel.getCellCUList().get(0).getCellLocalId()); - ricToCellMapping.forEach((ricId, cells) -> { - if (cells.contains(cellId)) { - cuModel.setNearRTRICId(ricId); - } - }); - } - AdditionalProperties<MLOutputModel> addProps = new AdditionalProperties<>(); - addProps.setResourceConfig(mlOutputMsg); - - if (isConfigDbEnabled) { - serviceDetails = configDbService.fetchServiceDetails(snssai); - } else { - serviceDetails = aaiInterface.fetchServiceDetails(snssai); - - } - policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails); - } + /** + * Process the message sent by ML service and sends notification to policy + */ + public void processMLMsg(MLOutputModel mlOutputMsg) { + Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true + : Configuration.getInstance().getConfigDbEnabled(); + Map<String, List<String>> ricToCellMapping = null; + Map<String, String> serviceDetails = null; + String snssai = mlOutputMsg.getSnssai(); + List<CUModel> cuData = mlOutputMsg.getData(); + if (isConfigDbEnabled) { + serviceDetails = configDbService.fetchServiceDetails(snssai); + ricToCellMapping = configDbService.fetchCUCPCellsOfSnssai(snssai); + } else { + ricToCellMapping = cpsInterface.fetchnrCellCUsOfSnssai(snssai); + serviceDetails = aaiInterface.fetchServiceDetails(snssai); + } + log.info("RIC to cell mapping of S-NSSAI {} is {}", snssai, ricToCellMapping); + for (CUModel cuModel : cuData) { + String cellId = String.valueOf(cuModel.getCellCUList().get(0).getCellLocalId()); + ricToCellMapping.forEach((ricId, cells) -> { + if (cells.contains(cellId)) { + cuModel.setNearRTRICId(ricId); + } + }); + } + AdditionalProperties<MLOutputModel> addProps = new AdditionalProperties<>(); + addProps.setResourceConfig(mlOutputMsg); + policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails); + } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/PolicyService.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/PolicyService.java index 2d3a2df0..da55c0b4 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/PolicyService.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/PolicyService.java @@ -3,6 +3,8 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 CTC, Inc. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,84 +37,167 @@ import org.onap.slice.analysis.ms.models.policy.AAI; import org.onap.slice.analysis.ms.models.policy.AdditionalProperties; import org.onap.slice.analysis.ms.models.policy.OnsetMessage; import org.onap.slice.analysis.ms.models.policy.Payload; -import org.onap.slice.analysis.ms.utils.DmaapUtils; +import org.onap.slice.analysis.ms.models.policy.Sla; +import org.onap.slice.analysis.ms.models.policy.TransportNetwork; +import org.onap.slice.analysis.ms.service.ccvpn.RequestOwner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; +/** + * Serivce to generate and publish onsetMessage to ONAP/Policy + */ @Component public class PolicyService { - private PolicyDmaapClient policyDmaapClient; - private static Logger log = LoggerFactory.getLogger(PolicyService.class); - private ObjectMapper objectMapper = new ObjectMapper(); - - /** - * Initialization - */ - @PostConstruct - public void init() { - Configuration configuration = Configuration.getInstance(); - policyDmaapClient = new PolicyDmaapClient(new DmaapUtils(), configuration); - } - - protected <T> OnsetMessage formPolicyOnsetMessage(String snssai, AdditionalProperties<T> addProps, Map<String, String> serviceDetails) { - OnsetMessage onsetmsg = new OnsetMessage(); - Payload payload = new Payload(); - payload.setGlobalSubscriberId(serviceDetails.get("globalSubscriberId")); - payload.setSubscriptionServiceType(serviceDetails.get("subscriptionServiceType")); - payload.setNetworkType("AN"); - payload.setName(serviceDetails.get("ranNFNSSIId")); - payload.setServiceInstanceID(serviceDetails.get("ranNFNSSIId")); - - addProps.setModifyAction(""); - Map<String, String> nsiInfo = new HashMap<>(); - nsiInfo.put("nsiId", UUID.randomUUID().toString()); - nsiInfo.put("nsiName", ""); - addProps.setNsiInfo(nsiInfo); - addProps.setScriptName("AN"); - addProps.setSliceProfileId(serviceDetails.get("sliceProfileId")); - addProps.setModifyAction("reconfigure"); - List<String> snssaiList = new ArrayList<>(); - snssaiList.add(snssai); - addProps.setSnssaiList(snssaiList); - - payload.setAdditionalProperties(addProps); - try { - onsetmsg.setPayload(objectMapper.writeValueAsString(payload)); - } catch (Exception e) { - log.error("Error while mapping payload as string , {}",e.getMessage()); - } - - onsetmsg.setClosedLoopControlName("ControlLoop-Slicing-116d7b00-dbeb-4d03-8719-d0a658fa735b"); - onsetmsg.setClosedLoopAlarmStart(System.currentTimeMillis()); - onsetmsg.setClosedLoopEventClient("microservice.sliceAnalysisMS"); - onsetmsg.setClosedLoopEventStatus("ONSET"); - onsetmsg.setRequestID(UUID.randomUUID().toString()); - onsetmsg.setTarget("generic-vnf.vnf-id"); - onsetmsg.setTargetType("VNF"); - onsetmsg.setFrom("DCAE"); - onsetmsg.setVersion("1.0.2"); - AAI aai = new AAI(); - aai.setVserverIsClosedLoopDisabled("false"); - aai.setVserverProvStatus("ACTIVE"); - aai.setvServerVNFId(serviceDetails.get("ranNFNSSIId")); - onsetmsg.setAai(aai); - return onsetmsg; - } - - protected <T> void sendOnsetMessageToPolicy(String snssai, AdditionalProperties<T> addProps, Map<String, String> serviceDetails) { - OnsetMessage onsetMessage = formPolicyOnsetMessage(snssai, addProps, serviceDetails); - String msg = ""; - try { - msg = objectMapper.writeValueAsString(onsetMessage); - log.info("Policy onset message for S-NSSAI: {} is {}", snssai, msg); - policyDmaapClient.sendNotificationToPolicy(msg); - } - catch (Exception e) { - log.error("Error sending notification to policy, {}",e.getMessage()); - } - } + private final static int SERVICE_RATE_INTERVAL = 5000; // in ms + private PolicyDmaapClient policyDmaapClient; + private static Logger log = LoggerFactory.getLogger(PolicyService.class); + private ObjectMapper objectMapper = new ObjectMapper(); + private RateLimiter rateLimiter; + /** + * Initialization + */ + @PostConstruct + public void init() { + Configuration configuration = Configuration.getInstance(); + policyDmaapClient = new PolicyDmaapClient(configuration); + rateLimiter = new RateLimiter(1, SERVICE_RATE_INTERVAL); + } + + protected <T> OnsetMessage formPolicyOnsetMessage(String snssai, AdditionalProperties<T> addProps, Map<String, String> serviceDetails) { + OnsetMessage onsetmsg = new OnsetMessage(); + Payload payload = new Payload(); + payload.setGlobalSubscriberId(serviceDetails.get("globalSubscriberId")); + payload.setSubscriptionServiceType(serviceDetails.get("subscriptionServiceType")); + payload.setNetworkType("AN"); + payload.setName(serviceDetails.get("ranNFNSSIId")); + payload.setServiceInstanceID(serviceDetails.get("ranNFNSSIId")); + + addProps.setModifyAction(""); + Map<String, String> nsiInfo = new HashMap<>(); + nsiInfo.put("nsiId", UUID.randomUUID().toString()); + nsiInfo.put("nsiName", ""); + addProps.setNsiInfo(nsiInfo); + addProps.setScriptName("AN"); + addProps.setSliceProfileId(serviceDetails.get("sliceProfileId")); + addProps.setModifyAction("reconfigure"); + List<String> snssaiList = new ArrayList<>(); + snssaiList.add(snssai); + addProps.setSnssaiList(snssaiList); + + payload.setAdditionalProperties(addProps); + try { + onsetmsg.setPayload(objectMapper.writeValueAsString(payload)); + } catch (Exception e) { + log.error("Error while mapping payload as string , {}",e.getMessage()); + } + + onsetmsg.setClosedLoopControlName("ControlLoop-Slicing-116d7b00-dbeb-4d03-8719-d0a658fa735b"); + onsetmsg.setClosedLoopAlarmStart(System.currentTimeMillis()); + onsetmsg.setClosedLoopEventClient("microservice.sliceAnalysisMS"); + onsetmsg.setClosedLoopEventStatus("ONSET"); + onsetmsg.setRequestID(UUID.randomUUID().toString()); + onsetmsg.setTarget("generic-vnf.vnf-id"); + onsetmsg.setTargetType("VNF"); + onsetmsg.setFrom("DCAE"); + onsetmsg.setVersion("1.0.2"); + AAI aai = new AAI(); + aai.setVserverIsClosedLoopDisabled("false"); + aai.setVserverProvStatus("ACTIVE"); + aai.setGenericVnfVNFId(serviceDetails.get("ranNFNSSIId")); + onsetmsg.setAai(aai); + return onsetmsg; + } + + protected <T> void sendOnsetMessageToPolicy(String snssai, AdditionalProperties<T> addProps, Map<String, String> serviceDetails) { + OnsetMessage onsetMessage = formPolicyOnsetMessage(snssai, addProps, serviceDetails); + String msg = ""; + try { + msg = objectMapper.writeValueAsString(onsetMessage); + log.info("Policy onset message for S-NSSAI: {} is {}", snssai, msg); + policyDmaapClient.sendNotificationToPolicy(msg); + } + catch (Exception e) { + log.error("Error sending notification to policy, {}",e.getMessage()); + } + } + + /** + * Generate onsetMessage for ccvpn service update operation + * @param cllId cloud leased line Id (ethernet service id) + * @param newBw new bandwidth value for bandwidth adjustment + * @param <T> type for additionalPropert + * ies, can be omitted + * @return OnsetMessage result + */ + public <T> OnsetMessage formPolicyOnsetMessageForCCVPN(String cllId, Integer newBw, RequestOwner owner) { + Sla sla = new Sla(2, newBw); + String transportNetworkId = cllId; + if (owner == RequestOwner.UUI) { + transportNetworkId += "-network-001"; + } else if (owner == RequestOwner.DCAE) { + transportNetworkId += "-network-002"; + } + TransportNetwork transportNetwork = new TransportNetwork(transportNetworkId, sla); + AdditionalProperties additionalProperties = new AdditionalProperties(); + additionalProperties.setModifyAction("bandwidth"); + additionalProperties.setEnableSdnc("true"); + List<TransportNetwork> transportNetworks = new ArrayList(); + transportNetworks.add(transportNetwork); + additionalProperties.setTransportNetworks(transportNetworks); + + Payload payload = new Payload(); + payload.setGlobalSubscriberId("IBNCustomer"); + payload.setSubscriptionServiceType("IBN"); + payload.setServiceType("CLL"); + payload.setName("cloud-leased-line-101"); + payload.setServiceInstanceID(cllId); + payload.setAdditionalProperties(additionalProperties); + payload.setModelInvariantUuid("6790ab0e-034f-11eb-adc1-0242ac120002"); + payload.setModelUuid("6790ab0e-034f-11eb-adc1-0242ac120002"); + + OnsetMessage onsetmsg = new OnsetMessage(); + try { + onsetmsg.setPayload(objectMapper.writeValueAsString(payload)); + } catch (Exception e) { + log.error("Error while mapping payload as string , {}",e.getMessage()); + } + onsetmsg.setClosedLoopControlName("ControlLoop-CCVPN-CLL-227e8b00-dbeb-4d03-8719-d0a658fb846c"); + onsetmsg.setClosedLoopAlarmStart(System.currentTimeMillis()); + onsetmsg.setClosedLoopEventClient("microservice.sliceAnalysisMS"); + onsetmsg.setClosedLoopEventStatus("ONSET"); + onsetmsg.setRequestID(UUID.randomUUID().toString()); + onsetmsg.setTarget("generic-vnf.vnf-id"); + onsetmsg.setTargetType("VNF"); + onsetmsg.setFrom("DCAE"); + onsetmsg.setVersion("1.0.2"); + AAI aai = new AAI(); + aai.setGenericVnfIsClosedLoopDisabled("false"); + aai.setGenericVnfProvStatus("ACTIVE"); + aai.setGenericVnfVNFId("00000000-0000-0000-0000-000000000000"); + aai.setGenericVnfVnfName("00000"); + onsetmsg.setAai(aai); + return onsetmsg; + } + + /** + * Sending the onsetMessage to Onap-Policy through PolicyDmaapClient + * @param onsetMessage the onsetMessage about to send + * @param <T> type inherent from previous implementation can be omitted + */ + public <T> void sendOnsetMessageToPolicy(OnsetMessage onsetMessage){ + String msg = ""; + try { + msg = objectMapper.writeValueAsString(onsetMessage); + rateLimiter.getToken(); + log.info("Sending onset message to Onap/Policy for ControlLoop-CCVPN-CLL, the msg: {}", msg); + policyDmaapClient.sendNotificationToPolicy(msg); + } + catch (Exception e) { + log.error("Error sending notification to policy, {}",e.getMessage()); + } + } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/RateLimiter.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/RateLimiter.java new file mode 100644 index 00000000..77ee61f2 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/RateLimiter.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service; + +/** + * A simple rate-limiter; make sure bandwidth adjustment requests don't swarm underlying network controller + */ +class RateLimiter { + private int MAX_TOKENS; + private long lastRequestTime = System.currentTimeMillis(); + private long possibleTokens = 0; + private long interval = 1000; + + /** + * Constructor for rate limiter (simple token bucket filter) + * @param maxTokens max number of token allowed + * @param interval interval(ms) between received new token + */ + public RateLimiter(int maxTokens, int interval){ + MAX_TOKENS = maxTokens; + this.interval = interval; + } + + /** + * Trying to get a new token for execution, if no token left, stall for interval ms. + * @throws InterruptedException + */ + synchronized public void getToken() throws InterruptedException { + possibleTokens += (System.currentTimeMillis() - lastRequestTime) / interval; + if (possibleTokens > MAX_TOKENS){ + possibleTokens = MAX_TOKENS; + } + if (possibleTokens == 0){ + Thread.sleep(interval); + } else { + possibleTokens--; + } + // granting token + lastRequestTime = System.currentTimeMillis(); + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SliceUtilization.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SliceUtilization.java new file mode 100644 index 00000000..a9d30ce7 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SliceUtilization.java @@ -0,0 +1,218 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.service; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.onap.slice.analysis.ms.aai.AaiService; +import org.onap.slice.analysis.ms.exception.DesClientException; +import org.onap.slice.analysis.ms.models.AggregatedConfig; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.models.SliceConfigDetails; +import org.onap.slice.analysis.ms.models.SliceConfigRequest; +import org.onap.slice.analysis.ms.models.SliceConfigResponse; +import org.onap.slice.analysis.ms.restclients.DesRestClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +/** + * This Service calculates the slice utilization details + */ +@Service +public class SliceUtilization { + + private static Logger log = LoggerFactory.getLogger(SliceUtilization.class); + + @Autowired + private AaiService aaiService; + + @Autowired + DesRestClient desRestClient; + + /** + * Default values set for uplink and downlink throughput calculation (in + * accordance with 3GPP specifications) + * + */ + private static final Integer numOfAggregatedComponentCarries = 8; + private static final Integer maxNumOfLayers = 4; + private static final Integer maxModulationOrder = 2; + private static final Integer scalingFactor = 1; + private static final Double maxBitRate = 948.0 / 1024; + private static final Integer nrNumerology = 2; + private static final Double averageSymbolDuration = Math.pow(10, -3) / (14 * 2 * nrNumerology); + private static final Double overHeadForDl = 0.18; + private static final Double overHeadForUl = 0.10; + private static final Integer TOTAL_PRB = 132; + + /** + * Calculates the slice utilization details for requested slices. + * + * @param sliceConfigRequest contains sliceInstanceId + * @return SliceConfigResponse contains slice utilization details + */ + public SliceConfigResponse getSliceUtilizationData(SliceConfigRequest sliceConfigRequest) { + + log.info("getSliceUtilizationData"); + SliceConfigResponse sliceConfigResponse = new SliceConfigResponse(); + ArrayList<SliceConfigDetails> sliceConfigDetailsList = new ArrayList<>(); + + try { + sliceConfigRequest.getSliceIdentifiers().forEach(sliceInstanceId -> { + List<String> snssaiList = null; + snssaiList = aaiService.getSnssaiList(sliceInstanceId); + List<JSONObject> pmDataList = new ArrayList<>(); + snssaiList.forEach(snssai -> { + JSONObject pmData = getPMData(snssai); + pmDataList.add(pmData); + }); + AggregatedConfig aggregatedConfig = calculateSliceUtilization(pmDataList); + SliceConfigDetails sliceConfigDetails = new SliceConfigDetails(); + sliceConfigDetails.setSliceIdentifiers(sliceInstanceId); + sliceConfigDetails.setAggregatedConfig(aggregatedConfig); + sliceConfigDetailsList.add(sliceConfigDetails); + + }); + } catch (Exception e) { + log.error("Exception caught while fetching data"); + } + sliceConfigResponse.setSliceConfigDetails(sliceConfigDetailsList); + log.info("SliceConfigResponse: " + sliceConfigResponse.toString()); + return sliceConfigResponse; + + } + + /** + * Fetches the PM data for requested SNSSAI from DES. + * + * @param snssai snssai ID + * @return PM Data for requested SNSSAI + */ + protected JSONObject getPMData(String snssai) { + String desUrl = Configuration.getInstance().getDesUrl(); + Map<String, String> inputParameter = new HashMap<>(); + int duration = Configuration.getInstance().getPmDataDurationInWeeks(); + Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + calendar.add(Calendar.WEEK_OF_MONTH, -duration); + inputParameter.put("snssai", "SM.PrbUsedDl." + snssai); + inputParameter.put("time", String.valueOf(calendar.getTimeInMillis())); + ResponseEntity<String> response = null; + JSONObject pmData = null; + try { + + String jsonRequestBody = new ObjectMapper().writeValueAsString(inputParameter); + log.info("fetching PM Data for : {}", snssai); + log.info("desUrl {}", desUrl); + log.info("jsonRequestBody {}", jsonRequestBody); + response = + desRestClient.sendPostRequest(desUrl, jsonRequestBody, new ParameterizedTypeReference<String>() {}); + pmData = new JSONObject(response.getBody()); + if (response.getStatusCode().value() != 200) { + throw new DesClientException(String.format("Response code from DES other than 200: %d\", statusCode", + response.getStatusCode().value())); + } + + } catch (Exception e) { + log.error("Error while fetching PM data from DES {} ", e); + } + + return pmData; + } + + /** + * Calculates average DL and UL PRB used from the PM data and returns the + * remaining resources(utilization details) in terms of throughput + * + * @param pmDataList PM data for all SNSSAIs + * @return aggregatedConfig containing slice utilization details + */ + protected AggregatedConfig calculateSliceUtilization(List<JSONObject> pmDataList) { + + Integer numOfPRBData = 0; + Integer dlPRBUsed = 0; + Integer ulPRBUsed = 0; + Integer dlThptIndex = 0; + Integer ulThptIndex = 1; + try { + for (JSONObject pmData : pmDataList) { + JSONArray result = pmData.getJSONArray("result"); + for (int i = 0; i < result.length(); i++) { + JSONObject measValuesObject = result.getJSONObject(i); + String measValuesListStr = measValuesObject.getString("measValuesList"); + String sMeasTypesListtStr = measValuesObject.getString("sMeasTypesList"); + JSONArray measValuesArray = new JSONArray(measValuesListStr); + JSONArray sMeasTypesArray = new JSONArray(sMeasTypesListtStr); + if (sMeasTypesArray.getString(0).contains("PrbUsedUl")) { + ulThptIndex = 0; + dlThptIndex = 1; + } + numOfPRBData += measValuesArray.length(); + for (int j = 0; j < measValuesArray.length(); j++) { + dlPRBUsed += + measValuesArray.getJSONArray(j).getJSONArray(1).getJSONArray(dlThptIndex).getInt(1); + ulPRBUsed += + measValuesArray.getJSONArray(j).getJSONArray(1).getJSONArray(ulThptIndex).getInt(1); + } + } + } + } catch (Exception e) { + log.error("Exception caught while calculating slice utilization: {}", e); + } + + Integer averageDLPrb = dlPRBUsed / numOfPRBData; + Integer averageULPrb = ulPRBUsed / numOfPRBData; + Double tempdl = 0.0; + Double tempul = 0.0; + int j = 1; + + while (j <= numOfAggregatedComponentCarries) { + tempdl += ((Math.pow(maxNumOfLayers, j) * Math.pow(maxModulationOrder, j) * Math.pow(scalingFactor, j) + * maxBitRate * (TOTAL_PRB - averageDLPrb) * 12 * (1 - Math.pow(overHeadForDl, j))) + / averageSymbolDuration) * Math.pow(10, -6); + tempul += ((Math.pow(maxNumOfLayers, j) * Math.pow(maxModulationOrder, j) * Math.pow(scalingFactor, j) + * maxBitRate * (TOTAL_PRB - averageULPrb) * 12 * (1 - Math.pow(overHeadForUl, j))) + / averageSymbolDuration) * Math.pow(10, -6); + j++; + + } + + Integer dLThptPerSliceInMbps = (int) Math.round(tempdl); + Integer uLThptPerSliceInMbps = (int) Math.round(tempul); + AggregatedConfig aggregatedConfig = new AggregatedConfig(); + aggregatedConfig.setDLThptPerSlice(dLThptPerSliceInMbps); + aggregatedConfig.setULThptPerSlice(uLThptPerSliceInMbps); + return aggregatedConfig; + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java index d802f81d..b4e06896 100644 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessor.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ * ============LICENSE_END========================================================= * *******************************************************************************/ + package org.onap.slice.analysis.ms.service; import java.util.ArrayList; @@ -29,9 +30,9 @@ import java.util.Objects; import javax.annotation.PostConstruct; -import org.onap.slice.analysis.ms.configdb.AaiInterface; -import org.onap.slice.analysis.ms.configdb.CpsInterface; +import org.onap.slice.analysis.ms.aai.AaiInterface; import org.onap.slice.analysis.ms.configdb.IConfigDbService; +import org.onap.slice.analysis.ms.cps.CpsInterface; import org.onap.slice.analysis.ms.models.Configuration; import org.onap.slice.analysis.ms.models.MeasurementObject; import org.onap.slice.analysis.ms.models.SubCounter; @@ -48,201 +49,201 @@ import org.springframework.stereotype.Component; @Component @Scope("prototype") public class SnssaiSamplesProcessor { - private static Logger log = LoggerFactory.getLogger(SnssaiSamplesProcessor.class); - - @Autowired - private PolicyService policyService; - - @Autowired - private IConfigDbService configDbService; - - @Autowired - private PmDataQueue pmDataQueue; - - @Autowired - private AverageCalculator averageCalculator; - - @Autowired - private AaiInterface aaiInterface; - - @Autowired - private CpsInterface cpsInterface; - - private List<MeasurementObject> snssaiMeasurementList = new ArrayList<>(); - private Map<String, List<String>> ricToCellMapping = new HashMap<>(); - private Map<String, Map<String, Integer>> ricToPrbsMapping = new HashMap<>(); - private Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); - private int noOfSamples; - private List<String> pmsToCompute; - private Map<String, String> prbThroughputMapping = new HashMap<>(); - private int minPercentageChange; - - @PostConstruct - public void init() { - Configuration configuration = Configuration.getInstance(); - noOfSamples = configuration.getSamples(); - pmsToCompute = new ArrayList<>(); - pmsToCompute.add("PrbUsedDl"); - pmsToCompute.add("PrbUsedUl"); - prbThroughputMapping = new HashMap<>(); - prbThroughputMapping.put("PrbUsedDl", "dLThptPerSlice"); - prbThroughputMapping.put("PrbUsedUl", "uLThptPerSlice"); - minPercentageChange = configuration.getMinPercentageChange(); + private static Logger log = LoggerFactory.getLogger(SnssaiSamplesProcessor.class); + + @Autowired + private PolicyService policyService; + + @Autowired + private IConfigDbService configDbService; + + @Autowired + private PmDataQueue pmDataQueue; + + @Autowired + private AverageCalculator averageCalculator; + + @Autowired + private AaiInterface aaiInterface; + + @Autowired + private CpsInterface cpsInterface; + + private List<MeasurementObject> snssaiMeasurementList = new ArrayList<>(); + private Map<String, List<String>> ricToCellMapping = new HashMap<>(); + private Map<String, Map<String, Integer>> ricToPrbsMapping = new HashMap<>(); + private Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); + private int noOfSamples; + private List<String> pmsToCompute; + private Map<String, String> prbThroughputMapping = new HashMap<>(); + private int minPercentageChange; + + @PostConstruct + public void init() { + Configuration configuration = Configuration.getInstance(); + noOfSamples = configuration.getSamples(); + pmsToCompute = new ArrayList<>(); + pmsToCompute.add("PrbUsedDl"); + pmsToCompute.add("PrbUsedUl"); + prbThroughputMapping = new HashMap<>(); + prbThroughputMapping.put("PrbUsedDl", "dLThptPerSlice"); + prbThroughputMapping.put("PrbUsedUl", "uLThptPerSlice"); + minPercentageChange = configuration.getMinPercentageChange(); + } + + /** + * process the measurement data of an S-NSSAI + */ + public boolean processSamplesOfSnnsai(String snssai, List<String> networkFunctions) { + Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true + : Configuration.getInstance().getConfigDbEnabled(); + List<MeasurementObject> sample = null; + List<List<MeasurementObject>> samples = null; + Map<String, String> serviceDetails = null; + log.info("Network Functions {} of snssai {}", networkFunctions, snssai); + for (String nf : networkFunctions) { + log.debug("Average of samples for {}:", snssai); + samples = pmDataQueue.getSamplesFromQueue(new SubCounter(nf, snssai), noOfSamples); + if (samples != null) { + sample = averageCalculator.findAverageOfSamples(samples); + addToMeasurementList(sample); + } else { + log.info("Not enough samples present for nf {}", nf); + return false; + } } - - /** - * process the measurement data of an S-NSSAI - */ - public boolean processSamplesOfSnnsai(String snssai, List<String> networkFunctions) { - Boolean isConfigDbEnabled = (Objects.isNull(Configuration.getInstance().getConfigDbEnabled())) ? true - : Configuration.getInstance().getConfigDbEnabled(); - List<MeasurementObject> sample = null; - List<List<MeasurementObject>> samples = null; - Map<String, String> serviceDetails =null; - log.info("Network Functions {} of snssai {}", networkFunctions, snssai); - for (String nf : networkFunctions) { - log.debug("Average of samples for {}:", snssai); - samples = pmDataQueue.getSamplesFromQueue(new SubCounter(nf, snssai), noOfSamples); - if (samples != null) { - sample = averageCalculator.findAverageOfSamples(samples); - addToMeasurementList(sample); - } else { - log.info("Not enough samples present for nf {}", nf); - return false; - } - } - log.info("snssai measurement list {}", snssaiMeasurementList); - Map<String, Map<String, Object>> ricConfiguration; - Map<String, Integer> sliceConfiguration; - if (isConfigDbEnabled) { - ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai); - ricConfiguration = configDbService.fetchCurrentConfigurationOfRIC(snssai); - sliceConfiguration = configDbService.fetchCurrentConfigurationOfSlice(snssai); - serviceDetails = configDbService.fetchServiceDetails(snssai); - } else { - ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai); - ricConfiguration = cpsInterface.fetchCurrentConfigurationOfRIC(snssai); - serviceDetails = aaiInterface.fetchServiceDetails(snssai); - sliceConfiguration = aaiInterface.fetchCurrentConfigurationOfSlice(snssai); - } - log.info("RIC to Cell Mapping for {} S-NSSAI: {}", snssai, ricToCellMapping); - log.info("RIC Configuration {} and Slice Configuration {}", ricConfiguration, sliceConfiguration); - pmsToCompute.forEach(pm -> { - log.debug("processing for pm {}", pm); - sumOfPrbsAcrossCells(pm); - int sum = computeSum(pm); - computeThroughput(sliceConfiguration, sum, pm); - calculatePercentageChange(ricConfiguration, prbThroughputMapping.get(pm)); - }); - updateConfiguration(); - if (ricToThroughputMapping.size() > 0) { - AdditionalProperties<Map<String, List<Map<String, Integer>>>> addProps = new AdditionalProperties<>(); - addProps.setResourceConfig(getChangedRIConfigFormat(ricToThroughputMapping)); - policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails); - } - return true; + log.info("snssai measurement list {}", snssaiMeasurementList); + Map<String, Map<String, Object>> ricConfiguration; + Map<String, Integer> sliceConfiguration; + if (isConfigDbEnabled) { + ricToCellMapping = configDbService.fetchRICsOfSnssai(snssai); + ricConfiguration = configDbService.fetchCurrentConfigurationOfRIC(snssai); + sliceConfiguration = configDbService.fetchCurrentConfigurationOfSlice(snssai); + serviceDetails = configDbService.fetchServiceDetails(snssai); + } else { + ricToCellMapping = cpsInterface.fetchRICsOfSnssai(snssai); + ricConfiguration = cpsInterface.fetchCurrentConfigurationOfRIC(snssai); + serviceDetails = aaiInterface.fetchServiceDetails(snssai); + sliceConfiguration = aaiInterface.fetchCurrentConfigurationOfSlice(snssai); } - - /** - * change the RICConfig data format to be compatible with SDN-R - */ - protected Map<String, List<Map<String, Integer>>> getChangedRIConfigFormat( - Map<String, Map<String, Integer>> ricToThroughputMapping) { - Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator(); - Map.Entry<String, Map<String, Integer>> entry = null; - List<Map<String, Integer>> ricConfigList = new ArrayList<>(); - Map<String, List<Map<String, Integer>>> ricConfigData = new HashMap<>(); - while (it.hasNext()) { - Map<String, Integer> newConfigMap = new HashMap<>(); - entry = it.next(); - newConfigMap = entry.getValue(); - newConfigMap.put("nearRTRICId", Integer.parseInt(entry.getKey())); - ricConfigList.add(newConfigMap); - } - ricConfigData.put("data", ricConfigList); - return ricConfigData; + log.info("RIC to Cell Mapping for {} S-NSSAI: {}", snssai, ricToCellMapping); + log.info("RIC Configuration {} and Slice Configuration {}", ricConfiguration, sliceConfiguration); + pmsToCompute.forEach(pm -> { + log.debug("processing for pm {}", pm); + sumOfPrbsAcrossCells(pm); + int sum = computeSum(pm); + computeThroughput(sliceConfiguration, sum, pm); + calculatePercentageChange(ricConfiguration, prbThroughputMapping.get(pm)); + }); + updateConfiguration(); + if (ricToThroughputMapping.size() > 0) { + AdditionalProperties<Map<String, List<Map<String, Integer>>>> addProps = new AdditionalProperties<>(); + addProps.setResourceConfig(getChangedRIConfigFormat(ricToThroughputMapping)); + policyService.sendOnsetMessageToPolicy(snssai, addProps, serviceDetails); } - - /** - * process the measurement data of an S-NSSAI - */ - protected void updateConfiguration() { - Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator(); - Map.Entry<String, Map<String, Integer>> entry = null; - while (it.hasNext()) { - entry = it.next(); - if (entry.getValue().size() == 0) { - it.remove(); - } - } + return true; + } + + /** + * change the RICConfig data format to be compatible with SDN-R + */ + protected Map<String, List<Map<String, Integer>>> getChangedRIConfigFormat( + Map<String, Map<String, Integer>> ricToThroughputMapping) { + Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator(); + Map.Entry<String, Map<String, Integer>> entry = null; + List<Map<String, Integer>> ricConfigList = new ArrayList<>(); + Map<String, List<Map<String, Integer>>> ricConfigData = new HashMap<>(); + while (it.hasNext()) { + Map<String, Integer> newConfigMap = new HashMap<>(); + entry = it.next(); + newConfigMap = entry.getValue(); + newConfigMap.put("nearRTRICId", Integer.parseInt(entry.getKey())); + ricConfigList.add(newConfigMap); } - - private void addToMeasurementList(List<MeasurementObject> sample) { - snssaiMeasurementList.addAll(sample); + ricConfigData.put("data", ricConfigList); + return ricConfigData; + } + + /** + * process the measurement data of an S-NSSAI + */ + protected void updateConfiguration() { + Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator(); + Map.Entry<String, Map<String, Integer>> entry = null; + while (it.hasNext()) { + entry = it.next(); + if (entry.getValue().size() == 0) { + it.remove(); + } } - - /** - * Calculate the change in the configuration value and keep the configuration - * only if it is greater than a specific limit - */ - protected void calculatePercentageChange(Map<String, Map<String, Object>> ricConfiguration, String pm) { - Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator(); - Map.Entry<String, Map<String, Integer>> entry = null; - float existing = 0; - float change = 0; - while (it.hasNext()) { - entry = it.next(); - existing = (float) ((int) ricConfiguration.get(entry.getKey()).get(pm)); - change = ((Math.abs(entry.getValue().get(pm) - existing)) / existing) * 100; - if (change <= minPercentageChange) { - ricToThroughputMapping.get(entry.getKey()).remove(pm); - log.info("Removing pm data {} for RIC {}", pm, entry.getKey()); - } - } + } + + private void addToMeasurementList(List<MeasurementObject> sample) { + snssaiMeasurementList.addAll(sample); + } + + /** + * Calculate the change in the configuration value and keep the configuration + * only if it is greater than a specific limit + */ + protected void calculatePercentageChange(Map<String, Map<String, Object>> ricConfiguration, String pm) { + Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToThroughputMapping.entrySet().iterator(); + Map.Entry<String, Map<String, Integer>> entry = null; + float existing = 0; + float change = 0; + while (it.hasNext()) { + entry = it.next(); + existing = (float) ((int) ricConfiguration.get(entry.getKey()).get(pm)); + change = ((Math.abs(entry.getValue().get(pm) - existing)) / existing) * 100; + if (change <= minPercentageChange) { + ricToThroughputMapping.get(entry.getKey()).remove(pm); + log.info("Removing pm data {} for RIC {}", pm, entry.getKey()); + } } - - protected void sumOfPrbsAcrossCells(String pmName) { - ricToCellMapping.forEach((ric, cells) -> { - int sumOfPrbs = 0; - for (String cell : cells) { - int index = MeasurementObject.findIndex(cell, snssaiMeasurementList); - sumOfPrbs += snssaiMeasurementList.get(index).getPmData().get(pmName); - } - if (ricToPrbsMapping.containsKey(ric)) { - ricToPrbsMapping.get(ric).put(pmName, sumOfPrbs); - } else { - Map<String, Integer> pmToPrbMapping = new HashMap<>(); - pmToPrbMapping.put(pmName, sumOfPrbs); - ricToPrbsMapping.put(ric, pmToPrbMapping); - } - }); - log.info("PRBs sum computed for RIC {}", ricToPrbsMapping); - } - - protected Integer computeSum(String pm) { - return ricToPrbsMapping.entrySet().stream().map(x -> x.getValue().get(pm)).reduce(0, Integer::sum); - } - - protected void computeThroughput(Map<String, Integer> sliceConfiguration, int sum, String pm) { - Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToPrbsMapping.entrySet().iterator(); - Map.Entry<String, Map<String, Integer>> entry = null; - Map<String, Integer> throughtputMap = null; - String ric = ""; - int value = 0; - while (it.hasNext()) { - entry = it.next(); - ric = entry.getKey(); - value = Math.round(((float) entry.getValue().get(pm) / sum) - * (float) sliceConfiguration.get(prbThroughputMapping.get(pm))); - if (ricToThroughputMapping.containsKey(ric)) { - ricToThroughputMapping.get(ric).put(prbThroughputMapping.get(pm), value); - } else { - throughtputMap = new HashMap<>(); - throughtputMap.put(prbThroughputMapping.get(pm), value); - ricToThroughputMapping.put(ric, throughtputMap); - } - } - log.info("Throughput computed for RIC {}", ricToThroughputMapping); + } + + protected void sumOfPrbsAcrossCells(String pmName) { + ricToCellMapping.forEach((ric, cells) -> { + int sumOfPrbs = 0; + for (String cell : cells) { + int index = MeasurementObject.findIndex(cell, snssaiMeasurementList); + sumOfPrbs += snssaiMeasurementList.get(index).getPmData().get(pmName); + } + if (ricToPrbsMapping.containsKey(ric)) { + ricToPrbsMapping.get(ric).put(pmName, sumOfPrbs); + } else { + Map<String, Integer> pmToPrbMapping = new HashMap<>(); + pmToPrbMapping.put(pmName, sumOfPrbs); + ricToPrbsMapping.put(ric, pmToPrbMapping); + } + }); + log.info("PRBs sum computed for RIC {}", ricToPrbsMapping); + } + + protected Integer computeSum(String pm) { + return ricToPrbsMapping.entrySet().stream().map(x -> x.getValue().get(pm)).reduce(0, Integer::sum); + } + + protected void computeThroughput(Map<String, Integer> sliceConfiguration, int sum, String pm) { + Iterator<Map.Entry<String, Map<String, Integer>>> it = ricToPrbsMapping.entrySet().iterator(); + Map.Entry<String, Map<String, Integer>> entry = null; + Map<String, Integer> throughtputMap = null; + String ric = ""; + int value = 0; + while (it.hasNext()) { + entry = it.next(); + ric = entry.getKey(); + value = Math.round(((float) entry.getValue().get(pm) / sum) + * (float) sliceConfiguration.get(prbThroughputMapping.get(pm))); + if (ricToThroughputMapping.containsKey(ric)) { + ricToThroughputMapping.get(ric).put(prbThroughputMapping.get(pm), value); + } else { + throughtputMap = new HashMap<>(); + throughtputMap.put(prbThroughputMapping.get(pm), value); + ricToThroughputMapping.put(ric, throughtputMap); + } } + log.info("Throughput computed for RIC {}", ricToThroughputMapping); + } } diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/BandwidthEvaluator.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/BandwidthEvaluator.java new file mode 100644 index 00000000..c5e3151a --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/BandwidthEvaluator.java @@ -0,0 +1,213 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +import lombok.NonNull; +import org.onap.slice.analysis.ms.aai.AaiService; + +import org.onap.slice.analysis.ms.models.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * This class implements the CCVPN PM Closed-loop logical function. + * A simple actor model design is implemented here. + */ +@Component +public class BandwidthEvaluator { + private static Logger log = LoggerFactory.getLogger(BandwidthEvaluator.class); + private Configuration configuration; + + @Autowired + StrategyFactory strategyFactory; + + private Loop evaluationEventLoop; + + private static final Event KILL_PILL = new SimpleEvent(null, 0); + private static final int DEFAULT_EVAL_INTERVAL = 5; + private static final String DEFAULT_STRATEGY_NAME = "FixedUpperBoundStrategy"; + /** + * Interval of each round of evaluation, defined in config_all.json + */ + private static int evaluationInterval; + + /** + * Bandwidth Evaluation and adjustment strategy. + */ + private static String strategyName; + + private final ScheduledExecutorService executorPool = Executors.newScheduledThreadPool(1); + + /** + * Initialize and start the bandwidth evaluator process, schedule a periodic service bandwidth usage check + */ + @PostConstruct + public void init() { + loadConfig(); + strategyName = (strategyName != null)? strategyName : DEFAULT_STRATEGY_NAME; + evaluationInterval = (evaluationInterval == 0)? DEFAULT_EVAL_INTERVAL : evaluationInterval; + EvaluationStrategy strategy = strategyFactory.getStrategy(strategyName); + log.info("{} is utilized as the bandwidth evaluatior strategy", strategyName); + + /** + * Evalution main loop + */ + evaluationEventLoop = new Loop("EvaluationLoop"){ + @Override + public void process(Event event) { + strategy.execute(event); + } + }; + + scheduleEvaluation(); + } + + /** + * Stop the bandwidth evaluator process including two actors and periodic usage check + */ + @PreDestroy + public void stop(){ + stopScheduleEvaluation(); + evaluationEventLoop.stop(); + } + + /** + * Start to schedule periodic usage check at fixed rate + */ + private void scheduleEvaluation(){ + executorPool.scheduleAtFixedRate(new Runnable() { + @Override + public void run() { + post(new SimpleEvent(SimpleEvent.Type.PERIODIC_CHECK, 1)); + } + }, 0, (evaluationInterval == 0? DEFAULT_EVAL_INTERVAL : evaluationInterval), TimeUnit.SECONDS); + } + + /** + * Stop periodic bandwidth usage check + */ + private void stopScheduleEvaluation(){ + executorPool.shutdownNow(); + } + + /** + * Post/broadcast event between Loops + * @param event event object + */ + public void post(@NonNull Event event){ + log.info("A new event triggered, type: {}, subject: {}, at time: {}", + event.type(), event.subject(), event.time()); + if (event.type() == SimpleEvent.Type.PERIODIC_CHECK) { + evaluationEventLoop.add(event); + } else if (event.type() == SimpleEvent.Type.ONDEMAND_CHECK) { + evaluationEventLoop.add(event); + } + } + + // update configuration + private void loadConfig() { + configuration = Configuration.getInstance(); + evaluationInterval = configuration.getCcvpnEvalInterval(); + strategyName = configuration.getCcvpnEvalStrategy(); + log.info("Evaluation loop configs has been loaded. Strategy {}.", strategyName); + } + + /** + * Inner loop implementation. Each loop acts like an actor. + */ + private abstract class Loop implements Runnable { + private final String name; + private volatile boolean running; + private final BlockingQueue<Event> eventsQueue; + private final ExecutorService executor; + private volatile Future<?> dispatchFuture; + + /** + * Constructor that accepts a loop name + * @param name name of this loop + */ + Loop(String name){ + this.name = name; + executor = Executors.newSingleThreadExecutor(); + eventsQueue = new LinkedBlockingQueue<>(); + dispatchFuture = executor.submit(this); + } + + /** + * Add new event to this loop + * @param evt Event + * @return true + */ + public boolean add(Event evt) { + return eventsQueue.add(evt); + } + + /** + * Running loop that process event accordingly + */ + @Override + public void run(){ + running = true; + log.info("BandwidthEvaluator -- {} initiated", this.name); + while (running){ + try{ + Event event = eventsQueue.take(); + if (event == KILL_PILL){ + break; + } + process(event); + } catch (InterruptedException e){ + log.warn("Process loop interrupted"); + } catch (Exception | Error e){ + log.warn("Process loop hit an error {}", e.getMessage()); + } + } + } + + /** + * Operation defined by subclass for different event processing + * @param event incoming event + */ + abstract public void process(Event event); + + /** + * Stop this loop + */ + public void stop(){ + running = false; + add(KILL_PILL); + } + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/CCVPNPmDatastore.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/CCVPNPmDatastore.java new file mode 100644 index 00000000..3e6c4746 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/CCVPNPmDatastore.java @@ -0,0 +1,377 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import lombok.Getter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.ArrayDeque; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * This class represents the data structure for storing the CCVPN pm data; + */ +@Component +public class CCVPNPmDatastore { + + private static Logger log = LoggerFactory.getLogger(CCVPNPmDatastore.class); + private static final Pattern pattern = Pattern.compile("([0-9.]+)\\s*(kb|Kb|mb|Mb|Gb|gb)*"); + private static final int WINDOW_SIZE = 5; + @Getter + private final ConcurrentMap<String, ServiceState> svcStatus = new ConcurrentHashMap<>(); + // Provisioned bandwidth of each endpoint + @Getter + private final ConcurrentMap<String, Integer> endpointToProvBw = new ConcurrentHashMap<>(); + // Max bandwidth (upper-bound) of each endpoint + @Getter + private final ConcurrentMap<String, Integer> upperBoundBw = new ConcurrentHashMap<>(); + // Current bandwidth usage data list from customers + @Getter + private final ConcurrentMap<Endpointkey, EvictingQueue<Integer>> endpointToUsedBw = new ConcurrentHashMap<>(); + // Original bandwidth of each endpoint + @Getter + private final ConcurrentMap<String, Integer> endpointToOriginalBw = new ConcurrentHashMap<>(); + // Assurance Status of each endpoint + @Getter + private final ConcurrentMap<String, Boolean> closedLoopBwAssuranceStatus = new ConcurrentHashMap<>(); + + /** + * Given a cllId, return a map between Endpointkey and their corresponding UsedBw Queue. + * All Endpoints belongs to this same service + * @param cllId target cll instance id + * @return a filtered map contains used bandwidth data of endpointkeys whose cllId equals to the given one. + */ + public Map<Endpointkey, EvictingQueue<Integer>> getUsedBwOfSvc(String cllId){ + return endpointToUsedBw.entrySet().stream() + .filter(map -> map.getKey().getCllId() == cllId) + .collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue())); + } + + /** + * Return the complete used bandwidth map. + * @return a complete endpoint to bandwidth data map + */ + public Map<Endpointkey, EvictingQueue<Integer>> getUsedBwMap(){ + return endpointToUsedBw; + } + + /** + * Return provisioned bandwidth of cll service. If provisioned bandwidth is null or missing, return 0; + * @param cllId target cll instance id + * @return Integer bandwidth value + */ + public Integer getProvBwOfSvc(String cllId){ + return endpointToProvBw.getOrDefault(cllId, 0); + } + + /** + * Get Service status of this cll service + * @param cllId target cll instance id + * @return ServiceState of this cll + */ + public ServiceState getStatusOfSvc(String cllId){ + return svcStatus.getOrDefault(cllId, ServiceState.UNKNOWN); + } + + /** + * If ccvpn flexible threshold is on, then bandwidth can be assured within scope. + * @param cllId + * @return + */ + public Integer getUpperBoundBwOfSvc(String cllId){ + return upperBoundBw.getOrDefault(cllId, Integer.MAX_VALUE); + } + + /** + * Get closed loop check status of this cll service + * @param cllId + * @return + */ + public Boolean getClosedloopStatus(String cllId){ + return closedLoopBwAssuranceStatus.getOrDefault(cllId,true); + } + + public int getOriginalBw(String cllId) { + return endpointToOriginalBw.getOrDefault(cllId, 0); + } + + + /** + * return the complete map of cll service status + * @return complete map of serviceStatusMap + */ + public ConcurrentMap<String, ServiceState> getSvcStatusMap(){ + return svcStatus; + } + + /** + * Override the service status to provided state + * @param cllId target cll instance id + * @param state new state + */ + public void updateSvcState(String cllId, ServiceState state){ + svcStatus.put(cllId, state); + } + + /** + * Update provisioned bandwidth value to given bandwidth string + * @param cllId target cll instance id + * @param bw new bandwidth + */ + public void updateProvBw(String cllId, String bw){ + double bwvvaldb = Double.parseDouble(bw); + int bwvval = (int) bwvvaldb; + updateProvBw(cllId, bwvval, false); + } + + /** + * Update the status, whether close loop bw modification of this cll service is on. + * @param cllId + * @param status + */ + public void updateClosedloopStatus(String cllId, Boolean status){ + closedLoopBwAssuranceStatus.put(cllId, status); + } + + /** + * Update cll original bw, which will not influenced by closed loop bw assurance + * @param cllId + * @param originalBw + */ + public void updateOriginalBw(String cllId, int originalBw){ + endpointToOriginalBw.put(cllId, originalBw); + } + + /** + * Update runtime configurations; + * @param cllId + * @param closedLoopBwAssuranceStatus + * @param originalBw + */ + public void updateConfigFromPolicy(String cllId, Boolean closedLoopBwAssuranceStatus, int originalBw) { + updateClosedloopStatus(cllId, closedLoopBwAssuranceStatus); + updateOriginalBw(cllId, originalBw); + } + + /** + * Update upper bound bandwidth value to given bandwidth + * @param cllId target cll instance id + * @param bw new bandwidth + */ + public void updateUpperBoundBw(String cllId, int bw){ + upperBoundBw.put(cllId, bw); + } + + /** + * Update local service related variables in case cll is deleted. + * @param allValidCllInstances + */ + public void updateCllInstances(Set<String> allValidCllInstances){ + Set<String> invalidCllIds; + invalidCllIds= filterInvalidCllIds(allValidCllInstances, svcStatus.keySet()); + for(String invalidCllId : invalidCllIds) { + log.debug("drop {} from endpointToUsedBw", invalidCllId); + endpointToUsedBw.entrySet().stream().dropWhile(map -> map.getKey().getCllId().equalsIgnoreCase(invalidCllId)); + Iterator<Map.Entry<Endpointkey, EvictingQueue<Integer>>> iterator = endpointToUsedBw.entrySet().iterator(); + while(iterator.hasNext()) { + Endpointkey endpointkey = iterator.next().getKey(); + if(endpointkey.getCllId().equalsIgnoreCase(invalidCllId)) { + endpointToUsedBw.remove(endpointkey); + } + } + } + svcStatus.keySet().removeAll(invalidCllIds); + invalidCllIds = filterInvalidCllIds(allValidCllInstances, endpointToProvBw.keySet()); + endpointToProvBw.keySet().removeAll(invalidCllIds); + invalidCllIds = filterInvalidCllIds(allValidCllInstances, upperBoundBw.keySet()); + upperBoundBw.keySet().removeAll(invalidCllIds); + invalidCllIds = filterInvalidCllIds(allValidCllInstances, endpointToOriginalBw.keySet()); + endpointToOriginalBw.keySet().removeAll(invalidCllIds); + invalidCllIds = filterInvalidCllIds(allValidCllInstances, closedLoopBwAssuranceStatus.keySet()); + closedLoopBwAssuranceStatus.keySet().removeAll(invalidCllIds); + } + + /** + * Filter out cllId to be deleted + * @param allValidCllInstances + * @param currentCllInstances + * @return + */ + public Set<String> filterInvalidCllIds(Set<String> allValidCllInstances, Set<String> currentCllInstances) { + Set<String> invalidCllInstances = new HashSet<>(currentCllInstances); + invalidCllInstances.removeAll(allValidCllInstances); + return invalidCllInstances; + } + + /** + * Update provisioned bandwidth to given bandwidth value; + * if @param{override} is false, only write the bandwidth if it is absent. + * Otherwise override the old value no matter if it exists or not + * Also, when @param{override} is true, compare the provided value with the old value, if equals, return false; + * otherwise, return true; + * @param cllId target cll instance id + * @param bw new bandwidth int value in Mbps + * @param override override old value or not + * @return whether bandwidth value is changed or not. + */ + public boolean updateProvBw(String cllId, int bw, boolean override){ + if ( endpointToProvBw.putIfAbsent(cllId, bw) == null || !override){ + return true; + } else { + if (endpointToProvBw.get(cllId) == bw){ + return false; + } else { + endpointToProvBw.replace(cllId, bw); + return true; + } + } + } + + /** + * Append the latest bandwidth data to associated endpoint + * @param cllId target cll instance id + * @param uniId target uni id + * @param bw latest bandwidth usage data + */ + public void addUsedBwToEndpoint(String cllId, String uniId, String bw){ + Endpointkey enk = new Endpointkey(cllId, uniId); + Matcher matcher = pattern.matcher(bw.trim()); + //Default input bw unit is kbps; + String unit = null; + // Bw in Mbps; + int result = 0; + if (matcher.find()) { + unit = matcher.group(2); + if (unit == null || unit.isEmpty() || unit.toLowerCase().equals("kb")) { + double val = Double.parseDouble(matcher.group(1)); + result = (int) Math.ceil((double) val / (int) 1000 ) ; + } else if (unit.toLowerCase().equals("mb")){ + double val = Double.parseDouble(matcher.group(1)); + result = (int) val ; + } else if (unit.toLowerCase().equals("gb")){ + double val = Double.parseDouble(matcher.group(1)); + result = (int) val * (int) 1000; + } + } else { + log.warn("Illigal bw string: " + bw); + } + + endpointToUsedBw.computeIfAbsent(enk, k -> new EvictingQueue<Integer>(WINDOW_SIZE)).offer(result); + } + + /** + * Copy the used bandwidth queue of specified cllId:uniId to an array and return; + * @param cllId target cll id + * @param uniId target uni id + * @return Object[] contains all the used bandwidth data + */ + public Object[] readToArray(String cllId, String uniId){ + return endpointToUsedBw.get(new Endpointkey(cllId, uniId)).tryReadToArray(); + } + + /** + * Inner data structure is logically similar to circular buffer, thread-safe through blocking + * @param <E> Generic type of data + */ + public class EvictingQueue<E> { + private final Queue<E> delegate; + final int maxSize; + + /** + * Constructor accept a maxsize param + * @param maxSize max size + */ + EvictingQueue(int maxSize){ + if (maxSize < 0){ + throw new IllegalArgumentException("Invalid maxsize for initializing EvictingQueue"); + } + this.delegate = new ArrayDeque<>(maxSize); + this.maxSize = maxSize; + } + + /** + * Adding new data to this queue + * @param e new data + * @return true + */ + public synchronized boolean offer(E e){ + return add(e); + } + + /** + * Try copy data to an array and return, only if data has filled up the whole queue + * Otherwise, return null + * @return the data array + */ + public synchronized Object[] tryReadToArray(){ + if (remainingCapacity() > 0){ + return null; + } + return toArray(); + } + + /** + * Return the size of this queue, and number of data added. It is no larger than the max capacity. + * @return int value of output + */ + public int size(){ + return delegate.size(); + } + + /** + * return the remaining capacity of this queue + * @return int value of output + */ + public int remainingCapacity(){ + return maxSize - size(); + } + + private Object[] toArray(){ + return delegate.toArray(); + } + + private boolean add(E e){ + if(null == e){ + throw new IllegalArgumentException("Invalid new item in add method"); + } + if (maxSize == 0){ + return true; + } + if (size() == maxSize){ + delegate.remove(); + } + delegate.add(e); + return true; + } + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/Endpointkey.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/Endpointkey.java new file mode 100644 index 00000000..f6c1a8c1 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/Endpointkey.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +import java.util.Objects; + +/** + * Endpoint key class represents each uni associated with each cll + */ +public class Endpointkey { + + private final String cllId; + private final String uniId; + + /** + * Constructor accpets cllId and uniId. + * @param cllId String cll instance id + * @param uniId String uni id + */ + public Endpointkey(String cllId, String uniId){ + this.cllId = cllId; + this.uniId = uniId; + } + + /** + * Return cllId + * @return String cllId + */ + public String getCllId() { + return cllId; + } + + /** + * Return uniId + * @return String uni id + */ + public String getUniId() { + return uniId; + } + + @Override + public int hashCode() { return Objects.hash(cllId, uniId); } + + @Override + public boolean equals(Object obj){ + if (this == obj){ + return true; + } + if (obj instanceof Endpointkey){ + final Endpointkey other = (Endpointkey) obj; + return Objects.equals(this.cllId, other.cllId) && + Objects.equals(this.uniId, other.uniId); + } + return false; + } + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/EvaluationStrategy.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/EvaluationStrategy.java new file mode 100644 index 00000000..7d502894 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/EvaluationStrategy.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +public interface EvaluationStrategy { + + /** + * Defined strategy logic to deal with different events + * @param event + */ + void execute(Event event); + + /** + * Return name of this strategy + * @return name + */ + String getName(); +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/Event.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/Event.java new file mode 100644 index 00000000..c36e4d86 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/Event.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +/** + * Event (CCVPN) interface; + * It is the message entity inside CCVPN Closed-loop. + * @param <T> message type + * @param <S> message paylaod + */ +public interface Event<T extends Enum, S> { + + long time(); + + T type(); + + S subject(); + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategy.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategy.java new file mode 100644 index 00000000..66dc6dc0 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategy.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +import com.google.gson.JsonObject; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.service.PolicyService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.Arrays; +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; + +/** + * Threshold strategy can be configured via configuration + * If "sliceanalysisms.ccvpnEvalStrategy" is set to "FixedUpperBoundStrategy", then this class is triggered. + */ +@Component +public class FixedUpperBoundStrategy implements EvaluationStrategy{ + private static Logger log = LoggerFactory.getLogger(FixedUpperBoundStrategy.class); + private Configuration configuration; + + private static final String TYPE_NAME = "FixedUpperBoundStrategy"; + private static final String SERVICE_INSTANCE_LOCATION_ID = "service-instance-location-id"; + private static final String BANDWIDTH_TOTAL = "bandwidth-total"; + + /** + * Percentage threshold of bandwidth adjustment. + */ + private static double upperThreshold; + + /** + * Precision of bandwidth evaluation and adjustment. + */ + private static double precision; // in Mbps; + + @Autowired + NetworkPolicyMonitor networkPolicyMonitor; + + @Autowired + CCVPNPmDatastore ccvpnPmDatastore; + + @Autowired + PolicyService policyService; + + @PostConstruct + public void init() { + loadConfig(); + } + + /** + * Periodically ensure endpoint bw adjustment is under assurance. + * This method will be invoked when FixedUpperBoundStrategy is set. + * @param event + */ + @Override + public void execute(Event event){ + if (event.type() == SimpleEvent.Type.PERIODIC_CHECK && isPeriodicCheckOn()){ + log.debug("=== Processing new periodic check request: {} ===", event.time()); + Map<Endpointkey, CCVPNPmDatastore.EvictingQueue<Integer>> usedBwMap = ccvpnPmDatastore.getUsedBwMap(); + Map<String, Integer> candidate = new TreeMap<>(); + for(Map.Entry<Endpointkey, CCVPNPmDatastore.EvictingQueue<Integer>> entry: usedBwMap.entrySet()) { + String serviceId = entry.getKey().getCllId(); + Object[] usedBws = entry.getValue().tryReadToArray(); + + if (!ccvpnPmDatastore.getClosedloopStatus(serviceId)) { + log.info("CCVPN Evaluator Output: service {}, closed loop bw modification is off.", serviceId); + continue; + } + if (usedBws == null) { + // No enough data for evaluating + log.info("CCVPN Evaluator Output: service {}, not enough data to evaluate", serviceId); + continue; + } + if (ccvpnPmDatastore.getProvBwOfSvc(serviceId) == 0) { + // Max bandwidth not cached yet + log.info("CCVPN Evaluator Output: service {}, max bandwidth not cached, wait for next round", serviceId); + post(new SimpleEvent(SimpleEvent.Type.AAI_BW_REQ, serviceId)); + continue; + } + double avg = Arrays.stream(usedBws) + .mapToInt(o -> (int) o) + .summaryStatistics() + .getAverage(); + int provBw = ccvpnPmDatastore.getProvBwOfSvc(serviceId); + int upperBw = ccvpnPmDatastore.getUpperBoundBwOfSvc(serviceId); + if (needAdjust(serviceId, avg, provBw, upperBw)) { + int newBw = needAdjustTo(serviceId, avg, provBw, upperBw); + if(Math.abs(newBw - provBw) >= precision){ + log.info("CCVPN Evaluator Output: service {}, need adjustment, putting into candidate list", serviceId); + candidate.put(serviceId, newBw); + } + } + } + // check svc under maintenance + Map<String , ServiceState> svcUnderMaintenance = getServicesUnderMaintenance(); + for (Map.Entry<String, ServiceState> entry: svcUnderMaintenance.entrySet()){ + candidate.putIfAbsent(entry.getKey(), 0); + } + // fetch the provisioned bandwidth info if underMaintenance; otherwise send modification request + for(Map.Entry<String, Integer> entry: candidate.entrySet()) { + //still doing adjustment + String cllId = entry.getKey(); + Integer newBw = entry.getValue(); + if(!ccvpnPmDatastore.getClosedloopStatus(cllId)) { + log.info("CCVPN Evaluator Output: service {} is not under closed loop assurance", cllId); + continue; + } + if (isServiceUnderMaintenance(cllId)) { + if (newBw == 0){ + log.info("CCVPN Evaluator Output: service {}," + + " is in maintenance state, fetching bandwidth info from AAI", cllId); + } else { + log.info("CCVPN Evaluator Output: candidate {}," + + " need an adjustment, but skipped due to in maintenance state", cllId); + } + post(new SimpleEvent(SimpleEvent.Type.AAI_BW_REQ, cllId)); + continue; + } + //not in the mid of adjustment; we are free to adjust. + log.info("CCVPN Evaluator Output: candidate {}," + + " need an adjustment, sending request to policy", entry.getKey()); + ccvpnPmDatastore.updateSvcState(entry.getKey(), ServiceState.UNDER_MAINTENANCE); + sendModifyRequest(entry.getKey(), newBw, RequestOwner.DCAE); + } + log.debug("=== Processing periodic check complete ==="); + } + if (event.type() == SimpleEvent.Type.ONDEMAND_CHECK && isOnDemandCheckOn()) { + log.info("=== Processing upperbound adjustment request: {} ===", event.time()); + JsonObject payload = (JsonObject) event.subject(); + String serviceId = payload.get(SERVICE_INSTANCE_LOCATION_ID).getAsString(); + int newBandwidth = payload.get(BANDWIDTH_TOTAL).getAsInt(); + log.info("Update service {} bandwidth upperbound to {} ", serviceId, newBandwidth); + ccvpnPmDatastore.updateUpperBoundBw(serviceId, newBandwidth); + log.info("=== Processing upperbound adjustment complete ==="); + } + } + + @Override + public String getName() { + return TYPE_NAME; + } + + /** + * Post/broadcast event to the networkPolicyMonitor + * @param event event object + */ + private void post(Event event){ + networkPolicyMonitor.post(event); + } + + private void loadConfig() { + configuration = Configuration.getInstance(); + upperThreshold = configuration.getCcvpnEvalUpperThreshold(); + precision = configuration.getCcvpnEvalPrecision(); // in Mbps; + } + + private boolean isPeriodicCheckOn() { + configuration = Configuration.getInstance(); + return configuration.isCcvpnEvalPeriodicCheckOn(); + } + + private boolean isOnDemandCheckOn() { + configuration = Configuration.getInstance(); + return configuration.isCcvpnEvalOnDemandCheckOn(); + } + + // send modification requestion + private void sendModifyRequest(String cllId, Integer newBandwidth, RequestOwner owner) { + log.info("Sending modification request to policy. RequestOwner: {} - Service: {} change to bw: {}", + owner, cllId, newBandwidth); + policyService.sendOnsetMessageToPolicy( + policyService.formPolicyOnsetMessageForCCVPN(cllId, newBandwidth, owner) + ); + } + // check if an adjustment is necessary + private boolean needAdjust(String serivceId, double used, int provBandwidth, int upper){ + log.info("CCVPN Service Usage Analysis: usage: {}, threshold: {}, currentProvisioned {}, upperbound {}", + used, upperThreshold, provBandwidth, upper); + return provBandwidth > upper || used > upperThreshold * provBandwidth; + } + + // calculate new bandwidth to accomodate customer + private int needAdjustTo(String serivceId, double used, int cur, int upper){ + if (cur >= upper){ + return upper; + } + int expected = (int) (Math.ceil((used / upperThreshold) * 1.2 / precision) * precision); + return Math.min(expected, upper); + } + // check is service under maint + private boolean isServiceUnderMaintenance(String serivceId) { + return ccvpnPmDatastore.getStatusOfSvc(serivceId) == ServiceState.UNDER_MAINTENANCE; + } + // get a collection of service under maint + private Map<String, ServiceState> getServicesUnderMaintenance(){ + return ccvpnPmDatastore.getSvcStatusMap().entrySet() + .stream() + .filter(e -> e.getValue() == ServiceState.UNDER_MAINTENANCE) + .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue())); + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FlexibleThresholdStrategy.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FlexibleThresholdStrategy.java new file mode 100644 index 00000000..6b552165 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/FlexibleThresholdStrategy.java @@ -0,0 +1,240 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +import com.google.gson.JsonObject; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.service.PolicyService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.Arrays; +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; + +/** + * Threshold strategy can be configured via configuration + * If "sliceanalysisms.ccvpnEvalStrategy" is set to "FlexibleThresholdStrategy", then this class is triggered. + */ +@Component +public class FlexibleThresholdStrategy implements EvaluationStrategy{ + private static Logger log = LoggerFactory.getLogger(FlexibleThresholdStrategy.class); + private Configuration configuration; + private static final String TYPE_NAME = "FlexibleThresholdStrategy"; + private static final String SERVICE_INSTANCE_LOCATION_ID = "service-instance-location-id"; + private static final String BANDWIDTH_TOTAL = "bandwidth-total"; + + /** + * Percentage threshold of bandwidth increase adjustment. + */ + private static double upperThreshold; + + /** + * Percentage threshold of bandwidth decrease adjustment. + */ + private static double lowerThreshold; + + /** + * Precision of bandwidth evaluation and adjustment. + */ + private static double precision; // in Mbps; + + @Autowired + NetworkPolicyMonitor networkPolicyMonitor; + + @Autowired + CCVPNPmDatastore ccvpnPmDatastore; + + @Autowired + PolicyService policyService; + + @PostConstruct + public void init() { + loadConfig(); + } + + /** + * Periodically ensure endpoint bw adjustment is under assurance. + * This method will be invoked when FlexibleThresholdStrategy is set. + * @param event + */ + @Override + public void execute(Event event){ + if (event.type() == SimpleEvent.Type.PERIODIC_CHECK && isPeriodicCheckOn()){ + log.info("=== Processing new periodic check request: {} ===", event.time()); + Map<Endpointkey, CCVPNPmDatastore.EvictingQueue<Integer>> usedBwMap = ccvpnPmDatastore.getUsedBwMap(); + Map<String, Integer> candidate = new TreeMap<>(); + for(Map.Entry<Endpointkey, CCVPNPmDatastore.EvictingQueue<Integer>> entry: usedBwMap.entrySet()) { + String serviceId = entry.getKey().getCllId(); + Object[] usedBws = entry.getValue().tryReadToArray(); + // Judge whether this cll is under closed loop assurance + if (!ccvpnPmDatastore.getClosedloopStatus(serviceId)) { + log.info("CCVPN Evaluator Output: service {}, closed loop bw modification is off.", serviceId); + continue; + } + if (usedBws == null) { + // Not enough data for evaluating + log.info("CCVPN Evaluator Output: service {}, not enough data to evaluate", serviceId); + continue; + } + if (ccvpnPmDatastore.getProvBwOfSvc(serviceId) == 0) { + // Max bandwidth not cached yet + log.info("CCVPN Evaluator Output: service {}, max bandwidth not cached, wait for next round", serviceId); + post(new SimpleEvent(SimpleEvent.Type.AAI_BW_REQ, serviceId)); + continue; + } + double avg = Arrays.stream(usedBws) + .mapToInt(o -> (int) o) + .summaryStatistics() + .getAverage(); + int provBw = ccvpnPmDatastore.getProvBwOfSvc(serviceId); + int originalBw = ccvpnPmDatastore.getOriginalBw(serviceId); + + if(needIncrease(serviceId, avg, provBw)){ + int newBw = (int) (Math.ceil((avg / upperThreshold) * 1.2 / precision) * precision); + log.info("For cll {}, going to increase bw to {}", serviceId, newBw); + candidate.put(serviceId, Math.max(candidate.getOrDefault(serviceId, 0), newBw)); + } else { + if(needDecrease(serviceId, avg, provBw, originalBw)) { + int newBw = Math.max((int) (Math.ceil(provBw * 0.5)), originalBw); + log.info("For cll {}, going to decrease bw to {}", serviceId, newBw); + candidate.put(serviceId, Math.max(candidate.getOrDefault(serviceId, 0), newBw)); + } + } + } + // check svc under maintenance + Map<String , ServiceState> svcUnderMaintenance = getServicesUnderMaintenance(); + for (Map.Entry<String, ServiceState> entry: svcUnderMaintenance.entrySet()){ + candidate.putIfAbsent(entry.getKey(), 0); + } + // fetch the provisioned bandwidth info if underMaintenance; otherwise send modification request + for(Map.Entry<String, Integer> entry: candidate.entrySet()) { + //still doing adjustment + String cllId = entry.getKey(); + Integer newBw = entry.getValue(); + if(!ccvpnPmDatastore.getClosedloopStatus(cllId)) { + log.info("CCVPN Evaluator Output: service {} is not under closed loop assurance", cllId); + continue; + } + if (isServiceUnderMaintenance(cllId)) { + if (newBw == 0){ + log.info("CCVPN Evaluator Output: service {}," + + " is in maintenance state, fetching bandwidth info from AAI", cllId); + } else { + log.info("CCVPN Evaluator Output: candidate {}," + + " need an adjustment, but skipped due to in maintenance state", cllId); + } + post(new SimpleEvent(SimpleEvent.Type.AAI_BW_REQ, cllId)); + continue; + } + //not in the mid of adjustment; we are free to adjust. + log.info("CCVPN Evaluator Output: candidate {}," + + " need an adjustment, sending request to policy, service state changed to under maintenance", entry.getKey()); + ccvpnPmDatastore.updateSvcState(entry.getKey(), ServiceState.UNDER_MAINTENANCE); + sendModifyRequest(entry.getKey(), newBw, RequestOwner.DCAE); + } + log.debug("=== Processing periodic check complete ==="); + } else if (event.type() == SimpleEvent.Type.ONDEMAND_CHECK && isOnDemandCheckOn()) { + log.info("=== Processing upperbound adjustment request: {} ===", event.time()); + JsonObject payload = (JsonObject) event.subject(); + String serviceId = payload.get(SERVICE_INSTANCE_LOCATION_ID).getAsString(); + int newBandwidth = payload.get(BANDWIDTH_TOTAL).getAsInt(); + log.info("Update service {} bandwidth upperbound to {} ", serviceId, newBandwidth); + ccvpnPmDatastore.updateUpperBoundBw(serviceId, newBandwidth); + log.debug("=== Processing upperbound adjustment complete ==="); + } + } + + @Override + public String getName() { + return TYPE_NAME; + } + + /** + * Post/broadcast event to the networkPolicyMonitor + * @param event event object + */ + private void post(Event event){ + networkPolicyMonitor.post(event); + } + + private void loadConfig() { + configuration = Configuration.getInstance(); + upperThreshold = configuration.getCcvpnEvalUpperThreshold(); + lowerThreshold = configuration.getCcvpnEvalLowerThreshold(); + precision = configuration.getCcvpnEvalPrecision(); // in Mbps; + } + + private boolean isPeriodicCheckOn() { + configuration = Configuration.getInstance(); + return configuration.isCcvpnEvalPeriodicCheckOn(); + } + + private boolean isOnDemandCheckOn() { + configuration = Configuration.getInstance(); + return configuration.isCcvpnEvalOnDemandCheckOn(); + } + + // send modification requestion + private void sendModifyRequest(String cllId, Integer newBandwidth, RequestOwner owner) { + log.info("Sending modification request to policy. RequestOwner: {} - Service: {} change to bw: {}", + owner, cllId, newBandwidth); + policyService.sendOnsetMessageToPolicy( + policyService.formPolicyOnsetMessageForCCVPN(cllId, newBandwidth, owner) + ); + } + + private boolean needIncrease(String serviceId, double currAvgUsage, int provBw) { + log.info("For service {} judge whether to increase, currAvg bw {}, maxBw {}", serviceId, currAvgUsage, provBw); + if ( currAvgUsage > upperThreshold * provBw ) { + log.info("decide to increase"); + return true; + } + return false; + } + + private boolean needDecrease(String serviceId, double currAvgUsage, int provBw, int originalBw) { + log.info("For service {} judge whether to decrease, original bw {}, currAvg bw {}, prov {}", serviceId, originalBw, currAvgUsage, provBw); + if( currAvgUsage < lowerThreshold * provBw) { + log.info("decide to decrease"); + return true; + } + return false; + } + + // check is service under maintenance + private boolean isServiceUnderMaintenance(String serivceId) { + return ccvpnPmDatastore.getStatusOfSvc(serivceId) == ServiceState.UNDER_MAINTENANCE; + } + + // get a collection of service under maintenance + private Map<String, ServiceState> getServicesUnderMaintenance(){ + return ccvpnPmDatastore.getSvcStatusMap().entrySet() + .stream() + .filter(e -> e.getValue() == ServiceState.UNDER_MAINTENANCE) + .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue())); + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/NetworkPolicyMonitor.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/NetworkPolicyMonitor.java new file mode 100644 index 00000000..9948804a --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/NetworkPolicyMonitor.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.service.ccvpn; + +import lombok.NonNull; +import org.onap.slice.analysis.ms.aai.AaiService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.Map; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; + +/** + * Actor that processes aai network-policy query request + */ +@Component +public class NetworkPolicyMonitor { + private static Logger log = LoggerFactory.getLogger(NetworkPolicyMonitor.class); + private Loop aaiEventLoop; + private static final Event KILL_PILL = new SimpleEvent(null, 0); + + @Autowired + AaiService aaiService; + + @Autowired + CCVPNPmDatastore ccvpnPmDatastore; + + /** + * Initialize and start the NetworkPolicyMonitor. + */ + @PostConstruct + public void init() { + /** + * AAI data consumer loop + */ + aaiEventLoop = new Loop("AAIEventLoop"){ + @Override + public void process(Event event) { + if (event.type() == SimpleEvent.Type.AAI_BW_REQ){ + log.debug("=== Processing new AAI network policy query at: {} ===", event.time()); + String serviceId = (String) event.subject(); + Map<String, Integer> maxBandwidthData = aaiService.fetchMaxBandwidthOfService(serviceId); + if (maxBandwidthData.get("maxBandwidth") != null){ + log.debug("Successfully retrieved bandwidth info from AAI; service: {}, bandwidth: {}", + serviceId, maxBandwidthData.get("maxBandwidth")); + int bwValue = maxBandwidthData.get("maxBandwidth").intValue(); + if (ccvpnPmDatastore.getProvBwOfSvc(serviceId) == 0){ + ccvpnPmDatastore.updateProvBw(serviceId, bwValue, true); + log.debug("Provision bw of cll {} updated from 0 to {}, max bw is {}", serviceId, ccvpnPmDatastore.getProvBwOfSvc(serviceId), bwValue); + } else if (ccvpnPmDatastore.getProvBwOfSvc(serviceId) != bwValue) { + log.debug("Service modification complete; serviceId: {} update prov bw from {} to {}", serviceId, ccvpnPmDatastore.getProvBwOfSvc(serviceId), bwValue); + ccvpnPmDatastore.updateProvBw(serviceId, bwValue, true); + ccvpnPmDatastore.updateSvcState(serviceId, ServiceState.RUNNING); + log.debug("Service state of {} is changed to running, {}", serviceId, ccvpnPmDatastore.getStatusOfSvc(serviceId)); + } + } + log.debug("=== Processing AAI network policy query complete ==="); + } + } + }; + } + + /** + * Post/broadcast event between Loops + * @param event event object + */ + public void post(@NonNull Event event) { + if (event.type() == SimpleEvent.Type.AAI_BW_REQ) { + aaiEventLoop.add(event); + } + } + /** + * Inner loop implementation. Each loop acts like an actor. + */ + private abstract class Loop implements Runnable { + private final String name; + private volatile boolean running; + private final BlockingQueue<Event> eventsQueue; + private final ExecutorService executor; + private volatile Future<?> dispatchFuture; + + /** + * Constructor that accepts a loop name + * @param name name of this loop + */ + Loop(String name){ + this.name = name; + executor = Executors.newSingleThreadExecutor(); + eventsQueue = new LinkedBlockingQueue<>(); + dispatchFuture = executor.submit(this); + } + + /** + * Add new event to this loop + * @param evt Event + * @return true + */ + public boolean add(Event evt) { + return eventsQueue.add(evt); + } + + /** + * Running loop that process event accordingly + */ + @Override + public void run(){ + running = true; + log.info("NetworkPolicyMonitor -- {} initiated", this.name); + while (running){ + try{ + Event event = eventsQueue.take(); + if (event == KILL_PILL){ + break; + } + process(event); + } catch (InterruptedException e){ + log.warn("Process loop interrupted"); + } catch (Exception | Error e){ + log.warn("Process loop hit an error {}", e.getMessage()); + } + } + } + + /** + * Operation defined by subclass for different event processing + * @param event incoming event + */ + abstract public void process(Event event); + + /** + * Stop this loop + */ + public void stop(){ + running = false; + add(KILL_PILL); + } + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/RequestOwner.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/RequestOwner.java new file mode 100644 index 00000000..319032ad --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/RequestOwner.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.service.ccvpn; + +/** + * Modification request owner + */ +public enum RequestOwner { + DCAE, + UUI +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/ServiceState.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/ServiceState.java new file mode 100644 index 00000000..b4d358f5 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/ServiceState.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +/** + * Enum class represents possible state of a Ethernet service (designed for CCVPN CLL serivce) + */ +public enum ServiceState { + RUNNING, + UNDER_MAINTENANCE, + ERROR, + DELETED, + UNKNOWN +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/SimpleEvent.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/SimpleEvent.java new file mode 100644 index 00000000..8277380d --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/SimpleEvent.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; + +/** + * SimpleEvent a generic class implements Event (CCVPN) interface; + * It is the message entity inside CCVPN Closed-loop + * + * @param <T> message type + * @param <S> message paylaod + */ +public class SimpleEvent<T extends Enum, S> implements Event<T, S> { + private final T type; + private final S subject; + private final long time; + + /** + * All the event types + */ + public enum Type { + PERIODIC_CHECK, + ONDEMAND_CHECK, + AAI_BW_REQ + } + + /** + * Event contructor + * @param type event type + * @param subject event content + */ + public SimpleEvent(T type, S subject) { + this.type = type; + this.subject = subject; + this.time = System.currentTimeMillis(); + } + + /** + * Return the epoch time of this event happened. + * @return long value of epoch time + */ + @Override + public long time() { + return time; + } + + /** + * Return the type of this event. + * @return event type + */ + @Override + public T type() { + return type; + } + + /** + * Return the subject of this event + * @return event content + */ + @Override + public S subject() { + return subject; + } + + /** + * toString method + * @return toString + */ + @Override + public String toString() { + return new StringBuilder() + .append("time " + LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault())) + .append("type " + type()) + .append("subject " + subject()) + .toString(); + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/StrategyFactory.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/StrategyFactory.java new file mode 100644 index 00000000..2feba83d --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/service/ccvpn/StrategyFactory.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class StrategyFactory { + private static Logger log = LoggerFactory.getLogger(StrategyFactory.class); + + @Autowired + public List<EvaluationStrategy> strategies; + + private StrategyFactory() {} + + /** + * Get evulation strategy by name + * @param name evaluationStrategy name + * @return EvaluationStrategy + */ + public EvaluationStrategy getStrategy(String name){ + if (null == name || name.isEmpty()){ + log.error("Empty strategy name provided in config file"); + throw new IllegalArgumentException("Unknown strategy name: " + name); + } + for(EvaluationStrategy s: strategies){ + if(s.getName().equals(name)){ + return s; + } + } + log.error("Unknown strategy name: {}", name); + throw new IllegalArgumentException("Unknown strategy name: " + name); + } +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/utils/DcaeDmaapUtil.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/utils/DcaeDmaapUtil.java new file mode 100644 index 00000000..9a5bf711 --- /dev/null +++ b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/utils/DcaeDmaapUtil.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.utils; + +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.model.streams.dmaap.MessageRouterSink; +import org.onap.dcaegen2.services.sdk.model.streams.dmaap.MessageRouterSource; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.ContentType; +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.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.ImmutableDmaapConnectionPoolConfig; +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.slice.analysis.ms.models.Configuration; + +public class DcaeDmaapUtil { + public static MessageRouterSubscriber buildSubscriber(){ + MessageRouterSubscriberConfig connectionPoolConfiguration = ImmutableMessageRouterSubscriberConfig.builder() + .connectionPoolConfig(ImmutableDmaapConnectionPoolConfig.builder() + .connectionPool(16) + .maxIdleTime(10) //in seconds + .maxLifeTime(20) //in seconds + .build()) + .build(); + + MessageRouterSubscriber cut = DmaapClientFactory.createMessageRouterSubscriber(connectionPoolConfiguration); + return cut; + } + + public static MessageRouterSubscribeRequest buildSubscriberRequest(String name, String topicUrl){ + MessageRouterSource sourceDefinition = ImmutableMessageRouterSource.builder() + .name(name) + .topicUrl(topicUrl) + .build(); + MessageRouterSubscribeRequest request = ImmutableMessageRouterSubscribeRequest.builder() + .consumerGroup("1") + .consumerId("1") + .sourceDefinition(sourceDefinition) + .build(); + + return request; + } + + public static MessageRouterPublisher buildPublisher(){ + MessageRouterPublisher pub = DmaapClientFactory + .createMessageRouterPublisher(MessageRouterPublisherConfig.createDefault()); + return pub; + } + + public static MessageRouterPublishRequest buildPublisherRequest(String name, String topicUrl){ + MessageRouterSink sinkDefinition = ImmutableMessageRouterSink.builder() + .name(name) + .topicUrl(topicUrl) + .build(); + MessageRouterPublishRequest request = ImmutableMessageRouterPublishRequest.builder() + .sinkDefinition(sinkDefinition) + .contentType(ContentType.TEXT_PLAIN) + .build(); + return request; + } + + +} diff --git a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/utils/DmaapUtils.java b/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/utils/DmaapUtils.java deleted file mode 100644 index 6e1cf912..00000000 --- a/components/slice-analysis-ms/src/main/java/org/onap/slice/analysis/ms/utils/DmaapUtils.java +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * slice-analysis-ms - * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. - * ============================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - *******************************************************************************/ - -package org.onap.slice.analysis.ms.utils; - -import com.att.nsa.cambria.client.CambriaBatchingPublisher; -import com.att.nsa.cambria.client.CambriaClient; -import com.att.nsa.cambria.client.CambriaClientBuilders; -import com.att.nsa.cambria.client.CambriaClientBuilders.ConsumerBuilder; -import com.att.nsa.cambria.client.CambriaClientBuilders.PublisherBuilder; -import com.att.nsa.cambria.client.CambriaClientBuilders.TopicManagerBuilder; -import com.att.nsa.cambria.client.CambriaConsumer; -import com.att.nsa.cambria.client.CambriaTopicManager; - -import java.net.MalformedURLException; -import java.security.GeneralSecurityException; - -import org.onap.slice.analysis.ms.models.Configuration; - -/** - * Utility class to perform actions related to Dmaap - */ -public class DmaapUtils { - - /** - * Build publisher. - */ - public CambriaBatchingPublisher buildPublisher(Configuration config, String topic) { - try { - return builder(config, topic).build(); - } catch (MalformedURLException | GeneralSecurityException e) { - return null; - - } - } - - /** - * Build consumer. - */ - public CambriaConsumer buildConsumer(Configuration config, String topic) { - - try { - return builderConsumer(config, topic).build(); - } catch (MalformedURLException | GeneralSecurityException e) { - return null; - } - - } - - private static PublisherBuilder builder(Configuration config, String topic) { - if (config.isSecured()) { - return authenticatedBuilder(config, topic); - } else { - return unAuthenticatedBuilder(config, topic); - } - } - - private static PublisherBuilder authenticatedBuilder(Configuration config, String topic) { - return unAuthenticatedBuilder(config, topic).usingHttps().authenticatedByHttp(config.getAafUsername(), - config.getAafPassword()); - } - - private static PublisherBuilder unAuthenticatedBuilder(Configuration config, String topic) { - return new CambriaClientBuilders.PublisherBuilder().usingHosts(config.getDmaapServers()).onTopic(topic) - .logSendFailuresAfter(5); - } - - private static ConsumerBuilder builderConsumer(Configuration config, String topic) { - if (config.isSecured()) { - return authenticatedConsumerBuilder(config, topic); - } else { - return unAuthenticatedConsumerBuilder(config, topic); - } - } - - private static ConsumerBuilder unAuthenticatedConsumerBuilder(Configuration config, String topic) { - return new CambriaClientBuilders.ConsumerBuilder().usingHosts(config.getDmaapServers()).onTopic(topic) - .knownAs(config.getCg(), config.getCid()).withSocketTimeout(config.getPollingTimeout() * 1000); - } - - private static ConsumerBuilder authenticatedConsumerBuilder(Configuration config, String topic) { - return unAuthenticatedConsumerBuilder(config, topic).usingHttps().authenticatedByHttp(config.getAafUsername(), - config.getAafPassword()); - } - - /** - * Build cambriaClient. - */ - public CambriaTopicManager cambriaCLientBuilder(Configuration configuration) { - if (configuration.isSecured()) { - return authenticatedCambriaCLientBuilder(configuration); - } else { - return unAuthenticatedCambriaCLientBuilder(configuration); - - } - } - - private static CambriaTopicManager authenticatedCambriaCLientBuilder(Configuration config) { - try { - return buildCambriaClient(new TopicManagerBuilder().usingHosts(config.getDmaapServers()) - .authenticatedByHttp(config.getAafUsername(), config.getAafPassword())); - } catch (MalformedURLException | GeneralSecurityException e) { - return null; - } - } - - private static CambriaTopicManager unAuthenticatedCambriaCLientBuilder(Configuration config) { - try { - return buildCambriaClient(new TopicManagerBuilder().usingHosts(config.getDmaapServers())); - } catch (MalformedURLException | GeneralSecurityException e) { - return null; - - } - } - - @SuppressWarnings("unchecked") - private static <T extends CambriaClient> T buildCambriaClient( - CambriaClientBuilders.AbstractAuthenticatedManagerBuilder<? extends CambriaClient> client) - throws MalformedURLException, GeneralSecurityException { - return (T) client.build(); - } - -} diff --git a/components/slice-analysis-ms/src/main/resources/logback.xml b/components/slice-analysis-ms/src/main/resources/logback.xml index 8d79c4ee..134c25dc 100644 --- a/components/slice-analysis-ms/src/main/resources/logback.xml +++ b/components/slice-analysis-ms/src/main/resources/logback.xml @@ -1,32 +1,35 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- +<!-- /******************************************************************************* * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 CTC, Inc. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= - * + * *******************************************************************************/ - --> - <configuration> +--> +<configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern> - %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36}:%line - %msg%n </Pattern> </layout> </appender> diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/aai/AaiInterfaceServiceTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/aai/AaiInterfaceServiceTest.java new file mode 100644 index 00000000..04e2594e --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/aai/AaiInterfaceServiceTest.java @@ -0,0 +1,238 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2021-2022 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.aai; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.collections.MapUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.restclients.AaiRestClient; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(SpringRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@SpringBootTest(classes = AaiInterfaceServiceTest.class) +public class AaiInterfaceServiceTest { + + Configuration configuration = Configuration.getInstance(); + + @InjectMocks + AaiService aaiService; + + @Mock + AaiRestClient restClient; + + @Test + public void fetchCurrentConfigurationOfSlice() throws IOException { + configuration.setAaiUrl("http://aai:30233/aai/v21/business/customers/customer/"); + Map<String, Integer> responsemap = new HashMap<>(); + responsemap.put("dLThptPerSlice", 60); + responsemap.put("uLThptPerSlice", 54); + String serviceInstance = + new String(Files.readAllBytes(Paths.get("src/test/resources/aaiDetailsList.json"))); + Mockito.when(restClient.sendGetRequest(Mockito.anyString(), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstance, HttpStatus.OK)); + assertEquals(responsemap, aaiService.fetchCurrentConfigurationOfSlice("001-010000")); + } + + @Test + public void fetchServiceProfile() throws IOException { + Map<String, String> responseMap = new HashMap<String, String>(); + responseMap.put("sNSSAI", "001-00110"); + responseMap.put("ranNFNSSIId", "4b889f2b-8ee4-4ec7-881f-5b1af8a74039"); + responseMap.put("sliceProfileId", "ab9af40f13f7219099333"); + responseMap.put("globalSubscriberId", "5GCustomer"); + responseMap.put("subscriptionServiceType", "5G"); + String serviceInstance = + new String(Files.readAllBytes(Paths.get("src/test/resources/aaiDetailsList.json"))); + Mockito.when(restClient.sendGetRequest(Mockito.anyString(), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstance, HttpStatus.OK)); + + assertEquals(responseMap, aaiService.fetchServiceDetails("001-00110")); + } + + @Test + public void fetchSubscriberAndSubscriptionServiceTypeTest() throws IOException { + + configuration.setAaiUrl("http://aai:30233/aai/v21"); + Map<String, String> expectedResponse = new HashMap<String, String>(); + expectedResponse.put("globalSubscriberId", "5GCustomer"); + expectedResponse.put("subscriptionServiceType", "5G"); + + String serviceInstance = + new String(Files.readAllBytes(Paths.get("src/test/resources/aaiDetailsList.json"))); + Mockito.when(restClient.sendGetRequest(Mockito.anyString(), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstance, HttpStatus.OK)); + + Map<String, String> actualResponse = aaiService.fetchSubscriberAndSubscriptionServiceType(); + assertEquals(expectedResponse, actualResponse); + } + + @Test + public void fetchSliceProfilesOfAllotedResourceDataTest() throws IOException { + configuration.setAaiUrl("http://aai:30233/aai/v21"); + List<String> allotedResourceList = new ArrayList<>(); + allotedResourceList.add("530d188d-9087-49af-a44a-90c40e0c2d47"); + List<String> expectedResponse = new ArrayList<>(); + expectedResponse.add("b2ae730f-1d5f-495a-8112-dac017a7348c"); + expectedResponse.add("cad8fa36-2d55-4c12-a92e-1bd551517a0c"); + expectedResponse.add("8d0d698e-77f4-4453-8c09-ae2cbe6a9a04"); + + String serviceInstance = + new String(Files.readAllBytes(Paths.get("src/test/resources/alloted-resource.json"))); + Mockito.when(restClient.sendGetRequest(Mockito.anyString(), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstance, HttpStatus.OK)); + + List<String> actualResponse = aaiService.fetchSliceProfilesOfAllotedResourceData(allotedResourceList); + assertEquals(expectedResponse, actualResponse); + } + + @Test + public void fetchSnssaiOfSliceProfileTest() throws IOException { + configuration.setAaiUrl("http://aai:30233/aai/v21"); + List<String> sliceProfileList = new ArrayList<>(); + sliceProfileList.add("b2ae730f-1d5f-495a-8112-dac017a7348c"); + sliceProfileList.add("cad8fa36-2d55-4c12-a92e-1bd551517a0c"); + sliceProfileList.add("8d0d698e-77f4-4453-8c09-ae2cbe6a9a04"); + List<String> expectedResponse = new ArrayList<>(); + expectedResponse.add("01-06E442"); + expectedResponse.add("01-B989BD"); + + String serviceInstanceUrlAn = "b2ae730f-1d5f-495a-8112-dac017a7348c"; + String serviceInstanceUrlCn = "cad8fa36-2d55-4c12-a92e-1bd551517a0c"; + String serviceInstanceUrlTn = "8d0d698e-77f4-4453-8c09-ae2cbe6a9a04"; + + String serviceInstanceAn = + new String(Files.readAllBytes(Paths.get("src/test/resources/sliceprofile_an_sa1.json"))); + Mockito.when(restClient.sendGetRequest(Mockito.contains(serviceInstanceUrlAn), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstanceAn, HttpStatus.OK)); + + String serviceInstanceCn = + new String(Files.readAllBytes(Paths.get("src/test/resources/sliceprofile_cn_sa1.json"))); + Mockito.when(restClient.sendGetRequest(Mockito.contains(serviceInstanceUrlCn), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstanceCn, HttpStatus.OK)); + + String serviceInstanceTn = + new String(Files.readAllBytes(Paths.get("src/test/resources/sliceprofile_tn_sa1.json"))); + Mockito.when(restClient.sendGetRequest(Mockito.contains(serviceInstanceUrlTn), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstanceTn, HttpStatus.OK)); + + List<String> actualResponse = aaiService.fetchSnssaiOfSliceProfile(sliceProfileList); + assertEquals(expectedResponse, actualResponse); + } + + @Test + public void getSnssaiListForNsiTest() throws IOException { + configuration.setAaiUrl("http://aai:30233/aai/v21"); + List<String> expectedResponse = new ArrayList<>(); + expectedResponse.add("01-06E442"); + expectedResponse.add("01-B989BD"); + + String allotedResource = + new String(Files.readAllBytes(Paths.get("src/test/resources/alloted-resource.json"))); + Mockito.when( + restClient.sendGetRequest(Mockito.contains("0835fd19-6726-4081-befb-cc8932c47767"), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(allotedResource, HttpStatus.OK)); + + String serviceInstance = new String(Files.readAllBytes(Paths.get("src/test/resources/nsi.json"))); + Mockito.when( + restClient.sendGetRequest(Mockito.contains("09cad94e-fbb8-4c70-9c4d-74ec75e97683"), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstance, HttpStatus.OK)); + + String serviceInstanceAn = + new String(Files.readAllBytes(Paths.get("src/test/resources/sliceprofile_an_sa1.json"))); + Mockito.when( + restClient.sendGetRequest(Mockito.contains("b2ae730f-1d5f-495a-8112-dac017a7348c"), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstanceAn, HttpStatus.OK)); + + String serviceInstanceCn = + new String(Files.readAllBytes(Paths.get("src/test/resources/sliceprofile_cn_sa1.json"))); + Mockito.when( + restClient.sendGetRequest(Mockito.contains("cad8fa36-2d55-4c12-a92e-1bd551517a0c"), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstanceCn, HttpStatus.OK)); + + String serviceInstanceTn = + new String(Files.readAllBytes(Paths.get("src/test/resources/sliceprofile_tn_sa1.json"))); + Mockito.when( + restClient.sendGetRequest(Mockito.contains("8d0d698e-77f4-4453-8c09-ae2cbe6a9a04"), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstanceTn, HttpStatus.OK)); + + List<String> actualResponse = aaiService.getSnssaiList("09cad94e-fbb8-4c70-9c4d-74ec75e97683"); + assertEquals(expectedResponse, actualResponse); + } + + @Test + public void getSnssaiListForNssiTest() throws IOException { + configuration.setAaiUrl("http://aai:30233/aai/v21"); + List<String> expectedResponse = new ArrayList<>(); + expectedResponse.add("01-06E442"); + + String nssi = new String(Files.readAllBytes(Paths.get("src/test/resources/nssi.json"))); + Mockito.when( + restClient.sendGetRequest(Mockito.contains("50f418a6-804f-4453-bf70-21f0efaf6fcd"), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(nssi, HttpStatus.OK)); + + String serviceInstanceAn = + new String(Files.readAllBytes(Paths.get("src/test/resources/sliceprofile_an_sa1.json"))); + Mockito.when( + restClient.sendGetRequest(Mockito.contains("b2ae730f-1d5f-495a-8112-dac017a7348c"), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(serviceInstanceAn, HttpStatus.OK)); + + List<String> actualResponse = aaiService.getSnssaiList("50f418a6-804f-4453-bf70-21f0efaf6fcd"); + assertEquals(expectedResponse, actualResponse); + } + + @Test + public void fetchMaxBandwidthOfServiceTest() { + String data = "{" + + " \"network-policy\":[" + + " {" + + " \"max-bandwidth\":99" + + " }" + + " ]" + + "}"; + Mockito.when(restClient.sendGetRequest(Mockito.anyString(), Mockito.any())).thenReturn(new ResponseEntity<>(data, HttpStatus.OK)); + Map<String, Integer> map = aaiService.fetchMaxBandwidthOfService(""); + assertEquals(99, MapUtils.getIntValue(map, "maxBandwidth")); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/AaiInterfaceServiceTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/AaiInterfaceServiceTest.java deleted file mode 100644 index 78607788..00000000 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/AaiInterfaceServiceTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * slice-analysis-ms - * ================================================================================ - * Copyright (C) 2021 Wipro Limited. - * ============================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - *******************************************************************************/ -package org.onap.slice.analysis.ms.configdb; - -import static org.junit.Assert.assertEquals; - -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.modules.junit4.PowerMockRunnerDelegate; -import org.onap.slice.analysis.ms.models.Configuration; -import org.onap.slice.analysis.ms.models.configdb.CellsModel; -import org.onap.slice.analysis.ms.models.configdb.NetworkFunctionModel; -import org.onap.slice.analysis.ms.restclients.AaiRestClient; -import org.onap.slice.analysis.ms.restclients.ConfigDbRestClient; -import org.onap.slice.analysis.ms.utils.BeanUtil; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(PowerMockRunner.class) -@PowerMockRunnerDelegate(SpringRunner.class) -@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) -@PrepareForTest({ AaiService.class,Configuration.class }) -@SpringBootTest(classes = AaiInterfaceServiceTest.class) -public class AaiInterfaceServiceTest { - - Configuration configuration = Configuration.getInstance(); - - @InjectMocks - AaiService aaiService; - - @Mock - AaiRestClient restClient; - - @Test - public void fetchCurrentConfigurationOfSlice() { - configuration.setAaiUrl("http://aai:30233/aai/v21/business/customers/customer/"); - PowerMockito.mockStatic(AaiService.class); - PowerMockito.mockStatic(Configuration.class); - PowerMockito.when(Configuration.getInstance()).thenReturn(configuration); - Map<String, Integer> responsemap = new HashMap<>(); - responsemap.put("dLThptPerSlice", 60); - responsemap.put("uLThptPerSlice", 54); - try { - String serviceInstance = new String( - Files.readAllBytes(Paths.get("src/test/resources/aaiDetailsList.json"))); - Mockito.when(restClient.sendGetRequest(Mockito.anyString(), Mockito.any())) - .thenReturn(new ResponseEntity<Object>(serviceInstance, HttpStatus.OK)); - - - } catch (Exception e) { - e.printStackTrace(); - - } - assertEquals(responsemap, aaiService.fetchCurrentConfigurationOfSlice("001-010000")); - } - - @Test - public void fetchServiceProfile() { - Map<String, String> responseMap = new HashMap<String, String>(); - responseMap.put("sNSSAI", "001-00110"); - responseMap.put("ranNFNSSIId", "4b889f2b-8ee4-4ec7-881f-5b1af8a74039"); - responseMap.put("sliceProfileId", "ab9af40f13f7219099333"); - responseMap.put("globalSubscriberId", "5GCustomer"); - responseMap.put("subscriptionServiceType", "5G"); - - try { - String serviceInstance = new String( - Files.readAllBytes(Paths.get("src/test/resources/aaiDetailsList.json"))); - Mockito.when(restClient.sendGetRequest(Mockito.anyString(), Mockito.any())) - .thenReturn(new ResponseEntity<Object>(serviceInstance, HttpStatus.OK)); - - } catch (Exception e) { - e.printStackTrace(); - - } - - assertEquals(responseMap, aaiService.fetchServiceDetails("001-00110")); - } -} - diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceServiceTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceServiceTest.java index 885a9171..28e157c8 100644 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceServiceTest.java +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/ConfigDbInterfaceServiceTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -126,6 +126,7 @@ public class ConfigDbInterfaceServiceTest { } + @Test public void fetchServiceProfile() { Map<String,String> responseMap=new HashMap<String, String>(); responseMap.put("sNSSAI", "001-010"); @@ -136,5 +137,34 @@ public class ConfigDbInterfaceServiceTest { .thenReturn(new ResponseEntity<Object>(responseMap, HttpStatus.OK)); assertEquals(responseMap, configdbservice.fetchServiceDetails("snssai")); } + + @Test + public void fetchCUCPCellsOfSnssaiTest() { + Map<String, List<CellsModel>> response = new HashMap<>(); + List<CellsModel> cellslist = new ArrayList<>(); + List<CellsModel> cellslist1 = new ArrayList<>(); + CellsModel cellsmodel1 = new CellsModel(); + cellsmodel1.setCellLocalId("1111"); + CellsModel cellsmodel2 = new CellsModel(); + cellsmodel2.setCellLocalId("2222"); + cellslist.add(cellsmodel1); + cellslist.add(cellsmodel2); + response.put("1", cellslist); + CellsModel cellsmodel3 = new CellsModel(); + cellsmodel3.setCellLocalId("3333"); + CellsModel cellsmodel4 = new CellsModel(); + cellsmodel4.setCellLocalId("4444"); + cellslist1.add(cellsmodel3); + cellslist1.add(cellsmodel4); + response.put("2", cellslist1); + Mockito.when(restclient.sendGetRequest(Mockito.anyString(), Mockito.any())) + .thenReturn(new ResponseEntity<Object>(response, HttpStatus.OK)); + List<String> outputlist = new ArrayList<>(); + outputlist.add("1111"); + outputlist.add("2222"); + Map<String, List<String>> output = configdbservice.fetchCUCPCellsOfSnssai("snssai"); + assertEquals(outputlist, output.get("1")); + + } } diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/CpsInterfaceServiceTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/CpsInterfaceServiceTest.java deleted file mode 100644 index 008736d3..00000000 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/configdb/CpsInterfaceServiceTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START======================================================= - * slice-analysis-ms - * ================================================================================ - * Copyright (C) 2021 Wipro Limited. - * ============================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - * - *******************************************************************************/ -package org.onap.slice.analysis.ms.configdb; - -import static org.junit.Assert.assertEquals; - -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.onap.slice.analysis.ms.models.Configuration; -import org.onap.slice.analysis.ms.restclients.CpsRestClient; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import org.powermock.modules.junit4.PowerMockRunnerDelegate; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(PowerMockRunner.class) -@PowerMockRunnerDelegate(SpringRunner.class) -@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) -@PrepareForTest({ CpsService.class,Configuration.class }) -@SpringBootTest(classes = CpsInterfaceServiceTest.class) -public class CpsInterfaceServiceTest { - @InjectMocks - CpsService cpsService; - - @Mock - CpsRestClient restClient; - - @Test - public void fetchCurrentConfigurationOfRICTest() { - Map<String, Object> map = new HashMap<>(); - map.put("dLThptPerSlice", 10); - map.put("uLThptPerSlice", 10); - map.put("maxNumberOfConns", 10); - Map<String, Map<String, Object>> responseMap = new HashMap<>(); - responseMap.put("11", map); - try { - String serviceInstance = new String( - Files.readAllBytes(Paths.get("src/test/resources/sliceConfig.json"))); - Mockito.when(restClient.sendPostRequest(Mockito.anyString(), Mockito.anyString(), Mockito.any())).thenReturn(new ResponseEntity<>(serviceInstance, HttpStatus.OK)); - } catch (Exception e) { - e.printStackTrace(); - } - assertEquals(responseMap, cpsService.fetchCurrentConfigurationOfRIC("111-1111")); - } - - @Test - public void fetchNetworkFunctionsOfSnssaiTest() { - List<String> responseList=new ArrayList<>(); - responseList.add("22"); - responseList.add("23"); - try { - String serviceInstance = new String( - Files.readAllBytes(Paths.get("src/test/resources/DUList.json"))); - Mockito.when(restClient.sendPostRequest(Mockito.anyString(), Mockito.anyString(), Mockito.any())).thenReturn(new ResponseEntity<>(serviceInstance, HttpStatus.OK)); - } catch (Exception e) { - e.printStackTrace(); - } - assertEquals(responseList, cpsService.fetchNetworkFunctionsOfSnssai("111-1111")); - } - - @Test - public void fetchRICsOfSnssaiTest() { - Map<String,List<String>> responseMap=new HashMap<>(); - List<String> cellslist=new ArrayList<>(); - cellslist.add("1599"); - cellslist.add("1598"); - responseMap.put("11",cellslist); - try { - String serviceInstance = new String( - Files.readAllBytes(Paths.get("src/test/resources/DUCellsList.json"))); - Mockito.when(restClient.sendPostRequest(Mockito.anyString(), Mockito.anyString(), Mockito.any())).thenReturn(new ResponseEntity<>(serviceInstance, HttpStatus.OK)); - } catch (Exception e) { - e.printStackTrace(); - } - assertEquals(responseMap, cpsService.fetchRICsOfSnssai("111-1111")); - } -} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbsTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbsTest.java new file mode 100644 index 00000000..84824547 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/controller/ConfigFetchFromCbsTest.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.controller; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +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 org.onap.dcaegen2.services.sdk.rest.services.model.logging.ImmutableRequestDiagnosticContext; +import org.onap.dcaegen2.services.sdk.rest.services.model.logging.RequestDiagnosticContext; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.slf4j.LoggerFactory; +import org.slf4j.Logger; +import reactor.core.publisher.Mono; + +import java.time.Duration; + +import static org.mockito.Mockito.times; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({LoggerFactory.class, + RequestDiagnosticContext.class, + CbsClientConfiguration.class, + ImmutableRequestDiagnosticContext.class, + CbsClientFactory.class}) +public class ConfigFetchFromCbsTest { + + @Test + public void getAppConfigTest() { + PowerMockito.mockStatic(LoggerFactory.class); + Logger log = PowerMockito.mock(Logger.class); + when(LoggerFactory.getLogger(ConfigFetchFromCbs.class)).thenReturn(log); + + PowerMockito.mockStatic(RequestDiagnosticContext.class); + ImmutableRequestDiagnosticContext diagnosticContext = PowerMockito.mock(ImmutableRequestDiagnosticContext.class); + when(RequestDiagnosticContext.create()).thenReturn(diagnosticContext); + + PowerMockito.mockStatic(CbsClientConfiguration.class); + CbsClientConfiguration cbsClientConfiguration = PowerMockito.mock(CbsClientConfiguration.class); + when(CbsClientConfiguration.fromEnvironment()).thenReturn(cbsClientConfiguration); + + PowerMockito.mockStatic(CbsClientFactory.class); + Mono mono = PowerMockito.mock(Mono.class); + when(CbsClientFactory.createCbsClient(cbsClientConfiguration)).thenReturn(mono); + + ConfigFetchFromCbs configFetchFromCbs = new ConfigFetchFromCbs(Duration.ofSeconds(60)); + ConfigFetchFromCbs spy = PowerMockito.spy(configFetchFromCbs); + Thread configFetchThread = new Thread(spy); + configFetchThread.start(); + Mockito.verify(spy, times(1)).run(); + + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/controller/SliceConfiguratonTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/controller/SliceConfiguratonTest.java new file mode 100644 index 00000000..b35ecdea --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/controller/SliceConfiguratonTest.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.controller; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.onap.slice.analysis.ms.models.SliceConfigRequest; +import org.onap.slice.analysis.ms.models.SliceConfigResponse; +import org.onap.slice.analysis.ms.service.SliceUtilization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +@RunWith(SpringRunner.class) +@WebMvcTest(SliceConfiguraton.class) +public class SliceConfiguratonTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private SliceUtilization sliceUtilization; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + private static final String UTF8 = StandardCharsets.UTF_8.name(); + + @Test + public void getSnssaiListTest() throws Exception { + SliceConfigRequest sliceConfigRequest = new SliceConfigRequest(); + List<String> sliceIdentifiersList = new ArrayList<>(); + sliceIdentifiersList.add("14559ead-f4fe-4c1c-a94c-8015fad3ea35"); + sliceIdentifiersList.add("14559ead-f4fe-4c1c-a94c-8015fad3ea36"); + sliceConfigRequest.setSliceIdentifiers(sliceIdentifiersList); + List<String> configParamsList = new ArrayList<>(); + configParamsList.add("dLThptPerSlice"); + configParamsList.add("uLThptPerSlice"); + sliceConfigRequest.setConfigParams(configParamsList); + + String executePath = "/api/v1/slices-config"; + String sliceConfigResquestString = + new String(Files.readAllBytes(Paths.get("src/test/resources/sliceConfigRequest.json"))); + ObjectMapper objectMapper = new ObjectMapper(); + SliceConfigResponse sliceConfigResponse = objectMapper + .readValue(new File("src/test/resources/sliceConfigResponse.json"), SliceConfigResponse.class); + Mockito.when(sliceUtilization.getSliceUtilizationData(ArgumentMatchers.any())).thenReturn(sliceConfigResponse); + + mockMvc.perform(get(executePath).contentType(MediaType.APPLICATION_JSON).characterEncoding(UTF8) + .content(objectMapper.writeValueAsString(sliceConfigRequest)).accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(objectMapper.writeValueAsString(sliceConfigResponse))); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/cps/CpsInterfaceServiceTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/cps/CpsInterfaceServiceTest.java new file mode 100644 index 00000000..96b5fe2d --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/cps/CpsInterfaceServiceTest.java @@ -0,0 +1,109 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2021-2022 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.cps; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.onap.slice.analysis.ms.restclients.CpsRestClient; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(SpringRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@SpringBootTest(classes = CpsInterfaceServiceTest.class) +public class CpsInterfaceServiceTest { + @InjectMocks + CpsService cpsService; + + @Mock + CpsRestClient restClient; + + @Test + public void fetchCurrentConfigurationOfRICTest() throws IOException { + Map<String, Object> map = new HashMap<>(); + map.put("dLThptPerSlice", 10); + map.put("uLThptPerSlice", 10); + map.put("maxNumberOfConns", 10); + Map<String, Map<String, Object>> responseMap = new HashMap<>(); + responseMap.put("11", map); + String serviceInstance = new String(Files.readAllBytes(Paths.get("src/test/resources/sliceConfig.json"))); + Mockito.when(restClient.sendPostRequest(Mockito.anyString(), Mockito.anyString(), Mockito.any())) + .thenReturn(new ResponseEntity<>(serviceInstance, HttpStatus.OK)); + assertEquals(responseMap, cpsService.fetchCurrentConfigurationOfRIC("111-1111")); + } + + @Test + public void fetchNetworkFunctionsOfSnssaiTest() throws IOException { + List<String> responseList = new ArrayList<>(); + responseList.add("22"); + responseList.add("23"); + String serviceInstance = new String(Files.readAllBytes(Paths.get("src/test/resources/DUList.json"))); + Mockito.when(restClient.sendPostRequest(Mockito.anyString(), Mockito.anyString(), Mockito.any())) + .thenReturn(new ResponseEntity<>(serviceInstance, HttpStatus.OK)); + assertEquals(responseList, cpsService.fetchNetworkFunctionsOfSnssai("111-1111")); + } + + @Test + public void fetchRICsOfSnssaiTest() throws IOException { + Map<String, List<String>> responseMap = new HashMap<>(); + List<String> cellslist = new ArrayList<>(); + cellslist.add("1599"); + cellslist.add("1598"); + responseMap.put("11", cellslist); + String serviceInstance = new String(Files.readAllBytes(Paths.get("src/test/resources/DUCellsList.json"))); + Mockito.when(restClient.sendPostRequest(Mockito.anyString(), Mockito.anyString(), Mockito.any())) + .thenReturn(new ResponseEntity<>(serviceInstance, HttpStatus.OK)); + assertEquals(responseMap, cpsService.fetchRICsOfSnssai("111-1111")); + } + + @Test + public void fetchnrCellCUsOfSnssaiTest() throws IOException { + Map<String, List<String>> responseMap = new HashMap<>(); + List<String> cellslist = new ArrayList<>(); + cellslist.add("15199"); + responseMap.put("11", cellslist); + String serviceInstance = new String(Files.readAllBytes(Paths.get("src/test/resources/DUCellsList.json"))); + Mockito.when(restClient.sendPostRequest(Mockito.anyString(), Mockito.anyString(), Mockito.any())) + .thenReturn(new ResponseEntity<>(serviceInstance, HttpStatus.OK)); + assertEquals(responseMap, cpsService.fetchnrCellCUsOfSnssai("111-1111")); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/AaiEventNotificationCallbackTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/AaiEventNotificationCallbackTest.java new file mode 100644 index 00000000..9fce12f1 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/AaiEventNotificationCallbackTest.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 CTC, Inc. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.dmaap; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.service.ccvpn.BandwidthEvaluator; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static org.mockito.ArgumentMatchers.any; +import static org.powermock.api.mockito.PowerMockito.doNothing; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = VesNotificationCallbackTest.class) +public class AaiEventNotificationCallbackTest { + + @Spy + @InjectMocks + AaiEventNotificationCallback aaiEventNotificationCallback; + + @Mock + BandwidthEvaluator bandwidthEvaluator; + + @Before + public void initConfiguration() { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("sliceanalysisms.aaiNotif.targetAction", "UPDATE"); + jsonObject.addProperty("sliceanalysisms.aaiNotif.targetEntity", "service-instance"); + jsonObject.addProperty("sliceanalysisms.aaiNotif.targetSource", "UUI"); + jsonObject.addProperty("postgres.port", "1"); + jsonObject.addProperty("sliceanalysisms.pollingInterval", "1"); + jsonObject.addProperty("postgres.password", "1"); + jsonObject.addProperty("postgres.username", "1"); + jsonObject.addProperty("postgres.host", "1"); + jsonObject.addProperty("sliceanalysisms.cg", "1"); + jsonObject.addProperty("sliceanalysisms.cid", "1"); + jsonObject.addProperty("sliceanalysisms.configDb.service", "1"); + jsonObject.addProperty("sliceanalysisms.configDbEnabled", "1"); + jsonObject.addProperty("sliceanalysisms.pollingTimeout", "1"); + jsonObject.addProperty("sliceanalysisms.samples", "1"); + jsonObject.addProperty("sliceanalysisms.minPercentageChange", "1"); + jsonObject.addProperty("sliceanalysisms.initialDelaySeconds", "1"); + jsonObject.addProperty("sliceanalysisms.rannfnssiDetailsTemplateId", "1"); + jsonObject.addProperty("sliceanalysisms.desUrl", "1"); + jsonObject.addProperty("sliceanalysisms.pmDataDurationInWeeks", "1"); + jsonObject.addProperty("sliceanalysisms.pollingInterval", "1"); + jsonObject.addProperty("sliceanalysisms.vesNotifChangeIdentifier", "1"); + jsonObject.addProperty("sliceanalysisms.vesNotifChangeType", "1"); + jsonObject.addProperty("sliceanalysisms.vesNotifPollingInterval", "1"); + jsonObject.addProperty("sliceanalysisms.ccvpnEvalInterval", "1"); + jsonObject.addProperty("sliceanalysisms.ccvpnEvalUpperThreshold", "1"); + jsonObject.addProperty("sliceanalysisms.ccvpnEvalLowerThreshold", "1"); + jsonObject.addProperty("sliceanalysisms.ccvpnEvalPrecision", "1"); + jsonObject.addProperty("sliceanalysisms.ccvpnEvalPeriodicCheckOn", "1"); + jsonObject.addProperty("sliceanalysisms.ccvpnEvalOnDemandCheckOn", "1"); + jsonObject.addProperty("sliceanalysisms.ccvpnEvalStrategy", "1"); + Configuration configuration = Configuration.getInstance(); + configuration.updateConfigurationFromJsonObject(jsonObject); + doNothing().when(bandwidthEvaluator).post(any()); + } + + @Test + public void initTest() { + aaiEventNotificationCallback.init(); + Mockito.verify(aaiEventNotificationCallback, Mockito.atLeastOnce()).init(); + } + + @Test + public void activateCallBackTest() throws IOException { + aaiEventNotificationCallback.init(); + String input = new String(Files.readAllBytes(Paths.get("src/test/resources/aaiEventDmaapMsg.json"))); + aaiEventNotificationCallback.activateCallBack(input); + Mockito.verify(aaiEventNotificationCallback, Mockito.atLeastOnce()).activateCallBack(Mockito.anyString()); + } + @Test + public void activateCallBackArrayTest() throws IOException { + aaiEventNotificationCallback.init(); + String input = new String(Files.readAllBytes(Paths.get("src/test/resources/aaiEventDmaapMsg.json"))); + JsonArray jsonArray = new JsonArray(); + + JsonPrimitive jsonPrimitive = new JsonPrimitive(input); + jsonArray.add(jsonPrimitive); + aaiEventNotificationCallback.activateCallBack(jsonArray.toString()); + Mockito.verify(aaiEventNotificationCallback, Mockito.atLeastOnce()).activateCallBack(Mockito.anyString()); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/DmaapClientTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/DmaapClientTest.java index b74056db..7da9f95f 100644 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/DmaapClientTest.java +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/DmaapClientTest.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,28 +23,23 @@ package org.onap.slice.analysis.ms.dmaap; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; -import com.att.nsa.cambria.client.CambriaTopicManager; import com.google.gson.Gson; import com.google.gson.JsonObject; import java.io.BufferedReader; import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; -import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.onap.slice.analysis.ms.models.Configuration; +import org.powermock.api.mockito.PowerMockito; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @@ -51,78 +47,43 @@ import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest(classes = DmaapClientTest.class) public class DmaapClientTest { - @Mock - private CambriaTopicManager topicManager; - - @InjectMocks - DmaapClient client; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void getAllTopicsTest() { - Set<String> topics = new HashSet<String>(); - topics.add("topic1"); - topics.add("topic2"); - Configuration configuration = Configuration.getInstance(); - List<String> list = new ArrayList<String>(); - list.add("server"); - configuration.setDmaapServers(list); - configuration.setCg("cg"); - configuration.setCid("cid"); - configuration.setPollingInterval(30); - configuration.setPollingTimeout(100); - configuration.setConfigDbService("sdnrService"); - - try { - when(topicManager.getTopics()).thenReturn(topics); - - client=Mockito.mock(DmaapClient.class); - client.initClient(); - Mockito.verify(client).initClient(); - // Mockito.verifycreateAndConfigureTopics(); - - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Test - public void startClientTest() { - try { - Configuration configuration = Configuration.getInstance(); - String configAllJson = readFromFile("src/test/resources/config_all.json"); - - JsonObject configAll = new Gson().fromJson(configAllJson, JsonObject.class); - - JsonObject config = configAll.getAsJsonObject("config"); - System.out.println(configuration); - configuration.updateConfigurationFromJsonObject(config); - DmaapClient client= new DmaapClient(); - client.initClient(); - //Mockito.verify(client).startClient(); - // Mockito.verifycreateAndConfigureTopics(); - - } catch ( Exception e) { - e.printStackTrace(); - } - } - - private static String readFromFile(String file) { - String content = ""; - try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) { - content = bufferedReader.readLine(); - String temp; - while ((temp = bufferedReader.readLine()) != null) { - content = content.concat(temp); - } - content = content.trim(); - } catch (Exception e) { - content = null; - } - return content; - } + @InjectMocks + DmaapClient client; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void startClientTest() { + Configuration configuration = Configuration.getInstance(); + String configAllJson = readFromFile("src/test/resources/config_all.json"); + + JsonObject configAll = new Gson().fromJson(configAllJson, JsonObject.class); + + JsonObject config = configAll.getAsJsonObject("config"); + System.out.println(configuration); + configuration.updateConfigurationFromJsonObject(config); + MRTopicMonitor mrTopicMonitor = Mockito.mock(MRTopicMonitor.class); + DmaapClient spy = PowerMockito.spy(client); + doReturn(mrTopicMonitor).when(spy).getMRTopicMonitor(); + doNothing().when(mrTopicMonitor).start(); + spy.initClient(); + } + + private static String readFromFile(String file) { + String content = ""; + try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) { + content = bufferedReader.readLine(); + String temp; + while ((temp = bufferedReader.readLine()) != null) { + content = content.concat(temp); + } + content = content.trim(); + } catch (Exception e) { + content = null; + } + return content; + } } diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/IntelligentSlicingCallbackTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/IntelligentSlicingCallbackTest.java new file mode 100644 index 00000000..59daae09 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/IntelligentSlicingCallbackTest.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.dmaap; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.onap.slice.analysis.ms.service.MLMessageProcessor; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = IntelligentSlicingCallbackTest.class) +public class IntelligentSlicingCallbackTest { + + + @Spy + @InjectMocks + IntelligentSlicingCallback intelligentSlicingCallback; + + @Mock + private MLMessageProcessor mlMsMessageProcessor; + + @Test + public void activateCallBackTest() { + Mockito.doNothing().when(mlMsMessageProcessor).processMLMsg(Mockito.any()); + intelligentSlicingCallback.activateCallBack("{}"); + verify(mlMsMessageProcessor, times(1)).processMLMsg(any()); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/MRTopicMonitorTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/MRTopicMonitorTest.java new file mode 100644 index 00000000..813bd463 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/MRTopicMonitorTest.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.dmaap; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.onap.slice.analysis.ms.models.Configuration; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.concurrent.Executors; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@PrepareForTest({ Executors.class}) +@SpringBootTest(classes = MRTopicMonitorTest.class) +public class MRTopicMonitorTest { + + @Spy + @InjectMocks + MRTopicMonitor mrTopicMonitor; + + @Mock + AaiEventNotificationCallback aaiEventNotificationCallback; + + @Before + public void before(){ + Configuration configuration = Configuration.getInstance(); + String configAllJson = readFromFile("src/test/resources/config_all.json"); + JsonObject configAll = new Gson().fromJson(configAllJson, JsonObject.class); + JsonObject config = configAll.getAsJsonObject("config"); + configuration.updateConfigurationFromJsonObject(config); + + mrTopicMonitor = new MRTopicMonitor("aai_subscriber", aaiEventNotificationCallback); + MockitoAnnotations.initMocks(this); + } + + @Test + public void run() { + mrTopicMonitor.run(); + Mockito.verify(mrTopicMonitor, Mockito.times(1)).run(); + } + + @Test + public void stop() { + mrTopicMonitor.start(); + mrTopicMonitor.stop(); + Mockito.verify(mrTopicMonitor, Mockito.times(1)).stop(); + } + + private static String readFromFile(String file) { + String content = ""; + try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) { + content = bufferedReader.readLine(); + String temp; + while ((temp = bufferedReader.readLine()) != null) { + content = content.concat(temp); + } + content = content.trim(); + } catch (Exception e) { + content = null; + } + return content; + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/MRTopicParamsTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/MRTopicParamsTest.java new file mode 100644 index 00000000..2498306c --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/MRTopicParamsTest.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.dmaap; + +import com.openpojo.reflection.PojoClass; +import com.openpojo.reflection.impl.PojoClassFactory; +import com.openpojo.validation.Validator; +import com.openpojo.validation.ValidatorBuilder; +import com.openpojo.validation.rule.impl.GetterMustExistRule; +import com.openpojo.validation.rule.impl.SetterMustExistRule; +import com.openpojo.validation.test.impl.GetterTester; +import com.openpojo.validation.test.impl.SetterTester; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + + +public class MRTopicParamsTest { + private static final String TEST_TOPIC = "test-topic"; + private static final String TEST_HOST = "test-host"; + private static final String MY_CLIENT = "my-client"; + private static final String MY_CG = "my-cg"; + private static final String MY_CI = "my-ci"; + private static final String MY_API_SEC = "my-api-sec"; + private static final String MY_API_KEY = "my-api-key"; + private static final int MY_FETCH_LIMIT = 100; + private static final int MY_FETCH_TIMEOUT = 1000; + private static final String MY_PASS = "my-pass"; + private static final String MY_USERNAME = "my-username"; + private static final int MY_PORT = 5555; + + @Test + public void builderTest() { + MRTopicParams params = MRTopicParams.builder() + .topic(TEST_TOPIC) + .hostname(TEST_HOST) + .clientName(MY_CLIENT) + .consumerGroup(MY_CG) + .consumerInstance(MY_CI) + .apiSecret(MY_API_SEC) + .apiKey(MY_API_KEY) + .fetchLimit(MY_FETCH_LIMIT) + .fetchTimeout(MY_FETCH_TIMEOUT) + .password(MY_PASS) + .userName(MY_USERNAME) + .port(MY_PORT) + .build(); + + assertEquals(TEST_TOPIC, params.getTopic()); + assertEquals(TEST_HOST, params.getHostname()); + assertEquals(MY_CLIENT, params.getClientName()); + assertEquals(MY_CG, params.getConsumerGroup()); + assertEquals(MY_CI, params.getConsumerInstance()); + assertEquals(MY_API_SEC, params.getApiSecret()); + assertEquals(MY_API_KEY, params.getApiKey()); + assertEquals(MY_FETCH_LIMIT, params.getFetchLimit()); + assertEquals(MY_FETCH_TIMEOUT, params.getFetchTimeout()); + assertEquals(MY_PASS, params.getPassword()); + assertEquals(MY_USERNAME, params.getUserName()); + assertEquals(MY_PORT, params.getPort()); + } + + @Test + public void testGetterSetterMRTopicParams() { + PojoClass pojoclass = PojoClassFactory.getPojoClass(MRTopicParams.class); + validateMd(pojoclass); + } + + public void validateMd(PojoClass pojoclass) { + Validator validator = ValidatorBuilder + .create() + .with(new SetterMustExistRule()) + .with(new GetterMustExistRule()) + .with(new SetterTester()) + .with(new GetterTester()) + .build(); + validator.validate(pojoclass); + } + + @Test + public void initProperty() { + List<String> strings = new ArrayList<>(); + Map<String, String> map = new HashMap<>(); + MRTopicParams params = MRTopicParams.builder() + .topic(TEST_TOPIC) + .hostname(TEST_HOST) + .clientName(MY_CLIENT) + .consumerGroup(MY_CG) + .consumerInstance(MY_CI) + .apiSecret(MY_API_SEC) + .apiKey(MY_API_KEY) + .fetchLimit(MY_FETCH_LIMIT) + .fetchTimeout(MY_FETCH_TIMEOUT) + .password(MY_PASS) + .userName(MY_USERNAME) + .port(MY_PORT) + .servers(strings) + .additionalProps(map) + .effectiveTopic("") + .useHttps(true) + .allowSelfSignedCerts(true) + .managed(true) + .environment("") + .aftEnvironment("") + .partner("") + .latitude("") + .longitude("") + .partitionId("") + .basePath("") + .serializationProvider("") + .build(); + assertEquals(TEST_TOPIC, params.getTopic()); + assertEquals(TEST_HOST, params.getHostname()); + assertEquals(MY_CLIENT, params.getClientName()); + assertEquals(MY_CG, params.getConsumerGroup()); + assertEquals(MY_CI, params.getConsumerInstance()); + assertEquals(MY_API_SEC, params.getApiSecret()); + assertEquals(MY_API_KEY, params.getApiKey()); + assertEquals(MY_FETCH_LIMIT, params.getFetchLimit()); + assertEquals(MY_FETCH_TIMEOUT, params.getFetchTimeout()); + assertEquals(MY_PASS, params.getPassword()); + assertEquals(MY_USERNAME, params.getUserName()); + assertEquals(MY_PORT, params.getPort()); + assertEquals(strings, params.getServers()); + assertEquals(map, params.getAdditionalProps()); + assertEquals("", params.getEffectiveTopic()); + assertTrue(params.isUseHttps()); + assertTrue(params.isAllowSelfSignedCerts()); + assertTrue(params.isManaged()); + assertEquals("", params.getEnvironment()); + assertEquals("", params.getAftEnvironment()); + assertEquals("", params.getPartner()); + assertEquals("", params.getLongitude()); + assertEquals("", params.getPartitionId()); + assertEquals("", params.getBasePath()); + assertEquals("", params.getSerializationProvider()); + + assertTrue(params.isEnvironmentInvalid()); + assertTrue(params.isAftEnvironmentInvalid()); + assertTrue(params.isLatitudeInvalid()); + assertTrue(params.isLongitudeInvalid()); + assertTrue(params.isPartnerInvalid()); + assertTrue(params.isServersInvalid()); + assertTrue(params.isPartitionIdInvalid()); + assertTrue(params.isApiKeyValid()); + assertTrue(params.isApiSecretValid()); + assertTrue(params.isUserNameValid()); + assertTrue(params.isPasswordValid()); + assertTrue(params.isAdditionalPropsValid()); + assertFalse(params.isConsumerInstanceInvalid()); + assertFalse(params.isConsumerGroupInvalid()); + assertFalse(params.isClientNameInvalid()); + assertFalse(params.isTopicInvalid()); + assertFalse(params.isHostnameInvalid()); + assertFalse(params.isPortInvalid()); + } + + +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/NotificationConsumerTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/NotificationConsumerTest.java index 9aab22c2..5b8e5f25 100644 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/NotificationConsumerTest.java +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/NotificationConsumerTest.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,44 +24,48 @@ package org.onap.slice.analysis.ms.dmaap; import static org.mockito.Mockito.when; -import java.util.ArrayList; -import java.util.List; - +import com.google.gson.JsonPrimitive; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.MessageRouterSubscriber; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.ImmutableMessageRouterSubscribeResponse; +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.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import com.att.nsa.cambria.client.CambriaConsumer; +import reactor.core.publisher.Mono; @RunWith(SpringRunner.class) @SpringBootTest(classes = NotificationConsumerTest.class) public class NotificationConsumerTest { - - @Mock - CambriaConsumer cambriaConsumer; - - @Mock - NotificationCallback notificationCallback; + + @Mock + NotificationCallback notificationCallback; + + @Mock + MessageRouterSubscriber subscriber; + + @Mock + MessageRouterSubscribeRequest request; - @InjectMocks - NotificationConsumer notificationConsumer; + @InjectMocks + NotificationConsumer notificationConsumer; - @Test - public void testNotificationConsumer() { - try { - List<String> notifications = new ArrayList<>(); - notifications.add("notification1"); - when(cambriaConsumer.fetch()).thenReturn(notifications); - Mockito.doNothing().when(notificationCallback).activateCallBack(Mockito.anyString()); - notificationConsumer.run(); - - }catch(Exception e) { - e.printStackTrace(); - } - } + @Test + public void testNotificationConsumer() { + io.vavr.collection.List<String> expectedItems = io.vavr.collection.List.of("I", "like", "pizza"); + MessageRouterSubscribeResponse expectedResponse = ImmutableMessageRouterSubscribeResponse + .builder() + .items(expectedItems.map(JsonPrimitive::new)) + .build(); + Mono<MessageRouterSubscribeResponse> responses = Mono.just(expectedResponse); + when(subscriber.get(request)).thenReturn(responses); + Mockito.doNothing().when(notificationCallback).activateCallBack(Mockito.anyString()); + notificationConsumer.run(); + } } diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/NotificationProducerTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/NotificationProducerTest.java index 9dc51412..d39c0af6 100644 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/NotificationProducerTest.java +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/NotificationProducerTest.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,42 +23,47 @@ package org.onap.slice.analysis.ms.dmaap; -import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; -import com.att.nsa.cambria.client.CambriaBatchingPublisher; - -import java.io.IOException; - +import com.google.gson.JsonPrimitive; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.MessageRouterPublisher; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.ImmutableMessageRouterPublishResponse; +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.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; +import reactor.core.publisher.Flux; + +import java.io.IOException; @RunWith(SpringRunner.class) @SpringBootTest(classes = NotificationProducerTest.class) public class NotificationProducerTest { - @Mock - CambriaBatchingPublisher cambriaBatchingPublisher; - - @InjectMocks - NotificationProducer notificationProducer; + @Mock + MessageRouterPublisher publisher; - @Test - public void notificationProducerTest() { + @Mock + MessageRouterPublishRequest request; - try { + @InjectMocks + NotificationProducer notificationProducer; - when(cambriaBatchingPublisher.send(Mockito.anyString(), Mockito.anyString())).thenReturn(0); - int result = notificationProducer.sendNotification("msg"); - assertEquals(0, result); - } catch (IOException e) { - e.printStackTrace(); - } + @Test + public void notificationProducerTest() throws IOException { + io.vavr.collection.List<String> expectedItems = io.vavr.collection.List.of("I", "like", "pizza"); + MessageRouterPublishResponse expectedResponse = ImmutableMessageRouterPublishResponse + .builder().items(expectedItems.map(JsonPrimitive::new)) + .build(); + Flux<MessageRouterPublishResponse> responses = Flux.just(expectedResponse); +// Flux<JsonPrimitive> singleMessage = Flux.just("msg").map(JsonPrimitive::new); + when(publisher.put(any(), any())).thenReturn(responses); - } + notificationProducer.sendNotification("msg"); + } } diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/PolicyDmaapClientTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/PolicyDmaapClientTest.java index 3ff56ab1..26f691e3 100644 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/PolicyDmaapClientTest.java +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/PolicyDmaapClientTest.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,51 +23,50 @@ package org.onap.slice.analysis.ms.dmaap; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; import java.util.HashMap; import java.util.Map; +import com.google.gson.JsonPrimitive; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.api.MessageRouterPublisher; +import org.onap.dcaegen2.services.sdk.rest.services.dmaap.client.model.ImmutableMessageRouterPublishResponse; +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.onap.slice.analysis.ms.models.Configuration; -import org.onap.slice.analysis.ms.utils.DmaapUtils; +import org.onap.slice.analysis.ms.utils.DcaeDmaapUtil; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import reactor.core.publisher.Flux; -import com.att.nsa.cambria.client.CambriaBatchingPublisher; -import com.att.nsa.cambria.client.CambriaConsumer; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; -@RunWith(MockitoJUnitRunner.class) -@SpringBootTest(classes = PolicyDmaapClient.class) +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@PrepareForTest({ DcaeDmaapUtil.class}) +@SpringBootTest(classes = PolicyDmaapClientTest.class) public class PolicyDmaapClientTest { @Mock Configuration configurationMock; - @Mock - DmaapUtils dmaapUtilsMock; - @InjectMocks PolicyDmaapClient policyDmaapClient; - @Mock - CambriaConsumer policyResponseCambriaConsumerMock; - - @Mock - CambriaBatchingPublisher cambriaBatchingPublisherMock; - - @Mock - NotificationProducer notificationProducerMock; - @Before public void setup() { - policyDmaapClient = new PolicyDmaapClient(dmaapUtilsMock, configurationMock); + policyDmaapClient = new PolicyDmaapClient(configurationMock); } @Test @@ -78,13 +78,21 @@ public class PolicyDmaapClientTest { dmaapInfo.put("dmaap_info", topics); streamsPublishes.put("CL_topic", dmaapInfo); Mockito.when(configurationMock.getStreamsPublishes()).thenReturn(streamsPublishes); - Mockito.when(dmaapUtilsMock.buildPublisher(configurationMock, "DCAE_CL_OUTPUT")).thenReturn(cambriaBatchingPublisherMock); - try { - Mockito.when(cambriaBatchingPublisherMock.send("", "hello")).thenReturn(0); - } catch (IOException e) { - e.printStackTrace(); - } - assertTrue(policyDmaapClient.sendNotificationToPolicy("hello")); - + + PowerMockito.mockStatic(DcaeDmaapUtil.class); + MessageRouterPublisher publisher = PowerMockito.mock(MessageRouterPublisher.class); + PowerMockito.when(DcaeDmaapUtil.buildPublisher()).thenReturn(publisher); + + MessageRouterPublishRequest request = PowerMockito.mock(MessageRouterPublishRequest.class); + PowerMockito.when(DcaeDmaapUtil.buildPublisherRequest(any(),any())).thenReturn(request); + + io.vavr.collection.List<String> expectedItems = io.vavr.collection.List.of("I", "like", "pizza"); + MessageRouterPublishResponse expectedResponse = ImmutableMessageRouterPublishResponse + .builder().items(expectedItems.map(JsonPrimitive::new)) + .build(); + Flux<MessageRouterPublishResponse> responses = Flux.just(expectedResponse); + when(publisher.put(any(), any())).thenReturn(responses); + + policyDmaapClient.sendNotificationToPolicy("msg"); } } diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/VesNotificationCallbackTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/VesNotificationCallbackTest.java new file mode 100644 index 00000000..97ee9fa9 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/dmaap/VesNotificationCallbackTest.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.dmaap; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.HashSet; +import java.util.Set; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.onap.slice.analysis.ms.aai.AaiService; +import org.onap.slice.analysis.ms.service.ccvpn.CCVPNPmDatastore; +import org.powermock.api.mockito.PowerMockito; +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.test.context.junit4.SpringRunner; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = VesNotificationCallbackTest.class) +public class VesNotificationCallbackTest { + ObjectMapper obj = new ObjectMapper(); + + @Mock + AaiService aaiService; + + @Mock + CCVPNPmDatastore ccvpnPmDatastore; + + @Spy + @InjectMocks + VesNotificationCallback vesNotificationCallback; + + @Test + public void initTest() { + vesNotificationCallback.init(); + Mockito.verify(vesNotificationCallback, Mockito.atLeastOnce()).init(); + } + + @Test + public void activateCallBackTest() { + String input = null; + try { + input = new String(Files.readAllBytes(Paths.get("src/test/resources/vesCCVPNNotiModel.json"))); + } catch (IOException e) { + e.printStackTrace(); + } + Set<String> cllInstances = new HashSet<>(); + cllInstances.add("cll-01"); + cllInstances.add("cll-02"); + Mockito.when(aaiService.fetchAllCllInstances()).thenReturn(cllInstances); + Mockito.doNothing().when(ccvpnPmDatastore).updateCllInstances(Mockito.any()); + vesNotificationCallback.activateCallBack(input); + Mockito.verify(vesNotificationCallback, Mockito.atLeastOnce()).activateCallBack(Mockito.anyString()); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/AggregatedConfigTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/AggregatedConfigTest.java new file mode 100644 index 00000000..e9097adf --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/AggregatedConfigTest.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.models; + +import nl.jqno.equalsverifier.EqualsVerifier; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.validation.constraints.NotEmpty; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@SpringBootTest(classes = AggregatedConfigTest.class) +public class AggregatedConfigTest { + + @Test + public void AggregatedConfigTest() { + + AggregatedConfig aggregatedConfig = new AggregatedConfig(); + aggregatedConfig.setDLThptPerSlice(1); + aggregatedConfig.setULThptPerSlice(2); + aggregatedConfig.setMaxNumberOfConns(3); + + assertEquals(1, aggregatedConfig.getDLThptPerSlice()); + assertEquals(2, aggregatedConfig.getULThptPerSlice()); + assertEquals(3, aggregatedConfig.getMaxNumberOfConns()); + } + + @Test + public void RelationshipListEqualsTest() { + + + AggregatedConfig aggregatedConfig = new AggregatedConfig(); + aggregatedConfig.setDLThptPerSlice(1); + aggregatedConfig.setULThptPerSlice(2); + aggregatedConfig.setMaxNumberOfConns(3); + + + AggregatedConfig aggregatedConfig2 = new AggregatedConfig(); + aggregatedConfig2.setDLThptPerSlice(1); + aggregatedConfig2.setULThptPerSlice(2); + aggregatedConfig2.setMaxNumberOfConns(3); + + + assertTrue(aggregatedConfig2.equals(aggregatedConfig)); + assertTrue(StringUtils.isNotBlank(aggregatedConfig.toString())); + assertTrue(aggregatedConfig.hashCode() != 0); + } + @Test + public void equalsContract() { + EqualsVerifier.simple().forClass(AggregatedConfig.class) + .withIgnoredAnnotations(NotEmpty.class) + .verify(); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/ConfigurationTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/ConfigurationTest.java index ed583cad..78379094 100644 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/ConfigurationTest.java +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/ConfigurationTest.java @@ -3,6 +3,8 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,6 +54,14 @@ public class ConfigurationTest { configuration.setSamples(10); configuration.setMinPercentageChange(50); configuration.setInitialDelaySeconds(1000); + configuration.setVesNotifPollingInterval(5); + configuration.setVesNotifChangeIdentifier("PM_BW_UPDATE"); + configuration.setVesNotifChangeType("BandwidthChanged"); + configuration.setCcvpnEvalInterval(5); + configuration.setCcvpnEvalPrecision(100); + configuration.setCcvpnEvalUpperThreshold(0.8); + configuration.setCcvpnEvalLowerThreshold(0.3); + configuration.setCcvpnEvalStrategy("FlexibleThresholdStrategy"); assertEquals(true,configuration.isSecured()); assertEquals("user", configuration.getAafUsername()); assertEquals("password", configuration.getAafPassword()); @@ -73,5 +83,13 @@ public class ConfigurationTest { assertEquals(10,configuration.getSamples()); assertEquals(50,configuration.getMinPercentageChange()); assertEquals(1000,configuration.getInitialDelaySeconds()); + assertEquals(5, configuration.getVesNotifPollingInterval()); + assertEquals("PM_BW_UPDATE", configuration.getVesNotifChangeIdentifier()); + assertEquals("BandwidthChanged", configuration.getVesNotifChangeType()); + assertEquals(5, configuration.getCcvpnEvalInterval()); + assertEquals(100.0, configuration.getCcvpnEvalPrecision(), 0.001); + assertEquals(0.8, configuration.getCcvpnEvalUpperThreshold(), 0.001); + assertEquals(0.3, configuration.getCcvpnEvalLowerThreshold(), 0.001); + assertEquals("FlexibleThresholdStrategy", configuration.getCcvpnEvalStrategy()); } } diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/ModelsTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/ModelsTest.java index 3150fb5c..682bef43 100644 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/ModelsTest.java +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/ModelsTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020-2021 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,9 @@ * ============LICENSE_END========================================================= * *******************************************************************************/ + package org.onap.slice.analysis.ms.models; -import org.junit.Test; + import com.openpojo.reflection.PojoClass; import com.openpojo.reflection.impl.PojoClassFactory; import com.openpojo.validation.Validator; @@ -29,28 +30,37 @@ import com.openpojo.validation.rule.impl.GetterMustExistRule; import com.openpojo.validation.rule.impl.SetterMustExistRule; import com.openpojo.validation.test.impl.GetterTester; import com.openpojo.validation.test.impl.SetterTester; + import nl.jqno.equalsverifier.EqualsVerifier; + +import org.junit.Test; + public class ModelsTest { @Test public void configDataEqualHashcodeTest() { - EqualsVerifier.simple().forClass(ConfigData.class).verify(); + EqualsVerifier.simple().forClass(ConfigData.class).verify(); } + @Test public void cellCUListEqualHashcodeTest() { - EqualsVerifier.simple().forClass(CellCUList.class).verify(); + EqualsVerifier.simple().forClass(CellCUList.class).verify(); } + @Test public void cuModelEqualHashcodeTest() { - EqualsVerifier.simple().forClass(CUModel.class).verify(); + EqualsVerifier.simple().forClass(CUModel.class).verify(); } + @Test public void subCounterEqualHashcodeTest() { EqualsVerifier.simple().forClass(SubCounter.class).verify(); } + @Test public void measurementObjectEqualHashcodeTest() { - EqualsVerifier.simple().forClass(MeasurementObject.class).verify(); + EqualsVerifier.simple().forClass(MeasurementObject.class).verify(); } + @Test public void testGetterSetterSubCounter() { PojoClass pojoclass = PojoClassFactory.getPojoClass(SubCounter.class); @@ -64,34 +74,55 @@ public class ModelsTest { .build(); validator.validate(pojoclass); } + @Test public void testGetterSetterMeasurementObject() { PojoClass pojoclass = PojoClassFactory.getPojoClass(MeasurementObject.class); validateMd(pojoclass); } + @Test public void testGetterSetterCellCUList() { PojoClass pojoclass = PojoClassFactory.getPojoClass(CellCUList.class); validateMd(pojoclass); } + @Test public void testGetterSetterCUModel() { PojoClass pojoclass = PojoClassFactory.getPojoClass(CUModel.class); validateMd(pojoclass); } + @Test public void testGetterSetterConfigData() { PojoClass pojoclass = PojoClassFactory.getPojoClass(ConfigData.class); validateMd(pojoclass); } + + @Test + public void testGetterSetterSliceConfigDetailsModel() { + PojoClass pojoclass = PojoClassFactory.getPojoClass(SliceConfigDetails.class); + validateMd(pojoclass); + } + + @Test + public void testGetterSetterSliceConfigRequestModel() { + PojoClass pojoclass = PojoClassFactory.getPojoClass(SliceConfigRequest.class); + validateMd(pojoclass); + } + + @Test + public void testGetterSetterSliceConfigResponseModel() { + PojoClass pojoclass = PojoClassFactory.getPojoClass(SliceConfigResponse.class); + validateMd(pojoclass); + } + public void validateMd(PojoClass pojoclass) { - Validator validator = ValidatorBuilder + Validator validator = ValidatorBuilder .create() .with(new SetterMustExistRule()) .with(new GetterMustExistRule()) - .with(new SetterTester()) - .with(new GetterTester()) - .build(); + .with(new SetterTester()).with(new GetterTester()).build(); validator.validate(pojoclass); } } diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/SliceConfigDetailsTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/SliceConfigDetailsTest.java new file mode 100644 index 00000000..c1f30002 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/SliceConfigDetailsTest.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.models; + +import nl.jqno.equalsverifier.EqualsVerifier; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.validation.constraints.NotEmpty; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@SpringBootTest(classes = SliceConfigDetailsTest.class) +public class SliceConfigDetailsTest { + + @Test + public void SliceConfigDetailsTest() { + + AggregatedConfig aggregatedConfig = new AggregatedConfig(); + + SliceConfigDetails sliceConfigDetails = new SliceConfigDetails(); + sliceConfigDetails.setSliceIdentifiers("slice"); + sliceConfigDetails.setAggregatedConfig(aggregatedConfig); + + assertEquals("slice", sliceConfigDetails.getSliceIdentifiers()); + assertEquals(aggregatedConfig, sliceConfigDetails.getAggregatedConfig()); + } + + @Test + public void RelationshipListEqualsTest() { + + AggregatedConfig aggregatedConfig = new AggregatedConfig(); + + SliceConfigDetails sliceConfigDetails = new SliceConfigDetails(); + sliceConfigDetails.setSliceIdentifiers("slice"); + sliceConfigDetails.setAggregatedConfig(aggregatedConfig); + + SliceConfigDetails sliceConfigDetails2 = new SliceConfigDetails(); + sliceConfigDetails2.setSliceIdentifiers("slice"); + sliceConfigDetails2.setAggregatedConfig(aggregatedConfig); + + + assertTrue(sliceConfigDetails2.equals(sliceConfigDetails)); + assertTrue(StringUtils.isNotBlank(sliceConfigDetails.toString())); + assertTrue(sliceConfigDetails.hashCode() != 0); + } + + @Test + public void equalsContract() { + EqualsVerifier.simple().forClass(SliceConfigDetails.class) + .withIgnoredAnnotations(NotEmpty.class) + .verify(); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/SliceConfigRequestTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/SliceConfigRequestTest.java new file mode 100644 index 00000000..bccc9b6b --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/SliceConfigRequestTest.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.models; + +import nl.jqno.equalsverifier.EqualsVerifier; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.validation.constraints.NotEmpty; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@SpringBootTest(classes = SliceConfigRequestTest.class) +public class SliceConfigRequestTest { + + @Test + public void SliceConfigRequestTest() { + + List<String> sliceIdentifiers = new ArrayList<>(); + List<String> configParams = new ArrayList<>(); + + SliceConfigRequest sliceConfigRequest = new SliceConfigRequest(); + sliceConfigRequest.setConfigParams(configParams); + sliceConfigRequest.setSliceIdentifiers(sliceIdentifiers); + + + assertEquals(sliceIdentifiers, sliceConfigRequest.getSliceIdentifiers()); + assertEquals(configParams, sliceConfigRequest.getConfigParams()); + } + + @Test + public void SliceConfigRequestEqualsTest() { + + List<String> sliceIdentifiers = new ArrayList<>(); + List<String> configParams = new ArrayList<>(); + + SliceConfigRequest sliceConfigRequest = new SliceConfigRequest(); + sliceConfigRequest.setConfigParams(configParams); + sliceConfigRequest.setSliceIdentifiers(sliceIdentifiers); + + SliceConfigRequest sliceConfigRequest1 = new SliceConfigRequest(); + sliceConfigRequest1.setConfigParams(configParams); + sliceConfigRequest1.setSliceIdentifiers(sliceIdentifiers); + + + assertTrue(sliceConfigRequest1.equals(sliceConfigRequest)); + assertTrue(StringUtils.isNotBlank(sliceConfigRequest.toString())); + assertTrue(sliceConfigRequest.hashCode() != 0); + } + @Test + public void equalsContract() { + EqualsVerifier.simple().forClass(SliceConfigRequest.class) + .withIgnoredAnnotations(NotEmpty.class) + .verify(); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/SliceConfigResponseTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/SliceConfigResponseTest.java new file mode 100644 index 00000000..c8373c86 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/SliceConfigResponseTest.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.models; + +import nl.jqno.equalsverifier.EqualsVerifier; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.validation.constraints.NotEmpty; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@SpringBootTest(classes = SliceConfigResponseTest.class) +public class SliceConfigResponseTest { + + @Test + public void SliceConfigResponseTest() { + + List<SliceConfigDetails> sliceConfigDetails = new ArrayList<>(); + + SliceConfigResponse sliceConfigResponse = new SliceConfigResponse(); + sliceConfigResponse.setSliceConfigDetails(sliceConfigDetails); + + + assertEquals(sliceConfigDetails, sliceConfigResponse.getSliceConfigDetails()); + } + + @Test + public void SliceConfigResponseEqualsTest() { + + List<SliceConfigDetails> sliceConfigDetails = new ArrayList<>(); + + SliceConfigResponse sliceConfigResponse = new SliceConfigResponse(); + sliceConfigResponse.setSliceConfigDetails(sliceConfigDetails); + + SliceConfigResponse sliceConfigResponse1 = new SliceConfigResponse(); + sliceConfigResponse1.setSliceConfigDetails(sliceConfigDetails); + + + assertTrue(sliceConfigResponse1.equals(sliceConfigResponse)); + assertTrue(StringUtils.isNotBlank(sliceConfigResponse.toString())); + assertTrue(sliceConfigResponse.hashCode() != 0); + } + @Test + public void equalsContract() { + EqualsVerifier.simple().forClass(SliceConfigResponse.class) + .withIgnoredAnnotations(NotEmpty.class) + .verify(); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/aai/RelationshipListTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/aai/RelationshipListTest.java new file mode 100644 index 00000000..8ecd395b --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/aai/RelationshipListTest.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.models.aai; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.JsonArray; +import nl.jqno.equalsverifier.EqualsVerifier; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.google.gson.JsonObject; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@SpringBootTest(classes = RelationshipListTest.class) +public class RelationshipListTest { + + @Test + public void RelationshipListTest() throws JsonProcessingException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("related-to", "related-to"); + jsonObject.addProperty("relationship-label", "relationship-label"); + jsonObject.addProperty("related-link", "related-link"); + + JsonArray relationshipData = new JsonArray(); + JsonObject relationshipDataObj = new JsonObject(); + relationshipDataObj.addProperty("a","1"); + relationshipData.add(relationshipDataObj); + JsonArray relatedToProperty = new JsonArray(); + JsonObject relatedToPropertyObj = new JsonObject(); + relatedToPropertyObj.addProperty("a","1"); + relatedToProperty.add(relatedToPropertyObj); + + jsonObject.add("relationship-data", relationshipData); + jsonObject.add("related-to-property", relatedToProperty); + + Relationship relationship = new ObjectMapper().readValue(jsonObject.toString(), Relationship.class); + + List<Relationship> relationships = new ArrayList<>(); + relationships.add(relationship); + + RelationshipList relationshipList = new RelationshipList(); + relationshipList.setRelationship(relationships); + + assertEquals(1, relationshipList.getRelationship().size()); + } + + @Test + public void RelationshipListEqualsTest() throws JsonProcessingException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("related-to", "related-to"); + jsonObject.addProperty("relationship-label", "relationship-label"); + jsonObject.addProperty("related-link", "related-link"); + + JsonArray relationshipData = new JsonArray(); + JsonObject relationshipDataObj = new JsonObject(); + relationshipDataObj.addProperty("a","1"); + relationshipData.add(relationshipDataObj); + JsonArray relatedToProperty = new JsonArray(); + JsonObject relatedToPropertyObj = new JsonObject(); + relatedToPropertyObj.addProperty("a","1"); + relatedToProperty.add(relatedToPropertyObj); + + jsonObject.add("relationship-data", relationshipData); + jsonObject.add("related-to-property", relatedToProperty); + + Relationship relationship = new ObjectMapper().readValue(jsonObject.toString(), Relationship.class); + + List<Relationship> relationships = new ArrayList<>(); + relationships.add(relationship); + + RelationshipList relationshipList = new RelationshipList(); + relationshipList.setRelationship(relationships); + + RelationshipList relationshipList1 = new RelationshipList(); + relationshipList1.setRelationship(relationships); + + assertTrue(relationshipList1.equals(relationshipList)); + assertTrue(StringUtils.isNotBlank(relationshipList.toString())); + } + @Test + public void equalsContract() { + EqualsVerifier.simple().forClass(RelationshipList.class) + .verify(); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/aai/RelationshipTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/aai/RelationshipTest.java new file mode 100644 index 00000000..764671a8 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/aai/RelationshipTest.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.models.aai; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.JsonArray; +import nl.jqno.equalsverifier.EqualsVerifier; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.google.gson.JsonObject; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@SpringBootTest(classes = RelationshipTest.class) +public class RelationshipTest { + + @Test + public void RelationshipTest() throws JsonProcessingException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("related-to", "related-to"); + jsonObject.addProperty("relationship-label", "relationship-label"); + jsonObject.addProperty("related-link", "related-link"); + + JsonArray relationshipData = new JsonArray(); + JsonObject relationshipDataObj = new JsonObject(); + relationshipDataObj.addProperty("a","1"); + relationshipData.add(relationshipDataObj); + JsonArray relatedToProperty = new JsonArray(); + JsonObject relatedToPropertyObj = new JsonObject(); + relatedToPropertyObj.addProperty("a","1"); + relatedToProperty.add(relatedToPropertyObj); + + jsonObject.add("relationship-data", relationshipData); + jsonObject.add("related-to-property", relatedToProperty); + + Relationship relationship = new ObjectMapper().readValue(jsonObject.toString(), Relationship.class); + assertEquals("related-to", relationship.getRelatedTo()); + assertEquals("relationship-label", relationship.getRelationshipLabel()); + assertEquals("related-link", relationship.getRelatedLink()); + assertEquals(1, relationship.getRelationshipData().size()); + assertEquals(1, relationship.getRelatedToProperty().size()); + } + + @Test + public void RelationshipEqualsTest() throws JsonProcessingException { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("related-to", "related-to"); + jsonObject.addProperty("relationship-label", "relationship-label"); + jsonObject.addProperty("related-link", "related-link"); + + JsonArray relationshipData = new JsonArray(); + JsonObject relationshipDataObj = new JsonObject(); + relationshipDataObj.addProperty("a","1"); + relationshipData.add(relationshipDataObj); + JsonArray relatedToProperty = new JsonArray(); + JsonObject relatedToPropertyObj = new JsonObject(); + relatedToPropertyObj.addProperty("a","1"); + relatedToProperty.add(relatedToPropertyObj); + + jsonObject.add("relationship-data", relationshipData); + jsonObject.add("related-to-property", relatedToProperty); + + Relationship relationship = new ObjectMapper().readValue(jsonObject.toString(), Relationship.class); + Relationship relationship1 = new ObjectMapper().readValue(jsonObject.toString(), Relationship.class); + + assertTrue(relationship1.equals(relationship)); + assertTrue(StringUtils.isNotBlank(relationship1.toString())); + + } + + @Test + public void equalsContract() { + EqualsVerifier.simple().forClass(Relationship.class) + .verify(); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/aai/ServiceInstanceTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/aai/ServiceInstanceTest.java new file mode 100644 index 00000000..8f275905 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/aai/ServiceInstanceTest.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.models.aai; + +import nl.jqno.equalsverifier.EqualsVerifier; +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@SpringBootTest(classes = ServiceInstanceTest.class) +public class ServiceInstanceTest { + + @Test + public void ServiceInstanceTest() { + + ServiceInstance serviceInstance = new ServiceInstance(); + serviceInstance.setServiceInstanceId("service-instance-id"); + serviceInstance.setServiceInstanceName("service-instance-name"); + serviceInstance.setServiceType("service-type"); + serviceInstance.setServiceRole("service-role"); + serviceInstance.setEnvironmentContext("environment-context"); + serviceInstance.setWorkloadContext("workload-context"); + serviceInstance.setOrchestrationStatus("orchestration-status"); + List<Relationship> relationships = new ArrayList<>(); + RelationshipList relationshipList = new RelationshipList(); + relationshipList.setRelationship(relationships); + serviceInstance.setRelationshipList(relationshipList); + + + assertEquals("service-instance-id", serviceInstance.getServiceInstanceId()); + assertEquals("service-instance-name", serviceInstance.getServiceInstanceName()); + assertEquals("service-type", serviceInstance.getServiceType()); + assertEquals("service-role", serviceInstance.getServiceRole()); + assertEquals("environment-context", serviceInstance.getEnvironmentContext()); + assertEquals("workload-context", serviceInstance.getWorkloadContext()); + assertEquals("orchestration-status", serviceInstance.getOrchestrationStatus()); + assertEquals(0, serviceInstance.getRelationshipList().getRelationship().size()); + } + + @Test + public void ServiceInstanceEqualsTest() { + + ServiceInstance serviceInstance = new ServiceInstance(); + serviceInstance.setServiceInstanceId("service-instance-id"); + serviceInstance.setServiceInstanceName("service-instance-name"); + serviceInstance.setServiceType("service-type"); + serviceInstance.setServiceRole("service-role"); + serviceInstance.setEnvironmentContext("environment-context"); + serviceInstance.setWorkloadContext("workload-context"); + serviceInstance.setOrchestrationStatus("orchestration-status"); + List<Relationship> relationships = new ArrayList<>(); + RelationshipList relationshipList = new RelationshipList(); + relationshipList.setRelationship(relationships); + serviceInstance.setRelationshipList(relationshipList); + + ServiceInstance serviceInstance1 = new ServiceInstance(); + serviceInstance1.setServiceInstanceId("service-instance-id"); + serviceInstance1.setServiceInstanceName("service-instance-name"); + serviceInstance1.setServiceType("service-type"); + serviceInstance1.setServiceRole("service-role"); + serviceInstance1.setEnvironmentContext("environment-context"); + serviceInstance1.setWorkloadContext("workload-context"); + serviceInstance1.setOrchestrationStatus("orchestration-status"); + List<Relationship> relationships1 = new ArrayList<>(); + RelationshipList relationshipList1 = new RelationshipList(); + relationshipList1.setRelationship(relationships1); + serviceInstance1.setRelationshipList(relationshipList1); + + assertTrue(serviceInstance1.equals(serviceInstance)); + assertTrue(StringUtils.isNotBlank(serviceInstance.toString())); + } + + @Test + public void equalsContract() { + EqualsVerifier.simple().forClass(ServiceInstance.class) + .verify(); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/vesnotification/VesModelsTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/vesnotification/VesModelsTest.java new file mode 100644 index 00000000..78cb635c --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/models/vesnotification/VesModelsTest.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.models.vesnotification; + +import com.openpojo.reflection.PojoClass; +import com.openpojo.reflection.impl.PojoClassFactory; +import com.openpojo.validation.Validator; +import com.openpojo.validation.ValidatorBuilder; +import com.openpojo.validation.rule.impl.GetterMustExistRule; +import com.openpojo.validation.rule.impl.SetterMustExistRule; +import com.openpojo.validation.test.impl.GetterTester; +import com.openpojo.validation.test.impl.SetterTester; +import org.junit.Test; +import org.onap.slice.analysis.ms.models.policy.Payload; + +public class VesModelsTest { + + @Test + public void testGetterSetterArrayOfNamedHashMap() { + PojoClass pojoclass = PojoClassFactory.getPojoClass(ArrayOfNamedHashMap.class); + validateMd(pojoclass); + } + + @Test + public void testGetterSetterHashMap() { + PojoClass pojoclass = PojoClassFactory.getPojoClass(HashMap.class); + validateMd(pojoclass); + } + + @Test + public void testGetterSetterNotificationFields() { + PojoClass pojoclass = PojoClassFactory.getPojoClass(NotificationFields.class); + validateMd(pojoclass); + } + + public void validateMd(PojoClass pojoclass) { + Validator validator = ValidatorBuilder + .create() + .with(new SetterMustExistRule()) + .with(new GetterMustExistRule()) + .with(new SetterTester()) + .with(new GetterTester()) + .build(); + validator.validate(pojoclass); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ConsumerThreadTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ConsumerThreadTest.java new file mode 100644 index 00000000..6aaaed51 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ConsumerThreadTest.java @@ -0,0 +1,135 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.service; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.onap.slice.analysis.ms.configdb.IConfigDbService; +import org.onap.slice.analysis.ms.cps.CpsInterface; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.utils.BeanUtil; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.api.support.membermodification.MemberModifier; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.powermock.api.mockito.PowerMockito.doNothing; +import static org.powermock.api.mockito.PowerMockito.doReturn; +import static org.powermock.api.mockito.PowerMockito.doThrow; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@PrepareForTest({ BeanUtil.class }) +@SpringBootTest(classes = ConsumerThreadTest.class) +public class ConsumerThreadTest { + + private ConsumerThread consumerThread; + @Mock + private PmDataQueue pmDataQueue; + @Mock + private IConfigDbService iConfigDbService; + @Mock + private CpsInterface cpsInterface; + + @Before + public void before() throws IllegalAccessException { + + PowerMockito.mockStatic(BeanUtil.class); + when(BeanUtil.getBean(PmDataQueue.class)).thenReturn(pmDataQueue); + + when(BeanUtil.getBean(IConfigDbService.class)).thenReturn(iConfigDbService); + + when(BeanUtil.getBean(CpsInterface.class)).thenReturn(cpsInterface); + + consumerThread = PowerMockito.spy(new ConsumerThread()); + + + + + MemberModifier.field(ConsumerThread.class, "cpsInterface") + .set(consumerThread , cpsInterface); + MemberModifier.field(ConsumerThread.class, "samples") + .set(consumerThread , 1); + } + + @Test + public void run1Test(){ + String snssai = "snssai"; + doReturn("snssai").when(pmDataQueue).getSnnsaiFromQueue(); + List<String> nfs = new ArrayList<>(); + when(iConfigDbService.fetchNetworkFunctionsOfSnssai(Mockito.any())).thenReturn(nfs); + when(pmDataQueue.checkSamplesInQueue(Mockito.any(), Mockito.anyInt())).thenReturn(true); + + + SnssaiSamplesProcessor snssaiSamplesProcessor = PowerMockito.mock(SnssaiSamplesProcessor.class); + when(BeanUtil.getBean(SnssaiSamplesProcessor.class)).thenReturn(snssaiSamplesProcessor); + Mockito.when(snssaiSamplesProcessor.processSamplesOfSnnsai(snssai, nfs)).thenReturn(false); + Mockito.doNothing().when(pmDataQueue).putSnssaiToQueue(snssai); + doThrow(new RuntimeException()).when(pmDataQueue).putSnssaiToQueue(snssai); + consumerThread.run(); + assertEquals(1,1); + } + + @Test + public void run2Test(){ + Configuration.getInstance().setConfigDbEnabled(false); + String snssai = "snssai"; + doReturn("snssai").when(pmDataQueue).getSnnsaiFromQueue(); + List<String> nfs = new ArrayList<>(); + when(iConfigDbService.fetchNetworkFunctionsOfSnssai(Mockito.any())).thenReturn(nfs); + when(pmDataQueue.checkSamplesInQueue(Mockito.any(), Mockito.anyInt())).thenReturn(true); + + when(cpsInterface.fetchNetworkFunctionsOfSnssai(snssai)).thenThrow(new RuntimeException()); + + SnssaiSamplesProcessor snssaiSamplesProcessor = PowerMockito.mock(SnssaiSamplesProcessor.class); + when(BeanUtil.getBean(SnssaiSamplesProcessor.class)).thenReturn(snssaiSamplesProcessor); + Mockito.when(snssaiSamplesProcessor.processSamplesOfSnnsai(snssai, nfs)).thenReturn(false); + Mockito.doNothing().when(pmDataQueue).putSnssaiToQueue(snssai); + doThrow(new RuntimeException()).when(pmDataQueue).putSnssaiToQueue(snssai); + consumerThread.run(); + assertEquals(1,1); + } + + @Test + public void checkForEnoughSamplesTest(){ + List<String> nfs = new ArrayList<>(); + nfs.add(""); + when(pmDataQueue.checkSamplesInQueue(Mockito.any(), Mockito.anyInt())).thenReturn(false); + doNothing().when(pmDataQueue).putSnssaiToQueue(Mockito.any()); + assertFalse(consumerThread.checkForEnoughSamples(nfs, "")); + + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/MLMessageProcessorTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/MLMessageProcessorTest.java index 6e0d1243..7223ecdd 100644 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/MLMessageProcessorTest.java +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/MLMessageProcessorTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * slice-analysis-ms * ================================================================================ - * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2020-2022 Wipro Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,16 @@ package org.onap.slice.analysis.ms.service; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.anyMap; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; @@ -29,73 +39,67 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; - import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.onap.slice.analysis.ms.aai.AaiService; import org.onap.slice.analysis.ms.configdb.IConfigDbService; -import org.onap.slice.analysis.ms.configdb.AaiService; -import org.onap.slice.analysis.ms.configdb.CpsService; +import org.onap.slice.analysis.ms.cps.CpsService; import org.onap.slice.analysis.ms.models.MLOutputModel; import org.onap.slice.analysis.ms.models.policy.AdditionalProperties; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; - @RunWith(SpringRunner.class) @SpringBootTest(classes = MLMessageProcessorTest.class) public class MLMessageProcessorTest { - ObjectMapper obj = new ObjectMapper(); - - @InjectMocks - private MLMessageProcessor mlMessageProcessor; - - @Mock - private IConfigDbService configDbService; + ObjectMapper obj = new ObjectMapper(); + + @InjectMocks + private MLMessageProcessor mlMessageProcessor; + + @Mock + private IConfigDbService configDbService; + + @Mock + AaiService aaiService; + + @Mock + CpsService cpsService; - @Mock - AaiService aaiService; + @Mock + private PolicyService policyService; - @Mock - CpsService cpsService; + @SuppressWarnings({"unchecked"}) + @Test + public void processMLMsgTest() { + MLOutputModel mloutput = null; + MLOutputModel mloutputExp = null; - @Mock - private PolicyService policyService; - - @SuppressWarnings({"unchecked" }) - @Test - public void processMLMsgTest() { - MLOutputModel mloutput = null; - MLOutputModel mloutputExp = null; + Map<String, List<String>> ricToCellMapping = new HashMap<>(); + List<String> myList = new ArrayList<String>(); + myList.add("111"); + myList.add("112"); + ricToCellMapping.put("12", myList); + myList = new ArrayList<String>(); + myList.add("113"); + myList.add("114"); + ricToCellMapping.put("13", myList); - Map<String, List<String>> ricToCellMapping = new HashMap<>(); - List<String> myList = new ArrayList<String>(); - myList.add("111"); - myList.add("112"); - ricToCellMapping.put("12", myList); - myList = new ArrayList<String>(); - myList.add("113"); - myList.add("114"); - ricToCellMapping.put("13", myList); + try { + mloutput = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/MLOutputModel.json"))),new TypeReference<MLOutputModel>() {}); + mloutputExp = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/MLOutputModel.json"))),new TypeReference<MLOutputModel>() {}); + } catch (IOException e) { + e.printStackTrace(); + } + when(configDbService.fetchCUCPCellsOfSnssai("0001-0111")).thenReturn(ricToCellMapping); + AdditionalProperties<MLOutputModel> addProps = new AdditionalProperties<>(); + addProps.setResourceConfig(mloutputExp); + doNothing().when(policyService).sendOnsetMessageToPolicy(anyString(), any(AdditionalProperties.class), + anyMap()); + mlMessageProcessor.processMLMsg(mloutput); + assertEquals(mloutputExp, mloutput); + } - try { - mloutput = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/MLOutputModel1.json"))), new TypeReference<MLOutputModel>(){}); - mloutputExp = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/MLOutputModel.json"))), new TypeReference<MLOutputModel>(){}); - } - catch (IOException e) { - e.printStackTrace(); - } - when(configDbService.fetchRICsOfSnssai("0001-0111")).thenReturn(ricToCellMapping); - AdditionalProperties<MLOutputModel> addProps = new AdditionalProperties<>(); - addProps.setResourceConfig(mloutputExp); - doNothing().when(policyService).sendOnsetMessageToPolicy(anyString(), any(AdditionalProperties.class), anyMap()); - mlMessageProcessor.processMLMsg(mloutput); - assertEquals(mloutputExp, mloutput); - } - } diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/PmThreadTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/PmThreadTest.java new file mode 100644 index 00000000..6308a21c --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/PmThreadTest.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.service; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.onap.slice.analysis.ms.data.repository.PerformanceNotificationsRepository; +import org.onap.slice.analysis.ms.dmaap.NewPmNotification; +import org.onap.slice.analysis.ms.models.MeasurementObject; +import org.onap.slice.analysis.ms.utils.BeanUtil; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.powermock.api.mockito.PowerMockito.doNothing; +import static org.powermock.api.mockito.PowerMockito.doThrow; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@PowerMockRunnerDelegate(SpringRunner.class) +@PrepareForTest({ BeanUtil.class }) +@SpringBootTest(classes = PmThreadTest.class) +public class PmThreadTest { + + private PmThread pmThread; + @Mock + private NewPmNotification newPmNotification; + @Mock + private PerformanceNotificationsRepository performanceNotificationsRepository; + @Mock + private IPmEventProcessor pmEventProcessor; + @Mock + private PmDataQueue pmDataQueue; + + @Before + public void before() throws IllegalAccessException { + + PowerMockito.mockStatic(BeanUtil.class); + when(BeanUtil.getBean(NewPmNotification.class)).thenReturn(newPmNotification); + + when(BeanUtil.getBean(PerformanceNotificationsRepository.class)).thenReturn(performanceNotificationsRepository); + + when(BeanUtil.getBean(PmDataQueue.class)).thenReturn(pmDataQueue); + + when(BeanUtil.getBean(IPmEventProcessor.class)).thenReturn(pmEventProcessor); + + pmThread = PowerMockito.spy(new PmThread()); + } + + @Test + public void runTest(){ + + when(newPmNotification.getNewNotif()).thenReturn(true); + + String pmNotificationString = "{" + + " \"event\":{" + + " \"commonEventHeader\":null," + + " \"perf3gppFields\":{" + + " \"perf3gppFieldsVersion\":\"\"," + + " \"measDataCollection\":{" + + " \"granularityPeriod\":1," + + " \"measuredEntityUserName\":\"measuredEntityUserName\"," + + " \"measuredEntityDn\":\"measuredEntityDn\"," + + " \"measuredEntitySoftwareVersion\":\"measuredEntitySoftwareVersion\"," + + " \"measInfoList\":[" + + "" + + " ]" + + " }" + + " }" + + " }" + + "}"; + when(performanceNotificationsRepository.getPerformanceNotificationFromQueue()).thenReturn(pmNotificationString); + + Map<String, List<MeasurementObject>> processedData = new HashMap<>(); + processedData.put("k", null); + when(pmEventProcessor.processEvent(any())).thenReturn(processedData); + doNothing().when(pmDataQueue).putDataToQueue(any(), any()); + doThrow(new RuntimeException()).when(pmDataQueue).putSnssaiToQueue(any()); + pmThread.run(); + Mockito.verify(pmDataQueue, Mockito.times(1)).putDataToQueue(any(), any()); + } + +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/PolicyServiceTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/PolicyServiceTest.java index fef9eb35..7ac92f29 100644 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/PolicyServiceTest.java +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/PolicyServiceTest.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 Huawei Canada Limited. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,6 +35,7 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.onap.slice.analysis.ms.models.policy.AdditionalProperties; import org.onap.slice.analysis.ms.models.policy.OnsetMessage; +import org.onap.slice.analysis.ms.service.ccvpn.RequestOwner; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @@ -44,41 +46,61 @@ import com.google.gson.Gson; @RunWith(SpringRunner.class) @SpringBootTest(classes = PolicyServiceTest.class) public class PolicyServiceTest { - ObjectMapper obj = new ObjectMapper(); - - @InjectMocks - PolicyService policyService; - - @Test - public void formPolicyOnsetMessageTest() { - String snssai = "001-100001"; - Map<String, String> input = null; - OnsetMessage output = null; - String expected = ""; - String actual = ""; - Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); - Map<String, Integer> ric1 = new HashMap<>(); - Map<String, Integer> ric2 = new HashMap<>(); - ric1.put("dLThptPerSlice",50); - ric1.put("uLThptPerSlice",40); - ric2.put("dLThptPerSlice",50); - ric2.put("uLThptPerSlice",30); - ricToThroughputMapping.put("1", ric1); - ricToThroughputMapping.put("2", ric2); - try { - input = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/serviceDetails.json"))), new TypeReference<Map<String,String>>(){}); - output = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/onsetMessage.json"))), OnsetMessage.class); - expected = obj.writeValueAsString(output); - } - catch (IOException e) { - e.printStackTrace(); - } + ObjectMapper obj = new ObjectMapper(); + + @InjectMocks + PolicyService policyService; + + @Test + public void formPolicyOnsetMessageTest() { + String snssai = "001-100001"; + Map<String, String> input = null; + OnsetMessage output = null; + String expected = ""; + String actual = ""; + Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); + Map<String, Integer> ric1 = new HashMap<>(); + Map<String, Integer> ric2 = new HashMap<>(); + ric1.put("dLThptPerSlice",50); + ric1.put("uLThptPerSlice",40); + ric2.put("dLThptPerSlice",50); + ric2.put("uLThptPerSlice",30); + ricToThroughputMapping.put("1", ric1); + ricToThroughputMapping.put("2", ric2); + try { + input = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/serviceDetails.json"))), new TypeReference<Map<String,String>>(){}); + output = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/onsetMessage.json"))), OnsetMessage.class); + expected = obj.writeValueAsString(output); + } + catch (IOException e) { + e.printStackTrace(); + } AdditionalProperties<Map<String, Map<String, Integer>>> addProps = new AdditionalProperties<>(); - addProps.setResourceConfig(ricToThroughputMapping); + addProps.setResourceConfig(ricToThroughputMapping); actual = new Gson().toJson(policyService.formPolicyOnsetMessage(snssai,addProps,input)); - + + assertThatJson(actual) + .whenIgnoringPaths("requestID","payload","closedLoopAlarmStart", "AAI", "target_type", "aai", "targetType") + .isEqualTo(expected); + } + + @Test + public void formPolicyOnsetMessageForCCVPNTest() { + String cllId = "cll-instance-01"; + OnsetMessage output = null; + String expected = ""; + String actual = ""; + try { + output = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/onsetMessage2.json"))), OnsetMessage.class); + expected = obj.writeValueAsString(output); + actual = new Gson().toJson(policyService + .formPolicyOnsetMessageForCCVPN(cllId, 3000, RequestOwner.UUI)); + } + catch (IOException e) { + e.printStackTrace(); + } assertThatJson(actual) - .whenIgnoringPaths("requestID","payload","closedLoopAlarmStart", "AAI", "target_type", "aai", "targetType") - .isEqualTo(expected); - } + .whenIgnoringPaths("requestID","payload","closedLoopAlarmStart", "AAI", "target_type", "aai", "targetType") + .isEqualTo(expected); + } } diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/RateLimiterTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/RateLimiterTest.java new file mode 100644 index 00000000..3f27a3e1 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/RateLimiterTest.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class RateLimiterTest { + + RateLimiter rateLimiter; + + @Before + public void setUp() throws Exception { + rateLimiter = new RateLimiter(1, 5000); + } + + @Test + public void getTokenTest() throws InterruptedException { + rateLimiter.getToken(); + long requestTime1 = System.currentTimeMillis(); + rateLimiter.getToken(); + long requestTime2 = System.currentTimeMillis(); + assertTrue("Actually is: " + (requestTime2 - requestTime1) + , requestTime2 - requestTime1 >= 5000); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/SliceUtilizationTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/SliceUtilizationTest.java new file mode 100644 index 00000000..1de57060 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/SliceUtilizationTest.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.service; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.onap.slice.analysis.ms.aai.AaiService; +import org.onap.slice.analysis.ms.models.AggregatedConfig; +import org.onap.slice.analysis.ms.models.Configuration; +import org.onap.slice.analysis.ms.models.SliceConfigRequest; +import org.onap.slice.analysis.ms.models.SliceConfigResponse; +import org.onap.slice.analysis.ms.restclients.DesRestClient; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(SpringRunner.class) +@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"}) +@SpringBootTest(classes = SliceUtilizationTest.class) +public class SliceUtilizationTest { + + ObjectMapper objectMapper = new ObjectMapper(); + + Configuration configuration = Configuration.getInstance(); + + @InjectMocks + SliceUtilization sliceUtilization; + + @Mock + AaiService aaiService; + + @Mock + DesRestClient desRestClient; + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void getPmDataTest() throws IOException { + configuration.setDesUrl("http://des:1681/datalake/v1/exposure/pm_data"); + configuration.setPmDataDurationInWeeks(4); + String pmData = new String(Files.readAllBytes(Paths.get("src/test/resources/pm_data.json"))); + Mockito.when(desRestClient.sendPostRequest(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(new ResponseEntity<>(pmData, HttpStatus.OK)); + JSONObject actualResponse = sliceUtilization.getPMData("001-1100"); + assertTrue(actualResponse.has("result")); + + } + + @Test + public void calculateSliceUtilizationTest() throws IOException { + + List<JSONObject> pmDataList = new ArrayList<>(); + String pmData; + pmData = new String(Files.readAllBytes(Paths.get("src/test/resources/pm_data.json"))); + JSONObject pmDataObj = new JSONObject(pmData); + pmDataList.add(pmDataObj); + pmDataList.add(pmDataObj); + pmDataList.add(pmDataObj); + AggregatedConfig actualResponse = sliceUtilization.calculateSliceUtilization(pmDataList); + assertEquals(190857028, (int) actualResponse.getDLThptPerSlice()); + assertEquals(119285978, (int) actualResponse.getULThptPerSlice()); + } + + @Test + public void getSliceUtilizationDataTest() throws IOException { + + SliceConfigRequest sliceConfigRequest = new SliceConfigRequest(); + List<String> sliceIdentifiersList = new ArrayList<>(); + sliceIdentifiersList.add("14559ead-f4fe-4c1c-a94c-8015fad3ea35"); + sliceIdentifiersList.add("14559ead-f4fe-4c1c-a94c-8015fad3ea36"); + sliceConfigRequest.setSliceIdentifiers(sliceIdentifiersList); + List<String> configParamsList = new ArrayList<>(); + configParamsList.add("dLThptPerSlice"); + configParamsList.add("uLThptPerSlice"); + sliceConfigRequest.setConfigParams(configParamsList); + List<String> snssaiList = new ArrayList<>(); + snssaiList.add("01-06E442"); + snssaiList.add("01-B989BD"); + configuration.setDesUrl("http://des:1681/datalake/v1/exposure/pm_data"); + configuration.setPmDataDurationInWeeks(4); + + Mockito.when(aaiService.getSnssaiList(Mockito.any())).thenReturn(snssaiList); + + String pmData = new String(Files.readAllBytes(Paths.get("src/test/resources/pm_data.json"))); + Mockito.when(desRestClient.sendPostRequest(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(new ResponseEntity<>(pmData, HttpStatus.OK)); + SliceConfigResponse actualResponse = sliceUtilization.getSliceUtilizationData(sliceConfigRequest); + String actualResponseString = objectMapper.writeValueAsString(actualResponse); + SliceConfigResponse sliceConfigResponse = objectMapper + .readValue(new File("src/test/resources/sliceConfigResponse.json"), SliceConfigResponse.class); + assertEquals(objectMapper.writeValueAsString(sliceConfigResponse), actualResponseString); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessorTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessorTest.java index e8cc2145..edc4f43b 100644 --- a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessorTest.java +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/SnssaiSamplesProcessorTest.java @@ -3,6 +3,7 @@ * slice-analysis-ms * ================================================================================ * Copyright (C) 2020 Wipro Limited. + * Copyright (C) 2022 CTC, Inc. * ============================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,10 +23,18 @@ package org.onap.slice.analysis.ms.service; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -34,7 +43,15 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.onap.slice.analysis.ms.aai.AaiInterface; +import org.onap.slice.analysis.ms.configdb.IConfigDbService; +import org.onap.slice.analysis.ms.cps.CpsInterface; +import org.onap.slice.analysis.ms.models.Configuration; import org.onap.slice.analysis.ms.models.MeasurementObject; +import org.onap.slice.analysis.ms.models.SubCounter; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.util.ReflectionTestUtils; @@ -43,151 +60,226 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; @RunWith(SpringRunner.class) +@PrepareForTest(SnssaiSamplesProcessor.class) @SpringBootTest(classes = SnssaiSamplesProcessorTest.class) public class SnssaiSamplesProcessorTest { - ObjectMapper obj = new ObjectMapper(); - - @InjectMocks - SnssaiSamplesProcessor snssaiSamplesProcessor; - - @Before - public void setup() { - Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); - Map<String, Integer> ric1 = new HashMap<>(); - Map<String, Integer> ric2 = new HashMap<>(); - ric1.put("dLThptPerSlice",50); - ric1.put("uLThptPerSlice",40); - ric2.put("dLThptPerSlice",50); - ric2.put("uLThptPerSlice",30); - ricToThroughputMapping.put("1", ric1); - ricToThroughputMapping.put("2", ric2); - ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToThroughputMapping", ricToThroughputMapping); - - Map<String, Map<String, Integer>> ricToPrbsMapping = null; - List<MeasurementObject> sliceMeasList = null; - Map<String, List<String>> ricToCellMapping = null; - Map<String, String> prbThroughputMapping = new HashMap<>(); - prbThroughputMapping = new HashMap<>(); - prbThroughputMapping.put("PrbUsedDl", "dLThptPerSlice"); - prbThroughputMapping.put("PrbUsedUl", "uLThptPerSlice"); - - try { - ricToPrbsMapping = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/ricToPrbMap.json"))), new TypeReference<Map<String, Map<String, Integer>>>(){}); - sliceMeasList = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/sliceMeasurementList.json"))), new TypeReference<List<MeasurementObject>>(){}); - ricToCellMapping = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/ricToCellMapping.json"))), new TypeReference<Map<String, List<String>>>(){}); - } - catch (IOException e) { - e.printStackTrace(); - } - ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToPrbsMapping", ricToPrbsMapping); - ReflectionTestUtils.setField(snssaiSamplesProcessor, "minPercentageChange", 6); - ReflectionTestUtils.setField(snssaiSamplesProcessor, "snssaiMeasurementList", sliceMeasList); - ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToCellMapping", ricToCellMapping); - ReflectionTestUtils.setField(snssaiSamplesProcessor, "prbThroughputMapping", prbThroughputMapping); - } - - @Test - public void computeSumTest() { - assertEquals(Integer.valueOf(100), snssaiSamplesProcessor.computeSum("PrbUsedDl")); - } - - @Test - public void updateConfigurationTest() { - Map<String, Map<String, Integer>> ricToThroughputMappingExp = new HashMap<>(); - Map<String, Integer> ric1 = new HashMap<>(); - Map<String, Integer> ric2 = new HashMap<>(); - ric1.put("dLThptPerSlice",50); - ric1.put("uLThptPerSlice",40); - ric2.put("dLThptPerSlice",50); - ric2.put("uLThptPerSlice",30); - ricToThroughputMappingExp.put("1", ric1); - ricToThroughputMappingExp.put("2", ric2); - snssaiSamplesProcessor.updateConfiguration(); - assertEquals(ricToThroughputMappingExp,ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToThroughputMapping")); - } - - @Test - public void updateConfigurationTrueTest() { - Map<String, Map<String, Integer>> ricToThroughputMappingExp = new HashMap<>(); - Map<String, Integer> ric2 = new HashMap<>(); - ric2.put("dLThptPerSlice",50); - ric2.put("uLThptPerSlice",30); - ricToThroughputMappingExp.put("2", ric2); - - Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); - Map<String, Integer> ric1 = new HashMap<>(); - ric2 = new HashMap<>(); - ric2.put("dLThptPerSlice",50); - ric2.put("uLThptPerSlice",30); - ricToThroughputMapping.put("1", ric1); - ricToThroughputMapping.put("2", ric2); - ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToThroughputMapping", ricToThroughputMapping); - - snssaiSamplesProcessor.updateConfiguration(); - System.out.println(); - assertEquals(ricToThroughputMappingExp, ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToThroughputMapping")); - } - - @Test - public void calculatePercentageChangeTest() { - Map<String, Map<String, Object>> ricConfiguration = null; - Map<String, Map<String, Integer>> exp = new HashMap<>(); - Map<String, Integer> ric1 = new HashMap<>(); - Map<String, Integer> ric2 = new HashMap<>(); - ric1.put("dLThptPerSlice", 50); - ric2.put("dLThptPerSlice", 50); - ric2.put("uLThptPerSlice", 30); - exp.put("1", ric1); - exp.put("2", ric2); - try { - ricConfiguration = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/ricConfiguration.json"))), new TypeReference<Map<String, Map<String, Object>>>(){}); - } - catch (IOException e) { - e.printStackTrace(); - } - snssaiSamplesProcessor.calculatePercentageChange(ricConfiguration, "uLThptPerSlice"); - assertEquals(exp,ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToThroughputMapping")); - - ricConfiguration.get("2").put("dLThptPerSlice",60); - exp.get("1").remove("dLThptPerSlice"); - snssaiSamplesProcessor.calculatePercentageChange(ricConfiguration, "dLThptPerSlice"); - assertEquals(exp,ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToThroughputMapping")); - } - - @Test - public void sumOfPrbsAcrossCellsTest() { - Map<String, Map<String, Integer>> ricToPrbsMapping = new HashMap<>(); - Map<String, Map<String, Integer>> ricToPrbsMappingExp = new HashMap<>(); - - ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToPrbsMapping", ricToPrbsMapping); - - try { - ricToPrbsMappingExp = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/ricToPrbOutput.json"))), new TypeReference<Map<String, Map<String, Integer>>>(){}); - } - catch (IOException e) { - e.printStackTrace(); - } + ObjectMapper obj = new ObjectMapper(); + + @InjectMocks + SnssaiSamplesProcessor snssaiSamplesProcessor; + @Mock + private PolicyService policyService; + + @Mock + private PmDataQueue pmDataQueue; + + @Mock + private AverageCalculator averageCalculator; + + @Mock + private IConfigDbService configDbService; + + @Mock + private AaiInterface aaiInterface; + + @Mock + private CpsInterface cpsInterface; + + @Before + public void setup() throws IOException { + Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); + Map<String, Integer> ric1 = new HashMap<>(); + Map<String, Integer> ric2 = new HashMap<>(); + ric1.put("dLThptPerSlice",50); + ric1.put("uLThptPerSlice",40); + ric2.put("dLThptPerSlice",50); + ric2.put("uLThptPerSlice",30); + ricToThroughputMapping.put("1", ric1); + ricToThroughputMapping.put("2", ric2); + ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToThroughputMapping", ricToThroughputMapping); + + Map<String, Map<String, Integer>> ricToPrbsMapping = null; + List<MeasurementObject> sliceMeasList = null; + Map<String, List<String>> ricToCellMapping = null; + Map<String, String> prbThroughputMapping = new HashMap<>(); + prbThroughputMapping = new HashMap<>(); + prbThroughputMapping.put("PrbUsedDl", "dLThptPerSlice"); + prbThroughputMapping.put("PrbUsedUl", "uLThptPerSlice"); + + ricToPrbsMapping = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/ricToPrbMap.json"))), new TypeReference<Map<String, Map<String, Integer>>>(){}); + sliceMeasList = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/sliceMeasurementList.json"))), new TypeReference<List<MeasurementObject>>(){}); + ricToCellMapping = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/ricToCellMapping.json"))), new TypeReference<Map<String, List<String>>>(){}); + ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToPrbsMapping", ricToPrbsMapping); + ReflectionTestUtils.setField(snssaiSamplesProcessor, "minPercentageChange", 6); + ReflectionTestUtils.setField(snssaiSamplesProcessor, "snssaiMeasurementList", sliceMeasList); + ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToCellMapping", ricToCellMapping); + ReflectionTestUtils.setField(snssaiSamplesProcessor, "prbThroughputMapping", prbThroughputMapping); + } + + + @Test + public void processSamplesOfSnnsaiTest() { + List<List<MeasurementObject>> samples = new ArrayList<>(); + when(pmDataQueue.getSamplesFromQueue(any(SubCounter.class),anyInt())).thenReturn(samples); + List<MeasurementObject> sample = new ArrayList<>(); + when(averageCalculator.findAverageOfSamples(samples)).thenReturn(sample); + + Map<String, List<String>> ricToCellMapping = new HashMap<>(); + when(configDbService.fetchRICsOfSnssai(any())).thenReturn(ricToCellMapping); + Map<String, Map<String, Object>> ricConfiguration = new HashMap<>(); + when(configDbService.fetchCurrentConfigurationOfRIC(any())).thenReturn(ricConfiguration); + Map<String, Integer> sliceConfiguration = new HashMap<>(); + when(configDbService.fetchCurrentConfigurationOfSlice(any())).thenReturn(sliceConfiguration); + Map<String, String> serviceDetails = new HashMap<>(); + when(configDbService.fetchServiceDetails(any())).thenReturn(serviceDetails); + + List<String> networkFunctions = new ArrayList<>(); + networkFunctions.add("nf1"); + SnssaiSamplesProcessor spy = PowerMockito.spy(snssaiSamplesProcessor); + doNothing().when(spy).sumOfPrbsAcrossCells(anyString()); + doReturn(1).when(spy).computeSum(any()); + doNothing().when(spy).computeThroughput(any(),anyInt(),any()); + doNothing().when(spy).calculatePercentageChange(any(),any()); + doNothing().when(spy).updateConfiguration(); + + Map<String, List<Map<String, Integer>>> map = new HashMap<>(); + doReturn(map).when(spy).getChangedRIConfigFormat(any()); + doNothing().when(policyService).sendOnsetMessageToPolicy(any(),any(), any()); + + spy.init(); + boolean b = spy.processSamplesOfSnnsai("", networkFunctions); + assertTrue(b); + + + } + @Test + public void processSamplesOfSnnsaiFalseTest() { + Configuration.getInstance().setConfigDbEnabled(false); + List<List<MeasurementObject>> samples = new ArrayList<>(); + when(pmDataQueue.getSamplesFromQueue(any(SubCounter.class),anyInt())).thenReturn(samples); + List<MeasurementObject> sample = new ArrayList<>(); + when(averageCalculator.findAverageOfSamples(samples)).thenReturn(sample); + + Map<String, List<String>> ricToCellMapping = new HashMap<>(); + when(cpsInterface.fetchRICsOfSnssai(any())).thenReturn(ricToCellMapping); + Map<String, Map<String, Object>> ricConfiguration = new HashMap<>(); + when(cpsInterface.fetchCurrentConfigurationOfRIC(any())).thenReturn(ricConfiguration); + Map<String, Integer> sliceConfiguration = new HashMap<>(); + when(aaiInterface.fetchCurrentConfigurationOfSlice(any())).thenReturn(sliceConfiguration); + Map<String, String> serviceDetails = new HashMap<>(); + when(aaiInterface.fetchServiceDetails(any())).thenReturn(serviceDetails); + + + List<String> networkFunctions = new ArrayList<>(); + networkFunctions.add("nf1"); + SnssaiSamplesProcessor spy = PowerMockito.spy(snssaiSamplesProcessor); + doNothing().when(spy).sumOfPrbsAcrossCells(anyString()); + doReturn(1).when(spy).computeSum(any()); + doNothing().when(spy).computeThroughput(any(),anyInt(),any()); + doNothing().when(spy).calculatePercentageChange(any(),any()); + doNothing().when(spy).updateConfiguration(); + + Map<String, List<Map<String, Integer>>> map = new HashMap<>(); + doReturn(map).when(spy).getChangedRIConfigFormat(any()); + doNothing().when(policyService).sendOnsetMessageToPolicy(any(),any(), any()); + + spy.init(); + boolean b = spy.processSamplesOfSnnsai("", networkFunctions); + assertTrue(b); + } + @Test + public void getChangedRIConfigFormatTest() { + Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); + Map<String, Integer> newConfigMap = new HashMap<>(); + ricToThroughputMapping.put("1", newConfigMap); + Map<String, List<Map<String, Integer>>> riConfigFormat = snssaiSamplesProcessor.getChangedRIConfigFormat(ricToThroughputMapping); + assertEquals(1, riConfigFormat.size()); + + } + + @Test + public void computeSumTest() { + assertEquals(Integer.valueOf(100), snssaiSamplesProcessor.computeSum("PrbUsedDl")); + } + + @Test + public void updateConfigurationTest() { + Map<String, Map<String, Integer>> ricToThroughputMappingExp = new HashMap<>(); + Map<String, Integer> ric1 = new HashMap<>(); + Map<String, Integer> ric2 = new HashMap<>(); + ric1.put("dLThptPerSlice",50); + ric1.put("uLThptPerSlice",40); + ric2.put("dLThptPerSlice",50); + ric2.put("uLThptPerSlice",30); + ricToThroughputMappingExp.put("1", ric1); + ricToThroughputMappingExp.put("2", ric2); + snssaiSamplesProcessor.updateConfiguration(); + assertEquals(ricToThroughputMappingExp,ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToThroughputMapping")); + } + + @Test + public void updateConfigurationTrueTest() { + Map<String, Map<String, Integer>> ricToThroughputMappingExp = new HashMap<>(); + Map<String, Integer> ric2 = new HashMap<>(); + ric2.put("dLThptPerSlice",50); + ric2.put("uLThptPerSlice",30); + ricToThroughputMappingExp.put("2", ric2); + + Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); + Map<String, Integer> ric1 = new HashMap<>(); + ric2 = new HashMap<>(); + ric2.put("dLThptPerSlice",50); + ric2.put("uLThptPerSlice",30); + ricToThroughputMapping.put("1", ric1); + ricToThroughputMapping.put("2", ric2); + ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToThroughputMapping", ricToThroughputMapping); + + snssaiSamplesProcessor.updateConfiguration(); + System.out.println(); + assertEquals(ricToThroughputMappingExp, ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToThroughputMapping")); + } + + @Test + public void calculatePercentageChangeTest() throws IOException { + Map<String, Map<String, Integer>> exp = new HashMap<>(); + Map<String, Integer> ric1 = new HashMap<>(); + Map<String, Integer> ric2 = new HashMap<>(); + ric1.put("dLThptPerSlice", 50); + ric2.put("dLThptPerSlice", 50); + ric2.put("uLThptPerSlice", 30); + exp.put("1", ric1); + exp.put("2", ric2); + Map<String, Map<String, Object>> ricConfiguration = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/ricConfiguration.json"))), new TypeReference<Map<String, Map<String, Object>>>(){}); + snssaiSamplesProcessor.calculatePercentageChange(ricConfiguration, "uLThptPerSlice"); + assertEquals(exp,ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToThroughputMapping")); + + ricConfiguration.get("2").put("dLThptPerSlice",60); + exp.get("1").remove("dLThptPerSlice"); + snssaiSamplesProcessor.calculatePercentageChange(ricConfiguration, "dLThptPerSlice"); + assertEquals(exp,ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToThroughputMapping")); + } + + @Test + public void sumOfPrbsAcrossCellsTest() throws IOException { + Map<String, Map<String, Integer>> ricToPrbsMapping = new HashMap<>(); + ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToPrbsMapping", ricToPrbsMapping); + + Map<String, Map<String, Integer>> ricToPrbsMappingExp = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/ricToPrbOutput.json"))), new TypeReference<Map<String, Map<String, Integer>>>(){}); snssaiSamplesProcessor.sumOfPrbsAcrossCells("PrbUsedDl"); assertEquals(ricToPrbsMappingExp, ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToPrbsMapping")); - } - - @Test - public void computeThroughputTest() { - Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); - ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToThroughputMapping", ricToThroughputMapping); - - Map<String, Map<String, Integer>> ricToThroughputMappingExp = new HashMap<>(); - try { - ricToThroughputMappingExp = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/ricToThroughputMappingOutput.json"))), new TypeReference<Map<String, Map<String, Integer>>>(){}); - } - catch (IOException e) { - e.printStackTrace(); - } - Map<String, Integer> sliceConfiguration = new HashMap<String, Integer>(); - sliceConfiguration.put("dLThptPerSlice",120); - sliceConfiguration.put("uLThptPerSlice",100); - snssaiSamplesProcessor.computeThroughput(sliceConfiguration, 100, "PrbUsedDl"); - snssaiSamplesProcessor.computeThroughput(sliceConfiguration, 70, "PrbUsedUl"); - assertEquals(ricToThroughputMappingExp, ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToThroughputMapping")); - } + } + + @Test + public void computeThroughputTest() throws IOException { + Map<String, Map<String, Integer>> ricToThroughputMapping = new HashMap<>(); + ReflectionTestUtils.setField(snssaiSamplesProcessor, "ricToThroughputMapping", ricToThroughputMapping); + + Map<String, Map<String, Integer>> ricToThroughputMappingExp = obj.readValue(new String(Files.readAllBytes(Paths.get("src/test/resources/ricToThroughputMappingOutput.json"))), new TypeReference<Map<String, Map<String, Integer>>>(){}); + Map<String, Integer> sliceConfiguration = new HashMap<String, Integer>(); + sliceConfiguration.put("dLThptPerSlice",120); + sliceConfiguration.put("uLThptPerSlice",100); + snssaiSamplesProcessor.computeThroughput(sliceConfiguration, 100, "PrbUsedDl"); + snssaiSamplesProcessor.computeThroughput(sliceConfiguration, 70, "PrbUsedUl"); + assertEquals(ricToThroughputMappingExp, ReflectionTestUtils.getField(snssaiSamplesProcessor, "ricToThroughputMapping")); + } } diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/BandwidthEvaluatorTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/BandwidthEvaluatorTest.java new file mode 100644 index 00000000..2d129393 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/BandwidthEvaluatorTest.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.service.ccvpn; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import java.util.ArrayList; +import java.util.List; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BandwidthEvaluatorTest.class) +public class BandwidthEvaluatorTest { + + FixedUpperBoundStrategy s1 = new FixedUpperBoundStrategy(); + FlexibleThresholdStrategy s2 = new FlexibleThresholdStrategy(); + + @Spy + private List<EvaluationStrategy> strategies = new ArrayList<>(); + + @Spy + @InjectMocks + StrategyFactory strategyFactory; + + @Spy + @InjectMocks + BandwidthEvaluator bandwidthEvaluator; + + @Before + public void setup(){ + MockitoAnnotations.initMocks(this); + strategies.add(s1); + strategies.add(s2); + } + + @Test + public void initTest(){ + bandwidthEvaluator.init(); + Mockito.verify(bandwidthEvaluator, Mockito.atLeastOnce()).init(); + } + + @Test + public void stopTest(){ + bandwidthEvaluator.init(); + bandwidthEvaluator.stop(); + Mockito.verify(bandwidthEvaluator, Mockito.atLeastOnce()).stop(); + } + + @Test + public void postTest() { + Event evt = new SimpleEvent(null, "{}"); + bandwidthEvaluator.post(evt); + Mockito.verify(bandwidthEvaluator, Mockito.atLeastOnce()).post(Mockito.any(Event.class)); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/CCVPNPmDatastoreTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/CCVPNPmDatastoreTest.java new file mode 100644 index 00000000..8b0b99f3 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/CCVPNPmDatastoreTest.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * Copyright (C) 2022 Huawei Technologies Co., Ltd. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.service.ccvpn; + +import java.util.HashSet; +import java.util.Set; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = CCVPNPmDatastoreTest.class) +public class CCVPNPmDatastoreTest { + + @Spy + @InjectMocks + CCVPNPmDatastore datastore; + + @Test + public void getUsedBwOfSvcTest() { + datastore.addUsedBwToEndpoint("cll-test", "uni-01", "100"); + datastore.addUsedBwToEndpoint("cll-test", "uni-01", "100"); + datastore.addUsedBwToEndpoint("cll-test", "uni-02", "100"); + datastore.addUsedBwToEndpoint("cll-test2", "uni-01", "100"); + assertEquals(datastore.getUsedBwOfSvc("cll-test").get(new Endpointkey("cll-test", "uni-01")).size(), + 2); + } + + @Test + public void getMaxBwOfSvcTest() { + datastore.updateProvBw("cll-test", 100, false); + assertEquals(datastore.getProvBwOfSvc("cll-test"), Integer.valueOf(100)); + } + + @Test + public void getStatusOfSvcTest() { + datastore.updateSvcState("cll-01", ServiceState.RUNNING); + assertEquals(datastore.getStatusOfSvc("cll-01"), ServiceState.RUNNING); + } + + @Test + public void getSvcStatusMapTest() { + datastore.updateSvcState("cll-01", ServiceState.RUNNING); + datastore.getSvcStatusMap(); + Mockito.verify(datastore, Mockito.atLeastOnce()).getSvcStatusMap(); + } + + @Test + public void getUsedBwMapTest() { + datastore.updateSvcState("cll-01", ServiceState.RUNNING); + datastore.getUsedBwMap(); + Mockito.verify(datastore, Mockito.atLeastOnce()).getUsedBwMap(); + } + + @Test + public void updateSvcStateTest() { + datastore.updateSvcState("cll-01", ServiceState.RUNNING); + assertEquals(datastore.getStatusOfSvc("cll-01"), ServiceState.RUNNING); + } + + @Test + public void readToArrayTest() { + for(int i = 0; i < 5; i++){ + datastore.addUsedBwToEndpoint("cll-01", "uni-n1", "300"); + } + assertTrue(Arrays.stream(datastore.readToArray("cll-01", "uni-n1")) + .mapToInt(o -> (int)o) + .allMatch(n -> n == 1)); + } + + @Test + public void updateMaxBwTest() throws NoSuchFieldException, IllegalAccessException { + datastore.updateProvBw("cll-01", "300"); + Mockito.verify(datastore, Mockito.atLeastOnce()).updateProvBw(Mockito.any(String.class), Mockito.any(String.class)); + } + + @Test + public void updateUpperBoundBwTest() throws NoSuchFieldException, IllegalAccessException { + datastore.updateUpperBoundBw("cll-01", 300); + Mockito.verify(datastore, Mockito.atLeastOnce()).updateUpperBoundBw(Mockito.any(String.class), Mockito.any(Integer.class)); + } + + @Test + public void addUsedBwToEndpointTest() { + datastore.addUsedBwToEndpoint("cll-01", "uni-n1", "300Mb"); + datastore.addUsedBwToEndpoint("cll-01", "uni-n1", "300mb"); + datastore.addUsedBwToEndpoint("cll-01", "uni-n1", "300Gb"); + datastore.addUsedBwToEndpoint("cll-01", "uni-n1", "300kb"); + assertTrue(datastore.readToArray("cll-01", "uni-n1") == null); + datastore.addUsedBwToEndpoint("cll-01", "uni-n1", "300.00"); + assertTrue(Arrays.stream(datastore.readToArray("cll-01", "uni-n1")) + .mapToInt(o -> (int)o) + .sum() == 300602 ); + } + + @Test + public void updateCllInstancesTest() { + datastore.addUsedBwToEndpoint("cll-01", "uni-n1", "300Mb"); + datastore.updateUpperBoundBw("cll-01", 300); + datastore.updateProvBw("cll-01", "300"); + datastore.updateSvcState("cll-01", ServiceState.RUNNING); + datastore.updateOriginalBw("cll-01", 1000); + datastore.updateClosedloopStatus("cll-01", true); + datastore.addUsedBwToEndpoint("cll-02", "uni-n2", "300Mb"); + datastore.updateUpperBoundBw("cll-02", 300); + datastore.updateProvBw("cll-02", "300"); + datastore.updateSvcState("cll-02", ServiceState.RUNNING); + datastore.updateOriginalBw("cll-02", 1000); + datastore.updateClosedloopStatus("cll-02", true); + Set<String> cllId = new HashSet<>(); + cllId.add("cll-01"); + datastore.updateCllInstances(cllId); + assertEquals(datastore.getEndpointToUsedBw().keySet().size(), 1); + assertEquals(datastore.getUpperBoundBw().keySet().equals(cllId), true); + assertEquals(datastore.getEndpointToProvBw().keySet().equals(cllId), true); + assertEquals(datastore.getSvcStatus().keySet().equals(cllId), true); + assertEquals(datastore.getEndpointToOriginalBw().keySet().equals(cllId), true); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategyTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategyTest.java new file mode 100644 index 00000000..6d5c8cde --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/FixedUpperBoundStrategyTest.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = FixedUpperBoundStrategyTest.class) +public class FixedUpperBoundStrategyTest { + + @Spy + @InjectMocks + BandwidthEvaluator bandwidthEvaluator; + + @Spy + @InjectMocks + FixedUpperBoundStrategy fixedUpperBoundStrategy; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + + @Test + public void initTest() { + fixedUpperBoundStrategy.init(); + Mockito.verify(fixedUpperBoundStrategy, Mockito.atLeastOnce()).init(); + } + + @Test + public void executeTest() { + Event evt = new SimpleEvent(null, "{}"); + fixedUpperBoundStrategy.execute(evt); + Mockito.verify(fixedUpperBoundStrategy, Mockito.atLeastOnce()) + .execute(Mockito.any(Event.class)); + } + + @Test + public void getNameTest() { + fixedUpperBoundStrategy.getName(); + Mockito.verify(fixedUpperBoundStrategy, Mockito.atLeastOnce()).getName(); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/FlexibleThresholdStrategyTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/FlexibleThresholdStrategyTest.java new file mode 100644 index 00000000..40028923 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/FlexibleThresholdStrategyTest.java @@ -0,0 +1,69 @@ +/*******************************************************************************
+ * ============LICENSE_START=======================================================
+ * slice-analysis-ms
+ * ================================================================================
+ * Copyright (C) 2022 Huawei Technologies Co., Ltd.
+ * ==============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.slice.analysis.ms.service.ccvpn;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = FixedUpperBoundStrategyTest.class)
+public class FlexibleThresholdStrategyTest {
+
+ @Spy
+ @InjectMocks
+ BandwidthEvaluator bandwidthEvaluator;
+
+ @Spy
+ @InjectMocks
+ FlexibleThresholdStrategy flexibleThresholdStrategy;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void initTest() {
+ flexibleThresholdStrategy.init();
+ Mockito.verify(flexibleThresholdStrategy, Mockito.atLeastOnce()).init();
+ }
+
+ @Test
+ public void executeTest() {
+ Event evt = new SimpleEvent(null, "{}");
+ flexibleThresholdStrategy.execute(evt);
+ Mockito.verify(flexibleThresholdStrategy, Mockito.atLeastOnce())
+ .execute(Mockito.any(Event.class));
+ }
+
+ @Test
+ public void getNameTest() {
+ flexibleThresholdStrategy.getName();
+ Mockito.verify(flexibleThresholdStrategy, Mockito.atLeastOnce()).getName();
+ }
+}
diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/NetworkPolicyMonitorTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/NetworkPolicyMonitorTest.java new file mode 100644 index 00000000..23366ab9 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/NetworkPolicyMonitorTest.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ + +package org.onap.slice.analysis.ms.service.ccvpn; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BandwidthEvaluatorTest.class) +public class NetworkPolicyMonitorTest { + + @Spy + @InjectMocks + NetworkPolicyMonitor NetworkPolicyMonitor; + @Test + public void initTest() { + NetworkPolicyMonitor.init(); + Mockito.verify(NetworkPolicyMonitor, Mockito.atLeastOnce()).init(); + } + + @Test + public void postTest() { + Event evt = new SimpleEvent(null, "{}"); + NetworkPolicyMonitor.post(evt); + Mockito.verify(NetworkPolicyMonitor, Mockito.atLeastOnce()).post(Mockito.any(Event.class)); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/StrategyFactoryTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/StrategyFactoryTest.java new file mode 100644 index 00000000..8a938a6e --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/service/ccvpn/StrategyFactoryTest.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 Huawei Canada Limited. + * ============================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + * + *******************************************************************************/ +package org.onap.slice.analysis.ms.service.ccvpn; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +public class StrategyFactoryTest { + + private static final String STRATEGY = "FixedUpperBoundStrategy"; + @Mock + FixedUpperBoundStrategy fixedUpperBoundStrategy; + + @Spy + private List<EvaluationStrategy> strategies = new ArrayList<>(); + + @Spy + @InjectMocks + StrategyFactory strategyFactory; + + @Before + public void setup(){ + MockitoAnnotations.initMocks(this); + strategies.add(fixedUpperBoundStrategy); + } + + @Test + public void getStrategyTest(){ + when(fixedUpperBoundStrategy.getName()).thenReturn(STRATEGY); + assertEquals(STRATEGY, strategyFactory.getStrategy(STRATEGY).getName()); + } +} diff --git a/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/utils/DcaeDmaapUtilTest.java b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/utils/DcaeDmaapUtilTest.java new file mode 100644 index 00000000..b77378a6 --- /dev/null +++ b/components/slice-analysis-ms/src/test/java/org/onap/slice/analysis/ms/utils/DcaeDmaapUtilTest.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * slice-analysis-ms + * ================================================================================ + * Copyright (C) 2022 CTC, Inc. + * ============================================================================== + * 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.slice.analysis.ms.utils; + +import org.junit.Test; +import org.junit.runner.RunWith; +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.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertNotNull; +import static org.onap.slice.analysis.ms.utils.DcaeDmaapUtil.buildPublisher; +import static org.onap.slice.analysis.ms.utils.DcaeDmaapUtil.buildPublisherRequest; +import static org.onap.slice.analysis.ms.utils.DcaeDmaapUtil.buildSubscriber; +import static org.onap.slice.analysis.ms.utils.DcaeDmaapUtil.buildSubscriberRequest; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = DcaeDmaapUtilTest.class) +public class DcaeDmaapUtilTest { + + @Test + public void buildSubscriberTest(){ + MessageRouterSubscriber subscriber = buildSubscriber(); + assertNotNull(subscriber); + } + + @Test + public void buildSubscriberRequestTest(){ + MessageRouterSubscribeRequest request = buildSubscriberRequest("name", "url"); + assertNotNull(request); + } + + @Test + public void buildPublisherTest(){ + MessageRouterPublisher publisher = buildPublisher(); + assertNotNull(publisher); + } + + @Test + public void buildPublisherRequestTest(){ + MessageRouterPublishRequest request = buildPublisherRequest("name", "url"); + assertNotNull(request); + } + +} diff --git a/components/slice-analysis-ms/src/test/resources/aaiDetailsList.json b/components/slice-analysis-ms/src/test/resources/aaiDetailsList.json index e538e220..4f306f34 100644 --- a/components/slice-analysis-ms/src/test/resources/aaiDetailsList.json +++ b/components/slice-analysis-ms/src/test/resources/aaiDetailsList.json @@ -44,9 +44,9 @@ "service-instance-id":"ab9af40f13f7219099333", "service-instance-name":"an_sp_1", "service-type":"00-000", - "service-role":"slice-profile-instance", + "service-role":"slice-profile", "environment-context":"001-00110", - "workload-context":"ÁN-NF", + "workload-context":"AN-NF", "service-instance-location-id":"[\"460-00\",\"460-01\"]", "resource-version":"1613715676282", "orchestration-status":"deactivated" diff --git a/components/slice-analysis-ms/src/test/resources/aaiEventDmaapMsg.json b/components/slice-analysis-ms/src/test/resources/aaiEventDmaapMsg.json new file mode 100644 index 00000000..d8cb65cd --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/aaiEventDmaapMsg.json @@ -0,0 +1,45 @@ +{ + "cambria.partition": "AAI", + "event-header": { + "severity": "NORMAL", + "entity-type": "service-instance", + "top-entity-type": "customer", + "entity-link": "/aai/v24/business/customers/customer/IBNCustomer/service-subscriptions/service-subscription/IBN/service-instances/service-instance/test", + "event-type": "AAI-EVENT", + "domain": "dev", + "action": "UPDATE", + "sequence-number": "0", + "id": "48c2016e-12cb-4f9f-ab25-5eaaf8da9fe8", + "source-name": "UUI", + "version": "v24", + "timestamp": "20220406-19:53:41:550" + }, + "entity":{ + "global-customer-id": "IBNCustomer", + "subscriber-name": "IBNCustomer", + "service-subscriptions": { + "service-subscription": [ + { + "service-type": "IBN", + "service-instances": { + "service-instance": [ + { + "model-version-id": "6790ab0e-034f-11eb-adc1-0242ac120002", + "service-instance-id": "test", + "resource-version": "1649274821478", + "service-type": "IBN", + "service-instance-location-id": "460-00", + "service-role": "TN", + "environment-context": "001-100001", + "bandwidth-total": "4000", + "model-invariant-id": "6790ab0e-034f-11eb-adc1-0242ac120002", + "service-instance-name": "decheng-test-001", + "orchestration-status": "allocated" + } + ] + } + } + ] + } + } +} diff --git a/components/slice-analysis-ms/src/test/resources/alloted-resource.json b/components/slice-analysis-ms/src/test/resources/alloted-resource.json new file mode 100644 index 00000000..56cfc9f3 --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/alloted-resource.json @@ -0,0 +1,115 @@ +{ + "service-instance-id":"0835fd19-6726-4081-befb-cc8932c47767", + "service-instance-name":"sa1", + "service-type":"embb", + "service-role":"service-profile", + "environment-context":"01-06E442", + "model-invariant-id":"8b94b147-2233-4e9f-b939-55c1b0e618ac", + "model-version-id":"961ec436-7b16-4d71-9d62-9c4ca5dd94bf", + "resource-version":"1645003055191", + "orchestration-status":"deactivated", + "relationship-list":{ + "relationship":[ + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/8a6115ef-bbca-48ea-98e2-831a2b0226d2", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"8a6115ef-bbca-48ea-98e2-831a2b0226d2" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sa1" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/b2ae730f-1d5f-495a-8112-dac017a7348c", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"b2ae730f-1d5f-495a-8112-dac017a7348c" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sliceprofile_an_sa1" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/cad8fa36-2d55-4c12-a92e-1bd551517a0c", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"cad8fa36-2d55-4c12-a92e-1bd551517a0c" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sliceprofile_cn_sa1" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/8d0d698e-77f4-4453-8c09-ae2cbe6a9a04", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"8d0d698e-77f4-4453-8c09-ae2cbe6a9a04" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sliceprofile_tn_sa1" + } + ] + } + ] + } +} diff --git a/components/slice-analysis-ms/src/test/resources/config_all.json b/components/slice-analysis-ms/src/test/resources/config_all.json index 79d70202..fc18cc14 100644 --- a/components/slice-analysis-ms/src/test/resources/config_all.json +++ b/components/slice-analysis-ms/src/test/resources/config_all.json @@ -5,7 +5,7 @@ "aaf_password": null, "type": "message-router", "dmaap_info": { - "topic_url": "https://message-router.onap.svc.cluster.local:3905/events/unauthenticated.VES_MEASUREMENT_OUTPUT", + "topic_url": "http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.PERFORMANCE_MEASUREMENTS", "client_role": "sliceanalysis-subscriber", "location": "onap", "client_id": "sdnr-sliceanalysis-1" @@ -16,12 +16,52 @@ "aaf_password": null, "type": "message-router", "dmaap_info": { - "topic_url": "https://message-router.onap.svc.cluster.local:3905/events/DCAE_CL_RSP", + "topic_url": "http://message-router.onap.svc.cluster.local:3904/events/DCAE_CL_RSP", "client_role": "sliceanalysis-subscriber", "location": "onap", "client_id": "sdnr-sliceanalysis-1" }, "aaf_username": null + }, + "intelligent_slicing_topic": { + "aaf_password": null, + "type": "message-router", + "dmaap_info": { + "topic_url": "http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.ML_RESPONSE_TOPIC", + "client_role": "sliceanalysis-subscriber", + "location": "onap", + "client_id": "sdnr-sliceanalysis-1" + }, + "aaf_username": null + }, + "ves_ccvpn_notification_topic": { + "aaf_password": null, + "type": "message-router", + "dmaap_info": { + "topic_url": "http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.VES_NOTIFICATION_OUTPUT", + "client_role": "sliceanalysis-subscriber", + "location": "onap", + "client_id": "sdnr-sliceanalysis-1" + }, + "aaf_username": null + }, + "aai_subscriber":{ + "type":"message_router", + "aaf_username": null, + "aaf_password": null, + "api_key" : null, + "api_secret" : null, + "servers" : ["dmaap:3904"], + "consumer_group" : "dcae_ccvpn_cl", + "consumer_instance" : "dcae_ccvpn_cl_aaievent", + "fetch_timeout" : 15000, + "fetch_limit" : 100, + "dmaap_info":{ + "topic_url":"http://message-router:3904/events/AAI-EVENT", + "client_role":"org.onap.dcae.aaiSub", + "location":"onap", + "client_id":"sdnr-sliceanalysis-1" + } } }, "streams_publishes": { @@ -29,7 +69,7 @@ "aaf_password": null, "type": "message-router", "dmaap_info": { - "topic_url": "https://message-router.onap.svc.cluster.local:3905/events/unauthenticated.DCAE_CL_OUTPUT", + "topic_url": "http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.DCAE_CL_OUTPUT", "client_role": "sliceanalysis-subscriber", "location": "onap", "client_id": "sdnr-sliceanalysis-1" @@ -47,17 +87,48 @@ "cbsPollingInterval": 60, "sliceanalysisms.cg": "sliceanalysisms-cg", "sliceanalysisms.pollingInterval": 20, + "sliceanalysisms.samples": 3, + "sliceanalysisms.minPercentageChange": 5, + "sliceanalysisms.initialDelaySeconds": 300000, + "sliceanalysisms.pollingTimeout": 60, "sliceanalysisms.cid": "sliceanalysisms-cid", - "sliceanalysisms.configDb.service": "http://sdnc.onap:8181", - "sliceanalysisms.pollingTimeout":4, - "sliceanalysisms.samples": 5, - "sliceanalysisms.minPercentageChange":4, - "sliceanalysisms.initialDelaySeconds": 60000, + "sliceanalysisms.configDb.service": "http://configdb_sim:5000", + "sliceanalysisms.aai.url": "https://aai-resources:8447/aai/v21", + "sliceanalysisms.cps.url": "http://cps-tbdmt:8080/execute/ran-network", + "sliceanalysisms.configDbEnabled": "false", + "sliceanalysisms.rannfnssiDetailsTemplateId": "get-rannfnssiid-details", + "sliceanalysisms.desUrl": "http://dl-des:1681/datalake/v1/exposure/pm_data", + "sliceanalysisms.pmDataDurationInWeeks": 4, + "sliceanalysisms.vesNotifPollingInterval": 5, + "sliceanalysisms.vesNotifChangeIdentifier": "PM_BW_UPDATE", + "sliceanalysisms.vesNotifChangeType": "BandwidthChanged", + "sliceanalysisms.aaiNotif.targetAction" : "UPDATE", + "sliceanalysisms.aaiNotif.targetSource" : "UUI", + "sliceanalysisms.aaiNotif.targetEntity" : "service-instance", + "sliceanalysisms.ccvpnEvalInterval": 5, + "sliceanalysisms.ccvpnEvalUpperThreshold": 0.8, + "sliceanalysisms.ccvpnEvalLowerThreshold": 0.3, + "sliceanalysisms.ccvpnEvalPrecision": 100.0, + "sliceanalysisms.ccvpnEvalPeriodicCheckOn": true, + "sliceanalysisms.ccvpnEvalOnDemandCheckOn": true, + "sliceanalysisms.ccvpnEvalStrategy": "FixedUpperBoundStrategy", "service_calls": { "policy-req": [] - } + }, + "trust_store_path": "/opt/app/sliceanalysisms/etc/cert/trust.jks", + "trust_store_pass_path": "/opt/app/sliceanalysisms/etc/cert/trust.pass" }, "policies": { - + "event": { + "action": "gathered", + "timestamp": "2019-09-18T14:57:55.320Z", + "update_id": "dbb88da8-8df1-489d-b51d-8d5cbbfbcd99", + "policies_count": 1 + }, + "items": [ + { + "policyName": "com.Config_PCIMS_CONFIG_POLICY.1.xml" + } + ] } } diff --git a/components/slice-analysis-ms/src/test/resources/nsi.json b/components/slice-analysis-ms/src/test/resources/nsi.json new file mode 100644 index 00000000..0ca3e529 --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/nsi.json @@ -0,0 +1,122 @@ +{ + "service-instance-id":"09cad94e-fbb8-4c70-9c4d-74ec75e97683", + "service-instance-name":"nsi_sa1", + "service-type":"embb", + "service-role":"nsi", + "model-invariant-id":"8a8e6666-6e1e-4f0d-88ee-71b9f12f6399", + "model-version-id":"1938db5a-213e-4ba8-b3a8-b39c66a79562", + "resource-version":"1645003054775", + "orchestration-status":"deactivated", + "service-function":"non-shared", + "relationship-list":{ + "relationship":[ + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/50f418a6-804f-4453-bf70-21f0efaf6fcd", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"50f418a6-804f-4453-bf70-21f0efaf6fcd" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"nssi_ansa1" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/99f24e52-5117-430e-a42d-5f77df3dddef", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"99f24e52-5117-430e-a42d-5f77df3dddef" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"nssi_cnsa1" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/23ed8231-016c-4420-be91-c042b68f9ea0", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"23ed8231-016c-4420-be91-c042b68f9ea0" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"nssi_tnsa1" + } + ] + }, + { + "related-to":"allotted-resource", + "relationship-label":"org.onap.relationships.inventory.Uses", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/0835fd19-6726-4081-befb-cc8932c47767/allotted-resources/allotted-resource/530d188d-9087-49af-a44a-90c40e0c2d47", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"0835fd19-6726-4081-befb-cc8932c47767" + }, + { + "relationship-key":"allotted-resource.id", + "relationship-value":"530d188d-9087-49af-a44a-90c40e0c2d47" + } + ], + "related-to-property":[ + { + "property-key":"allotted-resource.description" + }, + { + "property-key":"allotted-resource.allotted-resource-name", + "property-value":"Allotted_sa1" + } + ] + } + ] + } +} diff --git a/components/slice-analysis-ms/src/test/resources/nssi.json b/components/slice-analysis-ms/src/test/resources/nssi.json new file mode 100644 index 00000000..42916a70 --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/nssi.json @@ -0,0 +1,165 @@ +{ + "service-instance-id":"50f418a6-804f-4453-bf70-21f0efaf6fcd", + "service-instance-name":"nssi_ansa1", + "service-type":"embb", + "service-role":"nssi", + "environment-context":"an", + "workload-context":"AN", + "model-invariant-id":"68c76946-95a8-4a15-8100-ea482f31341f", + "model-version-id":"c8c1ba78-b7a2-4d72-a82a-75eb79d95347", + "service-instance-location-id":"39-00", + "resource-version":"1645002869853", + "orchestration-status":"deactivated", + "service-function":"non-shared", + "relationship-list":{ + "relationship":[ + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/b2ae730f-1d5f-495a-8112-dac017a7348c", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"b2ae730f-1d5f-495a-8112-dac017a7348c" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sliceprofile_an_sa1" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/09cad94e-fbb8-4c70-9c4d-74ec75e97683", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"09cad94e-fbb8-4c70-9c4d-74ec75e97683" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"nsi_sa1" + } + ] + }, + { + "related-to":"network-route", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/network/network-routes/network-route/450b4494-8f24-4c6b-b0a2-2c8a904bf032", + "relationship-data":[ + { + "relationship-key":"network-route.route-id", + "relationship-value":"450b4494-8f24-4c6b-b0a2-2c8a904bf032" + } + ] + }, + { + "related-to":"network-route", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/network/network-routes/network-route/361b6d8b-ad80-4f55-a8fb-be05cde37d5e", + "relationship-data":[ + { + "relationship-key":"network-route.route-id", + "relationship-value":"361b6d8b-ad80-4f55-a8fb-be05cde37d5e" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/01dfe2e6-eb8b-4907-bf26-2790a7211a07", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"01dfe2e6-eb8b-4907-bf26-2790a7211a07" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"nssi_tn_mh_9c6fed98-4ce2-4390-8824-ba7cf921851c" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/ec4a9f30-f025-4abb-bacd-33bb61bf2aec", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"ec4a9f30-f025-4abb-bacd-33bb61bf2aec" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"nssi_tn_fh_54aa886f-bb46-474f-96ff-b6f04962a37d" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/b6085a7b-2b34-48db-8150-70cfdd6f41fc", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"b6085a7b-2b34-48db-8150-70cfdd6f41fc" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"nssi_an_nf_ff726432-7c66-4afb-a1eb-096b493db635" + } + ] + } + ] + } +} diff --git a/components/slice-analysis-ms/src/test/resources/onsetMessage.json b/components/slice-analysis-ms/src/test/resources/onsetMessage.json index 033e9b94..fdd4e5d8 100644 --- a/components/slice-analysis-ms/src/test/resources/onsetMessage.json +++ b/components/slice-analysis-ms/src/test/resources/onsetMessage.json @@ -11,7 +11,7 @@ "vserver.prov-status": "ACTIVE", "generic-vnf.vnf-id": "e51a9b12-f313-11ea-adc1-0242ac120003" }, - "payload": "{\"name\":\"e51a9b12-f313-11ea-adc1-0242ac120003\",\"globalSubscriberId\":\"5GCustomer\",\"subscriptionServiceType\":\"5G\",\"networkType\":\"AN\",\"serviceInstanceID\":\"e51a9b12-f313-11ea-adc1-0242ac120003\",\"additionalProperties\":{\"modifyAction\":\"reconfigure\",\"snssaiList\":[\"001-100001\"],\"sliceProfileId\":\"e51a9b12-f313-11ea-adc1-0242ac120002\",\"resourceConfig\":{\"1\":{\"dLThptPerSlice\":50,\"uLThptPerSlice\":40},\"2\":{\"dLThptPerSlice\":50,\"uLThptPerSlice\":30}},\"nsiInfo\":{\"nsiId\":\"UUID\",\"nsiName\":\"\"},\"scriptName\":\"AN\"}}", + "payload": "{\"name\":\"e51a9b12-f313-11ea-adc1-0242ac120003\",\"globalSubscriberId\":\"5GCustomer\",\"subscriptionServiceType\":\"5G\",\"networkType\":\"AN\",\"serviceInstanceID\":\"e51a9b12-f313-11ea-adc1-0242ac120003\",\"additionalProperties\":{\"modifyAction\":\"reconfigure\",\"snssaiList\":[\"001-100001\"],\"sliceProfileId\":\"e51a9b12-f313-11ea-adc1-0242ac120002\",\"resourceConfig\":{\"data\":[{\"nearRTRICId\":1,\"dLThptPerSlice\":50,\"uLThptPerSlice\":40},{\"nearRTRICId\":2,\"dLThptPerSlice\":50,\"uLThptPerSlice\":30}]},\"nsiInfo\":{\"nsiId\":\"UUID\",\"nsiName\":\"\"},\"scriptName\":\"AN\"}}", "from": "DCAE", "version": "1.0.2" } diff --git a/components/slice-analysis-ms/src/test/resources/onsetMessage2.json b/components/slice-analysis-ms/src/test/resources/onsetMessage2.json new file mode 100644 index 00000000..eb64eff2 --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/onsetMessage2.json @@ -0,0 +1,18 @@ +{ + "closedLoopControlName": "ControlLoop-CCVPN-CLL-227e8b00-dbeb-4d03-8719-d0a658fb846c", + "closedLoopAlarmStart": 1605691996370, + "closedLoopEventClient": "microservice.sliceAnalysisMS", + "closedLoopEventStatus": "ONSET", + "requestID": "1e946480-1232-46d4-a39b-614ac534400f", + "target": "generic-vnf.vnf-id", + "payload": "{\"name\": \"cloud-leased-line-101\",\"serviceInstanceID\": \"cll-instance-01\",\"globalSubscriberId\": \"IBNCustomer\",\"subscriptionServiceType\": \"IBN\",\"serviceType\": \"CLL\",\"additionalProperties\": {\"modifyAction\": \"bandwdith\",\"enableSdnc\": \"true\",\"transportNetworks\": [{ \"id\": \"cll-101-network-001\", \"sla\": { \"latency\": 2, \"maxBandwidth\": 8000 }}]}}", + "from": "DCAE", + "version": "1.0.2", + "target_type": "VNF", + "AAI": { + "generic-vnf.is-closed-loop-disabled": "false", + "generic-vnf.prov-status": "ACTIVE", + "generic-vnf.vnf-id": "e51a9b12-f313-11ea-adc1-0242ac120003", + "generic-vnf.vnf-name": "76543" + } +} diff --git a/components/slice-analysis-ms/src/test/resources/pm_data.json b/components/slice-analysis-ms/src/test/resources/pm_data.json new file mode 100644 index 00000000..0f711160 --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/pm_data.json @@ -0,0 +1,17 @@ +{ + "result":[ + { + "measValuesList":"[[\"false\",[[1.0,\"75\"],[2.0,\"84\"]],\"11220\"],[\"false\",[[1.0,\"76\"],[2.0,\"85\"]],\"11221\"],[\"false\",[[1.0,\"90\"],[2.0,\"95\"]],\"11222\",]]", + "sMeasTypesList":"[\"SM.PrbUsedDl.01-06E442\",\"SM.PrbUsedUl.01-06E442\"]" + }, + { + "measValuesList":"[[\"false\",[[1.0,\"175\"],[2.0,\"184\"]],\"11225\"],[\"false\",[[1.0,\"176\"],[2.0,\"185\"]],\"11224\"],[\"false\",[[1.0,\"105\"],[2.0,\"100\"]],\"11222\"]]", + "sMeasTypesList":"[\"SM.PrbUsedDl.01-06E442\",\"SM.PrbUsedUl.01-06E442\"]" + } + ], + "request":{ + "snssai":"SM.PrbUsedDl.001-1100", + "time":"1538478000000" + }, + "result_count":2 +} diff --git a/components/slice-analysis-ms/src/test/resources/sliceConfigRequest.json b/components/slice-analysis-ms/src/test/resources/sliceConfigRequest.json new file mode 100644 index 00000000..133c4a1c --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/sliceConfigRequest.json @@ -0,0 +1,21 @@ +{ + + "sliceIdentifiers": [ + + "14559ead-f4fe-4c1c-a94c-8015fad3ea35", + + "14559ead-f4fe-4c1c-a94c-8015fad3ea36" + + ], + + "configParams": [ + + "dLThptPerSlice", + + "uLThptPerSlice", + + "maxNumberOfConns" + + ] + +} diff --git a/components/slice-analysis-ms/src/test/resources/sliceConfigResponse.json b/components/slice-analysis-ms/src/test/resources/sliceConfigResponse.json new file mode 100644 index 00000000..c99a92cd --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/sliceConfigResponse.json @@ -0,0 +1,20 @@ +{ + "sliceConfigDetails":[ + { + "sliceIdentifiers":"14559ead-f4fe-4c1c-a94c-8015fad3ea35", + "aggregatedConfig":{ + "maxNumberOfConns":null, + "dlthptPerSlice":190857028, + "ulthptPerSlice":119285978 + } + }, + { + "sliceIdentifiers":"14559ead-f4fe-4c1c-a94c-8015fad3ea36", + "aggregatedConfig":{ + "maxNumberOfConns":null, + "dlthptPerSlice":190857028, + "ulthptPerSlice":119285978 + } + } + ] +} diff --git a/components/slice-analysis-ms/src/test/resources/sliceprofile_an_sa1.json b/components/slice-analysis-ms/src/test/resources/sliceprofile_an_sa1.json new file mode 100644 index 00000000..aab0d531 --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/sliceprofile_an_sa1.json @@ -0,0 +1,155 @@ +{ + "service-instance-id":"b2ae730f-1d5f-495a-8112-dac017a7348c", + "service-instance-name":"sliceprofile_an_sa1", + "service-type":"embb", + "service-role":"slice-profile", + "environment-context":"01-06E442", + "workload-context":"AN", + "created-at":"2022-02-16 09:12:27", + "model-invariant-id":"68c76946-95a8-4a15-8100-ea482f31341f", + "model-version-id":"c8c1ba78-b7a2-4d72-a82a-75eb79d95347", + "service-instance-location-id":"39-00", + "resource-version":"1645002869957", + "orchestration-status":"deactivated", + "service-function":"non-shared", + "relationship-list":{ + "relationship":[ + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/0835fd19-6726-4081-befb-cc8932c47767", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"0835fd19-6726-4081-befb-cc8932c47767" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sa1" + } + ] + }, + { + "related-to":"network-route", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/network/network-routes/network-route/361b6d8b-ad80-4f55-a8fb-be05cde37d5e", + "relationship-data":[ + { + "relationship-key":"network-route.route-id", + "relationship-value":"361b6d8b-ad80-4f55-a8fb-be05cde37d5e" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/29b15561-0d2d-491d-8022-66d19e2175ca", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"29b15561-0d2d-491d-8022-66d19e2175ca" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sliceprofile_7bda9caa-4726-4460-bf70-38c598d165e4" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/50f418a6-804f-4453-bf70-21f0efaf6fcd", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"50f418a6-804f-4453-bf70-21f0efaf6fcd" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"nssi_ansa1" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/f08ce80d-0dec-4cbe-934e-197c516cbecc", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"f08ce80d-0dec-4cbe-934e-197c516cbecc" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sliceprofile_2b3147bc-4d89-459b-81d4-73c971fb4767" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/4f2cdc4d-bd1d-466a-bf7a-9d3d3f299dd5", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"4f2cdc4d-bd1d-466a-bf7a-9d3d3f299dd5" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sliceprofile_7eed6ea4-d2ae-4319-9613-847cc89cc3ab" + } + ] + } + ] + } +} diff --git a/components/slice-analysis-ms/src/test/resources/sliceprofile_cn_sa1.json b/components/slice-analysis-ms/src/test/resources/sliceprofile_cn_sa1.json new file mode 100644 index 00000000..90c594d7 --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/sliceprofile_cn_sa1.json @@ -0,0 +1,80 @@ +{ + "service-instance-id":"cad8fa36-2d55-4c12-a92e-1bd551517a0c", + "service-instance-name":"sliceprofile_cn_sa1", + "service-type":"embb", + "service-role":"slice-profile", + "environment-context":"01-06E442", + "workload-context":"CN", + "created-at":"2022-02-16 09:14:30", + "model-invariant-id":"32438b92-1450-4d32-9bb1-9642d08d260e", + "model-version-id":"3cb7b6ad-54a7-4a0f-8e80-d5dcc18f2184", + "service-instance-location-id":"39-00", + "resource-version":"1645002992778", + "orchestration-status":"deactivated", + "service-function":"non-shared", + "relationship-list":{ + "relationship":[ + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/0835fd19-6726-4081-befb-cc8932c47767", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"0835fd19-6726-4081-befb-cc8932c47767" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sa1" + } + ] + }, + { + "related-to":"network-route", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/network/network-routes/network-route/03c281af-f59c-4b3e-a42b-bbc28477e11d", + "relationship-data":[ + { + "relationship-key":"network-route.route-id", + "relationship-value":"03c281af-f59c-4b3e-a42b-bbc28477e11d" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/99f24e52-5117-430e-a42d-5f77df3dddef", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"99f24e52-5117-430e-a42d-5f77df3dddef" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"nssi_cnsa1" + } + ] + } + ] + } +} diff --git a/components/slice-analysis-ms/src/test/resources/sliceprofile_tn_sa1.json b/components/slice-analysis-ms/src/test/resources/sliceprofile_tn_sa1.json new file mode 100644 index 00000000..005df5b3 --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/sliceprofile_tn_sa1.json @@ -0,0 +1,68 @@ +{ + "service-instance-id":"8d0d698e-77f4-4453-8c09-ae2cbe6a9a04", + "service-instance-name":"sliceprofile_tn_sa1", + "service-type":"embb", + "service-role":"slice-profile", + "environment-context":"01-B989BD", + "workload-context":"TN_BH", + "created-at":"2022-02-16 09:16:32", + "model-invariant-id":"60424cf8-591a-4804-b189-9e2251d9d36b", + "model-version-id":"ed5bcf6a-6c0a-4286-96b1-877c5344f91a", + "resource-version":"1645003055020", + "orchestration-status":"deactivated", + "service-function":"non-shared", + "relationship-list":{ + "relationship":[ + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/0835fd19-6726-4081-befb-cc8932c47767", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"0835fd19-6726-4081-befb-cc8932c47767" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"sa1" + } + ] + }, + { + "related-to":"service-instance", + "relationship-label":"org.onap.relationships.inventory.ComposedOf", + "related-link":"/aai/v21/business/customers/customer/5GCustomer/service-subscriptions/service-subscription/5G/service-instances/service-instance/23ed8231-016c-4420-be91-c042b68f9ea0", + "relationship-data":[ + { + "relationship-key":"customer.global-customer-id", + "relationship-value":"5GCustomer" + }, + { + "relationship-key":"service-subscription.service-type", + "relationship-value":"5G" + }, + { + "relationship-key":"service-instance.service-instance-id", + "relationship-value":"23ed8231-016c-4420-be91-c042b68f9ea0" + } + ], + "related-to-property":[ + { + "property-key":"service-instance.service-instance-name", + "property-value":"nssi_tnsa1" + } + ] + } + ] + } +} diff --git a/components/slice-analysis-ms/src/test/resources/vesCCVPNNotiModel.json b/components/slice-analysis-ms/src/test/resources/vesCCVPNNotiModel.json new file mode 100644 index 00000000..270c0779 --- /dev/null +++ b/components/slice-analysis-ms/src/test/resources/vesCCVPNNotiModel.json @@ -0,0 +1,34 @@ +{ + "event": { + "commonEventHeader": { + "version": "4.0.1", + "vesEventListenerVersion": "7.0.1", + "domain": "notification", + "eventName": "ccvpnNotification_CloudLeaseLine_BandwidthChanged", + "eventId": "BandwidthChanged_1797490e-10ae-4d48-9ea7-3d7d790b25e1", + "lastEpochMicrosec": 8745745764578, + "priority": "Normal", + "reportingEntityName": "onap-sdnc", + "sequence": 0, + "sourceName": "onap-sdnc", + "startEpochMicrosec": 8745745764578, + "timeZoneOffset": "UTC-05.00" + }, + "notificationFields": { + "changeIdentifier": "PM_BW_UPDATE", + "changeType": "BandwidthChanged", + "notificationFieldsVersion": "2.0", + "arrayOfNamedHashMap": [ + { + "name": "DomainId-1-cll-instance-01-uni-01-8745745764578", + "hashMap": { + "cllId": "cll-instance-01", + "uniId": "uni-01", + "bandwidthValue": "4000", + "time": "2022-02-08T11:13:34.781-05:00" + } + } + ] + } + } +} diff --git a/components/slice-analysis-ms/version.properties b/components/slice-analysis-ms/version.properties index 4434ce3b..8a256ccb 100644 --- a/components/slice-analysis-ms/version.properties +++ b/components/slice-analysis-ms/version.properties @@ -3,6 +3,10 @@ # slice-analysis-ms # ================================================================================ # Copyright (C) 2020-2021 Wipro Limited. +# Copyright (C) 2022 Huawei Canada Limited. +# Copyright (C) 2022 CTC, Inc. +# Copyright (c) 2022 Wipro Limited. +# Copyright (C) 2023 Deutsche Telekom AG. 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. @@ -19,8 +23,8 @@ # ############################################################################### major=1 -minor=0 -patch=7 +minor=2 +patch=1 base_version=${major}.${minor}.${patch} release_version=${base_version} snapshot_version=${base_version}-SNAPSHOT diff --git a/releases/kpi-computation-ms-1.0.10-container.yaml b/releases/kpi-computation-ms-1.0.10-container.yaml new file mode 100644 index 00000000..3beffbfb --- /dev/null +++ b/releases/kpi-computation-ms-1.0.10-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.0.10' +project: 'dcaegen2-services-kpi-computation-ms' +log_dir: 'dcaegen2-services-kpi-computation-ms-maven-docker-stage-master/625/' +containers: + - name: 'org.onap.dcaegen2.services.components.kpi-ms' + version: '1.0.10-20221012T140353Z' +container_release_tag: '1.0.10' +ref: '430efb51d5c9bb3c294c9791f246d2b6c2c4388e' +git_tag: '1.0.10-kpi-computation-ms' diff --git a/releases/kpi-computation-ms-1.0.11-container.yaml b/releases/kpi-computation-ms-1.0.11-container.yaml new file mode 100644 index 00000000..9bffea63 --- /dev/null +++ b/releases/kpi-computation-ms-1.0.11-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.0.11' +project: 'dcaegen2-services-kpi-computation-ms' +log_dir: 'dcaegen2-services-kpi-computation-ms-maven-docker-stage-master/673/' +containers: + - name: 'org.onap.dcaegen2.services.components.kpi-ms' + version: '1.0.11-20221129T035200Z' +container_release_tag: '1.0.11' +ref: '584f29be579cd483c8f9bd888a747b2ebbeea7f1' +git_tag: '1.0.11-kpi-computation-ms' diff --git a/releases/kpi-computation-ms-1.0.4-container.yaml b/releases/kpi-computation-ms-1.0.4-container.yaml new file mode 100644 index 00000000..1dabab01 --- /dev/null +++ b/releases/kpi-computation-ms-1.0.4-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.0.4' +project: 'dcaegen2-services-kpi-computation-ms' +log_dir: 'dcaegen2-services-kpi-computation-ms-maven-docker-stage-master/415/' +containers: + - name: 'org.onap.dcaegen2.services.components.kpi-ms' + version: '1.0.4-20220316T035200Z' +container_release_tag: '1.0.4' +ref: '9cad4acaf0aa557589599baa5a965d13d44b9f7b' +git_tag: '1.0.4-kpi-computation-ms' diff --git a/releases/kpi-computation-ms-1.2.0-container.yaml b/releases/kpi-computation-ms-1.2.0-container.yaml new file mode 100644 index 00000000..94f22576 --- /dev/null +++ b/releases/kpi-computation-ms-1.2.0-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.2.0' +project: 'dcaegen2-services-kpi-computation-ms' +log_dir: 'dcaegen2-services-kpi-computation-ms-maven-docker-stage-master/795/' +containers: + - name: 'org.onap.dcaegen2.services.components.kpi-ms' + version: '1.2.0-20230331T035157Z' +container_release_tag: '1.2.0' +ref: 'c7ea15da1edda4281e6d45e621d12a0d0d892bbe' +git_tag: '1.2.0-kpi-computation-ms' diff --git a/releases/pmsh-2.2.1-container.yaml b/releases/pmsh-2.2.1-container.yaml new file mode 100644 index 00000000..8b08c02b --- /dev/null +++ b/releases/pmsh-2.2.1-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '2.2.1' +project: 'dcaegen2-services-pmsh' +log_dir: 'dcaegen2-services-pmsh-docker-merge-master/179/' +containers: + - name: 'org.onap.dcaegen2.services.pmsh' + version: '2.2.1-SNAPSHOT-20220312T025248Z' +container_release_tag: '2.2.1' +ref: '5386335b9fa32a761a22cafdac319e169fec6896' +git_tag: '2.2.1-pmsh'
\ No newline at end of file diff --git a/releases/pmsh-2.2.2-container.yaml b/releases/pmsh-2.2.2-container.yaml new file mode 100644 index 00000000..6e8ed89f --- /dev/null +++ b/releases/pmsh-2.2.2-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '2.2.2' +project: 'dcaegen2-services-pmsh' +log_dir: 'dcaegen2-services-pmsh-docker-merge-master/182/' +containers: + - name: 'org.onap.dcaegen2.services.pmsh' + version: '2.2.2-SNAPSHOT-20220321T163259Z' +container_release_tag: '2.2.2' +ref: '934454b4eb2da070d69c810f310c49fd4895f11c' +git_tag: '2.2.2-pmsh'
\ No newline at end of file diff --git a/releases/pmsh-2.2.3-container.yaml b/releases/pmsh-2.2.3-container.yaml new file mode 100644 index 00000000..36aac055 --- /dev/null +++ b/releases/pmsh-2.2.3-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '2.2.3' +project: 'dcaegen2-services-pmsh' +log_dir: 'dcaegen2-services-pmsh-docker-merge-master/230/' +containers: + - name: 'org.onap.dcaegen2.services.pmsh' + version: '2.2.3-SNAPSHOT-20230217T201822Z' +container_release_tag: '2.2.3' +ref: 'f0fb309e5bcdb31d86c51e56205f6d977dcb9fac' +git_tag: '2.2.3-pmsh'
\ No newline at end of file diff --git a/releases/slice-analysis-ms-1.0.7-container.yaml b/releases/slice-analysis-ms-1.0.7-container.yaml new file mode 100644 index 00000000..4b49a948 --- /dev/null +++ b/releases/slice-analysis-ms-1.0.7-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.0.7' +project: 'dcaegen2-services-slice-analysis-ms' +log_dir: 'dcaegen2-services-slice-analysis-ms-maven-docker-stage-master/592' +containers: + - name: 'org.onap.dcaegen2.services.components.slice-analysis-ms' + version: '1.0.7-20220311T014931Z' +container_release_tag: '1.0.7' +ref: '29c5e813b5cb595af267f75c2fd0b846ea386304' +git_tag: '1.0.7-slice-analysis-ms' diff --git a/releases/slice-analysis-ms-1.1.0-container.yaml b/releases/slice-analysis-ms-1.1.0-container.yaml new file mode 100644 index 00000000..e2c17dd9 --- /dev/null +++ b/releases/slice-analysis-ms-1.1.0-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.1.0' +project: 'dcaegen2-services-slice-analysis-ms' +log_dir: 'dcaegen2-services-slice-analysis-ms-maven-docker-stage-master/603' +containers: + - name: 'org.onap.dcaegen2.services.components.slice-analysis-ms' + version: '1.1.0-20220322T014929Z' +container_release_tag: '1.1.0' +ref: '7f2e4aa47f56085be6c95cb81b6a8bea8126d56d' +git_tag: '1.1.0-slice-analysis-ms' diff --git a/releases/slice-analysis-ms-1.1.1-container.yaml b/releases/slice-analysis-ms-1.1.1-container.yaml new file mode 100644 index 00000000..19114408 --- /dev/null +++ b/releases/slice-analysis-ms-1.1.1-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.1.1' +project: 'dcaegen2-services-slice-analysis-ms' +log_dir: 'dcaegen2-services-slice-analysis-ms-maven-docker-stage-master/634' +containers: + - name: 'org.onap.dcaegen2.services.components.slice-analysis-ms' + version: '1.1.1-20220422T014915Z' +container_release_tag: '1.1.1' +ref: 'ad5981f8e4969c41724885c830dda2cef304adf9' +git_tag: '1.1.1-slice-analysis-ms' diff --git a/releases/slice-analysis-ms-1.1.2-container.yaml b/releases/slice-analysis-ms-1.1.2-container.yaml new file mode 100644 index 00000000..a99abb7b --- /dev/null +++ b/releases/slice-analysis-ms-1.1.2-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.1.2' +project: 'dcaegen2-services-slice-analysis-ms' +log_dir: 'dcaegen2-services-slice-analysis-ms-maven-docker-stage-master/646' +containers: + - name: 'org.onap.dcaegen2.services.components.slice-analysis-ms' + version: '1.1.2-20220504T015001Z' +container_release_tag: '1.1.2' +ref: '662afdf33cb5934737e35ae991a4624d438a836a' +git_tag: '1.1.2-slice-analysis-ms' diff --git a/releases/slice-analysis-ms-1.1.3-container.yaml b/releases/slice-analysis-ms-1.1.3-container.yaml new file mode 100644 index 00000000..1242e1e4 --- /dev/null +++ b/releases/slice-analysis-ms-1.1.3-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.1.3' +project: 'dcaegen2-services-slice-analysis-ms' +log_dir: 'dcaegen2-services-slice-analysis-ms-maven-docker-stage-master/654' +containers: + - name: 'org.onap.dcaegen2.services.components.slice-analysis-ms' + version: '1.1.3-20220512T015004Z' +container_release_tag: '1.1.3' +ref: '3834528bd0ad36892e98acd49550ceb20cea7dec' +git_tag: '1.1.3-slice-analysis-ms' diff --git a/releases/slice-analysis-ms-1.1.5-container.yaml b/releases/slice-analysis-ms-1.1.5-container.yaml new file mode 100644 index 00000000..2e05a021 --- /dev/null +++ b/releases/slice-analysis-ms-1.1.5-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.1.5' +project: 'dcaegen2-services-slice-analysis-ms' +log_dir: 'dcaegen2-services-slice-analysis-ms-maven-docker-stage-master/794' +containers: + - name: 'org.onap.dcaegen2.services.components.slice-analysis-ms' + version: '1.1.5-20220927T221042Z' +container_release_tag: '1.1.5' +ref: '63d6a20970b8b37506141a2529fe5f3e8deaa3a1' +git_tag: '1.1.5-slice-analysis-ms' diff --git a/releases/slice-analysis-ms-1.2.1-container.yaml b/releases/slice-analysis-ms-1.2.1-container.yaml new file mode 100644 index 00000000..561b3cff --- /dev/null +++ b/releases/slice-analysis-ms-1.2.1-container.yaml @@ -0,0 +1,10 @@ +distribution_type: 'container' +version: '1.2.1' +project: 'dcaegen2-services-slice-analysis-ms' +log_dir: 'dcaegen2-services-slice-analysis-ms-maven-docker-stage-master/979' +containers: + - name: 'org.onap.dcaegen2.services.components.slice-analysis-ms' + version: '1.2.1-20230331T015044Z' +container_release_tag: '1.2.1' +ref: 'c7ea15da1edda4281e6d45e621d12a0d0d892bbe' +git_tag: '1.2.1-slice-analysis-ms' |