summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.gitignore2
-rw-r--r--checkstyle/pom.xml2
-rwxr-xr-xcps-application/pom.xml44
-rw-r--r--cps-bom/pom.xml2
-rwxr-xr-xcps-dependencies/pom.xml236
-rw-r--r--cps-events/pom.xml2
-rw-r--r--cps-ncmp-events/pom.xml2
-rw-r--r--cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-dmi-in-event-schema-1.0.0.json94
-rw-r--r--cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-ncmp-in-event-schema-1.0.0.json74
-rw-r--r--cps-ncmp-events/src/main/resources/schemas/trustlevel/device-trust-level-event-schema-1.0.0.json30
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml2
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml33
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java23
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/SampleCpsNcmpClientSpec.groovy82
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/TestApplication.groovy28
-rw-r--r--cps-ncmp-rest-stub/pom.xml2
-rw-r--r--cps-ncmp-rest/docs/openapi/components.yaml20
-rw-r--r--cps-ncmp-rest/pom.xml19
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapper.java3
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java12
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapper.java8
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy3
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy24
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapperSpec.groovy15
-rw-r--r--cps-ncmp-service/pom.xml4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpResponseStatus.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpEventResponseCode.java)17
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java34
-rwxr-xr-xcps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java98
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java8
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java20
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/EventsPublisher.java37
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java52
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapper.java5
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java19
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java34
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java5
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java80
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java13
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java67
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java16
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java30
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java12
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilter.java58
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java5
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java10
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java12
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java21
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java7
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java53
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceTrustLevel.java)27
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy17
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy44
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy22
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy50
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy32
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapperSpec.groovy29
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy25
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy83
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilterSpec.groovy41
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDogSpec.groovy3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy5
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy5
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy28
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy26
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy10
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy22
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy41
-rwxr-xr-xcps-parent/pom.xml2
-rw-r--r--cps-path-parser/pom.xml2
-rwxr-xr-xcps-rest/pom.xml20
-rw-r--r--cps-ri/pom.xml2
-rwxr-xr-xcps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java3
-rwxr-xr-xcps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java26
-rw-r--r--cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java93
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy2
-rw-r--r--cps-service/pom.xml53
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java4
-rwxr-xr-xcps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java27
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java2
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy15
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy2
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml4
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml2
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java12
-rw-r--r--dmi-plugin-demo-and-csit-stub/pom.xml2
-rw-r--r--docker-compose/docker-compose.yml2
-rw-r--r--docs/cps-ncmp-message-status-codes.rst12
-rw-r--r--docs/cps-path.rst4
-rw-r--r--docs/cps-stubs.rst120
-rw-r--r--docs/deployment.rst4
-rwxr-xr-xdocs/design.rst33
-rwxr-xr-xdocs/index.rst1
-rwxr-xr-xdocs/release-notes.rst40
-rw-r--r--docs/spelling_wordlist.txt67
-rw-r--r--docs/tox.ini10
-rw-r--r--integration-test/pom.xml2
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/TestConfig.groovy2
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy2
-rw-r--r--jacoco-report/pom.xml2
-rw-r--r--pom.xml2
-rw-r--r--releases/3.3.8-container.yaml8
-rw-r--r--releases/3.3.8.yaml4
-rw-r--r--spotbugs/pom.xml2
-rwxr-xr-xversion.properties2
114 files changed, 1810 insertions, 805 deletions
diff --git a/.gitignore b/.gitignore
index b4abc48bc..c59fc4731 100755
--- a/.gitignore
+++ b/.gitignore
@@ -27,10 +27,10 @@ tmp/
.checkstyle
/.tox
-/_build/*
/__pycache__/*
/docs/docs/
/docs/.vscode/
+/docs/_build/*
/test-tools/metrics-reports/
diff --git a/checkstyle/pom.xml b/checkstyle/pom.xml
index 4cf950efd..7d190fe10 100644
--- a/checkstyle/pom.xml
+++ b/checkstyle/pom.xml
@@ -26,7 +26,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.cps</groupId>
<artifactId>checkstyle</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<profiles>
<profile>
diff --git a/cps-application/pom.xml b/cps-application/pom.xml
index 3b5069a1c..f4e3e916f 100755
--- a/cps-application/pom.xml
+++ b/cps-application/pom.xml
@@ -28,7 +28,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
@@ -66,6 +66,18 @@
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-http</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.servlet</groupId>
+ <artifactId>jakarta.servlet-api</artifactId>
+ </dependency>
+ <dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
@@ -73,6 +85,11 @@
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-xml</artifactId>
+ </dependency>
+
<!-- T E S T D E P E N D E N C I E S -->
<dependency>
<groupId>org.springframework.security</groupId>
@@ -100,6 +117,10 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>com.tngtech.archunit</groupId>
+ <artifactId>archunit-junit5</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
@@ -110,26 +131,7 @@
</exclusion>
</exclusions>
</dependency>
- <dependency>
- <groupId>com.tngtech.archunit</groupId>
- <artifactId>archunit-junit5</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.dataformat</groupId>
- <artifactId>jackson-dataformat-xml</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- </dependency>
- <dependency>
- <groupId>jakarta.servlet</groupId>
- <artifactId>jakarta.servlet-api</artifactId>
- </dependency>
+
</dependencies>
<build>
diff --git a/cps-bom/pom.xml b/cps-bom/pom.xml
index 0f5cb4b48..b9da8b29a 100644
--- a/cps-bom/pom.xml
+++ b/cps-bom/pom.xml
@@ -25,7 +25,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.cps</groupId>
<artifactId>cps-bom</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<packaging>pom</packaging>
<description>This artifact contains dependencyManagement declarations of all published CPS components.</description>
diff --git a/cps-dependencies/pom.xml b/cps-dependencies/pom.xml
index f6931c302..cff596f05 100755
--- a/cps-dependencies/pom.xml
+++ b/cps-dependencies/pom.xml
@@ -27,7 +27,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.cps</groupId>
<artifactId>cps-dependencies</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<packaging>pom</packaging>
<name>${project.groupId}:${project.artifactId}</name>
@@ -41,6 +41,7 @@
<sonar.skip>true</sonar.skip>
<testcontainers.version>1.18.3</testcontainers.version>
<mapstruct.version>1.4.2.Final</mapstruct.version>
+ <jetty-version>11.0.16</jetty-version>
</properties>
<build>
@@ -70,6 +71,7 @@
<dependencyManagement>
<dependencies>
+ <!-- S P R I N G D E P E N D E N C I E S -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
@@ -90,16 +92,9 @@
<scope>import</scope>
</dependency>
<dependency>
- <groupId>org.opendaylight.yangtools</groupId>
- <artifactId>yangtools-artifacts</artifactId>
- <version>8.0.6</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>io.swagger.core.v3</groupId>
- <artifactId>swagger-annotations</artifactId>
- <version>2.2.10</version>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>6.0.11</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
@@ -107,94 +102,88 @@
<version>3.1.2</version>
</dependency>
<dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- <version>2.8.9</version>
- </dependency>
- <dependency>
- <groupId>io.hypersistence</groupId>
- <artifactId>hypersistence-utils-hibernate-60</artifactId>
- <version>3.5.0</version>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-cache</artifactId>
+ <version>3.1.2</version>
</dependency>
+ <!-- A L P H A B E T I C A L D E P E N D E N C I E S -->
<dependency>
- <groupId>org.antlr</groupId>
- <artifactId>antlr4-runtime</artifactId>
- <version>4.9.2</version>
+ <groupId>cglib</groupId>
+ <artifactId>cglib-nodep</artifactId>
+ <version>3.1</version>
</dependency>
<dependency>
- <groupId>org.codehaus.groovy</groupId>
- <artifactId>groovy</artifactId>
- <version>${groovy.version}</version>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.15.2</version>
</dependency>
<dependency>
- <groupId>org.codehaus.groovy</groupId>
- <artifactId>groovy-json</artifactId>
- <version>${groovy.version}</version>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-xml</artifactId>
+ <version>2.13.1</version>
</dependency>
<dependency>
- <groupId>org.spockframework</groupId>
- <artifactId>spock-core</artifactId>
- <version>2.4-M1-groovy-3.0</version>
+ <groupId>com.github.spotbugs</groupId>
+ <artifactId>spotbugs</artifactId>
+ <version>4.2.0</version>
</dependency>
<dependency>
- <groupId>org.spockframework</groupId>
- <artifactId>spock-spring</artifactId>
- <version>2.4-M1-groovy-3.0</version>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.8.9</version>
</dependency>
<dependency>
- <groupId>cglib</groupId>
- <artifactId>cglib-nodep</artifactId>
- <version>3.1</version>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>31.1-jre</version>
</dependency>
<dependency>
- <groupId>io.cloudevents</groupId>
- <artifactId>cloudevents-bom</artifactId>
- <version>2.5.0</version>
- <type>pom</type>
- <scope>import</scope>
+ <groupId>com.hazelcast</groupId>
+ <artifactId>hazelcast-spring</artifactId>
+ <version>5.3.1</version>
</dependency>
<dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>3.11</version>
+ <groupId>com.tngtech.archunit</groupId>
+ <artifactId>archunit-junit5</artifactId>
+ <version>0.18.0</version>
+ <scope>test</scope>
</dependency>
<dependency>
- <groupId>org.jetbrains</groupId>
- <artifactId>annotations</artifactId>
- <version>22.0.0</version>
+ <groupId>jakarta.validation</groupId>
+ <artifactId>jakarta.validation-api</artifactId>
+ <version>3.0.2</version>
</dependency>
<dependency>
- <groupId>org.testcontainers</groupId>
- <artifactId>testcontainers-bom</artifactId>
- <version>1.18.3</version>
+ <groupId>io.cloudevents</groupId>
+ <artifactId>cloudevents-bom</artifactId>
+ <version>2.5.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
- <groupId>com.github.spotbugs</groupId>
- <artifactId>spotbugs</artifactId>
- <version>4.2.0</version>
+ <groupId>io.gsonfire</groupId>
+ <artifactId>gson-fire</artifactId>
+ <version>1.8.5</version>
</dependency>
<dependency>
- <groupId>org.liquibase</groupId>
- <artifactId>liquibase-core</artifactId>
- <version>4.16.0</version>
+ <groupId>io.hypersistence</groupId>
+ <artifactId>hypersistence-utils-hibernate-60</artifactId>
+ <version>3.5.0</version>
</dependency>
<dependency>
- <groupId>com.tngtech.archunit</groupId>
- <artifactId>archunit-junit5</artifactId>
- <version>0.18.0</version>
- <scope>test</scope>
+ <groupId>io.micrometer</groupId>
+ <artifactId>micrometer-tracing-bridge-brave</artifactId>
+ <version>1.0.0</version>
</dependency>
<dependency>
- <groupId>org.mapstruct</groupId>
- <artifactId>mapstruct</artifactId>
- <version>${mapstruct.version}</version>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-annotations</artifactId>
+ <version>2.2.10</version>
</dependency>
<dependency>
- <groupId>org.mapstruct</groupId>
- <artifactId>mapstruct-processor</artifactId>
- <version>${mapstruct.version}</version>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-models</artifactId>
+ <version>2.2.15</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
@@ -202,24 +191,14 @@
<version>7.0.1</version>
</dependency>
<dependency>
- <groupId>org.codehaus.janino</groupId>
- <artifactId>janino</artifactId>
- <version>3.1.7</version>
- </dependency>
- <dependency>
- <groupId>com.hazelcast</groupId>
- <artifactId>hazelcast-spring</artifactId>
- <version>5.3.1</version>
- </dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>31.1-jre</version>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ <version>4.9.2</version>
</dependency>
<dependency>
- <groupId>javax.validation</groupId>
- <artifactId>validation-api</artifactId>
- <version>2.0.1.Final</version>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.11</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
@@ -227,54 +206,54 @@
<version>3.3.1</version>
</dependency>
<dependency>
- <groupId>jakarta.validation</groupId>
- <artifactId>jakarta.validation-api</artifactId>
- <version>3.0.2</version>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy</artifactId>
+ <version>${groovy.version}</version>
</dependency>
<dependency>
- <groupId>io.micrometer</groupId>
- <artifactId>micrometer-tracing-bridge-brave</artifactId>
- <version>1.0.0</version>
+ <groupId>org.codehaus.janino</groupId>
+ <artifactId>janino</artifactId>
+ <version>3.1.7</version>
</dependency>
<dependency>
- <groupId>com.fasterxml.jackson.dataformat</groupId>
- <artifactId>jackson-dataformat-xml</artifactId>
- <version>2.13.1</version>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-json</artifactId>
+ <version>${groovy.version}</version>
</dependency>
<dependency>
- <groupId>io.swagger.core.v3</groupId>
- <artifactId>swagger-models</artifactId>
- <version>2.2.15</version>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${jetty-version}</version>
</dependency>
<dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.24</version>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-http</artifactId>
+ <version>${jetty-version}</version>
</dependency>
<dependency>
- <groupId>io.gsonfire</groupId>
- <artifactId>gson-fire</artifactId>
- <version>1.8.5</version>
+ <groupId>org.jetbrains</groupId>
+ <artifactId>annotations</artifactId>
+ <version>22.0.0</version>
</dependency>
<dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.15.2</version>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <version>5.10.0</version>
</dependency>
<dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- <version>11.0.14</version>
+ <groupId>org.liquibase</groupId>
+ <artifactId>liquibase-core</artifactId>
+ <version>4.16.0</version>
</dependency>
<dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- <version>11.0.14</version>
+ <groupId>org.mapstruct</groupId>
+ <artifactId>mapstruct</artifactId>
+ <version>${mapstruct.version}</version>
</dependency>
<dependency>
- <groupId>jakarta.servlet</groupId>
- <artifactId>jakarta.servlet-api</artifactId>
- <version>6.0.0</version>
+ <groupId>org.mapstruct</groupId>
+ <artifactId>mapstruct-processor</artifactId>
+ <version>${mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
@@ -282,14 +261,33 @@
<version>0.2.4</version>
</dependency>
<dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-api</artifactId>
- <version>5.10.0</version>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yangtools-artifacts</artifactId>
+ <version>8.0.6</version>
+ <type>pom</type>
+ <scope>import</scope>
</dependency>
<dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <version>6.0.11</version>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <version>1.18.24</version>
+ </dependency>
+ <dependency>
+ <groupId>org.testcontainers</groupId>
+ <artifactId>testcontainers-bom</artifactId>
+ <version>1.18.3</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.spockframework</groupId>
+ <artifactId>spock-core</artifactId>
+ <version>2.4-M1-groovy-3.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.spockframework</groupId>
+ <artifactId>spock-spring</artifactId>
+ <version>2.4-M1-groovy-3.0</version>
</dependency>
</dependencies>
</dependencyManagement>
diff --git a/cps-events/pom.xml b/cps-events/pom.xml
index d776ccb09..6d16203a6 100644
--- a/cps-events/pom.xml
+++ b/cps-events/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-ncmp-events/pom.xml b/cps-ncmp-events/pom.xml
index 6a5ba4bf5..a59e92510 100644
--- a/cps-ncmp-events/pom.xml
+++ b/cps-ncmp-events/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-dmi-in-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-dmi-in-event-schema-1.0.0.json
new file mode 100644
index 000000000..caffb6334
--- /dev/null
+++ b/cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-dmi-in-event-schema-1.0.0.json
@@ -0,0 +1,94 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-merge-dmi-in-event-schema:1.0.0",
+ "$ref": "#/definitions/CmSubscriptionMergeDmiInEvent",
+ "definitions": {
+ "CmSubscriptionMergeDmiInEvent": {
+ "description": "The payload for cm subscription merge event incoming message from NCMP.",
+ "type": "object",
+ "javaType": "org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.ncmp_to_dmi.CmSubscriptionMergeDmiInEvent",
+ "additionalProperties": false,
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/data"
+ }
+ },
+ "required": [
+ "data"
+ ]
+ },
+ "data": {
+ "type": "object",
+ "description": "The actual data containing information about the targets and subscription",
+ "additionalProperties": false,
+ "properties": {
+ "cmhandles": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Details for the target cmhandles",
+ "additionalProperties": false,
+ "properties": {
+ "cmhandleId": {
+ "type": "string"
+ },
+ "private-properties": {
+ "type": "object",
+ "existingJavaType": "java.util.Map<String,String>",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "predicates": {
+ "type": "array",
+ "description": "Additional values to be added into the subscription",
+ "items": {
+ "type": "object",
+ "properties": {
+ "targetFilter": {
+ "description": "CM Handles to be targeted by the subscription",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "scopeFilter": {
+ "type": "object",
+ "properties": {
+ "datastore": {
+ "description": "datastore which is to be used by the subscription",
+ "type": "string",
+ "enum": ["ncmp-datastore:passthrough-operational", "ncmp-datastore:passthrough-running"]
+ },
+ "xpath-filter": {
+ "description": "filter to be applied to the CM Handles through this event",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "xpath-filter"
+ ]
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "targetFilter"
+ ]
+ },
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "cmhandles",
+ "predicates"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-ncmp-in-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-ncmp-in-event-schema-1.0.0.json
new file mode 100644
index 000000000..274206256
--- /dev/null
+++ b/cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-ncmp-in-event-schema-1.0.0.json
@@ -0,0 +1,74 @@
+{
+ "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-merge-ncmp-in-event:1.0.0",
+ "$ref": "#/definitions/CmSubscriptionMergeNcmpInEvent",
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "definitions": {
+ "CmSubscriptionMergeNcmpInEvent": {
+ "description": "The payload for subscription merge event.",
+ "javaType": "org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.client_to_ncmp.CmSubscriptionMergeNcmpInEvent",
+ "properties": {
+ "data": {
+ "properties": {
+ "subscriptionId": {
+ "description": "The subscription details.",
+ "type": "string"
+ },
+ "predicates": {
+ "type": "array",
+ "description": "Additional values to be added into the subscription",
+ "items": {
+ "type": "object",
+ "properties": {
+ "targetFilter": {
+ "description": "CM Handles to be targeted by the subscription",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "scopeFilter": {
+ "type": "object",
+ "properties": {
+ "datastore": {
+ "description": "datastore which is to be used by the subscription",
+ "type": "string",
+ "enum": ["ncmp-datastore:passthrough-operational", "ncmp-datastore:passthrough-running"]
+ },
+ "xpath-filter": {
+ "description": "filter to be applied to the CM Handles through this event",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "xpath-filter"
+ ]
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "targetFilter"
+ ]
+ },
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "subscriptionId",
+ "predicates"
+ ],
+ "type": "object",
+ "additionalProperties": false
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "data"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/cps-ncmp-events/src/main/resources/schemas/trustlevel/device-trust-level-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/trustlevel/device-trust-level-event-schema-1.0.0.json
new file mode 100644
index 000000000..e1796fbc7
--- /dev/null
+++ b/cps-ncmp-events/src/main/resources/schemas/trustlevel/device-trust-level-event-schema-1.0.0.json
@@ -0,0 +1,30 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "urn:cps:org.onap.cps.ncmp.events:device-trust-level-event-schema:1.0.0",
+ "$ref": "#/definitions/DeviceTrustLevel",
+ "definitions": {
+ "DeviceTrustLevel" : {
+ "description": "The payload for device trust level event.",
+ "type": "object",
+ "javaType": "org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel",
+ "properties": {
+ "data": {
+ "type": "object",
+ "properties": {
+ "trustLevel": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "trustLevel"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "data"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml
index 275313c3b..205a33c89 100644
--- a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml
@@ -22,7 +22,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-ncmp-rest-stub</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
</parent>
<artifactId>cps-ncmp-rest-stub-app</artifactId>
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
index 435cc7048..d2cce8797 100644
--- a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-ncmp-rest-stub</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
</parent>
<artifactId>cps-ncmp-rest-stub-service</artifactId>
@@ -46,11 +46,42 @@
<groupId>org.onap.cps</groupId>
<artifactId>cps-ncmp-rest</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.servlet</groupId>
+ <artifactId>jakarta.servlet-api</artifactId>
+ </dependency>
<!-- T E S T - D E P E N D E N C I E S -->
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.junit.vintage</groupId>
+ <artifactId>junit-vintage-engine</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.spockframework</groupId>
+ <artifactId>spock-spring</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.spockframework</groupId>
+ <artifactId>spock-core</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+
</project> \ No newline at end of file
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
index 198b14fc3..e33af45f9 100644
--- a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
@@ -141,13 +141,13 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
}
@Override
- public ResponseEntity<Void> createResourceDataRunningForCmHandle(@NotNull @Valid final String resourceIdentifier,
- final String datastoreName, final String cmHandle,
- @Valid final Object body,
+ public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String datastoreName, final String cmHandle,
+ @NotNull @Valid final String resourceIdentifier,
+ @Valid final Object body,
final String contentType) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
-
+
@Override
public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName, final String cmHandle,
@NotNull @Valid final String resourceIdentifier,
@@ -183,13 +183,13 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
}
@Override
- public ResponseEntity<Object> patchResourceDataRunningForCmHandle(@NotNull @Valid final String resourceIdentifier,
- final String datastoreName, final String cmHandle,
- @Valid final Object body,
+ public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String datastoreName, final String cmHandle,
+ @NotNull @Valid final String resourceIdentifier,
+ @Valid final Object body,
final String contentType) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
-
+
@Override
public ResponseEntity<Object> queryResourceDataForCmHandle(final String datastoreName, final String cmHandle,
@Valid final String cpsPath, @Valid final String options,
@@ -218,9 +218,10 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
}
@Override
- public ResponseEntity<Object> updateResourceDataRunningForCmHandle(@NotNull @Valid final String resourceIdentifier,
- final String datastoreName,
- final String cmHandle, @Valid final Object body,
+ public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String datastoreName,
+ final String cmHandle,
+ @NotNull @Valid final String resourceIdentifier,
+ @Valid final Object body,
final String contentType) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/SampleCpsNcmpClientSpec.groovy b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/SampleCpsNcmpClientSpec.groovy
new file mode 100644
index 000000000..b36e25ada
--- /dev/null
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/SampleCpsNcmpClientSpec.groovy
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 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.
+ * 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.cps.ncmp.rest.stub
+
+import org.onap.cps.ncmp.api.impl.operations.DatastoreType
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration
+import org.springframework.boot.test.context.SpringBootContextLoader
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.boot.test.web.client.TestRestTemplate
+import org.springframework.boot.test.web.server.LocalServerPort
+import org.springframework.http.HttpStatus
+import org.springframework.test.context.ActiveProfiles
+import org.springframework.test.context.ContextConfiguration
+
+import com.fasterxml.jackson.core.JsonProcessingException
+import com.fasterxml.jackson.core.type.TypeReference
+import com.fasterxml.jackson.databind.JsonMappingException
+import com.fasterxml.jackson.databind.ObjectMapper
+
+import spock.lang.Shared
+import spock.lang.Specification
+
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+class SampleCpsNcmpClientSpec extends Specification {
+
+ static final String CM_HANDLE = "anything"
+
+ static final String DATA_STORE_NAME = DatastoreType.PASSTHROUGH_OPERATIONAL.getDatastoreName()
+
+ @LocalServerPort
+ def port
+
+ final def testRestTemplate = new TestRestTemplate()
+
+ @Value('${rest.api.ncmp-stub-base-path}')
+ def stubBasePath
+
+ @Autowired
+ ObjectMapper objectMapper
+
+ def 'Test the invocation of the stub API' () throws JsonMappingException, JsonProcessingException {
+
+ when: 'Get resource data for cm handle URL is invoked'
+ def url = "${getBaseUrl()}/v1/ch/${CM_HANDLE}/data/ds/${DATA_STORE_NAME}?resourceIdentifier=parent&options=(a=1,b=2)"
+ def response = testRestTemplate.getForEntity(url, String.class)
+ then: 'Response is OK'
+ response.getStatusCode() == HttpStatus.OK
+
+ and: 'Response body contains customized stub response that contains correct bookstore category code'
+ def typeRef = new TypeReference<HashMap<String, Object>>() {}
+ def map = objectMapper.readValue(response.getBody(), typeRef)
+ def obj1 = (Map<String, Object>) map.get("stores:bookstore")
+ def obj2 = (List<Object>) obj1.get("categories")
+ def obj3 = (Map<String, Object>) obj2.iterator().next()
+
+ assert obj3.get("code") == "02"
+ }
+
+ def String getBaseUrl() {
+ return "http://localhost:" + port + stubBasePath
+ }
+}
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/TestApplication.groovy b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/TestApplication.groovy
new file mode 100644
index 000000000..79384239a
--- /dev/null
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/TestApplication.groovy
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 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.
+ * 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.cps.ncmp.rest.stub
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.context.annotation.ComponentScan
+
+@SpringBootApplication
+@ComponentScan(basePackages = ["org.onap.cps.ncmp.rest.stub", "org.onap.cps.ncmp.rest.stub.controller", "org.onap.cps.ncmp.rest.api"])
+class TestApplication {
+}
diff --git a/cps-ncmp-rest-stub/pom.xml b/cps-ncmp-rest-stub/pom.xml
index 4db8617b9..9e62ff592 100644
--- a/cps-ncmp-rest-stub/pom.xml
+++ b/cps-ncmp-rest-stub/pom.xml
@@ -22,7 +22,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml
index 9bae794a3..022e2bab7 100644
--- a/cps-ncmp-rest/docs/openapi/components.yaml
+++ b/cps-ncmp-rest/docs/openapi/components.yaml
@@ -87,6 +87,8 @@ components:
items:
type: string
example: [ my-cm-handle1, my-cm-handle2, my-cm-handle3 ]
+ upgradedCmHandles:
+ $ref: '#/components/schemas/UpgradedCmHandles'
DmiPluginRegistrationErrorResponse:
type: object
properties:
@@ -102,6 +104,10 @@ components:
type: array
items:
$ref: '#/components/schemas/CmHandlerRegistrationErrorResponse'
+ failedUpgradeCmHandles:
+ type: array
+ items:
+ $ref: '#/components/schemas/CmHandlerRegistrationErrorResponse'
CmHandlerRegistrationErrorResponse:
type: object
properties:
@@ -135,6 +141,20 @@ components:
additionalProperties:
type: string
example: my-property
+ #Module upgrade schema
+ UpgradedCmHandles:
+ required:
+ - cmHandles
+ type: object
+ properties:
+ cmHandles:
+ type: array
+ items:
+ type: string
+ example: [ my-cm-handle1, my-cm-handle2, my-cm-handle3 ]
+ moduleSetTag:
+ type: string
+ example: 'my-module-set-tag'
#Response Schemas
RestModuleReference:
diff --git a/cps-ncmp-rest/pom.xml b/cps-ncmp-rest/pom.xml
index ef34b1d36..6a52d9f1a 100644
--- a/cps-ncmp-rest/pom.xml
+++ b/cps-ncmp-rest/pom.xml
@@ -27,7 +27,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
@@ -62,6 +62,10 @@
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
@@ -77,6 +81,10 @@
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.openapitools</groupId>
+ <artifactId>jackson-databind-nullable</artifactId>
+ </dependency>
<!-- T E S T D E P E N D E N C I E S -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
@@ -115,16 +123,9 @@
</exclusions>
</dependency>
<dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- </dependency>
- <dependency>
- <groupId>org.openapitools</groupId>
- <artifactId>jackson-databind-nullable</artifactId>
- </dependency>
- <dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
+ <scope>test</scope>
</dependency>
</dependencies>
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapper.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapper.java
index b3f36f9c8..af785d565 100644
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapper.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapper.java
@@ -48,6 +48,9 @@ public interface NcmpRestInputMapper {
@Mapping(source = "removedCmHandles", target = "removedCmHandles",
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
+ @Mapping(source = "upgradedCmHandles", target = "upgradedCmHandles",
+ nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS,
+ nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
DmiPluginRegistration toDmiPluginRegistration(final RestDmiPluginRegistration restDmiPluginRegistration);
@Mapping(source = "cmHandle", target = "cmHandleId")
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java
index 87f9d835a..453abcabb 100755
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java
@@ -110,23 +110,23 @@ public class NetworkCmProxyInventoryController implements NetworkCmProxyInventor
getFailedResponses(dmiPluginRegistrationResponse.getUpdatedCmHandles()));
dmiPluginRegistrationErrorResponse.setFailedRemovedCmHandles(
getFailedResponses(dmiPluginRegistrationResponse.getRemovedCmHandles()));
-
+ dmiPluginRegistrationErrorResponse.setFailedUpgradeCmHandles(
+ getFailedResponses(dmiPluginRegistrationResponse.getUpgradedCmHandles()));
return dmiPluginRegistrationErrorResponse;
}
private List<CmHandlerRegistrationErrorResponse> getFailedResponses(
- final List<CmHandleRegistrationResponse> cmHandleRegistrationResponseList) {
+ final List<CmHandleRegistrationResponse> cmHandleRegistrationResponseList) {
return cmHandleRegistrationResponseList.stream()
- .filter(cmHandleRegistrationResponse -> cmHandleRegistrationResponse.getStatus() == Status.FAILURE)
- .map(this::toCmHandleRegistrationErrorResponse)
- .collect(Collectors.toList());
+ .filter(cmHandleRegistrationResponse -> cmHandleRegistrationResponse.getStatus() == Status.FAILURE)
+ .map(this::toCmHandleRegistrationErrorResponse).collect(Collectors.toList());
}
private CmHandlerRegistrationErrorResponse toCmHandleRegistrationErrorResponse(
final CmHandleRegistrationResponse registrationResponse) {
return new CmHandlerRegistrationErrorResponse()
.cmHandle(registrationResponse.getCmHandle())
- .errorCode(registrationResponse.getRegistrationError().errorCode)
+ .errorCode(registrationResponse.getNcmpResponseStatus().getCode())
.errorText(registrationResponse.getErrorText());
}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapper.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapper.java
index 82dc4837f..b436540fc 100644
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapper.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapper.java
@@ -20,6 +20,8 @@
package org.onap.cps.ncmp.rest.mapper;
+import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.LOCKED_MISBEHAVING;
+
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
@@ -75,8 +77,10 @@ public interface CmHandleStateMapper {
@Named("toExternalLockReason")
static LockReason toExternalLockReason(CompositeState.LockReason internalLockReason) {
final LockReason externalLockReason = new LockReason();
- if (internalLockReason.getLockReasonCategory() != null) {
- externalLockReason.setReason("LOCKED_MISBEHAVING");
+ if (internalLockReason.getLockReasonCategory() == null) {
+ externalLockReason.setReason(LOCKED_MISBEHAVING.name());
+ } else {
+ externalLockReason.setReason(internalLockReason.getLockReasonCategory().name());
}
externalLockReason.setDetails(internalLockReason.getDetails());
return externalLockReason;
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
index 6bfa5936e..de044d0aa 100644
--- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
@@ -615,8 +615,7 @@ class NetworkCmProxyControllerSpec extends Specification {
def expectedContent = [
'"state":',
'"cmHandleState":"ADVISED"',
- '"reason":"LOCKED_MISBEHAVING"',
- '"details":"lock details"',
+ '"lockReason":{"reason":"MODULE_SYNC_FAILED","details":"lock details"}',
'"lastUpdateTime":"2022-12-31T20:30:40.000+0000"',
'"dataSyncEnabled":false',
'"dataSyncState":',
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy
index e755094dd..1d03be107 100644
--- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy
@@ -219,14 +219,14 @@ class NetworkCmProxyInventoryControllerSpec extends Specification {
responseBody.getFailedUpdatedCmHandles() == expectedFailedUpdateCmHandle
responseBody.getFailedRemovedCmHandles() == expectedFailedRemovedCmHandle
where:
- scenario | createCmHandleResponse | updateCmHandleResponse | removeCmHandleResponse || expectedFailedCreatedCmHandle | expectedFailedUpdateCmHandle | expectedFailedRemovedCmHandle
- 'only create failed' | failedResponse('cm-handle-1') | successResponse('cm-handle-2') | successResponse('cm-handle-3') || [failedRestResponse('cm-handle-1')] | [] | []
- 'only update failed' | successResponse('cm-handle-1') | failedResponse('cm-handle-2') | successResponse('cm-handle-3') || [] | [failedRestResponse('cm-handle-2')] | []
- 'only delete failed' | successResponse('cm-handle-1') | successResponse('cm-handle-2') | failedResponse('cm-handle-3') || [] | [] | [failedRestResponse('cm-handle-3')]
- 'all three failed' | failedResponse('cm-handle-1') | failedResponse('cm-handle-2') | failedResponse('cm-handle-3') || [failedRestResponse('cm-handle-1')] | [failedRestResponse('cm-handle-2')] | [failedRestResponse('cm-handle-3')]
- 'create update failed' | failedResponse('cm-handle-1') | failedResponse('cm-handle-2') | successResponse('cm-handle-3') || [failedRestResponse('cm-handle-1')] | [failedRestResponse('cm-handle-2')] | []
- 'create delete failed' | failedResponse('cm-handle-1') | successResponse('cm-handle-2') | failedResponse('cm-handle-3') || [failedRestResponse('cm-handle-1')] | [] | [failedRestResponse('cm-handle-3')]
- 'update delete failed' | successResponse('cm-handle-1') | failedResponse('cm-handle-2') | failedResponse('cm-handle-3') || [] | [failedRestResponse('cm-handle-2')] | [failedRestResponse('cm-handle-3')]
+ scenario | createCmHandleResponse | updateCmHandleResponse | removeCmHandleResponse || expectedFailedCreatedCmHandle | expectedFailedUpdateCmHandle | expectedFailedRemovedCmHandle
+ 'only create failed' | expectedFailedResponse('cm-handle-1') | expectedSuccessResponse('cm-handle-2') | expectedSuccessResponse('cm-handle-3') || [expectedUnknownErrorResponse('cm-handle-1')] | [] | []
+ 'only update failed' | expectedSuccessResponse('cm-handle-1') | expectedFailedResponse('cm-handle-2') | expectedSuccessResponse('cm-handle-3') || [] | [expectedUnknownErrorResponse('cm-handle-2')] | []
+ 'only delete failed' | expectedSuccessResponse('cm-handle-1') | expectedSuccessResponse('cm-handle-2') | expectedFailedResponse('cm-handle-3') || [] | [] | [expectedUnknownErrorResponse('cm-handle-3')]
+ 'all three failed' | expectedFailedResponse('cm-handle-1') | expectedFailedResponse('cm-handle-2') | expectedFailedResponse('cm-handle-3') || [expectedUnknownErrorResponse('cm-handle-1')] | [expectedUnknownErrorResponse('cm-handle-2')] | [expectedUnknownErrorResponse('cm-handle-3')]
+ 'create update failed' | expectedFailedResponse('cm-handle-1') | expectedFailedResponse('cm-handle-2') | expectedSuccessResponse('cm-handle-3') || [expectedUnknownErrorResponse('cm-handle-1')] | [expectedUnknownErrorResponse('cm-handle-2')] | []
+ 'create delete failed' | expectedFailedResponse('cm-handle-1') | expectedSuccessResponse('cm-handle-2') | expectedFailedResponse('cm-handle-3') || [expectedUnknownErrorResponse('cm-handle-1')] | [] | [expectedUnknownErrorResponse('cm-handle-3')]
+ 'update delete failed' | expectedSuccessResponse('cm-handle-1') | expectedFailedResponse('cm-handle-2') | expectedFailedResponse('cm-handle-3') || [] | [expectedUnknownErrorResponse('cm-handle-2')] | [expectedUnknownErrorResponse('cm-handle-3')]
}
def 'Get all cm handle IDs by DMI plugin identifier.'() {
@@ -246,15 +246,15 @@ class NetworkCmProxyInventoryControllerSpec extends Specification {
assert response.contentAsString.contains('cm-handle-id-2')
}
- def failedRestResponse(cmHandle) {
- return new CmHandlerRegistrationErrorResponse('cmHandle': cmHandle, 'errorCode': '00', 'errorText': 'Failed')
+ def expectedUnknownErrorResponse(cmHandle) {
+ return new CmHandlerRegistrationErrorResponse('cmHandle': cmHandle, 'errorCode': '108', 'errorText': 'Failed')
}
- def failedResponse(cmHandle) {
+ def expectedFailedResponse(cmHandle) {
return CmHandleRegistrationResponse.createFailureResponse(cmHandle, new RuntimeException('Failed'))
}
- def successResponse(cmHandle) {
+ def expectedSuccessResponse(cmHandle) {
return CmHandleRegistrationResponse.createSuccessResponse(cmHandle)
}
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapperSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapperSpec.groovy
index 1fa83a539..f394f9193 100644
--- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapperSpec.groovy
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/mapper/CmHandleStateMapperSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * Copyright (C) 2022-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.
@@ -20,6 +20,7 @@
package org.onap.cps.ncmp.rest.mapper
+import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.LOCKED_MISBEHAVING
import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_SYNC_FAILED
import org.mapstruct.factory.Mappers
@@ -55,7 +56,7 @@ class CmHandleStateMapperSpec extends Specification {
and: 'mapped result should have correct values'
assert !result.dataSyncEnabled
assert result.lastUpdateTime == formattedDateAndTime
- assert result.lockReason.reason == 'LOCKED_MISBEHAVING'
+ assert result.lockReason.reason == MODULE_SYNC_FAILED.name()
assert result.lockReason.details == 'locked details'
assert result.cmHandleState == 'ADVISED'
assert result.dataSyncState.operational.getSyncState() != null
@@ -69,17 +70,17 @@ class CmHandleStateMapperSpec extends Specification {
def 'Internal to External Lock Reason Mapping of #scenario'() {
given: 'a LOCKED composite state with locked reason of #scenario'
- def compositeState = new CompositeStateBuilder()
+ def compositeState = new CompositeStateBuilder()
.withCmHandleState(CmHandleState.LOCKED)
.withLockReason(lockReason, '').build()
when: 'the composite state is mapped to a CMHandle composite state'
- def result = objectUnderTest.toCmHandleCompositeStateExternalLockReason(compositeState)
+ def result = objectUnderTest.toCmHandleCompositeStateExternalLockReason(compositeState)
then: 'the composite state contains the expected lock Reason and details'
- result.getLockReason().getReason() == expectedExternalLockReason
+ result.getLockReason().getReason() == (expectedExternalLockReason as String)
where:
scenario | lockReason || expectedExternalLockReason
- 'MODULE_SYNC_FAILED' | MODULE_SYNC_FAILED || 'LOCKED_MISBEHAVING'
- 'null value' | null || null
+ 'MODULE_SYNC_FAILED' | MODULE_SYNC_FAILED || MODULE_SYNC_FAILED
+ 'null value' | null || LOCKED_MISBEHAVING
}
}
diff --git a/cps-ncmp-service/pom.xml b/cps-ncmp-service/pom.xml
index 527d70b55..d7c177473 100644
--- a/cps-ncmp-service/pom.xml
+++ b/cps-ncmp-service/pom.xml
@@ -27,14 +27,14 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
<artifactId>cps-ncmp-service</artifactId>
<properties>
- <minimum-coverage>0.98</minimum-coverage>
+ <minimum-coverage>0.96</minimum-coverage>
</properties>
<dependencies>
<dependency>
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpEventResponseCode.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpResponseStatus.java
index 3b1124983..b9c834c55 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpEventResponseCode.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpResponseStatus.java
@@ -23,7 +23,7 @@ package org.onap.cps.ncmp.api;
import lombok.Getter;
@Getter
-public enum NcmpEventResponseCode {
+public enum NcmpResponseStatus {
SUCCESS("0", "Successfully applied changes"),
SUCCESSFULLY_APPLIED_SUBSCRIPTION("1", "successfully applied subscription"),
@@ -33,13 +33,16 @@ public enum NcmpEventResponseCode {
UNABLE_TO_READ_RESOURCE_DATA("103", "dmi plugin service is not able to read resource data"),
PARTIALLY_APPLIED_SUBSCRIPTION("104", "partially applied subscription"),
SUBSCRIPTION_NOT_APPLICABLE("105", "subscription not applicable for all cm handles"),
- SUBSCRIPTION_PENDING("106", "subscription pending for all cm handles");
+ SUBSCRIPTION_PENDING("106", "subscription pending for all cm handles"),
+ UNKNOWN_ERROR("108", "Unknown error"),
+ CM_HANDLE_ALREADY_EXIST("109", "cm-handle already exists"),
+ CM_HANDLE_INVALID_ID("110", "cm-handle has an invalid character(s) in id");
- private final String statusCode;
- private final String statusMessage;
+ private final String code;
+ private final String message;
- NcmpEventResponseCode(final String statusCode, final String statusMessage) {
- this.statusCode = statusCode;
- this.statusMessage = statusMessage;
+ NcmpResponseStatus(final String code, final String message) {
+ this.code = code;
+ this.message = message;
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java
index 58732b207..1f6c94869 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java
@@ -24,6 +24,7 @@ import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DM
import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_MODULES;
import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_PROPERTIES;
import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_CPS_PATH;
+import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_TRUST_LEVEL;
import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCpsPathConditionProperties;
import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateModuleNameConditionProperties;
import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
@@ -70,7 +71,8 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
return executeQueries(cmHandleQueryServiceParameters,
this::executeCpsPathQuery,
this::queryCmHandlesByPublicProperties,
- this::executeModuleNameQuery);
+ this::executeModuleNameQuery,
+ this::queryCmHandlesByTrustLevel);
}
@Override
@@ -117,9 +119,10 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
InventoryQueryConditions.HAS_ALL_ADDITIONAL_PROPERTIES.getName());
- return privatePropertyQueryPairs.isEmpty()
- ? NO_QUERY_TO_EXECUTE
- : cmHandleQueries.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
+ if (privatePropertyQueryPairs.isEmpty()) {
+ return NO_QUERY_TO_EXECUTE;
+ }
+ return cmHandleQueries.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
}
private Collection<String> queryCmHandlesByPublicProperties(
@@ -129,9 +132,23 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
HAS_ALL_PROPERTIES.getConditionName());
- return publicPropertyQueryPairs.isEmpty()
- ? NO_QUERY_TO_EXECUTE
- : cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
+ if (publicPropertyQueryPairs.isEmpty()) {
+ return NO_QUERY_TO_EXECUTE;
+ }
+ return cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
+ }
+
+ private Collection<String> queryCmHandlesByTrustLevel(final CmHandleQueryServiceParameters
+ cmHandleQueryServiceParameters) {
+
+ final Map<String, String> trustLevelPropertyQueryPairs =
+ getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
+ WITH_TRUST_LEVEL.getConditionName());
+
+ if (trustLevelPropertyQueryPairs.isEmpty()) {
+ return NO_QUERY_TO_EXECUTE;
+ }
+ return cmHandleQueries.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs);
}
private Collection<String> executeModuleNameQuery(
@@ -157,7 +174,8 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
}
try {
cpsPathQueryResult = collectCmHandleIdsFromDataNodes(
- cmHandleQueries.queryCmHandleDataNodesByCpsPath(cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS));
+ cmHandleQueries.queryCmHandleAncestorsByCpsPath(
+ cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS));
} catch (final PathParsingException pathParsingException) {
throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(),
pathParsingException);
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
index f8adde85f..a37b27199 100755
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
@@ -24,12 +24,18 @@
package org.onap.cps.ncmp.api.impl;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_READY;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID;
+import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE;
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCmHandleQueryParameters;
import com.google.common.collect.Lists;
import com.hazelcast.map.IMap;
+import java.text.MessageFormat;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Collection;
@@ -48,6 +54,7 @@ import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler;
import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
+import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder;
import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils;
import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState;
import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
@@ -61,11 +68,11 @@ import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters;
import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters;
import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse;
-import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError;
import org.onap.cps.ncmp.api.models.DataOperationRequest;
import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse;
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.api.models.UpgradedCmHandles;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.exceptions.AlreadyDefinedException;
import org.onap.cps.spi.exceptions.CpsException;
@@ -92,7 +99,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler;
private final CpsDataService cpsDataService;
private final IMap<String, Object> moduleSyncStartedOnCmHandles;
- private final IMap<String, TrustLevel> trustLevelPerDmiPlugin;
+ private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
@Override
public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(
@@ -102,18 +109,23 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
if (!dmiPluginRegistration.getRemovedCmHandles().isEmpty()) {
dmiPluginRegistrationResponse.setRemovedCmHandles(
- parseAndRemoveCmHandlesInDmiRegistration(dmiPluginRegistration.getRemovedCmHandles()));
+ parseAndProcessDeletedCmHandlesInRegistration(dmiPluginRegistration.getRemovedCmHandles()));
}
if (!dmiPluginRegistration.getCreatedCmHandles().isEmpty()) {
dmiPluginRegistrationResponse.setCreatedCmHandles(
- parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration));
+ parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration));
}
if (!dmiPluginRegistration.getUpdatedCmHandles().isEmpty()) {
dmiPluginRegistrationResponse.setUpdatedCmHandles(
networkCmProxyDataServicePropertyHandler
.updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles()));
}
+ if (dmiPluginRegistration.getUpgradedCmHandles() != null
+ && !dmiPluginRegistration.getUpgradedCmHandles().getCmHandles().isEmpty()) {
+ dmiPluginRegistrationResponse.setUpgradedCmHandles(
+ parseAndProcessUpgradedCmHandlesInRegistration(dmiPluginRegistration));
+ }
setTrustLevelPerDmiPlugin(dmiPluginRegistration);
@@ -210,8 +222,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
*/
@Override
public void setDataSyncEnabled(final String cmHandleId, final boolean dataSyncEnabled) {
- final CompositeState compositeState = inventoryPersistence
- .getCmHandleState(cmHandleId);
+ final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId);
if (compositeState.getDataSyncEnabled().equals(dataSyncEnabled)) {
log.info("Data-Sync Enabled flag is already: {} ", dataSyncEnabled);
} else if (compositeState.getCmHandleState() != CmHandleState.READY) {
@@ -274,8 +285,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
*/
@Override
public Map<String, String> getCmHandlePublicProperties(final String cmHandleId) {
- final YangModelCmHandle yangModelCmHandle =
- inventoryPersistence.getYangModelCmHandle(cmHandleId);
+ final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
final List<YangModelCmHandle.Property> yangModelPublicProperties = yangModelCmHandle.getPublicProperties();
final Map<String, String> cmHandlePublicProperties = new HashMap<>();
YangDataConverter.asPropertiesMap(yangModelPublicProperties, cmHandlePublicProperties);
@@ -299,7 +309,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
* @param dmiPluginRegistration dmi plugin registration information.
* @return cm-handle registration response for create cm-handle requests.
*/
- public List<CmHandleRegistrationResponse> parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(
+ public List<CmHandleRegistrationResponse> parseAndProcessCreatedCmHandlesInRegistration(
final DmiPluginRegistration dmiPluginRegistration) {
final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle = new HashMap<>();
dmiPluginRegistration.getCreatedCmHandles()
@@ -308,18 +318,19 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
dmiPluginRegistration.getDmiPlugin(),
dmiPluginRegistration.getDmiDataPlugin(),
dmiPluginRegistration.getDmiModelPlugin(),
- cmHandle);
+ cmHandle,
+ cmHandle.getModuleSetTag());
cmHandleStatePerCmHandle.put(yangModelCmHandle, CmHandleState.ADVISED);
});
return registerNewCmHandles(cmHandleStatePerCmHandle);
}
- protected List<CmHandleRegistrationResponse> parseAndRemoveCmHandlesInDmiRegistration(
+ protected List<CmHandleRegistrationResponse> parseAndProcessDeletedCmHandlesInRegistration(
final List<String> tobeRemovedCmHandles) {
final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses =
new ArrayList<>(tobeRemovedCmHandles.size());
final Collection<YangModelCmHandle> yangModelCmHandles =
- inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandles);
+ inventoryPersistence.getYangModelCmHandles(tobeRemovedCmHandles);
updateCmHandleStateBatch(yangModelCmHandles, CmHandleState.DELETING);
@@ -349,6 +360,42 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
return cmHandleRegistrationResponses;
}
+ protected List<CmHandleRegistrationResponse> parseAndProcessUpgradedCmHandlesInRegistration(
+ final DmiPluginRegistration dmiPluginRegistration) {
+
+ final UpgradedCmHandles upgradedCmHandles = dmiPluginRegistration.getUpgradedCmHandles();
+ final String moduleSetTag = dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag();
+ final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle =
+ new HashMap<>(upgradedCmHandles.getCmHandles().size());
+ final Collection<String> notReadyCmHandles = new ArrayList<>(upgradedCmHandles.getCmHandles().size());
+ final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle();
+ final String formattedModuleSetTag = MessageFormat.format("new moduleSetTag: {0}", moduleSetTag);
+
+ upgradedCmHandles.getCmHandles().forEach(cmHandleId -> {
+ if (cmHandleQueries.cmHandleHasState(cmHandleId, CmHandleState.READY)) {
+ ncmpServiceCmHandle.setCmHandleId(cmHandleId);
+ ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder()
+ .withCmHandleState(CmHandleState.READY)
+ .withLockReason(MODULE_UPGRADE, formattedModuleSetTag).build());
+ final YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(
+ dmiPluginRegistration.getDmiPlugin(),
+ dmiPluginRegistration.getDmiDataPlugin(),
+ dmiPluginRegistration.getDmiModelPlugin(),
+ ncmpServiceCmHandle,
+ moduleSetTag);
+ cmHandleStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED);
+ } else {
+ notReadyCmHandles.add(cmHandleId);
+ }
+ });
+
+ final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses
+ = upgradeCmHandles(cmHandleStatePerCmHandle);
+ cmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponses(notReadyCmHandles,
+ CM_HANDLES_NOT_READY));
+ return cmHandleRegistrationResponses;
+ }
+
private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) {
try {
deleteCmHandleFromDbAndModuleSyncMap(cmHandleId);
@@ -356,13 +403,11 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
} catch (final DataNodeNotFoundException dataNodeNotFoundException) {
log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}",
cmHandleId, dataNodeNotFoundException.getMessage());
- return CmHandleRegistrationResponse.createFailureResponse(cmHandleId,
- RegistrationError.CM_HANDLE_DOES_NOT_EXIST);
+ return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND);
} catch (final DataValidationException dataValidationException) {
log.error("Unable to de-register cm-handle id: {}, caused by: {}",
cmHandleId, dataValidationException.getMessage());
- return CmHandleRegistrationResponse.createFailureResponse(cmHandleId,
- RegistrationError.CM_HANDLE_INVALID_ID);
+ return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID);
} catch (final Exception exception) {
log.error("Unable to de-register cm-handle id : {} , caused by : {}", cmHandleId, exception.getMessage());
return CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception);
@@ -404,20 +449,35 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
private List<CmHandleRegistrationResponse> registerNewCmHandles(final Map<YangModelCmHandle, CmHandleState>
cmHandleStatePerCmHandle) {
- final List<String> cmHandleIds = cmHandleStatePerCmHandle.keySet().stream().map(YangModelCmHandle::getId)
- .collect(Collectors.toList());
+ final List<String> cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle);
try {
lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle);
return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds);
} catch (final AlreadyDefinedException alreadyDefinedException) {
return CmHandleRegistrationResponse.createFailureResponses(
alreadyDefinedException.getAlreadyDefinedObjectNames(),
- RegistrationError.CM_HANDLE_ALREADY_EXIST);
+ CM_HANDLE_ALREADY_EXIST);
+ } catch (final Exception exception) {
+ return CmHandleRegistrationResponse.createFailureResponses(cmHandleIds, exception);
+ }
+ }
+
+ private List<CmHandleRegistrationResponse> upgradeCmHandles(final Map<YangModelCmHandle, CmHandleState>
+ cmHandleStatePerCmHandle) {
+ final List<String> cmHandleIds = getCmHandleIds(cmHandleStatePerCmHandle);
+ log.info("Moving cm handles : {} into locked (for upgrade) state.", cmHandleIds);
+ try {
+ lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle);
+ return CmHandleRegistrationResponse.createSuccessResponses(cmHandleIds);
} catch (final Exception exception) {
return CmHandleRegistrationResponse.createFailureResponses(cmHandleIds, exception);
}
}
+ private static List<String> getCmHandleIds(final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle) {
+ return cmHandleStatePerCmHandle.keySet().stream().map(YangModelCmHandle::getId).toList();
+ }
+
private void setTrustLevelPerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) {
if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) {
trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiPlugin(), TrustLevel.COMPLETE);
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
index 2f61b228b..401b19036 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
@@ -22,6 +22,8 @@
package org.onap.cps.ncmp.api.impl;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID;
import static org.onap.cps.ncmp.api.impl.NetworkCmProxyDataServicePropertyHandler.PropertyType.DMI_PROPERTY;
import static org.onap.cps.ncmp.api.impl.NetworkCmProxyDataServicePropertyHandler.PropertyType.PUBLIC_PROPERTY;
@@ -38,7 +40,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse;
-import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError;
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.onap.cps.spi.exceptions.DataValidationException;
@@ -75,13 +76,12 @@ public class NetworkCmProxyDataServicePropertyHandler {
log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}",
cmHandleId, e.getMessage());
cmHandleRegistrationResponses.add(CmHandleRegistrationResponse
- .createFailureResponse(cmHandleId, RegistrationError.CM_HANDLE_DOES_NOT_EXIST));
+ .createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND));
} catch (final DataValidationException e) {
log.error("Unable to update cm handle : {}, caused by : {}",
cmHandleId, e.getMessage());
cmHandleRegistrationResponses.add(
- CmHandleRegistrationResponse.createFailureResponse(cmHandleId,
- RegistrationError.CM_HANDLE_INVALID_ID));
+ CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID));
} catch (final Exception exception) {
log.error("Unable to update cmHandle : {} , caused by : {}",
cmHandleId, exception.getMessage());
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
index 6a8310c20..e8ce050b2 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
@@ -75,10 +75,8 @@ public class DmiRestClient {
final HttpEntity<Object> httpHeaders = new HttpEntity<>(configureHttpHeaders(new HttpHeaders()));
final JsonNode dmiPluginHealthStatus = restTemplate.getForObject(dmiPluginBaseUrl + "/manage/health",
JsonNode.class, httpHeaders);
- if (dmiPluginHealthStatus != null) {
- if (dmiPluginHealthStatus.get("status").asText().equals("UP")) {
- return DmiPluginStatus.UP;
- }
+ if (dmiPluginHealthStatus != null && dmiPluginHealthStatus.get("status").asText().equals("UP")) {
+ return DmiPluginStatus.UP;
}
} catch (final Exception exception) {
log.warn("Could not send request for health check since {}", exception.getMessage());
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java
index ebe99057d..171db5299 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java
@@ -20,10 +20,8 @@
package org.onap.cps.ncmp.api.impl.config.embeddedcache;
-import com.hazelcast.collection.ISet;
import com.hazelcast.config.MapConfig;
-import com.hazelcast.config.SetConfig;
-import com.hazelcast.map.IMap;
+import java.util.Map;
import org.onap.cps.cache.HazelcastCacheConfig;
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
import org.springframework.context.annotation.Bean;
@@ -32,21 +30,21 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class TrustLevelCacheConfig extends HazelcastCacheConfig {
- private static final SetConfig untrustworthyCmHandlesSetConfig =
- createSetConfig("untrustworthyCmHandlesSetConfig");
+ private static final MapConfig trustLevelPerCmHandleCacheConfig =
+ createMapConfig("trustLevelPerCmHandleCacheConfig");
private static final MapConfig trustLevelPerDmiPluginCacheConfig =
createMapConfig("trustLevelPerDmiPluginCacheConfig");
/**
- * Distributed collection of untrustworthy cm handles.
+ * Distributed instance of trust level cache containing the trust level per cm handle.
*
- * @return instance of distributed set of untrustworthy cm handles.
+ * @return configured map of cm handle name as keys to trust-level for values.
*/
@Bean
- public ISet<String> untrustworthyCmHandlesSet() {
- return createHazelcastInstance("untrustworthyCmHandlesSet",
- untrustworthyCmHandlesSetConfig).getSet("untrustworthyCmHandlesSet");
+ public Map<String, TrustLevel> trustLevelPerCmHandle() {
+ return createHazelcastInstance("hazelcastInstanceTrustLevelPerCmHandleMap",
+ trustLevelPerCmHandleCacheConfig).getMap("trustLevelPerCmHandle");
}
/**
@@ -55,7 +53,7 @@ public class TrustLevelCacheConfig extends HazelcastCacheConfig {
* @return configured map of dmi-plugin name as keys to trust-level for values.
*/
@Bean
- public IMap<String, TrustLevel> trustLevelPerDmiPlugin() {
+ public Map<String, TrustLevel> trustLevelPerDmiPlugin() {
return createHazelcastInstance("hazelcastInstanceTrustLevelPerDmiPluginMap",
trustLevelPerDmiPluginCacheConfig).getMap("trustLevelPerDmiPlugin");
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/EventsPublisher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/EventsPublisher.java
index 49e455e58..355e5cdf7 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/EventsPublisher.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/EventsPublisher.java
@@ -64,8 +64,8 @@ public class EventsPublisher<T> {
cloudEventKafkaTemplate.send(topicName, eventKey, event);
eventFuture.whenComplete((result, e) -> {
if (e == null) {
- log.debug("Successfully published event to topic : {} , Event : {}",
- result.getRecordMetadata().topic(), result.getProducerRecord().value());
+ log.debug("Successfully published event to topic : {} , Event : {}", result.getRecordMetadata().topic(),
+ result.getProducerRecord().value());
} else {
log.error("Unable to publish event to topic : {} due to {}", topicName, e.getMessage());
@@ -85,14 +85,7 @@ public class EventsPublisher<T> {
public void publishEvent(final String topicName, final String eventKey, final T event) {
final CompletableFuture<SendResult<String, T>> eventFuture =
legacyKafkaEventTemplate.send(topicName, eventKey, event);
- eventFuture.whenComplete((result, e) -> {
- if (e == null) {
- log.debug("Successfully published event to topic : {} , Event : {}",
- result.getRecordMetadata().topic(), result.getProducerRecord().value());
- } else {
- log.error("Unable to publish event to topic : {} due to {}", topicName, e.getMessage());
- }
- });
+ handleLegacyEventCallback(topicName, eventFuture);
}
/**
@@ -107,16 +100,8 @@ public class EventsPublisher<T> {
final ProducerRecord<String, T> producerRecord =
new ProducerRecord<>(topicName, null, eventKey, event, eventHeaders);
- final CompletableFuture<SendResult<String, T>> eventFuture =
- legacyKafkaEventTemplate.send(producerRecord);
- eventFuture.whenComplete((result, ex) -> {
- if (ex != null) {
- log.error("Unable to publish event to topic : {} due to {}", topicName, ex.getMessage());
- } else {
- log.debug("Successfully published event to topic : {} , Event : {}",
- result.getRecordMetadata().topic(), result.getProducerRecord().value());
- }
- });
+ final CompletableFuture<SendResult<String, T>> eventFuture = legacyKafkaEventTemplate.send(producerRecord);
+ handleLegacyEventCallback(topicName, eventFuture);
}
/**
@@ -133,6 +118,18 @@ public class EventsPublisher<T> {
publishEvent(topicName, eventKey, convertToKafkaHeaders(eventHeaders), event);
}
+ private void handleLegacyEventCallback(final String topicName,
+ final CompletableFuture<SendResult<String, T>> eventFuture) {
+ eventFuture.whenComplete((result, e) -> {
+ if (e != null) {
+ log.error("Unable to publish event to topic : {} due to {}", topicName, e.getMessage());
+ } else {
+ log.debug("Successfully published event to topic : {} , Event : {}", result.getRecordMetadata().topic(),
+ result.getProducerRecord().value());
+ }
+ });
+ }
+
private Headers convertToKafkaHeaders(final Map<String, Object> eventMessageHeaders) {
final Headers eventHeaders = new RecordHeaders();
eventMessageHeaders.forEach((key, value) -> eventHeaders.add(key, SerializationUtils.serialize(value)));
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java
index 473538c93..a0fd81c12 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java
@@ -20,13 +20,20 @@
package org.onap.cps.ncmp.api.impl.events.cmsubscription;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.PARTIALLY_APPLIED_SUBSCRIPTION;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUBSCRIPTION_NOT_APPLICABLE;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUBSCRIPTION_PENDING;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUCCESSFULLY_APPLIED_SUBSCRIPTION;
+import static org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus.ACCEPTED;
+import static org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus.PENDING;
+import static org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus.REJECTED;
+
import io.cloudevents.CloudEvent;
import java.util.List;
import java.util.Map;
-import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.NcmpEventResponseCode;
+import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.impl.events.EventsPublisher;
import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistence;
import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus;
@@ -100,48 +107,39 @@ public class CmSubscriptionNcmpOutEventPublisher {
cmSubscriptionStatus.setStatus(SubscriptionStatus.fromString(status));
cmSubscriptionStatus.setDetails(details);
return cmSubscriptionStatus;
- }).collect(Collectors.toList());
+ }).toList();
}
- private NcmpEventResponseCode decideOnNcmpEventResponseCodeForSubscription(
+ private NcmpResponseStatus decideOnNcmpEventResponseCodeForSubscription(
final Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMap) {
- final boolean isAllTargetsPending = isAllTargetCmHandleStatusMatch(cmHandleIdToStatusAndDetailsAsMap,
- SubscriptionStatus.PENDING);
-
- final boolean isAllTargetsRejected = isAllTargetCmHandleStatusMatch(cmHandleIdToStatusAndDetailsAsMap,
- SubscriptionStatus.REJECTED);
-
- final boolean isAllTargetsAccepted = isAllTargetCmHandleStatusMatch(cmHandleIdToStatusAndDetailsAsMap,
- SubscriptionStatus.ACCEPTED);
-
- if (isAllTargetsAccepted) {
- return NcmpEventResponseCode.SUCCESSFULLY_APPLIED_SUBSCRIPTION;
- } else if (isAllTargetsRejected) {
- return NcmpEventResponseCode.SUBSCRIPTION_NOT_APPLICABLE;
- } else if (isAllTargetsPending) {
- return NcmpEventResponseCode.SUBSCRIPTION_PENDING;
- } else {
- return NcmpEventResponseCode.PARTIALLY_APPLIED_SUBSCRIPTION;
+ if (allTargetsHaveStatus(cmHandleIdToStatusAndDetailsAsMap, ACCEPTED)) {
+ return SUCCESSFULLY_APPLIED_SUBSCRIPTION;
+ }
+ if (allTargetsHaveStatus(cmHandleIdToStatusAndDetailsAsMap, REJECTED)) {
+ return SUBSCRIPTION_NOT_APPLICABLE;
+ }
+ if (allTargetsHaveStatus(cmHandleIdToStatusAndDetailsAsMap, PENDING)) {
+ return SUBSCRIPTION_PENDING;
}
+ return PARTIALLY_APPLIED_SUBSCRIPTION;
}
- private boolean isAllTargetCmHandleStatusMatch(
- final Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMap,
- final SubscriptionStatus subscriptionStatus) {
+ private boolean allTargetsHaveStatus(final Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMap,
+ final SubscriptionStatus subscriptionStatus) {
return cmHandleIdToStatusAndDetailsAsMap.values().stream()
.allMatch(entryset -> entryset.containsValue(subscriptionStatus.toString()));
}
private CmSubscriptionNcmpOutEvent fromCmSubscriptionEvent(
final CmSubscriptionEvent cmSubscriptionEvent,
- final NcmpEventResponseCode ncmpEventResponseCode) {
+ final NcmpResponseStatus ncmpResponseStatus) {
final CmSubscriptionNcmpOutEvent cmSubscriptionNcmpOutEvent =
cmSubscriptionEventToCmSubscriptionNcmpOutEventMapper.toCmSubscriptionNcmpOutEvent(
cmSubscriptionEvent);
- cmSubscriptionNcmpOutEvent.getData().setStatusCode(Integer.parseInt(ncmpEventResponseCode.getStatusCode()));
- cmSubscriptionNcmpOutEvent.getData().setStatusMessage(ncmpEventResponseCode.getStatusMessage());
+ cmSubscriptionNcmpOutEvent.getData().setStatusCode(Integer.parseInt(ncmpResponseStatus.getCode()));
+ cmSubscriptionNcmpOutEvent.getData().setStatusMessage(ncmpResponseStatus.getMessage());
return cmSubscriptionNcmpOutEvent;
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapper.java
index 98ba95386..4120970e5 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapper.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapper.java
@@ -25,7 +25,6 @@ import io.cloudevents.CloudEvent;
import io.cloudevents.core.CloudEventUtils;
import io.cloudevents.core.data.PojoCloudEventData;
import io.cloudevents.jackson.PojoCloudEventDataMapper;
-import io.cloudevents.rw.CloudEventRWException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -51,9 +50,9 @@ public class CloudEventMapper {
mappedCloudEvent =
CloudEventUtils.mapData(cloudEvent, PojoCloudEventDataMapper.from(objectMapper, targetEventClass));
- } catch (final CloudEventRWException cloudEventRwException) {
+ } catch (final RuntimeException runtimeException) {
log.error("Unable to map cloud event to target event class type : {} with cause : {}", targetEventClass,
- cloudEventRwException.getMessage());
+ runtimeException.getMessage());
}
return mappedCloudEvent == null ? null : mappedCloudEvent.getValue();
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java
index 4776788c8..81467dbb3 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java
@@ -45,6 +45,14 @@ public interface CmHandleQueries {
Collection<String> queryCmHandlePublicProperties(Map<String, String> publicPropertyQueryPairs);
/**
+ * Query CmHandles based on Trust Level.
+ *
+ * @param trustLevelPropertyQueryPairs trust level properties for query
+ * @return CmHandles which have desired trust level
+ */
+ Collection<String> queryCmHandlesByTrustLevel(Map<String, String> trustLevelPropertyQueryPairs);
+
+ /**
* Method which returns cm handles by the cm handles state.
*
* @param cmHandleState cm handle state
@@ -53,12 +61,21 @@ public interface CmHandleQueries {
List<DataNode> queryCmHandlesByState(CmHandleState cmHandleState);
/**
+ * Method to return data nodes with ancestor representing the cm handles.
+ *
+ * @param cpsPath cps path for which the cmHandle is requested
+ * @return a list of data nodes representing the cm handles.
+ */
+ List<DataNode> queryCmHandleAncestorsByCpsPath(String cpsPath,
+ FetchDescendantsOption fetchDescendantsOption);
+
+ /**
* Method to return data nodes representing the cm handles.
*
* @param cpsPath cps path for which the cmHandle is requested
* @return a list of data nodes representing the cm handles.
*/
- List<DataNode> queryCmHandleDataNodesByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption);
+ List<DataNode> queryNcmpRegistryByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption);
/**
* Method to check the state of a cm handle with given id.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java
index b3ade4f1c..e5cf8edd6 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java
@@ -35,6 +35,8 @@ import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType;
+import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
+import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelFilter;
import org.onap.cps.spi.CpsDataPersistenceService;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.model.DataNode;
@@ -45,9 +47,9 @@ import org.springframework.stereotype.Component;
public class CmHandleQueriesImpl implements CmHandleQueries {
private static final String DESCENDANT_PATH = "//";
-
- private final CpsDataPersistenceService cpsDataPersistenceService;
private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles";
+ private final CpsDataPersistenceService cpsDataPersistenceService;
+ private final Map<String, TrustLevel> trustLevelPerCmHandle;
@Override
public Collection<String> queryCmHandleAdditionalProperties(final Map<String, String> privatePropertyQueryPairs) {
@@ -60,16 +62,31 @@ public class CmHandleQueriesImpl implements CmHandleQueries {
}
@Override
+ public Collection<String> queryCmHandlesByTrustLevel(final Map<String, String> trustLevelPropertyQueryPairs) {
+ final String trustLevelProperty = trustLevelPropertyQueryPairs.values().iterator().next();
+ final TrustLevel targetTrustLevel = TrustLevel.valueOf(trustLevelProperty);
+
+ final TrustLevelFilter trustLevelFilter = new TrustLevelFilter(targetTrustLevel, trustLevelPerCmHandle);
+ return trustLevelFilter.getAllCmHandleIdsByTargetTrustLevel();
+ }
+
+ @Override
public List<DataNode> queryCmHandlesByState(final CmHandleState cmHandleState) {
- return queryCmHandleDataNodesByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]",
+ return queryCmHandleAncestorsByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]",
INCLUDE_ALL_DESCENDANTS);
}
@Override
- public List<DataNode> queryCmHandleDataNodesByCpsPath(final String cpsPath,
- final FetchDescendantsOption fetchDescendantsOption) {
+ public List<DataNode> queryNcmpRegistryByCpsPath(final String cpsPath,
+ final FetchDescendantsOption fetchDescendantsOption) {
return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption);
+ cpsPath, fetchDescendantsOption);
+ }
+
+ @Override
+ public List<DataNode> queryCmHandleAncestorsByCpsPath(final String cpsPath,
+ final FetchDescendantsOption fetchDescendantsOption) {
+ return queryNcmpRegistryByCpsPath(cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption);
}
@Override
@@ -81,7 +98,7 @@ public class CmHandleQueriesImpl implements CmHandleQueries {
@Override
public List<DataNode> queryCmHandlesByOperationalSyncState(final DataStoreSyncState dataStoreSyncState) {
- return queryCmHandleDataNodesByCpsPath("//state/datastores" + "/operational[@sync-state=\""
+ return queryCmHandleAncestorsByCpsPath("//state/datastores" + "/operational[@sync-state=\""
+ dataStoreSyncState + "\"]", FetchDescendantsOption.OMIT_DESCENDANTS);
}
@@ -114,7 +131,8 @@ public class CmHandleQueriesImpl implements CmHandleQueries {
+ publicPropertyQueryPair.getKey()
+ "\" and @value=\"" + publicPropertyQueryPair.getValue() + "\"]";
- final Collection<DataNode> dataNodes = queryCmHandleDataNodesByCpsPath(cpsPath, OMIT_DESCENDANTS);
+ final Collection<DataNode> dataNodes = queryCmHandleAncestorsByCpsPath(cpsPath,
+ OMIT_DESCENDANTS);
if (cmHandleIds == null) {
cmHandleIds = collectCmHandleIdsFromDataNodes(dataNodes);
} else {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java
index ef4b299e1..99cca8c0b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java
@@ -100,7 +100,9 @@ public class CompositeStateUtils {
compositeState.setLastUpdateTimeNow();
final String oldLockReasonDetails = compositeState.getLockReason().getDetails();
final CompositeState.LockReason lockReason =
- CompositeState.LockReason.builder().details(oldLockReasonDetails).build();
+ CompositeState.LockReason.builder()
+ .lockReasonCategory(compositeState.getLockReason().getLockReasonCategory())
+ .details(oldLockReasonDetails).build();
compositeState.setLockReason(lockReason);
};
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java
index 8306619f2..e2b2c6b4a 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java
@@ -21,5 +21,8 @@
package org.onap.cps.ncmp.api.impl.inventory;
public enum LockReasonCategory {
- MODULE_SYNC_FAILED, MODULE_UPGRADE, MODULE_UPGRADE_FAILED
+ MODULE_SYNC_FAILED,
+ MODULE_UPGRADE,
+ MODULE_UPGRADE_FAILED,
+ LOCKED_MISBEHAVING
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java
index b2949c278..8e17ab916 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java
@@ -20,20 +20,38 @@
package org.onap.cps.ncmp.api.impl.inventory.sync;
+import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME;
+import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR;
+import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
+import java.time.OffsetDateTime;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsDataService;
import org.onap.cps.api.CpsModuleService;
+import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
+import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
+import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
+import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory;
import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations;
+import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
import org.onap.cps.spi.CascadeDeleteAllowed;
+import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.exceptions.SchemaSetNotFoundException;
+import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.model.ModuleReference;
+import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.stereotype.Service;
@Slf4j
@@ -43,16 +61,31 @@ public class ModuleSyncService {
private final DmiModelOperations dmiModelOperations;
private final CpsModuleService cpsModuleService;
-
private final CpsAdminService cpsAdminService;
+ private final CmHandleQueries cmHandleQueries;
+ private final CpsDataService cpsDataService;
+ private final JsonObjectMapper jsonObjectMapper;
/**
* This method registers a cm handle and initiates modules sync.
*
- * @param yangModelCmHandle the yang model of cm handle.
+ * @param upgradedCmHandle the yang model of cm handle.
*/
- public void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) {
+ public void syncAndCreateOrUpgradeSchemaSetAndAnchor(final YangModelCmHandle upgradedCmHandle) {
+
+ final String moduleSetTag = extractModuleSetTag(upgradedCmHandle.getCompositeState());
+ final Optional<DataNode> existingCmHandleWithSameModuleSetTag
+ = getFirstReadyDataNodeWithModuleSetTag(moduleSetTag);
+ if (existingCmHandleWithSameModuleSetTag.isPresent()) {
+ upgradeUsingModuleSetTag(upgradedCmHandle, moduleSetTag);
+ } else {
+ syncAndCreateSchemaSetAndAnchor(upgradedCmHandle);
+ }
+ setCmHandleModuleSetTag(upgradedCmHandle, moduleSetTag);
+ }
+
+ private void syncAndCreateSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) {
final Collection<ModuleReference> allModuleReferencesFromCmHandle =
dmiModelOperations.getModuleReferences(yangModelCmHandle);
@@ -73,8 +106,8 @@ public class ModuleSyncService {
final Map<String, String> newModuleNameToContentMap,
final Collection<ModuleReference> allModuleReferencesFromCmHandle) {
final String schemaSetAndAnchorName = yangModelCmHandle.getId();
- cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName,
- newModuleNameToContentMap, allModuleReferencesFromCmHandle);
+ cpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
+ schemaSetAndAnchorName, newModuleNameToContentMap, allModuleReferencesFromCmHandle);
cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetAndAnchorName,
schemaSetAndAnchorName);
}
@@ -94,4 +127,41 @@ public class ModuleSyncService {
}
}
+ private Optional<DataNode> getFirstReadyDataNodeWithModuleSetTag(final String moduleSetTag) {
+ final List<DataNode> dataNodes = StringUtils.isNotBlank(moduleSetTag) ? cmHandleQueries
+ .queryNcmpRegistryByCpsPath("//cm-handles[@module-set-tag='" + moduleSetTag + "']",
+ FetchDescendantsOption.OMIT_DESCENDANTS) : Collections.emptyList();
+ return dataNodes.stream().filter(dataNode -> {
+ final String cmHandleId = YangDataConverter.extractCmHandleIdFromXpath(dataNode.getXpath());
+ return cmHandleQueries.cmHandleHasState(cmHandleId, CmHandleState.READY);
+ }).findFirst();
+ }
+
+ private void setCmHandleModuleSetTag(final YangModelCmHandle upgradedCmHandle, final String moduleSetTag) {
+ final Map<String, Map<String, String>> dmiRegistryProperties = new HashMap<>(1);
+ final Map<String, String> cmHandleProperties = new HashMap<>(2);
+ cmHandleProperties.put("id", upgradedCmHandle.getId());
+ cmHandleProperties.put("module-set-tag", moduleSetTag);
+ dmiRegistryProperties.put("cm-handles", cmHandleProperties);
+ cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT,
+ jsonObjectMapper.asJsonString(dmiRegistryProperties), OffsetDateTime.now());
+ }
+
+ private void upgradeUsingModuleSetTag(final YangModelCmHandle upgradedCmHandle, final String moduleSetTag) {
+ log.info("Found cm handle having module set tag: {}", moduleSetTag);
+ final Collection<ModuleReference> moduleReferencesFromExistingCmHandle =
+ cpsModuleService.getYangResourcesModuleReferences(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR);
+ final String upgradedSchemaSetAndAnchorName = upgradedCmHandle.getId();
+ final Map<String, String> noNewModules = Collections.emptyMap();
+ cpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
+ upgradedSchemaSetAndAnchorName, noNewModules, moduleReferencesFromExistingCmHandle);
+ }
+
+ private static String extractModuleSetTag(final CompositeState compositeState) {
+ return compositeState.getLockReason() != null && compositeState.getLockReason().getLockReasonCategory()
+ == LockReasonCategory.MODULE_UPGRADE
+ ? Arrays.stream(compositeState.getLockReason().getDetails().split(":")).toList().get(1).trim()
+ : StringUtils.EMPTY;
+ }
+
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java
index 7306f7174..c19dbeb90 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java
@@ -60,7 +60,8 @@ public class ModuleSyncTasks {
public CompletableFuture<Void> performModuleSync(final Collection<DataNode> cmHandlesAsDataNodes,
final AtomicInteger batchCounter) {
try {
- final Map<YangModelCmHandle, CmHandleState> cmHandelStatePerCmHandle = new HashMap<>();
+ final Map<YangModelCmHandle, CmHandleState> cmHandelStatePerCmHandle
+ = new HashMap<>(cmHandlesAsDataNodes.size());
for (final DataNode cmHandleAsDataNode : cmHandlesAsDataNodes) {
final String cmHandleId = String.valueOf(cmHandleAsDataNode.getLeaves().get("id"));
final YangModelCmHandle yangModelCmHandle =
@@ -68,16 +69,18 @@ public class ModuleSyncTasks {
final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId);
try {
moduleSyncService.deleteSchemaSetIfExists(cmHandleId);
- moduleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle);
+ moduleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle);
+ yangModelCmHandle.getCompositeState().setLockReason(null);
cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.READY);
} catch (final Exception e) {
- log.warn("Processing of {} module sync failed due to reason {}.", cmHandleId, e.getMessage());
+ log.warn("Processing of {} module sync failed due to reason {}.",
+ cmHandleId, e.getMessage());
syncUtils.updateLockReasonDetailsAndAttempts(compositeState,
LockReasonCategory.MODULE_SYNC_FAILED, e.getMessage());
setCmHandleStateLocked(yangModelCmHandle, compositeState.getLockReason());
cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED);
}
- log.info("{} is now in {} state", cmHandleId, compositeState.getCmHandleState().name());
+ log.info("{} is now in {} state", cmHandleId, cmHandelStatePerCmHandle.get(yangModelCmHandle).name());
}
lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandelStatePerCmHandle);
} finally {
@@ -96,7 +99,7 @@ public class ModuleSyncTasks {
final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle = new HashMap<>(failedCmHandles.size());
for (final YangModelCmHandle failedCmHandle : failedCmHandles) {
final CompositeState compositeState = failedCmHandle.getCompositeState();
- final boolean isReadyForRetry = syncUtils.needsModuleSyncRetry(compositeState);
+ final boolean isReadyForRetry = syncUtils.needsModuleSyncRetryOrUpgrade(compositeState);
log.info("Retry for cmHandleId : {} is {}", failedCmHandle.getId(), isReadyForRetry);
if (isReadyForRetry) {
final String resetCmHandleId = failedCmHandle.getId();
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java
index 6ba52ee16..75781eb1b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java
@@ -90,7 +90,7 @@ public class ModuleSyncWatchdog {
@Scheduled(fixedDelayString = "${ncmp.timers.locked-modules-sync.sleep-time-ms:300000}")
public void resetPreviouslyFailedCmHandles() {
log.info("Processing module sync retry-watchdog waking up.");
- final List<YangModelCmHandle> failedCmHandles = syncUtils.getModuleSyncFailedCmHandles();
+ final List<YangModelCmHandle> failedCmHandles = syncUtils.getCmHandlesThatFailedModelSyncOrUpgrade();
log.info("Retrying {} cmHandles", failedCmHandles.size());
moduleSyncTasks.resetFailedCmHandles(failedCmHandles);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java
index c50bd4278..ab85c2127 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/SyncUtils.java
@@ -35,7 +35,6 @@ import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
@@ -100,13 +99,14 @@ public class SyncUtils {
}
/**
- * Query data nodes for cm handles with an "LOCKED" cm handle state with reason MODULE_SYNC_FAILED".
+ * Query data nodes for cm handles with an "LOCKED" cm handle state with reason.
*
* @return a random LOCKED yang model cm handle, return null if not found
*/
- public List<YangModelCmHandle> getModuleSyncFailedCmHandles() {
- final List<DataNode> lockedCmHandlesAsDataNodeList = cmHandleQueries.queryCmHandleDataNodesByCpsPath(
- "//lock-reason[@reason=\"MODULE_SYNC_FAILED\"]",
+ public List<YangModelCmHandle> getCmHandlesThatFailedModelSyncOrUpgrade() {
+ final List<DataNode> lockedCmHandlesAsDataNodeList
+ = cmHandleQueries.queryCmHandleAncestorsByCpsPath(
+ "//lock-reason[@reason=\"MODULE_SYNC_FAILED\" or @reason=\"MODULE_UPGRADE\"]",
FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
return convertCmHandlesDataNodesToYangModelCmHandles(lockedCmHandlesAsDataNodeList);
}
@@ -139,32 +139,39 @@ public class SyncUtils {
* @param compositeState the composite state currently in the locked state
* @return if the retry mechanism should be attempted
*/
- public boolean needsModuleSyncRetry(final CompositeState compositeState) {
- final OffsetDateTime time =
- OffsetDateTime.parse(compositeState.getLastUpdateTime(),
- DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
- final Matcher matcher = retryAttemptPattern.matcher(compositeState.getLockReason().getDetails());
+ public boolean needsModuleSyncRetryOrUpgrade(final CompositeState compositeState) {
+ final OffsetDateTime time = OffsetDateTime.parse(compositeState.getLastUpdateTime(),
+ DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
+ final CompositeState.LockReason lockReason = compositeState.getLockReason();
+
final boolean failedDuringModuleSync = LockReasonCategory.MODULE_SYNC_FAILED
- == compositeState.getLockReason().getLockReasonCategory();
- if (!failedDuringModuleSync) {
- log.info("Locked for other reason");
- return false;
- }
- final int timeInMinutesUntilNextAttempt;
- if (matcher.find()) {
- timeInMinutesUntilNextAttempt = (int) Math.pow(2, Integer.parseInt(matcher.group(1)));
- } else {
- timeInMinutesUntilNextAttempt = 1;
- log.info("First Attempt: no current attempts found.");
- }
- final int timeSinceLastAttempt = (int) Duration.between(time, OffsetDateTime.now()).toMinutes();
- if (timeInMinutesUntilNextAttempt >= timeSinceLastAttempt) {
- log.info("Time until next attempt is {} minutes: ",
- timeInMinutesUntilNextAttempt - timeSinceLastAttempt);
- return false;
+ == lockReason.getLockReasonCategory();
+ final boolean moduleUpgrade = LockReasonCategory.MODULE_UPGRADE
+ == lockReason.getLockReasonCategory();
+
+ if (failedDuringModuleSync) {
+ final int timeInMinutesUntilNextAttempt;
+ final Matcher matcher = retryAttemptPattern.matcher(lockReason.getDetails());
+ if (matcher.find()) {
+ timeInMinutesUntilNextAttempt = (int) Math.pow(2, Integer.parseInt(matcher.group(1)));
+ } else {
+ timeInMinutesUntilNextAttempt = 1;
+ log.info("First Attempt: no current attempts found.");
+ }
+ final int timeSinceLastAttempt = (int) Duration.between(time, OffsetDateTime.now()).toMinutes();
+ if (timeInMinutesUntilNextAttempt >= timeSinceLastAttempt) {
+ log.info("Time until next attempt is {} minutes: ",
+ timeInMinutesUntilNextAttempt - timeSinceLastAttempt);
+ return false;
+ }
+ log.info("Retry due now");
+ return true;
+ } else if (moduleUpgrade) {
+ log.info("Locked for module upgrade.");
+ return true;
}
- log.info("Retry due now");
- return true;
+ log.info("Locked for other reason");
+ return false;
}
/**
@@ -196,6 +203,6 @@ public class SyncUtils {
final List<DataNode> cmHandlesAsDataNodeList) {
return cmHandlesAsDataNodeList.stream()
.map(cmHandle -> YangDataConverter.convertCmHandleToYangModel(cmHandle,
- cmHandle.getLeaves().get("id").toString())).collect(Collectors.toList());
+ cmHandle.getLeaves().get("id").toString())).toList();
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
index 8f76a45e0..b8edeccf2 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
@@ -21,6 +21,8 @@
package org.onap.cps.ncmp.api.impl.operations;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA;
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING;
import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ;
@@ -30,7 +32,7 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.NcmpEventResponseCode;
+import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException;
@@ -230,9 +232,7 @@ public class DmiDataOperations extends DmiOperations {
final Map<String, List<DmiDataOperation>>
groupsOutPerDmiServiceName) {
- groupsOutPerDmiServiceName.entrySet().forEach(groupsOutPerDmiServiceNameEntry -> {
- final String dmiServiceName = groupsOutPerDmiServiceNameEntry.getKey();
- final List<DmiDataOperation> dmiDataOperationRequestBodies = groupsOutPerDmiServiceNameEntry.getValue();
+ groupsOutPerDmiServiceName.forEach((dmiServiceName, dmiDataOperationRequestBodies) -> {
final String dmiDataOperationResourceUrl =
getDmiServiceDataOperationRequestUrl(dmiServiceName, topicParamInQuery, requestId);
sendDataOperationRequestToDmiService(dmiDataOperationResourceUrl, dmiDataOperationRequestBodies);
@@ -261,18 +261,18 @@ public class DmiDataOperations extends DmiOperations {
final String topicName = dataOperationResourceUrlParameters.get("topic").get(0);
final String requestId = dataOperationResourceUrlParameters.get("requestId").get(0);
- final MultiValueMap<DmiDataOperation, Map<NcmpEventResponseCode, List<String>>>
+ final MultiValueMap<DmiDataOperation, Map<NcmpResponseStatus, List<String>>>
cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>();
dmiDataOperationRequestBodies.forEach(dmiDataOperationRequestBody -> {
final List<String> cmHandleIds = dmiDataOperationRequestBody.getCmHandles().stream()
- .map(CmHandle::getId).collect(Collectors.toList());
+ .map(CmHandle::getId).toList();
if (throwable.getCause() instanceof HttpClientRequestException) {
cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
- Map.of(NcmpEventResponseCode.UNABLE_TO_READ_RESOURCE_DATA, cmHandleIds));
+ Map.of(UNABLE_TO_READ_RESOURCE_DATA, cmHandleIds));
} else {
cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
- Map.of(NcmpEventResponseCode.DMI_SERVICE_NOT_RESPONDING, cmHandleIds));
+ Map.of(DMI_SERVICE_NOT_RESPONDING, cmHandleIds));
}
});
ResourceDataOperationRequestUtils.publishErrorMessageToClientTopic(topicName, requestId,
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java
index 458c1b851..b6d74d980 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java
@@ -20,14 +20,14 @@
package org.onap.cps.ncmp.api.impl.trustlevel;
-import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent;
-
-import com.hazelcast.collection.ISet;
import io.cloudevents.CloudEvent;
import io.cloudevents.kafka.impl.KafkaHeaders;
+import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper;
+import org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@@ -36,7 +36,8 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor
public class DeviceHeartbeatConsumer {
- private final ISet<String> untrustworthyCmHandlesSet;
+ private static final String CLOUD_EVENT_ID_HEADER_NAME = "ce_id";
+ private final Map<String, TrustLevel> trustLevelPerCmHandle;
/**
* Listening the device heartbeats.
@@ -47,23 +48,16 @@ public class DeviceHeartbeatConsumer {
containerFactory = "cloudEventConcurrentKafkaListenerContainerFactory")
public void heartbeatListener(final ConsumerRecord<String, CloudEvent> deviceHeartbeatConsumerRecord) {
- final String cmHandleId = KafkaHeaders.getParsedKafkaHeader(deviceHeartbeatConsumerRecord.headers(), "ce_id");
+ final String cmHandleId = KafkaHeaders.getParsedKafkaHeader(deviceHeartbeatConsumerRecord.headers(),
+ CLOUD_EVENT_ID_HEADER_NAME);
final DeviceTrustLevel deviceTrustLevel =
- toTargetEvent(deviceHeartbeatConsumerRecord.value(), DeviceTrustLevel.class);
-
- if (deviceTrustLevel == null || deviceTrustLevel.getTrustLevel() == null) {
- log.warn("No or Invalid trust level defined");
- return;
- }
+ CloudEventMapper.toTargetEvent(deviceHeartbeatConsumerRecord.value(), DeviceTrustLevel.class);
- if (deviceTrustLevel.getTrustLevel().equals(TrustLevel.NONE)) {
- untrustworthyCmHandlesSet.add(cmHandleId);
- log.debug("Added cmHandleId to untrustworthy set : {}", cmHandleId);
- } else if (deviceTrustLevel.getTrustLevel().equals(TrustLevel.COMPLETE) && untrustworthyCmHandlesSet.contains(
- cmHandleId)) {
- untrustworthyCmHandlesSet.remove(cmHandleId);
- log.debug("Removed cmHandleId from untrustworthy set : {}", cmHandleId);
+ if (cmHandleId != null && deviceTrustLevel != null) {
+ final String trustLevel = deviceTrustLevel.getData().getTrustLevel();
+ trustLevelPerCmHandle.put(cmHandleId, TrustLevel.valueOf(trustLevel));
+ log.debug("Added cmHandleId to trustLevelPerCmHandle map as {}:{}", cmHandleId, trustLevel);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java
index f4254bb47..8d1f8e90f 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java
@@ -20,6 +20,16 @@
package org.onap.cps.ncmp.api.impl.trustlevel;
+import lombok.Getter;
+
+@Getter
public enum TrustLevel {
- NONE, COMPLETE;
+ NONE(0), COMPLETE(99);
+
+ private final int value;
+
+ TrustLevel(final int value) {
+ this.value = value;
+ }
+
} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilter.java
new file mode 100644
index 000000000..3b704ae4f
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilter.java
@@ -0,0 +1,58 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 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.
+ * 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.cps.ncmp.api.impl.trustlevel;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+public class TrustLevelFilter implements Comparable<TrustLevel> {
+
+ @EqualsAndHashCode.Include
+ private final TrustLevel targetTrustLevel;
+ private final Map<String, TrustLevel> trustLevelPerCmHandle;
+
+ @Override
+ public int compareTo(@NonNull final TrustLevel other) {
+ return Integer.compare(this.targetTrustLevel.getValue(), other.getValue());
+ }
+
+ /**
+ * This method return cm handles that matches with given trust level.
+ *
+ * @return cm handle ids.
+ */
+ public Collection<String> getAllCmHandleIdsByTargetTrustLevel() {
+ final Collection<String> resultCmHandleIds = new HashSet<>();
+ trustLevelPerCmHandle.entrySet().forEach(cmHandleTrustLevelEntrySet -> {
+ if (compareTo(cmHandleTrustLevelEntrySet.getValue()) == 0) {
+ resultCmHandleIds.add(cmHandleTrustLevelEntrySet.getKey());
+ }
+ });
+ return resultCmHandleIds;
+ }
+
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java
index dac32aa73..39f880257 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java
@@ -20,7 +20,7 @@
package org.onap.cps.ncmp.api.impl.trustlevel.dmiavailability;
-import com.hazelcast.map.IMap;
+import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Service;
@Service
public class DMiPluginWatchDog {
- private final IMap<String, TrustLevel> trustLevelPerDmiPlugin;
+ private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
private final DmiRestClient dmiRestClient;
@@ -46,7 +46,7 @@ public class DMiPluginWatchDog {
*/
@Scheduled(fixedDelayString = "${ncmp.timers.trust-evel.dmi-availability-watchdog-ms:30000}")
public void watchDmiPluginAliveness() {
- trustLevelPerDmiPlugin.keySet().forEach((dmiPluginName) -> {
+ trustLevelPerDmiPlugin.keySet().forEach(dmiPluginName -> {
final DmiPluginStatus dmiPluginStatus = dmiRestClient.getDmiPluginStatus(dmiPluginName);
log.debug("Trust level for dmi-plugin: {} is {}", dmiPluginName, dmiPluginStatus.toString());
if (DmiPluginStatus.UP.equals(dmiPluginStatus)) {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java
index b1bb7f767..a59776036 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * Copyright (C) 2022-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.
@@ -29,7 +29,8 @@ import lombok.Getter;
public enum CmHandleQueryConditions {
HAS_ALL_PROPERTIES("hasAllProperties"),
HAS_ALL_MODULES("hasAllModules"),
- WITH_CPS_PATH("cmHandleWithCpsPath");
+ WITH_CPS_PATH("cmHandleWithCpsPath"),
+ WITH_TRUST_LEVEL("cmHandleWithTrustLevel");
public static final Collection<String> ALL_CONDITION_NAMES = Arrays.stream(CmHandleQueryConditions.values())
.map(CmHandleQueryConditions::getConditionName).collect(Collectors.toList());
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java
index 1b190759e..b6a04d367 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java
@@ -86,7 +86,8 @@ public class YangDataConverter {
(String) cmHandleDataNode.getLeaves().get("dmi-service-name"),
(String) cmHandleDataNode.getLeaves().get("dmi-data-service-name"),
(String) cmHandleDataNode.getLeaves().get("dmi-model-service-name"),
- ncmpServiceCmHandle
+ ncmpServiceCmHandle,
+ (String) cmHandleDataNode.getLeaves().get("module-set-tag")
);
}
@@ -105,7 +106,12 @@ public class YangDataConverter {
return yangModelCmHandles;
}
- private static String extractCmHandleIdFromXpath(final String xpath) {
+ /**
+ * This method extract cm handle id from xpath of data node.
+ * @param xpath for data node of the cm handle
+ * @return cm handle Id
+ */
+ public static String extractCmHandleIdFromXpath(final String xpath) {
final Matcher matcher = cmHandleIdInXpathPattern.matcher(xpath);
matcher.find();
return matcher.group(1);
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java
index 65cda9478..61da706c5 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/DataOperationEventCreator.java
@@ -28,7 +28,7 @@ import java.util.Map;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.NcmpEventResponseCode;
+import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.impl.events.NcmpCloudEventBuilder;
import org.onap.cps.ncmp.api.impl.operations.DmiDataOperation;
import org.onap.cps.ncmp.events.async1_0_0.Data;
@@ -51,7 +51,7 @@ public class DataOperationEventCreator {
public static CloudEvent createDataOperationEvent(final String clientTopic,
final String requestId,
final MultiValueMap<DmiDataOperation,
- Map<NcmpEventResponseCode, List<String>>>
+ Map<NcmpResponseStatus, List<String>>>
cmHandleIdsPerResponseCodesPerOperation) {
final DataOperationEvent dataOperationEvent = new DataOperationEvent();
final Data data = createPayloadFromDataOperationResponses(cmHandleIdsPerResponseCodesPerOperation);
@@ -62,7 +62,7 @@ public class DataOperationEventCreator {
}
private static Data createPayloadFromDataOperationResponses(final MultiValueMap<DmiDataOperation,
- Map<NcmpEventResponseCode, List<String>>> cmHandleIdsPerResponseCodesPerOperation) {
+ Map<NcmpResponseStatus, List<String>>> cmHandleIdsPerResponseCodesPerOperation) {
final Data data = new Data();
final List<org.onap.cps.ncmp.events.async1_0_0.Response> responses = new ArrayList<>();
cmHandleIdsPerResponseCodesPerOperation.forEach((dmiDataOperation, cmHandleIdsPerResponseCodes) ->
@@ -75,13 +75,13 @@ public class DataOperationEventCreator {
private static List<Response> createResponseFromDataOperationResponses(
final DmiDataOperation dmiDataOperation,
- final Map<NcmpEventResponseCode, List<String>> cmHandleIdsPerResponseCodeEntries) {
+ final Map<NcmpResponseStatus, List<String>> cmHandleIdsPerResponseCodeEntries) {
final List<org.onap.cps.ncmp.events.async1_0_0.Response> responses = new ArrayList<>();
cmHandleIdsPerResponseCodeEntries.forEach((ncmpEventResponseCode, cmHandleIds) -> {
final Response response = new Response();
response.setOperationId(dmiDataOperation.getOperationId());
- response.setStatusCode(ncmpEventResponseCode.getStatusCode());
- response.setStatusMessage(ncmpEventResponseCode.getStatusMessage());
+ response.setStatusCode(ncmpEventResponseCode.getCode());
+ response.setStatusMessage(ncmpEventResponseCode.getMessage());
response.setIds(cmHandleIds);
response.setResourceIdentifier(dmiDataOperation.getResourceIdentifier());
response.setOptions(dmiDataOperation.getOptions());
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java
index e95d4f4c7..e78f0901f 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java
@@ -20,6 +20,9 @@
package org.onap.cps.ncmp.api.impl.utils.data.operation;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_READY;
+
import io.cloudevents.CloudEvent;
import java.util.ArrayList;
import java.util.Collection;
@@ -32,7 +35,7 @@ import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.NcmpEventResponseCode;
+import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.impl.events.EventsPublisher;
import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
import org.onap.cps.ncmp.api.impl.operations.CmHandle;
@@ -68,7 +71,7 @@ public class ResourceDataOperationRequestUtils {
final Collection<YangModelCmHandle> yangModelCmHandles) {
final Map<String, List<DmiDataOperation>> dmiDataOperationsOutPerDmiServiceName = new HashMap<>();
- final MultiValueMap<DmiDataOperation, Map<NcmpEventResponseCode,
+ final MultiValueMap<DmiDataOperation, Map<NcmpResponseStatus,
List<String>>> cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>();
final Set<String> nonReadyCmHandleIdsLookup = filterAndGetNonReadyCmHandleIds(yangModelCmHandles);
@@ -102,10 +105,10 @@ public class ResourceDataOperationRequestUtils {
}
populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation,
DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn),
- NcmpEventResponseCode.CM_HANDLES_NOT_FOUND, nonExistingCmHandleIds);
+ CM_HANDLES_NOT_FOUND, nonExistingCmHandleIds);
populateCmHandleIdsPerOperationIdPerResponseCode(cmHandleIdsPerResponseCodesPerOperation,
DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn),
- NcmpEventResponseCode.CM_HANDLES_NOT_READY, nonReadyCmHandleIds);
+ CM_HANDLES_NOT_READY, nonReadyCmHandleIds);
}
if (!cmHandleIdsPerResponseCodesPerOperation.isEmpty()) {
publishErrorMessageToClientTopic(topicParamInQuery, requestId, cmHandleIdsPerResponseCodesPerOperation);
@@ -124,7 +127,7 @@ public class ResourceDataOperationRequestUtils {
public static void publishErrorMessageToClientTopic(final String clientTopic,
final String requestId,
final MultiValueMap<DmiDataOperation,
- Map<NcmpEventResponseCode, List<String>>>
+ Map<NcmpResponseStatus, List<String>>>
cmHandleIdsPerResponseCodesPerOperation) {
final CloudEvent dataOperationCloudEvent = DataOperationEventCreator.createDataOperationEvent(clientTopic,
requestId, cmHandleIdsPerResponseCodesPerOperation);
@@ -175,13 +178,13 @@ public class ResourceDataOperationRequestUtils {
}
private static void populateCmHandleIdsPerOperationIdPerResponseCode(final MultiValueMap<DmiDataOperation,
- Map<NcmpEventResponseCode, List<String>>> cmHandleIdsPerResponseCodesPerOperation,
+ Map<NcmpResponseStatus, List<String>>> cmHandleIdsPerResponseCodesPerOperation,
final DmiDataOperation dmiDataOperation,
- final NcmpEventResponseCode
- ncmpEventResponseCode,
+ final NcmpResponseStatus
+ ncmpResponseStatus,
final List<String> cmHandleIds) {
if (!cmHandleIds.isEmpty()) {
- cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperation, Map.of(ncmpEventResponseCode, cmHandleIds));
+ cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperation, Map.of(ncmpResponseStatus, cmHandleIds));
}
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java
index 52fc81f50..d148f371b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java
@@ -64,6 +64,9 @@ public class YangModelCmHandle {
@JsonProperty("dmi-model-service-name")
private String dmiModelServiceName;
+ @JsonProperty("module-set-tag")
+ private String moduleSetTag;
+
@JsonProperty("additional-properties")
private List<Property> dmiProperties;
@@ -102,12 +105,14 @@ public class YangModelCmHandle {
public static YangModelCmHandle toYangModelCmHandle(final String dmiServiceName,
final String dmiDataServiceName,
final String dmiModelServiceName,
- final NcmpServiceCmHandle ncmpServiceCmHandle) {
+ final NcmpServiceCmHandle ncmpServiceCmHandle,
+ final String moduleSetTag) {
final YangModelCmHandle yangModelCmHandle = new YangModelCmHandle();
yangModelCmHandle.setId(ncmpServiceCmHandle.getCmHandleId());
yangModelCmHandle.setDmiServiceName(dmiServiceName);
yangModelCmHandle.setDmiDataServiceName(dmiDataServiceName);
yangModelCmHandle.setDmiModelServiceName(dmiModelServiceName);
+ yangModelCmHandle.setModuleSetTag(moduleSetTag);
yangModelCmHandle.setDmiProperties(asYangModelCmHandleProperties(ncmpServiceCmHandle.getDmiProperties()));
yangModelCmHandle.setPublicProperties(asYangModelCmHandleProperties(
ncmpServiceCmHandle.getPublicProperties()));
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java
index d5b27b61f..e007491ce 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java
@@ -1,7 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2022 Bell Canada
- * Modifications Copyright (C) 2022 Nordix Foundation
+ * Modifications Copyright (C) 2022-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,16 +21,16 @@
package org.onap.cps.ncmp.api.models;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
import lombok.Builder;
import lombok.Data;
-import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.NcmpResponseStatus;
+import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
@Data
@Builder
@@ -39,11 +39,9 @@ public class CmHandleRegistrationResponse {
private final String cmHandle;
private final Status status;
- private RegistrationError registrationError;
+ private NcmpResponseStatus ncmpResponseStatus;
private String errorText;
- private static final Pattern cmHandleIdInXpathPattern = Pattern.compile("\\[@id='(.*?)']");
-
/**
* Creates a failure response based on exception.
*
@@ -56,7 +54,7 @@ public class CmHandleRegistrationResponse {
return CmHandleRegistrationResponse.builder()
.cmHandle(cmHandleId)
.status(Status.FAILURE)
- .registrationError(RegistrationError.UNKNOWN_ERROR)
+ .ncmpResponseStatus(UNKNOWN_ERROR)
.errorText(exception.getMessage()).build();
}
@@ -64,15 +62,15 @@ public class CmHandleRegistrationResponse {
* Creates a failure response based on registration error.
*
* @param cmHandleId cmHandleId
- * @param registrationError registrationError
+ * @param ncmpResponseStatus registration error code and status
* @return CmHandleRegistrationResponse
*/
public static CmHandleRegistrationResponse createFailureResponse(final String cmHandleId,
- final RegistrationError registrationError) {
+ final NcmpResponseStatus ncmpResponseStatus) {
return CmHandleRegistrationResponse.builder().cmHandle(cmHandleId)
.status(Status.FAILURE)
- .registrationError(registrationError)
- .errorText(registrationError.errorText)
+ .ncmpResponseStatus(ncmpResponseStatus)
+ .errorText(ncmpResponseStatus.getMessage())
.build();
}
@@ -80,18 +78,18 @@ public class CmHandleRegistrationResponse {
* Creates a failure response based on registration error.
*
* @param failedXpaths list of failed Xpaths
- * @param registrationError enum describing the type of registration error
+ * @param ncmpResponseStatus enum describing the type of registration error
* @return CmHandleRegistrationResponse
*/
public static List<CmHandleRegistrationResponse> createFailureResponses(final Collection<String> failedXpaths,
- final RegistrationError registrationError) {
+ final NcmpResponseStatus ncmpResponseStatus) {
final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = new ArrayList<>(failedXpaths.size());
for (final String xpath : failedXpaths) {
- final Matcher matcher = cmHandleIdInXpathPattern.matcher(xpath);
- if (matcher.find()) {
+ try {
+ final String cmHandleId = YangDataConverter.extractCmHandleIdFromXpath(xpath);
cmHandleRegistrationResponses.add(
- CmHandleRegistrationResponse.createFailureResponse(matcher.group(1), registrationError));
- } else {
+ CmHandleRegistrationResponse.createFailureResponse(cmHandleId, ncmpResponseStatus));
+ } catch (IllegalArgumentException | IllegalStateException e) {
log.warn("Unexpected xpath {}", xpath);
}
}
@@ -109,7 +107,7 @@ public class CmHandleRegistrationResponse {
final Exception exception) {
return cmHandleIds.stream()
.map(cmHandleId -> CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception))
- .collect(Collectors.toList());
+ .toList();
}
public static CmHandleRegistrationResponse createSuccessResponse(final String cmHandle) {
@@ -118,23 +116,10 @@ public class CmHandleRegistrationResponse {
}
public static List<CmHandleRegistrationResponse> createSuccessResponses(final List<String> cmHandleIds) {
- return cmHandleIds.stream().map(CmHandleRegistrationResponse::createSuccessResponse)
- .collect(Collectors.toList());
+ return cmHandleIds.stream().map(CmHandleRegistrationResponse::createSuccessResponse).toList();
}
public enum Status {
SUCCESS, FAILURE;
}
-
- @RequiredArgsConstructor
- public enum RegistrationError {
- UNKNOWN_ERROR("00", "Unknown error"),
- CM_HANDLE_ALREADY_EXIST("01", "cm-handle already exists"),
- CM_HANDLE_DOES_NOT_EXIST("02", "cm-handle does not exist"),
- CM_HANDLE_INVALID_ID("03", "cm-handle has an invalid character(s) in id");
-
- public final String errorCode;
- public final String errorText;
-
- }
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java
index 953b3c4e9..4615af61c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java
@@ -50,6 +50,8 @@ public class DmiPluginRegistration {
private List<String> removedCmHandles = Collections.emptyList();
+ private UpgradedCmHandles upgradedCmHandles;
+
/**
* Validates plugin service names.
* @throws NcmpException if validation fails.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java
index 8a3d26414..ee034176e 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2022 Bell Canada
+ * Modifications Copyright (C) 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.
@@ -31,4 +32,5 @@ public class DmiPluginRegistrationResponse {
private List<CmHandleRegistrationResponse> createdCmHandles = Collections.emptyList();
private List<CmHandleRegistrationResponse> updatedCmHandles = Collections.emptyList();
private List<CmHandleRegistrationResponse> removedCmHandles = Collections.emptyList();
+ private List<CmHandleRegistrationResponse> upgradedCmHandles = Collections.emptyList();
} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java
index c46a8c26d..0b50346f8 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java
@@ -52,6 +52,9 @@ public class NcmpServiceCmHandle {
@JsonSetter(nulls = Nulls.AS_EMPTY)
private CompositeState compositeState;
+ @JsonSetter(nulls = Nulls.AS_EMPTY)
+ private String moduleSetTag;
+
/**
* NcmpServiceCmHandle copy constructor.
*
@@ -63,5 +66,6 @@ public class NcmpServiceCmHandle {
this.publicProperties = new LinkedHashMap<>(ncmpServiceCmHandle.getPublicProperties());
this.compositeState = ncmpServiceCmHandle.getCompositeState() != null ? new CompositeState(
ncmpServiceCmHandle.getCompositeState()) : null;
+ this.moduleSetTag = ncmpServiceCmHandle.getModuleSetTag();
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceTrustLevel.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java
index 2ed4e4522..61cd99ac8 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceTrustLevel.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java
@@ -18,20 +18,19 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.trustlevel;
+package org.onap.cps.ncmp.api.models;
-import java.io.Serializable;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@AllArgsConstructor
-@Data
-@NoArgsConstructor
-class DeviceTrustLevel implements Serializable {
-
- private static final long serialVersionUID = -1705715024067165212L;
-
- private TrustLevel trustLevel;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import java.util.Collections;
+import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
+@Getter
+@Setter
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class UpgradedCmHandles {
+ private List<String> cmHandles = Collections.emptyList();
+ private String moduleSetTag;
}
+
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy
index c2e2b91cf..7c410cc58 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy
@@ -39,7 +39,7 @@ import spock.lang.Specification
class NetworkCmProxyCmHandleQueryServiceSpec extends Specification {
def cmHandleQueries = Mock(CmHandleQueries)
- def partiallyMockedCmHandleQueries = Spy(CmHandleQueriesImpl)
+ def partiallyMockedCmHandleQueries = Spy(CmHandleQueries)
def mockInventoryPersistence = Mock(InventoryPersistence)
def dmiRegistry = new DataNode(xpath: NCMP_DMI_REGISTRY_PARENT, childDataNodes: createDataNodeList(['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4']))
@@ -53,7 +53,7 @@ class NetworkCmProxyCmHandleQueryServiceSpec extends Specification {
def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']])
cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
and: 'the query get the cm handle datanodes excluding all descendants returns a datanode'
- cmHandleQueries.queryCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])]
+ cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])]
when: 'the query is executed for cm handle ids'
def result = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
then: 'the correct expected cm handles ids are returned'
@@ -66,7 +66,7 @@ class NetworkCmProxyCmHandleQueryServiceSpec extends Specification {
def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']])
cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
and: 'cmHandleQueries throws a path parsing exception'
- cmHandleQueries.queryCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> { throw thrownException }
+ cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> { throw thrownException }
when: 'the query is executed for cm handle ids'
objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
then: 'a data validation exception is thrown'
@@ -106,6 +106,17 @@ class NetworkCmProxyCmHandleQueryServiceSpec extends Specification {
'No anchors are returned' | []
}
+ def 'Query cm handles with some trust level query parameters'() {
+ given: 'a trust level condition property'
+ def trustLevelQueryParameters = new CmHandleQueryServiceParameters()
+ def trustLevelConditionProperties = createConditionProperties('cmHandleWithTrustLevel', [['trustLevel': 'COMPLETE'] as Map])
+ trustLevelQueryParameters.setCmHandleQueryParameters([trustLevelConditionProperties])
+ when: 'the query is being executed'
+ objectUnderTest.queryCmHandleIds(trustLevelQueryParameters)
+ then: 'the query is being delegated to the cm handle query service with correct parameter'
+ 1 * cmHandleQueries.queryCmHandlesByTrustLevel(['trustLevel': 'COMPLETE'] as Map)
+ }
+
def 'Query cm handle details with module names when #scenario from query.'() {
given: 'a modules condition property'
def cmHandleQueryParameters = new CmHandleQueryServiceParameters()
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
index 46666b941..9e4737fff 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
@@ -21,6 +21,12 @@
package org.onap.cps.ncmp.api.impl
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
+import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
+
import com.fasterxml.jackson.databind.ObjectMapper
import com.hazelcast.map.IMap
import org.onap.cps.api.CpsDataService
@@ -45,12 +51,6 @@ import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Shared
import spock.lang.Specification
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_DOES_NOT_EXIST
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_ALREADY_EXIST
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_INVALID_ID
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.UNKNOWN_ERROR
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
-
class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
@Shared
@@ -80,11 +80,11 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
when: 'registration is processed'
objectUnderTest.updateDmiRegistrationAndSyncModule(dmiRegistration)
then: 'cm-handles are removed first'
- 1 * objectUnderTest.parseAndRemoveCmHandlesInDmiRegistration(*_)
+ 1 * objectUnderTest.parseAndProcessDeletedCmHandlesInRegistration(*_)
and: 'de-registered cm handle entry is removed from in progress map'
1 * mockModuleSyncStartedOnCmHandles.remove('cmhandle-2')
then: 'cm-handles are created'
- 1 * objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(*_)
+ 1 * objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(*_)
then: 'cm-handles are updated'
1 * mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(*_)
}
@@ -100,10 +100,10 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(*_) >> updateResponses
and: 'create cm-handles can be processed successfully'
def createdResponses = [CmHandleRegistrationResponse.createSuccessResponse('cmhandle-1')]
- objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(*_) >> createdResponses
+ objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(*_) >> createdResponses
and: 'delete cm-handles can be processed successfully'
def removeResponses = [CmHandleRegistrationResponse.createSuccessResponse('cmhandle-3')]
- objectUnderTest.parseAndRemoveCmHandlesInDmiRegistration(*_) >> removeResponses
+ objectUnderTest.parseAndProcessDeletedCmHandlesInRegistration(*_) >> removeResponses
when: 'registration is processed'
def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiRegistration)
then: 'response has values from all operations'
@@ -120,7 +120,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
when: 'update registration and sync module is called with correct DMI plugin information'
objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
then: 'create cm handles registration and sync modules is called with the correct plugin information'
- 1 * objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration)
+ 1 * objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration)
and: 'dmi is added to the trustLevel map'
1 * mockTrustLevelPerDmiPlugin.put(dmiPluginRegisteredName, TrustLevel.COMPLETE)
where:
@@ -141,7 +141,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def exceptionThrown = thrown(DmiRequestException.class)
assert exceptionThrown.getMessage().contains(expectedMessageDetails)
and: 'registration is not called'
- 0 * objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration)
+ 0 * objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(dmiPluginRegistration)
where:
scenario | dmiPlugin | dmiModelPlugin | dmiDataPlugin || expectedMessageDetails
'empty DMI plugins' | '' | '' | '' || 'No DMI plugin service names'
@@ -203,7 +203,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
response.createdCmHandles.each {
assert it.cmHandle == 'cmhandle2'
assert it.status == Status.FAILURE
- assert it.registrationError == CM_HANDLE_ALREADY_EXIST
+ assert it.ncmpResponseStatus == CM_HANDLE_ALREADY_EXIST
assert it.errorText == 'cm-handle already exists'
}
}
@@ -221,7 +221,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
with(response.createdCmHandles[0]) {
assert it.status == Status.FAILURE
assert it.cmHandle == 'cmhandle'
- assert it.registrationError == expectedError
+ assert it.ncmpResponseStatus == expectedError
assert it.errorText == expectedErrorText
}
where:
@@ -236,7 +236,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
and: 'cm-handle updates can be processed successfully'
def updateOperationResponse = [CmHandleRegistrationResponse.createSuccessResponse('cm-handle-1'),
CmHandleRegistrationResponse.createFailureResponse('cm-handle-2', new Exception("Failed")),
- CmHandleRegistrationResponse.createFailureResponse('cm-handle-3', CM_HANDLE_DOES_NOT_EXIST),
+ CmHandleRegistrationResponse.createFailureResponse('cm-handle-3', CM_HANDLES_NOT_FOUND),
CmHandleRegistrationResponse.createFailureResponse('cm handle 4', CM_HANDLE_INVALID_ID)]
mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(_) >> updateOperationResponse
when: 'registration is updated'
@@ -310,7 +310,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
and: '2nd cm-handle deletion fails'
with(response.removedCmHandles[1]) {
assert it.status == Status.FAILURE
- assert it.registrationError == UNKNOWN_ERROR
+ assert it.ncmpResponseStatus == UNKNOWN_ERROR
assert it.errorText == 'Failed'
assert it.cmHandle == 'cmhandle2'
}
@@ -344,7 +344,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
assert it.status == Status.FAILURE
assert it.cmHandle == 'cmhandle'
assert it.errorText == 'Failed'
- assert it.registrationError == UNKNOWN_ERROR
+ assert it.ncmpResponseStatus == UNKNOWN_ERROR
}
}
@@ -364,16 +364,16 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
with(response.removedCmHandles[0]) {
assert it.status == Status.FAILURE
assert it.cmHandle == 'cmhandle'
- assert it.registrationError == expectedError
+ assert it.ncmpResponseStatus == expectedError
assert it.errorText == expectedErrorText
}
and: 'the cm handle state is not updated to "DELETED"'
0 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_, CmHandleState.DELETED)
where:
- scenario | cmHandleId | deleteListElementException || expectedError | expectedErrorText
- 'cm-handle does not exist' | 'cmhandle' | new DataNodeNotFoundException('', '', '') || CM_HANDLE_DOES_NOT_EXIST | 'cm-handle does not exist'
- 'cm-handle has invalid name' | 'cm handle with space' | new DataValidationException('', '') || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id'
- 'an unexpected exception' | 'cmhandle' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed'
+ scenario | cmHandleId | deleteListElementException || expectedError | expectedErrorText
+ 'cm-handle does not exist' | 'cmhandle' | new DataNodeNotFoundException('', '', '') || CM_HANDLES_NOT_FOUND | 'cm handle id(s) not found'
+ 'cm-handle has invalid name' | 'cm handle with space' | new DataValidationException('', '') || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id'
+ 'an unexpected exception' | 'cmhandle' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed'
}
def getObjectUnderTest() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
index 01a0600af..af65cfc1a 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
@@ -76,7 +76,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
def mockCpsCmHandlerQueryService = Mock(NetworkCmProxyCmHandleQueryService)
def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler)
def stubModuleSyncStartedOnCmHandles = Stub(IMap<String, Object>)
- def stubTrustLevelPerDmiPlugin = Stub(IMap<String, TrustLevel>)
+ def stubTrustLevelPerDmiPlugin = Stub(Map<String, TrustLevel>)
def NO_TOPIC = null
def NO_REQUEST_ID = null
@@ -261,7 +261,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle]
mockDmiPluginRegistration.getCreatedCmHandles() >> [ncmpServiceCmHandle]
when: 'parse and create cm handle in dmi registration then sync module'
- objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(mockDmiPluginRegistration)
+ objectUnderTest.parseAndProcessCreatedCmHandlesInRegistration(mockDmiPluginRegistration)
then: 'system persists the cm handle state'
1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> {
args -> {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
index 610400f75..6439f0b58 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
@@ -24,13 +24,13 @@ package org.onap.cps.ncmp.api.impl
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
+import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
import org.onap.cps.spi.exceptions.DataValidationException
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_DOES_NOT_EXIST
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_INVALID_ID
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.UNKNOWN_ERROR
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
import org.onap.cps.spi.exceptions.DataNodeNotFoundException
import org.onap.cps.spi.model.DataNode
@@ -131,14 +131,14 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
with(response.get(0)) {
assert it.status == Status.FAILURE
assert it.cmHandle == cmHandleId
- assert it.registrationError == expectedError
+ assert it.ncmpResponseStatus == expectedError
assert it.errorText == expectedErrorText
}
where:
- scenario | cmHandleId | exception || expectedError | expectedErrorText
- 'Cm Handle does not exist' | 'cmHandleId' | new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR) || CM_HANDLE_DOES_NOT_EXIST | 'cm-handle does not exist'
- 'Unknown' | 'cmHandleId' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed'
- 'Invalid cm handle id' | 'cmHandleId with spaces' | new DataValidationException('Name Validation Error.', cmHandleId + 'contains an invalid character') || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id'
+ scenario | cmHandleId | exception || expectedError | expectedErrorText
+ 'Cm Handle does not exist' | 'cmHandleId' | new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR) || CM_HANDLES_NOT_FOUND | 'cm handle id(s) not found'
+ 'Unknown' | 'cmHandleId' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed'
+ 'Invalid cm handle id' | 'cmHandleId with spaces' | new DataValidationException('Name Validation Error.', cmHandleId + 'contains an invalid character') || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id'
}
def 'Multiple update operations in a single request'() {
@@ -166,8 +166,8 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
with(cmHandleResponseList.get(1)) {
assert it.status == Status.FAILURE
assert it.cmHandle == cmHandleId
- assert it.registrationError == CM_HANDLE_DOES_NOT_EXIST
- assert it.errorText == "cm-handle does not exist"
+ assert it.ncmpResponseStatus == CM_HANDLES_NOT_FOUND
+ assert it.errorText == 'cm handle id(s) not found'
}
then: 'the replace list method is called twice'
2 * mockInventoryPersistence.replaceListContent(cmHandleXpath,_)
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy
index 6184a9722..3eff96d79 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy
@@ -22,7 +22,6 @@ package org.onap.cps.ncmp.api.impl.config.embeddedcache
import com.hazelcast.config.Config
import com.hazelcast.core.Hazelcast
-import com.hazelcast.map.IMap
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
@@ -32,7 +31,10 @@ import spock.lang.Specification
class TrustLevelCacheConfigSpec extends Specification {
@Autowired
- private IMap<String, TrustLevel> trustLevelPerDmiPlugin
+ private Map<String, TrustLevel> trustLevelPerDmiPlugin
+
+ @Autowired
+ private Map<String, TrustLevel> trustLevelPerCmHandle
def 'Hazelcast cache for trust level per dmi plugin'() {
expect: 'system is able to create an instance of the trust level per dmi plugin cache'
@@ -43,23 +45,29 @@ class TrustLevelCacheConfigSpec extends Specification {
assert Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceTrustLevelPerDmiPluginMap')
}
- def 'Verify Trust Level Per Dmi Plugin Cache for basic hazelcast map operations'() {
- when: 'the key inserted into Trust Level Per Dmi Plugin Cache'
- trustLevelPerDmiPlugin.put('dmi1', TrustLevel.COMPLETE)
- trustLevelPerDmiPlugin.put('dmi2', TrustLevel.NONE)
- then: 'the value for each dmi can be retrieved'
- assert trustLevelPerDmiPlugin.get('dmi1') == TrustLevel.COMPLETE
- assert trustLevelPerDmiPlugin.get('dmi2') == TrustLevel.NONE
+ def 'Hazelcast cache for trust level per cm handle'() {
+ expect: 'system is able to create an instance of the trust level per cm handle cache'
+ assert null != trustLevelPerCmHandle
+ and: 'there is at least 1 instance'
+ assert Hazelcast.allHazelcastInstances.size() > 0
+ and: 'Hazelcast cache instance for trust level is present'
+ assert Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceTrustLevelPerCmHandleMap')
}
- def 'Verify configs for Distributed Caches'(){
- given: 'the Trust Level Per Dmi Plugin Cache config'
- def trustLevelDmiPerPluginCacheConfig = Hazelcast.getHazelcastInstanceByName('hazelcastInstanceTrustLevelPerDmiPluginMap').config
- def trustLevelDmiPerPluginCacheMapConfig = trustLevelDmiPerPluginCacheConfig.mapConfigs.get('trustLevelPerDmiPluginCacheConfig')
- expect: 'system created instance with correct config'
- assert trustLevelDmiPerPluginCacheConfig.clusterName == 'cps-and-ncmp-test-caches'
- assert trustLevelDmiPerPluginCacheMapConfig.backupCount == 3
- assert trustLevelDmiPerPluginCacheMapConfig.asyncBackupCount == 3
+ def 'Trust level cache configurations: #scenario'() {
+ when: 'retrieving the cache config for trustLevel'
+ def cacheConfig = Hazelcast.getHazelcastInstanceByName(hazelcastInstanceName).config
+ then: 'the cache config has the right cluster'
+ assert cacheConfig.clusterName == 'cps-and-ncmp-test-caches'
+ when: 'retrieving the map config for trustLevel'
+ def mapConfig = cacheConfig.mapConfigs.get(hazelcastMapConfigName)
+ then: 'the map config has the correct backup counts'
+ assert mapConfig.backupCount == 3
+ assert mapConfig.asyncBackupCount == 3
+ where: 'the following caches are used'
+ scenario | hazelcastInstanceName | hazelcastMapConfigName
+ 'cmhandle map' | 'hazelcastInstanceTrustLevelPerCmHandleMap' | 'trustLevelPerCmHandleCacheConfig'
+ 'dmi plugin map' | 'hazelcastInstanceTrustLevelPerDmiPluginMap' | 'trustLevelPerDmiPluginCacheConfig'
}
def 'Verify deployment network configs for Distributed Caches'() {
@@ -70,6 +78,14 @@ class TrustLevelCacheConfigSpec extends Specification {
assert !trustLevelDmiPerPluginCacheConfig.join.kubernetesConfig.enabled
}
+ def 'Verify deployment network configs for Cm Handle Distributed Caches'() {
+ given: 'the Trust Level Per Cm Handle Cache config'
+ def trustLevelPerCmHandlePluginCacheConfig = Hazelcast.getHazelcastInstanceByName('hazelcastInstanceTrustLevelPerCmHandleMap').config.networkConfig
+ expect: 'system created instance with correct config'
+ assert trustLevelPerCmHandlePluginCacheConfig.join.autoDetectionConfig.enabled
+ assert !trustLevelPerCmHandlePluginCacheConfig.join.kubernetesConfig.enabled
+ }
+
def 'Verify network config'() {
given: 'Synchronization config object and test configuration'
def objectUnderTest = new TrustLevelCacheConfig()
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy
index cc1419519..a0567cb4c 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy
@@ -20,11 +20,15 @@
package org.onap.cps.ncmp.api.impl.events.cmsubscription
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUCCESSFULLY_APPLIED_SUBSCRIPTION
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUBSCRIPTION_PENDING
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUBSCRIPTION_NOT_APPLICABLE
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.PARTIALLY_APPLIED_SUBSCRIPTION
+
import com.fasterxml.jackson.databind.ObjectMapper
import io.cloudevents.CloudEvent
import io.cloudevents.core.builder.CloudEventBuilder
import org.mapstruct.factory.Mappers
-import org.onap.cps.ncmp.api.NcmpEventResponseCode
import org.onap.cps.ncmp.api.impl.events.EventsPublisher
import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistence
import org.onap.cps.ncmp.api.impl.utils.DataNodeBaseSpec
@@ -98,9 +102,9 @@ class CmSubscriptionNcmpOutEventPublisherSpec extends DataNodeBaseSpec {
then: 'the result will be equal to ncmp out event'
expectedResult == ncmpOutEvent
where: 'the following values are used'
- scenario | ncmpEventResponseCode || statusMessage || statusCode
- 'is full outcome' | NcmpEventResponseCode.SUCCESSFULLY_APPLIED_SUBSCRIPTION || 'successfully applied subscription' || 1
- 'is partial outcome' | NcmpEventResponseCode.PARTIALLY_APPLIED_SUBSCRIPTION || 'partially applied subscription' || 104
+ scenario | ncmpEventResponseCode || statusMessage || statusCode
+ 'is full outcome' | SUCCESSFULLY_APPLIED_SUBSCRIPTION || 'successfully applied subscription' || 1
+ 'is partial outcome' | PARTIALLY_APPLIED_SUBSCRIPTION || 'partially applied subscription' || 104
}
def 'Check cm handle id to status map to see if it is a full outcome response'() {
@@ -109,16 +113,16 @@ class CmSubscriptionNcmpOutEventPublisherSpec extends DataNodeBaseSpec {
then: 'the result will be as expected'
response == expectedOutcomeResponseDecision
where: 'the following values are used'
- scenario | cmHandleIdToStatusAndDetailsAsMap || expectedOutcomeResponseDecision
- 'The map contains PENDING status' | [CMHandle1: [details:'Subscription forwarded to dmi plugin',status:'PENDING'] as Map] as Map || NcmpEventResponseCode.SUBSCRIPTION_PENDING
- 'The map contains ACCEPTED status' | [CMHandle1: [details:'',status:'ACCEPTED'] as Map] as Map || NcmpEventResponseCode.SUCCESSFULLY_APPLIED_SUBSCRIPTION
- 'The map contains REJECTED status' | [CMHandle1: [details:'Cm handle does not exist',status:'REJECTED'] as Map] as Map || NcmpEventResponseCode.SUBSCRIPTION_NOT_APPLICABLE
- 'The map contains PENDING and PENDING statuses' | [CMHandle1: [details:'Some details',status:'PENDING'] as Map, CMHandle2: [details:'Some details',status:'PENDING'] as Map as Map] as Map || NcmpEventResponseCode.SUBSCRIPTION_PENDING
- 'The map contains ACCEPTED and ACCEPTED statuses' | [CMHandle1: [details:'',status:'ACCEPTED'] as Map, CMHandle2: [details:'',status:'ACCEPTED'] as Map as Map] as Map || NcmpEventResponseCode.SUCCESSFULLY_APPLIED_SUBSCRIPTION
- 'The map contains REJECTED and REJECTED statuses' | [CMHandle1: [details:'Reject details',status:'REJECTED'] as Map, CMHandle2: [details:'Reject details',status:'REJECTED'] as Map as Map] as Map || NcmpEventResponseCode.SUBSCRIPTION_NOT_APPLICABLE
- 'The map contains PENDING and ACCEPTED statuses' | [CMHandle1: [details:'Some details',status:'PENDING'] as Map, CMHandle2: [details:'',status:'ACCEPTED'] as Map as Map] as Map || NcmpEventResponseCode.PARTIALLY_APPLIED_SUBSCRIPTION
- 'The map contains REJECTED and ACCEPTED statuses' | [CMHandle1: [details:'Cm handle does not exist',status:'REJECTED'] as Map, CMHandle2: [details:'',status:'ACCEPTED'] as Map as Map] as Map || NcmpEventResponseCode.PARTIALLY_APPLIED_SUBSCRIPTION
- 'The map contains PENDING and REJECTED statuses' | [CMHandle1: [details:'Subscription forwarded to dmi plugin',status:'PENDING'] as Map, CMHandle2: [details:'Cm handle does not exist',status:'REJECTED'] as Map as Map] as Map || NcmpEventResponseCode.PARTIALLY_APPLIED_SUBSCRIPTION
+ scenario | cmHandleIdToStatusAndDetailsAsMap || expectedOutcomeResponseDecision
+ 'The map contains PENDING status' | [CMHandle1: [details: 'Subscription forwarded to dmi plugin', status: 'PENDING'] as Map] as Map || SUBSCRIPTION_PENDING
+ 'The map contains ACCEPTED status' | [CMHandle1: [details: '', status: 'ACCEPTED'] as Map] as Map || SUCCESSFULLY_APPLIED_SUBSCRIPTION
+ 'The map contains REJECTED status' | [CMHandle1: [details: 'Cm handle does not exist', status: 'REJECTED'] as Map] as Map || SUBSCRIPTION_NOT_APPLICABLE
+ 'The map contains PENDING and PENDING statuses' | [CMHandle1: [details: 'Some details', status: 'PENDING'] as Map, CMHandle2: [details: 'Some details', status: 'PENDING'] as Map as Map] as Map || SUBSCRIPTION_PENDING
+ 'The map contains ACCEPTED and ACCEPTED statuses' | [CMHandle1: [details: '', status: 'ACCEPTED'] as Map, CMHandle2: [details: '', status: 'ACCEPTED'] as Map as Map] as Map || SUCCESSFULLY_APPLIED_SUBSCRIPTION
+ 'The map contains REJECTED and REJECTED statuses' | [CMHandle1: [details: 'Reject details', status: 'REJECTED'] as Map, CMHandle2: [details: 'Reject details', status: 'REJECTED'] as Map as Map] as Map || SUBSCRIPTION_NOT_APPLICABLE
+ 'The map contains PENDING and ACCEPTED statuses' | [CMHandle1: [details: 'Some details', status: 'PENDING'] as Map, CMHandle2: [details: '', status: 'ACCEPTED'] as Map as Map] as Map || PARTIALLY_APPLIED_SUBSCRIPTION
+ 'The map contains REJECTED and ACCEPTED statuses' | [CMHandle1: [details: 'Cm handle does not exist', status: 'REJECTED'] as Map, CMHandle2: [details: '', status: 'ACCEPTED'] as Map as Map] as Map || PARTIALLY_APPLIED_SUBSCRIPTION
+ 'The map contains PENDING and REJECTED statuses' | [CMHandle1: [details: 'Subscription forwarded to dmi plugin', status: 'PENDING'] as Map, CMHandle2: [details: 'Cm handle does not exist', status: 'REJECTED'] as Map as Map] as Map || PARTIALLY_APPLIED_SUBSCRIPTION
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapperSpec.groovy
index 380aea405..e6d383128 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapperSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapperSpec.groovy
@@ -34,17 +34,30 @@ class CloudEventMapperSpec extends Specification {
@Autowired
JsonObjectMapper jsonObjectMapper
- def 'Cloud event to Target event type when it is #scenario'() {
- expect: 'Events mapped correctly'
- assert mappedCloudEvent == (CloudEventMapper.toTargetEvent(testCloudEvent(), targetClass) != null)
+ def 'Cloud event to target event type'() {
+ given: 'a cloud event with valid payload'
+ def cloudEvent = testCloudEvent(new CmSubscriptionNcmpInEvent())
+ when: 'the cloud event mapped to target event'
+ def result = CloudEventMapper.toTargetEvent((cloudEvent), CmSubscriptionNcmpInEvent.class)
+ then: 'the cloud event is mapped'
+ assert result instanceof CmSubscriptionNcmpInEvent
+ }
+
+ def 'Cloud event to target event type when it is #scenario'() {
+ given: 'a cloud event with invalid payload'
+ def cloudEvent = testCloudEvent(payload)
+ when: 'the cloud event mapped to target event'
+ def result = CloudEventMapper.toTargetEvent(cloudEvent, CmSubscriptionNcmpInEvent.class)
+ then: 'result is null'
+ assert result == null
where: 'below are the scenarios'
- scenario | targetClass || mappedCloudEvent
- 'valid concrete type' | CmSubscriptionNcmpInEvent.class || true
- 'invalid concrete type' | ArrayList.class || false
+ scenario | payload
+ 'invalid payload type' | ArrayList.class
+ 'without payload' | null
}
- def testCloudEvent() {
- return CloudEventBuilder.v1().withData(jsonObjectMapper.asJsonBytes(new CmSubscriptionNcmpInEvent()))
+ def testCloudEvent(payload) {
+ return CloudEventBuilder.v1().withData(jsonObjectMapper.asJsonBytes(payload))
.withId("cmhandle1")
.withSource(URI.create('test-source'))
.withDataSchema(URI.create('test'))
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
index 76ef23fe5..39c4fe6ee 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
@@ -21,8 +21,16 @@
package org.onap.cps.ncmp.api.impl.operations
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE
+import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING
+
import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.ncmp.api.NcmpEventResponseCode
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
import org.onap.cps.ncmp.api.impl.events.EventsPublisher
import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException
@@ -41,13 +49,6 @@ import org.springframework.http.HttpStatus
import spock.lang.Shared
import java.util.concurrent.TimeoutException
-import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL
-import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE
-import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent
-
@SpringBootTest
@ContextConfiguration(classes = [EventsPublisher, CpsApplicationContext, NcmpConfiguration.DmiProperties, DmiDataOperations])
class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
@@ -128,12 +129,12 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def eventDataValue = extractDataValue(actualDataOperationCloudEvent)
assert eventDataValue.operationId == dmiDataOperation.operationId
assert eventDataValue.ids == dmiDataOperation.cmHandles.id
- assert eventDataValue.statusCode == responseCode.statusCode
- assert eventDataValue.statusMessage == responseCode.statusMessage
+ assert eventDataValue.statusCode == responseCode.code
+ assert eventDataValue.statusMessage == responseCode.message
where: 'the following exceptions are occurred'
scenario | exception || responseCode
- 'http client request exception' | new HttpClientRequestException('error-message', 'error-details', HttpStatus.SERVICE_UNAVAILABLE.value()) || NcmpEventResponseCode.UNABLE_TO_READ_RESOURCE_DATA
- 'timeout exception' | new TimeoutException() || NcmpEventResponseCode.DMI_SERVICE_NOT_RESPONDING
+ 'http client request exception' | new HttpClientRequestException('error-message', 'error-details', HttpStatus.SERVICE_UNAVAILABLE.value()) || UNABLE_TO_READ_RESOURCE_DATA
+ 'timeout exception' | new TimeoutException() || DMI_SERVICE_NOT_RESPONDING
}
def 'call get all resource data.'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy
index 48de23dca..80778b9c7 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy
@@ -21,81 +21,70 @@
package org.onap.cps.ncmp.api.impl.trustlevel
import com.fasterxml.jackson.databind.ObjectMapper
-import com.hazelcast.collection.ISet
+import com.hazelcast.map.IMap
import io.cloudevents.CloudEvent
import io.cloudevents.core.builder.CloudEventBuilder
import org.apache.kafka.clients.consumer.ConsumerRecord
+import org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel
import org.onap.cps.utils.JsonObjectMapper
+import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import spock.lang.Specification
@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper])
class DeviceHeartbeatConsumerSpec extends Specification {
- def mockUntrustworthyCmHandlesSet = Mock(ISet<String>)
+ def mockTrustLevelPerCmHandle = Mock(Map<String, TrustLevel>)
+
+ def objectUnderTest = new DeviceHeartbeatConsumer(mockTrustLevelPerCmHandle)
def objectMapper = new ObjectMapper()
- def objectUnderTest = new DeviceHeartbeatConsumer(mockUntrustworthyCmHandlesSet)
+ @Autowired
+ JsonObjectMapper jsonObjectMapper
+
+ def static trustLevelString = '{"data":{"trustLevel": "COMPLETE"}}'
- def 'Operations to be done in an empty untrustworthy set for #scenario'() {
- given: 'an event with trustlevel as #trustLevel'
- def incomingEvent = testCloudEvent(trustLevel)
- and: 'transformed as a kafka record'
- def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', incomingEvent)
+ def 'Consume a trustlevel event'() {
+ given: 'an event from dmi with trust level complete'
+ def payload = jsonObjectMapper.convertJsonString(trustLevelString, DeviceTrustLevel.class)
+ def eventFromDmi = createTrustLevelEvent(payload)
+ and: 'transformed to a consumer record with a cloud event id (ce_id)'
+ def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'sample-message-key', eventFromDmi)
consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('cmhandle1'))
when: 'the event is consumed'
objectUnderTest.heartbeatListener(consumerRecord)
- then: 'untrustworthy cmhandles are stored'
- untrustworthyCmHandlesSetInvocationForAdd * mockUntrustworthyCmHandlesSet.add(_)
- and: 'trustworthy cmHandles will be removed from untrustworthy set'
- untrustworthyCmHandlesSetInvocationForContains * mockUntrustworthyCmHandlesSet.contains(_)
-
- where: 'below scenarios are applicable'
- scenario | trustLevel || untrustworthyCmHandlesSetInvocationForAdd | untrustworthyCmHandlesSetInvocationForContains
- 'None trust' | TrustLevel.NONE || 1 | 0
- 'Complete trust' | TrustLevel.COMPLETE || 0 | 1
+ then: 'cm handles are stored with correct trust level'
+ 1 * mockTrustLevelPerCmHandle.put('"cmhandle1"', TrustLevel.COMPLETE)
}
- def 'Invalid trust'() {
- when: 'we provide an invalid trust in the event'
- def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', testCloudEvent(null))
- consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('cmhandle1'))
+ def 'Consume trustlevel event without cloud event id'() {
+ given: 'an event from dmi'
+ def payload = jsonObjectMapper.convertJsonString(trustLevelString, DeviceTrustLevel.class)
+ def eventFromDmi = createTrustLevelEvent(payload)
+ and: 'transformed to a consumer record WITHOUT Cloud event ID (ce_id)'
+ def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'sample-message-key', eventFromDmi)
+ when: 'the event is consumed'
objectUnderTest.heartbeatListener(consumerRecord)
- then: 'no interaction with the untrustworthy cmhandles set'
- 0 * mockUntrustworthyCmHandlesSet.add(_)
- 0 * mockUntrustworthyCmHandlesSet.contains(_)
- 0 * mockUntrustworthyCmHandlesSet.remove(_)
- and: 'control flow returns without any exception'
- noExceptionThrown()
-
+ then: 'no cm handle has been stored in the map'
+ 0 * mockTrustLevelPerCmHandle.put(*_)
}
- def 'Remove trustworthy cmhandles from untrustworthy cmhandles set'() {
- given: 'an event with COMPLETE trustlevel'
- def incomingEvent = testCloudEvent(TrustLevel.COMPLETE)
- and: 'transformed as a kafka record'
- def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', incomingEvent)
- consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('cmhandle1'))
- and: 'untrustworthy cmhandles set contains cmhandle1'
- 1 * mockUntrustworthyCmHandlesSet.contains(_) >> true
+ def 'Consume a trust level event without payload'() {
+ given: 'a consumer record with ce_id header but without payload'
+ def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', createTrustLevelEvent(null))
+ consumerRecord.headers().add('some_other_header_value', objectMapper.writeValueAsBytes('cmhandle1'))
when: 'the event is consumed'
objectUnderTest.heartbeatListener(consumerRecord)
- then: 'cmhandle removed from untrustworthy cmhandles set'
- 1 * mockUntrustworthyCmHandlesSet.remove(_) >> {
- args ->
- {
- args[0].equals('cmhandle1')
- }
- }
-
+ then: 'no cm handle has been stored in the map'
+ 0 * mockTrustLevelPerCmHandle.put(*_)
}
- def testCloudEvent(trustLevel) {
- return CloudEventBuilder.v1().withData(objectMapper.writeValueAsBytes(new DeviceTrustLevel(trustLevel)))
+ def createTrustLevelEvent(eventPayload) {
+ return CloudEventBuilder.v1().withData(objectMapper.writeValueAsBytes(eventPayload))
.withId("cmhandle1")
.withSource(URI.create('DMI'))
.withDataSchema(URI.create('test'))
- .withType('org.onap.cm.events.trustlevel-notification')
+ .withType('org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel')
.build()
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilterSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilterSpec.groovy
new file mode 100644
index 000000000..8f6621d24
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilterSpec.groovy
@@ -0,0 +1,41 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 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.
+ * 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.cps.ncmp.api.impl.trustlevel
+
+
+import spock.lang.Specification
+
+class TrustLevelFilterSpec extends Specification {
+
+ def targetTrustLevel = TrustLevel.COMPLETE
+
+ def trustLevelPerCmHandle = [ 'my completed cm handle': TrustLevel.COMPLETE, 'my untrusted cm handle': TrustLevel.NONE ]
+
+ def objectUnderTest = new TrustLevelFilter(targetTrustLevel, trustLevelPerCmHandle)
+
+ def 'Obtain cm handle ids by a given trust level value'() {
+ when: 'cm handles are retrieved'
+ def result = objectUnderTest.getAllCmHandleIdsByTargetTrustLevel()
+ then: 'the result only contains the completed cm handle'
+ assert result.size() == 1
+ assert result[0] == 'my completed cm handle'
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDogSpec.groovy
index af546b7f5..b6259bdf3 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDogSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDogSpec.groovy
@@ -20,7 +20,6 @@
package org.onap.cps.ncmp.api.impl.trustlevel.dmiavailability
-import com.hazelcast.map.IMap
import org.onap.cps.ncmp.api.impl.client.DmiRestClient
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
import spock.lang.Specification
@@ -28,7 +27,7 @@ import spock.lang.Specification
class DMiPluginWatchDogSpec extends Specification {
- def mockTrustLevelPerDmiPlugin = Mock(IMap<String, TrustLevel>)
+ def mockTrustLevelPerDmiPlugin = Mock(Map<String, TrustLevel>)
def mockDmiRestClient = Mock(DmiRestClient)
def objectUnderTest = new DMiPluginWatchDog(mockTrustLevelPerDmiPlugin, mockDmiRestClient)
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy
index f0e2d9f0b..100705ff5 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy
@@ -26,10 +26,11 @@ class CmHandleQueryConditionsSpec extends Specification {
def 'CmHandle query condition names.'() {
expect: '3 conditions with the correct names'
- assert CmHandleQueryConditions.ALL_CONDITION_NAMES.size() == 3
+ assert CmHandleQueryConditions.ALL_CONDITION_NAMES.size() == 4
assert CmHandleQueryConditions.ALL_CONDITION_NAMES.containsAll('hasAllProperties',
'hasAllModules',
- 'cmHandleWithCpsPath')
+ 'cmHandleWithCpsPath',
+ 'cmHandleWithTrustLevel')
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy
index 6c4575515..2b17e5d41 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy
@@ -32,7 +32,7 @@ import spock.lang.Specification
class DmiServiceUrlBuilderSpec extends Specification {
static YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('dmiServiceName',
- 'dmiDataServiceName', 'dmiModuleServiceName', new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id'))
+ 'dmiDataServiceName', 'dmiModuleServiceName', new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id'),'')
NcmpConfiguration.DmiProperties dmiProperties = new NcmpConfiguration.DmiProperties()
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy
index a58f22b95..ca0015e99 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy
@@ -47,7 +47,7 @@ class YangModelCmHandleSpec extends Specification {
.withOperationalDataStores(DataStoreSyncState.SYNCHRONIZED, 'some-sync-time').build()
ncmpServiceCmHandle.setCompositeState(compositeState)
when: 'it is converted to a yang model cm handle'
- def objectUnderTest = YangModelCmHandle.toYangModelCmHandle('', '', '', ncmpServiceCmHandle)
+ def objectUnderTest = YangModelCmHandle.toYangModelCmHandle('', '', '', ncmpServiceCmHandle,'')
then: 'the result has the right size'
assert objectUnderTest.dmiProperties.size() == 1
and: 'the DMI property in the result has the correct name and value'
@@ -63,7 +63,8 @@ class YangModelCmHandleSpec extends Specification {
def 'Resolve DMI service name: #scenario and #requiredService service require.'() {
given: 'a yang model cm handle'
- def objectUnderTest = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, dmiDataServiceName, dmiModelServiceName, new NcmpServiceCmHandle(cmHandleId: 'cm-handle-id-1'))
+ def objectUnderTest = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, dmiDataServiceName,
+ dmiModelServiceName, new NcmpServiceCmHandle(cmHandleId: 'cm-handle-id-1'),'')
expect:
assert objectUnderTest.resolveDmiServiceName(requiredService) == expectedService
where:
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy
index ffdd67265..a3a5efc74 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy
@@ -21,12 +21,15 @@
package org.onap.cps.ncmp.api.inventory
+import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
+
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
+import com.hazelcast.map.IMap
import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueriesImpl
import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState
@@ -37,8 +40,9 @@ import spock.lang.Specification
class CmHandleQueriesImplSpec extends Specification {
def cpsDataPersistenceService = Mock(CpsDataPersistenceService)
+ def trustLevelPerCmHandle = [ 'my completed cm handle': TrustLevel.COMPLETE, 'my untrusted cm handle': TrustLevel.NONE ]
- def objectUnderTest = new CmHandleQueriesImpl(cpsDataPersistenceService)
+ def objectUnderTest = new CmHandleQueriesImpl(cpsDataPersistenceService, trustLevelPerCmHandle)
@Shared
def static sampleDataNodes = [new DataNode()]
@@ -60,11 +64,21 @@ class CmHandleQueriesImplSpec extends Specification {
result.containsAll(expectedCmHandleIds)
result.size() == expectedCmHandleIds.size()
where: 'the following data is used'
- scenario | publicPropertyPairs || expectedCmHandleIds
- 'single property matches' | ['Contact' : 'newemailforstore@bookstore.com'] || ['PNFDemo', 'PNFDemo2', 'PNFDemo4']
- 'public property does not match' | ['wont_match' : 'wont_match'] || []
- '2 properties, only one match' | ['Contact' : 'newemailforstore@bookstore.com', 'Contact2': 'newemailforstore2@bookstore.com'] || ['PNFDemo4']
- '2 properties, no matches' | ['Contact' : 'newemailforstore@bookstore.com', 'Contact2': ''] || []
+ scenario | publicPropertyPairs || expectedCmHandleIds
+ 'single property matches' | [Contact: 'newemailforstore@bookstore.com'] || ['PNFDemo', 'PNFDemo2', 'PNFDemo4']
+ 'public property does not match' | [wont_match: 'wont_match'] || []
+ '2 properties, only one match' | [Contact: 'newemailforstore@bookstore.com', Contact2: 'newemailforstore2@bookstore.com'] || ['PNFDemo4']
+ '2 properties, no matches' | [Contact: 'newemailforstore@bookstore.com', Contact2: ''] || []
+ }
+
+ def 'Query cm handles on trust level'() {
+ given: 'query properties for trustlevel COMPLETE'
+ def trustLevelPropertyQueryPairs = ['trustLevel' : TrustLevel.COMPLETE.toString()]
+ when: 'the query is executed'
+ def result = objectUnderTest.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs)
+ then: 'the result only contains the completed cm handle'
+ assert result.size() == 1
+ assert result[0] == 'my completed cm handle'
}
def 'Query CmHandles using empty public properties query pair.'() {
@@ -153,7 +167,7 @@ class CmHandleQueriesImplSpec extends Specification {
cpsPath + '/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS)
>> Arrays.asList(cmHandleDataNode)
when: 'get cm handles by cps path is invoked'
- def result = objectUnderTest.queryCmHandleDataNodesByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS)
+ def result = objectUnderTest.queryCmHandleAncestorsByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS)
then: 'the returned result is a list of data nodes returned by cps data service'
assert result.contains(cmHandleDataNode)
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy
index e96105559..b547da7a1 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy
@@ -20,17 +20,24 @@
package org.onap.cps.ncmp.api.inventory.sync
+import org.onap.cps.spi.FetchDescendantsOption
+
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
+import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE
import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
import org.onap.cps.ncmp.api.impl.inventory.sync.ModuleSyncService
import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries
+import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
import org.onap.cps.spi.CascadeDeleteAllowed
import org.onap.cps.spi.exceptions.SchemaSetNotFoundException
import org.onap.cps.spi.model.ModuleReference
+import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Specification
class ModuleSyncServiceSpec extends Specification {
@@ -38,17 +45,23 @@ class ModuleSyncServiceSpec extends Specification {
def mockCpsModuleService = Mock(CpsModuleService)
def mockDmiModelOperations = Mock(DmiModelOperations)
def mockCpsAdminService = Mock(CpsAdminService)
+ def mockCmHandleQueries = Mock(CmHandleQueries)
+ def mockCpsDataService = Mock(CpsDataService)
+ def mockJsonObjectMapper = Mock(JsonObjectMapper)
- def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService, mockCpsAdminService)
+ def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService, mockCpsAdminService,
+ mockCmHandleQueries, mockCpsDataService, mockJsonObjectMapper)
def expectedDataspaceName = NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
def 'Sync model for a (new) cm handle with #scenario'() {
- given: 'a cm handle'
+ given: 'a cm handle having lock reason : MODULE_UPGRADE'
def ncmpServiceCmHandle = new NcmpServiceCmHandle()
+ ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder()
+ .withLockReason(MODULE_UPGRADE, 'new moduleSetTag: someModuleSetTag').build())
def dmiServiceName = 'some service name'
ncmpServiceCmHandle.cmHandleId = 'cmHandleId-1'
- def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '', '', ncmpServiceCmHandle)
+ def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '', '', ncmpServiceCmHandle,'someModuleSetTag')
and: 'DMI operations returns some module references'
def moduleReferences = [ new ModuleReference('module1','1'), new ModuleReference('module2','2') ]
mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences
@@ -56,11 +69,14 @@ class ModuleSyncServiceSpec extends Specification {
mockCpsModuleService.getYangResourceModuleReferences(expectedDataspaceName) >> toModuleReference(existingModuleResourcesInCps)
and: 'DMI-Plugin returns resource(s) for "new" module(s)'
mockDmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle, [new ModuleReference('module1', '1')]) >> newModuleNameContentToMap
+ and: 'empty data node list is returned by cps path a query'
+ mockCmHandleQueries.queryNcmpRegistryByCpsPath("//cm-handles[@module-set-tag='someModuleSetTag']",
+ FetchDescendantsOption.OMIT_DESCENDANTS) >> Collections.emptyList()
when: 'module sync is triggered'
mockCpsModuleService.identifyNewModuleReferences(moduleReferences) >> toModuleReference(identifiedNewModuleReferences)
- objectUnderTest.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle)
+ objectUnderTest.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle)
then: 'create schema set from module is invoked with correct parameters'
- 1 * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', newModuleNameContentToMap, moduleReferences)
+ 1 * mockCpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', newModuleNameContentToMap, moduleReferences)
and: 'anchor is created with the correct parameters'
1 * mockCpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', 'cmHandleId-1')
where: 'the following parameters are used'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy
index 231e34a92..a11f14838 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy
@@ -69,8 +69,8 @@ class ModuleSyncTasksSpec extends Specification {
1 * mockModuleSyncService.deleteSchemaSetIfExists('cm-handle-1')
1 * mockModuleSyncService.deleteSchemaSetIfExists('cm-handle-2')
and: 'module sync service is invoked for each cm handle'
- 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-1') }
- 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-2') }
+ 1 * mockModuleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-1') }
+ 1 * mockModuleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-2') }
and: 'the state handler is called for the both cm handles'
1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >> { args ->
assertBatch(args, ['cm-handle-1', 'cm-handle-2'], CmHandleState.READY)
@@ -86,7 +86,7 @@ class ModuleSyncTasksSpec extends Specification {
def cmHandleState = new CompositeState(cmHandleState: CmHandleState.ADVISED)
1 * mockInventoryPersistence.getCmHandleState('cm-handle') >> cmHandleState
and: 'module sync service attempts to sync the cm handle and throws an exception'
- 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(*_) >> { throw new Exception('some exception') }
+ 1 * mockModuleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(*_) >> { throw new Exception('some exception') }
when: 'module sync is executed'
objectUnderTest.performModuleSync([cmHandle], batchCount)
then: 'update lock reason, details and attempts is invoked'
@@ -112,7 +112,7 @@ class ModuleSyncTasksSpec extends Specification {
moduleSyncStartedOnCmHandles.put('cm-handle-1', 'started')
moduleSyncStartedOnCmHandles.put('cm-handle-2', 'started')
and: 'sync utils retry locked cm handle returns #isReadyForRetry'
- mockSyncUtils.needsModuleSyncRetry(lockedState) >>> isReadyForRetry
+ mockSyncUtils.needsModuleSyncRetryOrUpgrade(lockedState) >>> isReadyForRetry
when: 'resetting failed cm handles'
objectUnderTest.resetFailedCmHandles([yangModelCmHandle1, yangModelCmHandle2])
then: 'updated to state "ADVISED" from "READY" is called as often as there are cm handles ready for retry'
@@ -135,7 +135,7 @@ class ModuleSyncTasksSpec extends Specification {
when: 'module sync poll is executed'
objectUnderTest.performModuleSync([cmHandle1], batchCount)
then: 'module sync service is invoked for cm handle'
- 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-1') }
+ 1 * mockModuleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args, 'cm-handle-1') }
and: 'the entry for other cm handle is still in the progress map'
assert moduleSyncStartedOnCmHandles.get('other-cm-handle') != null
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy
index d85686aa3..390e88b3d 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy
@@ -111,7 +111,7 @@ class ModuleSyncWatchdogSpec extends Specification {
def 'Reset failed cm handles.'() {
given: 'sync utilities returns failed cm handles'
def failedCmHandles = [new YangModelCmHandle()]
- mockSyncUtils.getModuleSyncFailedCmHandles() >> failedCmHandles
+ mockSyncUtils.getCmHandlesThatFailedModelSyncOrUpgrade() >> failedCmHandles
when: 'reset failed cm handles is started'
objectUnderTest.resetPreviouslyFailedCmHandles()
then: 'it is delegated to the module sync task (service)'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy
index 8fdbb6f53..00d14cd2a 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy
@@ -115,11 +115,11 @@ class SyncUtilsSpec extends Specification{
def 'Get all locked Cm-Handle where Lock Reason is MODULE_SYNC_FAILED cm handle #scenario'() {
given: 'the cps (persistence service) returns a collection of data nodes'
- mockCmHandleQueries.queryCmHandleDataNodesByCpsPath(
- '//lock-reason[@reason="MODULE_SYNC_FAILED"]',
+ mockCmHandleQueries.queryCmHandleAncestorsByCpsPath(
+ '//lock-reason[@reason="MODULE_SYNC_FAILED" or @reason="MODULE_UPGRADE"]',
FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [dataNode]
when: 'get locked Misbehaving cm handle is called'
- def result = objectUnderTest.getModuleSyncFailedCmHandles()
+ def result = objectUnderTest.getCmHandlesThatFailedModelSyncOrUpgrade()
then: 'the returned cm handle collection is the correct size'
result.size() == 1
and: 'the correct cm handle is returned'
@@ -133,7 +133,7 @@ class SyncUtilsSpec extends Specification{
lastUpdatedTime = neverUpdatedBefore
}
when: 'checking to see if cm handle is ready for retry'
- def result = objectUnderTest.needsModuleSyncRetry(new CompositeStateBuilder()
+ def result = objectUnderTest.needsModuleSyncRetryOrUpgrade(new CompositeStateBuilder()
.withLockReason(MODULE_SYNC_FAILED, lockDetails)
.withLastUpdatedTime(lastUpdatedTime).build())
then: 'retry is only attempted when expected'
@@ -151,16 +151,18 @@ class SyncUtilsSpec extends Specification{
def 'Retry Locked Cm-Handle with other lock reasons (category) #lockReasonCategory'() {
when: 'checking to see if cm handle is ready for retry'
- def result = objectUnderTest.needsModuleSyncRetry(new CompositeStateBuilder()
+ def result = objectUnderTest.needsModuleSyncRetryOrUpgrade(new CompositeStateBuilder()
.withLockReason(lockReasonCategory, 'some details')
.withLastUpdatedTime(nowAsString).build())
- then: 'retry attempt is never triggered'
- assert result == false
+ then: 'verify retry attempts'
+ assert result == retryAttempt
and: 'logs contain related information'
- def logs = loggingListAppender.list.toString()
- assert logs.contains('Locked for other reason')
+ def logs = loggingListAppender.list.toString()
+ assert logs.contains(logReason)
where: 'the following lock reasons occurred'
- lockReasonCategory << [MODULE_UPGRADE, MODULE_UPGRADE_FAILED]
+ scenario | lockReasonCategory || logReason | retryAttempt
+ 'module upgrade' | MODULE_UPGRADE || 'Locked for module upgrade.' | true
+ 'module sync failed' | MODULE_SYNC_FAILED || 'First Attempt:' | false
}
def 'Get a Cm-Handle where #scenario'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy
index dba29343e..d76f91223 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2022 Bell Canada
+ * Modifications Copyright (C) 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.
@@ -20,10 +21,11 @@
package org.onap.cps.ncmp.api.models
-import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
+
import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
import spock.lang.Specification
-
import java.util.stream.Collectors
class CmHandleRegistrationResponseSpec extends Specification {
@@ -37,7 +39,7 @@ class CmHandleRegistrationResponseSpec extends Specification {
assert it.status == Status.SUCCESS
}
and: 'error details are null'
- cmHandleRegistrationResponse.registrationError == null
+ cmHandleRegistrationResponse.ncmpResponseStatus == null
cmHandleRegistrationResponse.errorText == null
}
@@ -47,33 +49,29 @@ class CmHandleRegistrationResponseSpec extends Specification {
CmHandleRegistrationResponse.createFailureResponse('cmHandle', new Exception('unexpected error'))
then: 'the response is created with expected value'
with(cmHandleRegistrationResponse) {
- assert it.registrationError == RegistrationError.UNKNOWN_ERROR
+ assert it.ncmpResponseStatus == UNKNOWN_ERROR
assert it.cmHandle == 'cmHandle'
assert errorText == 'unexpected error'
}
}
- def 'Failed cm-handle Registration Response: for #scenario'() {
- when: 'cm-handle failure response is created for #scenario'
- def cmHandleRegistrationResponse =
- CmHandleRegistrationResponse.createFailureResponse(cmHandleId, registrationError)
+ def 'Failed cm-handle Registration Response'() {
+ when: 'cm-handle failure response is created'
+ def cmHandleRegistrationResponse =
+ CmHandleRegistrationResponse.createFailureResponse('cmHandle', CM_HANDLE_ALREADY_EXIST)
then: 'the response is created with expected value'
- with(cmHandleRegistrationResponse) {
- assert it.registrationError == registrationError
- assert it.cmHandle == cmHandleId
- assert it.status == Status.FAILURE
- assert errorText == registrationError.errorText
- }
- where:
- scenario | cmHandleId | registrationError
- 'cm-handle already exists' | 'cmHandle' | RegistrationError.CM_HANDLE_ALREADY_EXIST
- 'cm-handle id is invalid' | 'cm handle' | RegistrationError.CM_HANDLE_INVALID_ID
+ with(cmHandleRegistrationResponse) {
+ assert it.ncmpResponseStatus == CM_HANDLE_ALREADY_EXIST
+ assert it.cmHandle == 'cmHandle'
+ assert it.status == Status.FAILURE
+ assert errorText == CM_HANDLE_ALREADY_EXIST.message
+ }
}
def 'Failed cm-handle Registration with multiple responses.'() {
when: 'cm-handle failure response is created for 2 xpaths'
def cmHandleRegistrationResponses =
- CmHandleRegistrationResponse.createFailureResponses(["somePathWithId[@id='123']","somePathWithId[@id='456']"], RegistrationError.CM_HANDLE_ALREADY_EXIST)
+ CmHandleRegistrationResponse.createFailureResponses(["somePathWithId[@id='123']","somePathWithId[@id='456']"], CM_HANDLE_ALREADY_EXIST)
then: 'the response has the correct cm handle ids'
assert cmHandleRegistrationResponses.size() == 2
assert cmHandleRegistrationResponses.stream().map(it -> it.cmHandle).collect(Collectors.toList())
@@ -83,12 +81,9 @@ class CmHandleRegistrationResponseSpec extends Specification {
def 'Failed cm-handle Registration with multiple responses with an unexpected xpath.'() {
when: 'cm-handle failure response is created for one valid and one unexpected xpath'
def cmHandleRegistrationResponses =
- CmHandleRegistrationResponse.createFailureResponses(["somePathWithId[@id='123']","valid/xpath/without-id[@key='123']"], RegistrationError.CM_HANDLE_ALREADY_EXIST)
+ CmHandleRegistrationResponse.createFailureResponses(["somePathWithId[@id='123']","valid/xpath/without-id[@key='123']"], CM_HANDLE_ALREADY_EXIST)
then: 'the response has only one entry'
assert cmHandleRegistrationResponses.size() == 1
}
-
-
-
}
diff --git a/cps-parent/pom.xml b/cps-parent/pom.xml
index 41215567c..37c9ad3f7 100755
--- a/cps-parent/pom.xml
+++ b/cps-parent/pom.xml
@@ -32,7 +32,7 @@
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
diff --git a/cps-path-parser/pom.xml b/cps-path-parser/pom.xml
index 8ce3fa5b2..4fc7d405d 100644
--- a/cps-path-parser/pom.xml
+++ b/cps-path-parser/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-rest/pom.xml b/cps-rest/pom.xml
index cd5bc0d36..f99e48f11 100755
--- a/cps-rest/pom.xml
+++ b/cps-rest/pom.xml
@@ -28,7 +28,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
@@ -39,6 +39,7 @@
<groupId>${project.groupId}</groupId>
<artifactId>cps-service</artifactId>
</dependency>
+ <!-- S P R I N G D E P E N D E N C I E S -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@@ -65,6 +66,15 @@
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
+ <!-- A L P H A B E T I C A L D E P E N D E N C I E S -->
+ <dependency>
+ <groupId>jakarta.validation</groupId>
+ <artifactId>jakarta.validation-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.gsonfire</groupId>
+ <artifactId>gson-fire</artifactId>
+ </dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
@@ -122,14 +132,6 @@
</exclusion>
</exclusions>
</dependency>
- <dependency>
- <groupId>jakarta.validation</groupId>
- <artifactId>jakarta.validation-api</artifactId>
- </dependency>
- <dependency>
- <groupId>io.gsonfire</groupId>
- <artifactId>gson-fire</artifactId>
- </dependency>
</dependencies>
<build>
diff --git a/cps-ri/pom.xml b/cps-ri/pom.xml
index f8fd730a1..63a6ab21c 100644
--- a/cps-ri/pom.xml
+++ b/cps-ri/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java
index ca88a4da2..0d77530b3 100755
--- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java
@@ -46,7 +46,6 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
-import org.onap.cps.spi.CpsAdminPersistenceService;
import org.onap.cps.spi.CpsModulePersistenceService;
import org.onap.cps.spi.entities.DataspaceEntity;
import org.onap.cps.spi.entities.SchemaSetEntity;
@@ -89,8 +88,6 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
private final DataspaceRepository dataspaceRepository;
- private final CpsAdminPersistenceService cpsAdminPersistenceService;
-
private final ModuleReferenceRepository moduleReferenceRepository;
@Override
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java
index b8503a7fe..19646c523 100755
--- a/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java
@@ -70,13 +70,25 @@ public interface AnchorRepository extends JpaRepository<AnchorEntity, Long> {
Integer countByDataspace(DataspaceEntity dataspaceEntity);
- @Query(value = "SELECT anchor.* FROM yang_resource\n"
- + "JOIN schema_set_yang_resources ON schema_set_yang_resources.yang_resource_id = yang_resource.id\n"
- + "JOIN schema_set ON schema_set.id = schema_set_yang_resources.schema_set_id\n"
- + "JOIN anchor ON anchor.schema_set_id = schema_set.id\n"
- + "WHERE schema_set.dataspace_id = :dataspaceId AND module_name = ANY (:moduleNames)\n"
- + "GROUP BY anchor.id, anchor.name, anchor.dataspace_id, anchor.schema_set_id\n"
- + "HAVING COUNT(DISTINCT module_name) = :sizeOfModuleNames", nativeQuery = true)
+ @Query(value = """
+ SELECT
+ anchor.*
+ FROM
+ yang_resource
+ JOIN schema_set_yang_resources ON schema_set_yang_resources.yang_resource_id = yang_resource.id
+ JOIN schema_set ON schema_set.id = schema_set_yang_resources.schema_set_id
+ JOIN anchor ON anchor.schema_set_id = schema_set.id
+ WHERE
+ schema_set.dataspace_id = :dataspaceId
+ AND module_name = ANY ( :moduleNames )
+ GROUP BY
+ anchor.id,
+ anchor.name,
+ anchor.dataspace_id,
+ anchor.schema_set_id
+ HAVING
+ COUNT(DISTINCT module_name) = :sizeOfModuleNames
+ """, nativeQuery = true)
Collection<AnchorEntity> getAnchorsByDataspaceIdAndModuleNames(@Param("dataspaceId") int dataspaceId,
@Param("moduleNames") String[] moduleNames,
@Param("sizeOfModuleNames") int sizeOfModuleNames);
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java
index df21ccc52..e83379633 100644
--- a/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java
@@ -41,56 +41,65 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity
return findAllByChecksumIn(checksums.toArray(new String[0]));
}
- @Query(value = "SELECT DISTINCT\n"
- + "yang_resource.module_name AS module_name,\n"
- + "yang_resource.revision AS revision\n"
- + "FROM\n"
- + "dataspace\n"
- + "JOIN schema_set ON schema_set.dataspace_id = dataspace.id\n"
- + "JOIN schema_set_yang_resources ON schema_set_yang_resources.schema_set_id = "
- + "schema_set.id\n"
- + "JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id\n"
- + "WHERE\n"
- + "dataspace.name = :dataspaceName", nativeQuery = true)
+ @Query(value = """
+ SELECT DISTINCT
+ yang_resource.module_name AS module_name,
+ yang_resource.revision AS revision
+ FROM
+ dataspace
+ JOIN schema_set ON schema_set.dataspace_id = dataspace.id
+ JOIN schema_set_yang_resources ON schema_set_yang_resources.schema_set_id = schema_set.id
+ JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id
+ WHERE
+ dataspace.name = :dataspaceName
+ """, nativeQuery = true)
Set<YangResourceModuleReference> findAllModuleReferencesByDataspace(@Param("dataspaceName") String dataspaceName);
- @Query(value = "SELECT DISTINCT\n"
- + "yang_resource.module_Name AS module_name,\n"
- + "yang_resource.revision AS revision\n"
- + "FROM\n"
- + "dataspace\n"
- + "JOIN anchor ON anchor.dataspace_id = dataspace.id\n"
- + "JOIN schema_set ON schema_set.id = anchor.schema_set_id\n"
- + "JOIN schema_set_yang_resources ON schema_set_yang_resources.schema_set_id = "
- + "schema_set.id\n"
- + "JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id\n"
- + "WHERE\n"
- + "dataspace.name = :dataspaceName AND\n"
- + "anchor.name =:anchorName", nativeQuery = true)
+ @Query(value = """
+ SELECT DISTINCT
+ yang_resource.module_name AS module_name,
+ yang_resource.revision AS revision
+ FROM
+ dataspace
+ JOIN anchor ON anchor.dataspace_id = dataspace.id
+ JOIN schema_set ON schema_set.id = anchor.schema_set_id
+ JOIN schema_set_yang_resources ON schema_set_yang_resources.schema_set_id = schema_set.id
+ JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id
+ WHERE
+ dataspace.name = :dataspaceName
+ AND anchor.name = :anchorName
+ """, nativeQuery = true)
Set<YangResourceModuleReference> findAllModuleReferencesByDataspaceAndAnchor(
@Param("dataspaceName") String dataspaceName, @Param("anchorName") String anchorName);
- @Query(value = "SELECT DISTINCT yang_resource.*\n"
- + "FROM dataspace\n"
- + "JOIN anchor ON anchor.dataspace_id = dataspace.id\n"
- + "JOIN schema_set ON schema_set.id = anchor.schema_set_id\n"
- + "JOIN schema_set_yang_resources ON schema_set_yang_resources.schema_set_id = schema_set.id\n"
- + "JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id\n"
- + "WHERE dataspace.name = :dataspaceName "
- + "AND anchor.name =:anchorName", nativeQuery = true)
+ @Query(value = """
+ SELECT DISTINCT
+ yang_resource.*
+ FROM
+ dataspace
+ JOIN anchor ON anchor.dataspace_id = dataspace.id
+ JOIN schema_set ON schema_set.id = anchor.schema_set_id
+ JOIN schema_set_yang_resources ON schema_set_yang_resources.schema_set_id = schema_set.id
+ JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id
+ WHERE
+ dataspace.name = :dataspaceName
+ AND anchor.name = :anchorName
+ """, nativeQuery = true)
Set<YangResourceEntity> findAllModuleDefinitionsByDataspaceAndAnchor(
@Param("dataspaceName") String dataspaceName, @Param("anchorName") String anchorName);
- @Query(value = "SELECT DISTINCT\n"
- + "yang_resource.*\n"
- + "FROM\n"
- + "dataspace\n"
- + "JOIN schema_set ON schema_set.dataspace_id = dataspace.id\n"
- + "JOIN schema_set_yang_resources ON schema_set_yang_resources.schema_set_id = "
- + "schema_set.id\n"
- + "JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id\n"
- + "WHERE\n"
- + "dataspace.name = :dataspaceName and yang_resource.module_Name = ANY (:moduleNames)", nativeQuery = true)
+ @Query(value = """
+ SELECT DISTINCT
+ yang_resource.*
+ FROM
+ dataspace
+ JOIN schema_set ON schema_set.dataspace_id = dataspace.id
+ JOIN schema_set_yang_resources ON schema_set_yang_resources.schema_set_id = schema_set.id
+ JOIN yang_resource ON yang_resource.id = schema_set_yang_resources.yang_resource_id
+ WHERE
+ dataspace.name = :dataspaceName
+ AND yang_resource.module_name = ANY ( :moduleNames )
+ """, nativeQuery = true)
Set<YangResourceModuleReference> findAllModuleReferencesByDataspaceAndModuleNames(
@Param("dataspaceName") String dataspaceName, @Param("moduleNames") String[] moduleNames);
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy
index 52651c6b1..9696b28cd 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy
@@ -69,7 +69,7 @@ class CpsModulePersistenceServiceSpec extends Specification {
def setup() {
objectUnderTest = new CpsModulePersistenceServiceImpl(yangResourceRepositoryMock, schemaSetRepositoryMock,
- dataspaceRepositoryMock, cpsAdminPersistenceServiceMock, moduleReferenceRepositoryMock)
+ dataspaceRepositoryMock, moduleReferenceRepositoryMock)
}
def 'Store schema set error scenario: #scenario.'() {
diff --git a/cps-service/pom.xml b/cps-service/pom.xml
index 4a3c90e41..0787409ca 100644
--- a/cps-service/pom.xml
+++ b/cps-service/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
@@ -37,6 +37,26 @@
<dependencies>
<dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-messaging</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-cache</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-aop</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.kafka</groupId>
+ <artifactId>spring-kafka</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
@@ -55,6 +75,10 @@
<artifactId>micrometer-core</artifactId>
</dependency>
<dependency>
+ <groupId>jakarta.validation</groupId>
+ <artifactId>jakarta.validation-api</artifactId>
+ </dependency>
+ <dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
</dependency>
@@ -104,33 +128,12 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-messaging</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-cache</artifactId>
- <version>3.0.0</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-aop</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-validation</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.kafka</groupId>
- <artifactId>spring-kafka</artifactId>
- </dependency>
+ <!-- T E S T D E P E N D E N C I E S -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
- <!-- T E S T D E P E N D E N C I E S -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
@@ -176,9 +179,5 @@
<artifactId>aspectjrt</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>jakarta.validation</groupId>
- <artifactId>jakarta.validation-api</artifactId>
- </dependency>
</dependencies>
</project>
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
index 5ff08c9ac..e8c3e7775 100644
--- a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
+++ b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
@@ -47,13 +47,13 @@ public interface CpsModuleService {
Map<String, String> yangResourcesNameToContentMap);
/**
- * Create a schema set from new modules and existing modules.
+ * Create or upgrade a schema set from new modules and existing modules or only existing modules.
* @param dataspaceName Dataspace name
* @param schemaSetName schema set name
* @param newModuleNameToContentMap YANG resources map where key is a module name and value is content
* @param allModuleReferences All YANG resource module references
*/
- void createSchemaSetFromModules(String dataspaceName, String schemaSetName,
+ void createOrUpgradeSchemaSetFromModules(String dataspaceName, String schemaSetName,
Map<String, String> newModuleNameToContentMap,
Collection<ModuleReference> allModuleReferences);
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
index 7db87e87e..1d68450f8 100755
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
@@ -31,6 +31,7 @@ import static org.onap.cps.notification.Operation.UPDATE;
import io.micrometer.core.annotation.Timed;
import java.io.Serializable;
import java.time.OffsetDateTime;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
@@ -321,28 +322,12 @@ public class CpsDataServiceImpl implements CpsDataService {
processDataUpdatedEventAsync(anchor, listNodeXpath, DELETE, observedTimestamp);
}
- private DataNode buildDataNode(final Anchor anchor, final String parentNodeXpath, final String nodeData,
- final ContentType contentType) {
- final SchemaContext schemaContext = getSchemaContext(anchor);
-
- if (ROOT_NODE_XPATH.equals(parentNodeXpath)) {
- final ContainerNode containerNode = timedYangParser.parseData(contentType, nodeData, schemaContext);
- return new DataNodeBuilder().withContainerNode(containerNode).build();
- }
-
- final ContainerNode containerNode =
- timedYangParser.parseData(contentType, nodeData, schemaContext, parentNodeXpath);
-
- return new DataNodeBuilder()
- .withParentNodeXpath(parentNodeXpath)
- .withContainerNode(containerNode)
- .build();
- }
-
private Collection<DataNode> buildDataNodes(final Anchor anchor, final Map<String, String> nodesJsonData) {
- return nodesJsonData.entrySet().stream().map(nodeJsonData ->
- buildDataNode(anchor, nodeJsonData.getKey(),
- nodeJsonData.getValue(), ContentType.JSON)).collect(Collectors.toList());
+ final Collection<DataNode> dataNodes = new ArrayList<>();
+ for (final Map.Entry<String, String> nodeJsonData : nodesJsonData.entrySet()) {
+ dataNodes.addAll(buildDataNodes(anchor, nodeJsonData.getKey(), nodeJsonData.getValue(), ContentType.JSON));
+ }
+ return dataNodes;
}
private Collection<DataNode> buildDataNodes(final Anchor anchor, final String parentNodeXpath,
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
index 7d9c472e6..444c895fb 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
@@ -66,7 +66,7 @@ public class CpsModuleServiceImpl implements CpsModuleService {
}
@Override
- public void createSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+ public void createOrUpgradeSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
final Map<String, String> newModuleNameToContentMap,
final Collection<ModuleReference> allModuleReferences) {
cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
index b4ac7a68f..e1d15d68a 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
@@ -307,15 +307,16 @@ class CpsDataServiceImplSpec extends Specification {
objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, jsonData, observedTimestamp)
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
- { dataNode -> dataNode.xpath[0] == expectedNodeXpath })
+ { dataNode -> dataNode.xpath == expectedNodeXpath})
and: 'data updated event is sent to notification service'
1 * mockNotificationService.processDataUpdatedEvent(anchor, parentNodeXpath, Operation.UPDATE, observedTimestamp)
and: 'the CpsValidator is called on the dataspaceName and AnchorName'
1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
where: 'following parameters were used'
- scenario | parentNodeXpath | jsonData || expectedNodeXpath
- 'top level node' | '/' | '{"test-tree": {"branch": []}}' || '/test-tree'
- 'level 2 node' | '/test-tree' | '{"branch": [{"name":"Name"}]}' || '/test-tree/branch[@name=\'Name\']'
+ scenario | parentNodeXpath | jsonData || expectedNodeXpath
+ 'top level node' | '/' | '{"test-tree": {"branch": []}}' || ['/test-tree']
+ 'level 2 node' | '/test-tree' | '{"branch": [{"name":"Name"}]}' || ['/test-tree/branch[@name=\'Name\']']
+ 'json list' | '/test-tree' | '{"branch": [{"name":"Name1"}, {"name":"Name2"}]}' || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"]
}
def 'Replace data node using multiple data nodes: #scenario.'() {
@@ -327,14 +328,16 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
{ dataNode -> dataNode.xpath == expectedNodeXpath})
and: 'data updated event is sent to notification service'
- 1 * mockNotificationService.processDataUpdatedEvent(anchor, nodesJsonData.keySet()[0], Operation.UPDATE, observedTimestamp)
- 1 * mockNotificationService.processDataUpdatedEvent(anchor, nodesJsonData.keySet()[1], Operation.UPDATE, observedTimestamp)
+ nodesJsonData.keySet().each {
+ 1 * mockNotificationService.processDataUpdatedEvent(anchor, it, Operation.UPDATE, observedTimestamp)
+ }
and: 'the CpsValidator is called on the dataspaceName and AnchorName'
1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
where: 'following parameters were used'
scenario | nodesJsonData || expectedNodeXpath
'top level node' | ['/' : '{"test-tree": {"branch": []}}', '/test-tree' : '{"branch": [{"name":"Name"}]}'] || ["/test-tree", "/test-tree/branch[@name='Name']"]
'level 2 node' | ['/test-tree' : '{"branch": [{"name":"Name"}]}', '/test-tree/branch[@name=\'Name\']':'{"nest":{"name":"nestName"}}'] || ["/test-tree/branch[@name='Name']", "/test-tree/branch[@name='Name']/nest"]
+ 'json list' | ['/test-tree' : '{"branch": [{"name":"Name1"}, {"name":"Name2"}]}'] || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"]
}
def 'Replace data node with concurrency exception in persistence layer.'() {
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
index a794c58fc..61f67416d 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
@@ -65,7 +65,7 @@ class CpsModuleServiceImplSpec extends Specification {
def moduleReferenceForExistingModule = new ModuleReference('test', '2021-10-12','test.org')
def listOfExistingModulesModuleReference = [moduleReferenceForExistingModule]
when: 'create schema set from modules method is invoked'
- objectUnderTest.createSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference)
+ objectUnderTest.createOrUpgradeSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference)
then: 'processing is delegated to persistence service'
1 * mockCpsModulePersistenceService.storeSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference)
and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml
index 583268a50..97f1bdc03 100644
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml
+++ b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml
@@ -22,7 +22,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>dmi-plugin-demo-and-csit-stub</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
</parent>
<artifactId>dmi-plugin-demo-and-csit-stub-app</artifactId>
@@ -106,7 +106,7 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
- <version>11.0.14</version>
+ <version>11.0.16</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml
index 8daddba3b..3a46e4391 100644
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml
+++ b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>dmi-plugin-demo-and-csit-stub</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
</parent>
<artifactId>dmi-plugin-demo-and-csit-stub-service</artifactId>
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java
index 987436feb..3f9731d72 100644
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java
+++ b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java
@@ -20,6 +20,8 @@
package org.onap.cps.ncmp.dmi.rest.stub.controller;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUCCESS;
+
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.cloudevents.CloudEvent;
@@ -28,12 +30,10 @@ import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
-import org.onap.cps.ncmp.api.NcmpEventResponseCode;
import org.onap.cps.ncmp.api.impl.utils.EventDateTimeFormatter;
import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.CmHandle;
import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.DataOperationRequest;
@@ -161,9 +161,9 @@ public class DmiRestStubController {
private DataOperationEvent getDataOperationEvent(final DataOperationRequest dataOperationRequest) {
final Response response = new Response();
response.setOperationId(dataOperationRequest.getOperationId());
- response.setStatusCode(NcmpEventResponseCode.SUCCESS.getStatusCode());
- response.setStatusMessage(NcmpEventResponseCode.SUCCESS.getStatusMessage());
- response.setIds(dataOperationRequest.getCmHandles().stream().map(CmHandle::getId).collect(Collectors.toList()));
+ response.setStatusCode(SUCCESS.getCode());
+ response.setStatusMessage(SUCCESS.getMessage());
+ response.setIds(dataOperationRequest.getCmHandles().stream().map(CmHandle::getId).toList());
response.setResourceIdentifier(dataOperationRequest.getResourceIdentifier());
response.setOptions(dataOperationRequest.getOptions());
final String ietfNetworkTopologySample = ResourceFileReaderUtil
@@ -176,7 +176,7 @@ public class DmiRestStubController {
} catch (final ParseException parseException) {
log.error("Unable to parse event result as json object. cause : {}", parseException.getMessage());
}
- final List<Response> responseList = new ArrayList<>();
+ final List<Response> responseList = new ArrayList<>(1);
responseList.add(response);
final Data data = new Data();
data.setResponses(responseList);
diff --git a/dmi-plugin-demo-and-csit-stub/pom.xml b/dmi-plugin-demo-and-csit-stub/pom.xml
index 430476985..88f11c797 100644
--- a/dmi-plugin-demo-and-csit-stub/pom.xml
+++ b/dmi-plugin-demo-and-csit-stub/pom.xml
@@ -22,7 +22,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml
index bb286fde2..2607385de 100644
--- a/docker-compose/docker-compose.yml
+++ b/docker-compose/docker-compose.yml
@@ -38,6 +38,7 @@ services:
ports:
- ${CPS_CORE_PORT:-8883}:8080
- ${CPS_CORE_MANAGEMENT_PORT:-8887}:8081
+ - ${CPS_CORE_DEBUG_PORT:-5005}:5005
environment:
CPS_USERNAME: ${CPS_CORE_USERNAME:-cpsuser}
CPS_PASSWORD: ${CPS_CORE_PASSWORD:-cpsr0cks!}
@@ -52,6 +53,7 @@ services:
NOTIFICATION_DATASPACE_FILTER_PATTERNS: '.*'
NCMP_TIMERS_ADVISED-MODULES-SYNC_SLEEP-TIME-MS: ${ADVISED_MODULES_SYNC_SLEEP_TIME_MS:-30000}
NCMP_TIMERS_CM-HANDLE-DATA-SYNC_SLEEP-TIME-MS: ${CMHANDLE_DATA_SYNC_SLEEP_TIME_MS:-30000}
+ JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
restart: unless-stopped
depends_on:
- dbpostgresql
diff --git a/docs/cps-ncmp-message-status-codes.rst b/docs/cps-ncmp-message-status-codes.rst
index 1b74153d7..20a5ae3c1 100644
--- a/docs/cps-ncmp-message-status-codes.rst
+++ b/docs/cps-ncmp-message-status-codes.rst
@@ -10,15 +10,15 @@ CPS-NCMP Message Status Codes
#############################
+-----------------+------------------------------------------------------+-----------------------------------+
- | Status Code | Status Message | Feature |
+ | Status Code | Status Message | Feature(s) |
+=================+======================================================+===================================+
| 0 | Successfully applied changes | Data Operation |
+-----------------+------------------------------------------------------+-----------------------------------+
| 1 | successfully applied subscription | CM Data Notification Subscription |
+-----------------+------------------------------------------------------+-----------------------------------+
- | 100 | cm handle id(s) is(are) not found | Data Operation |
+ | 100 | cm handle id(s) is(are) not found | Data Operation, Inventory |
+-----------------+------------------------------------------------------+-----------------------------------+
- | 101 | cm handle id(s) is(are) in non ready state | Data Operation |
+ | 101 | cm handle(s) not ready | Data Operation |
+-----------------+------------------------------------------------------+-----------------------------------+
| 102 | dmi plugin service is not responding | Data Operation |
+-----------------+------------------------------------------------------+-----------------------------------+
@@ -32,6 +32,12 @@ CPS-NCMP Message Status Codes
+-----------------+------------------------------------------------------+-----------------------------------+
| 107 | southbound system is busy | Data Operation |
+-----------------+------------------------------------------------------+-----------------------------------+
+ | 108 | Unknown error | Inventory |
+ +-----------------+------------------------------------------------------+-----------------------------------+
+ | 109 | cm-handle already exists | Inventory |
+ +-----------------+------------------------------------------------------+-----------------------------------+
+ | 110 | cm-handle has an invalid character(s) in id | Inventory |
+ +-----------------+------------------------------------------------------+-----------------------------------+
.. note::
diff --git a/docs/cps-path.rst b/docs/cps-path.rst
index 661178954..eb203d891 100644
--- a/docs/cps-path.rst
+++ b/docs/cps-path.rst
@@ -247,7 +247,7 @@ leaf-conditions
- Using comparative operators with string values will lead to an error at runtime. This error can't be validated earlier as the datatype is unknown until the execution phase.
- The key should be supplied with correct data type for it to be queried from DB. In the last example above the attribute code is of type
Integer so the cps query will not work if the value is passed as string.
- eg: ``//categories[@code="1"]`` or ``//categories[@code='1']`` will not work because the key attribute code is treated a string.
+ e.g.: ``//categories[@code="1"]`` or ``//categories[@code='1']`` will not work because the key attribute code is treated a string.
**Notes**
- For performance reasons it does not make sense to query using key leaf as attribute. If the key value is known it is better to execute a get request with the complete xpath.
@@ -260,7 +260,7 @@ The text()-condition can be added to any CPS path query.
**Syntax**: ``<cps-path> ( '/' <leaf-name> '[text()=' <string-value> ']' )?``
- ``cps-path``: Any CPS path query.
- ``leaf-name``: The name of the leaf or leaf-list which value needs to be compared.
- - ``string-value``: The required value of the leaf or leaf-list element as a string wrapped in quotation marks (U+0022) or apostrophes (U+0027). This wil still match integer values.
+ - ``string-value``: The required value of the leaf or leaf-list element as a string wrapped in quotation marks (U+0022) or apostrophes (U+0027). This will still match integer values.
**Examples**
- ``//book/label[text()="classic"]``
diff --git a/docs/cps-stubs.rst b/docs/cps-stubs.rst
new file mode 100644
index 000000000..00577eb0d
--- /dev/null
+++ b/docs/cps-stubs.rst
@@ -0,0 +1,120 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. Copyright (C) 2023 Nordix Foundation
+
+.. DO NOT CHANGE THIS LABEL FOR RELEASE NOTES - EVEN THOUGH IT GIVES A WARNING
+
+.. _cpsStubs:
+
+
+CPS Stubs
+#########
+
+.. toctree::
+ :maxdepth: 1
+
+NCMP Stubs
+==========
+
+The CPS NCMP stub module provides the capability to create dynamic and customizable stubs, offering control over the responses generated for each endpoint. This capability ensures that client interactions adhere to a specified NCMP interface, enabling comprehensive testing and validation of your applications.
+
+The NCMP stub RestController is an extended implementation of the actual NCMP interface. It can be deployed as part of the application JAR or within a SpringBootTest JUnit environment, allowing you to define dynamic responses for each endpoint and allowing testing against real stub interfaces.
+
+Prerequisites
+=============
+
+Ensure you meet the following prerequisites:
+
+1. **Required Java Installation:**
+
+ Ensure that you have the required Java installed on your system.
+
+2. **Access to Gerrit and Maven Installation (for building CPS project locally):**
+
+ - Ensure you have access to the ONAP Gerrit repository.
+
+ - If you plan to build the CPS project locally, make sure you have Maven installed.
+
+Method 1: Running Stubs as an Application
+=========================================
+
+Follow these steps to run the CPS-NCMP stub application:
+
+1. **Download Application Jar:**
+
+ You can obtain the CPS-NCMP stub application jar in one of the following ways:
+
+ - **Option 1: Download from Nexus Repository:**
+
+ Download the application jar from the Nexus repository at `https://nexus.onap.org/content/repositories/releases/org/onap/cps/cps-ncmp-rest-stub-app/`_.
+
+ - **Option 2: Build Locally:**
+
+ To build the CPS project locally, navigate to the project's root directory. Once there, you can build the project using :code:`mvn clean install`, and the application CPS-NCMP stub application jar can be found in the following location:
+
+ ::
+
+ cps/cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/target/
+
+2. **Run the Application:**
+
+ After obtaining the application jar, use the following command to run it:
+
+ .. code-block:: bash
+
+ java -jar ./cps-ncmp-rest-stub-app-<VERSION>.jar
+
+ Replace ``<VERSION>`` with the actual version number of the application jar.
+
+This will start the CPS-NCMP stub application, and you can interact with it as needed.
+
+.. _`https://nexus.onap.org/content/repositories/releases/org/onap/cps/cps-ncmp-rest-stub-app/`: https://nexus.onap.org/content/repositories/releases/org/onap/cps/cps-ncmp-rest-stub-app/
+
+Method 2: Using Stubs in Unit Tests
+===================================
+1. **Add Dependency to pom.xml:**
+
+ To include the required module in your project, add the following dependency to your `pom.xml` file:
+
+ .. code-block:: xml
+
+ <dependency>
+ <groupId>org.onap.cps</groupId>
+ <artifactId>cps-ncmp-rest-stub-service</artifactId>
+ <version>VERSION</version>
+ </dependency>
+
+ Replace ``VERSION`` with the actual version number.
+
+2. **Using Custom Response Objects:**
+
+ If you prefer to use custom response objects instead of the built-in ones, follow these steps:
+
+ Modify the `application.yaml` file located in your project's test resources directory (`src/test/resources`).
+
+ Add the following property to the `application.yaml` file, specifying the directory that contains your custom response objects:
+
+ .. code-block:: yaml
+
+ stub:
+ path: "/my_custom_stubs/"
+
+ **Note:** Custom response objects can be placed in the `src/test/resources` directory of your project under the directory defined in above property. Refer to the `examples <https://github.com/onap/cps/tree/master/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/resources/stubs>`_ included in the CPS source repository for reference.
+
+3. **Simple Test Code:**
+
+ You may refer to the sample test code 'SampleCpsNcmpClientSpec.groovy' in the local CPS project under the following directory:
+
+ ::
+
+ /cps/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/
+
+ Alternatively, you can refer to the `example <https://github.com/onap/cps/tree/master/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub>`_ included in the CPS source repository.
+
+**Custom Responses for Supported Endpoints**
+
+ Only the following endpoints are supported for the first draft. To use your custom response objects for these endpoints, create the corresponding JSON files:
+
+ - For RequestMethod.GET /v1/ch/{cm-handle}/data/ds/{datastore-name}, create "passthrough-operational-example.json".
+
+ - For RequestMethod.POST /v1/ch/searches, create "cmHandlesSearch.json".
diff --git a/docs/deployment.rst b/docs/deployment.rst
index 0642e6a8e..0fee55969 100644
--- a/docs/deployment.rst
+++ b/docs/deployment.rst
@@ -197,8 +197,8 @@ Any spring supported property can be configured by providing in ``config.additio
| logging.level | Logging level set in cps-core | info |
| | | |
+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.useStrimziKafka | If targeting a custom kafka cluster, ie useStrimziKafka: false, the config.eventPublisher.spring.kafka | true |
-| | values below must be set. | |
+| config.useStrimziKafka | If targeting a custom kafka cluster, i.e. useStrimziKafka: false, the | true |
+| | config.eventPublisher.spring.kafka values below must be set. | |
+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
| config.eventPublisher. | Kafka hostname and port | ``<kafka-bootstrap>:9092`` |
| spring.kafka.bootstrap-servers | | |
diff --git a/docs/design.rst b/docs/design.rst
index c6413c294..80eb5f152 100755
--- a/docs/design.rst
+++ b/docs/design.rst
@@ -1,6 +1,6 @@
.. This work is licensed under a Creative Commons Attribution 4.0 International License.
.. http://creativecommons.org/licenses/by/4.0
-.. Copyright (C) 2021-2022 Nordix Foundation
+.. Copyright (C) 2021-2023 Nordix Foundation
.. DO NOT CHANGE THIS LABEL FOR RELEASE NOTES - EVEN THOUGH IT GIVES A WARNING
.. _design:
@@ -83,3 +83,34 @@ NCMP Inventory CM Handle Querying
The CM Handle searches ncmp inventory endpoints can be used to query for CM Handles or CM Handle IDs.
This endpoint is described in detail in :doc:`ncmp-inventory-querying`.
+
+Common NCMP Response Codes
+==========================
+
+NCMP uses common responses codes in REST responses and events. Also the DMI plugin interface uses these codes which are defined here:
+
+.. toctree::
+ :maxdepth: 1
+
+ cps-ncmp-message-status-codes.rst
+
+Contract Testing (stubs)
+========================
+
+The CPS team is committed to supporting consumers of our APIs through contract testing.
+Obviously we test our own contracts on a continuous basis as part of the build and delivery process.
+CPS uses a contract-first approach. That means we write our OpenAPi contracts first and then generate the interface code from that.
+This means our interface implementation simply cannot deviate from the OpenApi contracts we deliver.
+
+Another advantage is that we can also generate 'stubs'. Stubs are a basic implementation of the same interface for testing purposes.
+These stubs can be used by clients for unit testing but also for more higher level integration-like testing where the real service is replaced by a stub.
+This can be useful for faster feedback loops where deployment of a full stack is difficult and not strictly needed for the purpose of the tests.
+
+Stubs for contract testing typically always return the same response which is sufficient for the strict definition of a contract test.
+However it is often useful to allow more variation in the responses so different clients or the same client can test different scenarios without having to mock the service.
+CPS has implemented what we call 'extended stubs' that allow clients to provide alternate responses.implementation
+
+The available stubs and how to use them are described in :doc:'cps-stubs'.
+
+
+
diff --git a/docs/index.rst b/docs/index.rst
index c1427ad38..573bd5412 100755
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -25,6 +25,7 @@ CPS
cps-events.rst
deployment.rst
release-notes.rst
+ cps-stubs.rst
DMI-Plugin
==========
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
index 26a7a552e..e6b81fcba 100755
--- a/docs/release-notes.rst
+++ b/docs/release-notes.rst
@@ -16,6 +16,33 @@ CPS Release Notes
.. * * * MONTREAL * * *
.. ========================
+Version: 3.3.9
+==============
+
+Release Data
+------------
+
++--------------------------------------+--------------------------------------------------------+
+| **CPS Project** | |
+| | |
++--------------------------------------+--------------------------------------------------------+
+| **Docker images** | onap/cps-and-ncmp:3.3.9 |
+| | |
++--------------------------------------+--------------------------------------------------------+
+| **Release designation** | 3.3.9 Montreal |
+| | |
++--------------------------------------+--------------------------------------------------------+
+| **Release date** | Not yet released |
+| | |
++--------------------------------------+--------------------------------------------------------+
+
+Bug Fixes
+---------
+3.3.9
+
+Features
+--------
+
Version: 3.3.8
==============
@@ -32,7 +59,7 @@ Release Data
| **Release designation** | 3.3.8 Montreal |
| | |
+--------------------------------------+--------------------------------------------------------+
-| **Release date** | Not yet released |
+| **Release date** | 2023 September 29 |
| | |
+--------------------------------------+--------------------------------------------------------+
@@ -42,6 +69,7 @@ Bug Fixes
Features
--------
+ - `CPS-1888 <https://jira.onap.org/browse/CPS-1888>`_ Uplift Spring Boot to 3.1.2.
Version: 3.3.7
==============
@@ -70,7 +98,7 @@ Bug Fixes
Features
--------
-- `CPS-1789 <https://jira.onap.org/browse/CPS-1789>`_ CPS Upgrade to Springboot 3.0.
+ - `CPS-1789 <https://jira.onap.org/browse/CPS-1789>`_ CPS Upgrade to Springboot 3.0.
Note
----
@@ -487,7 +515,7 @@ Bug Fixes
- `CPS-1289 <https://jira.onap.org/browse/CPS-1289>`_ Getting wrong error code for create node api
- `CPS-1326 <https://jira.onap.org/browse/CPS-1326>`_ Creation of DataNodeBuilder with module name prefix is very slow
- `CPS-1344 <https://jira.onap.org/browse/CPS-1344>`_ Top level container (prefix) is not always the first module
- - `CPS-1350 <https://jira.onap.org/browse/CPS-1350>`_ Add Basic Auth to CPS/NCMP OpenAPI Definitions.
+ - `CPS-1350 <https://jira.onap.org/browse/CPS-1350>`_ Add Basic Authentication to CPS/NCMP OpenAPI Definitions.
- `CPS-1352 <https://jira.onap.org/browse/CPS-1352>`_ Handle YangChoiceNode in right format.
- `CPS-1409 <https://jira.onap.org/browse/CPS-1409>`_ Fix Delete uses case with '/' in path.
- `CPS-1433 <https://jira.onap.org/browse/CPS-1433>`_ Fix to allow posting data with '/' key fields.
@@ -673,7 +701,7 @@ Bug Fixes
- `CPS-957 <https://jira.onap.org/browse/CPS-957>`_ NCMP: fix getResourceDataForPassthroughOperational endpoint
- `CPS-1020 <https://jira.onap.org/browse/CPS-1020>`_ DuplicatedYangResourceException error at parallel cmHandle registration
- `CPS-1056 <https://jira.onap.org/browse/CPS-1056>`_ Wrong error response format in case of Dmi plugin error
- - `CPS-1067 <https://jira.onap.org/browse/CPS-1067>`_ NCMP returns 500 error on searches endpoint when No DMi Handles registered
+ - `CPS-1067 <https://jira.onap.org/browse/CPS-1067>`_ NCMP returns 500 error on searches endpoint when No DMI Handles registered
- `CPS-1085 <https://jira.onap.org/browse/CPS-1085>`_ Performance degradation on ncmp/v1/ch/searches endpoint
- `CPS-1088 <https://jira.onap.org/browse/CPS-1088>`_ Kafka consumer can not be turned off
- `CPS-1097 <https://jira.onap.org/browse/CPS-1097>`_ Unable to change state from LOCKED to ADVISED
@@ -785,7 +813,7 @@ Bug Fixes
- `CPS-886 <https://jira.onap.org/browse/CPS-886>`_ Fragment handling decreasing performance for large number of cmHandles
- `CPS-887 <https://jira.onap.org/browse/CPS-887>`_ Increase performance of cmHandle registration for large number of schema sets in DB
- `CPS-892 <https://jira.onap.org/browse/CPS-892>`_ Fixed the response code during CM-Handle Registration from 201 CREATED to 204 NO_CONTENT
- - `CPS-893 <https://jira.onap.org/browse/CPS-893>`_ NCMP Java API depends on NCM-Rest-API (cyclic) through json properties on Java API
+ - `CPS-893 <https://jira.onap.org/browse/CPS-893>`_ NCMP Java API depends on NCMP-Rest-API (cyclic) through json properties on Java API
Known Limitations, Issues and Workarounds
-----------------------------------------
@@ -1240,7 +1268,7 @@ Security Notes
*Known Security Issues*
- * Weak Crytography using md5
+ * Weak Cryptography using md5
* Risk seen in Zip file expansion
*Known Vulnerabilities in Used Modules*
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
new file mode 100644
index 000000000..3bfa9a0a3
--- /dev/null
+++ b/docs/spelling_wordlist.txt
@@ -0,0 +1,67 @@
+api
+async
+authorization
+boolean
+behavior
+camelCasing
+cmHandle
+cmHandles
+config
+color
+cps
+cpsPath
+cpsPaths
+csit
+customizations
+dataschema
+dataspace
+dataspaces
+datasource
+datastore
+datastores
+deliverables
+dmi
+dmiPlugin
+dmiPlugins
+rnv
+hazelcast
+hostname
+jira
+json
+kafka
+kibana
+kubernetes
+kohn
+lifecycle
+liquibase
+logback
+modeled
+modeling
+normalized
+ncmp
+onap
+openapi
+optimized
+passthrough
+performant
+postgres
+queryable
+repo
+runtime
+schemas
+sql
+ssl
+standardized
+synchronize
+synchronization
+undeploying
+utilizes
+xml
+xNF
+xNFs
+xpath
+xpaths
+xPath
+XPath
+XPaths
+yaml \ No newline at end of file
diff --git a/docs/tox.ini b/docs/tox.ini
index 8684276f9..7020752c8 100644
--- a/docs/tox.ini
+++ b/docs/tox.ini
@@ -21,23 +21,23 @@ minversion = 1.6
envlist = docs,docs-linkcheck,docs-spellcheck
skipsdist = true
[testenv:docs]
-basepython = python3.8
+basepython = python3.10
deps =
-r{toxinidir}/requirements-docs.txt
-chttps://raw.githubusercontent.com/openstack/requirements/stable/yoga/upper-constraints.txt
-chttps://git.onap.org/doc/plain/etc/upper-constraints.onap.txt?h=master
commands =
- sphinx-build -W -q -b html -n -d {envtmpdir}/doctrees {toxinidir} {toxinidir}/_build/html
+ sphinx-build -q -b html -n -d {envtmpdir}/doctrees {toxinidir} {toxinidir}/_build/html
[testenv:docs-linkcheck]
-basepython = python3.8
+basepython = python3.10
deps =
-r{toxinidir}/requirements-docs.txt
-chttps://raw.githubusercontent.com/openstack/requirements/stable/yoga/upper-constraints.txt
-chttps://git.onap.org/doc/plain/etc/upper-constraints.onap.txt?h=master
commands =
- sphinx-build -W -q -b linkcheck -d {envtmpdir}/doctrees {toxinidir} {toxinidir}/_build/linkcheck
+ sphinx-build -q -b linkcheck -d {envtmpdir}/doctrees {toxinidir} {toxinidir}/_build/linkcheck
[testenv:docs-spellcheck]
-basepython = python3.8
+basepython = python3.10
deps =
-r{toxinidir}/requirements-docs.txt
-chttps://raw.githubusercontent.com/openstack/requirements/stable/yoga/upper-constraints.txt
diff --git a/integration-test/pom.xml b/integration-test/pom.xml
index af67a5f69..b2bdce757 100644
--- a/integration-test/pom.xml
+++ b/integration-test/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/TestConfig.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/TestConfig.groovy
index e39e11440..f4cc8b733 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/base/TestConfig.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/TestConfig.groovy
@@ -90,7 +90,7 @@ class TestConfig extends Specification{
@Bean
CpsModulePersistenceService cpsModulePersistenceService() {
- return (CpsModulePersistenceService) new CpsModulePersistenceServiceImpl(yangResourceRepository, schemaSetRepository, dataspaceRepository, cpsAdminPersistenceService(), moduleReferenceRepository)
+ return (CpsModulePersistenceService) new CpsModulePersistenceServiceImpl(yangResourceRepository, schemaSetRepository, dataspaceRepository, moduleReferenceRepository)
}
@Bean
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy
index cfc8ab7ad..d33a77446 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy
@@ -94,7 +94,7 @@ class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
moduleReferences.addAll(existingModuleReferences)
when: 'the new schema set is created'
def schemaSetName = "NewSchemaWith${numberOfNewModules}Modules"
- objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, newYangResourcesNameToContentMap, moduleReferences)
+ objectUnderTest.createOrUpgradeSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, newYangResourcesNameToContentMap, moduleReferences)
and: 'associated with a new anchor'
cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, 'newAnchor')
then: 'the new anchor has the correct number of modules'
diff --git a/jacoco-report/pom.xml b/jacoco-report/pom.xml
index 22e071fcb..020cbc960 100644
--- a/jacoco-report/pom.xml
+++ b/jacoco-report/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/pom.xml b/pom.xml
index 71310fb58..9efdef2ad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,7 +32,7 @@
<groupId>org.onap.cps</groupId>
<artifactId>cps-aggregator</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<packaging>pom</packaging>
<name>cps</name>
diff --git a/releases/3.3.8-container.yaml b/releases/3.3.8-container.yaml
new file mode 100644
index 000000000..810f328b6
--- /dev/null
+++ b/releases/3.3.8-container.yaml
@@ -0,0 +1,8 @@
+distribution_type: container
+container_release_tag: 3.3.8
+project: cps
+log_dir: cps-maven-docker-stage-master/929/
+ref: cb9d15022ca5e7696e474ffc8c1b10fa053d6b40
+containers:
+ - name: 'cps-and-ncmp'
+ version: '3.3.8-20230928T113343Z' \ No newline at end of file
diff --git a/releases/3.3.8.yaml b/releases/3.3.8.yaml
new file mode 100644
index 000000000..e28b4532e
--- /dev/null
+++ b/releases/3.3.8.yaml
@@ -0,0 +1,4 @@
+distribution_type: maven
+log_dir: cps-maven-stage-master/937/
+project: cps
+version: 3.3.8 \ No newline at end of file
diff --git a/spotbugs/pom.xml b/spotbugs/pom.xml
index d511c0fb9..743d3b795 100644
--- a/spotbugs/pom.xml
+++ b/spotbugs/pom.xml
@@ -25,7 +25,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.cps</groupId>
<artifactId>spotbugs</artifactId>
- <version>3.3.8-SNAPSHOT</version>
+ <version>3.3.9-SNAPSHOT</version>
<properties>
<nexusproxy>https://nexus.onap.org</nexusproxy>
diff --git a/version.properties b/version.properties
index 4709bf127..482fe366c 100755
--- a/version.properties
+++ b/version.properties
@@ -22,7 +22,7 @@
major=3
minor=3
-patch=8
+patch=9
base_version=${major}.${minor}.${patch}