Merge "Amend http status for CM Handles Data Enpoints in Documentation"
authorSourabh Sourabh <sourabh.sourabh@est.tech>
Fri, 5 Jan 2024 10:20:47 +0000 (10:20 +0000)
committerGerrit Code Review <gerrit@onap.org>
Fri, 5 Jan 2024 10:20:47 +0000 (10:20 +0000)
169 files changed:
checkstyle/pom.xml
cps-application/pom.xml [changed mode: 0755->0644]
cps-application/src/main/resources/application.yml
cps-bom/pom.xml
cps-dependencies/pom.xml [changed mode: 0755->0644]
cps-events/pom.xml
cps-ncmp-events/pom.xml
cps-ncmp-events/src/main/resources/schemas/cmsubscription/cm-subscription-dmi-in-event-schema-1.0.0.json
cps-ncmp-events/src/main/resources/schemas/cmsubscription/cm-subscription-dmi-out-event-schema-1.0.0.json
cps-ncmp-events/src/main/resources/schemas/cmsubscription/cm-subscription-ncmp-in-event-schema-1.0.0.json
cps-ncmp-events/src/main/resources/schemas/cmsubscription/cm-subscription-ncmp-out-event-schema-1.0.0.json
cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-dmi-in-event-schema-1.0.0.json [deleted file]
cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-dmi-out-event-schema-1.0.0.json [deleted file]
cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-ncmp-in-event-schema-1.0.0.json [deleted file]
cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-ncmp-out-event-schema-1.0.0.json [deleted file]
cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-dmi-in-event-schema-1.0.0.json [new file with mode: 0644]
cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-dmi-out-event-schema-1.0.0.json [new file with mode: 0644]
cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-ncmp-in-event-schema-1.0.0.json [new file with mode: 0644]
cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-ncmp-out-event-schema-1.0.0.json [new file with mode: 0644]
cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml
cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
cps-ncmp-rest-stub/pom.xml
cps-ncmp-rest/docs/openapi/components.yaml
cps-ncmp-rest/pom.xml
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapperSpec.groovy
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/executor/CpsNcmpTaskExecutorSpec.groovy
cps-ncmp-service/pom.xml
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/deprecated/subscriptions/SubscriptionPersistence.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistence.java with 96% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/deprecated/subscriptions/SubscriptionPersistenceImpl.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceImpl.java with 99% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/deprecated/subscriptions/SubscriptionStatus.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionStatus.java with 96% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionDmiOutEventConsumer.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionDmiOutEventConsumer.java with 97% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionDmiOutEventToYangModelSubscriptionEventMapper.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionDmiOutEventToYangModelSubscriptionEventMapper.java with 91% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionEventToCmSubscriptionNcmpOutEventMapper.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionEventToCmSubscriptionNcmpOutEventMapper.java with 97% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionNcmpInEventConsumer.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventConsumer.java with 96% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionNcmpInEventForwarder.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarder.java with 97% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionNcmpInEventMapper.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventMapper.java with 97% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionNcmpInEventToCmSubscriptionDmiInEventMapper.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventToCmSubscriptionDmiInEventMapper.java with 95% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisher.java with 93% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/ResponseTimeoutTask.java [moved from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/ResponseTimeoutTask.java with 96% similarity]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtils.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmDataSubscriptionEvent.java [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelSubscriptionEvent.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmSubscriptionStatus.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/SubscriptionEventResponse.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
cps-ncmp-service/src/main/resources/models/dmi-registry@2023-11-27.yang [moved from integration-test/src/test/resources/data/ncmp-registry/dmi-registry@2022-05-10.yang with 74% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy [new file with mode: 0644]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/deprecated/subscriptions/SubscriptionPersistenceSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/subscriptions/SubscriptionPersistenceSpec.groovy with 99% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/ClientCmSubscriptionNcmpInEventMapperSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/ClientCmSubscriptionNcmpInEventMapperSpec.groovy with 93% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionDmiOutEventConsumerSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionDmiOutEventConsumerSpec.groovy with 97% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionDmiOutEventToYangModelSubscriptionEventMapperSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionDmiOutEventToYangModelSubscriptionEventMapperSpec.groovy with 91% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionEventToCmSubscriptionNcmpOutEventMapperSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionEventToCmSubscriptionNcmpOutEventMapperSpec.groovy with 94% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionNcmpInEventConsumerSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventConsumerSpec.groovy with 94% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionNcmpInEventForwarderSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventForwarderSpec.groovy with 96% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionNcmpInEventMapperSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpInEventMapperSpec.groovy with 93% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/deprecated/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmSubscriptionNcmpOutEventPublisherSpec.groovy with 95% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImplSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncServiceSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/util/deprecated/CmSubscriptionEventCloudMapperSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmSubscriptionEventCloudMapperSpec.groovy with 91% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/util/deprecated/SubscriptionOutcomeCloudMapperSpec.groovy [moved from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/SubscriptionOutcomeCloudMapperSpec.groovy with 91% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/NcmpServiceCmHandleSpec.groovy [deleted file]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/AbstractModelLoaderSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoaderSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
cps-ncmp-service/src/test/resources/deprecatedCmSubscription/cmSubscriptionDmiInEvent.json [moved from cps-ncmp-service/src/test/resources/cmSubscriptionDmiInEvent.json with 100% similarity]
cps-ncmp-service/src/test/resources/deprecatedCmSubscription/cmSubscriptionDmiOutEvent.json [moved from cps-ncmp-service/src/test/resources/cmSubscriptionDmiOutEvent.json with 100% similarity]
cps-ncmp-service/src/test/resources/deprecatedCmSubscription/cmSubscriptionEvent.json [moved from cps-ncmp-service/src/test/resources/cmSubscriptionEvent.json with 100% similarity]
cps-ncmp-service/src/test/resources/deprecatedCmSubscription/cmSubscriptionNcmpInEvent.json [moved from cps-ncmp-service/src/test/resources/cmSubscriptionNcmpInEvent.json with 100% similarity]
cps-ncmp-service/src/test/resources/deprecatedCmSubscription/cmSubscriptionNcmpOutEvent.json [moved from cps-ncmp-service/src/test/resources/cmSubscriptionNcmpOutEvent.json with 100% similarity]
cps-ncmp-service/src/test/resources/deprecatedCmSubscription/cmSubscriptionNcmpOutEvent2.json [moved from cps-ncmp-service/src/test/resources/cmSubscriptionNcmpOutEvent2.json with 100% similarity]
cps-parent/pom.xml [changed mode: 0755->0644]
cps-path-parser/pom.xml
cps-rest/pom.xml [changed mode: 0755->0644]
cps-rest/src/main/java/org/onap/cps/rest/controller/AdminRestController.java
cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy
cps-rest/src/test/groovy/org/onap/cps/rest/exceptions/CpsRestExceptionHandlerSpec.groovy
cps-ri/pom.xml
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java
cps-ri/src/main/java/org/onap/cps/spi/repository/YangResourceRepository.java
cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy
cps-service/pom.xml
cps-service/src/main/java/org/onap/cps/api/CpsAnchorService.java [moved from cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java with 75% similarity, mode: 0644]
cps-service/src/main/java/org/onap/cps/api/CpsDataspaceService.java [new file with mode: 0644]
cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java [moved from cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java with 66% similarity, mode: 0644]
cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
cps-service/src/main/java/org/onap/cps/api/impl/CpsDataspaceServiceImpl.java [new file with mode: 0644]
cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java [deleted file]
cps-service/src/main/java/org/onap/cps/notification/KafkaProducerListener.java [deleted file]
cps-service/src/main/java/org/onap/cps/notification/NotificationErrorHandler.java [deleted file]
cps-service/src/main/java/org/onap/cps/notification/NotificationProperties.java [deleted file]
cps-service/src/main/java/org/onap/cps/notification/NotificationPublisher.java [deleted file]
cps-service/src/main/java/org/onap/cps/notification/NotificationService.java [deleted file]
cps-service/src/main/java/org/onap/cps/notification/Operation.java [deleted file]
cps-service/src/main/java/org/onap/cps/spi/CpsModulePersistenceService.java
cps-service/src/main/java/org/onap/cps/utils/PrefixResolver.java
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAnchorServiceImplSpec.groovy [moved from cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy with 74% similarity, mode: 0644]
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataspaceServiceImplSpec.groovy [new file with mode: 0644]
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
cps-service/src/test/groovy/org/onap/cps/config/AsyncConfigSpec.groovy [new file with mode: 0644]
cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdatedEventFactorySpec.groovy [deleted file]
cps-service/src/test/groovy/org/onap/cps/notification/KafkaPublisherSpecBase.groovy [deleted file]
cps-service/src/test/groovy/org/onap/cps/notification/KafkaTestContainerConfig.groovy [deleted file]
cps-service/src/test/groovy/org/onap/cps/notification/NotificationErrorHandlerSpec.groovy [deleted file]
cps-service/src/test/groovy/org/onap/cps/notification/NotificationPublisherSpec.groovy [deleted file]
cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy [deleted file]
cps-service/src/test/groovy/org/onap/cps/utils/PrefixResolverSpec.groovy
csit/plans/cps/sdnc/check_sdnc_mount_node.sh [new file with mode: 0644]
csit/plans/cps/sdnc/sdnc_setup.sh
csit/plans/cps/setup.sh
csit/plans/cps/testplanCps.txt [new file with mode: 0644]
csit/plans/cps/testplanNcmp.txt [moved from csit/plans/cps/testplan.txt with 91% similarity]
csit/run-csit.sh
csit/tests/ncmp-passthrough/ncmp-passthrough.robot
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml
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
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/moduleResourcesResponse.json
dmi-plugin-demo-and-csit-stub/pom.xml
docker-compose/README.md
docker-compose/docker-compose.yml
docs/api/swagger/cps/openapi.yaml
docs/api/swagger/ncmp/openapi-inventory.yaml
docs/api/swagger/ncmp/openapi.yaml
docs/deployment.rst
docs/design.rst [changed mode: 0755->0644]
docs/index.rst [changed mode: 0755->0644]
docs/release-notes.rst [changed mode: 0755->0644]
integration-test/pom.xml
integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
integration-test/src/test/groovy/org/onap/cps/integration/base/FunctionalSpecBase.groovy
integration-test/src/test/groovy/org/onap/cps/integration/base/TestConfig.groovy
integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsAnchorServiceIntegrationSpec.groovy [moved from integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsAdminServiceIntegrationSpec.groovy with 66% similarity]
integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy
integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataspaceServiceIntegrationSpec.groovy [new file with mode: 0644]
integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy
integration-test/src/test/groovy/org/onap/cps/integration/performance/base/CpsPerfTestBase.groovy
integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy
integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/CpsDataServiceLimitsPerfTest.groovy
integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/CpsDataspaceServiceLimitsPerfTest.groovy [moved from integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/CpsAdminServiceLimitsPerfTest.groovy with 91% similarity]
integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/DeletePerfTest.groovy
integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/UpdatePerfTest.groovy
integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/WritePerfTest.groovy
integration-test/src/test/resources/data/ncmp-registry/dmi-registry@2023-11-27.yang [moved from cps-ncmp-service/src/main/resources/models/dmi-registry@2023-08-23.yang with 94% similarity]
jacoco-report/pom.xml
pom.xml
releases/3.4.1-container.yaml [new file with mode: 0644]
releases/3.4.1.yaml [new file with mode: 0644]
spotbugs/pom.xml
version.properties [changed mode: 0755->0644]

index f41f899..dac29d8 100644 (file)
@@ -26,7 +26,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.cps</groupId>
     <artifactId>checkstyle</artifactId>
-    <version>3.4.1-SNAPSHOT</version>
+    <version>3.4.2-SNAPSHOT</version>
 
     <profiles>
         <profile>
old mode 100755 (executable)
new mode 100644 (file)
index f989638..244067b
@@ -28,7 +28,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index 89969b9..f973b6f 100644 (file)
@@ -114,10 +114,6 @@ app:
 
 notification:
     enabled: true
-    data-updated:
-        topic: ${CPS_CHANGE_EVENT_TOPIC:cps.data-updated-events}
-        filters:
-            enabled-dataspaces: ${NOTIFICATION_DATASPACE_FILTER_PATTERNS:""}
     async:
         executor:
             core-pool-size: 2
@@ -170,6 +166,11 @@ logging:
                 cps: INFO
 ncmp:
     dmi:
+        httpclient:
+            connectionTimeoutInSeconds: 180
+            maximumConnectionsPerRoute: 50
+            maximumConnectionsTotal: 100
+            idleConnectionEvictionThresholdInSeconds: 5
         auth:
             username: ${DMI_USERNAME}
             password: ${DMI_PASSWORD}
index ac6b460..bde5143 100644 (file)
@@ -25,7 +25,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.cps</groupId>
     <artifactId>cps-bom</artifactId>
-    <version>3.4.1-SNAPSHOT</version>
+    <version>3.4.2-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <description>This artifact contains dependencyManagement declarations of all published CPS components.</description>
old mode 100755 (executable)
new mode 100644 (file)
index 660364e..b40b029
@@ -27,7 +27,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.cps</groupId>
     <artifactId>cps-dependencies</artifactId>
-    <version>3.4.1-SNAPSHOT</version>
+    <version>3.4.2-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>${project.groupId}:${project.artifactId}</name>
index 4b531c1..b46665d 100644 (file)
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index 8a8d4d8..037fbba 100644 (file)
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index 3750bd0..4d4d504 100644 (file)
   "$ref": "#/definitions/CmSubscriptionDmiInEvent",
   "definitions": {
     "CmSubscriptionDmiInEvent": {
-      "description": "The payload for subscription event to be forwarded to dmi plugins.",
-      "javaType": "org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_dmi.CmSubscriptionDmiInEvent",
+      "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.CmSubscriptionDmiInEvent",
+      "additionalProperties": false,
       "properties": {
         "data": {
-          "properties": {
-            "dataType": {
-              "description": "The datatype content.",
-              "properties": {
-                "dataCategory": {
-                  "description": "The category type of the data",
-                  "type": "string"
-                },
-                "dataProvider": {
-                  "description": "The provider name of the data",
+          "$ref": "#/definitions/data"
+        }
+      },
+      "required": [
+        "data"
+      ]
+    },
+    "data": {
+      "type": "object",
+      "description": "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"
-                },
-                "dataspace": {
-                  "description": "The dataspace name",
+                }
+              }
+            }
+          }
+        },
+        "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"
                 }
               },
-              "required": [
-                "dataCategory",
-                "dataProvider",
-                "dataspace"
-              ],
-              "type": "object",
-              "additionalProperties": false
-            },
-            "predicates": {
-              "description": "Additional values to be added into the subscription",
-              "properties": {
-                "datastore": {
-                  "description": "datastore which is to be used by the subscription",
-                  "type": "string"
-                },
-                "targets": {
-                  "description": "CM Handles to be targeted by the subscription",
-                  "type": "array",
-                  "items": {
-                    "$ref": "#/definitions/CmHandle"
+              "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"
+                    }
                   }
                 },
-                "datastore-xpath-filter": {
-                  "description": "filter to be applied to the CM Handles through this event",
-                  "type": "string"
-                }
-              },
-              "required": [
-                "datastore",
-                "targets",
-                "datastore-xpath-filter"
-              ],
-              "type": "object",
-              "additionalProperties": false
+                "additionalProperties": false,
+                "required": [
+                  "xpath-filter"
+                ]
+              }
             },
-            "subscription": {
-              "description": "The subscription details.",
-              "properties": {
-                "clientID": {
-                  "description": "The clientID",
-                  "type": "string"
-                },
-                "name": {
-                  "description": "The name of the subscription",
-                  "type": "string"
-                },
-                "isTagged": {
-                  "description": "optional parameter, default is no",
-                  "type": "boolean",
-                  "default": false
-                }
-              },
-              "required": [
-                "clientID",
-                "name"
-              ],
-              "type": "object",
-              "additionalProperties": false
-            }
+            "additionalProperties": false,
+            "required": [
+              "targetFilter"
+            ]
           },
-          "required": [
-            "dataType",
-            "predicates",
-            "subscription"
-          ],
-          "type": "object",
           "additionalProperties": false
         }
       },
-      "type": "object",
-      "additionalProperties": false,
       "required": [
-        "data"
+        "cmhandles",
+        "predicates"
       ]
-    },
-    "CmHandle": {
-      "description": "The CM handle information",
-      "type": "object",
-      "properties": {
-        "id": {
-          "type": "string"
-        },
-        "additional-properties": {
-          "existingJavaType": "java.util.Map<String,String>"
-        }
-      },
-      "required": [
-        "id",
-        "additional-properties"
-      ],
-      "additionalProperties": false
     }
   }
 }
\ No newline at end of file
index ebbdde9..5ae6225 100644 (file)
@@ -3,67 +3,41 @@
   "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-dmi-out-event-schema:1.0.0",
   "$ref": "#/definitions/CmSubscriptionDmiOutEvent",
   "definitions": {
-    "SubscriptionStatus": {
-      "description": "The subscription status information",
+    "CmSubscriptionDmiOutEvent": {
+      "description": "The payload for cm subscription merge event coming out from DMI Plugin.",
       "type": "object",
+      "additionalProperties": false,
+      "javaType": "org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.dmi_to_ncmp.CmSubscriptionDmiOutEvent",
       "properties": {
-        "id": {
-          "type": "string"
-        },
-        "status" : {
-          "type": "string",
-          "enum": [
-            "ACCEPTED",
-            "REJECTED"
-          ]
-        },
-        "details" : {
-          "type": "string"
+        "data": {
+          "$ref": "#/definitions/Data"
         }
       },
       "required": [
-        "id",
-        "status"
+        "data"
       ],
-      "additionalProperties": false
+      "title": "CmSubscriptionDmiOutEvent"
     },
-    "CmSubscriptionDmiOutEvent" : {
-      "description": "The payload for subscription response event.",
+    "Data": {
       "type": "object",
-      "javaType": "org.onap.cps.ncmp.events.cmsubscription1_0_0.dmi_to_ncmp.CmSubscriptionDmiOutEvent",
+      "description": "Information about the targets and subscription",
+      "additionalProperties": false,
       "properties": {
-        "data": {
-          "type": "object",
-          "properties": {
-            "clientId": {
-              "type": "string"
-            },
-            "subscriptionName": {
-              "type": "string"
-            },
-            "dmiName": {
-              "type": "string"
-            },
-            "subscriptionStatus": {
-              "type": "array",
-              "items": {
-                "$ref": "#/definitions/SubscriptionStatus"
-              }
-            }
-          },
-          "required": [
-            "clientId",
-            "subscriptionName",
-            "dmiName",
-            "subscriptionStatus"
-          ],
-          "additionalProperties": false
+        "statusCode": {
+          "type": "string",
+          "format": "integer",
+          "description": "The common status as defined in CPS"
+        },
+        "statusMessage": {
+          "type": "string",
+          "description": "The common status message as defined in CPS"
         }
       },
-      "additionalProperties": false,
       "required": [
-        "data"
-      ]
+        "statusCode",
+        "statusMessage"
+      ],
+      "title": "Data"
     }
   }
 }
\ No newline at end of file
index 818a8e7..ffdc2e3 100644 (file)
@@ -4,86 +4,61 @@
   "$schema": "https://json-schema.org/draft/2019-09/schema",
   "definitions": {
     "CmSubscriptionNcmpInEvent": {
-      "description": "The payload for subscription event.",
-      "javaType": "org.onap.cps.ncmp.events.cmsubscription1_0_0.client_to_ncmp.CmSubscriptionNcmpInEvent",
+      "description": "The payload for subscription merge event.",
+      "javaType": "org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.client_to_ncmp.CmSubscriptionNcmpInEvent",
       "properties": {
         "data": {
           "properties": {
-            "dataType": {
-              "description": "The datatype content.",
-              "properties": {
-                "dataCategory": {
-                  "description": "The category type of the data",
-                  "type": "string"
-                },
-                "dataProvider": {
-                  "description": "The provider name of the data",
-                  "type": "string"
-                },
-                "dataspace": {
-                  "description": "The dataspace name",
-                  "type": "string"
-                }
-              },
-              "required": [
-                "dataCategory",
-                "dataProvider",
-                "dataspace"
-              ],
-              "type": "object",
-              "additionalProperties": false
+            "subscriptionId": {
+              "description": "The subscription details.",
+              "type": "string"
             },
             "predicates": {
+              "type": "array",
               "description": "Additional values to be added into the subscription",
-              "properties": {
-                "datastore": {
-                  "description": "datastore which is to be used by the subscription",
-                  "type": "string"
-                },
-                "targets": {
-                  "description": "CM Handles to be targeted by the subscription",
-                  "type": "array",
-                  "items": {
-                    "type": "string"
+              "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"
+                    ]
                   }
                 },
-                "datastore-xpath-filter": {
-                  "description": "filter to be applied to the CM Handles through this event",
-                  "type": "string"
-                }
-              },
-              "required": [
-                "datastore",
-                "targets",
-                "datastore-xpath-filter"
-              ],
-              "type": "object",
-              "additionalProperties": false
-            },
-            "subscription": {
-              "description": "The subscription details.",
-              "properties": {
-                "clientID": {
-                  "description": "The clientID",
-                  "type": "string"
-                },
-                "name": {
-                  "description": "The name of the subscription",
-                  "type": "string"
-                }
+                "additionalProperties": false,
+                "required": [
+                  "targetFilter"
+                ]
               },
-              "required": [
-                "clientID",
-                "name"
-              ],
-              "type": "object",
               "additionalProperties": false
             }
           },
           "required": [
-            "dataType",
-            "predicates",
-            "subscription"
+            "subscriptionId",
+            "predicates"
           ],
           "type": "object",
           "additionalProperties": false
index 9c0c28b..e5659a7 100644 (file)
@@ -4,66 +4,60 @@
   "$ref": "#/definitions/CmSubscriptionNcmpOutEvent",
   "definitions": {
     "CmSubscriptionNcmpOutEvent": {
-      "description": "The payload for avc subscription event outcome message.",
       "type": "object",
-      "javaType": "org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_client.CmSubscriptionNcmpOutEvent",
+      "description": "The payload applied cm subscription merge event coming out from NCMP.",
+      "javaType": "org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.ncmp_to_client.CmSubscriptionNcmpOutEvent",
       "additionalProperties": false,
       "properties": {
         "data": {
-          "$ref": "#/definitions/data"
+          "$ref": "#/definitions/Data"
         }
       },
       "required": [
         "data"
-      ]
+      ],
+      "title": "CmSubscriptionNcmpOutEvent"
     },
-    "data": {
+    "Data": {
       "type": "object",
-      "description": "The actual data containing information about the pending and rejected targets",
+      "description": "Information about the targets and subscription",
       "additionalProperties": false,
       "properties": {
-        "statusCode": {
-          "type": "integer"
+        "subscriptionId": {
+          "type": "string",
+          "description": "The unique subscription id"
         },
-        "statusMessage": {
-          "type": "string"
+        "accepted-targets": {
+          "type": "array",
+          "description": "List of accepted targets",
+          "items": {
+            "type": "string"
+          }
         },
-        "additionalInfo": {
-          "type": "object",
-          "additionalProperties": false,
-          "properties": {
-            "rejected": {
-              "$ref": "#/definitions/additionalInfoDetails"
-            },
-            "pending": {
-              "$ref": "#/definitions/additionalInfoDetails"
-            }
+        "rejected-targets": {
+          "type": "array",
+          "description": "List of rejected targets",
+          "items": {
+            "type": "string"
           }
-        }
-      },
-      "required": [
-        "statusCode",
-        "statusMessage"
-      ]
-    },
-    "additionalInfoDetails": {
-      "type": "array",
-      "items": {
-        "type": "object",
-        "description": "Details for the target cmhandles",
-        "additionalProperties": false,
-        "properties": {
-          "details": {
+        },
+        "pending-targets": {
+          "type": "array",
+          "description": "List of pending targets",
+          "items": {
             "type": "string"
-          },
-          "targets": {
-            "type": "array",
-            "items": {
-              "type": "string"
-            }
           }
         }
-      }
+      },
+      "required": [
+        "accepted-targets",
+        "pending-targets",
+        "rejected-targets",
+        "subscriptionId"
+      ],
+      "title": "Data"
     }
   }
+
+
 }
\ No newline at end of file
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
deleted file mode 100644 (file)
index 4d4d504..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-{
-  "$schema": "https://json-schema.org/draft/2019-09/schema",
-  "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-dmi-in-event-schema:1.0.0",
-  "$ref": "#/definitions/CmSubscriptionDmiInEvent",
-  "definitions": {
-    "CmSubscriptionDmiInEvent": {
-      "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.CmSubscriptionDmiInEvent",
-      "additionalProperties": false,
-      "properties": {
-        "data": {
-          "$ref": "#/definitions/data"
-        }
-      },
-      "required": [
-        "data"
-      ]
-    },
-    "data": {
-      "type": "object",
-      "description": "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-dmi-out-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-dmi-out-event-schema-1.0.0.json
deleted file mode 100644 (file)
index 5ae6225..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-{
-  "$schema": "https://json-schema.org/draft/2019-09/schema",
-  "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-dmi-out-event-schema:1.0.0",
-  "$ref": "#/definitions/CmSubscriptionDmiOutEvent",
-  "definitions": {
-    "CmSubscriptionDmiOutEvent": {
-      "description": "The payload for cm subscription merge event coming out from DMI Plugin.",
-      "type": "object",
-      "additionalProperties": false,
-      "javaType": "org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.dmi_to_ncmp.CmSubscriptionDmiOutEvent",
-      "properties": {
-        "data": {
-          "$ref": "#/definitions/Data"
-        }
-      },
-      "required": [
-        "data"
-      ],
-      "title": "CmSubscriptionDmiOutEvent"
-    },
-    "Data": {
-      "type": "object",
-      "description": "Information about the targets and subscription",
-      "additionalProperties": false,
-      "properties": {
-        "statusCode": {
-          "type": "string",
-          "format": "integer",
-          "description": "The common status as defined in CPS"
-        },
-        "statusMessage": {
-          "type": "string",
-          "description": "The common status message as defined in CPS"
-        }
-      },
-      "required": [
-        "statusCode",
-        "statusMessage"
-      ],
-      "title": "Data"
-    }
-  }
-}
\ 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
deleted file mode 100644 (file)
index ffdc2e3..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-{
-  "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-ncmp-in-event:1.0.0",
-  "$ref": "#/definitions/CmSubscriptionNcmpInEvent",
-  "$schema": "https://json-schema.org/draft/2019-09/schema",
-  "definitions": {
-    "CmSubscriptionNcmpInEvent": {
-      "description": "The payload for subscription merge event.",
-      "javaType": "org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.client_to_ncmp.CmSubscriptionNcmpInEvent",
-      "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/cmsubscriptionmerge/cm-subscription-ncmp-out-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/cmsubscriptionmerge/cm-subscription-ncmp-out-event-schema-1.0.0.json
deleted file mode 100644 (file)
index e5659a7..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-{
-  "$schema": "https://json-schema.org/draft/2019-09/schema",
-  "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-ncmp-out-event-schema:1.0.0",
-  "$ref": "#/definitions/CmSubscriptionNcmpOutEvent",
-  "definitions": {
-    "CmSubscriptionNcmpOutEvent": {
-      "type": "object",
-      "description": "The payload applied cm subscription merge event coming out from NCMP.",
-      "javaType": "org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.ncmp_to_client.CmSubscriptionNcmpOutEvent",
-      "additionalProperties": false,
-      "properties": {
-        "data": {
-          "$ref": "#/definitions/Data"
-        }
-      },
-      "required": [
-        "data"
-      ],
-      "title": "CmSubscriptionNcmpOutEvent"
-    },
-    "Data": {
-      "type": "object",
-      "description": "Information about the targets and subscription",
-      "additionalProperties": false,
-      "properties": {
-        "subscriptionId": {
-          "type": "string",
-          "description": "The unique subscription id"
-        },
-        "accepted-targets": {
-          "type": "array",
-          "description": "List of accepted targets",
-          "items": {
-            "type": "string"
-          }
-        },
-        "rejected-targets": {
-          "type": "array",
-          "description": "List of rejected targets",
-          "items": {
-            "type": "string"
-          }
-        },
-        "pending-targets": {
-          "type": "array",
-          "description": "List of pending targets",
-          "items": {
-            "type": "string"
-          }
-        }
-      },
-      "required": [
-        "accepted-targets",
-        "pending-targets",
-        "rejected-targets",
-        "subscriptionId"
-      ],
-      "title": "Data"
-    }
-  }
-
-
-}
\ No newline at end of file
diff --git a/cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-dmi-in-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-dmi-in-event-schema-1.0.0.json
new file mode 100644 (file)
index 0000000..3750bd0
--- /dev/null
@@ -0,0 +1,121 @@
+{
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-dmi-in-event-schema:1.0.0",
+  "$ref": "#/definitions/CmSubscriptionDmiInEvent",
+  "definitions": {
+    "CmSubscriptionDmiInEvent": {
+      "description": "The payload for subscription event to be forwarded to dmi plugins.",
+      "javaType": "org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_dmi.CmSubscriptionDmiInEvent",
+      "properties": {
+        "data": {
+          "properties": {
+            "dataType": {
+              "description": "The datatype content.",
+              "properties": {
+                "dataCategory": {
+                  "description": "The category type of the data",
+                  "type": "string"
+                },
+                "dataProvider": {
+                  "description": "The provider name of the data",
+                  "type": "string"
+                },
+                "dataspace": {
+                  "description": "The dataspace name",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "dataCategory",
+                "dataProvider",
+                "dataspace"
+              ],
+              "type": "object",
+              "additionalProperties": false
+            },
+            "predicates": {
+              "description": "Additional values to be added into the subscription",
+              "properties": {
+                "datastore": {
+                  "description": "datastore which is to be used by the subscription",
+                  "type": "string"
+                },
+                "targets": {
+                  "description": "CM Handles to be targeted by the subscription",
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/definitions/CmHandle"
+                  }
+                },
+                "datastore-xpath-filter": {
+                  "description": "filter to be applied to the CM Handles through this event",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "datastore",
+                "targets",
+                "datastore-xpath-filter"
+              ],
+              "type": "object",
+              "additionalProperties": false
+            },
+            "subscription": {
+              "description": "The subscription details.",
+              "properties": {
+                "clientID": {
+                  "description": "The clientID",
+                  "type": "string"
+                },
+                "name": {
+                  "description": "The name of the subscription",
+                  "type": "string"
+                },
+                "isTagged": {
+                  "description": "optional parameter, default is no",
+                  "type": "boolean",
+                  "default": false
+                }
+              },
+              "required": [
+                "clientID",
+                "name"
+              ],
+              "type": "object",
+              "additionalProperties": false
+            }
+          },
+          "required": [
+            "dataType",
+            "predicates",
+            "subscription"
+          ],
+          "type": "object",
+          "additionalProperties": false
+        }
+      },
+      "type": "object",
+      "additionalProperties": false,
+      "required": [
+        "data"
+      ]
+    },
+    "CmHandle": {
+      "description": "The CM handle information",
+      "type": "object",
+      "properties": {
+        "id": {
+          "type": "string"
+        },
+        "additional-properties": {
+          "existingJavaType": "java.util.Map<String,String>"
+        }
+      },
+      "required": [
+        "id",
+        "additional-properties"
+      ],
+      "additionalProperties": false
+    }
+  }
+}
\ No newline at end of file
diff --git a/cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-dmi-out-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-dmi-out-event-schema-1.0.0.json
new file mode 100644 (file)
index 0000000..ebbdde9
--- /dev/null
@@ -0,0 +1,69 @@
+{
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-dmi-out-event-schema:1.0.0",
+  "$ref": "#/definitions/CmSubscriptionDmiOutEvent",
+  "definitions": {
+    "SubscriptionStatus": {
+      "description": "The subscription status information",
+      "type": "object",
+      "properties": {
+        "id": {
+          "type": "string"
+        },
+        "status" : {
+          "type": "string",
+          "enum": [
+            "ACCEPTED",
+            "REJECTED"
+          ]
+        },
+        "details" : {
+          "type": "string"
+        }
+      },
+      "required": [
+        "id",
+        "status"
+      ],
+      "additionalProperties": false
+    },
+    "CmSubscriptionDmiOutEvent" : {
+      "description": "The payload for subscription response event.",
+      "type": "object",
+      "javaType": "org.onap.cps.ncmp.events.cmsubscription1_0_0.dmi_to_ncmp.CmSubscriptionDmiOutEvent",
+      "properties": {
+        "data": {
+          "type": "object",
+          "properties": {
+            "clientId": {
+              "type": "string"
+            },
+            "subscriptionName": {
+              "type": "string"
+            },
+            "dmiName": {
+              "type": "string"
+            },
+            "subscriptionStatus": {
+              "type": "array",
+              "items": {
+                "$ref": "#/definitions/SubscriptionStatus"
+              }
+            }
+          },
+          "required": [
+            "clientId",
+            "subscriptionName",
+            "dmiName",
+            "subscriptionStatus"
+          ],
+          "additionalProperties": false
+        }
+      },
+      "additionalProperties": false,
+      "required": [
+        "data"
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-ncmp-in-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-ncmp-in-event-schema-1.0.0.json
new file mode 100644 (file)
index 0000000..818a8e7
--- /dev/null
@@ -0,0 +1,99 @@
+{
+  "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-ncmp-in-event:1.0.0",
+  "$ref": "#/definitions/CmSubscriptionNcmpInEvent",
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "definitions": {
+    "CmSubscriptionNcmpInEvent": {
+      "description": "The payload for subscription event.",
+      "javaType": "org.onap.cps.ncmp.events.cmsubscription1_0_0.client_to_ncmp.CmSubscriptionNcmpInEvent",
+      "properties": {
+        "data": {
+          "properties": {
+            "dataType": {
+              "description": "The datatype content.",
+              "properties": {
+                "dataCategory": {
+                  "description": "The category type of the data",
+                  "type": "string"
+                },
+                "dataProvider": {
+                  "description": "The provider name of the data",
+                  "type": "string"
+                },
+                "dataspace": {
+                  "description": "The dataspace name",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "dataCategory",
+                "dataProvider",
+                "dataspace"
+              ],
+              "type": "object",
+              "additionalProperties": false
+            },
+            "predicates": {
+              "description": "Additional values to be added into the subscription",
+              "properties": {
+                "datastore": {
+                  "description": "datastore which is to be used by the subscription",
+                  "type": "string"
+                },
+                "targets": {
+                  "description": "CM Handles to be targeted by the subscription",
+                  "type": "array",
+                  "items": {
+                    "type": "string"
+                  }
+                },
+                "datastore-xpath-filter": {
+                  "description": "filter to be applied to the CM Handles through this event",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "datastore",
+                "targets",
+                "datastore-xpath-filter"
+              ],
+              "type": "object",
+              "additionalProperties": false
+            },
+            "subscription": {
+              "description": "The subscription details.",
+              "properties": {
+                "clientID": {
+                  "description": "The clientID",
+                  "type": "string"
+                },
+                "name": {
+                  "description": "The name of the subscription",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "clientID",
+                "name"
+              ],
+              "type": "object",
+              "additionalProperties": false
+            }
+          },
+          "required": [
+            "dataType",
+            "predicates",
+            "subscription"
+          ],
+          "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/deprecated.cmsubscription/cm-subscription-ncmp-out-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/deprecated.cmsubscription/cm-subscription-ncmp-out-event-schema-1.0.0.json
new file mode 100644 (file)
index 0000000..9c0c28b
--- /dev/null
@@ -0,0 +1,69 @@
+{
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "$id": "urn:cps:org.onap.cps.ncmp.events:cm-subscription-ncmp-out-event-schema:1.0.0",
+  "$ref": "#/definitions/CmSubscriptionNcmpOutEvent",
+  "definitions": {
+    "CmSubscriptionNcmpOutEvent": {
+      "description": "The payload for avc subscription event outcome message.",
+      "type": "object",
+      "javaType": "org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_client.CmSubscriptionNcmpOutEvent",
+      "additionalProperties": false,
+      "properties": {
+        "data": {
+          "$ref": "#/definitions/data"
+        }
+      },
+      "required": [
+        "data"
+      ]
+    },
+    "data": {
+      "type": "object",
+      "description": "The actual data containing information about the pending and rejected targets",
+      "additionalProperties": false,
+      "properties": {
+        "statusCode": {
+          "type": "integer"
+        },
+        "statusMessage": {
+          "type": "string"
+        },
+        "additionalInfo": {
+          "type": "object",
+          "additionalProperties": false,
+          "properties": {
+            "rejected": {
+              "$ref": "#/definitions/additionalInfoDetails"
+            },
+            "pending": {
+              "$ref": "#/definitions/additionalInfoDetails"
+            }
+          }
+        }
+      },
+      "required": [
+        "statusCode",
+        "statusMessage"
+      ]
+    },
+    "additionalInfoDetails": {
+      "type": "array",
+      "items": {
+        "type": "object",
+        "description": "Details for the target cmhandles",
+        "additionalProperties": false,
+        "properties": {
+          "details": {
+            "type": "string"
+          },
+          "targets": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
index 602df4f..554bfd4 100644 (file)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-ncmp-rest-stub</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
     </parent>
 
     <artifactId>cps-ncmp-rest-stub-app</artifactId>
index 126bdc7..7a94305 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-ncmp-rest-stub</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
     </parent>
     <artifactId>cps-ncmp-rest-stub-service</artifactId>
 
index 26c95ab..3b1192f 100644 (file)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index 9b5a1fd..3bee633 100644 (file)
@@ -140,6 +140,9 @@ components:
             type: string
             enum: [COMPLETE, NONE]
             example: "COMPLETE"
+        alternateId:
+          type: string
+          example: "my-alternate-id"
     RestCmHandleProperties:
       type: object
       additionalProperties:
@@ -158,6 +161,7 @@ components:
           example: [ my-cm-handle1, my-cm-handle2, my-cm-handle3 ]
         moduleSetTag:
           type: string
+          default: ""
           example: 'my-module-set-tag'
 
     #Response Schemas
index f34bfd4..25f9c5a 100644 (file)
@@ -27,7 +27,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index c4dd91e..0bc0c1e 100644 (file)
@@ -41,7 +41,7 @@ class NcmpRestInputMapperSpec extends Specification {
     def 'Convert a created REST CM Handle Input to an NCMP Service CM Handle with #scenario'() {
         given: 'a rest cm handle input'
             def inputRestCmHandle = new RestInputCmHandle(cmHandle : 'example-id', cmHandleProperties: registrationDmiProperties,
-                publicCmHandleProperties: registrationPublicProperties, trustLevel: registrationTrustLevel)
+                publicCmHandleProperties: registrationPublicProperties, trustLevel: registrationTrustLevel, alternateId: 'my-alternate-id', moduleSetTag: 'my-module-set-tag')
             def restDmiPluginRegistration = new RestDmiPluginRegistration(
                 createdCmHandles: [inputRestCmHandle])
         when: 'to plugin dmi registration is called'
@@ -54,6 +54,9 @@ class NcmpRestInputMapperSpec extends Specification {
             result.createdCmHandles[0].dmiProperties == mappedDmiProperties
             result.createdCmHandles[0].publicProperties == mappedPublicProperties
             result.createdCmHandles[0].registrationTrustLevel == mappedTrustLevel
+        and: 'alternate ID and module set tag converted correctly'
+            result.createdCmHandles[0].alternateId == 'my-alternate-id'
+            result.createdCmHandles[0].moduleSetTag == 'my-module-set-tag'
         where: 'the following parameters are used'
             scenario                    | registrationDmiProperties                | registrationPublicProperties                           | registrationTrustLevel || mappedDmiProperties                      | mappedPublicProperties                                 | mappedTrustLevel
             'dmi and public properties' | ['Property-Example': 'example property'] | ['Public-Property-Example': 'public example property'] | 'COMPLETE'             || ['Property-Example': 'example property'] | ['Public-Property-Example': 'public example property'] | TrustLevel.COMPLETE
index 870c36c..5559016 100644 (file)
@@ -26,7 +26,6 @@ import ch.qos.logback.classic.spi.ILoggingEvent
 import ch.qos.logback.core.read.ListAppender
 import org.junit.jupiter.api.AfterEach
 import org.junit.jupiter.api.BeforeEach
-import org.onap.cps.notification.NotificationErrorHandler
 import org.slf4j.LoggerFactory
 import spock.lang.Specification
 
@@ -44,7 +43,7 @@ class CpsNcmpTaskExecutorSpec extends Specification {
 
     @AfterEach
     void teardown() {
-        ((Logger) LoggerFactory.getLogger(NotificationErrorHandler.class)).detachAndStopAllAppenders();
+        ((Logger) LoggerFactory.getLogger(CpsNcmpTaskExecutor.class)).detachAndStopAllAppenders();
     }
 
     def 'Execute successful task.'() {
index f448c8f..8cc58c1 100644 (file)
@@ -27,7 +27,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents.client5</groupId>
+            <artifactId>httpclient5</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.cloudevents</groupId>
             <artifactId>cloudevents-json-jackson</artifactId>
index 1afe5c7..469d75a 100755 (executable)
@@ -328,7 +328,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
                             dmiPluginRegistration.getDmiDataPlugin(),
                             dmiPluginRegistration.getDmiModelPlugin(),
                             cmHandle,
-                            cmHandle.getModuleSetTag());
+                            cmHandle.getModuleSetTag(),
+                            cmHandle.getAlternateId());
                     yangModelCmHandles.add(yangModelCmHandle);
                     initialTrustLevelPerCmHandleId.put(cmHandle.getCmHandleId(), cmHandle.getRegistrationTrustLevel());
                 });
@@ -420,7 +421,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
                 .withLockReason(MODULE_UPGRADE, lockReasonWithModuleSetTag).build());
         return YangModelCmHandle.toYangModelCmHandle(dmiPluginRegistration.getDmiPlugin(),
                 dmiPluginRegistration.getDmiDataPlugin(), dmiPluginRegistration.getDmiModelPlugin(),
-                ncmpServiceCmHandle, moduleSetTag);
+                ncmpServiceCmHandle, moduleSetTag, ncmpServiceCmHandle.getAlternateId());
     }
 
     private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java
new file mode 100644 (file)
index 0000000..729930e
--- /dev/null
@@ -0,0 +1,57 @@
+/*-
+ * ============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.config;
+
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.convert.DurationUnit;
+
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "ncmp.dmi.httpclient", ignoreUnknownFields = true)
+public class HttpClientConfiguration {
+
+    /**
+     * The maximum time to establish a connection.
+     */
+    @DurationUnit(ChronoUnit.SECONDS)
+    private Duration connectionTimeoutInSeconds = Duration.ofSeconds(180);
+
+    /**
+     * The maximum number of open connections per route.
+     */
+    private int maximumConnectionsPerRoute = 50;
+
+    /**
+     * The maximum total number of open connections.
+     */
+    private int maximumConnectionsTotal = maximumConnectionsPerRoute * 2;
+
+    /**
+     * The duration after which idle connections are evicted.
+     */
+    @DurationUnit(ChronoUnit.SECONDS)
+    private Duration idleConnectionEvictionThresholdInSeconds = Duration.ofSeconds(5);
+
+}
index ffecf9c..c6ff116 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-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.
 
 package org.onap.cps.ncmp.api.impl.config;
 
-import java.time.Duration;
 import java.util.Arrays;
 import lombok.AccessLevel;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.boot.web.client.RestTemplateBuilder;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Scope;
 import org.springframework.http.MediaType;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
 
 @Configuration
+@EnableConfigurationProperties(HttpClientConfiguration.class)
 @RequiredArgsConstructor(access = AccessLevel.PROTECTED)
 public class NcmpConfiguration {
 
-    private static final Duration CONNECTION_TIMEOUT_MILLISECONDS = Duration.ofMillis(180000);
-    private static final Duration READ_TIMEOUT_MILLISECONDS = Duration.ofMillis(180000);
-
     @Getter
     @Component
     public static class DmiProperties {
@@ -60,13 +67,38 @@ public class NcmpConfiguration {
      * Rest template bean.
      *
      * @param restTemplateBuilder the rest template builder
+     * @param httpClientConfiguration the http client configuration
      * @return rest template instance
      */
     @Bean
     @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
-    public static RestTemplate restTemplate(final RestTemplateBuilder restTemplateBuilder) {
-        final RestTemplate restTemplate = restTemplateBuilder.setConnectTimeout(CONNECTION_TIMEOUT_MILLISECONDS)
-                .setReadTimeout(READ_TIMEOUT_MILLISECONDS).build();
+    public static RestTemplate restTemplate(final RestTemplateBuilder restTemplateBuilder,
+                                            final HttpClientConfiguration httpClientConfiguration) {
+
+        final ConnectionConfig connectionConfig = ConnectionConfig.copy(ConnectionConfig.DEFAULT)
+                .setConnectTimeout(Timeout.of(httpClientConfiguration.getConnectionTimeoutInSeconds()))
+                .build();
+
+        final PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
+                .setDefaultConnectionConfig(connectionConfig)
+                .setMaxConnTotal(httpClientConfiguration.getMaximumConnectionsTotal())
+                .setMaxConnPerRoute(httpClientConfiguration.getMaximumConnectionsPerRoute())
+                .build();
+
+        final CloseableHttpClient httpClient = HttpClients.custom()
+                .setConnectionManager(connectionManager)
+                .evictExpiredConnections()
+                .evictIdleConnections(
+                        TimeValue.of(httpClientConfiguration.getIdleConnectionEvictionThresholdInSeconds()))
+                .build();
+
+        final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
+
+        final RestTemplate restTemplate = restTemplateBuilder
+                .requestFactory(() -> requestFactory)
+                .setConnectTimeout(httpClientConfiguration.getConnectionTimeoutInSeconds())
+                .build();
+
         setRestTemplateMessageConverters(restTemplate);
         return restTemplate;
     }
@@ -18,7 +18,7 @@
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription;
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription;
 
 import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent;
 
@@ -30,7 +30,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.kafka.clients.consumer.ConsumerRecord;
 import org.onap.cps.ncmp.api.impl.config.embeddedcache.ForwardedSubscriptionEventCacheConfig;
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistence;
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionPersistence;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent;
 import org.onap.cps.ncmp.api.models.CmSubscriptionEvent;
 import org.onap.cps.ncmp.events.cmsubscription1_0_0.dmi_to_ncmp.CmSubscriptionDmiOutEvent;
@@ -18,7 +18,7 @@
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription;
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription;
 
 import java.util.List;
 import java.util.stream.Collectors;
@@ -49,7 +49,8 @@ public interface CmSubscriptionDmiOutEventToYangModelSubscriptionEventMapper {
     default List<YangModelSubscriptionEvent.TargetCmHandle> mapSubscriptionStatusToCmHandleTargets(
             List<SubscriptionStatus> subscriptionStatus) {
         return subscriptionStatus.stream().map(status -> new YangModelSubscriptionEvent.TargetCmHandle(status.getId(),
-                org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus.fromString(status.getStatus().value()),
+                org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus.fromString(
+                        status.getStatus().value()),
                         status.getDetails())).collect(Collectors.toList());
     }
 }
@@ -18,7 +18,7 @@
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription;
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription;
 
 import java.util.List;
 import java.util.Map;
@@ -26,7 +26,7 @@ import java.util.stream.Collectors;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Named;
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus;
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus;
 import org.onap.cps.ncmp.api.models.CmSubscriptionEvent;
 import org.onap.cps.ncmp.api.models.CmSubscriptionStatus;
 import org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_client.AdditionalInfo;
@@ -18,7 +18,7 @@
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription;
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription;
 
 import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent;
 import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL;
@@ -28,7 +28,7 @@ import io.cloudevents.CloudEvent;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.kafka.clients.consumer.ConsumerRecord;
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistence;
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionPersistence;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent;
 import org.onap.cps.ncmp.events.cmsubscription1_0_0.client_to_ncmp.CmSubscriptionNcmpInEvent;
 import org.springframework.beans.factory.annotation.Value;
@@ -18,7 +18,7 @@
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription;
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription;
 
 import com.hazelcast.map.IMap;
 import io.cloudevents.CloudEvent;
@@ -37,10 +37,10 @@ import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.impl.config.embeddedcache.ForwardedSubscriptionEventCacheConfig;
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionPersistence;
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus;
 import org.onap.cps.ncmp.api.impl.events.EventsPublisher;
 import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistence;
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus;
 import org.onap.cps.ncmp.api.impl.utils.CmSubscriptionEventCloudMapper;
 import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription;
+package org.onap.cps.ncmp.api.impl.events.deprecated.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 static org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus.ACCEPTED;
+import static org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus.PENDING;
+import static org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus.REJECTED;
 
 import io.cloudevents.CloudEvent;
 import java.util.List;
@@ -34,9 +34,9 @@ import java.util.Map;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.NcmpResponseStatus;
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionPersistence;
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus;
 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;
 import org.onap.cps.ncmp.api.impl.utils.DataNodeHelper;
 import org.onap.cps.ncmp.api.impl.utils.SubscriptionOutcomeCloudMapper;
 import org.onap.cps.ncmp.api.models.CmSubscriptionEvent;
index 159d8f3..a0aeac3 100644 (file)
@@ -29,7 +29,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsAnchorService;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.api.CpsModuleService;
 import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
@@ -48,7 +48,7 @@ import org.springframework.stereotype.Component;
 public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements InventoryPersistence {
 
     private final CpsModuleService cpsModuleService;
-    private final CpsAdminService cpsAdminService;
+    private final CpsAnchorService cpsAnchorService;
     private final CpsValidator cpsValidator;
 
     /**
@@ -58,14 +58,14 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
      * @param cpsDataService   cps data service instance
      * @param cpsModuleService cps module service instance
      * @param cpsValidator     cps validation service instance
-     * @param cpsAdminService  cps admin service instance
+     * @param cpsAnchorService  cps anchor service instance
      */
     public InventoryPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService,
                                     final CpsModuleService cpsModuleService, final CpsValidator cpsValidator,
-                                    final CpsAdminService cpsAdminService) {
+                                    final CpsAnchorService cpsAnchorService) {
         super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator);
         this.cpsModuleService = cpsModuleService;
-        this.cpsAdminService = cpsAdminService;
+        this.cpsAnchorService = cpsAnchorService;
         this.cpsValidator = cpsValidator;
     }
 
@@ -160,7 +160,7 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
 
     @Override
     public Collection<String> getCmHandleIdsWithGivenModules(final Collection<String> moduleNamesForQuery) {
-        return cpsAdminService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery);
+        return cpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery);
     }
 
     private static String createCmHandleXPath(final String cmHandleId) {
index 25ea3bc..750be2d 100644 (file)
@@ -38,6 +38,7 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 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;
@@ -64,7 +65,7 @@ public class ModuleOperationsUtils {
     public static final String MODULE_SET_TAG_KEY = "moduleSetTag";
     public static final String MODULE_SET_TAG_MESSAGE_FORMAT = "Upgrade to ModuleSetTag: {0}";
     private static final String UPGRADE_FORMAT = "Upgrade to ModuleSetTag: %s";
-    private static final String UPGRADE_FAILED_FORMAT = UPGRADE_FORMAT + " Attempt #%d failed: %s";
+    private static final String LOCK_REASON_DETAILS_MSG_FORMAT = UPGRADE_FORMAT + " Attempt #%d failed: %s";
     private static final Pattern retryAttemptPattern = Pattern.compile("Attempt #(\\d+) failed:.+");
     private static final Pattern moduleSetTagPattern = Pattern.compile("Upgrade to ModuleSetTag: (\\S+)");
 
@@ -127,13 +128,14 @@ public class ModuleOperationsUtils {
         int attempt = 1;
         final Map<String, String> compositeStateDetails
                 = getLockedCompositeStateDetails(compositeState.getLockReason());
-        if (!compositeStateDetails.isEmpty()) {
+        if (!compositeStateDetails.isEmpty() && compositeStateDetails.containsKey(RETRY_ATTEMPT_KEY)) {
             attempt = 1 + Integer.parseInt(compositeStateDetails.get(RETRY_ATTEMPT_KEY));
         }
+        final String moduleSetTag = compositeStateDetails.get(MODULE_SET_TAG_KEY);
         compositeState.setLockReason(CompositeState.LockReason.builder()
-                .details(String.format(UPGRADE_FAILED_FORMAT,
-                        compositeStateDetails.get(MODULE_SET_TAG_KEY), attempt, errorMessage))
-                .lockReasonCategory(lockReasonCategory).build());
+                .details(String.format(LOCK_REASON_DETAILS_MSG_FORMAT, StringUtils.isNotBlank(moduleSetTag)
+                        ? moduleSetTag : "not-specified", attempt, errorMessage)).lockReasonCategory(lockReasonCategory)
+                .build());
     }
 
     /**
@@ -174,13 +176,19 @@ public class ModuleOperationsUtils {
                 DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
         final CompositeState.LockReason lockReason = compositeState.getLockReason();
 
+        final boolean moduleUpgrade = LockReasonCategory.MODULE_UPGRADE == lockReason.getLockReasonCategory();
+        if (moduleUpgrade) {
+            log.info("Locked for module upgrade");
+            return true;
+        }
+
         final boolean failedDuringModuleSync = LockReasonCategory.MODULE_SYNC_FAILED
                 == lockReason.getLockReasonCategory();
         final boolean failedDuringModuleUpgrade = LockReasonCategory.MODULE_UPGRADE_FAILED
                 == lockReason.getLockReasonCategory();
 
         if (failedDuringModuleSync || failedDuringModuleUpgrade) {
-            log.info("Locked for module {}.", failedDuringModuleSync ? "sync" : "upgrade");
+            log.info("Locked for module {} (last attempt failed).", failedDuringModuleSync ? "sync" : "upgrade");
             return isRetryDue(lockReason, time);
         }
         log.info("Locked for other reason");
index 841368c..b21a2f1 100644 (file)
@@ -35,7 +35,7 @@ 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.CpsAnchorService;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.api.CpsModuleService;
 import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
@@ -59,9 +59,9 @@ 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 CpsAnchorService cpsAnchorService;
     private final JsonObjectMapper jsonObjectMapper;
     private final Map<String, Collection<ModuleReference>> moduleSetTagCache;
     private static final Map<String, String> NO_NEW_MODULES = Collections.emptyMap();
@@ -73,60 +73,43 @@ public class ModuleSyncService {
      */
     public void syncAndCreateOrUpgradeSchemaSetAndAnchor(final YangModelCmHandle yangModelCmHandle) {
 
-        final String moduleSetTag;
         final String cmHandleId = yangModelCmHandle.getId();
         final CompositeState compositeState = yangModelCmHandle.getCompositeState();
         final boolean inUpgrade = ModuleOperationsUtils.isInUpgradeOrUpgradeFailed(compositeState);
-
-        if (inUpgrade) {
-            moduleSetTag = ModuleOperationsUtils.getLockedCompositeStateDetails(compositeState.getLockReason())
-                    .get(ModuleOperationsUtils.MODULE_SET_TAG_KEY);
-        } else {
-            moduleSetTag = yangModelCmHandle.getModuleSetTag();
-        }
+        final String moduleSetTag = getModuleSetTag(yangModelCmHandle, compositeState, inUpgrade);
 
         final Collection<ModuleReference> moduleReferencesFromCache = moduleSetTagCache.get(moduleSetTag);
 
         if (moduleReferencesFromCache == null) {
-            final Optional<DataNode> optionalExistingCmHandleWithSameModuleSetTag
+            final Optional<DataNode> existingCmHandleWithSameModuleSetTag
                     = getFirstReadyDataNodeWithModuleSetTag(moduleSetTag);
 
-            if (optionalExistingCmHandleWithSameModuleSetTag.isPresent()) {
-                final String existingCmHandleAnchorName
-                        = optionalExistingCmHandleWithSameModuleSetTag.get().getAnchorName();
-                createOrUpgradeSchemaSetUsingModuleSetTag(cmHandleId, moduleSetTag, existingCmHandleAnchorName);
+            if (existingCmHandleWithSameModuleSetTag.isPresent()) {
+                final String existingAnchorName = existingCmHandleWithSameModuleSetTag.get().getAnchorName();
+                final Collection<ModuleReference> moduleReferencesFromExistingCmHandle =
+                        upgradeOrCreateSchemaSetUsingModuleSetTag(yangModelCmHandle.getId(), moduleSetTag,
+                                existingAnchorName, inUpgrade);
+                updateModuleSetTagCache(moduleSetTag, moduleReferencesFromExistingCmHandle);
             } else {
-                syncAndCreateSchemaSet(yangModelCmHandle, moduleSetTag);
+                final Collection<ModuleReference> allModuleReferencesFromCmHandle
+                        = syncAndCreateSchemaSet(yangModelCmHandle);
+                updateModuleSetTagCache(moduleSetTag, allModuleReferencesFromCmHandle);
             }
         } else {
-            cpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
-                    cmHandleId, NO_NEW_MODULES, moduleReferencesFromCache);
+            if (inUpgrade) {
+                cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
+                        NO_NEW_MODULES, moduleReferencesFromCache);
+            } else {
+                cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
+                        cmHandleId, NO_NEW_MODULES, moduleReferencesFromCache);
+            }
         }
         if (!inUpgrade) {
-            cpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cmHandleId);
+            cpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cmHandleId);
         }
         setCmHandleModuleSetTag(yangModelCmHandle, moduleSetTag);
     }
 
-    private void syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle, final String moduleSetTag) {
-        final Collection<ModuleReference> allModuleReferencesFromCmHandle =
-                dmiModelOperations.getModuleReferences(yangModelCmHandle);
-        final Collection<ModuleReference> identifiedNewModuleReferencesFromCmHandle = cpsModuleService
-                .identifyNewModuleReferences(allModuleReferencesFromCmHandle);
-        final Map<String, String> newModuleNameToContentMap;
-        if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) {
-            newModuleNameToContentMap = NO_NEW_MODULES;
-        } else {
-            newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle,
-                    identifiedNewModuleReferencesFromCmHandle);
-        }
-        cpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
-            yangModelCmHandle.getId(), newModuleNameToContentMap, allModuleReferencesFromCmHandle);
-        if (StringUtils.isNotBlank(moduleSetTag)) {
-            moduleSetTagCache.put(moduleSetTag, allModuleReferencesFromCmHandle);
-        }
-    }
-
     /**
      * Deletes the SchemaSet for schema set id if the SchemaSet Exists.
      *
@@ -162,16 +145,56 @@ public class ModuleSyncService {
                 jsonObjectMapper.asJsonString(dmiRegistryProperties), OffsetDateTime.now());
     }
 
-    private void createOrUpgradeSchemaSetUsingModuleSetTag(final String schemaSetName,
-                                                           final String moduleSetTag,
-                                                           final String existingCmHandleAnchorName) {
+    private Collection<ModuleReference> syncAndCreateSchemaSet(final YangModelCmHandle yangModelCmHandle) {
+        final Collection<ModuleReference> allModuleReferencesFromCmHandle =
+                dmiModelOperations.getModuleReferences(yangModelCmHandle);
+        final Collection<ModuleReference> identifiedNewModuleReferencesFromCmHandle = cpsModuleService
+                .identifyNewModuleReferences(allModuleReferencesFromCmHandle);
+        final Map<String, String> newModuleNameToContentMap;
+        if (identifiedNewModuleReferencesFromCmHandle.isEmpty()) {
+            newModuleNameToContentMap = NO_NEW_MODULES;
+        } else {
+            newModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(yangModelCmHandle,
+                    identifiedNewModuleReferencesFromCmHandle);
+        }
+        cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
+                yangModelCmHandle.getId(), newModuleNameToContentMap, allModuleReferencesFromCmHandle);
+        return allModuleReferencesFromCmHandle;
+    }
+
+    private Collection<ModuleReference> upgradeOrCreateSchemaSetUsingModuleSetTag(final String schemaSetName,
+                                                                                  final String moduleSetTag,
+                                                                                  final String existingAnchorName,
+                                                                                  final boolean inUpgrade) {
         log.info("Found cm handle having module set tag: {}", moduleSetTag);
         final Collection<ModuleReference> moduleReferencesFromExistingCmHandle =
                 cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
-                        existingCmHandleAnchorName);
-        cpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
-            schemaSetName, NO_NEW_MODULES, moduleReferencesFromExistingCmHandle);
-        moduleSetTagCache.put(moduleSetTag, moduleReferencesFromExistingCmHandle);
+                        existingAnchorName);
+        if (inUpgrade) {
+            cpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName,
+                    NO_NEW_MODULES, moduleReferencesFromExistingCmHandle);
+        } else {
+            cpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME,
+                    schemaSetName, NO_NEW_MODULES, moduleReferencesFromExistingCmHandle);
+        }
+        return moduleReferencesFromExistingCmHandle;
+    }
+
+    private String getModuleSetTag(final YangModelCmHandle yangModelCmHandle,
+                                   final CompositeState compositeState,
+                                   final boolean inUpgrade) {
+        if (inUpgrade) {
+            return ModuleOperationsUtils.getLockedCompositeStateDetails(compositeState.getLockReason())
+                    .get(ModuleOperationsUtils.MODULE_SET_TAG_KEY);
+        }
+        return yangModelCmHandle.getModuleSetTag();
+    }
+
+    private void updateModuleSetTagCache(final String moduleSetTag,
+                                         final Collection<ModuleReference> allModuleReferencesFromCmHandle) {
+        if (StringUtils.isNotBlank(moduleSetTag)) {
+            moduleSetTagCache.putIfAbsent(moduleSetTag, allModuleReferencesFromCmHandle);
+        }
     }
 
 }
index 896316a..e214044 100644 (file)
@@ -67,20 +67,20 @@ public class ModuleSyncTasks {
                 final YangModelCmHandle yangModelCmHandle =
                         YangDataConverter.convertCmHandleToYangModel(cmHandleAsDataNode, cmHandleId);
                 final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId);
+                final boolean inUpgrade = ModuleOperationsUtils.isInUpgradeOrUpgradeFailed(compositeState);
                 try {
-                    moduleSyncService.deleteSchemaSetIfExists(cmHandleId);
+                    if (!inUpgrade) {
+                        moduleSyncService.deleteSchemaSetIfExists(cmHandleId);
+                    }
                     moduleSyncService.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle);
                     yangModelCmHandle.getCompositeState().setLockReason(null);
                     cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.READY);
                 } catch (final Exception e) {
                     log.warn("Processing of {} module failed due to reason {}.", cmHandleId, e.getMessage());
-                    if (ModuleOperationsUtils.isInUpgradeOrUpgradeFailed(compositeState)) {
-                        moduleOperationsUtils.updateLockReasonDetailsAndAttempts(compositeState,
-                                LockReasonCategory.MODULE_UPGRADE_FAILED, e.getMessage());
-                    } else {
-                        moduleOperationsUtils.updateLockReasonDetailsAndAttempts(compositeState,
-                                LockReasonCategory.MODULE_SYNC_FAILED, e.getMessage());
-                    }
+                    final LockReasonCategory lockReasonCategory = inUpgrade ? LockReasonCategory.MODULE_UPGRADE_FAILED
+                            : LockReasonCategory.MODULE_SYNC_FAILED;
+                    moduleOperationsUtils.updateLockReasonDetailsAndAttempts(compositeState,
+                            lockReasonCategory, e.getMessage());
                     setCmHandleStateLocked(yangModelCmHandle, compositeState.getLockReason());
                     cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED);
                 }
index b6a04d3..b54c154 100644 (file)
@@ -87,7 +87,8 @@ public class YangDataConverter {
                 (String) cmHandleDataNode.getLeaves().get("dmi-data-service-name"),
                 (String) cmHandleDataNode.getLeaves().get("dmi-model-service-name"),
                 ncmpServiceCmHandle,
-                (String) cmHandleDataNode.getLeaves().get("module-set-tag")
+                (String) cmHandleDataNode.getLeaves().get("module-set-tag"),
+                (String) cmHandleDataNode.getLeaves().get("alternate-id")
         );
     }
 
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmDataSubscriptionEvent.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmDataSubscriptionEvent.java
new file mode 100644 (file)
index 0000000..e527d99
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  ============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.yangmodels;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Subscription event model to persist data into DB.
+ * Yang model subscription event
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@JsonInclude(Include.NON_NULL)
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+public class YangModelCmDataSubscriptionEvent {
+
+    @EqualsAndHashCode.Include
+    @JsonProperty("name")
+    private String name;
+
+    private List<CmHandle> cmHandles;
+
+    @AllArgsConstructor
+    @Data
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    public static class CmHandle {
+
+        @JsonProperty()
+        private final String id;
+
+        private final List<Filter> filters;
+    }
+
+    @AllArgsConstructor
+    @Data
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    public static class Filter {
+
+        @JsonProperty()
+        private final String id;
+
+        @JsonProperty()
+        private final List<String> subscribers;
+    }
+}
+
+
index f930d5b..ba36b1a 100644 (file)
@@ -68,6 +68,9 @@ public class YangModelCmHandle {
     @JsonProperty("module-set-tag")
     private String moduleSetTag;
 
+    @JsonProperty("alternate-id")
+    private String alternateId;
+
     @JsonProperty("additional-properties")
     private List<Property> dmiProperties;
 
@@ -91,6 +94,7 @@ public class YangModelCmHandle {
         copy.dmiProperties = original.getDmiProperties() == null ? null : new ArrayList<>(original.getDmiProperties());
         copy.publicProperties =
                 original.getPublicProperties() == null ? null : new ArrayList<>(original.getPublicProperties());
+        copy.alternateId = original.getAlternateId();
         return copy;
     }
 
@@ -107,13 +111,15 @@ public class YangModelCmHandle {
                                                         final String dmiDataServiceName,
                                                         final String dmiModelServiceName,
                                                         final NcmpServiceCmHandle ncmpServiceCmHandle,
-                                                        final String moduleSetTag) {
+                                                        final String moduleSetTag,
+                                                        final String alternateId) {
         final YangModelCmHandle yangModelCmHandle = new YangModelCmHandle();
         yangModelCmHandle.setId(ncmpServiceCmHandle.getCmHandleId());
         yangModelCmHandle.setDmiServiceName(dmiServiceName);
         yangModelCmHandle.setDmiDataServiceName(dmiDataServiceName);
         yangModelCmHandle.setDmiModelServiceName(dmiModelServiceName);
         yangModelCmHandle.setModuleSetTag(moduleSetTag == null ? StringUtils.EMPTY : moduleSetTag);
+        yangModelCmHandle.setAlternateId(alternateId);
         yangModelCmHandle.setDmiProperties(asYangModelCmHandleProperties(ncmpServiceCmHandle.getDmiProperties()));
         yangModelCmHandle.setPublicProperties(asYangModelCmHandleProperties(
                 ncmpServiceCmHandle.getPublicProperties()));
index 866bfd4..a6cfa7b 100644 (file)
@@ -31,7 +31,7 @@ import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus;
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus;
 
 /**
  * Subscription event model to persist data into DB.
index 5541a01..c569123 100644 (file)
@@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import jakarta.validation.constraints.NotNull;
 import lombok.Getter;
 import lombok.Setter;
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus;
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus;
 
 @JsonInclude(JsonInclude.Include.NON_NULL)
 @Getter
index f323079..4989878 100644 (file)
@@ -23,7 +23,6 @@ package org.onap.cps.ncmp.api.models;
 import com.fasterxml.jackson.annotation.JsonSetter;
 import com.fasterxml.jackson.annotation.Nulls;
 import java.util.Collections;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
@@ -59,18 +58,6 @@ public class NcmpServiceCmHandle {
     @JsonSetter(nulls = Nulls.AS_EMPTY)
     private TrustLevel registrationTrustLevel;
 
-    /**
-     * NcmpServiceCmHandle copy constructor.
-     *
-     * @param ncmpServiceCmHandle Ncmp Service CmHandle
-     */
-    public NcmpServiceCmHandle(final NcmpServiceCmHandle ncmpServiceCmHandle) {
-        this.cmHandleId = ncmpServiceCmHandle.getCmHandleId();
-        this.dmiProperties = new LinkedHashMap<>(ncmpServiceCmHandle.getDmiProperties());
-        this.publicProperties = new LinkedHashMap<>(ncmpServiceCmHandle.getPublicProperties());
-        this.compositeState = ncmpServiceCmHandle.getCompositeState() != null ? new CompositeState(
-                ncmpServiceCmHandle.getCompositeState()) : null;
-        this.moduleSetTag = ncmpServiceCmHandle.getModuleSetTag();
-        this.registrationTrustLevel = ncmpServiceCmHandle.getRegistrationTrustLevel();
-    }
+    @JsonSetter(nulls = Nulls.AS_EMPTY)
+    private String alternateId;
 }
index 05663a5..cabd868 100644 (file)
@@ -25,7 +25,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.Map;
 import lombok.Getter;
 import lombok.Setter;
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus;
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus;
 
 @JsonInclude(JsonInclude.Include.NON_NULL)
 @Getter
index fd5f2b0..bd8dec4 100644 (file)
@@ -29,8 +29,9 @@ import java.util.Map;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsAnchorService;
 import org.onap.cps.api.CpsDataService;
+import org.onap.cps.api.CpsDataspaceService;
 import org.onap.cps.api.CpsModuleService;
 import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException;
 import org.onap.cps.spi.CascadeDeleteAllowed;
@@ -44,9 +45,10 @@ import org.springframework.boot.context.event.ApplicationReadyEvent;
 @RequiredArgsConstructor
 abstract class AbstractModelLoader implements ModelLoader {
 
-    private final CpsAdminService cpsAdminService;
+    private final CpsDataspaceService cpsDataspaceService;
     private final CpsModuleService cpsModuleService;
     private final CpsDataService cpsDataService;
+    private final CpsAnchorService cpsAnchorService;
 
     private static final int EXIT_CODE_ON_ERROR = 1;
 
@@ -71,7 +73,7 @@ abstract class AbstractModelLoader implements ModelLoader {
     void waitUntilDataspaceIsAvailable(final String dataspaceName) {
         log.info("Model Loader start-up, waiting for database to be ready");
         int attemptCount = 0;
-        while (cpsAdminService.getDataspace(dataspaceName) == null) {
+        while (cpsDataspaceService.getDataspace(dataspaceName) == null) {
             if (attemptCount < maximumAttemptCount) {
                 try {
                     Thread.sleep(attemptCount * retryTimeMs);
@@ -111,7 +113,7 @@ abstract class AbstractModelLoader implements ModelLoader {
 
     void createAnchor(final String dataspaceName, final String schemaSetName, final String anchorName) {
         try {
-            cpsAdminService.createAnchor(dataspaceName, schemaSetName, anchorName);
+            cpsAnchorService.createAnchor(dataspaceName, schemaSetName, anchorName);
         } catch (final AlreadyDefinedException alreadyDefinedException) {
             log.warn("Creating new anchor failed as anchor already exists");
         } catch (final Exception exception) {
@@ -134,7 +136,7 @@ abstract class AbstractModelLoader implements ModelLoader {
 
     void updateAnchorSchemaSet(final String dataspaceName, final String anchorName, final String schemaSetName) {
         try {
-            cpsAdminService.updateAnchorSchemaSet(dataspaceName, anchorName, schemaSetName);
+            cpsAnchorService.updateAnchorSchemaSet(dataspaceName, anchorName, schemaSetName);
         } catch (final Exception exception) {
             log.error("Updating schema set failed: {}", exception.getMessage());
             throw new NcmpStartUpException("Updating schema set failed", exception.getMessage());
index ade31e9..c0f0279 100644 (file)
@@ -23,8 +23,9 @@ package org.onap.cps.ncmp.init;
 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME;
 
 import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsAnchorService;
 import org.onap.cps.api.CpsDataService;
+import org.onap.cps.api.CpsDataspaceService;
 import org.onap.cps.api.CpsModuleService;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
@@ -45,10 +46,11 @@ public class CmDataSubscriptionModelLoader extends AbstractModelLoader {
 
 
 
-    public CmDataSubscriptionModelLoader(final CpsAdminService cpsAdminService,
+    public CmDataSubscriptionModelLoader(final CpsDataspaceService cpsDataspaceService,
                                          final CpsModuleService cpsModuleService,
-                                         final CpsDataService cpsDataService) {
-        super(cpsAdminService, cpsModuleService, cpsDataService);
+                                         final CpsDataService cpsDataService,
+                                         final CpsAnchorService cpsAnchorService) {
+        super(cpsDataspaceService, cpsModuleService, cpsDataService, cpsAnchorService);
     }
 
     @Value("${ncmp.model-loader.subscription:true}")
index b805cdc..0e562cd 100644 (file)
@@ -24,8 +24,9 @@ import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DA
 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR;
 
 import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsAnchorService;
 import org.onap.cps.api.CpsDataService;
+import org.onap.cps.api.CpsDataspaceService;
 import org.onap.cps.api.CpsModuleService;
 import org.springframework.stereotype.Service;
 
@@ -33,13 +34,14 @@ import org.springframework.stereotype.Service;
 @Service
 public class InventoryModelLoader extends AbstractModelLoader {
 
-    private static final String NEW_MODEL_FILE_NAME = "dmi-registry@2023-08-23.yang";
-    private static final String NEW_SCHEMA_SET_NAME = "dmi-registry-2023-08-23";
+    private static final String NEW_MODEL_FILE_NAME = "dmi-registry@2023-11-27.yang";
+    private static final String NEW_SCHEMA_SET_NAME = "dmi-registry-2023-11-27";
 
-    public InventoryModelLoader(final CpsAdminService cpsAdminService,
+    public InventoryModelLoader(final CpsDataspaceService cpsDataspaceService,
                                 final CpsModuleService cpsModuleService,
-                                final CpsDataService cpsDataService) {
-        super(cpsAdminService, cpsModuleService, cpsDataService);
+                                final CpsDataService cpsDataService,
+                                final CpsAnchorService cpsAnchorService) {
+        super(cpsDataspaceService, cpsModuleService, cpsDataService, cpsAnchorService);
     }
 
     @Override
@@ -8,19 +8,29 @@ module dmi-registry {
 
   contact "toine.siebelink@est.tech";
 
+  revision "2023-11-27" {
+    description
+    "Added alternate-id";
+  }
+
+  revision "2023-08-23" {
+    description
+    "Added module-set-tag";
+  }
+
   revision "2022-05-10" {
     description
-    "Added DataSyncEnabled, SyncState with State, LastSyncTime, DataStoreSyncState with Operational and Running syncstate";
+    "Added data-sync-enabled, sync-state with state, last-sync-time, data-store-sync-state with operational and running syncstate";
   }
 
   revision "2022-02-10" {
     description
-    "Added State, LockReason, LockReasonDetails to aid with cmHandle sync and timestamp to aid with retry/timeout scenarios";
+    "Added state, lock-reason, lock-reason-details to aid with cmHandle sync and timestamp to aid with retry/timeout scenarios";
   }
 
   revision "2021-12-13" {
     description
-    "Added new list of public additional properties for a Cm-Handle which are exposed to clients of the NCMP interface";
+    "Added new list of public-properties and additional-properties for a Cm-Handle which are exposed to clients of the NCMP interface";
   }
 
   revision "2021-10-20" {
@@ -75,6 +85,12 @@ module dmi-registry {
       leaf dmi-model-service-name {
         type string;
       }
+      leaf module-set-tag {
+        type string;
+      }
+      leaf alternate-id {
+        type string;
+      }
 
       list additional-properties {
         key "name";
@@ -120,4 +136,5 @@ module dmi-registry {
       }
     }
   }
-}
\ No newline at end of file
+}
+
index 51b00d1..f565ede 100644 (file)
@@ -210,12 +210,10 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
             }
         and: 'state handler is invoked with the expected parameters'
             1 * mockLcmEventsCmHandleStateHandler.initiateStateAdvised(_) >> {
-                args ->
-                    {
-                        def cmHandleStatePerCmHandle = (args[0] as Map)
-                        cmHandleStatePerCmHandle.each {
-                            assert (it.id == 'cmhandle' && it.dmiServiceName == 'my-server')
-                        }
+                args ->  {
+                        def yangModelCmHandles = args[0]
+                        assert yangModelCmHandles.id == ['cmhandle']
+                        assert yangModelCmHandles.dmiServiceName == ['my-server']
                     }
             }
         where:
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy
new file mode 100644 (file)
index 0000000..2c76b5b
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * ============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.config
+
+import java.time.Duration
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.context.properties.EnableConfigurationProperties
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.TestPropertySource
+import org.springframework.test.context.support.AnnotationConfigContextLoader
+import spock.lang.Specification
+
+@SpringBootTest
+@ContextConfiguration(classes = [HttpClientConfiguration])
+@EnableConfigurationProperties(HttpClientConfiguration.class)
+@TestPropertySource(properties = ["ncmp.dmi.httpclient.connectionTimeoutInSeconds=1", "ncmp.dmi.httpclient.maximumConnectionsTotal=200"])
+class HttpClientConfigurationSpec extends Specification {
+
+    @Autowired
+    private HttpClientConfiguration httpClientConfiguration
+
+    def 'Test HttpClientConfiguration properties with custom and default values'() {
+        expect: 'custom property values'
+        assert httpClientConfiguration.getConnectionTimeoutInSeconds() == Duration.ofSeconds(1)
+        assert httpClientConfiguration.getMaximumConnectionsTotal() == 200
+        and: 'default property values'
+        assert httpClientConfiguration.getMaximumConnectionsPerRoute() == 50
+        assert httpClientConfiguration.getIdleConnectionEvictionThresholdInSeconds() == Duration.ofSeconds(5)
+    }
+}
index e1aba79..a4df9b3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-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.
  */
 package org.onap.cps.ncmp.api.impl.config
 
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.boot.web.client.RestTemplateBuilder
 import org.springframework.http.MediaType
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
 import org.springframework.test.context.ContextConfiguration
 import org.springframework.web.client.RestTemplate
 import spock.lang.Specification
 
 @SpringBootTest
-@ContextConfiguration(classes = [NcmpConfiguration.DmiProperties])
+@ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, HttpClientConfiguration])
 class NcmpConfigurationSpec extends Specification{
 
     @Autowired
     NcmpConfiguration.DmiProperties dmiProperties
-
+    
+    @Autowired
+    HttpClientConfiguration httpClientConfiguration
+    
     def mockRestTemplateBuilder = new RestTemplateBuilder()
 
     def 'NcmpConfiguration Construction.'() {
@@ -48,11 +53,14 @@ class NcmpConfigurationSpec extends Specification{
             dmiProperties.authPassword == 'some-password'
     }
 
-    def 'Rest Template creation.'() {
+    def 'Rest Template creation with CloseableHttpClient and MappingJackson2HttpMessageConverter.'() {
         when: 'a rest template is created'
-            def result = NcmpConfiguration.restTemplate(mockRestTemplateBuilder)
+            def result = NcmpConfiguration.restTemplate(mockRestTemplateBuilder, httpClientConfiguration)
         then: 'the rest template is returned'
             assert result instanceof RestTemplate
+        and: 'the rest template is created with httpclient5'
+            assert result.getRequestFactory() instanceof HttpComponentsClientHttpRequestFactory
+            assert ((HttpComponentsClientHttpRequestFactory) result.getRequestFactory()).getHttpClient() instanceof CloseableHttpClient;
         and: 'a jackson media converter has been added'
             def lastMessageConverter = result.getMessageConverters().get(result.getMessageConverters().size()-1)
             lastMessageConverter instanceof MappingJackson2HttpMessageConverter
@@ -18,7 +18,7 @@
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.subscriptions
+package org.onap.cps.ncmp.api.impl.deprecated.subscriptions
 
 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NO_TIMESTAMP
@@ -18,7 +18,7 @@
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription
 
 import com.fasterxml.jackson.databind.ObjectMapper
 import org.mapstruct.factory.Mappers
@@ -39,7 +39,7 @@ class ClientCmSubscriptionNcmpInEventMapperSpec extends Specification {
 
     def 'Map clients subscription event to ncmps subscription event'() {
         given: 'a Subscription Event'
-            def jsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpInEvent.json')
+            def jsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpInEvent.json')
             def testEventToMap = jsonObjectMapper.convertJsonString(jsonData, CmSubscriptionNcmpInEvent.class)
         when: 'the client event is mapped to a ncmp subscription event'
             def result = objectUnderTest.toCmSubscriptionDmiInEvent(testEventToMap)
@@ -18,7 +18,7 @@
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription
 
 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
 
@@ -27,7 +27,7 @@ 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.api.impl.subscriptions.SubscriptionPersistenceImpl
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionPersistenceImpl
 import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
 import org.onap.cps.ncmp.events.cmsubscription1_0_0.dmi_to_ncmp.CmSubscriptionDmiOutEvent
 import org.onap.cps.ncmp.utils.TestUtils
@@ -115,7 +115,7 @@ class CmSubscriptionDmiOutEventConsumerSpec extends MessagingBaseSpec {
     }
 
     def getDmiOutEvent() {
-        def cmSubscriptionDmiOutEventJsonData = TestUtils.getResourceFileContent('cmSubscriptionDmiOutEvent.json')
+        def cmSubscriptionDmiOutEventJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionDmiOutEvent.json')
         return jsonObjectMapper.convertJsonString(cmSubscriptionDmiOutEventJsonData, CmSubscriptionDmiOutEvent.class)
     }
 
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription
 
 import com.fasterxml.jackson.databind.ObjectMapper
 import org.mapstruct.factory.Mappers
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus
 import org.onap.cps.ncmp.events.cmsubscription1_0_0.dmi_to_ncmp.CmSubscriptionDmiOutEvent
 import org.onap.cps.ncmp.utils.TestUtils
 import org.onap.cps.utils.JsonObjectMapper
@@ -41,7 +41,7 @@ class CmSubscriptionDmiOutEventToYangModelSubscriptionEventMapperSpec extends Sp
 
     def 'Map dmi out event to yang model subscription event'() {
         given: 'a dmi out event'
-            def jsonData = TestUtils.getResourceFileContent('cmSubscriptionDmiOutEvent.json')
+            def jsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionDmiOutEvent.json')
             def testEventToMap = jsonObjectMapper.convertJsonString(jsonData, CmSubscriptionDmiOutEvent.class)
         when: 'the event is mapped to a yang model subscription'
             def result = objectUnderTest.toYangModelSubscriptionEvent(testEventToMap)
@@ -18,7 +18,7 @@
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription
 
 import com.fasterxml.jackson.databind.ObjectMapper
 import org.mapstruct.factory.Mappers
@@ -42,7 +42,7 @@ class CmSubscriptionEventToCmSubscriptionNcmpOutEventMapperSpec extends Specific
 
     def 'Map cm subscription event to ncmp out event'() {
         given: 'a cm subscription event'
-            def cmSubscriptionEventJsonData = TestUtils.getResourceFileContent('cmSubscriptionEvent.json')
+            def cmSubscriptionEventJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionEvent.json')
             def cmSubscriptionEvent = jsonObjectMapper.convertJsonString(cmSubscriptionEventJsonData, CmSubscriptionEvent.class)
         when: 'cm subscription event is mapped to ncmp out event'
             def result = objectUnderTest.toCmSubscriptionNcmpOutEvent(cmSubscriptionEvent)
@@ -62,7 +62,7 @@ class CmSubscriptionEventToCmSubscriptionNcmpOutEventMapperSpec extends Specific
 
     def 'Map cm subscription event to ncmp out event with the given scenarios causes an exception'() {
         given: 'a cm subscription event'
-            def cmSubscriptionEventJsonData = TestUtils.getResourceFileContent('cmSubscriptionEvent.json')
+            def cmSubscriptionEventJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionEvent.json')
             def cmSubscriptionEvent = jsonObjectMapper.convertJsonString(cmSubscriptionEventJsonData, CmSubscriptionEvent.class)
         and: 'set cm subscription status with given scenarios'
             cmSubscriptionEvent.setCmSubscriptionStatus(subscriptionStatusList)
@@ -79,7 +79,7 @@ class CmSubscriptionEventToCmSubscriptionNcmpOutEventMapperSpec extends Specific
 
     def 'Map cm subscription event to ncmp out event without any exception'() {
         given: 'a cm subscription Event'
-            def subscriptionResponseJsonData = TestUtils.getResourceFileContent('cmSubscriptionEvent.json')
+            def subscriptionResponseJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionEvent.json')
             def subscriptionResponseEvent = jsonObjectMapper.convertJsonString(subscriptionResponseJsonData, CmSubscriptionEvent.class)
         when: 'cm subscription event is mapped to ncmp out event'
             objectUnderTest.toCmSubscriptionNcmpOutEvent(subscriptionResponseEvent)
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription
 
 import com.fasterxml.jackson.databind.ObjectMapper
 import io.cloudevents.CloudEvent
 import io.cloudevents.core.builder.CloudEventBuilder
 import org.apache.kafka.clients.consumer.ConsumerRecord
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistence
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionPersistence
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent
 import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
 import org.onap.cps.ncmp.events.cmsubscription1_0_0.client_to_ncmp.CmSubscriptionNcmpInEvent
@@ -52,7 +52,7 @@ class CmSubscriptionNcmpInEventConsumerSpec extends MessagingBaseSpec {
 
     def 'Consume, persist and forward valid CM create message'() {
         given: 'an event with data category CM'
-            def jsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpInEvent.json')
+            def jsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpInEvent.json')
             def testEventSent = jsonObjectMapper.convertJsonString(jsonData, CmSubscriptionNcmpInEvent.class)
             testEventSent.getData().getDataType().setDataCategory(dataCategory)
             def testCloudEventSent = CloudEventBuilder.v1()
@@ -86,7 +86,7 @@ class CmSubscriptionNcmpInEventConsumerSpec extends MessagingBaseSpec {
 
     def 'Consume event with wrong datastore causes an exception'() {
         given: 'an event'
-            def jsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpInEvent.json')
+            def jsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpInEvent.json')
             def testEventSent = jsonObjectMapper.convertJsonString(jsonData, CmSubscriptionNcmpInEvent.class)
         and: 'datastore is set to a passthrough-running datastore'
             testEventSent.getData().getPredicates().setDatastore('operational')
@@ -18,7 +18,7 @@
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription
 
 import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent
 
@@ -27,8 +27,8 @@ import com.hazelcast.map.IMap
 import io.cloudevents.CloudEvent
 import org.mapstruct.factory.Mappers
 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
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionPersistence
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus
 import org.onap.cps.ncmp.api.impl.utils.CmSubscriptionEventCloudMapper
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelSubscriptionEvent.TargetCmHandle
@@ -73,7 +73,7 @@ class CmSubscriptionNcmpInEventForwarderSpec extends MessagingBaseSpec {
 
     def 'Forward valid CM create subscription and simulate timeout'() {
         given: 'a ncmp in event'
-            def ncmpInEventJsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpInEvent.json')
+            def ncmpInEventJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpInEvent.json')
             def ncmpInEventJson = jsonObjectMapper.convertJsonString(ncmpInEventJsonData, CmSubscriptionNcmpInEvent.class)
         and: 'the InventoryPersistence returns private properties for the supplied CM Handles'
             1 * mockInventoryPersistence.getYangModelCmHandles(["CMHandle1", "CMHandle2", "CMHandle3"]) >> [
@@ -116,7 +116,7 @@ class CmSubscriptionNcmpInEventForwarderSpec extends MessagingBaseSpec {
 
     def 'Forward CM create subscription where target CM Handles are #scenario'() {
         given: 'a ncmp in event'
-            def ncmpInEventJsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpInEvent.json')
+            def ncmpInEventJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpInEvent.json')
             def ncmpInEventJson = jsonObjectMapper.convertJsonString(ncmpInEventJsonData, CmSubscriptionNcmpInEvent.class)
         and: 'the target CMHandles are set to #scenario'
             ncmpInEventJson.getData().getPredicates().setTargets(invalidTargets)
@@ -133,7 +133,7 @@ class CmSubscriptionNcmpInEventForwarderSpec extends MessagingBaseSpec {
 
     def 'Forward valid CM create subscription where targets are not associated to any existing CMHandles'() {
         given: 'a ncmp in event'
-            def ncmpInEventJsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpInEvent.json')
+            def ncmpInEventJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpInEvent.json')
             def ncmpInEventJson = jsonObjectMapper.convertJsonString(ncmpInEventJsonData, CmSubscriptionNcmpInEvent.class)
         and: 'the InventoryPersistence returns no private properties for the supplied CM Handles'
             1 * mockInventoryPersistence.getYangModelCmHandles(["CMHandle1", "CMHandle2", "CMHandle3"]) >> []
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription
 
 import com.fasterxml.jackson.databind.ObjectMapper
 import org.mapstruct.factory.Mappers
-import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionStatus
+import org.onap.cps.ncmp.api.impl.deprecated.subscriptions.SubscriptionStatus
 import org.onap.cps.ncmp.events.cmsubscription1_0_0.client_to_ncmp.CmSubscriptionNcmpInEvent
 import org.onap.cps.ncmp.utils.TestUtils
 import org.onap.cps.utils.JsonObjectMapper
@@ -41,7 +41,7 @@ class CmSubscriptionNcmpInEventMapperSpec extends Specification {
 
     def 'Map subscription event to yang model subscription event where #scenario'() {
         given: 'a Subscription Event'
-            def jsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpInEvent.json')
+            def jsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpInEvent.json')
             def testEventToMap = jsonObjectMapper.convertJsonString(jsonData, CmSubscriptionNcmpInEvent.class)
         when: 'the event is mapped to a yang model subscription'
             def result = objectUnderTest.toYangModelSubscriptionEvent(testEventToMap)
@@ -18,7 +18,7 @@
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.events.cmsubscription
+package org.onap.cps.ncmp.api.impl.events.deprecated.cmsubscription
 
 import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUCCESSFULLY_APPLIED_SUBSCRIPTION
 import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUBSCRIPTION_PENDING
@@ -30,7 +30,7 @@ import io.cloudevents.CloudEvent
 import io.cloudevents.core.builder.CloudEventBuilder
 import org.mapstruct.factory.Mappers
 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.deprecated.subscriptions.SubscriptionPersistence
 import org.onap.cps.ncmp.api.impl.utils.DataNodeBaseSpec
 import org.onap.cps.ncmp.api.impl.utils.SubscriptionOutcomeCloudMapper
 import org.onap.cps.ncmp.api.models.CmSubscriptionEvent
@@ -64,10 +64,10 @@ class CmSubscriptionNcmpOutEventPublisherSpec extends DataNodeBaseSpec {
 
     def 'Send response to the client apps successfully'() {
         given: 'a cm subscription event'
-            def cmSubscriptionEventJsonData = TestUtils.getResourceFileContent('cmSubscriptionEvent.json')
+            def cmSubscriptionEventJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionEvent.json')
             def cmSubscriptionEvent = jsonObjectMapper.convertJsonString(cmSubscriptionEventJsonData, CmSubscriptionEvent.class)
         and: 'a ncmp out event'
-            def ncmpOutEventJsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpOutEvent2.json')
+            def ncmpOutEventJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpOutEvent2.json')
             def ncmpOutEvent = jsonObjectMapper.convertJsonString(ncmpOutEventJsonData, CmSubscriptionNcmpOutEvent.class)
         and: 'a random id for the cloud event'
             SubscriptionOutcomeCloudMapper.randomId = 'some-id'
@@ -89,10 +89,10 @@ class CmSubscriptionNcmpOutEventPublisherSpec extends DataNodeBaseSpec {
 
     def 'Create ncmp out message as expected'() {
         given: 'a cm subscription event'
-            def cmSubscriptionEventJsonData = TestUtils.getResourceFileContent('cmSubscriptionEvent.json')
+            def cmSubscriptionEventJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionEvent.json')
             def cmSubscriptionEvent = jsonObjectMapper.convertJsonString(cmSubscriptionEventJsonData, CmSubscriptionEvent.class)
         and: 'a ncmp out event'
-            def ncmpOutEventJsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpOutEvent.json')
+            def ncmpOutEventJsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpOutEvent.json')
             def ncmpOutEvent = jsonObjectMapper.convertJsonString(ncmpOutEventJsonData, CmSubscriptionNcmpOutEvent.class)
         and: 'a status code and status message a per #scenarios'
             ncmpOutEvent.getData().setStatusCode(statusCode)
index bb4eebd..297f18c 100644 (file)
@@ -22,6 +22,8 @@
 
 package org.onap.cps.ncmp.api.impl.inventory
 
+import org.onap.cps.api.CpsAnchorService
+
 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
 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
@@ -30,12 +32,8 @@ import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NO_TIME
 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
 
 import com.fasterxml.jackson.databind.ObjectMapper
-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.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistenceImpl
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
 import org.onap.cps.spi.CascadeDeleteAllowed
 import org.onap.cps.spi.FetchDescendantsOption
@@ -58,12 +56,12 @@ class InventoryPersistenceImplSpec extends Specification {
 
     def mockCpsModuleService = Mock(CpsModuleService)
 
-    def mockCpsAdminService = Mock(CpsAdminService)
+    def mockCpsAnchorService = Mock(CpsAnchorService)
 
     def mockCpsValidator = Mock(CpsValidator)
 
     def objectUnderTest = new InventoryPersistenceImpl(spiedJsonObjectMapper, mockCpsDataService, mockCpsModuleService,
-            mockCpsValidator, mockCpsAdminService)
+            mockCpsValidator, mockCpsAnchorService)
 
     def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
             .format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
@@ -284,7 +282,7 @@ class InventoryPersistenceImplSpec extends Specification {
         when: 'the method to get cm handles is called'
             objectUnderTest.getCmHandleIdsWithGivenModules(['sample-module-name'])
         then: 'the admin persistence service method to query anchors is invoked once with the same parameter'
-            1 * mockCpsAdminService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, ['sample-module-name'])
+            1 * mockCpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, ['sample-module-name'])
     }
 
     def 'Replace list content'() {
index 099fc5a..8f3d8d9 100644 (file)
@@ -108,9 +108,24 @@ class ModuleOperationsUtilsSpec extends Specification{
             assert compositeState.lockReason.lockReasonCategory == MODULE_SYNC_FAILED
             assert compositeState.lockReason.details.contains(expectedDetails)
         where:
-            scenario         | lockReason                                                                                   || expectedDetails
-            'does not exist' | null                                                                                         || 'Attempt #1 failed: new error message'
-            'exists'         | CompositeState.LockReason.builder().details("Attempt #2 failed: some error message").build() || 'Attempt #3 failed: new error message'
+            scenario                           | lockReason                                                                                       || expectedDetails
+            'does not exist'                   | null                                                                                             || 'Attempt #1 failed: new error message'
+            'exists'                           | CompositeState.LockReason.builder().details("Attempt #2 failed: some error message").build()     || 'Attempt #3 failed: new error message'
+    }
+
+    def 'Update lock reason details that contains #scenario'() {
+        given: 'A locked state'
+            def compositeState = new CompositeStateBuilder().withCmHandleState(CmHandleState.LOCKED)
+                .withLockReason(MODULE_UPGRADE, "Upgrade to ModuleSetTag: " + moduleSetTag).build()
+        when: 'update cm handle details'
+            objectUnderTest.updateLockReasonDetailsAndAttempts(compositeState, MODULE_UPGRADE_FAILED, 'new error message')
+        then: 'the composite state lock reason and details are updated'
+            assert compositeState.lockReason.lockReasonCategory == MODULE_UPGRADE_FAILED
+            assert compositeState.lockReason.details.contains("Upgrade to ModuleSetTag: " + expectedDetails)
+        where:
+            scenario               | moduleSetTag       || expectedDetails
+            'a module set tag'     | 'someModuleSetTag' || 'someModuleSetTag'
+            'empty module set tag' | ''                 || 'not-specified'
     }
 
     def 'Get all locked Cm-Handle where Lock Reason is MODULE_SYNC_FAILED cm handle #scenario'() {
index 5384f31..de783ed 100644 (file)
 
 package org.onap.cps.ncmp.api.impl.inventory.sync
 
+import org.onap.cps.api.CpsAnchorService
+
 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.ncmp.api.impl.inventory.CmHandleState
 import org.onap.cps.spi.FetchDescendantsOption
 import org.onap.cps.spi.model.DataNode
-import org.onap.cps.api.CpsAdminService
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.api.CpsModuleService
 import org.onap.cps.spi.model.DataNodeBuilder
@@ -45,14 +46,14 @@ class ModuleSyncServiceSpec extends Specification {
 
     def mockCpsModuleService = Mock(CpsModuleService)
     def mockDmiModelOperations = Mock(DmiModelOperations)
-    def mockCpsAdminService = Mock(CpsAdminService)
+    def mockCpsAnchorService = Mock(CpsAnchorService)
     def mockCmHandleQueries = Mock(CmHandleQueries)
     def mockCpsDataService = Mock(CpsDataService)
     def mockJsonObjectMapper = Mock(JsonObjectMapper)
     def mockModuleSetTagCache = [:]
 
-    def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService, mockCpsAdminService,
-            mockCmHandleQueries, mockCpsDataService, mockJsonObjectMapper, mockModuleSetTagCache)
+    def objectUnderTest = new ModuleSyncService(mockDmiModelOperations, mockCpsModuleService,
+            mockCmHandleQueries, mockCpsDataService, mockCpsAnchorService, mockJsonObjectMapper, mockModuleSetTagCache)
 
     def expectedDataspaceName = NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
     def static cmHandleWithModuleSetTag = new DataNodeBuilder().withXpath("//cm-handles[@module-set-tag='tag-1'][@id='otherId']").withAnchor('otherId').build()
@@ -62,7 +63,7 @@ class ModuleSyncServiceSpec extends Specification {
             def ncmpServiceCmHandle = new NcmpServiceCmHandle()
             ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder().withCmHandleState(CmHandleState.ADVISED).build())
             ncmpServiceCmHandle.cmHandleId = 'ch-1'
-            def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('some service name', '', '', ncmpServiceCmHandle, moduleSetTag)
+            def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('some service name', '', '', ncmpServiceCmHandle, moduleSetTag, '')
         and: 'DMI operations returns some module references'
             def moduleReferences =  [ new ModuleReference('module1','1'), new ModuleReference('module2','2') ]
             mockDmiModelOperations.getModuleReferences(yangModelCmHandle) >> moduleReferences
@@ -76,9 +77,9 @@ class ModuleSyncServiceSpec extends Specification {
         when: 'module sync is triggered'
             objectUnderTest.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle)
         then: 'create schema set from module is invoked with correct parameters'
-            1 * mockCpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', newModuleNameContentToMap, moduleReferences)
+            1 * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', newModuleNameContentToMap, moduleReferences)
         and: 'anchor is created with the correct parameters'
-            1 * mockCpsAdminService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', 'ch-1')
+            1 * mockCpsAnchorService.createAnchor(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'ch-1', 'ch-1')
         where: 'the following parameters are used'
             scenario         | existingModuleResourcesInCps         | identifiedNewModuleReferences | newModuleNameContentToMap     | moduleSetTag
             'one new module' | [['module2': '2'], ['module3': '3']] | [['module1': '1']]            | [module1: 'some yang source'] | ''
@@ -91,7 +92,7 @@ class ModuleSyncServiceSpec extends Specification {
             ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder().withLockReason(MODULE_UPGRADE, 'Upgrade to ModuleSetTag: tag-1').build())
             def dmiServiceName = 'some service name'
             ncmpServiceCmHandle.cmHandleId = 'upgraded-ch'
-            def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '', '', ncmpServiceCmHandle,'tag-1')
+            def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '', '', ncmpServiceCmHandle,'tag-1', '')
         and: 'some module references'
             def moduleReferences =  [ new ModuleReference('module1','1') ]
         and: 'cache or DMI operations returns some module references for upgraded cm handle'
@@ -110,15 +111,17 @@ class ModuleSyncServiceSpec extends Specification {
             mockCmHandleQueries.cmHandleHasState('otherId', CmHandleState.READY) >> true
         when: 'module sync is triggered'
             objectUnderTest.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle)
-        then: 'create schema set from module is invoked for the upgraded cm handle'
-            1 * mockCpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'upgraded-ch', [:], moduleReferences)
+        then: 'update schema set from module is invoked for the upgraded cm handle'
+            expectedCallsToUpgradeSchemaSet * mockCpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'upgraded-ch', [:], moduleReferences)
+        and: 'create schema set from module is invoked for the upgraded cm handle'
+            expectedCallsToCeateSchemaSet * mockCpsModuleService.createSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'upgraded-ch', [:], moduleReferences)
         and: 'No anchor is created for the upgraded cm handle'
-            0 * mockCpsAdminService.createAnchor(*_)
+            0 * mockCpsAnchorService.createAnchor(*_)
         where: 'the following parameters are used'
-            scenario      | populateCache | existingCmHandlesWithSameTag
-            'new'         | false         | []
-            'in cache'    | true          | []
-            'in database' | false         | [cmHandleWithModuleSetTag]
+            scenario      | populateCache | existingCmHandlesWithSameTag || expectedCallsToUpgradeSchemaSet | expectedCallsToCeateSchemaSet
+            'new'         | false         | []                           || 0                               | 1
+            'in cache'    | true          | []                           || 1                               | 0
+            'in database' | false         | [cmHandleWithModuleSetTag]   || 1                               | 0
     }
 
     def 'upgrade model for a existing cm handle'() {
@@ -127,7 +130,7 @@ class ModuleSyncServiceSpec extends Specification {
             ncmpServiceCmHandle.setCompositeState(new CompositeStateBuilder()
                 .withLockReason(MODULE_UPGRADE, 'Upgrade to ModuleSetTag: targetModuleSetTag').build())
             ncmpServiceCmHandle.setCmHandleId('cmHandleId-1')
-            def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('some service name', '', '', ncmpServiceCmHandle, 'targetModuleSetTag')
+            def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('some service name', '', '', ncmpServiceCmHandle, 'targetModuleSetTag', '')
             mockCmHandleQueries.cmHandleHasState('cmHandleId-1', CmHandleState.READY) >> true
         and: 'the module service returns some module references'
             def moduleReferences = [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')]
@@ -138,7 +141,7 @@ class ModuleSyncServiceSpec extends Specification {
         when: 'module upgrade is triggered'
             objectUnderTest.syncAndCreateOrUpgradeSchemaSetAndAnchor(yangModelCmHandle)
         then: 'the upgrade is delegated to the module service (with the correct parameters)'
-            1 * mockCpsModuleService.createOrUpgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', Collections.emptyMap(), moduleReferences)
+            1 * mockCpsModuleService.upgradeSchemaSetFromModules(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'cmHandleId-1', Collections.emptyMap(), moduleReferences)
     }
 
     def 'Delete Schema Set for CmHandle'() {
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.utils
+package org.onap.cps.ncmp.api.impl.util.deprecated
 
 import com.fasterxml.jackson.core.JsonProcessingException
 import com.fasterxml.jackson.databind.ObjectMapper
 import io.cloudevents.core.builder.CloudEventBuilder
+import org.onap.cps.ncmp.api.impl.utils.CmSubscriptionEventCloudMapper
 import org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_dmi.CmSubscriptionDmiInEvent
 import org.onap.cps.ncmp.utils.TestUtils
 import org.onap.cps.utils.JsonObjectMapper
@@ -45,7 +46,7 @@ class CmSubscriptionEventCloudMapperSpec extends Specification {
 
     def 'Map the subscription event to data of the cloud event'() {
         given: 'a subscription event'
-            def jsonData = TestUtils.getResourceFileContent('cmSubscriptionDmiInEvent.json')
+            def jsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionDmiInEvent.json')
             def testEventData = jsonObjectMapper.convertJsonString(jsonData,
                 CmSubscriptionDmiInEvent.class)
             def testCloudEvent = CloudEventBuilder.v1()
@@ -70,7 +71,7 @@ class CmSubscriptionEventCloudMapperSpec extends Specification {
             def jsonProcessingException = new JsonProcessingException('The Cloud Event could not be constructed')
             spyObjectMapper.writeValueAsBytes(_) >> { throw jsonProcessingException }
         and: 'a subscription event of ncmp version'
-            def jsonData = TestUtils.getResourceFileContent('cmSubscriptionDmiInEvent.json')
+            def jsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionDmiInEvent.json')
             def testEventData = jsonObjectMapper.convertJsonString(jsonData,
                 CmSubscriptionDmiInEvent.class)
         when: 'the subscription event map to cloud event'
  *  ============LICENSE_END=========================================================
  */
 
-package org.onap.cps.ncmp.api.impl.utils
+package org.onap.cps.ncmp.api.impl.util.deprecated
 
 import com.fasterxml.jackson.core.JsonProcessingException
 import com.fasterxml.jackson.databind.ObjectMapper
 import io.cloudevents.core.builder.CloudEventBuilder
+import org.onap.cps.ncmp.api.impl.utils.SubscriptionOutcomeCloudMapper
 import org.onap.cps.ncmp.events.cmsubscription1_0_0.ncmp_to_client.CmSubscriptionNcmpOutEvent
 import org.onap.cps.ncmp.utils.TestUtils
 import org.onap.cps.utils.JsonObjectMapper
@@ -45,7 +46,7 @@ class SubscriptionOutcomeCloudMapperSpec extends Specification {
 
     def 'Map the subscription outcome to cloud event'() {
         given: 'a subscription event'
-            def jsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpOutEvent.json')
+            def jsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpOutEvent.json')
             def testEventData = jsonObjectMapper.convertJsonString(jsonData, CmSubscriptionNcmpOutEvent.class)
             def testCloudEvent = CloudEventBuilder.v1()
                 .withData(objectMapper.writeValueAsBytes(testEventData))
@@ -69,7 +70,7 @@ class SubscriptionOutcomeCloudMapperSpec extends Specification {
             def jsonProcessingException = new JsonProcessingException('The Cloud Event could not be constructed')
             spyObjectMapper.writeValueAsBytes(_) >> { throw jsonProcessingException }
         and: 'a cloud event having a subscription outcome in the data part'
-            def jsonData = TestUtils.getResourceFileContent('cmSubscriptionNcmpOutEvent.json')
+            def jsonData = TestUtils.getResourceFileContent('deprecatedCmSubscription/cmSubscriptionNcmpOutEvent.json')
             def testEventData = jsonObjectMapper.convertJsonString(jsonData, CmSubscriptionNcmpOutEvent.class)
         when: 'the subscription outcome map to cloud event'
             def expectedResult = objectUnderTest.toCloudEvent(testEventData, 'some-key', 'some-event-type')
index 2b17e5d..c83a540 100644 (file)
@@ -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'),'my-module-set-tag', 'my-alternate-id')
 
     NcmpConfiguration.DmiProperties dmiProperties = new NcmpConfiguration.DmiProperties()
 
index ca0015e..493db8c 100644 (file)
@@ -47,9 +47,12 @@ 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,'my-module-set-tag', 'my-alternate-id')
         then: 'the result has the right size'
             assert objectUnderTest.dmiProperties.size() == 1
+        and: 'the result has the correct values for module set tag and alternate ID'
+            assert objectUnderTest.moduleSetTag == 'my-module-set-tag'
+            assert objectUnderTest.alternateId == 'my-alternate-id'
         and: 'the DMI property in the result has the correct name and value'
             assert objectUnderTest.dmiProperties[0].name == 'myDmiProperty'
             assert objectUnderTest.dmiProperties[0].value == 'value1'
@@ -64,7 +67,7 @@ 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'),'')
+                    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/models/NcmpServiceCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/NcmpServiceCmHandleSpec.groovy
deleted file mode 100644 (file)
index e42b914..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  ============LICENSE_START=======================================================
- *  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.
- *  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.models
-
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import spock.lang.Specification
-
-class NcmpServiceCmHandleSpec extends Specification {
-
-
-    def 'NCMP Service CmHandle check for deep copy operation'() {
-        given: 'ncmp service cm handle'
-            def originalNcmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'cmhandleid',
-                dmiProperties: ['property1': 'value1', 'property2': 'value2'],
-                publicProperties: ['pubproperty1': 'value1', 'pubproperty2': 'value2'],
-                compositeState: new CompositeState(cmHandleState: CmHandleState.ADVISED, dataSyncEnabled: Boolean.FALSE))
-        when: 'we create a deep copy'
-            def deepCopiedNcmpServiceCmHandle = new NcmpServiceCmHandle(originalNcmpServiceCmHandle)
-        and: 'we change the original ncmp service cmhandle'
-            originalNcmpServiceCmHandle.dmiProperties = ['newProperty1': 'newValue1']
-            originalNcmpServiceCmHandle.publicProperties = ['newPublicProperty1': 'newPubValue1']
-            originalNcmpServiceCmHandle.compositeState = new CompositeState(cmHandleState: CmHandleState.DELETED, dataSyncEnabled: Boolean.TRUE)
-        then: 'no change in the copied dmi and public properties of ncmp service cmhandle'
-            deepCopiedNcmpServiceCmHandle.dmiProperties == ['property1': 'value1', 'property2': 'value2']
-            deepCopiedNcmpServiceCmHandle.publicProperties == ['pubproperty1': 'value1', 'pubproperty2': 'value2']
-        and: 'no change in the composite state'
-            deepCopiedNcmpServiceCmHandle.compositeState.cmHandleState == CmHandleState.ADVISED
-            deepCopiedNcmpServiceCmHandle.compositeState.dataSyncEnabled == Boolean.FALSE
-    }
-
-}
index e5ed21f..f9ecd63 100644 (file)
@@ -23,7 +23,8 @@ package org.onap.cps.ncmp.init
 import ch.qos.logback.classic.Level
 import ch.qos.logback.classic.Logger
 import ch.qos.logback.core.read.ListAppender
-import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsDataspaceService
+import org.onap.cps.api.CpsAnchorService
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.api.CpsModuleService
 import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException
@@ -37,10 +38,11 @@ import spock.lang.Specification
 
 class AbstractModelLoaderSpec extends Specification {
 
-    def mockCpsAdminService = Mock(CpsAdminService)
+    def mockCpsDataspaceService = Mock(CpsDataspaceService)
     def mockCpsModuleService = Mock(CpsModuleService)
     def mockCpsDataService = Mock(CpsDataService)
-    def objectUnderTest = Spy(new TestModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsDataService))
+    def mockCpsAnchorService = Mock(CpsAnchorService)
+    def objectUnderTest = Spy(new TestModelLoader(mockCpsDataspaceService, mockCpsModuleService, mockCpsDataService, mockCpsAnchorService))
 
     def applicationContext = new AnnotationConfigApplicationContext()
 
@@ -49,7 +51,7 @@ class AbstractModelLoaderSpec extends Specification {
     def loggingListAppender
 
     void setup() {
-        yangResourceToContentMap = objectUnderTest.createYangResourcesToContentMap('subscription.yang')
+        yangResourceToContentMap = objectUnderTest.createYangResourcesToContentMap('cm-data-subscriptions@2023-11-13.yang')
         logger.setLevel(Level.DEBUG)
         loggingListAppender = new ListAppender()
         logger.addAppender(loggingListAppender)
@@ -89,7 +91,7 @@ class AbstractModelLoaderSpec extends Specification {
 
     def 'Create schema set.'() {
         when: 'creating a schema set'
-            objectUnderTest.createSchemaSet('some dataspace','new name','subscription.yang')
+            objectUnderTest.createSchemaSet('some dataspace','new name','cm-data-subscriptions@2023-11-13.yang')
         then: 'the operation is delegated to the admin service'
             1 * mockCpsModuleService.createSchemaSet('some dataspace','new name',_)
     }
@@ -98,7 +100,7 @@ class AbstractModelLoaderSpec extends Specification {
         given: 'the module service throws an already defined exception'
             mockCpsModuleService.createSchemaSet(*_) >>  { throw AlreadyDefinedException.forSchemaSet('name','context',null) }
         when: 'attempt to create a schema set'
-            objectUnderTest.createSchemaSet('some dataspace','new name','subscription.yang')
+            objectUnderTest.createSchemaSet('some dataspace','new name','cm-data-subscriptions@2023-11-13.yang')
         then: 'the exception is ignored i.e. no exception thrown up'
             noExceptionThrown()
         and: 'the exception message is logged'
@@ -141,12 +143,12 @@ class AbstractModelLoaderSpec extends Specification {
         when: 'creating an anchor'
             objectUnderTest.createAnchor('some dataspace','some schema set','new name')
         then: 'the operation is delegated to the admin service'
-            1 * mockCpsAdminService.createAnchor('some dataspace','some schema set', 'new name')
+            1 * mockCpsAnchorService.createAnchor('some dataspace','some schema set', 'new name')
     }
 
     def 'Create anchor with already defined exception.'() {
         given: 'the admin service throws an already defined exception'
-            mockCpsAdminService.createAnchor(*_)>>  { throw AlreadyDefinedException.forAnchor('name','context',null) }
+            mockCpsAnchorService.createAnchor(*_)>>  { throw AlreadyDefinedException.forAnchor('name','context',null) }
         when: 'attempt to create anchor'
             objectUnderTest.createAnchor('some dataspace','some schema set','new name')
         then: 'the exception is ignored i.e. no exception thrown up'
@@ -158,7 +160,7 @@ class AbstractModelLoaderSpec extends Specification {
 
     def 'Create anchor with any other exception.'() {
         given: 'the admin service throws a exception'
-            mockCpsAdminService.createAnchor(*_)>>  { throw new RuntimeException('test message') }
+            mockCpsAnchorService.createAnchor(*_)>>  { throw new RuntimeException('test message') }
         when: 'attempt to create anchor'
             objectUnderTest.createAnchor('some dataspace','some schema set','new name')
         then: 'a startup exception with correct message and details is thrown'
@@ -201,12 +203,12 @@ class AbstractModelLoaderSpec extends Specification {
         when: 'a schema set for an anchor is updated'
             objectUnderTest.updateAnchorSchemaSet('some dataspace', 'anchor', 'new schema set')
         then: 'the request is delegated to the admin service'
-            1 * mockCpsAdminService.updateAnchorSchemaSet('some dataspace', 'anchor', 'new schema set')
+            1 * mockCpsAnchorService.updateAnchorSchemaSet('some dataspace', 'anchor', 'new schema set')
     }
 
     def 'Update anchor schema set with exception.'() {
         given: 'the admin service throws an exception'
-            mockCpsAdminService.updateAnchorSchemaSet(*_) >> { throw new RuntimeException('test message') }
+            mockCpsAnchorService.updateAnchorSchemaSet(*_) >> { throw new RuntimeException('test message') }
         when: 'a schema set for an anchor is updated'
             objectUnderTest.updateAnchorSchemaSet('some dataspace', 'anchor', 'new schema set')
         then: 'a startup exception with correct message and details is thrown'
@@ -217,10 +219,11 @@ class AbstractModelLoaderSpec extends Specification {
 
     class TestModelLoader extends AbstractModelLoader {
 
-        TestModelLoader(final CpsAdminService cpsAdminService,
+        TestModelLoader(final CpsDataspaceService cpsDataspaceService,
                         final CpsModuleService cpsModuleService,
-                        final CpsDataService cpsDataService) {
-            super(cpsAdminService, cpsModuleService, cpsDataService)
+                        final CpsDataService cpsDataService,
+                        final CpsAnchorService cpsAnchorService) {
+            super(cpsDataspaceService, cpsModuleService, cpsDataService, cpsAnchorService)
             super.maximumAttemptCount = 2
             super.retryTimeMs = 1
         }
index 0662712..aed495e 100644 (file)
 
 package org.onap.cps.ncmp.init
 
+import org.onap.cps.api.CpsAnchorService
+
 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
 
 import ch.qos.logback.classic.Level
 import ch.qos.logback.classic.Logger
 import ch.qos.logback.core.read.ListAppender
-import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsDataspaceService
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.api.CpsModuleService
 import org.onap.cps.spi.model.Dataspace
@@ -36,10 +38,11 @@ import spock.lang.Specification
 
 class CmDataSubscriptionModelLoaderSpec extends Specification {
 
-    def mockCpsAdminService = Mock(CpsAdminService)
+    def mockCpsDataspaceService = Mock(CpsDataspaceService)
     def mockCpsModuleService = Mock(CpsModuleService)
     def mockCpsDataService = Mock(CpsDataService)
-    def objectUnderTest = new CmDataSubscriptionModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsDataService)
+    def mockCpsAnchorService = Mock(CpsAnchorService)
+    def objectUnderTest = new CmDataSubscriptionModelLoader(mockCpsDataspaceService, mockCpsModuleService, mockCpsDataService, mockCpsAnchorService)
 
     def applicationContext = new AnnotationConfigApplicationContext()
 
@@ -65,13 +68,13 @@ class CmDataSubscriptionModelLoaderSpec extends Specification {
         given:'model loader is enabled'
             objectUnderTest.subscriptionModelLoaderEnabled = true
         and: 'dataspace is ready for use'
-            mockCpsAdminService.getDataspace(NCMP_DATASPACE_NAME) >> new Dataspace('')
+            mockCpsDataspaceService.getDataspace(NCMP_DATASPACE_NAME) >> new Dataspace('')
         when: 'the application is ready'
             objectUnderTest.onApplicationEvent(Mock(ApplicationReadyEvent))
         then: 'the module service to create schema set is called once'
             1 * mockCpsModuleService.createSchemaSet(NCMP_DATASPACE_NAME, 'cm-data-subscriptions', expectedYangResourcesToContentMap)
         and: 'the admin service to create an anchor set is called once'
-            1 * mockCpsAdminService.createAnchor(NCMP_DATASPACE_NAME, 'cm-data-subscriptions', 'cm-data-subscriptions')
+            1 * mockCpsAnchorService.createAnchor(NCMP_DATASPACE_NAME, 'cm-data-subscriptions', 'cm-data-subscriptions')
         and: 'the data service to create a top level datanode is called once'
             1 * mockCpsDataService.saveData(NCMP_DATASPACE_NAME, 'cm-data-subscriptions', '{"datastores":{}}', _)
     }
@@ -82,7 +85,7 @@ class CmDataSubscriptionModelLoaderSpec extends Specification {
         when: 'application is ready'
             objectUnderTest.onApplicationEvent(Mock(ApplicationReadyEvent))
         then: 'no interaction with admin service'
-            0 * mockCpsAdminService.getDataspace(_)
+            0 * mockCpsDataspaceService.getDataspace(_)
         then: 'a message is logged that the function is disabled'
             def logs = loggingListAppender.list.toString()
             assert logs.contains('Subscription Model Loader is disabled')
index 43e0f69..5557993 100644 (file)
 
 package org.onap.cps.ncmp.init
 
+import org.onap.cps.api.CpsAnchorService
+
 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 ch.qos.logback.classic.Level
 import ch.qos.logback.classic.Logger
 import ch.qos.logback.core.read.ListAppender
-import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsDataspaceService
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.api.CpsModuleService
 import org.onap.cps.spi.model.Dataspace
@@ -37,10 +39,11 @@ import spock.lang.Specification
 
 class InventoryModelLoaderSpec extends Specification {
 
-    def mockCpsAdminService = Mock(CpsAdminService)
+    def mockCpsAdminService = Mock(CpsDataspaceService)
     def mockCpsModuleService = Mock(CpsModuleService)
     def mockCpsDataService = Mock(CpsDataService)
-    def objectUnderTest = new InventoryModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsDataService)
+    def mockCpsAnchorService = Mock(CpsAnchorService)
+    def objectUnderTest = new InventoryModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsDataService, mockCpsAnchorService)
 
     def applicationContext = new AnnotationConfigApplicationContext()
 
@@ -49,7 +52,7 @@ class InventoryModelLoaderSpec extends Specification {
     def loggingListAppender
 
     void setup() {
-        expectedYangResourceToContentMap = objectUnderTest.createYangResourcesToContentMap('dmi-registry@2023-08-23.yang')
+        expectedYangResourceToContentMap = objectUnderTest.createYangResourcesToContentMap('dmi-registry@2023-11-27.yang')
         logger.setLevel(Level.DEBUG)
         loggingListAppender = new ListAppender()
         logger.addAppender(loggingListAppender)
@@ -68,9 +71,9 @@ class InventoryModelLoaderSpec extends Specification {
         when: 'the application is ready'
             objectUnderTest.onApplicationEvent(Mock(ApplicationReadyEvent))
         then: 'the module service is used to create the new schema set from the correct resource'
-            1 * mockCpsModuleService.createSchemaSet(NCMP_DATASPACE_NAME, 'dmi-registry-2023-08-23', expectedYangResourceToContentMap)
+            1 * mockCpsModuleService.createSchemaSet(NCMP_DATASPACE_NAME, 'dmi-registry-2023-11-27', expectedYangResourceToContentMap)
         and: 'the admin service is used to update the anchor'
-            1 * mockCpsAdminService.updateAnchorSchemaSet(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, 'dmi-registry-2023-08-23')
+            1 * mockCpsAnchorService.updateAnchorSchemaSet(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, 'dmi-registry-2023-11-27')
         and: 'No schema sets are being removed by the module service (yet)'
             0 * mockCpsModuleService.deleteSchemaSet(NCMP_DATASPACE_NAME, _, _)
     }
old mode 100755 (executable)
new mode 100644 (file)
index 3e4412b..5a64613
@@ -32,7 +32,7 @@
 
     <groupId>org.onap.cps</groupId>
     <artifactId>cps-parent</artifactId>
-    <version>3.4.1-SNAPSHOT</version>
+    <version>3.4.2-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <properties>
index e3e39ec..f88ef13 100644 (file)
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
old mode 100755 (executable)
new mode 100644 (file)
index 2d9e420..8471723
@@ -28,7 +28,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index 993dad5..9b78f85 100755 (executable)
@@ -33,7 +33,8 @@ import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
-import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsAnchorService;
+import org.onap.cps.api.CpsDataspaceService;
 import org.onap.cps.api.CpsModuleService;
 import org.onap.cps.rest.api.CpsAdminApi;
 import org.onap.cps.rest.model.AnchorDetails;
@@ -53,9 +54,10 @@ import org.springframework.web.multipart.MultipartFile;
 @RequiredArgsConstructor
 public class AdminRestController implements CpsAdminApi {
 
-    private final CpsAdminService cpsAdminService;
+    private final CpsDataspaceService cpsDataspaceService;
     private final CpsModuleService cpsModuleService;
     private final CpsRestInputMapper cpsRestInputMapper;
+    private final CpsAnchorService cpsAnchorService;
 
     /**
      * Create a dataspace.
@@ -65,7 +67,7 @@ public class AdminRestController implements CpsAdminApi {
      */
     @Override
     public ResponseEntity<String> createDataspace(@NotNull @Valid final String dataspaceName) {
-        cpsAdminService.createDataspace(dataspaceName);
+        cpsDataspaceService.createDataspace(dataspaceName);
         return new ResponseEntity<>(dataspaceName, HttpStatus.CREATED);
     }
 
@@ -77,7 +79,7 @@ public class AdminRestController implements CpsAdminApi {
      */
     @Override
     public ResponseEntity<Void> createDataspaceV2(@NotNull @Valid final String dataspaceName) {
-        cpsAdminService.createDataspace(dataspaceName);
+        cpsDataspaceService.createDataspace(dataspaceName);
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
@@ -89,7 +91,7 @@ public class AdminRestController implements CpsAdminApi {
      */
     @Override
     public ResponseEntity<Void> deleteDataspace(final String apiVersion, final String dataspaceName) {
-        cpsAdminService.deleteDataspace(dataspaceName);
+        cpsDataspaceService.deleteDataspace(dataspaceName);
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
@@ -184,7 +186,7 @@ public class AdminRestController implements CpsAdminApi {
     @Override
     public ResponseEntity<String> createAnchor(final String dataspaceName, @NotNull @Valid final String schemaSetName,
         @NotNull @Valid final String anchorName) {
-        cpsAdminService.createAnchor(dataspaceName, schemaSetName, anchorName);
+        cpsAnchorService.createAnchor(dataspaceName, schemaSetName, anchorName);
         return new ResponseEntity<>(anchorName, HttpStatus.CREATED);
     }
 
@@ -199,7 +201,7 @@ public class AdminRestController implements CpsAdminApi {
     @Override
     public ResponseEntity<Void> createAnchorV2(final String dataspaceName, @NotNull @Valid final String schemaSetName,
         @NotNull @Valid final String anchorName) {
-        cpsAdminService.createAnchor(dataspaceName, schemaSetName, anchorName);
+        cpsAnchorService.createAnchor(dataspaceName, schemaSetName, anchorName);
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
@@ -214,7 +216,7 @@ public class AdminRestController implements CpsAdminApi {
     @Override
     public ResponseEntity<Void> deleteAnchor(final String apiVersion,
             final String dataspaceName, final String anchorName) {
-        cpsAdminService.deleteAnchor(dataspaceName, anchorName);
+        cpsAnchorService.deleteAnchor(dataspaceName, anchorName);
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
@@ -229,7 +231,7 @@ public class AdminRestController implements CpsAdminApi {
     @Override
     public ResponseEntity<AnchorDetails> getAnchor(final String apiVersion,
             final String dataspaceName, final String anchorName) {
-        final var anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final var anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         final var anchorDetails = cpsRestInputMapper.toAnchorDetails(anchor);
         return new ResponseEntity<>(anchorDetails, HttpStatus.OK);
     }
@@ -244,7 +246,7 @@ public class AdminRestController implements CpsAdminApi {
     @Override
     public ResponseEntity<List<AnchorDetails>> getAnchors(final String apiVersion,
             final String dataspaceName) {
-        final Collection<Anchor> anchors = cpsAdminService.getAnchors(dataspaceName);
+        final Collection<Anchor> anchors = cpsAnchorService.getAnchors(dataspaceName);
         final List<AnchorDetails> anchorDetails = anchors.stream().map(cpsRestInputMapper::toAnchorDetails)
             .collect(Collectors.toList());
         return new ResponseEntity<>(anchorDetails, HttpStatus.OK);
@@ -252,7 +254,7 @@ public class AdminRestController implements CpsAdminApi {
 
     @Override
     public ResponseEntity<List<DataspaceDetails>> getAllDataspaces(final String apiVersion) {
-        final Collection<Dataspace> dataspaces = cpsAdminService.getAllDataspaces();
+        final Collection<Dataspace> dataspaces = cpsDataspaceService.getAllDataspaces();
         final List<DataspaceDetails> dataspaceDetails = dataspaces.stream().map(cpsRestInputMapper::toDataspaceDetails)
                 .collect(Collectors.toList());
         return new ResponseEntity<>(dataspaceDetails, HttpStatus.OK);
@@ -260,7 +262,7 @@ public class AdminRestController implements CpsAdminApi {
 
     @Override
     public ResponseEntity<DataspaceDetails> getDataspace(final String apiVersion, final String dataspaceName) {
-        final Dataspace dataspace = cpsAdminService.getDataspace(dataspaceName);
+        final Dataspace dataspace = cpsDataspaceService.getDataspace(dataspaceName);
         final DataspaceDetails dataspaceDetails = cpsRestInputMapper.toDataspaceDetails(dataspace);
         return new ResponseEntity<>(dataspaceDetails, HttpStatus.OK);
     }
index f81efd6..81ac511 100755 (executable)
@@ -23,6 +23,8 @@
 
 package org.onap.cps.rest.controller
 
+import org.onap.cps.api.CpsAnchorService
+
 import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
@@ -30,7 +32,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
 
 import org.mapstruct.factory.Mappers
-import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsDataspaceService
 import org.onap.cps.api.CpsModuleService
 import org.onap.cps.spi.exceptions.AlreadyDefinedException
 import org.onap.cps.spi.exceptions.SchemaSetInUseException
@@ -56,7 +58,10 @@ class AdminRestControllerSpec extends Specification {
     CpsModuleService mockCpsModuleService = Mock()
 
     @SpringBean
-    CpsAdminService mockCpsAdminService = Mock()
+    CpsDataspaceService mockCpsDataspaceService = Mock()
+
+    @SpringBean
+    CpsAnchorService mockCpsAnchorService = Mock()
 
     @SpringBean
     CpsRestInputMapper cpsRestInputMapper = Mappers.getMapper(CpsRestInputMapper)
@@ -76,26 +81,27 @@ class AdminRestControllerSpec extends Specification {
     def 'Create new dataspace with #scenario.'() {
         when: 'post is invoked'
             def response =
-                    mvc.perform(
-                            post("/cps/api/${apiVersion}/dataspaces")
-                                    .param('dataspace-name', dataspaceName))
-                            .andReturn().response
+                mvc.perform(
+                    post("/cps/api/${apiVersion}/dataspaces")
+                        .param('dataspace-name', dataspaceName))
+                    .andReturn().response
         then: 'service method is invoked with expected parameters'
-            1 * mockCpsAdminService.createDataspace(dataspaceName)
+            1 * mockCpsDataspaceService.createDataspace(dataspaceName)
         and: 'dataspace is create successfully'
             response.status == HttpStatus.CREATED.value()
             assert response.getContentAsString() == expectedResponseBody
         where: 'following cases are tested'
-            scenario | apiVersion  || expectedResponseBody
-            'V1 API' | 'v1'        || 'my_dataspace'
-            'V2 API' | 'v2'        || ''
-    } 
+            scenario | apiVersion || expectedResponseBody
+            'V1 API' | 'v1'       || 'my_dataspace'
+            'V2 API' | 'v2'       || ''
+    }
+
     def 'Create dataspace over existing with same name.'() {
         given: 'an endpoint'
             def createDataspaceEndpoint = "$basePath/v1/dataspaces"
         and: 'the service method throws an exception indicating the dataspace is already defined'
             def thrownException = new AlreadyDefinedException(dataspaceName, new RuntimeException())
-            mockCpsAdminService.createDataspace(dataspaceName) >> { throw thrownException }
+            mockCpsDataspaceService.createDataspace(dataspaceName) >> { throw thrownException }
         when: 'post is invoked'
             def response =
                     mvc.perform(
@@ -108,7 +114,7 @@ class AdminRestControllerSpec extends Specification {
 
     def 'Get a dataspace.'() {
         given: 'service method returns a dataspace'
-            mockCpsAdminService.getDataspace(dataspaceName) >> dataspace
+            mockCpsDataspaceService.getDataspace(dataspaceName) >> dataspace
         and: 'an endpoint'
             def getDataspaceEndpoint = "$basePath/v1/admin/dataspaces/$dataspaceName"
         when: 'get dataspace API is invoked'
@@ -120,7 +126,7 @@ class AdminRestControllerSpec extends Specification {
 
     def 'Get all dataspaces.'() {
         given: 'service method returns all dataspace'
-            mockCpsAdminService.getAllDataspaces() >> [dataspace, new Dataspace(name: "dataspace-test2")]
+            mockCpsDataspaceService.getAllDataspaces() >> [dataspace, new Dataspace(name: "dataspace-test2")]
         and: 'an endpoint'
             def getAllDataspaceEndpoint = "$basePath/v1/admin/dataspaces"
         when: 'get all dataspace API is invoked'
@@ -317,7 +323,7 @@ class AdminRestControllerSpec extends Specification {
                                     .params(requestParams as MultiValueMap))
                                     .andReturn().response
         then: 'anchor is created successfully'
-            1 * mockCpsAdminService.createAnchor(dataspaceName, schemaSetName, anchorName)
+            1 * mockCpsAnchorService.createAnchor(dataspaceName, schemaSetName, anchorName)
             assert response.status == HttpStatus.CREATED.value()
             assert response.getContentAsString() == expectedResponseBody
         where: 'following cases are tested'
@@ -328,7 +334,7 @@ class AdminRestControllerSpec extends Specification {
 
     def 'Get existing anchor.'() {
         given: 'service method returns a list of anchors'
-            mockCpsAdminService.getAnchors(dataspaceName) >> [anchor]
+            mockCpsAnchorService.getAnchors(dataspaceName) >> [anchor]
         and: 'an endpoint'
             def anchorEndpoint = "$basePath/v1/dataspaces/$dataspaceName/anchors"
         when: 'get all anchors API is invoked'
@@ -340,7 +346,7 @@ class AdminRestControllerSpec extends Specification {
 
     def 'Get existing anchor by dataspace and anchor name.'() {
         given: 'service method returns an anchor'
-            mockCpsAdminService.getAnchor(dataspaceName, anchorName) >>
+            mockCpsAnchorService.getAnchor(dataspaceName, anchorName) >>
                     new Anchor(name: anchorName, dataspaceName: dataspaceName, schemaSetName: schemaSetName)
         and: 'an endpoint'
             def anchorEndpoint = "$basePath/v1/dataspaces/$dataspaceName/anchors/$anchorName"
@@ -360,7 +366,7 @@ class AdminRestControllerSpec extends Specification {
         when: 'delete method is invoked on anchor endpoint'
             def response = mvc.perform(delete(anchorEndpoint)).andReturn().response
         then: 'associated service method is invoked with expected parameters'
-            1 * mockCpsAdminService.deleteAnchor(dataspaceName, anchorName)
+            1 * mockCpsAnchorService.deleteAnchor(dataspaceName, anchorName)
         and: 'response code indicates success'
             response.status == HttpStatus.NO_CONTENT.value()
     }
@@ -373,7 +379,7 @@ class AdminRestControllerSpec extends Specification {
                 .param('dataspace-name', dataspaceName))
                 .andReturn().response
         then: 'associated service method is invoked with expected parameter'
-            1 * mockCpsAdminService.deleteDataspace(dataspaceName)
+            1 * mockCpsDataspaceService.deleteDataspace(dataspaceName)
         and: 'response code indicates success'
             response.status == HttpStatus.NO_CONTENT.value()
     }
index 535b83d..ff2bed4 100644 (file)
@@ -26,7 +26,8 @@ package org.onap.cps.rest.exceptions
 
 import com.fasterxml.jackson.databind.ObjectMapper
 import groovy.json.JsonSlurper
-import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsDataspaceService
+import org.onap.cps.api.CpsAnchorService
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.api.CpsModuleService
 import org.onap.cps.api.CpsQueryService
@@ -63,7 +64,10 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
 class CpsRestExceptionHandlerSpec extends Specification {
 
     @SpringBean
-    CpsAdminService mockCpsAdminService = Stub()
+    CpsDataspaceService mockCpsAdminService = Stub()
+
+    @SpringBean
+    CpsAnchorService mockCpsAnchorService = Stub()
 
     @SpringBean
     CpsModuleService mockCpsModuleService = Stub()
@@ -198,7 +202,7 @@ class CpsRestExceptionHandlerSpec extends Specification {
      */
 
     def setupTestException(exception) {
-        mockCpsAdminService.getAnchors(_) >> { throw exception }
+        mockCpsAnchorService.getAnchors(_) >> { throw exception }
     }
 
     def performTestRequest() {
index a30a42a..8e2683d 100644 (file)
@@ -26,7 +26,7 @@
     <parent>\r
         <groupId>org.onap.cps</groupId>\r
         <artifactId>cps-parent</artifactId>\r
-        <version>3.4.1-SNAPSHOT</version>\r
+        <version>3.4.2-SNAPSHOT</version>\r
         <relativePath>../cps-parent/pom.xml</relativePath>\r
     </parent>\r
 \r
index 0d77530..b115f9a 100755 (executable)
@@ -34,6 +34,7 @@ import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -190,6 +191,21 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
         schemaSetRepository.deleteByDataspaceAndNameIn(dataspaceEntity, schemaSetNames);
     }
 
+
+    @Override
+    @Transactional
+    public void updateSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+                                           final Map<String, String> newModuleNameToContentMap,
+                                           final Collection<ModuleReference> allModuleReferences) {
+        final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+        final SchemaSetEntity schemaSetEntity =
+            schemaSetRepository.getByDataspaceAndName(dataspaceEntity, schemaSetName);
+        storeAndLinkNewModules(newModuleNameToContentMap, schemaSetEntity);
+        updateAllModuleReferences(allModuleReferences, schemaSetEntity.getId());
+    }
+
+
+
     @Override
     @Transactional
     public void deleteUnusedYangResourceModules() {
@@ -364,4 +380,21 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
         return SchemaSet.builder().name(schemaSetEntity.getName())
                 .dataspaceName(schemaSetEntity.getDataspace().getName()).build();
     }
+
+    private void storeAndLinkNewModules(final Map<String, String> newModuleNameToContentMap,
+                                        final SchemaSetEntity schemaSetEntity) {
+        final Set<YangResourceEntity> yangResourceEntities
+            = new HashSet<>(synchronizeYangResources(newModuleNameToContentMap));
+        schemaSetEntity.setYangResources(yangResourceEntities);
+        schemaSetRepository.save(schemaSetEntity);
+    }
+
+    private void updateAllModuleReferences(final Collection<ModuleReference> allModuleReferences,
+                                           final Integer schemaSetEntityId) {
+        yangResourceRepository.deleteSchemaSetYangResourceForSchemaSetId(schemaSetEntityId);
+        final List<Integer> allYangResourceIds =
+            yangResourceRepository.getResourceIdsByModuleReferences(allModuleReferences);
+        yangResourceRepository.insertSchemaSetIdYangResourceId(schemaSetEntityId, allYangResourceIds);
+    }
+
 }
index e833796..3fec462 100644 (file)
@@ -108,6 +108,10 @@ public interface YangResourceRepository extends JpaRepository<YangResourceEntity
         return findAllModuleReferencesByDataspaceAndModuleNames(dataspaceName, moduleNames.toArray(new String[0]));
     }
 
+    @Modifying
+    @Query(value = "DELETE FROM schema_set_yang_resources WHERE schema_set_id = :schemaSetId", nativeQuery = true)
+    void deleteSchemaSetYangResourceForSchemaSetId(@Param("schemaSetId") int schemaSetId);
+
     @Modifying
     @Query(value = "DELETE FROM yang_resource yr WHERE NOT EXISTS "
         + "(SELECT 1 FROM schema_set_yang_resources ssyr WHERE ssyr.yang_resource_id = yr.id)", nativeQuery = true)
index 9696b28..3447a1c 100644 (file)
 package org.onap.cps.spi.impl
 
 import org.hibernate.exception.ConstraintViolationException
-import org.onap.cps.spi.CpsAdminPersistenceService
 import org.onap.cps.spi.CpsModulePersistenceService
+import org.onap.cps.spi.entities.SchemaSetEntity
 import org.onap.cps.spi.exceptions.DuplicatedYangResourceException
+import org.onap.cps.spi.model.ModuleReference
 import org.onap.cps.spi.repository.DataspaceRepository
 import org.onap.cps.spi.repository.ModuleReferenceRepository
 import org.onap.cps.spi.repository.SchemaSetRepository
 import org.onap.cps.spi.repository.YangResourceRepository
 import org.springframework.dao.DataIntegrityViolationException
 import spock.lang.Specification
-
 import java.sql.SQLException
 
 /**
@@ -39,11 +39,10 @@ class CpsModulePersistenceServiceSpec extends Specification {
 
     CpsModulePersistenceService objectUnderTest
 
-    def dataspaceRepositoryMock = Mock(DataspaceRepository)
-    def yangResourceRepositoryMock = Mock(YangResourceRepository)
-    def schemaSetRepositoryMock = Mock(SchemaSetRepository)
-    def cpsAdminPersistenceServiceMock = Mock(CpsAdminPersistenceService)
-    def moduleReferenceRepositoryMock = Mock(ModuleReferenceRepository)
+    def mockDataspaceRepository = Mock(DataspaceRepository)
+    def mockYangResourceRepository = Mock(YangResourceRepository)
+    def mockSchemaSetRepository = Mock(SchemaSetRepository)
+    def mockModuleReferenceRepository = Mock(ModuleReferenceRepository)
 
     def yangResourceName = 'my-yang-resource-name'
     def yangResourceContent = 'module stores {\n' +
@@ -68,15 +67,15 @@ class CpsModulePersistenceServiceSpec extends Specification {
     static otherIntegrityException = new DataIntegrityViolationException('another integrity exception')
 
     def setup() {
-        objectUnderTest = new CpsModulePersistenceServiceImpl(yangResourceRepositoryMock, schemaSetRepositoryMock,
-            dataspaceRepositoryMock, moduleReferenceRepositoryMock)
+        objectUnderTest = new CpsModulePersistenceServiceImpl(mockYangResourceRepository, mockSchemaSetRepository,
+            mockDataspaceRepository, mockModuleReferenceRepository)
     }
 
     def 'Store schema set error scenario: #scenario.'() {
         given: 'no yang resource are currently saved'
-            yangResourceRepositoryMock.findAllByChecksumIn(_ as Collection<String>) >> Collections.emptyList()
+            mockYangResourceRepository.findAllByChecksumIn(_ as Collection<String>) >> Collections.emptyList()
         and: 'persisting yang resource raises db constraint exception (in case of concurrent requests for example)'
-            yangResourceRepositoryMock.saveAll(_) >> { throw dbException }
+            mockYangResourceRepository.saveAll(_) >> { throw dbException }
         when: 'attempt to store schema set '
             def newYangResourcesNameToContentMap = [(yangResourceName):yangResourceContent]
             objectUnderTest.storeSchemaSet('my-dataspace', 'my-schema-set', newYangResourcesNameToContentMap)
@@ -90,4 +89,15 @@ class CpsModulePersistenceServiceSpec extends Specification {
             'other data failure'                | otherIntegrityException                   || DataIntegrityViolationException | 'another integrity exception'
     }
 
+    def 'Upgrade existing schema set'() {
+        given: 'old schema has empty yang resource'
+            mockYangResourceRepository.findAllByChecksumIn(_ as Collection<String>) >> Collections.emptyList()
+        def schemaSetEntity = new SchemaSetEntity(id: 1)
+            mockSchemaSetRepository.getByDataspaceAndName(_, _) >> schemaSetEntity
+        when: 'schema set update is requested'
+            objectUnderTest.updateSchemaSetFromModules('my-dataspace', 'my-schemaset', [:], [new ModuleReference('some module name', 'some revision name')])
+        then: 'no exception is thrown '
+            noExceptionThrown()
+    }
+
 }
index 3749f71..a428a35 100644 (file)
@@ -29,7 +29,7 @@
   <parent>
     <groupId>org.onap.cps</groupId>
     <artifactId>cps-parent</artifactId>
-    <version>3.4.1-SNAPSHOT</version>
+    <version>3.4.2-SNAPSHOT</version>
     <relativePath>../cps-parent/pom.xml</relativePath>
   </parent>
 
old mode 100755 (executable)
new mode 100644 (file)
similarity index 75%
rename from cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java
rename to cps-service/src/main/java/org/onap/cps/api/CpsAnchorService.java
index edd052a..a247150
@@ -1,9 +1,6 @@
 /*
- *  ============LICENSE_START=======================================================
- *  Copyright (C) 2020-2023 Nordix Foundation
- *  Modifications Copyright (C) 2020-2022 Bell Canada.
- *  Modifications Copyright (C) 2021 Pantheon.tech
- *  Modifications Copyright (C) 2022 TechMahindra Ltd.
+ * ============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.
 package org.onap.cps.api;
 
 import java.util.Collection;
-import org.onap.cps.spi.exceptions.AlreadyDefinedException;
 import org.onap.cps.spi.exceptions.CpsException;
 import org.onap.cps.spi.model.Anchor;
-import org.onap.cps.spi.model.Dataspace;
 
-/**
- * CPS Admin Service.
- */
-public interface CpsAdminService {
-
-    /**
-     * Create dataspace.
-     *
-     * @param dataspaceName dataspace name
-     * @throws AlreadyDefinedException if dataspace with same name already exists
-     */
-    void createDataspace(String dataspaceName);
-
-    /**
-     * Delete dataspace.
-     *
-     * @param dataspaceName the name of the dataspace to delete
-     */
-    void deleteDataspace(String dataspaceName);
-
-    /**
-     * Get dataspace by given dataspace name.
-     *
-     * @param dataspaceName dataspace name
-     * @return a dataspace
-     */
-    Dataspace getDataspace(String dataspaceName);
-
-    /**
-     * Get All Dataspaces.
-     *
-     *
-     * @return a collection of dataspaces
-     */
-    Collection<Dataspace> getAllDataspaces();
+public interface CpsAnchorService {
 
     /**
      * Create an Anchor.
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsDataspaceService.java b/cps-service/src/main/java/org/onap/cps/api/CpsDataspaceService.java
new file mode 100644 (file)
index 0000000..7b94604
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2020-2023 Nordix Foundation
+ *  Modifications Copyright (C) 2020-2022 Bell Canada.
+ *  Modifications Copyright (C) 2021 Pantheon.tech
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd.
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.api;
+
+import java.util.Collection;
+import org.onap.cps.spi.exceptions.AlreadyDefinedException;
+import org.onap.cps.spi.model.Dataspace;
+
+/**
+ * CPS Admin Service.
+ */
+public interface CpsDataspaceService {
+
+    /**
+     * Create dataspace.
+     *
+     * @param dataspaceName dataspace name
+     * @throws AlreadyDefinedException if dataspace with same name already exists
+     */
+    void createDataspace(String dataspaceName);
+
+    /**
+     * Delete dataspace.
+     *
+     * @param dataspaceName the name of the dataspace to delete
+     */
+    void deleteDataspace(String dataspaceName);
+
+    /**
+     * Get dataspace by given dataspace name.
+     *
+     * @param dataspaceName dataspace name
+     * @return a dataspace
+     */
+    Dataspace getDataspace(String dataspaceName);
+
+    /**
+     * Get All Dataspaces.
+     *
+     *
+     * @return a collection of dataspaces
+     */
+    Collection<Dataspace> getAllDataspaces();
+
+}
index e8c3e77..2928464 100644 (file)
@@ -53,7 +53,7 @@ public interface CpsModuleService {
      * @param newModuleNameToContentMap YANG resources map where key is a module name and value is content
      * @param allModuleReferences       All YANG resource module references
      */
-    void createOrUpgradeSchemaSetFromModules(String dataspaceName, String schemaSetName,
+    void createSchemaSetFromModules(String dataspaceName, String schemaSetName,
                                     Map<String, String> newModuleNameToContentMap,
                                     Collection<ModuleReference> allModuleReferences);
 
@@ -94,6 +94,19 @@ public interface CpsModuleService {
      */
     void deleteSchemaSetsWithCascade(String dataspaceName, Collection<String> schemaSetNames);
 
+
+    /**
+     * upgrade schema sets with existing or new 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 upgradeSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+                                     final Map<String, String> newModuleNameToContentMap,
+                                     final Collection<ModuleReference> allModuleReferences);
+
     /**
      * Retrieve module references for the given dataspace name.
      *
old mode 100755 (executable)
new mode 100644 (file)
similarity index 66%
rename from cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java
rename to cps-service/src/main/java/org/onap/cps/api/impl/CpsAnchorServiceImpl.java
index d83ee43..f09a795
@@ -1,9 +1,6 @@
 /*
- *  ============LICENSE_START=======================================================
- *  Copyright (C) 2020-2023 Nordix Foundation
- *  Modifications Copyright (C) 2020-2022 Bell Canada.
- *  Modifications Copyright (C) 2021 Pantheon.tech
- *  Modifications Copyright (C) 2022 TechMahindra Ltd.
+ * ============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.
 
 package org.onap.cps.api.impl;
 
-import java.time.OffsetDateTime;
 import java.util.Collection;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
-import org.onap.cps.api.CpsAdminService;
-import org.onap.cps.api.CpsDataService;
+import org.onap.cps.api.CpsAnchorService;
 import org.onap.cps.spi.CpsAdminPersistenceService;
+import org.onap.cps.spi.CpsDataPersistenceService;
 import org.onap.cps.spi.model.Anchor;
-import org.onap.cps.spi.model.Dataspace;
 import org.onap.cps.spi.utils.CpsValidator;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
 
-@Component("CpsAdminServiceImpl")
-@RequiredArgsConstructor(onConstructor = @__(@Lazy))
-public class CpsAdminServiceImpl implements CpsAdminService {
+@Service
+@RequiredArgsConstructor
+public class CpsAnchorServiceImpl implements CpsAnchorService {
 
     private final CpsAdminPersistenceService cpsAdminPersistenceService;
-    @Lazy
-    private final CpsDataService cpsDataService;
+    private final CpsDataPersistenceService cpsDataPersistenceService;
     private final CpsValidator cpsValidator;
 
-    @Override
-    public void createDataspace(final String dataspaceName) {
-        cpsValidator.validateNameCharacters(dataspaceName);
-        cpsAdminPersistenceService.createDataspace(dataspaceName);
-    }
-
-    @Override
-    public void deleteDataspace(final String dataspaceName) {
-        cpsValidator.validateNameCharacters(dataspaceName);
-        cpsAdminPersistenceService.deleteDataspace(dataspaceName);
-    }
-
-    @Override
-    public Dataspace getDataspace(final String dataspaceName) {
-        cpsValidator.validateNameCharacters(dataspaceName);
-        return cpsAdminPersistenceService.getDataspace(dataspaceName);
-    }
-
-    @Override
-    public Collection<Dataspace> getAllDataspaces() {
-        return cpsAdminPersistenceService.getAllDataspaces();
-    }
-
     @Override
     public void createAnchor(final String dataspaceName, final String schemaSetName, final String anchorName) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName, anchorName);
@@ -102,7 +72,7 @@ public class CpsAdminServiceImpl implements CpsAdminService {
     @Override
     public void deleteAnchor(final String dataspaceName, final String anchorName) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        cpsDataService.deleteDataNodes(dataspaceName, anchorName, OffsetDateTime.now());
+        cpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName);
         cpsAdminPersistenceService.deleteAnchor(dataspaceName, anchorName);
     }
 
@@ -110,7 +80,7 @@ public class CpsAdminServiceImpl implements CpsAdminService {
     public void deleteAnchors(final String dataspaceName, final Collection<String> anchorNames) {
         cpsValidator.validateNameCharacters(dataspaceName);
         cpsValidator.validateNameCharacters(anchorNames);
-        cpsDataService.deleteDataNodes(dataspaceName, anchorNames, OffsetDateTime.now());
+        cpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorNames);
         cpsAdminPersistenceService.deleteAnchors(dataspaceName, anchorNames);
     }
 
@@ -123,8 +93,8 @@ public class CpsAdminServiceImpl implements CpsAdminService {
 
     @Override
     public void updateAnchorSchemaSet(final String dataspaceName,
-                                         final String anchorName,
-                                         final String schemaSetName) {
+                                      final String anchorName,
+                                      final String schemaSetName) {
         cpsAdminPersistenceService.updateAnchorSchemaSet(dataspaceName, anchorName, schemaSetName);
     }
 }
index e74e0ad..a1bae6a 100755 (executable)
 
 package org.onap.cps.api.impl;
 
-import static org.onap.cps.notification.Operation.CREATE;
-import static org.onap.cps.notification.Operation.DELETE;
-import static org.onap.cps.notification.Operation.UPDATE;
-
 import io.micrometer.core.annotation.Timed;
 import java.io.Serializable;
 import java.time.OffsetDateTime;
@@ -39,12 +35,10 @@ import java.util.Map;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsAnchorService;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.api.CpsDeltaService;
 import org.onap.cps.cpspath.parser.CpsPathUtil;
-import org.onap.cps.notification.NotificationService;
-import org.onap.cps.notification.Operation;
 import org.onap.cps.spi.CpsDataPersistenceService;
 import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.spi.exceptions.DataValidationException;
@@ -68,9 +62,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     private static final long DEFAULT_LOCK_TIMEOUT_IN_MILLISECONDS = 300L;
 
     private final CpsDataPersistenceService cpsDataPersistenceService;
-    private final CpsAdminService cpsAdminService;
+    private final CpsAnchorService cpsAnchorService;
     private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
-    private final NotificationService notificationService;
     private final CpsValidator cpsValidator;
     private final TimedYangParser timedYangParser;
     private final CpsDeltaService cpsDeltaService;
@@ -87,10 +80,9 @@ public class CpsDataServiceImpl implements CpsDataService {
     public void saveData(final String dataspaceName, final String anchorName, final String nodeData,
                          final OffsetDateTime observedTimestamp, final ContentType contentType) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         final Collection<DataNode> dataNodes = buildDataNodes(anchor, ROOT_NODE_XPATH, nodeData, contentType);
         cpsDataPersistenceService.storeDataNodes(dataspaceName, anchorName, dataNodes);
-        processDataUpdatedEventAsync(anchor, ROOT_NODE_XPATH, CREATE, observedTimestamp);
     }
 
     @Override
@@ -106,10 +98,9 @@ public class CpsDataServiceImpl implements CpsDataService {
                          final String nodeData, final OffsetDateTime observedTimestamp,
                          final ContentType contentType) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         final Collection<DataNode> dataNodes = buildDataNodes(anchor, parentNodeXpath, nodeData, contentType);
         cpsDataPersistenceService.addChildDataNodes(dataspaceName, anchorName, parentNodeXpath, dataNodes);
-        processDataUpdatedEventAsync(anchor, parentNodeXpath, CREATE, observedTimestamp);
     }
 
     @Override
@@ -118,7 +109,7 @@ public class CpsDataServiceImpl implements CpsDataService {
     public void saveListElements(final String dataspaceName, final String anchorName,
         final String parentNodeXpath, final String jsonData, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         final Collection<DataNode> listElementDataNodeCollection =
             buildDataNodes(anchor, parentNodeXpath, jsonData, ContentType.JSON);
         if (isRootNodeXpath(parentNodeXpath)) {
@@ -127,7 +118,6 @@ public class CpsDataServiceImpl implements CpsDataService {
             cpsDataPersistenceService.addListElements(dataspaceName, anchorName, parentNodeXpath,
                                                       listElementDataNodeCollection);
         }
-        processDataUpdatedEventAsync(anchor, parentNodeXpath, UPDATE, observedTimestamp);
     }
 
     @Override
@@ -136,12 +126,11 @@ public class CpsDataServiceImpl implements CpsDataService {
     public void saveListElementsBatch(final String dataspaceName, final String anchorName, final String parentNodeXpath,
             final Collection<String> jsonDataList, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         final Collection<Collection<DataNode>> listElementDataNodeCollections =
                 buildDataNodes(anchor, parentNodeXpath, jsonDataList, ContentType.JSON);
         cpsDataPersistenceService.addMultipleLists(dataspaceName, anchorName, parentNodeXpath,
                 listElementDataNodeCollections);
-        processDataUpdatedEventAsync(anchor, parentNodeXpath, UPDATE, observedTimestamp);
     }
 
     @Override
@@ -171,13 +160,12 @@ public class CpsDataServiceImpl implements CpsDataService {
     public void updateNodeLeaves(final String dataspaceName, final String anchorName, final String parentNodeXpath,
         final String jsonData, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         final Collection<DataNode> dataNodesInPatch = buildDataNodes(anchor, parentNodeXpath, jsonData,
                 ContentType.JSON);
         final Map<String, Map<String, Serializable>> xpathToUpdatedLeaves = dataNodesInPatch.stream()
                 .collect(Collectors.toMap(DataNode::getXpath, DataNode::getLeaves));
         cpsDataPersistenceService.batchUpdateDataLeaves(dataspaceName, anchorName, xpathToUpdatedLeaves);
-        processDataUpdatedEventAsync(anchor, parentNodeXpath, UPDATE, observedTimestamp);
     }
 
     @Override
@@ -188,13 +176,12 @@ public class CpsDataServiceImpl implements CpsDataService {
         final String dataNodeUpdatesAsJson,
         final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         final Collection<DataNode> dataNodeUpdates =
             buildDataNodes(anchor, parentNodeXpath, dataNodeUpdatesAsJson, ContentType.JSON);
         for (final DataNode dataNodeUpdate : dataNodeUpdates) {
             processDataNodeUpdate(anchor, dataNodeUpdate);
         }
-        processDataUpdatedEventAsync(anchor, parentNodeXpath, UPDATE, observedTimestamp);
     }
 
     @Override
@@ -241,10 +228,9 @@ public class CpsDataServiceImpl implements CpsDataService {
                                              final String parentNodeXpath, final String jsonData,
                                              final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         final Collection<DataNode> dataNodes = buildDataNodes(anchor, parentNodeXpath, jsonData, ContentType.JSON);
         cpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, dataNodes);
-        processDataUpdatedEventAsync(anchor, parentNodeXpath, UPDATE, observedTimestamp);
     }
 
     @Override
@@ -254,11 +240,9 @@ public class CpsDataServiceImpl implements CpsDataService {
                                               final Map<String, String> nodesJsonData,
                                               final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         final Collection<DataNode> dataNodes = buildDataNodes(anchor, nodesJsonData);
         cpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, dataNodes);
-        nodesJsonData.keySet().forEach(nodeXpath ->
-            processDataUpdatedEventAsync(anchor, nodeXpath, UPDATE, observedTimestamp));
     }
 
     @Override
@@ -267,7 +251,7 @@ public class CpsDataServiceImpl implements CpsDataService {
     public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
             final String jsonData, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         final Collection<DataNode> newListElements =
             buildDataNodes(anchor, parentNodeXpath, jsonData, ContentType.JSON);
         replaceListContent(dataspaceName, anchorName, parentNodeXpath, newListElements, observedTimestamp);
@@ -279,9 +263,7 @@ public class CpsDataServiceImpl implements CpsDataService {
     public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
             final Collection<DataNode> dataNodes, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
         cpsDataPersistenceService.replaceListContent(dataspaceName, anchorName, parentNodeXpath, dataNodes);
-        processDataUpdatedEventAsync(anchor, parentNodeXpath, UPDATE, observedTimestamp);
     }
 
     @Override
@@ -290,9 +272,7 @@ public class CpsDataServiceImpl implements CpsDataService {
     public void deleteDataNode(final String dataspaceName, final String anchorName, final String dataNodeXpath,
                                final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
         cpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, dataNodeXpath);
-        processDataUpdatedEventAsync(anchor, dataNodeXpath, DELETE, observedTimestamp);
     }
 
     @Override
@@ -302,9 +282,6 @@ public class CpsDataServiceImpl implements CpsDataService {
                                 final Collection<String> dataNodeXpaths, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
         cpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName, dataNodeXpaths);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
-        dataNodeXpaths.forEach(dataNodeXpath ->
-            processDataUpdatedEventAsync(anchor, dataNodeXpath, DELETE, observedTimestamp));
     }
 
     @Override
@@ -313,8 +290,6 @@ public class CpsDataServiceImpl implements CpsDataService {
     public void deleteDataNodes(final String dataspaceName, final String anchorName,
                                 final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
-        processDataUpdatedEventAsync(anchor, ROOT_NODE_XPATH, DELETE, observedTimestamp);
         cpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName);
     }
 
@@ -325,9 +300,6 @@ public class CpsDataServiceImpl implements CpsDataService {
                                 final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName);
         cpsValidator.validateNameCharacters(anchorNames);
-        for (final Anchor anchor : cpsAdminService.getAnchors(dataspaceName, anchorNames)) {
-            processDataUpdatedEventAsync(anchor, ROOT_NODE_XPATH, DELETE, observedTimestamp);
-        }
         cpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorNames);
     }
 
@@ -337,9 +309,7 @@ public class CpsDataServiceImpl implements CpsDataService {
     public void deleteListOrListElement(final String dataspaceName, final String anchorName, final String listNodeXpath,
         final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
         cpsDataPersistenceService.deleteListDataNode(dataspaceName, anchorName, listNodeXpath);
-        processDataUpdatedEventAsync(anchor, listNodeXpath, DELETE, observedTimestamp);
     }
 
     private Collection<DataNode> buildDataNodes(final Anchor anchor, final Map<String, String> nodesJsonData) {
@@ -385,16 +355,6 @@ public class CpsDataServiceImpl implements CpsDataService {
             .collect(Collectors.toList());
     }
 
-    private void processDataUpdatedEventAsync(final Anchor anchor, final String xpath,
-                                              final Operation operation, final OffsetDateTime observedTimestamp) {
-        try {
-            notificationService.processDataUpdatedEvent(anchor, xpath, operation, observedTimestamp);
-        } catch (final Exception exception) {
-            //If async message can't be queued for notification service, the initial request should not fail.
-            log.error("Failed to send message to notification service", exception);
-        }
-    }
-
     private SchemaContext getSchemaContext(final Anchor anchor) {
         return yangTextSchemaSourceSetCache
             .get(anchor.getDataspaceName(), anchor.getSchemaSetName()).getSchemaContext();
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataspaceServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataspaceServiceImpl.java
new file mode 100644 (file)
index 0000000..a7f5da4
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2020-2023 Nordix Foundation
+ *  Modifications Copyright (C) 2020-2022 Bell Canada.
+ *  Modifications Copyright (C) 2021 Pantheon.tech
+ *  Modifications Copyright (C) 2022 TechMahindra Ltd.
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.api.impl;
+
+import java.util.Collection;
+import lombok.RequiredArgsConstructor;
+import org.onap.cps.api.CpsDataspaceService;
+import org.onap.cps.spi.CpsAdminPersistenceService;
+import org.onap.cps.spi.model.Dataspace;
+import org.onap.cps.spi.utils.CpsValidator;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class CpsDataspaceServiceImpl implements CpsDataspaceService {
+
+    private final CpsAdminPersistenceService cpsAdminPersistenceService;
+    private final CpsValidator cpsValidator;
+
+    @Override
+    public void createDataspace(final String dataspaceName) {
+        cpsValidator.validateNameCharacters(dataspaceName);
+        cpsAdminPersistenceService.createDataspace(dataspaceName);
+    }
+
+    @Override
+    public void deleteDataspace(final String dataspaceName) {
+        cpsValidator.validateNameCharacters(dataspaceName);
+        cpsAdminPersistenceService.deleteDataspace(dataspaceName);
+    }
+
+    @Override
+    public Dataspace getDataspace(final String dataspaceName) {
+        cpsValidator.validateNameCharacters(dataspaceName);
+        return cpsAdminPersistenceService.getDataspace(dataspaceName);
+    }
+
+    @Override
+    public Collection<Dataspace> getAllDataspaces() {
+        return cpsAdminPersistenceService.getAllDataspaces();
+    }
+
+}
index d274b51..61a4e62 100644 (file)
@@ -28,7 +28,7 @@ import java.util.Collection;
 import java.util.Map;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
-import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsAnchorService;
 import org.onap.cps.api.CpsModuleService;
 import org.onap.cps.spi.CascadeDeleteAllowed;
 import org.onap.cps.spi.CpsModulePersistenceService;
@@ -49,7 +49,7 @@ public class CpsModuleServiceImpl implements CpsModuleService {
 
     private final CpsModulePersistenceService cpsModulePersistenceService;
     private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
-    private final CpsAdminService cpsAdminService;
+    private final CpsAnchorService cpsAnchorService;
     private final CpsValidator cpsValidator;
     private final TimedYangTextSchemaSourceSetBuilder timedYangTextSchemaSourceSetBuilder;
 
@@ -66,9 +66,9 @@ public class CpsModuleServiceImpl implements CpsModuleService {
     }
 
     @Override
-    public void createOrUpgradeSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
-        final Map<String, String> newModuleNameToContentMap,
-        final Collection<ModuleReference> allModuleReferences) {
+    public void createSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+                                           final Map<String, String> newModuleNameToContentMap,
+                                           final Collection<ModuleReference> allModuleReferences) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
         cpsModulePersistenceService.storeSchemaSetFromModules(dataspaceName, schemaSetName,
             newModuleNameToContentMap, allModuleReferences);
@@ -97,12 +97,12 @@ public class CpsModuleServiceImpl implements CpsModuleService {
     public void deleteSchemaSet(final String dataspaceName, final String schemaSetName,
                                 final CascadeDeleteAllowed cascadeDeleteAllowed) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
-        final Collection<Anchor> anchors = cpsAdminService.getAnchors(dataspaceName, schemaSetName);
+        final Collection<Anchor> anchors = cpsAnchorService.getAnchors(dataspaceName, schemaSetName);
         if (!anchors.isEmpty() && isCascadeDeleteProhibited(cascadeDeleteAllowed)) {
             throw new SchemaSetInUseException(dataspaceName, schemaSetName);
         }
         for (final Anchor anchor : anchors) {
-            cpsAdminService.deleteAnchor(dataspaceName, anchor.getName());
+            cpsAnchorService.deleteAnchor(dataspaceName, anchor.getName());
         }
         cpsModulePersistenceService.deleteSchemaSet(dataspaceName, schemaSetName);
         yangTextSchemaSourceSetCache.removeFromCache(dataspaceName, schemaSetName);
@@ -114,9 +114,9 @@ public class CpsModuleServiceImpl implements CpsModuleService {
     public void deleteSchemaSetsWithCascade(final String dataspaceName, final Collection<String> schemaSetNames) {
         cpsValidator.validateNameCharacters(dataspaceName);
         cpsValidator.validateNameCharacters(schemaSetNames);
-        final Collection<String> anchorNames = cpsAdminService.getAnchors(dataspaceName, schemaSetNames)
+        final Collection<String> anchorNames = cpsAnchorService.getAnchors(dataspaceName, schemaSetNames)
             .stream().map(Anchor::getName).collect(Collectors.toSet());
-        cpsAdminService.deleteAnchors(dataspaceName, anchorNames);
+        cpsAnchorService.deleteAnchors(dataspaceName, anchorNames);
         cpsModulePersistenceService.deleteUnusedYangResourceModules();
         cpsModulePersistenceService.deleteSchemaSets(dataspaceName, schemaSetNames);
         for (final String schemaSetName : schemaSetNames) {
@@ -124,6 +124,17 @@ public class CpsModuleServiceImpl implements CpsModuleService {
         }
     }
 
+    @Override
+    public void upgradeSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+                                            final Map<String, String> newModuleNameToContentMap,
+                                            final Collection<ModuleReference> allModuleReferences) {
+        cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+        cpsModulePersistenceService.updateSchemaSetFromModules(dataspaceName, schemaSetName,
+                newModuleNameToContentMap, allModuleReferences);
+        yangTextSchemaSourceSetCache.removeFromCache(dataspaceName, schemaSetName);
+    }
+
+
     @Override
     public Collection<ModuleReference> getYangResourceModuleReferences(final String dataspaceName) {
         cpsValidator.validateNameCharacters(dataspaceName);
diff --git a/cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java b/cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java
deleted file mode 100644 (file)
index 696fd60..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (c) 2021-2022 Bell Canada.
- * Modifications Copyright (c) 2022-2023 Nordix Foundation
- * Modifications Copyright (C) 2023 TechMahindra Ltd.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.notification;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.time.OffsetDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.SneakyThrows;
-import org.onap.cps.api.CpsDataService;
-import org.onap.cps.event.model.Content;
-import org.onap.cps.event.model.CpsDataUpdatedEvent;
-import org.onap.cps.event.model.Data;
-import org.onap.cps.spi.FetchDescendantsOption;
-import org.onap.cps.spi.model.Anchor;
-import org.onap.cps.spi.model.DataNode;
-import org.onap.cps.utils.DataMapUtils;
-import org.onap.cps.utils.PrefixResolver;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Component;
-
-@Component
-@AllArgsConstructor(onConstructor = @__(@Lazy))
-public class CpsDataUpdatedEventFactory {
-
-    private static final DateTimeFormatter DATE_TIME_FORMATTER =
-        DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
-
-    @Lazy
-    private final CpsDataService cpsDataService;
-
-    @Lazy
-    private final PrefixResolver prefixResolver;
-
-    /**
-     * Generates CPS Data Updated event. If observedTimestamp is not provided, then current timestamp is used.
-     *
-     * @param anchor            anchor
-     * @param observedTimestamp observedTimestamp
-     * @param operation         operation
-     * @return CpsDataUpdatedEvent
-     */
-    public CpsDataUpdatedEvent createCpsDataUpdatedEvent(final Anchor anchor,
-        final OffsetDateTime observedTimestamp, final Operation operation) {
-        final var dataNode = (operation == Operation.DELETE) ? null :
-            cpsDataService.getDataNodes(anchor.getDataspaceName(), anchor.getName(),
-                "/", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS).iterator().next();
-        return toCpsDataUpdatedEvent(anchor, dataNode, observedTimestamp, operation);
-    }
-
-    @SneakyThrows(URISyntaxException.class)
-    private CpsDataUpdatedEvent toCpsDataUpdatedEvent(final Anchor anchor,
-                                                      final DataNode dataNode,
-                                                      final OffsetDateTime observedTimestamp,
-                                                      final Operation operation) {
-        final CpsDataUpdatedEvent cpsDataUpdatedEvent = new CpsDataUpdatedEvent();
-        cpsDataUpdatedEvent.withContent(createContent(anchor, dataNode, observedTimestamp, operation));
-        cpsDataUpdatedEvent.withId(UUID.randomUUID().toString());
-        cpsDataUpdatedEvent.withSchema(new URI("urn:cps:org.onap.cps:data-updated-event-schema:v1"));
-        cpsDataUpdatedEvent.withSource(new URI("urn:cps:org.onap.cps"));
-        cpsDataUpdatedEvent.withType("org.onap.cps.data-updated-event");
-        return cpsDataUpdatedEvent;
-    }
-
-    private Data createData(final DataNode dataNode, final String prefix) {
-        final Data data = new Data();
-        DataMapUtils.toDataMapWithIdentifier(dataNode, prefix).forEach(data::setAdditionalProperty);
-        return data;
-    }
-
-    private Content createContent(final Anchor anchor, final DataNode dataNode,
-        final OffsetDateTime observedTimestamp, final Operation operation) {
-        final var content = new Content();
-        content.withAnchorName(anchor.getName());
-        content.withDataspaceName(anchor.getDataspaceName());
-        content.withSchemaSetName(anchor.getSchemaSetName());
-        content.withOperation(Content.Operation.fromValue(operation.name()));
-        content.withObservedTimestamp(
-            DATE_TIME_FORMATTER.format(observedTimestamp == null ? OffsetDateTime.now() : observedTimestamp));
-        if (dataNode != null) {
-            final String prefix = prefixResolver.getPrefix(anchor, dataNode.getXpath());
-            content.withData(createData(dataNode, prefix));
-        }
-        return content;
-    }
-}
diff --git a/cps-service/src/main/java/org/onap/cps/notification/KafkaProducerListener.java b/cps-service/src/main/java/org/onap/cps/notification/KafkaProducerListener.java
deleted file mode 100644 (file)
index f4b68c0..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Bell Canada. All rights reserved.
- *  ================================================================================
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  SPDX-License-Identifier: Apache-2.0
- *  ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.notification;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.kafka.clients.producer.ProducerRecord;
-import org.apache.kafka.clients.producer.RecordMetadata;
-import org.springframework.kafka.support.ProducerListener;
-import org.springframework.stereotype.Component;
-
-@Slf4j
-@Component
-public class KafkaProducerListener<K, V> implements ProducerListener<K, V> {
-
-    private NotificationErrorHandler notificationErrorHandler;
-
-    public KafkaProducerListener(final NotificationErrorHandler notificationErrorHandler) {
-        this.notificationErrorHandler = notificationErrorHandler;
-    }
-
-    @Override
-    public void onSuccess(final ProducerRecord<K, V> producerRecord, final RecordMetadata recordMetadata) {
-        log.debug("Message sent to event-bus topic :'{}' with body : {} ", producerRecord.topic(),
-            producerRecord.value());
-    }
-
-    @Override
-    public void onError(final ProducerRecord<K, V> producerRecord,
-            final RecordMetadata recordMetadata,
-            final Exception exception) {
-        notificationErrorHandler.onException("Failed to send message to message bus",
-            exception, producerRecord, recordMetadata);
-    }
-
-}
diff --git a/cps-service/src/main/java/org/onap/cps/notification/NotificationErrorHandler.java b/cps-service/src/main/java/org/onap/cps/notification/NotificationErrorHandler.java
deleted file mode 100644 (file)
index eef028d..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Bell Canada. All rights reserved.
- *  ================================================================================
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  SPDX-License-Identifier: Apache-2.0
- *  ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.notification;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-@Component
-@Slf4j
-public class NotificationErrorHandler {
-
-    void onException(final Exception exception, final Object... context) {
-        onException("Failed to process", exception, context);
-    }
-
-    void onException(final String message, final Exception exception, final Object... context) {
-        log.error("{} \n Error cause: {} \n Error context: {}",
-            message,
-            exception.getCause() != null ? exception.getCause().toString() : exception.getMessage(),
-            context,
-            exception);
-    }
-}
diff --git a/cps-service/src/main/java/org/onap/cps/notification/NotificationProperties.java b/cps-service/src/main/java/org/onap/cps/notification/NotificationProperties.java
deleted file mode 100644 (file)
index b8a7144..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Bell Canada. All rights reserved.
- *  ================================================================================
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  SPDX-License-Identifier: Apache-2.0
- *  ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.notification;
-
-import jakarta.validation.constraints.NotNull;
-import java.util.Collections;
-import java.util.Map;
-import lombok.Data;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-import org.springframework.validation.annotation.Validated;
-
-@ConfigurationProperties(prefix = "notification.data-updated")
-@Component
-@Data
-@Validated
-public class NotificationProperties {
-
-    @NotNull
-    private String topic;
-    private Map<String, String> filters = Collections.emptyMap();
-
-    @Value("${notification.enabled:true}")
-    private boolean enabled;
-}
diff --git a/cps-service/src/main/java/org/onap/cps/notification/NotificationPublisher.java b/cps-service/src/main/java/org/onap/cps/notification/NotificationPublisher.java
deleted file mode 100644 (file)
index 2d87488..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (c) 2021 Bell Canada.
- *  ================================================================================
- *  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.notification;
-
-import lombok.extern.slf4j.Slf4j;
-import org.checkerframework.checker.nullness.qual.NonNull;
-import org.onap.cps.event.model.CpsDataUpdatedEvent;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.kafka.core.KafkaTemplate;
-import org.springframework.stereotype.Component;
-
-@Component
-@Slf4j
-public class NotificationPublisher {
-
-    private KafkaTemplate<String, CpsDataUpdatedEvent> kafkaTemplate;
-    private String topicName;
-
-    /**
-     * Create an instance of Notification Publisher.
-     *
-     * @param kafkaTemplate kafkaTemplate is send event using kafka
-     * @param topicName     topic, to which cpsDataUpdatedEvent is sent, is provided by setting
-     *                      'notification.data-updated.topic' in the application properties
-     */
-    @Autowired
-    public NotificationPublisher(
-        final KafkaTemplate<String, CpsDataUpdatedEvent> kafkaTemplate,
-        final @Value("${notification.data-updated.topic}") String topicName) {
-        this.kafkaTemplate = kafkaTemplate;
-        this.topicName = topicName;
-    }
-
-    /**
-     * Send event to Kafka with correct message key.
-     *
-     * @param cpsDataUpdatedEvent event to be sent to kafka
-     */
-    public void sendNotification(@NonNull final CpsDataUpdatedEvent cpsDataUpdatedEvent) {
-        final var messageKey = cpsDataUpdatedEvent.getContent().getDataspaceName() + ","
-            + cpsDataUpdatedEvent.getContent().getAnchorName();
-        log.debug("Data Updated event is being sent with messageKey: '{}' & body : {} ",
-            messageKey, cpsDataUpdatedEvent);
-        kafkaTemplate.send(topicName, messageKey, cpsDataUpdatedEvent);
-    }
-
-}
diff --git a/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java b/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java
deleted file mode 100644 (file)
index c29d042..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (c) 2021-2022 Bell Canada.
- * 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.
- * 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.notification;
-
-import jakarta.annotation.PostConstruct;
-import java.time.OffsetDateTime;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Future;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.api.CpsAdminService;
-import org.onap.cps.spi.model.Anchor;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Service;
-
-@Service
-@Slf4j
-@RequiredArgsConstructor
-public class NotificationService {
-
-    private final NotificationProperties notificationProperties;
-    private final NotificationPublisher notificationPublisher;
-    private final CpsDataUpdatedEventFactory cpsDataUpdatedEventFactory;
-    private final NotificationErrorHandler notificationErrorHandler;
-    private final CpsAdminService cpsAdminService;
-    private List<Pattern> dataspacePatterns;
-
-    @PostConstruct
-    public void init() {
-        log.info("Notification Properties {}", notificationProperties);
-        this.dataspacePatterns = getDataspaceFilterPatterns(notificationProperties);
-    }
-
-    private List<Pattern> getDataspaceFilterPatterns(final NotificationProperties notificationProperties) {
-        if (notificationProperties.isEnabled()) {
-            return Arrays.stream(notificationProperties.getFilters()
-                .getOrDefault("enabled-dataspaces", "")
-                .split(","))
-                .map(filterPattern -> Pattern.compile(filterPattern, Pattern.CASE_INSENSITIVE))
-                .collect(Collectors.toList());
-        } else {
-            return Collections.emptyList();
-        }
-    }
-
-    /**
-     * Process Data Updated Event and publishes the notification.
-     *
-     * @param anchor            anchor
-     * @param xpath             xpath of changed data node
-     * @param operation         operation
-     * @param observedTimestamp observedTimestamp
-     * @return future
-     */
-    @Async("notificationExecutor")
-    public Future<Void> processDataUpdatedEvent(final Anchor anchor, final String xpath, final Operation operation,
-                                                final OffsetDateTime observedTimestamp) {
-
-        log.debug("process data updated event for anchor '{}'", anchor);
-        try {
-            if (shouldSendNotification(anchor.getDataspaceName())) {
-                final var cpsDataUpdatedEvent =
-                        cpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(anchor,
-                                observedTimestamp, getRootNodeOperation(xpath, operation));
-                log.debug("data updated event to be published {}", cpsDataUpdatedEvent);
-                notificationPublisher.sendNotification(cpsDataUpdatedEvent);
-            }
-        } catch (final Exception exception) {
-            /* All the exceptions are handled to not to propagate it to caller.
-               CPS operation should not fail if sending event fails for any reason.
-             */
-            notificationErrorHandler.onException("Failed to process cps-data-updated-event.",
-                    exception, anchor, xpath, operation);
-        }
-        return CompletableFuture.completedFuture(null);
-    }
-
-    /*
-        Add more complex rules based on dataspace and anchor later
-     */
-    private boolean shouldSendNotification(final String dataspaceName) {
-
-        return notificationProperties.isEnabled()
-            && dataspacePatterns.stream()
-            .anyMatch(pattern -> pattern.matcher(dataspaceName).find());
-    }
-
-    private Operation getRootNodeOperation(final String xpath, final Operation operation) {
-        return isRootXpath(xpath) || isRootContainerNodeXpath(xpath) ? operation : Operation.UPDATE;
-    }
-
-    private static boolean isRootXpath(final String xpath) {
-        return "/".equals(xpath) || "".equals(xpath);
-    }
-
-    private static boolean isRootContainerNodeXpath(final String xpath) {
-        return 0 == xpath.lastIndexOf('/');
-    }
-
-}
diff --git a/cps-service/src/main/java/org/onap/cps/notification/Operation.java b/cps-service/src/main/java/org/onap/cps/notification/Operation.java
deleted file mode 100644 (file)
index 83e1ccf..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (c) 2022 Bell Canada.
- *  ================================================================================
- *  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.notification;
-
-public enum Operation {
-    CREATE,
-    UPDATE,
-    DELETE
-}
index beb3d4f..aaca2ee 100755 (executable)
@@ -43,7 +43,7 @@ public interface CpsModulePersistenceService {
     void storeSchemaSet(String dataspaceName, String schemaSetName, Map<String, String> yangResourcesNameToContentMap);
 
     /**
-     * Stores a schema set from new modules and existing modules.
+     * Stores a new schema set from new modules and existing modules.
      *
      * @param dataspaceName             Dataspace name
      * @param schemaSetName             Schema set name
@@ -53,6 +53,19 @@ public interface CpsModulePersistenceService {
     void storeSchemaSetFromModules(String dataspaceName, String schemaSetName,
         Map<String, String> newModuleNameToContentMap, Collection<ModuleReference> allModuleReferences);
 
+    /**
+     * Update an existing schema set from new modules and 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 resources module references
+     */
+    void updateSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
+                                    final Map<String, String> newModuleNameToContentMap,
+                                    final Collection<ModuleReference> allModuleReferences);
+
+
     /**
      * Get all schema sets for a given dataspace.
      *
index d58ddf4..35dc734 100644 (file)
@@ -26,7 +26,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import lombok.RequiredArgsConstructor;
-import org.onap.cps.api.CpsAdminService;
+import org.onap.cps.api.CpsAnchorService;
 import org.onap.cps.api.impl.YangTextSchemaSourceSetCache;
 import org.onap.cps.cache.AnchorDataCacheEntry;
 import org.onap.cps.cpspath.parser.CpsPathPrefixType;
@@ -48,7 +48,7 @@ public class PrefixResolver {
 
     private static final String CACHE_ENTRY_PROPERTY_NAME = "prefixPerContainerName";
 
-    private final CpsAdminService cpsAdminService;
+    private final CpsAnchorService cpsAnchorService;
 
     private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
 
@@ -63,7 +63,7 @@ public class PrefixResolver {
      * @return the prefix of the module the top level element of given xpath
      */
     public String getPrefix(final String dataspaceName, final String anchorName, final String xpath) {
-        final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
+        final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
         return getPrefix(anchor, xpath);
     }
 
@@ -1,9 +1,6 @@
 /*
- *  ============LICENSE_START=======================================================
- *  Copyright (C) 2020-2023 Nordix Foundation
- *  Modifications Copyright (C) 2020-2022 Bell Canada.
- *  Modifications Copyright (C) 2021 Pantheon.tech
- *  Modifications Copyright (C) 2022 TechMahindra Ltd.
+ * ============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.
 
 package org.onap.cps.api.impl
 
-import org.onap.cps.api.CpsDataService
 import org.onap.cps.spi.CpsAdminPersistenceService
+import org.onap.cps.spi.CpsDataPersistenceService
 import org.onap.cps.spi.exceptions.ModuleNamesNotFoundException
 import org.onap.cps.spi.model.Anchor
-import org.onap.cps.spi.model.Dataspace
 import org.onap.cps.spi.utils.CpsValidator
 import spock.lang.Specification
-import java.time.OffsetDateTime
 
-class CpsAdminServiceImplSpec extends Specification {
+class CpsAnchorServiceImplSpec extends Specification {
+
     def mockCpsAdminPersistenceService = Mock(CpsAdminPersistenceService)
-    def mockCpsDataService = Mock(CpsDataService)
+    def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
     def mockCpsValidator = Mock(CpsValidator)
-    def objectUnderTest = new CpsAdminServiceImpl(mockCpsAdminPersistenceService, mockCpsDataService,mockCpsValidator)
 
-    def 'Create dataspace method invokes persistence service.'() {
-        when: 'create dataspace method is invoked'
-            objectUnderTest.createDataspace('someDataspace')
-        then: 'the persistence service method is invoked with same parameters'
-            1 * mockCpsAdminPersistenceService.createDataspace('someDataspace')
-        and: 'the CpsValidator is called on the dataspaceName'
-            1 * mockCpsValidator.validateNameCharacters('someDataspace')
-    }
+    def objectUnderTest = new CpsAnchorServiceImpl(mockCpsAdminPersistenceService, mockCpsDataPersistenceService, mockCpsValidator)
 
     def 'Create anchor method invokes persistence service.'() {
         when: 'create anchor method is invoked'
@@ -105,29 +93,13 @@ class CpsAdminServiceImplSpec extends Specification {
             1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someAnchor')
     }
 
-    def 'Retrieve dataspace.'() {
-        given: 'a dataspace is already created'
-            def dataspace = new Dataspace(name: "someDataspace")
-            mockCpsAdminPersistenceService.getDataspace('someDataspace') >> dataspace
-        expect: 'the dataspace provided by persistence service is returned as result'
-          assert objectUnderTest.getDataspace('someDataspace') == dataspace
-    }
-
-    def 'Retrieve all dataspaces.'() {
-        given: 'that all given dataspaces are already created'
-        def dataspaces = [new Dataspace(name: "test-dataspace1"), new Dataspace(name: "test-dataspace2")]
-            mockCpsAdminPersistenceService.getAllDataspaces() >> dataspaces
-        expect: 'the dataspace provided by persistence service is returned as result'
-           assert objectUnderTest.getAllDataspaces() == dataspaces
-    }
-
     def 'Delete anchor.'() {
         when: 'delete anchor is invoked'
             objectUnderTest.deleteAnchor('someDataspace','someAnchor')
         then: 'delete data nodes is invoked on the data service with expected parameters'
-            1 * mockCpsDataService.deleteDataNodes('someDataspace','someAnchor', _ as OffsetDateTime )
+            1 * mockCpsDataPersistenceService.deleteDataNodes('someDataspace','someAnchor')
         and: 'the persistence service method is invoked with same parameters to delete anchor'
-             1 * mockCpsAdminPersistenceService.deleteAnchor('someDataspace','someAnchor')
+            1 * mockCpsAdminPersistenceService.deleteAnchor('someDataspace','someAnchor')
         and: 'the CpsValidator is called on the dataspaceName, anchorName'
             1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someAnchor')
     }
@@ -136,7 +108,7 @@ class CpsAdminServiceImplSpec extends Specification {
         when: 'delete anchors is invoked'
             objectUnderTest.deleteAnchors('someDataspace', ['anchor1', 'anchor2'])
         then: 'delete data nodes is invoked on the data service with expected parameters'
-            1 * mockCpsDataService.deleteDataNodes('someDataspace', _ as Collection<String>, _ as OffsetDateTime)
+            1 * mockCpsDataPersistenceService.deleteDataNodes('someDataspace', _ as Collection<String>)
         and: 'the persistence service method is invoked with same parameters to delete anchor'
             1 * mockCpsAdminPersistenceService.deleteAnchors('someDataspace',_ as Collection<String>)
         and: 'the CpsValidator is called on the dataspace name and anchor names'
@@ -157,7 +129,7 @@ class CpsAdminServiceImplSpec extends Specification {
 
     def 'Query all anchors with Module Names Not Found Exception in persistence layer.'() {
         given: 'the persistence layer throws a Module Names Not Found Exception'
-            def originalException = new ModuleNamesNotFoundException('exception-ds', [ 'm1', 'm2'])
+            def originalException = new ModuleNamesNotFoundException('exception-ds', ['m1', 'm2'])
             mockCpsAdminPersistenceService.queryAnchors(*_) >> { throw originalException}
         when: 'attempt query anchors'
             objectUnderTest.queryAnchorNames('some-dataspace-name', [])
@@ -170,19 +142,11 @@ class CpsAdminServiceImplSpec extends Specification {
             assert thrownUp.details.contains('m2')
     }
 
-    def 'Delete dataspace.'() {
-        when: 'delete dataspace is invoked'
-            objectUnderTest.deleteDataspace('someDataspace')
-        then: 'associated persistence service method is invoked with correct parameter'
-            1 * mockCpsAdminPersistenceService.deleteDataspace('someDataspace')
-        and: 'the CpsValidator is called on the dataspaceName'
-            1 * mockCpsValidator.validateNameCharacters('someDataspace')
-    }
-
     def 'Update anchor schema set.'() {
         when: 'update anchor is invoked'
             objectUnderTest.updateAnchorSchemaSet('someDataspace', 'someAnchor', 'someSchemaSetName')
         then: 'associated persistence service method is invoked with correct parameter'
             1 * mockCpsAdminPersistenceService.updateAnchorSchemaSet('someDataspace', 'someAnchor', 'someSchemaSetName')
     }
+
 }
index a914598..77e15c3 100644 (file)
 package org.onap.cps.api.impl
 
 import org.onap.cps.TestUtils
-import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsAnchorService
 import org.onap.cps.api.CpsDeltaService
-import org.onap.cps.notification.NotificationService
-import org.onap.cps.notification.Operation
 import org.onap.cps.spi.CpsDataPersistenceService
 import org.onap.cps.spi.FetchDescendantsOption
 import org.onap.cps.spi.exceptions.ConcurrencyException
@@ -38,7 +36,6 @@ import org.onap.cps.spi.exceptions.SessionTimeoutException
 import org.onap.cps.spi.model.Anchor
 import org.onap.cps.spi.model.DataNode
 import org.onap.cps.spi.model.DataNodeBuilder
-import org.onap.cps.spi.model.DeltaReportBuilder
 import org.onap.cps.spi.utils.CpsValidator
 import org.onap.cps.utils.ContentType
 import org.onap.cps.utils.TimedYangParser
@@ -46,27 +43,24 @@ import org.onap.cps.yang.YangTextSchemaSourceSet
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
 import spock.lang.Shared
 import spock.lang.Specification
-
 import java.time.OffsetDateTime
 import java.util.stream.Collectors
 
 class CpsDataServiceImplSpec extends Specification {
     def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
-    def mockCpsAdminService = Mock(CpsAdminService)
+    def mockCpsAnchorService = Mock(CpsAnchorService)
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
-    def mockNotificationService = Mock(NotificationService)
     def mockCpsValidator = Mock(CpsValidator)
     def timedYangParser = new TimedYangParser()
     def mockCpsDeltaService = Mock(CpsDeltaService);
 
-    def objectUnderTest = new CpsDataServiceImpl(mockCpsDataPersistenceService, mockCpsAdminService,
-            mockYangTextSchemaSourceSetCache, mockNotificationService, mockCpsValidator, timedYangParser, mockCpsDeltaService)
+    def objectUnderTest = new CpsDataServiceImpl(mockCpsDataPersistenceService, mockCpsAnchorService,
+            mockYangTextSchemaSourceSetCache, mockCpsValidator, timedYangParser, mockCpsDeltaService)
 
     def setup() {
-
-        mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
-        mockCpsAdminService.getAnchor(dataspaceName, ANCHOR_NAME_1) >> anchor1
-        mockCpsAdminService.getAnchor(dataspaceName, ANCHOR_NAME_2) >> anchor2
+        mockCpsAnchorService.getAnchor(dataspaceName, anchorName) >> anchor
+        mockCpsAnchorService.getAnchor(dataspaceName, ANCHOR_NAME_1) >> anchor1
+        mockCpsAnchorService.getAnchor(dataspaceName, ANCHOR_NAME_2) >> anchor2
     }
 
     @Shared
@@ -92,8 +86,6 @@ class CpsDataServiceImplSpec extends Specification {
                     { dataNode -> dataNode.xpath[0] == '/test-tree' })
         and: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'data updated event is sent to notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, '/', Operation.CREATE, observedTimestamp)
         where: 'given parameters'
             scenario | dataFile         | contentType
             'json'   | 'test-tree.json' | ContentType.JSON
@@ -115,18 +107,6 @@ class CpsDataServiceImplSpec extends Specification {
             'invalid xml'   | '<invalid xml'  | ContentType.XML  || 'Failed to parse xml data'
     }
 
-    def 'Saving #scenarioDesired data exception during notification.'() {
-        given: 'schema set for given anchor and dataspace references test-tree model'
-            setupSchemaSetMocks('test-tree.yang')
-        and: 'the notification service throws an exception'
-            mockNotificationService.processDataUpdatedEvent(*_) >> { throw new RuntimeException('to be ignored')}
-        when: 'save data method is invoked with test-tree json data'
-            def data = TestUtils.getResourceFileContent('test-tree.json')
-            objectUnderTest.saveData(dataspaceName, anchorName, data, observedTimestamp)
-        then: 'the exception is ignored'
-            noExceptionThrown()
-    }
-
     def 'Saving list element data fragment under Root node.'() {
         given: 'schema set for given anchor and dataspace references bookstore model'
             setupSchemaSetMocks('bookstore.yang')
@@ -145,8 +125,6 @@ class CpsDataServiceImplSpec extends Specification {
             )
         and: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'data updated event is sent to notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, '/', Operation.UPDATE, observedTimestamp)
     }
 
     def 'Saving child data fragment under existing node.'() {
@@ -160,8 +138,6 @@ class CpsDataServiceImplSpec extends Specification {
                 { dataNode -> dataNode.xpath[0] == '/test-tree/branch[@name=\'New\']' })
         and: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'data updated event is sent to notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, '/test-tree', Operation.CREATE, observedTimestamp)
     }
 
     def 'Saving list element data fragment under existing node.'() {
@@ -182,8 +158,6 @@ class CpsDataServiceImplSpec extends Specification {
             )
         and: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'data updated event is sent to notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, '/test-tree', Operation.UPDATE, observedTimestamp)
     }
 
     def 'Saving collection of a batch with data fragment under existing node.'() {
@@ -202,8 +176,6 @@ class CpsDataServiceImplSpec extends Specification {
                     assert listOfXpaths.containsAll(['/test-tree/branch[@name=\'B\']','/test-tree/branch[@name=\'A\']'])
                 }
             }
-        and: 'data updated event is sent to notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, '/test-tree', Operation.UPDATE, observedTimestamp)
     }
 
     def 'Saving empty list element data fragment.'() {
@@ -266,8 +238,6 @@ class CpsDataServiceImplSpec extends Specification {
             1 * mockCpsDataPersistenceService.batchUpdateDataLeaves(dataspaceName, anchorName, {dataNode -> dataNode.keySet()[0] == expectedNodeXpath})
         and: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'data updated event is sent to notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, parentNodeXpath, Operation.UPDATE, observedTimestamp)
         where: 'following parameters were used'
             scenario         | parentNodeXpath | jsonData                        || expectedNodeXpath
             'top level node' | '/'             | '{"test-tree": {"branch": []}}' || '/test-tree'
@@ -300,8 +270,6 @@ class CpsDataServiceImplSpec extends Specification {
             1 * mockCpsDataPersistenceService.batchUpdateDataLeaves(dataspaceName, anchorName, {dataNode -> dataNode.keySet()[index] == expectedNodeXpath})
         and: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'data updated event is sent to notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, parentNodeXpath, Operation.UPDATE, observedTimestamp)
         where: 'the following parameters were used'
             index | expectedNodeXpath
             0     | '/first-container'
@@ -325,8 +293,6 @@ class CpsDataServiceImplSpec extends Specification {
                     .iterator().next() == "/bookstore/categories[@code='01']/books[@title='new']"})
         and: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'the data updated event is sent to the notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, '/bookstore', Operation.UPDATE, observedTimestamp)
     }
 
     def 'Replace data node using singular data node: #scenario.'() {
@@ -337,8 +303,6 @@ class CpsDataServiceImplSpec extends Specification {
         then: 'the persistence service method is invoked with correct parameters'
             1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
                     { 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'
@@ -356,10 +320,6 @@ class CpsDataServiceImplSpec extends Specification {
         then: 'the persistence service method is invoked with correct parameters'
             1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
                 { dataNode -> dataNode.xpath == expectedNodeXpath})
-        and: 'data updated event is sent to notification service'
-            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'
@@ -399,8 +359,6 @@ class CpsDataServiceImplSpec extends Specification {
             )
         and: 'the CpsValidator is called on the dataspaceName and AnchorName twice'
             2 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'data updated event is sent to notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, '/test-tree', Operation.UPDATE, observedTimestamp)
     }
 
     def 'Replace whole list content with empty list element.'() {
@@ -420,8 +378,6 @@ class CpsDataServiceImplSpec extends Specification {
             1 * mockCpsDataPersistenceService.deleteListDataNode(dataspaceName, anchorName, '/test-tree/branch')
         and: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'data updated event is sent to notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, '/test-tree/branch', Operation.DELETE, observedTimestamp)
     }
 
     def 'Delete multiple list elements under existing node.'() {
@@ -431,8 +387,6 @@ class CpsDataServiceImplSpec extends Specification {
             1 * mockCpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName, ['/test-tree/branch[@name="A"]', '/test-tree/branch[@name="B"]'])
         and: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'two data updated events are sent to notification service'
-            2 * mockNotificationService.processDataUpdatedEvent(anchor, _, Operation.DELETE, observedTimestamp)
     }
 
     def 'Delete data node under anchor and dataspace.'() {
@@ -442,16 +396,12 @@ class CpsDataServiceImplSpec extends Specification {
             1 * mockCpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, '/data-node')
         and: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
-        and: 'data updated event is sent to notification service'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, '/data-node', Operation.DELETE, observedTimestamp)
     }
 
     def 'Delete all data nodes for a given anchor and dataspace.'() {
         when: 'delete data nodes method is invoked with correct parameters'
             objectUnderTest.deleteDataNodes(dataspaceName, anchorName, observedTimestamp)
-        then: 'data updated event is sent to notification service before the delete'
-            1 * mockNotificationService.processDataUpdatedEvent(anchor, '/', Operation.DELETE, observedTimestamp)
-        and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+        then: 'the CpsValidator is called on the dataspaceName and AnchorName'
             1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
         and: 'the persistence service method is invoked with the correct parameters'
             1 * mockCpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName)
@@ -474,14 +424,12 @@ class CpsDataServiceImplSpec extends Specification {
     def 'Delete all data nodes for given dataspace and multiple anchors.'() {
         given: 'schema set for given anchors and dataspace references test tree model'
             setupSchemaSetMocks('test-tree.yang')
-            mockCpsAdminService.getAnchors(dataspaceName, ['anchor1', 'anchor2']) >>
+            mockCpsAnchorService.getAnchors(dataspaceName, ['anchor1', 'anchor2']) >>
                 [new Anchor(name: 'anchor1', dataspaceName: dataspaceName),
                  new Anchor(name: 'anchor2', dataspaceName: dataspaceName)]
         when: 'delete data node method is invoked with correct parameters'
             objectUnderTest.deleteDataNodes(dataspaceName, ['anchor1', 'anchor2'], observedTimestamp)
-        then: 'data updated events are sent to notification service before the delete'
-            2 * mockNotificationService.processDataUpdatedEvent(_, '/', Operation.DELETE, observedTimestamp)
-        and: 'the CpsValidator is called on the dataspace name and the anchor names'
+        then: 'the CpsValidator is called on the dataspace name and the anchor names'
             2 * mockCpsValidator.validateNameCharacters(_)
         and: 'the persistence service method is invoked with the correct parameters'
             1 * mockCpsDataPersistenceService.deleteDataNodes(dataspaceName, _ as Collection<String>)
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataspaceServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataspaceServiceImplSpec.groovy
new file mode 100644 (file)
index 0000000..8e17594
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  ============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.api.impl
+
+import org.onap.cps.spi.CpsAdminPersistenceService
+import org.onap.cps.spi.model.Dataspace
+import org.onap.cps.spi.utils.CpsValidator
+import spock.lang.Specification
+
+class CpsDataspaceServiceImplSpec extends Specification {
+    def mockCpsAdminPersistenceService = Mock(CpsAdminPersistenceService)
+    def mockCpsValidator = Mock(CpsValidator)
+    def objectUnderTest = new CpsDataspaceServiceImpl(mockCpsAdminPersistenceService,mockCpsValidator)
+
+    def 'Create dataspace method invokes persistence service.'() {
+        when: 'create dataspace method is invoked'
+            objectUnderTest.createDataspace('someDataspace')
+        then: 'the persistence service method is invoked with same parameters'
+            1 * mockCpsAdminPersistenceService.createDataspace('someDataspace')
+        and: 'the CpsValidator is called on the dataspaceName'
+            1 * mockCpsValidator.validateNameCharacters('someDataspace')
+    }
+
+    def 'Retrieve dataspace.'() {
+        given: 'a dataspace is already created'
+            def dataspace = new Dataspace(name: "someDataspace")
+            mockCpsAdminPersistenceService.getDataspace('someDataspace') >> dataspace
+        expect: 'the dataspace provided by persistence service is returned as result'
+          assert objectUnderTest.getDataspace('someDataspace') == dataspace
+    }
+
+    def 'Retrieve all dataspaces.'() {
+        given: 'that all given dataspaces are already created'
+        def dataspaces = [new Dataspace(name: "test-dataspace1"), new Dataspace(name: "test-dataspace2")]
+            mockCpsAdminPersistenceService.getAllDataspaces() >> dataspaces
+        expect: 'the dataspace provided by persistence service is returned as result'
+           assert objectUnderTest.getAllDataspaces() == dataspaces
+    }
+
+    def 'Delete dataspace.'() {
+        when: 'delete dataspace is invoked'
+            objectUnderTest.deleteDataspace('someDataspace')
+        then: 'associated persistence service method is invoked with correct parameter'
+            1 * mockCpsAdminPersistenceService.deleteDataspace('someDataspace')
+        and: 'the CpsValidator is called on the dataspaceName'
+            1 * mockCpsValidator.validateNameCharacters('someDataspace')
+    }
+
+}
index 61f6741..d909e27 100644 (file)
 
 package org.onap.cps.api.impl
 
+import org.onap.cps.api.CpsAnchorService
+
+import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED
+import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED
+
 import org.onap.cps.TestUtils
-import org.onap.cps.api.CpsAdminService
 import org.onap.cps.spi.CpsModulePersistenceService
 import org.onap.cps.spi.exceptions.DuplicatedYangResourceException
 import org.onap.cps.spi.exceptions.ModelValidationException
@@ -38,18 +42,16 @@ import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder
 import org.onap.cps.yang.YangTextSchemaSourceSet
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
 import spock.lang.Specification
-import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED
-import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED
 
 class CpsModuleServiceImplSpec extends Specification {
 
     def mockCpsModulePersistenceService = Mock(CpsModulePersistenceService)
-    def mockCpsAdminService = Mock(CpsAdminService)
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
+    def mockCpsAnchorService = Mock(CpsAnchorService)
     def mockCpsValidator = Mock(CpsValidator)
     def timedYangTextSchemaSourceSetBuilder = new TimedYangTextSchemaSourceSetBuilder()
 
-    def objectUnderTest = new CpsModuleServiceImpl(mockCpsModulePersistenceService, mockYangTextSchemaSourceSetCache, mockCpsAdminService, mockCpsValidator,timedYangTextSchemaSourceSetBuilder)
+    def objectUnderTest = new CpsModuleServiceImpl(mockCpsModulePersistenceService, mockYangTextSchemaSourceSetCache, mockCpsAnchorService, mockCpsValidator,timedYangTextSchemaSourceSetBuilder)
 
     def 'Create schema set.'() {
         when: 'Create schema set method is invoked'
@@ -65,7 +67,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.createOrUpgradeSchemaSetFromModules('someDataspaceName', 'someSchemaSetName', [newModule: 'newContent'], listOfExistingModulesModuleReference)
+            objectUnderTest.createSchemaSetFromModules('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'
@@ -132,11 +134,11 @@ class CpsModuleServiceImplSpec extends Specification {
     def 'Delete schema-set when cascade is allowed.'() {
         given: '#numberOfAnchors anchors are associated with schemaset'
             def associatedAnchors = createAnchors(numberOfAnchors)
-            mockCpsAdminService.getAnchors('my-dataspace', 'my-schemaset') >> associatedAnchors
+            mockCpsAnchorService.getAnchors('my-dataspace', 'my-schemaset') >> associatedAnchors
         when: 'schema set deletion is requested with cascade allowed'
             objectUnderTest.deleteSchemaSet('my-dataspace', 'my-schemaset', CASCADE_DELETE_ALLOWED)
         then: 'anchor deletion is called #numberOfAnchors times'
-            numberOfAnchors * mockCpsAdminService.deleteAnchor('my-dataspace', _)
+            numberOfAnchors * mockCpsAnchorService.deleteAnchor('my-dataspace', _)
         and: 'persistence service method is invoked with same parameters'
             1 * mockCpsModulePersistenceService.deleteSchemaSet('my-dataspace', 'my-schemaset')
         and: 'schema set will be removed from the cache'
@@ -151,11 +153,11 @@ class CpsModuleServiceImplSpec extends Specification {
 
     def 'Delete schema-set when cascade is prohibited.'() {
         given: 'no anchors are associated with schemaset'
-            mockCpsAdminService.getAnchors('my-dataspace', 'my-schemaset') >> Collections.emptyList()
+            mockCpsAnchorService.getAnchors('my-dataspace', 'my-schemaset') >> Collections.emptyList()
         when: 'schema set deletion is requested with cascade allowed'
             objectUnderTest.deleteSchemaSet('my-dataspace', 'my-schemaset', CASCADE_DELETE_PROHIBITED)
         then: 'no anchors are deleted'
-            0 * mockCpsAdminService.deleteAnchor(_, _)
+            0 * mockCpsAnchorService.deleteAnchor(_, _)
         and: 'persistence service method is invoked with same parameters'
             1 * mockCpsModulePersistenceService.deleteSchemaSet('my-dataspace', 'my-schemaset')
         and: 'schema set will be removed from the cache'
@@ -168,26 +170,20 @@ class CpsModuleServiceImplSpec extends Specification {
 
     def 'Delete schema-set when cascade is prohibited and schema-set has anchors.'() {
         given: '2 anchors are associated with schemaset'
-            mockCpsAdminService.getAnchors('my-dataspace', 'my-schemaset') >> createAnchors(2)
+            mockCpsAnchorService.getAnchors('my-dataspace', 'my-schemaset') >> createAnchors(2)
         when: 'schema set deletion is requested with cascade allowed'
             objectUnderTest.deleteSchemaSet('my-dataspace', 'my-schemaset', CASCADE_DELETE_PROHIBITED)
         then: 'Schema-Set in Use exception is thrown'
             thrown(SchemaSetInUseException)
     }
 
-    def createAnchors(int anchorCount) {
-        def anchors = []
-        (0..<anchorCount).each { anchors.add(new Anchor("my-anchor-$it", 'my-dataspace', 'my-schemaset')) }
-        return anchors
-    }
-
     def 'Delete multiple schema-sets when cascade is allowed.'() {
         given: '#numberOfAnchors anchors are associated with each schemaset'
-            mockCpsAdminService.getAnchors('my-dataspace', ['my-schemaset1', 'my-schemaset2']) >> createAnchors(numberOfAnchors * 2)
+            mockCpsAnchorService.getAnchors('my-dataspace', ['my-schemaset1', 'my-schemaset2']) >> createAnchors(numberOfAnchors * 2)
         when: 'schema set deletion is requested with cascade allowed'
             objectUnderTest.deleteSchemaSetsWithCascade('my-dataspace', ['my-schemaset1', 'my-schemaset2'])
         then: 'anchor deletion is called #numberOfAnchors times'
-            mockCpsAdminService.deleteAnchors('my-dataspace', _)
+            mockCpsAnchorService.deleteAnchors('my-dataspace', _)
         and: 'persistence service method is invoked with same parameters'
             mockCpsModulePersistenceService.deleteSchemaSets('my-dataspace', _)
         and: 'schema sets will be removed from the cache'
@@ -202,9 +198,16 @@ class CpsModuleServiceImplSpec extends Specification {
             numberOfAnchors << [0, 3]
     }
 
+    def 'Upgrade existing schema set'() {
+        when: 'schema set update is requested'
+        objectUnderTest.upgradeSchemaSetFromModules('my-dataspace', 'my-schemaset', [:], moduleReferences)
+        then: 'no exception is thrown '
+        noExceptionThrown()
+    }
+
     def 'Get all yang resources module references.'() {
         given: 'an already present module reference'
-            def moduleReferences = [new ModuleReference('some module name','some revision name')]
+            def moduleReferences = getModuleReferences()
             mockCpsModulePersistenceService.getYangResourceModuleReferences('someDataspaceName') >> moduleReferences
         when: 'get yang resource module references is called'
             def result = objectUnderTest.getYangResourceModuleReferences('someDataspaceName')
@@ -228,7 +231,7 @@ class CpsModuleServiceImplSpec extends Specification {
 
     def 'Identifying new module references.'(){
         given: 'module references from cm handle'
-            def moduleReferencesToCheck = [new ModuleReference('some-module', 'some-revision')]
+            def moduleReferencesToCheck = getModuleReferences()
         when: 'identifyNewModuleReferences is called'
             objectUnderTest.identifyNewModuleReferences(moduleReferencesToCheck)
         then: 'cps module persistence service is called with module references to check'
@@ -246,4 +249,14 @@ class CpsModuleServiceImplSpec extends Specification {
         and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
             1 * mockCpsValidator.validateNameCharacters('some-dataspace-name', 'some-anchor-name')
     }
+
+    def getModuleReferences() {
+        return [new ModuleReference('some module name','some revision name')]
+    }
+
+    def createAnchors(int anchorCount) {
+        def anchors = []
+        (0..<anchorCount).each { anchors.add(new Anchor("my-anchor-$it", 'my-dataspace', 'my-schemaset')) }
+        return anchors
+    }
 }
index 1b873ec..4782468 100755 (executable)
@@ -24,9 +24,9 @@
 package org.onap.cps.api.impl\r
 \r
 import org.onap.cps.TestUtils\r
-import org.onap.cps.api.CpsAdminService\r
+import org.onap.cps.api.CpsAnchorService\r
 import org.onap.cps.api.CpsDeltaService\r
-import org.onap.cps.notification.NotificationService\r
+import org.onap.cps.spi.CpsDataPersistenceService\r
 import org.onap.cps.spi.CpsDataPersistenceService\r
 import org.onap.cps.spi.CpsModulePersistenceService\r
 import org.onap.cps.spi.model.Anchor\r
@@ -40,8 +40,7 @@ import spock.lang.Specification
 class E2ENetworkSliceSpec extends Specification {\r
     def mockModuleStoreService = Mock(CpsModulePersistenceService)\r
     def mockDataStoreService = Mock(CpsDataPersistenceService)\r
-    def mockCpsAdminService = Mock(CpsAdminService)\r
-    def mockNotificationService = Mock(NotificationService)\r
+    def mockCpsAnchorService = Mock(CpsAnchorService)\r
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)\r
     def mockCpsValidator = Mock(CpsValidator)\r
     def timedYangTextSchemaSourceSetBuilder = new TimedYangTextSchemaSourceSetBuilder()\r
@@ -49,10 +48,10 @@ class E2ENetworkSliceSpec extends Specification {
     def mockCpsDeltaService = Mock(CpsDeltaService)\r
 \r
     def cpsModuleServiceImpl = new CpsModuleServiceImpl(mockModuleStoreService,\r
-            mockYangTextSchemaSourceSetCache, mockCpsAdminService, mockCpsValidator,timedYangTextSchemaSourceSetBuilder)\r
+            mockYangTextSchemaSourceSetCache, mockCpsAnchorService, mockCpsValidator,timedYangTextSchemaSourceSetBuilder)\r
 \r
-    def cpsDataServiceImpl = new CpsDataServiceImpl(mockDataStoreService, mockCpsAdminService,\r
-            mockYangTextSchemaSourceSetCache, mockNotificationService, mockCpsValidator, timedYangParser, mockCpsDeltaService)\r
+    def cpsDataServiceImpl = new CpsDataServiceImpl(mockDataStoreService, mockCpsAnchorService,\r
+            mockYangTextSchemaSourceSetCache, mockCpsValidator, timedYangParser, mockCpsDeltaService)\r
 \r
     def dataspaceName = 'someDataspace'\r
     def anchorName = 'someAnchor'\r
@@ -91,7 +90,7 @@ class E2ENetworkSliceSpec extends Specification {
         and : 'a valid json is provided for the model'\r
             def jsonData = TestUtils.getResourceFileContent('e2e/basic/cps-Cavsta-Data.txt')\r
         and : 'all the further dependencies are mocked '\r
-            mockCpsAdminService.getAnchor(dataspaceName, anchorName) >>\r
+            mockCpsAnchorService.getAnchor(dataspaceName, anchorName) >>\r
                     new Anchor().builder().name(anchorName).schemaSetName(schemaSetName).dataspaceName(dataspaceName).build()\r
             mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >>\r
                     YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)\r
@@ -124,7 +123,7 @@ class E2ENetworkSliceSpec extends Specification {
         and : 'a valid json is provided for the model'\r
             def jsonData = TestUtils.getResourceFileContent('e2e/basic/cps-ran-inventory-data.json')\r
         and : 'all the further dependencies are mocked '\r
-            mockCpsAdminService.getAnchor('someDataspace', 'someAnchor') >>\r
+            mockCpsAnchorService.getAnchor('someDataspace', 'someAnchor') >>\r
                     new Anchor().builder().name('someAnchor').schemaSetName('someSchemaSet').dataspaceName(dataspaceName).build()\r
             mockYangTextSchemaSourceSetCache.get('someDataspace', 'someSchemaSet') >> YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)\r
             mockModuleStoreService.getYangSchemaResources('someDataspace', 'someSchemaSet') >> schemaContext\r
diff --git a/cps-service/src/test/groovy/org/onap/cps/config/AsyncConfigSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/config/AsyncConfigSpec.groovy
new file mode 100644 (file)
index 0000000..9f4e81a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  ============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.config
+
+import spock.lang.Specification
+
+class AsyncConfigSpec extends Specification {
+
+    def objectUnderTest = new AsyncConfig()
+
+    def 'Create Async Config and validate it'() {
+        when: 'we set some test properties to tune taskexecutor'
+            objectUnderTest.setCorePoolSize(5)
+            objectUnderTest.setMaxPoolSize(50)
+            objectUnderTest.setQueueCapacity(100)
+            objectUnderTest.setThreadNamePrefix('Test-')
+            objectUnderTest.setWaitForTasksToCompleteOnShutdown(true)
+        then: 'we can instantiate a Async Config object'
+            assert objectUnderTest != null
+        and: 'taskexector is configured with correct properties'
+            def tasExecutor = objectUnderTest.getThreadAsyncExecutorForNotification()
+            assert tasExecutor.properties['corePoolSize'] == 5
+            assert tasExecutor.properties['maxPoolSize'] == 50
+            assert tasExecutor.properties['queueCapacity'] == 100
+            assert tasExecutor.properties['keepAliveSeconds'] == 60
+            assert tasExecutor.properties['threadNamePrefix'] == 'Test-'
+    }
+}
diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdatedEventFactorySpec.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdatedEventFactorySpec.groovy
deleted file mode 100644 (file)
index 49f4bf3..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- *  ============LICENSE_START=======================================================
- *  Copyright (c) 2021-2022 Bell Canada.
- *  Modifications Copyright (c) 2022-2023 Nordix Foundation
- *  Modifications Copyright (C) 2023 TechMahindra Ltd.
- *  ================================================================================
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  SPDX-License-Identifier: Apache-2.0
- *  ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.notification
-
-import org.onap.cps.spi.model.DataNode
-
-import java.time.OffsetDateTime
-import java.time.format.DateTimeFormatter
-import org.onap.cps.utils.DateTimeUtility
-import org.onap.cps.utils.PrefixResolver
-import org.onap.cps.api.CpsDataService
-import org.onap.cps.event.model.Content
-import org.onap.cps.event.model.Data
-import org.onap.cps.spi.FetchDescendantsOption
-import org.onap.cps.spi.model.Anchor
-import org.onap.cps.spi.model.DataNodeBuilder
-import org.springframework.util.StringUtils
-import spock.lang.Specification
-
-class CpsDataUpdatedEventFactorySpec extends Specification {
-
-    def mockCpsDataService = Mock(CpsDataService)
-
-    def mockPrefixResolver = Mock(PrefixResolver)
-
-    def objectUnderTest = new CpsDataUpdatedEventFactory(mockCpsDataService, mockPrefixResolver)
-
-    def dateTimeFormat = 'yyyy-MM-dd\'T\'HH:mm:ss.SSSZ'
-
-    def 'Create a CPS data updated event successfully: #scenario'() {
-        given: 'an anchor which has been updated'
-            def anchor = new Anchor('my-anchorname', 'my-dataspace', 'my-schemaset-name')
-        and: 'cps data service returns the data node details'
-            def xpath = '/xpath'
-            def dataNode = new DataNodeBuilder().withXpath(xpath).withLeaves(['leafName': 'leafValue']).build()
-            mockCpsDataService.getDataNodes(
-                    'my-dataspace', 'my-anchorname', '/', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [dataNode]
-        when: 'CPS data updated event is created'
-            def cpsDataUpdatedEvent = objectUnderTest.createCpsDataUpdatedEvent(anchor,
-                    DateTimeUtility.toOffsetDateTime(inputObservedTimestamp), Operation.CREATE)
-        then: 'CPS data updated event is created with correct envelope'
-            with(cpsDataUpdatedEvent) {
-                type == 'org.onap.cps.data-updated-event'
-                source == new URI('urn:cps:org.onap.cps')
-                schema == new URI('urn:cps:org.onap.cps:data-updated-event-schema:v1')
-                StringUtils.hasText(id)
-                content != null
-            }
-        and: 'correct content'
-            with(cpsDataUpdatedEvent.content) {
-                assert isExpectedDateTimeFormat(observedTimestamp): "$observedTimestamp is not in $dateTimeFormat format"
-                if (inputObservedTimestamp != null)
-                    assert observedTimestamp == inputObservedTimestamp
-                else
-                    assert OffsetDateTime.now().minusSeconds(20).isBefore(
-                            DateTimeUtility.toOffsetDateTime(observedTimestamp))
-                assert anchorName == 'my-anchorname'
-                assert dataspaceName == 'my-dataspace'
-                assert schemaSetName == 'my-schemaset-name'
-                assert operation == Content.Operation.CREATE
-                assert data == new Data().withAdditionalProperty('xpath', ['leafName': 'leafValue'])
-            }
-        where:
-            scenario                        | inputObservedTimestamp
-            'with observed timestamp -0400' | '2021-01-01T23:00:00.345-0400'
-            'with observed timestamp +0400' | '2021-01-01T23:00:00.345+0400'
-            'missing observed timestamp'    | null
-    }
-
-    def 'Create a delete CPS data updated event successfully'() {
-        given: 'an anchor which has been deleted'
-            def anchor = new Anchor('my-anchorname', 'my-dataspace', 'my-schemaset-name')
-            def deletionTimestamp = '2021-01-01T23:00:00.345-0400'
-        when: 'a delete root data node event is created'
-            def cpsDataUpdatedEvent = objectUnderTest.createCpsDataUpdatedEvent(anchor,
-                    DateTimeUtility.toOffsetDateTime(deletionTimestamp), Operation.DELETE)
-        then: 'CPS data updated event is created with correct envelope'
-            with(cpsDataUpdatedEvent) {
-                type == 'org.onap.cps.data-updated-event'
-                source == new URI('urn:cps:org.onap.cps')
-                schema == new URI('urn:cps:org.onap.cps:data-updated-event-schema:v1')
-                StringUtils.hasText(id)
-                content != null
-            }
-        and: 'correct content'
-            with(cpsDataUpdatedEvent.content) {
-                assert isExpectedDateTimeFormat(observedTimestamp): "$observedTimestamp is not in $dateTimeFormat format"
-                assert observedTimestamp == deletionTimestamp
-                assert anchorName == 'my-anchorname'
-                assert dataspaceName == 'my-dataspace'
-                assert schemaSetName == 'my-schemaset-name'
-                assert operation == Content.Operation.DELETE
-                assert data == null
-            }
-    }
-
-    def 'Create CPS Data Event with URI Syntax Exception'() {
-        given: 'an anchor'
-            def anchor = new Anchor('my-anchorname', 'my-dataspace', 'my-schemaset-name')
-        and: 'a mocked data Node (collection)'
-            def mockDataNode = Mock(DataNode)
-            mockCpsDataService.getDataNodes(*_) >> [ mockDataNode ]
-        and: 'a URI syntax exception is thrown somewhere (using datanode as cannot manipulate hardcoded URIs'
-            def originalException = new URISyntaxException('input', 'reason', 0)
-            mockDataNode.getXpath() >> { throw originalException }
-        when: 'attempt to create data updated event'
-            objectUnderTest.createCpsDataUpdatedEvent(anchor, OffsetDateTime.now(), Operation.UPDATE)
-        then: 'the same exception is thrown up'
-            def thrownUp = thrown(URISyntaxException)
-            assert thrownUp == originalException
-    }
-
-    def isExpectedDateTimeFormat(String observedTimestamp) {
-        try {
-            DateTimeFormatter.ofPattern(dateTimeFormat).parse(observedTimestamp)
-        } catch (DateTimeParseException) {
-            return false
-        }
-        return true
-    }
-
-}
diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/KafkaPublisherSpecBase.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/KafkaPublisherSpecBase.groovy
deleted file mode 100644 (file)
index b60b38f..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Bell Canada. All rights reserved.
- *  ================================================================================
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  SPDX-License-Identifier: Apache-2.0
- *  ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.notification
-
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration
-import org.springframework.boot.test.context.SpringBootTest
-import org.springframework.kafka.config.TopicBuilder
-import org.springframework.kafka.core.ConsumerFactory
-import org.springframework.kafka.core.KafkaAdmin
-import org.springframework.kafka.core.KafkaTemplate
-import org.springframework.kafka.listener.ConcurrentMessageListenerContainer
-import org.springframework.kafka.listener.ContainerProperties
-import org.springframework.kafka.listener.MessageListener
-import org.springframework.kafka.test.utils.ContainerTestUtils
-import org.springframework.test.context.ContextConfiguration
-import org.springframework.test.context.DynamicPropertyRegistry
-import org.springframework.test.context.DynamicPropertySource
-import spock.lang.Shared
-import spock.lang.Specification
-
-@ContextConfiguration(classes = [KafkaAutoConfiguration, KafkaProducerListener, NotificationErrorHandler])
-@SpringBootTest
-class KafkaPublisherSpecBase extends Specification {
-
-    @Autowired
-    KafkaTemplate kafkaTemplate
-
-    @Autowired
-    KafkaAdmin kafkaAdmin
-
-    @Autowired
-    ConsumerFactory consumerFactory
-
-    @Shared volatile topicCreated = false
-    @Shared consumedMessages = new ArrayList<>()
-
-    def cpsEventTopic = 'cps-events'
-
-    @DynamicPropertySource
-    static void registerKafkaProperties(DynamicPropertyRegistry registry) {
-        registry.add("spring.kafka.bootstrap-servers", KafkaTestContainerConfig::getBootstrapServers)
-    }
-
-    def setup() {
-        // Kafka listener and topic should be created only once for a test-suite.
-        // We are also dependent on sprint context to achieve it, and can not execute it in setupSpec
-        if (!topicCreated) {
-            kafkaAdmin.createOrModifyTopics(TopicBuilder.name(cpsEventTopic).partitions(1).replicas(1).build())
-            startListeningToTopic()
-            topicCreated = true
-        }
-        /* kafka message listener stores the messages to consumedMessages.
-            It is important to clear the list before each test case so that test cases can fetch the message from index '0'.
-         */
-        consumedMessages.clear()
-    }
-
-    def startListeningToTopic() {
-        ContainerProperties containerProperties = new ContainerProperties(cpsEventTopic)
-        containerProperties.setMessageListener([
-                onMessage: {
-                    record ->
-                        consumedMessages.add(record.value())
-                }] as MessageListener)
-
-        ConcurrentMessageListenerContainer container =
-                new ConcurrentMessageListenerContainer<>(
-                        consumerFactory,
-                        containerProperties)
-
-        container.start()
-        ContainerTestUtils.waitForAssignment(container, 1)
-    }
-
-}
diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/KafkaTestContainerConfig.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/KafkaTestContainerConfig.groovy
deleted file mode 100644 (file)
index b07b31a..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Bell Canada. All rights reserved.
- *  ================================================================================
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  SPDX-License-Identifier: Apache-2.0
- *  ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.notification
-
-import org.testcontainers.containers.KafkaContainer
-import org.testcontainers.utility.DockerImageName
-
-class KafkaTestContainerConfig {
-
-    private static KafkaContainer kafkaContainer
-
-    static {
-        getKafkaContainer()
-    }
-
-    // Not the best performance but it is good enough for test case
-    private static synchronized KafkaContainer getKafkaContainer() {
-        if (kafkaContainer == null) {
-            kafkaContainer = new KafkaContainer(DockerImageName.parse("registry.nordix.org/onaptest/confluentinc/cp-kafka:6.2.1").asCompatibleSubstituteFor("confluentinc/cp-kafka"))
-                    .withEnv("KAFKA_AUTO_CREATE_TOPICS_ENABLE", "false")
-            kafkaContainer.start()
-            Runtime.getRuntime().addShutdownHook(new Thread(kafkaContainer::stop))
-        }
-        return kafkaContainer
-    }
-
-    static String getBootstrapServers() {
-        getKafkaContainer()
-        return kafkaContainer.getBootstrapServers()
-    }
-
-}
diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationErrorHandlerSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationErrorHandlerSpec.groovy
deleted file mode 100644 (file)
index 89e305a..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  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.
- *  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.notification
-
-import ch.qos.logback.classic.Logger
-import ch.qos.logback.classic.spi.ILoggingEvent
-import ch.qos.logback.core.read.ListAppender
-import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.BeforeEach
-import org.slf4j.LoggerFactory
-
-import spock.lang.Specification
-
-class NotificationErrorHandlerSpec extends Specification{
-
-    NotificationErrorHandler objectUnderTest = new NotificationErrorHandler()
-    def logWatcher = Spy(ListAppender<ILoggingEvent>)
-
-    @BeforeEach
-    void setup() {
-        ((Logger) LoggerFactory.getLogger(NotificationErrorHandler.class)).addAppender(logWatcher);
-        logWatcher.start();
-    }
-
-    @AfterEach
-    void teardown() {
-        ((Logger) LoggerFactory.getLogger(NotificationErrorHandler.class)).detachAndStopAllAppenders();
-    }
-
-    def 'Logging exception via notification error handler #scenario'() {
-        when: 'exception #scenario occurs'
-            objectUnderTest.onException(exception, 'some context')
-        then: 'log output results contains the correct error details'
-            def logMessage = logWatcher.list[0].getFormattedMessage()
-            assert logMessage.contains('Failed to process')
-            assert logMessage.contains("Error cause: ${exptectedCauseString}")
-            assert logMessage.contains("Error context: [some context]")
-        where:
-            scenario        | exception                                               || exptectedCauseString
-            'with cause'    | new Exception('message')                                || 'message'
-            'without cause' | new Exception('message', new RuntimeException('cause')) || 'java.lang.RuntimeException: cause'
-    }
-}
diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationPublisherSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationPublisherSpec.groovy
deleted file mode 100644 (file)
index 6cd9ae1..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Bell Canada. All rights reserved.
- *  Modifications Copyright (C) 2021-2022 Nordix Foundation
- * ================================================================================
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  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.notification
-
-import org.apache.kafka.clients.producer.ProducerRecord
-import org.onap.cps.event.model.Content
-import org.onap.cps.event.model.CpsDataUpdatedEvent
-import org.spockframework.spring.SpringBean
-import org.springframework.kafka.KafkaException
-import org.springframework.kafka.core.KafkaTemplate
-import spock.util.concurrent.PollingConditions
-
-class NotificationPublisherSpec extends KafkaPublisherSpecBase {
-
-    @SpringBean
-    NotificationErrorHandler spyNotificationErrorHandler = Spy(new NotificationErrorHandler())
-
-    @SpringBean
-    KafkaProducerListener spyKafkaProducerListener = Spy(new KafkaProducerListener<>(spyNotificationErrorHandler))
-
-    KafkaTemplate spyKafkaTemplate
-    NotificationPublisher objectUnderTest
-
-    def myAnchorName = 'my-anchor'
-    def myDataspaceName = 'my-dataspace'
-
-    def cpsDataUpdatedEvent = new CpsDataUpdatedEvent()
-            .withContent(new Content()
-                    .withDataspaceName(myDataspaceName)
-                    .withAnchorName(myAnchorName))
-
-    def setup() {
-        spyKafkaTemplate = Spy(kafkaTemplate)
-        objectUnderTest = new NotificationPublisher(spyKafkaTemplate, cpsEventTopic);
-    }
-
-    def 'Sending event to message bus with correct message Key.'() {
-
-        when: 'event is sent to publisher'
-            objectUnderTest.sendNotification(cpsDataUpdatedEvent)
-            kafkaTemplate.flush()
-
-        then: 'event is sent to correct topic with the expected messageKey'
-            interaction {
-                def messageKey = myDataspaceName + "," + myAnchorName
-                1 * spyKafkaTemplate.send(cpsEventTopic, messageKey, cpsDataUpdatedEvent)
-            }
-        and: 'received a successful response'
-            1 * spyKafkaProducerListener.onSuccess(_ as ProducerRecord, _)
-        and: 'kafka consumer returns expected message'
-            def conditions = new PollingConditions(timeout: 60, initialDelay: 0, factor: 1)
-            conditions.eventually {
-                assert cpsDataUpdatedEvent == consumedMessages.get(0)
-            }
-    }
-
-    def 'Handling of async errors from message bus.'() {
-        given: 'topic does not exist'
-            objectUnderTest.topicName = 'non-existing-topic'
-
-        when: 'message to sent to a non-existing topic'
-            objectUnderTest.sendNotification(cpsDataUpdatedEvent)
-            kafkaTemplate.flush()
-
-        then: 'error is thrown'
-            thrown KafkaException
-        and: 'error handler is called with exception details'
-            1 * spyKafkaProducerListener.onError(_ as ProducerRecord, _, _ as Exception)
-            1 * spyNotificationErrorHandler.onException(_ as String, _ as Exception,
-                    _ as ProducerRecord, _)
-    }
-
-}
diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy
deleted file mode 100644 (file)
index f07f89b..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- *  Copyright (c) 2021-2022 Bell Canada.
- *  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.
- *  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.notification
-
-import org.onap.cps.api.CpsAdminService
-import org.onap.cps.config.AsyncConfig
-import org.onap.cps.event.model.CpsDataUpdatedEvent
-import org.onap.cps.spi.model.Anchor
-import org.spockframework.spring.SpringBean
-import org.spockframework.spring.SpringSpy
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.context.properties.EnableConfigurationProperties
-import org.springframework.boot.test.context.SpringBootTest
-import org.springframework.test.context.ContextConfiguration
-import spock.lang.Shared
-import spock.lang.Specification
-
-import java.time.OffsetDateTime
-import java.util.concurrent.TimeUnit
-
-@SpringBootTest
-@EnableConfigurationProperties
-@ContextConfiguration(classes = [NotificationProperties, NotificationService, NotificationErrorHandler, AsyncConfig])
-class NotificationServiceSpec extends Specification {
-
-    @SpringSpy
-    NotificationProperties spyNotificationProperties
-    @SpringBean
-    NotificationPublisher mockNotificationPublisher = Mock()
-    @SpringBean
-    CpsDataUpdatedEventFactory mockCpsDataUpdatedEventFactory = Mock()
-    @SpringSpy
-    NotificationErrorHandler spyNotificationErrorHandler
-    @SpringBean
-    CpsAdminService mockCpsAdminService = Mock()
-
-    @Autowired
-    NotificationService objectUnderTest
-
-    @Shared
-    def dataspaceName = 'my-dataspace-published'
-    @Shared
-    def anchorName = 'my-anchorname'
-    @Shared
-    def anchor = new Anchor('my-anchorname', 'my-dataspace-published', 'my-schemaset-name')
-    def myObservedTimestamp = OffsetDateTime.now()
-
-    def setup() {
-        mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
-    }
-
-    def 'Skip sending notification when disabled.'() {
-        given: 'notification is disabled'
-            spyNotificationProperties.isEnabled() >> false
-        when: 'dataUpdatedEvent is received'
-            objectUnderTest.processDataUpdatedEvent(anchor, '/', Operation.CREATE, myObservedTimestamp)
-        then: 'the notification is not sent'
-            0 * mockNotificationPublisher.sendNotification(_)
-    }
-
-    def 'Send notification when enabled: #scenario.'() {
-        given: 'notification is enabled'
-            spyNotificationProperties.isEnabled() >> true
-        and: 'an anchor is in dataspace where #scenario'
-            def anchor = new Anchor('my-anchorname', dataspaceName, 'my-schemaset-name')
-        and: 'event factory can create event successfully'
-            def cpsDataUpdatedEvent = new CpsDataUpdatedEvent()
-            mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(anchor, myObservedTimestamp, Operation.CREATE) >> cpsDataUpdatedEvent
-        when: 'dataUpdatedEvent is received'
-            def future = objectUnderTest.processDataUpdatedEvent(anchor, '/', Operation.CREATE, myObservedTimestamp)
-        and: 'wait for async processing to complete'
-            future.get(10, TimeUnit.SECONDS)
-        then: 'async process completed successfully'
-            future.isDone()
-        and: 'notification is sent'
-            expectedSendNotificationCount * mockNotificationPublisher.sendNotification(cpsDataUpdatedEvent)
-        where:
-            scenario                               | dataspaceName            || expectedSendNotificationCount
-            'dataspace name does not match filter' | 'does-not-match-pattern' || 0
-            'dataspace name matches filter'        | 'my-dataspace-published' || 1
-    }
-
-    def '#scenario are changed with xpath #xpath and operation #operation'() {
-        given: 'notification is enabled'
-            spyNotificationProperties.isEnabled() >> true
-        and: 'event factory creates event if operation is #operation'
-            def cpsDataUpdatedEvent = new CpsDataUpdatedEvent()
-            mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(anchor, myObservedTimestamp, expectedOperationInEvent) >>
-                    cpsDataUpdatedEvent
-        when: 'dataUpdatedEvent is received for #xpath'
-            def future = objectUnderTest.processDataUpdatedEvent(anchor, xpath, operation, myObservedTimestamp)
-        and: 'wait for async processing to complete'
-            future.get(10, TimeUnit.SECONDS)
-        then: 'async process completed successfully'
-            future.isDone()
-        and: 'notification is sent'
-            1 * mockNotificationPublisher.sendNotification(cpsDataUpdatedEvent)
-        where:
-            scenario                                   | xpath           | operation            || expectedOperationInEvent
-            'Same event is sent when root nodes'       | ''              | Operation.CREATE || Operation.CREATE
-            'Same event is sent when root nodes'       | ''              | Operation.UPDATE || Operation.UPDATE
-            'Same event is sent when root nodes'       | ''              | Operation.DELETE || Operation.DELETE
-            'Same event is sent when root nodes'       | '/'             | Operation.CREATE || Operation.CREATE
-            'Same event is sent when root nodes'       | '/'             | Operation.UPDATE || Operation.UPDATE
-            'Same event is sent when root nodes'       | '/'             | Operation.DELETE || Operation.DELETE
-            'Same event is sent when container nodes'  | '/parent'       | Operation.CREATE || Operation.CREATE
-            'Same event is sent when container nodes'  | '/parent'       | Operation.UPDATE || Operation.UPDATE
-            'Same event is sent when container nodes'  | '/parent'       | Operation.DELETE || Operation.DELETE
-            'UPDATE event is sent when non root nodes' | '/parent/child' | Operation.CREATE || Operation.UPDATE
-            'UPDATE event is sent when non root nodes' | '/parent/child' | Operation.UPDATE || Operation.UPDATE
-            'UPDATE event is sent when non root nodes' | '/parent/child' | Operation.DELETE || Operation.UPDATE
-    }
-
-    def 'Error handling in notification service.'() {
-        given: 'notification is enabled'
-            spyNotificationProperties.isEnabled() >> true
-        and: 'event factory can not create event successfully'
-            mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(anchor, myObservedTimestamp, Operation.CREATE) >>
-                    { throw new Exception("Could not create event") }
-        when: 'event is sent for processing'
-            def future = objectUnderTest.processDataUpdatedEvent(anchor, '/', Operation.CREATE, myObservedTimestamp)
-        and: 'wait for async processing to complete'
-            future.get(10, TimeUnit.SECONDS)
-        then: 'async process completed successfully'
-            future.isDone()
-        and: 'error is handled and not thrown to caller'
-            notThrown Exception
-            1 * spyNotificationErrorHandler.onException(_, _, _, '/', Operation.CREATE)
-    }
-
-    def 'Disabled Notification services'() {
-        given: 'a notification service that is disabled'
-            spyNotificationProperties.enabled >> false
-            NotificationService notificationService = new NotificationService(spyNotificationProperties, mockNotificationPublisher, mockCpsDataUpdatedEventFactory, spyNotificationErrorHandler, mockCpsAdminService)
-            notificationService.init()
-        expect: 'it will not send notifications'
-            assert notificationService.shouldSendNotification('') == false
-    }
-}
index ff6ab34..b975de6 100644 (file)
@@ -24,7 +24,7 @@ package org.onap.cps.utils
 
 import com.hazelcast.map.IMap
 import org.onap.cps.TestUtils
-import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsAnchorService
 import org.onap.cps.api.impl.YangTextSchemaSourceSetCache
 import org.onap.cps.cache.AnchorDataCacheEntry
 import org.onap.cps.spi.model.Anchor
@@ -34,13 +34,13 @@ import spock.lang.Specification
 
 class PrefixResolverSpec extends Specification {
 
-    def mockCpsAdminService = Mock(CpsAdminService)
+    def mockCpsAnchorService = Mock(CpsAnchorService)
 
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
 
     def mockAnchorDataCache = Mock(IMap<String, AnchorDataCacheEntry>)
 
-    def objectUnderTest = new PrefixResolver(mockCpsAdminService, mockYangTextSchemaSourceSetCache, mockAnchorDataCache)
+    def objectUnderTest = new PrefixResolver(mockCpsAnchorService, mockYangTextSchemaSourceSetCache, mockAnchorDataCache)
 
     def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
 
@@ -52,7 +52,7 @@ class PrefixResolverSpec extends Specification {
         given: 'an anchor for the test-tree model'
             def anchor = new Anchor(dataspaceName: 'testDataspace', name: 'testAnchor')
         and: 'the system can get this anchor'
-            mockCpsAdminService.getAnchor('testDataspace', 'testAnchor') >> anchor
+            mockCpsAnchorService.getAnchor('testDataspace', 'testAnchor') >> anchor
         and: 'the schema source cache contains the schema context for the test-tree module'
             mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
     }
diff --git a/csit/plans/cps/sdnc/check_sdnc_mount_node.sh b/csit/plans/cps/sdnc/check_sdnc_mount_node.sh
new file mode 100644 (file)
index 0000000..9ea6670
--- /dev/null
@@ -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.
+# ============LICENSE_END=========================================================
+
+# WAIT 10 minutes maximum and test every 30 seconds if SDNC is up using HealthCheck API
+TIME_OUT=600
+INTERVAL=30
+TIME=0
+while [ "$TIME" -lt "$TIME_OUT" ]; do
+  response=$(curl --write-out '%{http_code}' --silent --output /dev/null -H "Authorization: Basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==" -X POST -H "X-FromAppId: csit-sdnc" -H "X-TransactionId: csit-sdnc" -H "Accept: application/json" -H "Content-Type: application/json" http://$SDNC_HOST:$SDNC_PORT/restconf/operations/SLI-API:healthcheck );
+  echo $response
+
+  if [ "$response" == "200" ]; then
+    echo SDNC started in $TIME seconds
+    break;
+  fi
+
+  echo Sleep: $INTERVAL seconds before testing if SDNC is up. Total wait time up now is: $TIME seconds. Timeout is: $TIME_OUT seconds
+  sleep $INTERVAL
+  TIME=$(($TIME+$INTERVAL))
+done
+
+if [ "$TIME" -ge "$TIME_OUT" ]; then
+   echo TIME OUT: karaf session not started in $TIME_OUT seconds... Could cause problems for testing activities...
+fi
+
+###################### mount pnf-sim as PNFDemo ##########################
+SDNC_TIME_OUT=250
+SDNC_INTERVAL=10
+SDNC_TIME=0
+
+while [ "$SDNC_TIME" -le "$SDNC_TIME_OUT" ]; do
+
+  # Mount netconf node
+  curl --location --request PUT 'http://'$SDNC_HOST:$SDNC_PORT'/restconf/config/network-topology:network-topology/topology/topology-netconf/node/PNFDemo' \
+  --header 'Authorization: Basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==' \
+  --header 'Content-Type: application/json' \
+  --data-raw '{
+    "node": [
+    {
+      "node-id": "PNFDemo",
+      "netconf-node-topology:protocol": {
+      "name": "TLS"
+      },
+      "netconf-node-topology:host": "'$LOCAL_IP'",
+      "netconf-node-topology:key-based": {
+      "username": "netconf",
+      "key-id": "ODL_private_key_0"
+      },
+      "netconf-node-topology:port": 6512,
+      "netconf-node-topology:tcp-only": false,
+      "netconf-node-topology:max-connection-attempts": 5
+    }
+    ]
+  }'
+
+   # Verify node has been mounted
+
+  RESPONSE=$( curl --location --request GET 'http://'$SDNC_HOST:$SDNC_PORT'/restconf/config/network-topology:network-topology/topology/topology-netconf' --header 'Authorization: basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==')
+
+  if [[ "$RESPONSE" == *"PNFDemo"* ]]; then
+    echo "Node mounted in $SDNC_TIME"
+    sleep 10
+    break;
+  fi
+
+  sleep $SDNC_INTERVAL
+  SDNC_TIME=$((SDNC_TIME + SDNC_INTERVAL))
+
+done
\ No newline at end of file
index 9c17b83..61c61fc 100644 (file)
 export SDNC_CERT_PATH=$WORKSPACE/plans/cps/sdnc/certs
 
 #start SDNC containers with docker compose and configuration from docker-compose.yml
-docker-compose -f $WORKSPACE/plans/cps/sdnc/docker-compose.yml up -d
-
-# WAIT 10 minutes maximum and test every 30 seconds if SDNC is up using HealthCheck API
-TIME_OUT=600
-INTERVAL=30
-TIME=0
-while [ "$TIME" -lt "$TIME_OUT" ]; do
-  response=$(curl --write-out '%{http_code}' --silent --output /dev/null -H "Authorization: Basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==" -X POST -H "X-FromAppId: csit-sdnc" -H "X-TransactionId: csit-sdnc" -H "Accept: application/json" -H "Content-Type: application/json" http://$SDNC_HOST:$SDNC_PORT/restconf/operations/SLI-API:healthcheck );
-  echo $response
-
-  if [ "$response" == "200" ]; then
-    echo SDNC started in $TIME seconds
-    break;
-  fi
-
-  echo Sleep: $INTERVAL seconds before testing if SDNC is up. Total wait time up now is: $TIME seconds. Timeout is: $TIME_OUT seconds
-  sleep $INTERVAL
-  TIME=$(($TIME+$INTERVAL))
-done
-
-if [ "$TIME" -ge "$TIME_OUT" ]; then
-   echo TIME OUT: karaf session not started in $TIME_OUT seconds... Could cause problems for testing activities...
-fi
\ No newline at end of file
+docker-compose -f $WORKSPACE/plans/cps/sdnc/docker-compose.yml up -d
\ No newline at end of file
index c4e5c15..80829eb 100755 (executable)
@@ -72,53 +72,6 @@ source $WORKSPACE/plans/cps/sdnc/sdnc_setup.sh
 ###################### setup pnfsim #####################################
 docker-compose -f $WORKSPACE/plans/cps/pnfsim/docker-compose.yml up -d
 
-# Allow time for netconf-pnp-simulator & SDNC to come up fully
-sleep 30s
-
-###################### mount pnf-sim as PNFDemo ##########################
-SDNC_TIME_OUT=250
-SDNC_INTERVAL=10
-SDNC_TIME=0
-
-while [ "$SDNC_TIME" -le "$SDNC_TIME_OUT" ]; do
-
-  # Mount netconf node
-  curl --location --request PUT 'http://'$SDNC_HOST:$SDNC_PORT'/restconf/config/network-topology:network-topology/topology/topology-netconf/node/PNFDemo' \
-  --header 'Authorization: Basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==' \
-  --header 'Content-Type: application/json' \
-  --data-raw '{
-    "node": [
-    {
-      "node-id": "PNFDemo",
-      "netconf-node-topology:protocol": {
-      "name": "TLS"
-      },
-      "netconf-node-topology:host": "'$LOCAL_IP'",
-      "netconf-node-topology:key-based": {
-      "username": "netconf",
-      "key-id": "ODL_private_key_0"
-      },
-      "netconf-node-topology:port": 6512,
-      "netconf-node-topology:tcp-only": false,
-      "netconf-node-topology:max-connection-attempts": 5
-    }
-    ]
-  }'
-
-   # Verify node has been mounted
-
-  RESPONSE=$( curl --location --request GET 'http://'$SDNC_HOST:$SDNC_PORT'/restconf/config/network-topology:network-topology/topology/topology-netconf' --header 'Authorization: basic YWRtaW46S3A4Yko0U1hzek0wV1hsaGFrM2VIbGNzZTJnQXc4NHZhb0dHbUp2VXkyVQ==')
-
-  if [[ "$RESPONSE" == *"PNFDemo"* ]]; then
-    echo "Node mounted in $SDNC_TIME"
-    break;
-  fi
-
-  sleep $SDNC_INTERVAL
-  SDNC_TIME=$((SDNC_TIME + SDNC_INTERVAL))
-
-done
-
 ###################### verify ncmp-cps health ##########################
 
 check_health $CPS_CORE_HOST:$CPS_CORE_PORT 'cps-ncmp'
diff --git a/csit/plans/cps/testplanCps.txt b/csit/plans/cps/testplanCps.txt
new file mode 100644 (file)
index 0000000..8b0ad08
--- /dev/null
@@ -0,0 +1,21 @@
+# ============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.
+# ============LICENSE_END=========================================================
+
+# Test suites are relative paths under csit/tests/.
+# Place the suites in run order.
+actuator
+cps-admin
+cps-data
\ No newline at end of file
similarity index 91%
rename from csit/plans/cps/testplan.txt
rename to csit/plans/cps/testplanNcmp.txt
index 45e8381..81c5468 100644 (file)
@@ -1,5 +1,5 @@
 # ============LICENSE_START=======================================================
-# Copyright (C) 2021-2023 Nordix Foundation
+# 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.
@@ -16,9 +16,6 @@
 
 # Test suites are relative paths under csit/tests/.
 # Place the suites in run order.
-actuator
-cps-admin
-cps-data
 cps-model-sync
 cps-data-sync
 cps-subscriptions
index 9a344c1..6f5142c 100755 (executable)
@@ -43,6 +43,32 @@ fi
 # functions
 #
 
+# relax set options so the sourced file will not fail
+# the responsibility is shifted to the sourced file...
+function relax_set() {
+    set +e
+    set +o pipefail
+}
+
+# load the saved set options
+function load_set() {
+    _setopts="$-"
+
+    # bash shellopts
+    for i in $(echo "$SHELLOPTS" | tr ':' ' ') ; do
+        set +o ${i}
+    done
+    for i in $(echo "$RUN_CSIT_SHELLOPTS" | tr ':' ' ') ; do
+        set -o ${i}
+    done
+
+    # other options
+    for i in $(echo "$_setopts" | sed 's/./& /g') ; do
+        set +${i}
+    done
+    set -${RUN_CSIT_SAVE_SET}
+}
+
 # wrapper for sourcing a file
 function source_safely() {
     [ -z "$1" ] && return 1
@@ -104,36 +130,26 @@ function save_set() {
     RUN_CSIT_SHELLOPTS="$SHELLOPTS"
 }
 
-# load the saved set options
-function load_set() {
-    _setopts="$-"
-
-    # bash shellopts
-    for i in $(echo "$SHELLOPTS" | tr ':' ' ') ; do
-        set +o ${i}
-    done
-    for i in $(echo "$RUN_CSIT_SHELLOPTS" | tr ':' ' ') ; do
-        set -o ${i}
-    done
-
-    # other options
-    for i in $(echo "$_setopts" | sed 's/./& /g') ; do
-        set +${i}
-    done
-    set -${RUN_CSIT_SAVE_SET}
-}
-
 # set options for quick bailout when error
 function harden_set() {
     set -xeo pipefail
     set +u # enabled it would probably fail too many often
 }
 
-# relax set options so the sourced file will not fail
-# the responsibility is shifted to the sourced file...
-function relax_set() {
-    set +e
-    set +o pipefail
+function run_test_plan() {
+    testplan=$1
+
+    cd "$WORKDIR"
+    echo "Reading the testplan:"
+    cat "${TESTPLANDIR}/${testplan}.txt" | egrep -v '(^[[:space:]]*#|^[[:space:]]*$)' | sed "s|^|${WORKSPACE}/tests/|" > ${testplan}.txt
+    cat ${testplan}.txt
+    SUITES=$( xargs -a ${testplan}.txt )
+
+    python3 -m robot.run -N ${TESTPLAN} -v WORKSPACE:/tmp ${ROBOT_VARIABLES} ${TESTOPTIONS} ${SUITES}
+    RESULT=$?
+    load_set
+    echo "RESULT: $RESULT"
+    return $RESULT
 }
 
 #
@@ -158,10 +174,10 @@ if [ -z "$WORKSPACE" ]; then
     export WORKSPACE=$(git rev-parse --show-toplevel)
 fi
 
-if [ -f "${WORKSPACE}/${1}/testplan.txt" ]; then
+if [ -f "${WORKSPACE}/${1}/testplanCps.txt" ]; then
     export TESTPLAN="${1}"
 else
-    echo "testplan not found: ${WORKSPACE}/${TESTPLAN}/testplan.txt"
+    echo "testplan not found: ${WORKSPACE}/${TESTPLAN}/testplanCps.txt or testplanNcmp.txt"
     exit 2
 fi
 
@@ -198,12 +214,6 @@ fi
 docker_stats | tee "$WORKSPACE/archives/$TESTPLAN/_sysinfo-1-after-setup.txt"
 
 # Run test plan
-cd "$WORKDIR"
-echo "Reading the testplan:"
-cat "${TESTPLANDIR}/testplan.txt" | egrep -v '(^[[:space:]]*#|^[[:space:]]*$)' | sed "s|^|${WORKSPACE}/tests/|" > testplan.txt
-cat testplan.txt
-SUITES=$( xargs -a testplan.txt )
-
 echo ROBOT_VARIABLES="${ROBOT_VARIABLES}"
 echo "Starting Robot test suites ${SUITES} ..."
 relax_set
@@ -213,9 +223,18 @@ python3 --version
 pip freeze
 python3 -m robot.run --version || :
 
-python3 -m robot.run -N ${TESTPLAN} -v WORKSPACE:/tmp ${ROBOT_VARIABLES} ${TESTOPTIONS} ${SUITES}
-RESULT=$?
-load_set
-echo "RESULT: $RESULT"
+run_test_plan "testplanCps"
+CPSRESULT="$?"
+
+cd "${TESTPLANDIR}"
+checkandmount="${TESTPLANDIR}/sdnc/check_sdnc_mount_node.sh"
+if [ -f "${checkandmount}" ]; then
+    echo "Running check_sdnc_mount_node script ${checkandmount}"
+    source_safely "${checkandmount}"
+fi
+
+run_test_plan "testplanNcmp"
+NCMPRESULT="$?"
+
 # Note that the final steps are done in on_exit function after this exit!
-exit $RESULT
+exit $CPSRESULT || $NCMPRESULT
index 2385d22..48af1cf 100644 (file)
@@ -74,7 +74,7 @@ Verify create to bookstore using passthrough-running
         END
     END
 
-Update Bookstore using passthrough-running for Category 01
+Update Bookstore using passthrough-running update Category 01 (replace category)
     ${uri}=              Set Variable       ${ncmpBasePath}/v1/ch/PNFDemo/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=stores:bookstore/categories=01
     ${headers}=          Create Dictionary  Content-Type=application/json   Authorization=${auth}
     ${jsonData}=         Get Binary File    ${DATADIR_NCMP}${/}bookstoreUpdateExample.json
index c298651..0818ccc 100644 (file)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>dmi-plugin-demo-and-csit-stub</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
     </parent>
 
     <artifactId>dmi-plugin-demo-and-csit-stub-app</artifactId>
index e37df42..e2d326c 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>dmi-plugin-demo-and-csit-stub</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
     </parent>
     <artifactId>dmi-plugin-demo-and-csit-stub-service</artifactId>
 
index 3f9731d..5c72429 100644 (file)
@@ -84,6 +84,7 @@ public class DmiRestStubController {
         final String moduleResponseContent = ResourceFileReaderUtil
                 .getResourceFileContent(applicationContext.getResource(
                         ResourceLoader.CLASSPATH_URL_PREFIX + "module/moduleResponse.json"));
+        log.info("cm handle: {} requested for modules", cmHandle);
         return ResponseEntity.ok(moduleResponseContent);
     }
 
@@ -102,6 +103,7 @@ public class DmiRestStubController {
         final String moduleResourcesResponseContent = ResourceFileReaderUtil
                 .getResourceFileContent(applicationContext.getResource(
                         ResourceLoader.CLASSPATH_URL_PREFIX + "module/moduleResourcesResponse.json"));
+        log.info("cm handle: {} requested for module resources", cmHandle);
         return ResponseEntity.ok(moduleResourcesResponseContent);
     }
 
index 69eb9da..571c2ef 100644 (file)
@@ -7,47 +7,47 @@
        {
                "moduleName": "ietf-yang-types-2",
                "revision": "2013-07-16",
-               "yangSource": "module ietf-yang-types-2 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-2\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-2 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-2\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-16 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-3",
                "revision": "2013-07-17",
-               "yangSource": "module ietf-yang-types-3 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-3\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-3 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-3\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-17 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-4",
                "revision": "2013-07-18",
-               "yangSource": "module ietf-yang-types-4 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-4\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-4 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-4\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-18 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-5",
                "revision": "2013-07-19",
-               "yangSource": "module ietf-yang-types-5 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-5\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-5 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-5\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-19 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-6",
                "revision": "2013-07-20",
-               "yangSource": "module ietf-yang-types-6 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-6\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-6 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-6\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-20 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-7",
                "revision": "2013-07-21",
-               "yangSource": "module ietf-yang-types-7 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-7\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-7 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-7\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-21 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-8",
                "revision": "2013-07-22",
-               "yangSource": "module ietf-yang-types-8 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-8\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-8 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-8\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-22 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-9",
                "revision": "2013-07-23",
-               "yangSource": "module ietf-yang-types-9 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-9\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-9 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-9\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-23 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        },
        {
                "moduleName": "ietf-yang-types-10",
                "revision": "2013-07-24",
-               "yangSource": "module ietf-yang-types-10 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-10\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-15 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
+               "yangSource": "module ietf-yang-types-10 {\n\n  namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-10\";\n  prefix \"yang\";\n\n  organization\n   \"IETF NETMOD (NETCONF Data Modeling Language) Working Group\";\n\n  contact\n   \"WG Web:   <http://tools.ietf.org/wg/netmod/>\n    WG List:  <mailto:netmod@ietf.org>\n\n    WG Chair: David Kessens\n              <mailto:david.kessens@nsn.com>\n\n    WG Chair: Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\n\n    Editor:   Juergen Schoenwaelder\n              <mailto:j.schoenwaelder@jacobs-university.de>\";\n\n  description\n   \"This module contains a collection of generally useful derived\n    YANG data types.\n\n    Copyright (c) 2013 IETF Trust and the persons identified as\n    authors of the code.  All rights reserved.\n\n    Redistribution and use in source and binary forms, with or\n    without modification, is permitted pursuant to, and subject\n    to the license terms contained in, the Simplified BSD License\n    set forth in Section 4.c of the IETF Trust's Legal Provisions\n    Relating to IETF Documents\n    (http://trustee.ietf.org/license-info).\n\n    This version of this YANG module is part of RFC 6991; see\n    the RFC itself for full legal notices.\";\n\n  revision 2013-07-24 {\n    description\n     \"This revision adds the following new data types:\n      - yang-identifier\n      - hex-string\n      - uuid\n      - dotted-quad\";\n    reference\n     \"RFC 6991: Common YANG Data Types\";\n  }\n\n  revision 2010-09-24 {\n    description\n     \"Initial revision.\";\n    reference\n     \"RFC 6021: Common YANG Data Types\";\n  }\n\n  /*** collection of counter and gauge types ***/\n\n  typedef counter32 {\n    type uint32;\n    description\n     \"The counter32 type represents a non-negative integer\n      that monotonically increases until it reaches a\n      maximum value of 2^32-1 (4294967295 decimal), when it\n      wraps around and starts increasing again from zero.\n\n      Counters have no defined 'initial' value, and thus, a\n      single value of a counter has (in general) no information\n      content.  Discontinuities in the monotonically increasing\n      value normally occur at re-initialization of the\n      management system, and at other times as specified in the\n      description of a schema node using this type.  If such\n      other times can occur, for example, the creation of\n      a schema node of type counter32 at times other than\n      re-initialization, then a corresponding schema node\n      should be defined, with an appropriate type, to indicate\n      the last discontinuity.\n\n      The counter32 type should not be used for configuration\n      schema nodes.  A default statement SHOULD NOT be used in\n      combination with the type counter32.\n\n      In the value set and its semantics, this type is equivalent\n      to the Counter32 type of the SMIv2.\";\n    reference\n     \"RFC 2578: Structure of Management Information Version 2\n                (SMIv2)\";\n  }\n}\n"
        }
 ]
 
index cfba461..fd2f317 100644 (file)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index 8cc6e57..de1fbe2 100644 (file)
@@ -57,9 +57,7 @@ It starts both Postgres database and CPS services.
    2. To send data-updated events to kafka,
       * uncomment the `zookeeper` and `kafka` services.
       * uncomment environment variables
-        * `notification.data-updated.enabled: 'true'`
         * `KAFKA_BOOTSTRAP_SERVER: kafka:9092`
-        * `NOTIFICATION_DATASPACE_FILTER_PATTERNS: '.*'`
 2. Execute following command from `docker-compose` folder:
 
 Use one of the below version type that has been generated in the local system's docker image list after the build.
index acfe984..80f8782 100644 (file)
@@ -101,8 +101,6 @@ services:
       DMI_USERNAME: ${DMI_USERNAME:-cpsuser}
       DMI_PASSWORD: ${DMI_PASSWORD:-cpsr0cks!}
       KAFKA_BOOTSTRAP_SERVER: kafka:29092
-      notification.data-updated.enabled: 'true'
-      NOTIFICATION_DATASPACE_FILTER_PATTERNS: '.*'
     restart: unless-stopped
     profiles:
       - dmi-service
index 30ca1fd..bade85e 100644 (file)
@@ -2136,6 +2136,109 @@ paths:
       summary: Replace list content
       tags:
       - cps-data
+  /v2/dataspaces/{dataspace-name}/anchors/{anchor-name}/delta:
+    get:
+      description: Get delta between two anchors within a given dataspace
+      operationId: getDeltaByDataspaceAndAnchors
+      parameters:
+      - description: dataspace-name
+        in: path
+        name: dataspace-name
+        required: true
+        schema:
+          example: my-dataspace
+          type: string
+      - description: anchor-name
+        in: path
+        name: anchor-name
+        required: true
+        schema:
+          example: my-anchor
+          type: string
+      - description: target-anchor-name
+        in: query
+        name: target-anchor-name
+        required: true
+        schema:
+          example: my-anchor
+          type: string
+      - description: "For more details on xpath, please refer https://docs.onap.org/projects/onap-cps/en/latest/xpath.html"
+        examples:
+          container xpath:
+            value: /shops/bookstore
+          list attributes xpath:
+            value: "/shops/bookstore/categories[@code=1]"
+        in: query
+        name: xpath
+        required: false
+        schema:
+          default: /
+          type: string
+      - description: "Number of descendants to query. Allowed values are 'none', 'all',\
+          \ 'direct', 1 (for direct), -1 (for all), 0 (for none) and any positive\
+          \ number."
+        in: query
+        name: descendants
+        required: false
+        schema:
+          default: none
+          example: "3"
+          type: string
+      responses:
+        "200":
+          content:
+            application/json:
+              examples:
+                dataSample:
+                  $ref: '#/components/examples/deltaReportSample'
+                  value: null
+              schema:
+                type: object
+          description: OK
+        "400":
+          content:
+            application/json:
+              example:
+                status: 400
+                message: Bad Request
+                details: The provided request is not valid
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+          description: Bad Request
+        "401":
+          content:
+            application/json:
+              example:
+                status: 401
+                message: Unauthorized request
+                details: This request is unauthorized
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+          description: Unauthorized
+        "403":
+          content:
+            application/json:
+              example:
+                status: 403
+                message: Request Forbidden
+                details: This request is forbidden
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+          description: Forbidden
+        "500":
+          content:
+            application/json:
+              example:
+                status: 500
+                message: Internal Server Error
+                details: Internal Server Error occurred
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+          description: Internal Server Error
+      summary: Get delta between anchors in the same dataspace
+      tags:
+      - cps-data
+      x-codegen-request-body-name: xpath
   /v1/dataspaces/{dataspace-name}/anchors/{anchor-name}/nodes/query:
     get:
       deprecated: true
@@ -2448,6 +2551,24 @@ components:
       value: <stores xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> <bookstore xmlns="org:onap:ccsdk:sample">
         <bookstore-name>Chapters</bookstore-name> <categories> <code>1</code> <name>SciFi</name>
         </categories> </bookstore> </stores>
+    deltaReportSample:
+      value:
+      - action: ADD
+        xpath: "/bookstore/categories/[@code=3]"
+        target-data:
+          code: "3,"
+          name: kidz
+      - action: REMOVE
+        xpath: "/bookstore/categories/[@code=1]"
+        source-data:
+          code: "1,"
+          name: Fiction
+      - action: UPDATE
+        xpath: "/bookstore/categories/[@code=2]"
+        source-data:
+          name: Funny
+        target-data:
+          name: Comic
     dataSampleAcrossAnchors:
       value:
       - anchorName: bookstore1
@@ -2588,6 +2709,14 @@ components:
       required: true
       schema:
         type: string
+    targetAnchorNameInQuery:
+      description: target-anchor-name
+      in: query
+      name: target-anchor-name
+      required: true
+      schema:
+        example: my-anchor
+        type: string
     cpsPathInQuery:
       description: "For more details on cps path, please refer https://docs.onap.org/projects/onap-cps/en/latest/cps-path.html"
       examples:
index 9f64f58..53f51f3 100644 (file)
@@ -261,6 +261,7 @@ components:
       example:
         updatedCmHandles:
         - cmHandle: my-cm-handle
+          alternateId: my-alternate-id
           publicCmHandleProperties:
             key: my-property
           cmHandleProperties:
@@ -268,6 +269,7 @@ components:
           moduleSetTag: my-module-set-tag
           trustLevel: COMPLETE
         - cmHandle: my-cm-handle
+          alternateId: my-alternate-id
           publicCmHandleProperties:
             key: my-property
           cmHandleProperties:
@@ -276,6 +278,7 @@ components:
           trustLevel: COMPLETE
         createdCmHandles:
         - cmHandle: my-cm-handle
+          alternateId: my-alternate-id
           publicCmHandleProperties:
             key: my-property
           cmHandleProperties:
@@ -283,6 +286,7 @@ components:
           moduleSetTag: my-module-set-tag
           trustLevel: COMPLETE
         - cmHandle: my-cm-handle
+          alternateId: my-alternate-id
           publicCmHandleProperties:
             key: my-property
           cmHandleProperties:
@@ -337,6 +341,7 @@ components:
     RestInputCmHandle:
       example:
         cmHandle: my-cm-handle
+        alternateId: my-alternate-id
         publicCmHandleProperties:
           key: my-property
         cmHandleProperties:
@@ -366,6 +371,9 @@ components:
           - NONE
           example: COMPLETE
           type: string
+        alternateId:
+          example: my-alternate-id
+          type: string
       required:
       - cmHandle
       type: object
@@ -391,6 +399,7 @@ components:
             type: string
           type: array
         moduleSetTag:
+          default: ""
           example: my-module-set-tag
           type: string
       required:
index 810210f..8098fae 100644 (file)
@@ -1974,6 +1974,7 @@ components:
             reason: LOCKED_MISBEHAVING
             details: locked due to failure in module sync
           lastUpdateTime: 2022-12-31T20:30:40.000+0000
+        trustLevel: COMPLETE
       properties:
         cmHandle:
           example: my-cm-handle1
@@ -1987,6 +1988,10 @@ components:
           type: array
         state:
           $ref: '#/components/schemas/CmHandleCompositeState'
+        trustLevel:
+          description: Current trust level of the relevant CM handle ID.
+          example: COMPLETE
+          type: string
       title: CM handle Details
       type: object
     CmHandlePublicProperties:
@@ -2064,6 +2069,10 @@ components:
           example: 2022-12-31T20:30:40.000+0000
           type: string
       type: object
+    CmHandleTrustLevel:
+      description: Current trust level of the relevant CM handle ID.
+      example: COMPLETE
+      type: string
     RestOutputCmHandlePublicProperties:
       example:
         publicCmHandleProperties:
index eb5804e..61eeeda 100644 (file)
@@ -162,133 +162,142 @@ values to configure the application to be deployed. This list is not exhaustive.
 
 Any spring supported property can be configured by providing in ``config.additional.<spring-supported-property-name>: value`` Example: config.additional.spring.datasource.hikari.maximumPoolSize: 30
 
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| Property                              | Description                                                                                             | Default Value                 |
-+=======================================+=========================================================================================================+===============================+
-| config.appUserName                    | User name used by cps-core service to configure the authentication for REST API it exposes.             | ``cpsuser``                   |
-|                                       |                                                                                                         |                               |
-|                                       | This is the user name to be used by cps-core REST clients to authenticate themselves.                   |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.appUserPassword                | Password used by cps-core service to configure the authentication for REST API it exposes.              | Not defined                   |
-|                                       |                                                                                                         |                               |
-|                                       | If not defined, the password is generated when deploying the application.                               |                               |
-|                                       |                                                                                                         |                               |
-|                                       | See also :ref:`cps_common_credentials_retrieval`.                                                       |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| postgres.config.pgUserName            | Internal user name used by cps-core to connect to its own database.                                     | ``cps``                       |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| postgres.config.pgUserPassword        | Internal password used by cps-core to connect to its own database.                                      | Not defined                   |
-|                                       |                                                                                                         |                               |
-|                                       | If not defined, the password is generated when deploying the application.                               |                               |
-|                                       |                                                                                                         |                               |
-|                                       | See also :ref:`cps_common_credentials_retrieval`.                                                       |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| postgres.config.pgDatabase            | Database name used by cps-core                                                                          | ``cpsdb``                     |
-|                                       |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| logging.level                         | Logging level set in cps-core                                                                           | info                          |
-|                                       |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| 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        |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.eventPublisher.                | Kafka consumer client id                                                                                | ``cps-core``                  |
-| spring.kafka.consumer.client-id       |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.eventPublisher.                | Kafka security protocol.                                                                                | ``SASL_PLAINTEXT``            |
-| spring.kafka.security.protocol        | Some possible values are:                                                                               |                               |
-|                                       |                                                                                                         |                               |
-|                                       | * ``PLAINTEXT``                                                                                         |                               |
-|                                       | * ``SASL_PLAINTEXT``, for authentication                                                                |                               |
-|                                       | * ``SASL_SSL``, for authentication and encryption                                                       |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.eventPublisher.                | Kafka security SASL mechanism. Required for SASL_PLAINTEXT and SASL_SSL protocols.                      | Not defined                   |
-| spring.kafka.properties.              | Some possible values are:                                                                               |                               |
-| sasl.mechanism                        |                                                                                                         |                               |
-|                                       | * ``PLAIN``, for PLAINTEXT                                                                              |                               |
-|                                       | * ``SCRAM-SHA-512``, for SSL                                                                            |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.eventPublisher.                | Kafka security SASL JAAS configuration. Required for SASL_PLAINTEXT and SASL_SSL protocols.             | Not defined                   |
-| spring.kafka.properties.              | Some possible values are:                                                                               |                               |
-| sasl.jaas.config                      |                                                                                                         |                               |
-|                                       | * ``org.apache.kafka.common.security.plain.PlainLoginModule required username="..." password="...";``,  |                               |
-|                                       |   for PLAINTEXT                                                                                         |                               |
-|                                       | * ``org.apache.kafka.common.security.scram.ScramLoginModule required username="..." password="...";``,  |                               |
-|                                       |   for SSL                                                                                               |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.eventPublisher.                | Kafka security SASL SSL store type. Required for SASL_SSL protocol.                                     | Not defined                   |
-| spring.kafka.ssl.trust-store-type     | Some possible values are:                                                                               |                               |
-|                                       |                                                                                                         |                               |
-|                                       | * ``JKS``                                                                                               |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.eventPublisher.                | Kafka security SASL SSL store file location. Required for SASL_SSL protocol.                            | Not defined                   |
-| spring.kafka.ssl.trust-store-location |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.eventPublisher.                | Kafka security SASL SSL store password. Required for SASL_SSL protocol.                                 | Not defined                   |
-| spring.kafka.ssl.trust-store-password |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.eventPublisher.                | Kafka security SASL SSL broker hostname identification verification. Required for SASL_SSL protocol.    | Not defined                   |
-| spring.kafka.properties.              | Possible value is:                                                                                      |                               |
-| ssl.endpoint.identification.algorithm |                                                                                                         |                               |
-|                                       | * ``""``, empty string to disable                                                                       |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.additional.                    | If asynchronous messaging, user notifications, and updated event persistence should be enabled          | ``true``                      |
-| notification.data-updated.enabled     |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.additional.                    | Core pool size in asynchronous execution of notification.                                               | ``2``                         |
-| notification.async.executor.          |                                                                                                         |                               |
-| core-pool-size                        |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.additional.                    | Max pool size in asynchronous execution of notification.                                                | ``1``                         |
-| notification.async.executor.          |                                                                                                         |                               |
-| max-pool-size                         |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.additional.                    | Queue Capacity in asynchronous execution of notification.                                               | ``500``                       |
-| notification.async.executor.          |                                                                                                         |                               |
-| queue-capacity                        |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.additional.                    | If the executor should wait for the tasks to be completed on shutdown                                   | ``true``                      |
-| notification.async.executor.          |                                                                                                         |                               |
-| wait-for-tasks-to-complete-on-shutdown|                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.additional.                    | Prefix to be added to the thread name in asynchronous execution of notifications.                       | ``Async-``                    |
-| notification.async.executor.          |                                                                                                         |                               |
-| thread-name-prefix                    |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.additional.                    | Specifies number of database connections between database and application.                              | ``10``                        |
-| spring.datasource.hikari.             | This property controls the maximum size that the pool is allowed to reach,                              |                               |
-| maximumPoolSize                       | including both idle and in-use connections.                                                             |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| Property                                  | Description                                                                                             | Default Value                 |
++===========================================+=========================================================================================================+===============================+
+| config.appUserName                        | User name used by cps-core service to configure the authentication for REST API it exposes.             | ``cpsuser``                   |
+|                                           |                                                                                                         |                               |
+|                                           | This is the user name to be used by cps-core REST clients to authenticate themselves.                   |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.appUserPassword                    | Password used by cps-core service to configure the authentication for REST API it exposes.              | Not defined                   |
+|                                           |                                                                                                         |                               |
+|                                           | If not defined, the password is generated when deploying the application.                               |                               |
+|                                           |                                                                                                         |                               |
+|                                           | See also :ref:`cps_common_credentials_retrieval`.                                                       |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| postgres.config.pgUserName                | Internal user name used by cps-core to connect to its own database.                                     | ``cps``                       |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| postgres.config.pgUserPassword            | Internal password used by cps-core to connect to its own database.                                      | Not defined                   |
+|                                           |                                                                                                         |                               |
+|                                           | If not defined, the password is generated when deploying the application.                               |                               |
+|                                           |                                                                                                         |                               |
+|                                           | See also :ref:`cps_common_credentials_retrieval`.                                                       |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| postgres.config.pgDatabase                | Database name used by cps-core                                                                          | ``cpsdb``                     |
+|                                           |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| logging.level                             | Logging level set in cps-core                                                                           | info                          |
+|                                           |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| 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            |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.eventPublisher.                    | Kafka consumer client id                                                                                | ``cps-core``                  |
+| spring.kafka.consumer.client-id           |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.eventPublisher.                    | Kafka security protocol.                                                                                | ``SASL_PLAINTEXT``            |
+| spring.kafka.security.protocol            | Some possible values are:                                                                               |                               |
+|                                           |                                                                                                         |                               |
+|                                           | * ``PLAINTEXT``                                                                                         |                               |
+|                                           | * ``SASL_PLAINTEXT``, for authentication                                                                |                               |
+|                                           | * ``SASL_SSL``, for authentication and encryption                                                       |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.eventPublisher.                    | Kafka security SASL mechanism. Required for SASL_PLAINTEXT and SASL_SSL protocols.                      | Not defined                   |
+| spring.kafka.properties.                  | Some possible values are:                                                                               |                               |
+| sasl.mechanism                            |                                                                                                         |                               |
+|                                           | * ``PLAIN``, for PLAINTEXT                                                                              |                               |
+|                                           | * ``SCRAM-SHA-512``, for SSL                                                                            |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.eventPublisher.                    | Kafka security SASL JAAS configuration. Required for SASL_PLAINTEXT and SASL_SSL protocols.             | Not defined                   |
+| spring.kafka.properties.                  | Some possible values are:                                                                               |                               |
+| sasl.jaas.config                          |                                                                                                         |                               |
+|                                           | * ``org.apache.kafka.common.security.plain.PlainLoginModule required username="..." password="...";``,  |                               |
+|                                           |   for PLAINTEXT                                                                                         |                               |
+|                                           | * ``org.apache.kafka.common.security.scram.ScramLoginModule required username="..." password="...";``,  |                               |
+|                                           |   for SSL                                                                                               |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.eventPublisher.                    | Kafka security SASL SSL store type. Required for SASL_SSL protocol.                                     | Not defined                   |
+| spring.kafka.ssl.trust-store-type         | Some possible values are:                                                                               |                               |
+|                                           |                                                                                                         |                               |
+|                                           | * ``JKS``                                                                                               |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.eventPublisher.                    | Kafka security SASL SSL store file location. Required for SASL_SSL protocol.                            | Not defined                   |
+| spring.kafka.ssl.trust-store-location     |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.eventPublisher.                    | Kafka security SASL SSL store password. Required for SASL_SSL protocol.                                 | Not defined                   |
+| spring.kafka.ssl.trust-store-password     |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.eventPublisher.                    | Kafka security SASL SSL broker hostname identification verification. Required for SASL_SSL protocol.    | Not defined                   |
+| spring.kafka.properties.                  | Possible value is:                                                                                      |                               |
+| ssl.endpoint.identification.algorithm     |                                                                                                         |                               |
+|                                           | * ``""``, empty string to disable                                                                       |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.additional.                        | Core pool size in asynchronous execution of notification.                                               | ``2``                         |
+| notification.async.executor.              |                                                                                                         |                               |
+| core-pool-size                            |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.additional.                        | Max pool size in asynchronous execution of notification.                                                | ``1``                         |
+| notification.async.executor.              |                                                                                                         |                               |
+| max-pool-size                             |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.additional.                        | Queue Capacity in asynchronous execution of notification.                                               | ``500``                       |
+| notification.async.executor.              |                                                                                                         |                               |
+| queue-capacity                            |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.additional.                        | If the executor should wait for the tasks to be completed on shutdown                                   | ``true``                      |
+| notification.async.executor.              |                                                                                                         |                               |
+| wait-for-tasks-to-complete-on-shutdown    |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.additional.                        | Prefix to be added to the thread name in asynchronous execution of notifications.                       | ``Async-``                    |
+| notification.async.executor.              |                                                                                                         |                               |
+| thread-name-prefix                        |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.additional.                        | Specifies number of database connections between database and application.                              | ``10``                        |
+| spring.datasource.hikari.                 | This property controls the maximum size that the pool is allowed to reach,                              |                               |
+| maximumPoolSize                           | including both idle and in-use connections.                                                             |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
 
 .. _additional-cps-ncmp-customizations:
 
 Additional CPS-NCMP Customizations
 ==================================
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.dmiPluginUserName              | User name used by cps-core to authenticate themselves for using ncmp-dmi-plugin service.                | ``dmiuser``                   |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.dmiPluginUserPassword          | Internal password used by cps-core to connect to ncmp-dmi-plugin service.                               | Not defined                   |
-|                                       |                                                                                                         |                               |
-|                                       | If not defined, the password is generated when deploying the application.                               |                               |
-|                                       |                                                                                                         |                               |
-|                                       | See also :ref:`cps_common_credentials_retrieval`.                                                       |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.ncmp.timers                    | Specifies the delay in milliseconds in which the module sync watch dog will wake again after finishing. | ``30000``                     |
-| .advised-modules-sync.sleep-time-ms   |                                                                                                         |                               |
-|                                       |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.ncmp.timers                    | Specifies the delay in milliseconds in which the retry mechanism watch dog                              |                               |
-| .locked-modules-sync.sleep-time-ms    | will wake again after finishing.                                                                        | ``300000``                    |
-|                                       |                                                                                                         |                               |
-|                                       |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.ncmp.timers                    | Specifies the delay in milliseconds in which the data sync watch dog will wake again after finishing.   | ``30000``                     |
-| .cm-handle-data-sync.sleep-time-ms    |                                                                                                         |                               |
-|                                       |                                                                                                         |                               |
-+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.dmiPluginUserName                  | User name used by cps-core to authenticate themselves for using ncmp-dmi-plugin service.                | ``dmiuser``                   |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.dmiPluginUserPassword              | Internal password used by cps-core to connect to ncmp-dmi-plugin service.                               | Not defined                   |
+|                                           |                                                                                                         |                               |
+|                                           | If not defined, the password is generated when deploying the application.                               |                               |
+|                                           |                                                                                                         |                               |
+|                                           | See also :ref:`cps_common_credentials_retrieval`.                                                       |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.ncmp.timers                        | Specifies the delay in milliseconds in which the module sync watch dog will wake again after finishing. | ``30000``                     |
+| .advised-modules-sync.sleep-time-ms       |                                                                                                         |                               |
+|                                           |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.ncmp.timers                        | Specifies the delay in milliseconds in which the retry mechanism watch dog                              |                               |
+| .locked-modules-sync.sleep-time-ms        | will wake again after finishing.                                                                        | ``300000``                    |
+|                                           |                                                                                                         |                               |
+|                                           |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.ncmp.timers                        | Specifies the delay in milliseconds in which the data sync watch dog will wake again after finishing.   | ``30000``                     |
+| .cm-handle-data-sync.sleep-time-ms        |                                                                                                         |                               |
+|                                           |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.additional.ncmp.dmi.httpclient     | Specifies the maximum time in seconds, to wait for establishing a connection for the HTTP Client.       | ``180``                       |
+| .connectionTimeoutInSeconds               |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.additional.ncmp.dmi.httpclient     | Specifies the maximum number of connections allowed per route in the HTTP client.                       | ``50``                        |
+| .maximumConnectionsPerRoute               |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.additional.ncmp.dmi.httpclient     | Specifies the maximum total number of connections that can be held by the HTTP client.                  | ``100``                       |
+| .maximumConnectionsTotal                  |                                                                                                         |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
+| config.additional.ncmp.dmi.httpclient     | Specifies the duration in seconds for the threshold, after which idle connections will be evicted       | ``5``                         |
+| .idleConnectionEvictionThresholdInSeconds | from the connection pool by the HTTP client.                                                            |                               |
++-------------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
 
 CPS-Core Docker Installation
 ============================
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 63a877d..7fabfc3
@@ -16,6 +16,35 @@ CPS Release Notes
 ..      * * *   NEW DELHI   * * *
 ..      =========================
 
+Version: 3.4.2
+==============
+
+Release Data
+------------
+
++--------------------------------------+--------------------------------------------------------+
+| **CPS Project**                      |                                                        |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+| **Docker images**                    | onap/cps-and-ncmp:3.4.2                                |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+| **Release designation**              | 3.4.2 New Delhi                                        |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+| **Release date**                     | Not yet released                                       |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+
+Bug Fixes
+---------
+3.4.2
+
+
+Features
+--------
+
+
 Version: 3.4.1
 ==============
 
@@ -32,18 +61,26 @@ Release Data
 | **Release designation**              | 3.4.1 New Delhi                                        |
 |                                      |                                                        |
 +--------------------------------------+--------------------------------------------------------+
-| **Release date**                     | Not yet released                                       |
+| **Release date**                     | 2023 December 20                                       |
 |                                      |                                                        |
 +--------------------------------------+--------------------------------------------------------+
 
 Bug Fixes
 ---------
+3.4.1
     - `CPS-1979 <https://jira.onap.org/browse/CPS-1979>`_ Bug fix for Invalid topic name suffix.
 
 Features
 --------
     - CPS-Temporal is no longer supported and any related documentation has been removed.
+    - `CPS-1733 <https://jira.onap.org/browse/CPS-1733>`_ Upgrade YANG schema-set for CM handle without removing and adding it.
     - `CPS-1980 <https://jira.onap.org/browse/CPS-1980>`_ Exposing health and cluster metrics for hazelcast.
+    - `CPS-1994 <https://jira.onap.org/browse/CPS-1994>`_ Use Apache Http Client for DMI REST requests.
+    - `CPS-2005 <https://jira.onap.org/browse/CPS-2005>`_ Removing notification feature for cps updated events ( exclusively used by cps-temporal )
+
+Known Issues
+------------
+    - `CPS-2000 <https://jira.onap.org/browse/CPS-2000>`_ Schema object cache is not distributed.
 
 
 Version: 3.4.0
index 4a8ec5b..18e72b2 100644 (file)
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index 40fe030..6dec3db 100644 (file)
 
 package org.onap.cps.integration.base
 
+import org.onap.cps.api.CpsAnchorService
+import org.onap.cps.api.CpsDataService
+import org.onap.cps.api.CpsDataspaceService
+import org.onap.cps.api.CpsModuleService
 import org.onap.cps.api.CpsQueryService
-import org.onap.cps.api.impl.CpsAdminServiceImpl
-import org.onap.cps.api.impl.CpsDataServiceImpl
-import org.onap.cps.api.impl.CpsModuleServiceImpl
 import org.onap.cps.integration.DatabaseTestContainer
 import org.onap.cps.spi.config.CpsSessionFactory
 import org.onap.cps.spi.exceptions.DataspaceNotFoundException
@@ -44,7 +45,7 @@ import spock.lang.Specification
 
 import java.time.OffsetDateTime
 
-@SpringBootTest(classes = [TestConfig, CpsAdminServiceImpl, CpsValidatorImpl, SessionManager, CpsSessionFactory])
+@SpringBootTest(classes = [TestConfig, CpsValidatorImpl, SessionManager, CpsSessionFactory])
 @Testcontainers
 @EnableAutoConfiguration
 @EnableJpaRepositories(basePackageClasses = [DataspaceRepository])
@@ -57,15 +58,19 @@ class CpsIntegrationSpecBase extends Specification {
 
     @Autowired
     @Lazy
-    CpsAdminServiceImpl cpsAdminService
+    CpsDataspaceService cpsDataspaceService
 
     @Autowired
     @Lazy
-    CpsDataServiceImpl cpsDataService
+    CpsAnchorService cpsAnchorService
 
     @Autowired
     @Lazy
-    CpsModuleServiceImpl cpsModuleService
+    CpsDataService cpsDataService
+
+    @Autowired
+    @Lazy
+    CpsModuleService cpsModuleService
 
     @Autowired
     @Lazy
@@ -83,7 +88,7 @@ class CpsIntegrationSpecBase extends Specification {
 
     def setup() {
         if (!initialized) {
-            cpsAdminService.createDataspace(GENERAL_TEST_DATASPACE)
+            cpsDataspaceService.createDataspace(GENERAL_TEST_DATASPACE)
             def bookstoreModelFileContent = readResourceDataFile('bookstore/bookstore.yang')
             cpsModuleService.createSchemaSet(GENERAL_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, [bookstore : bookstoreModelFileContent])
             initialized = true;
@@ -108,7 +113,7 @@ class CpsIntegrationSpecBase extends Specification {
 
     def dataspaceExists(dataspaceName) {
         try {
-            cpsAdminService.getDataspace(dataspaceName)
+            cpsDataspaceService.getDataspace(dataspaceName)
         } catch (DataspaceNotFoundException dataspaceNotFoundException) {
             return false
         }
@@ -117,7 +122,7 @@ class CpsIntegrationSpecBase extends Specification {
 
     def addAnchorsWithData(numberOfAnchors, dataspaceName, schemaSetName, anchorNamePrefix, data) {
         (1..numberOfAnchors).each {
-            cpsAdminService.createAnchor(dataspaceName, schemaSetName, anchorNamePrefix + it)
+            cpsAnchorService.createAnchor(dataspaceName, schemaSetName, anchorNamePrefix + it)
             cpsDataService.saveData(dataspaceName, anchorNamePrefix + it, data.replace("Easons", "Easons-"+it.toString()), OffsetDateTime.now())
         }
     }
index 14612d6..b101945 100644 (file)
@@ -50,9 +50,9 @@ class FunctionalSpecBase extends CpsIntegrationSpecBase {
     }
 
     def setupBookstoreInfraStructure() {
-        cpsAdminService.createDataspace(FUNCTIONAL_TEST_DATASPACE_1)
-        cpsAdminService.createDataspace(FUNCTIONAL_TEST_DATASPACE_2)
-        cpsAdminService.createDataspace(FUNCTIONAL_TEST_DATASPACE_3)
+        cpsDataspaceService.createDataspace(FUNCTIONAL_TEST_DATASPACE_1)
+        cpsDataspaceService.createDataspace(FUNCTIONAL_TEST_DATASPACE_2)
+        cpsDataspaceService.createDataspace(FUNCTIONAL_TEST_DATASPACE_3)
         def bookstoreYangModelAsString = readResourceDataFile('bookstore/bookstore.yang')
         cpsModuleService.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_SCHEMA_SET, [bookstore: bookstoreYangModelAsString])
         cpsModuleService.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_2, BOOKSTORE_SCHEMA_SET, [bookstore: bookstoreYangModelAsString])
@@ -73,8 +73,8 @@ class FunctionalSpecBase extends CpsIntegrationSpecBase {
 
     def restoreBookstoreDataAnchor(anchorNumber) {
         def anchorName = 'bookstoreAnchor' + anchorNumber
-        cpsAdminService.deleteAnchor(FUNCTIONAL_TEST_DATASPACE_1, anchorName)
-        cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_SCHEMA_SET, anchorName)
+        cpsAnchorService.deleteAnchor(FUNCTIONAL_TEST_DATASPACE_1, anchorName)
+        cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_SCHEMA_SET, anchorName)
         cpsDataService.saveData(FUNCTIONAL_TEST_DATASPACE_1, anchorName, bookstoreJsonData.replace("Easons", "Easons-"+anchorNumber.toString()), OffsetDateTime.now())
     }
 
index f4cc8b7..e1ccdaa 100644 (file)
@@ -21,7 +21,6 @@
 package org.onap.cps.integration.base
 
 import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.notification.NotificationService
 import org.onap.cps.spi.CpsDataPersistenceService
 import org.onap.cps.spi.CpsModulePersistenceService
 import org.onap.cps.spi.impl.CpsAdminPersistenceServiceImpl
@@ -98,11 +97,6 @@ class TestConfig extends Specification{
         return new JsonObjectMapper(new ObjectMapper())
     }
 
-    @Bean
-    NotificationService notificationService() {
-        return Stub(NotificationService)
-    }
-
     @Bean
     TimedYangParser timedYangParser() {
         return new TimedYangParser()
 
 package org.onap.cps.integration.functional
 
-import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsAnchorService
 import org.onap.cps.integration.base.CpsIntegrationSpecBase
 import org.onap.cps.spi.FetchDescendantsOption
 import org.onap.cps.spi.exceptions.AlreadyDefinedException
 import org.onap.cps.spi.exceptions.AnchorNotFoundException
-import org.onap.cps.spi.exceptions.DataspaceInUseException
-import org.onap.cps.spi.exceptions.DataspaceNotFoundException
-import java.time.OffsetDateTime
-
-class CpsAdminServiceIntegrationSpec extends CpsIntegrationSpecBase {
-
-    CpsAdminService objectUnderTest
 
-    def setup() { objectUnderTest = cpsAdminService }
-
-    def 'Dataspace CRUD operations.'() {
-        when: 'a dataspace is created'
-            objectUnderTest.createDataspace('newDataspace')
-        then: 'the dataspace can be read'
-            assert objectUnderTest.getDataspace('newDataspace').name == 'newDataspace'
-        and: 'it can be deleted'
-            objectUnderTest.deleteDataspace('newDataspace')
-        then: 'the dataspace no longer exists i.e. an exception is thrown if an attempt is made to retrieve it'
-            def thrown = null
-            try {
-                objectUnderTest.getDataspace('newDataspace')
-            } catch(Exception exception) {
-                thrown = exception
-            }
-           assert thrown instanceof DataspaceNotFoundException
-    }
+import java.time.OffsetDateTime
 
-    def 'Delete dataspace with error; #scenario.'() {
-        setup: 'add some anchors if needed'
-            numberOfAnchors.times {
-                objectUnderTest.createAnchor(GENERAL_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'anchor' + it)
-            }
-        when: 'attempt to delete dataspace'
-            objectUnderTest.deleteDataspace(dataspaceName)
-        then: 'the correct exception is thrown with the relevant details'
-            def thrownException = thrown(expectedException)
-            thrownException.details.contains(expectedMessageDetails)
-        cleanup:
-            numberOfAnchors.times {
-                objectUnderTest.deleteAnchor(GENERAL_TEST_DATASPACE, 'anchor' + it)
-            }
-        where: 'the following data is used'
-            scenario                        | dataspaceName          | numberOfAnchors || expectedException          | expectedMessageDetails
-            'dataspace name does not exist' | 'unknown'              | 0               || DataspaceNotFoundException | 'unknown does not exist'
-            'dataspace contains schemasets' | GENERAL_TEST_DATASPACE | 0               || DataspaceInUseException    | 'contains 1 schemaset(s)'
-            'dataspace contains anchors'    | GENERAL_TEST_DATASPACE | 2               || DataspaceInUseException    | 'contains 2 anchor(s)'
-    }
+class CpsAnchorServiceIntegrationSpec extends CpsIntegrationSpecBase {
 
-    def 'Retrieve all dataspaces (depends on total test suite).'() {
-        given: 'two addtional dataspaces are created'
-            objectUnderTest.createDataspace('dataspace1')
-            objectUnderTest.createDataspace('dataspace2')
-        when: 'all datespaces are retreived'
-            def result = objectUnderTest.getAllDataspaces()
-        then: 'there are at least 3 dataspaces (2 new ones plus the general test dataspace)'
-            result.size() >= 3
-            assert result.name.containsAll([GENERAL_TEST_DATASPACE, 'dataspace1', 'dataspace2'])
-    }
+    CpsAnchorService objectUnderTest
 
-    def 'Duplicate dataspaces.'() {
-        when: 'attempting to create a dataspace with the same name as an existing one'
-            objectUnderTest.createDataspace(GENERAL_TEST_DATASPACE)
-        then: 'an exception is thrown indicating the dataspace already exists'
-            thrown(AlreadyDefinedException)
-    }
+    def setup() { objectUnderTest = cpsAnchorService }
 
     def 'Anchor CRUD operations.'() {
         when: 'an anchor is created'
@@ -148,9 +91,9 @@ class CpsAdminServiceIntegrationSpec extends CpsIntegrationSpecBase {
         then: 'an empty result is returned (no error)'
             assert result == []
         where:
-           scenario                 | dataspaceName
-           'non existing database'  | 'nonExistingDataspace'
-           'just unknown module(s)' | GENERAL_TEST_DATASPACE
+            scenario                 | dataspaceName
+            'non existing database'  | 'nonExistingDataspace'
+            'just unknown module(s)' | GENERAL_TEST_DATASPACE
     }
 
     def 'Update anchor schema set.'() {
index 017ede7..b107a87 100644 (file)
@@ -34,8 +34,6 @@ import org.onap.cps.spi.exceptions.DataValidationException
 import org.onap.cps.spi.exceptions.DataspaceNotFoundException
 import org.onap.cps.spi.model.DeltaReport
 
-import java.time.OffsetDateTime
-
 import static org.onap.cps.spi.FetchDescendantsOption.DIRECT_CHILDREN_ONLY
 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
 import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
@@ -174,7 +172,7 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase {
 
     def 'Attempt to create a top level data node using root.'() {
         given: 'a new anchor'
-            cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_SCHEMA_SET, 'newAnchor1');
+            cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_SCHEMA_SET, 'newAnchor1');
         when: 'attempt to save new top level datanode'
             def json = '{"bookstore": {"bookstore-name": "New Store"} }'
             objectUnderTest.saveData(FUNCTIONAL_TEST_DATASPACE_1, 'newAnchor1' , '/', json, now)
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataspaceServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataspaceServiceIntegrationSpec.groovy
new file mode 100644 (file)
index 0000000..739e802
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ *  ============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.integration.functional
+
+import org.onap.cps.api.CpsDataspaceService
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.onap.cps.spi.exceptions.AlreadyDefinedException
+import org.onap.cps.spi.exceptions.DataspaceInUseException
+import org.onap.cps.spi.exceptions.DataspaceNotFoundException
+
+class CpsDataspaceServiceIntegrationSpec extends CpsIntegrationSpecBase {
+
+    CpsDataspaceService objectUnderTest
+
+    def setup() { objectUnderTest = cpsDataspaceService }
+
+    def 'Dataspace CRUD operations.'() {
+        when: 'a dataspace is created'
+            objectUnderTest.createDataspace('newDataspace')
+        then: 'the dataspace can be read'
+            assert objectUnderTest.getDataspace('newDataspace').name == 'newDataspace'
+        and: 'it can be deleted'
+            objectUnderTest.deleteDataspace('newDataspace')
+        then: 'the dataspace no longer exists i.e. an exception is thrown if an attempt is made to retrieve it'
+            def thrown = null
+            try {
+                objectUnderTest.getDataspace('newDataspace')
+            } catch(Exception exception) {
+                thrown = exception
+            }
+           assert thrown instanceof DataspaceNotFoundException
+    }
+
+    def 'Attempt to delete a non-existing dataspace'() {
+        when: 'attempt to delete a non-existing dataspace'
+            objectUnderTest.deleteDataspace('non-existing-name')
+        then: 'a not found exception is thrown with the relevant dataspace name'
+            def thrownException = thrown(DataspaceNotFoundException)
+            assert thrownException.details.contains('non-existing-name does not exist')
+    }
+
+    def 'Attempt Delete dataspace with a schema set and anchor'() {
+        setup: 'a dataspace with a schema set and anchor'
+            objectUnderTest.createDataspace('targetDataspace')
+            cpsModuleService.createSchemaSet('targetDataspace','someSchemaSet',[:])
+            cpsAnchorService.createAnchor('targetDataspace', 'someSchemaSet', 'some_anchor')
+        when: 'attempt to delete dataspace'
+            objectUnderTest.deleteDataspace('targetDataspace')
+        then: 'an in-use exception is thrown mentioning anchors'
+            def thrownException = thrown(DataspaceInUseException)
+            assert thrownException.details.contains('contains 1 anchor(s)')
+        cleanup:
+            cpsModuleService.deleteSchemaSetsWithCascade('targetDataspace',['someSchemaSet'])
+            objectUnderTest.deleteDataspace('targetDataspace')
+    }
+
+    def 'Attempt to delete dataspace with just a schema set'() {
+        setup: 'a dataspace with a schema set'
+            objectUnderTest.createDataspace('targetDataspace')
+            cpsModuleService.createSchemaSet('targetDataspace','someSchemaSet',[:])
+        when: 'attempt to delete dataspace'
+            objectUnderTest.deleteDataspace('targetDataspace')
+        then: 'an in-use exception is thrown mentioning schemasets'
+            def thrownException = thrown(DataspaceInUseException)
+            assert thrownException.details.contains('contains 1 schemaset(s)')
+        cleanup:
+            cpsModuleService.deleteSchemaSetsWithCascade('targetDataspace',['someSchemaSet'])
+            objectUnderTest.deleteDataspace('targetDataspace')
+    }
+
+    def 'Retrieve all dataspaces (depends on total test suite).'() {
+        given: 'two addtional dataspaces are created'
+            objectUnderTest.createDataspace('dataspace1')
+            objectUnderTest.createDataspace('dataspace2')
+        when: 'all datespaces are retreived'
+            def result = objectUnderTest.getAllDataspaces()
+        then: 'there are at least 3 dataspaces (2 new ones plus the general test dataspace)'
+            result.size() >= 3
+            assert result.name.containsAll([GENERAL_TEST_DATASPACE, 'dataspace1', 'dataspace2'])
+    }
+
+    def 'Duplicate dataspaces.'() {
+        when: 'attempting to create a dataspace with the same name as an existing one'
+            objectUnderTest.createDataspace(GENERAL_TEST_DATASPACE)
+        then: 'an exception is thrown indicating the dataspace already exists'
+            thrown(AlreadyDefinedException)
+    }
+
+}
index d33a774..cf0e0b5 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.cps.integration.functional
 
+import org.onap.cps.api.CpsModuleService
 import org.onap.cps.api.impl.CpsModuleServiceImpl
 import org.onap.cps.integration.base.FunctionalSpecBase
 import org.onap.cps.spi.CascadeDeleteAllowed
@@ -33,7 +34,7 @@ import org.onap.cps.spi.model.ModuleReference
 
 class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
 
-    CpsModuleServiceImpl objectUnderTest
+    CpsModuleService objectUnderTest
 
     private static def originalNumberOfModuleReferences = 1
     private static def existingModuleReference = new ModuleReference('stores','2020-09-15')
@@ -52,6 +53,7 @@ class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
 
     def newYangResourcesNameToContentMap = [:]
     def moduleReferences = []
+    def noNewModules = [:]
 
     def setup() {
         objectUnderTest = cpsModuleService
@@ -94,9 +96,9 @@ class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
             moduleReferences.addAll(existingModuleReferences)
         when: 'the new schema set is created'
             def schemaSetName = "NewSchemaWith${numberOfNewModules}Modules"
-            objectUnderTest.createOrUpgradeSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, newYangResourcesNameToContentMap, moduleReferences)
+            objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, newYangResourcesNameToContentMap, moduleReferences)
         and: 'associated with a new anchor'
-            cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, 'newAnchor')
+            cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, schemaSetName, 'newAnchor')
         then: 'the new anchor has the correct number of modules'
             def yangResourceModuleReferences = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'newAnchor')
             assert expectedNumberOfModulesForAnchor == yangResourceModuleReferences.size()
@@ -203,7 +205,7 @@ class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
             objectUnderTest.createSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', newYangResourcesNameToContentMap)
         and: 'optionally create anchor for the schema set'
             if (associateWithAnchor) {
-                cpsAdminService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', 'newAnchor')
+                cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'newSchemaSet', 'newAnchor')
             }
         when: 'attempt to delete the schema set'
             try {
@@ -261,16 +263,75 @@ class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
             'schema set does not exists' | FUNCTIONAL_TEST_DATASPACE_1 | 'unknown'       || SchemaSetNotFoundException
     }
 
+    /*
+        U P G R A D E
+     */
+
+    def 'Upgrade schema set (with existing and new modules, no matching module set tag in NCMP)'() {
+        given: 'an anchor and schema set with 2 modules (to be upgraded)'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences('original', 2)
+            objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', newYangResourcesNameToContentMap, [])
+            cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', 'targetAnchor')
+            def yangResourceModuleReferencesBeforeUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor')
+            assert yangResourceModuleReferencesBeforeUpgrade.size() == 2
+            assert yangResourceModuleReferencesBeforeUpgrade.containsAll([new ModuleReference('original_0','2000-01-01'),new ModuleReference('original_1','2001-01-01')])
+        and: 'two new 2 modules (from node)'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences('new', 2)
+            def newModuleReferences = [new ModuleReference('new_0','2000-01-01'),new ModuleReference('new_1','2001-01-01')]
+        and: 'a list of all module references (normally retrieved from node)'
+            def allModuleReferences = []
+            allModuleReferences.add(existingModuleReference)
+            allModuleReferences.addAll(newModuleReferences)
+        when: 'the schema set is upgraded'
+            objectUnderTest.upgradeSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', newYangResourcesNameToContentMap, allModuleReferences)
+        then: 'the new anchor has the correct new and existing modules'
+            def yangResourceModuleReferencesAfterUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor')
+            assert yangResourceModuleReferencesAfterUpgrade.size() == 3
+            assert yangResourceModuleReferencesAfterUpgrade.contains(existingModuleReference)
+            assert yangResourceModuleReferencesAfterUpgrade.containsAll(newModuleReferences);
+        cleanup:
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, ['targetSchema'])
+    }
+
+    def 'Upgrade existing schema set from another anchor (used in NCMP for matching module set tag)'() {
+        given: 'an anchor and schema set with 1 module (target)'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences('target', 1)
+            objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', newYangResourcesNameToContentMap, [])
+            cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', 'targetAnchor')
+            def moduleReferencesBeforeUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor')
+            assert moduleReferencesBeforeUpgrade.size() == 1
+        and: 'another anchor and schema set with 2 other modules (source for upgrade)'
+            populateNewYangResourcesNameToContentMapAndAllModuleReferences('source', 2)
+            objectUnderTest.createSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'sourceSchema', newYangResourcesNameToContentMap, [])
+            cpsAnchorService.createAnchor(FUNCTIONAL_TEST_DATASPACE_1, 'sourceSchema', 'sourceAnchor')
+            assert objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'sourceAnchor').size() == 2
+        when: 'the target schema is upgraded using the module references from the source anchor'
+            def moduleReferencesFromSourceAnchor = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'sourceAnchor')
+            objectUnderTest.upgradeSchemaSetFromModules(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema', noNewModules, moduleReferencesFromSourceAnchor)
+        then: 'the target schema now refers to the source modules (with namespace) modules'
+            def schemaSetModuleReferencesAfterUpgrade = getObjectUnderTest().getSchemaSet(FUNCTIONAL_TEST_DATASPACE_1, 'targetSchema').moduleReferences
+            assert schemaSetModuleReferencesAfterUpgrade.containsAll([new ModuleReference('source_0','2000-01-01','org:onap:ccsdk:sample'),new ModuleReference('source_1','2001-01-01','org:onap:ccsdk:sample')]);
+        and: 'the associated target anchor has the same module references (without namespace but that is a legacy issue)'
+            def anchorModuleReferencesAfterUpgrade = objectUnderTest.getYangResourcesModuleReferences(FUNCTIONAL_TEST_DATASPACE_1, 'targetAnchor')
+            assert anchorModuleReferencesAfterUpgrade.containsAll([new ModuleReference('source_0','2000-01-01'),new ModuleReference('source_1','2001-01-01')]);
+        cleanup:
+            objectUnderTest.deleteSchemaSetsWithCascade(FUNCTIONAL_TEST_DATASPACE_1, ['sourceSchema', 'targetSchema'])
+    }
+
     /*
         H E L P E R   M E T H O D S
      */
 
     def populateNewYangResourcesNameToContentMapAndAllModuleReferences(numberOfModules) {
+        populateNewYangResourcesNameToContentMapAndAllModuleReferences('name', numberOfModules)
+    }
+
+    def populateNewYangResourcesNameToContentMapAndAllModuleReferences(namePrefix, numberOfModules) {
         numberOfModules.times {
-            def uniqueName = 'name_' + it
+            def uniqueName = namePrefix + '_' + it
             def uniqueRevision = String.valueOf(2000 + it) + '-01-01'
             moduleReferences.add(new ModuleReference(uniqueName, uniqueRevision))
-            def uniqueContent = NEW_RESOURCE_CONTENT.replace(NEW_RESOURCE_REVISION, uniqueRevision)
+            def uniqueContent = NEW_RESOURCE_CONTENT.replace(NEW_RESOURCE_REVISION, uniqueRevision).replace('module test_module', 'module '+uniqueName)
             newYangResourcesNameToContentMap.put(uniqueRevision, uniqueContent)
         }
     }
index d8012ec..816aeff 100644 (file)
@@ -43,7 +43,7 @@ class CpsPerfTestBase extends PerfTestBase {
     }
 
     def setupPerformanceInfraStructure() {
-        cpsAdminService.createDataspace(CPS_PERFORMANCE_TEST_DATASPACE)
+        cpsDataspaceService.createDataspace(CPS_PERFORMANCE_TEST_DATASPACE)
         def modelAsString = readResourceDataFile('bookstore/bookstore.yang')
         cpsModuleService.createSchemaSet(CPS_PERFORMANCE_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, [bookstore: modelAsString])
     }
index bef4224..19c96fd 100644 (file)
@@ -59,20 +59,20 @@ class NcmpPerfTestBase extends PerfTestBase {
     }
 
     def setupPerformanceInfraStructure() {
-        cpsAdminService.createDataspace(NCMP_PERFORMANCE_TEST_DATASPACE)
+        cpsDataspaceService.createDataspace(NCMP_PERFORMANCE_TEST_DATASPACE)
         createRegistrySchemaSet()
         createCmDataSubscriptionsSchemaSet()
         addCmSubscriptionData()
     }
 
     def createInitialData() {
-        cpsAdminService.createAnchor(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_SCHEMA_SET, REGISTRY_ANCHOR)
+        cpsAnchorService.createAnchor(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_SCHEMA_SET, REGISTRY_ANCHOR)
         def data = readResourceDataFile('ncmp-registry/1000-cmhandles.json')
         cpsDataService.saveData(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR, data, OffsetDateTime.now())
     }
 
     def createRegistrySchemaSet() {
-        def modelAsString = readResourceDataFile('ncmp-registry/dmi-registry@2022-05-10.yang')
+        def modelAsString = readResourceDataFile('ncmp-registry/dmi-registry@2023-11-27.yang')
         cpsModuleService.createSchemaSet(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_SCHEMA_SET, [registry: modelAsString])
     }
 
@@ -82,7 +82,7 @@ class NcmpPerfTestBase extends PerfTestBase {
     }
 
     def addCmSubscriptionData() {
-        cpsAdminService.createAnchor(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_SCHEMA_SET, CM_DATA_SUBSCRIPTIONS_ANCHOR)
+        cpsAnchorService.createAnchor(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_SCHEMA_SET, CM_DATA_SUBSCRIPTIONS_ANCHOR)
         cpsDataService.saveData(NCMP_PERFORMANCE_TEST_DATASPACE, CM_DATA_SUBSCRIPTIONS_ANCHOR, datastore1cmHandlePlaceHolder, now)
         def subscribers = createLeafList('subscribers',numberOfCmDataSubscribers, subscriberIdPrefix)
         def filters = '"filters":' + createJsonArray('filter',numberOfFiltersPerCmHandle,'xpath',xpathPrefix,subscribers)
index ce66cb0..4d4d612 100644 (file)
@@ -35,7 +35,7 @@ class CpsDataServiceLimitsPerfTest extends CpsPerfTestBase {
 
     def 'Create 33,000 books (note further tests depend on this running first).'() {
         given: 'an anchor containing a bookstore with one category'
-            cpsAdminService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'limitsAnchor')
+            cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'limitsAnchor')
             def parentNodeData = '{"bookstore": { "categories": [{ "code": 1, "name": "Test", "books" : [] }] }}'
             cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, 'limitsAnchor', parentNodeData, OffsetDateTime.now())
         when: '33,000 books are added'
@@ -84,7 +84,7 @@ class CpsDataServiceLimitsPerfTest extends CpsPerfTestBase {
         when:
             resourceMeter.start()
             cpsDataService.deleteDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, 'limitsAnchor', OffsetDateTime.now())
-            cpsAdminService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, 'limitsAnchor')
+            cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, 'limitsAnchor')
             resourceMeter.stop()
             def durationInSeconds = resourceMeter.getTotalTimeInSeconds()
         then: 'test data is deleted in 1 second'
 
 package org.onap.cps.integration.performance.cps
 
-import org.onap.cps.api.CpsAdminService
+import org.onap.cps.api.CpsAnchorService
 import org.onap.cps.integration.performance.base.CpsPerfTestBase
 
-class CpsAdminServiceLimitsPerfTest extends CpsPerfTestBase {
+class CpsDataspaceServiceLimitsPerfTest extends CpsPerfTestBase {
 
-    CpsAdminService objectUnderTest
+    CpsAnchorService objectUnderTest
 
-    def setup() { objectUnderTest = cpsAdminService }
+    def setup() { objectUnderTest = cpsAnchorService }
 
     def 'Get anchors from multiple schema set names limit exceeded: 32,766 (~ 2^15) schema set names.'() {
         given: 'more than 32,766 schema set names'
index 818c300..e7bfabe 100644 (file)
@@ -182,7 +182,7 @@ class DeletePerfTest extends CpsPerfTestBase {
             def anchorNames = (1..10).collect {'delete' + it}
         when: 'data nodes are deleted'
             resourceMeter.start()
-            cpsAdminService.deleteAnchors(CPS_PERFORMANCE_TEST_DATASPACE, anchorNames)
+            cpsAnchorService.deleteAnchors(CPS_PERFORMANCE_TEST_DATASPACE, anchorNames)
             resourceMeter.stop()
             def deleteDurationInSeconds = resourceMeter.getTotalTimeInSeconds()
         then: 'delete duration is within expected time and memory used is within limit'
index 8118010..35f6555 100644 (file)
@@ -24,68 +24,132 @@ import java.time.OffsetDateTime
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.integration.performance.base.CpsPerfTestBase
 
+import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
+
 class UpdatePerfTest extends CpsPerfTestBase {
+    static final def UPDATE_TEST_ANCHOR = 'updateTestAnchor'
+    static final def INNER_NODE_JSON = readResourceDataFile('openroadm/innerNode.json')
 
     CpsDataService objectUnderTest
     def now = OffsetDateTime.now()
 
     def setup() { objectUnderTest = cpsDataService }
 
-    def 'Update 1 data node with descendants'() {
-        given: 'a list of data nodes to update as JSON'
-            def parentNodeXpath = "/openroadm-devices/openroadm-device[@device-id='C201-7-1A-10']"
-            def jsonData = readResourceDataFile('openroadm/innerNode.json').replace('NODE_ID_HERE', '10')
-        when: 'the fragment entities are updated by the data nodes'
-            resourceMeter.start()
-            objectUnderTest.updateDataNodeAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', parentNodeXpath, jsonData, now)
-            resourceMeter.stop()
-            def updateDurationInSeconds = resourceMeter.getTotalTimeInSeconds()
-        then: 'update completes within expected time and memory used is within limit'
-            recordAndAssertResourceUsage('Update 1 data node', 0.6, updateDurationInSeconds, 100, resourceMeter.getTotalMemoryUsageInMB())
+    def 'Test setup for CPS Update API.'() {
+        given: 'an anchor and empty container node for OpenROADM devices'
+            cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, LARGE_SCHEMA_SET, UPDATE_TEST_ANCHOR)
+            cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR,
+                    '{ "openroadm-devices": { "openroadm-device": []}}', now)
+        expect: 'no device nodes exist yet'
+            assert 0 == countDataNodes('/openroadm-devices/openroadm-device')
     }
 
-    def 'Batch update 100 data nodes with descendants'() {
-        given: 'a list of data nodes to update as JSON'
-            def innerNodeJson = readResourceDataFile('openroadm/innerNode.json')
-            def nodesJsonData = (1..100).collectEntries {[
-                "/openroadm-devices/openroadm-device[@device-id='C201-7-1A-" + it + "']",
-                innerNodeJson.replace('NODE_ID_HERE', it.toString())
-            ]}
-        when: 'the fragment entities are updated by the data nodes'
+    def 'JVM warm up for update tests: #scenario.'() {
+        given: 'replacement JSON for node containing list of device nodes'
+            def jsonData = '{ "openroadm-devices": ' + generateJsonForOpenRoadmDevices(startId, totalNodes, changeLeaves) + '}'
+        when: 'the container node is updated'
+            objectUnderTest.updateDataNodeAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR, '/', jsonData, now)
+        then: 'there are the expected number of total nodes'
+            assert totalNodes == countDataNodes('/openroadm-devices/openroadm-device')
+        where:
+            scenario                           | totalNodes | startId | changeLeaves
+            'Replace 0 nodes with 100'         | 100        | 1       | false
+            'Replace 100 using same data'      | 100        | 1       | false
+            'Replace 100 with new leaf values' | 100        | 1       | true
+            'Replace 100 with 100 new nodes'   | 100        | 101     | false
+            'Replace 50 existing and 50 new'   | 100        | 151     | true
+            'Replace 100 nodes with 0'         | 0          | 1       | false
+    }
+
+    def 'Replace single data node and descendants: #scenario.'() {
+        given: 'replacement JSON for node containing list of device nodes'
+            def jsonData = '{ "openroadm-devices": ' + generateJsonForOpenRoadmDevices(startId, totalNodes, changeLeaves) + '}'
+        when: 'the container node is updated'
             resourceMeter.start()
-            objectUnderTest.updateDataNodesAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm1', nodesJsonData, now)
+            objectUnderTest.updateDataNodeAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR, '/', jsonData, now)
             resourceMeter.stop()
-            def updateDurationInSeconds = resourceMeter.getTotalTimeInSeconds()
-        then: 'update completes within expected time and memory used is within limit'
-            recordAndAssertResourceUsage('Update 100 data nodes', 40, updateDurationInSeconds, 800, resourceMeter.getTotalMemoryUsageInMB())
+        then: 'there are the expected number of total nodes'
+            assert totalNodes == countDataNodes('/openroadm-devices/openroadm-device')
+        and: 'data leaves have expected values'
+            assert totalNodes == countDataNodes(changeLeaves? '/openroadm-devices/openroadm-device[@status="fail"]'
+                                                            : '/openroadm-devices/openroadm-device[@status="success"]')
+        and: 'update completes within expected time and memory used is within limit'
+            recordAndAssertResourceUsage(scenario,
+                    timeLimit, resourceMeter.getTotalTimeInSeconds(),
+                    memoryLimit, resourceMeter.getTotalMemoryUsageInMB())
+        where:
+            scenario                           | totalNodes | startId | changeLeaves || timeLimit | memoryLimit
+            'Replace 0 nodes with 100'         | 100        | 1       | false        ||         7 | 250
+            'Replace 100 using same data'      | 100        | 1       | false        ||         5 | 250
+            'Replace 100 with new leaf values' | 100        | 1       | true         ||         5 | 250
+            'Replace 100 with 100 new nodes'   | 100        | 101     | false        ||        12 | 300
+            'Replace 50 existing and 50 new'   | 100        | 151     | true         ||         8 | 250
+            'Replace 100 nodes with 0'         | 0          | 1       | false        ||         5 | 250
     }
 
-    def 'Update leaves for 1 data node (twice)'() {
-        given: 'Updated json for openroadm data'
-            def jsonDataUpdated  = "{'openroadm-device':{'device-id':'C201-7-1A-10','status':'fail','ne-state':'jeopardy'}}"
-            def jsonDataOriginal = "{'openroadm-device':{'device-id':'C201-7-1A-10','status':'success','ne-state':'inservice'}}"
-        when: 'update is performed for leaves'
+    def 'Replace list content: #scenario.'() {
+        given: 'replacement JSON for list of device nodes'
+            def jsonListData = generateJsonForOpenRoadmDevices(startId, totalNodes, changeLeaves)
+        when: 'the container node is updated'
             resourceMeter.start()
-            objectUnderTest.updateNodeLeaves(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm2', "/openroadm-devices", jsonDataUpdated, now)
-            objectUnderTest.updateNodeLeaves(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm2', "/openroadm-devices", jsonDataOriginal, now)
+            objectUnderTest.replaceListContent(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR, '/openroadm-devices', jsonListData, now)
             resourceMeter.stop()
-            def updateDurationInSeconds = resourceMeter.getTotalTimeInSeconds()
-        then: 'update completes within expected time and memory used is within limit'
-            recordAndAssertResourceUsage('Update leaves for 1 data node', 0.7, updateDurationInSeconds, 200, resourceMeter.getTotalMemoryUsageInMB())
+        then: 'there are the expected number of total nodes'
+            assert totalNodes == countDataNodes('/openroadm-devices/openroadm-device')
+        and: 'data leaves have expected values'
+            assert totalNodes == countDataNodes(changeLeaves? '/openroadm-devices/openroadm-device[@status="fail"]'
+                                                            : '/openroadm-devices/openroadm-device[@status="success"]')
+        and: 'update completes within expected time and memory used is within limit'
+            recordAndAssertResourceUsage(scenario,
+                    timeLimit, resourceMeter.getTotalTimeInSeconds(),
+                    memoryLimit, resourceMeter.getTotalMemoryUsageInMB())
+        where:
+            scenario                                   | totalNodes | startId | changeLeaves || timeLimit | memoryLimit
+            'Replace list of 0 with 100'               | 100        | 1       | false        ||         7 | 250
+            'Replace list of 100 using same data'      | 100        | 1       | false        ||         5 | 250
+            'Replace list of 100 with new leaf values' | 100        | 1       | true         ||         5 | 250
+            'Replace list with 100 new nodes'          | 100        | 101     | false        ||        12 | 300
+            'Replace list with 50 existing and 50 new' | 100        | 151     | true         ||         8 | 250
+            'Replace list of 100 nodes with 1'         | 1          | 1       | false        ||         5 | 250
     }
 
-    def 'Batch update leaves for 100 data nodes (twice)'() {
-        given: 'Updated json for openroadm data'
-            def jsonDataUpdated  = "{'openroadm-device':[" + (1..100).collect { "{'device-id':'C201-7-1A-" + it + "','status':'fail','ne-state':'jeopardy'}" }.join(",") + "]}"
-            def jsonDataOriginal = "{'openroadm-device':[" + (1..100).collect { "{'device-id':'C201-7-1A-" + it + "','status':'success','ne-state':'inservice'}" }.join(",") + "]}"
+    def 'Update leaves for 100 data nodes.'() {
+        given: 'there are 200 existing data nodes'
+            def jsonListData = generateJsonForOpenRoadmDevices(1, 200, false)
+            objectUnderTest.replaceListContent(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR, '/openroadm-devices', jsonListData, now)
+        and: 'JSON for updated data leaves of 100 nodes'
+            def jsonDataUpdated  = "{'openroadm-device':[" + (1..100).collect {"{'device-id':'C201-7-1A-" + it + "','status':'fail','ne-state':'jeopardy'}" }.join(",") + "]}"
         when: 'update is performed for leaves'
             resourceMeter.start()
-            objectUnderTest.updateNodeLeaves(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm2', "/openroadm-devices", jsonDataUpdated, now)
-            objectUnderTest.updateNodeLeaves(CPS_PERFORMANCE_TEST_DATASPACE, 'openroadm2', "/openroadm-devices", jsonDataOriginal, now)
+            objectUnderTest.updateNodeLeaves(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR, "/openroadm-devices", jsonDataUpdated, now)
             resourceMeter.stop()
-            def updateDurationInSeconds = resourceMeter.getTotalTimeInSeconds()
-        then: 'update completes within expected time and memory used is within limit'
-            recordAndAssertResourceUsage('Batch update leaves for 100 data nodes', 1, updateDurationInSeconds, 200, resourceMeter.getTotalMemoryUsageInMB())
+        then: 'data leaves have expected values'
+            assert 100 == countDataNodes('/openroadm-devices/openroadm-device[@status="fail"]')
+        and: 'update completes within expected time and memory used is within limit'
+            recordAndAssertResourceUsage('Update leaves for 100 data nodes',
+                    0.5, resourceMeter.getTotalTimeInSeconds(),
+                    120, resourceMeter.getTotalMemoryUsageInMB())
+    }
+
+    def 'Clean up for CPS Update API.'() {
+        cleanup: 'test anchor and data nodes'
+            cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR)
+    }
+
+    def generateJsonForOpenRoadmDevices(int startId, int totalNodes, boolean changeLeaves) {
+        return '{ "openroadm-device": [' + (0..<totalNodes).collect {makeInnerNodeJson(it + startId, changeLeaves) }.join(',') + ']}}'
+    }
+
+    def makeInnerNodeJson(int nodeId, boolean changeLeaf) {
+        def nodeJson = INNER_NODE_JSON.replace('NODE_ID_HERE', nodeId.toString())
+        if (changeLeaf) {
+            nodeJson = nodeJson.replace('"status": "success"', '"status": "fail"')
+        }
+        return nodeJson
+    }
+
+    def countDataNodes(String cpsPathQuery) {
+        return cpsQueryService.queryDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR, cpsPathQuery, OMIT_DESCENDANTS).size()
     }
 
 }
index 0c7107a..2d38a0d 100644 (file)
@@ -27,7 +27,7 @@ class WritePerfTest extends CpsPerfTestBase {
 
     def 'Writing openroadm data has linear time.'() {
         given: 'an empty anchor exists for openroadm'
-            cpsAdminService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, LARGE_SCHEMA_SET, 'writeAnchor')
+            cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, LARGE_SCHEMA_SET, 'writeAnchor')
         and: 'a list of device nodes to add'
             def jsonData = generateOpenRoadData(totalNodes)
         when: 'device nodes are added'
@@ -39,7 +39,7 @@ class WritePerfTest extends CpsPerfTestBase {
             recordAndAssertResourceUsage("Writing ${totalNodes} devices", expectedDuration, durationInSeconds, memoryLimit, resourceMeter.getTotalMemoryUsageInMB())
         cleanup:
             cpsDataService.deleteDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor', OffsetDateTime.now())
-            cpsAdminService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor')
+            cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor')
         where:
             totalNodes || expectedDuration | memoryLimit
             50         || 4                | 100
@@ -50,7 +50,7 @@ class WritePerfTest extends CpsPerfTestBase {
 
     def 'Writing bookstore data has exponential time.'() {
         given: 'an anchor containing a bookstore with a single category'
-            cpsAdminService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'writeAnchor')
+            cpsAnchorService.createAnchor(CPS_PERFORMANCE_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'writeAnchor')
             def parentNodeData = '{"bookstore": { "categories": [{ "code": 1, "name": "Test", "books" : [] }] }}'
             cpsDataService.saveData(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor', parentNodeData, OffsetDateTime.now())
         and: 'a list of books to add'
@@ -64,7 +64,7 @@ class WritePerfTest extends CpsPerfTestBase {
             recordAndAssertResourceUsage("Writing ${totalBooks} books", expectedDuration, durationInSeconds, memoryLimit, resourceMeter.getTotalMemoryUsageInMB())
         cleanup:
             cpsDataService.deleteDataNodes(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor', OffsetDateTime.now())
-            cpsAdminService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor')
+            cpsAnchorService.deleteAnchor(CPS_PERFORMANCE_TEST_DATASPACE, 'writeAnchor')
         where:
             totalBooks || expectedDuration | memoryLimit
             800        || 1                | 50
@@ -8,6 +8,11 @@ module dmi-registry {
 
   contact "toine.siebelink@est.tech";
 
+  revision "2023-11-27" {
+    description
+    "Added alternateId";
+  }
+
   revision "2023-08-23" {
     description
     "Added ModuleSetTag";
@@ -83,6 +88,9 @@ module dmi-registry {
       leaf module-set-tag {
         type string;
       }
+      leaf alternate-id {
+        type string;
+      }
 
       list additional-properties {
         key "name";
@@ -129,3 +137,4 @@ module dmi-registry {
     }
   }
 }
+
index 5580119..6fd135c 100644 (file)
@@ -5,7 +5,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.1-SNAPSHOT</version>
+        <version>3.4.2-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
diff --git a/pom.xml b/pom.xml
index 675b5a4..4f9355d 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -32,7 +32,7 @@
 \r
     <groupId>org.onap.cps</groupId>\r
     <artifactId>cps-aggregator</artifactId>\r
-    <version>3.4.1-SNAPSHOT</version>\r
+    <version>3.4.2-SNAPSHOT</version>\r
     <packaging>pom</packaging>\r
 \r
     <name>cps</name>\r
diff --git a/releases/3.4.1-container.yaml b/releases/3.4.1-container.yaml
new file mode 100644 (file)
index 0000000..43b488d
--- /dev/null
@@ -0,0 +1,8 @@
+distribution_type: container
+container_release_tag: 3.4.1
+project: cps
+log_dir: cps-maven-docker-stage-master/932/
+ref: 3e14d392a02aa6d7253418702c1dc2f713251af3
+containers:
+  - name: 'cps-and-ncmp'
+    version: '3.4.1-20231220T140720Z'
\ No newline at end of file
diff --git a/releases/3.4.1.yaml b/releases/3.4.1.yaml
new file mode 100644 (file)
index 0000000..39cfcc9
--- /dev/null
@@ -0,0 +1,4 @@
+distribution_type: maven
+log_dir: cps-maven-stage-master/940/
+project: cps
+version: 3.4.1
\ No newline at end of file
index 2c7a903..d47a688 100644 (file)
@@ -25,7 +25,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.cps</groupId>
     <artifactId>spotbugs</artifactId>
-    <version>3.4.1-SNAPSHOT</version>
+    <version>3.4.2-SNAPSHOT</version>
 
     <properties>
         <nexusproxy>https://nexus.onap.org</nexusproxy>
old mode 100755 (executable)
new mode 100644 (file)
index 919f72e..9c3bc33
@@ -22,7 +22,7 @@
 
 major=3
 minor=4
-patch=1
+patch=2
 
 base_version=${major}.${minor}.${patch}