aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--checkstyle/pom.xml2
-rw-r--r--cps-application/pom.xml2
-rw-r--r--cps-application/src/main/resources/application.yml1
-rw-r--r--cps-bom/pom.xml2
-rw-r--r--cps-dependencies/pom.xml6
-rw-r--r--cps-events/pom.xml2
-rw-r--r--cps-ncmp-events/pom.xml2
-rw-r--r--cps-ncmp-events/src/main/resources/schemas/cmnotificationsubscription/ncmp-out-event-schema-1.0.0.json28
-rw-r--r--cps-ncmp-events/src/main/resources/schemas/dmidataavc/avc-event-schema-1.0.0.json22
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml2
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml2
-rw-r--r--cps-ncmp-rest-stub/pom.xml2
-rwxr-xr-xcps-ncmp-rest/docs/openapi/ncmp.yml2
-rwxr-xr-xcps-ncmp-rest/docs/openapi/openapi-inventory.yml2
-rwxr-xr-xcps-ncmp-rest/docs/openapi/openapi.yml2
-rw-r--r--cps-ncmp-rest/pom.xml2
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java18
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandler.java12
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy8
-rw-r--r--cps-ncmp-rest/src/test/resources/application.yml2
-rw-r--r--cps-ncmp-service/pom.xml2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobService.java15
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobStatusService.java45
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteRequest.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiClientRequestException.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiClientRequestException.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiRequestException.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiRequestException.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/InvalidTopicException.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/InvalidTopicException.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/NcmpException.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PayloadTooLargeException.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/PayloadTooLargeException.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/ServerNcmpException.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/ServerNcmpException.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DataNodeHelper.java100
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/CpsApplicationContext.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContext.java)4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/HttpClientConfiguration.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/KafkaConfig.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/OpenTelemetryConfig.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java)76
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NcmpStartUpException.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpStartUpException.java)6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/EventsFacade.java65
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/MappersFacade.java77
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/cache/DmiCacheHandler.java22
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/cmavc/CmAvcEventConsumer.java11
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiCmSubscriptionDetailsPerDmiMapper.java103
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumer.java21
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/models/DmiCmSubscriptionKey.java (renamed from dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DmiOperationCmHandle.java)28
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/models/DmiCmSubscriptionTuple.java (renamed from k6-tests/ncmp/2-wait-for-cmhandles-to-be-ready.js)32
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandler.java3
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImpl.java158
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumer.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventMapper.java8
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java38
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java5
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/utils/CmSubscriptionPersistenceService.java15
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java14
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/PolicyExecutor.java74
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImpl.java13
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java67
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java25
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiProperties.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiProperties.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java)26
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameOrganizer.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/DmiServiceUrlTemplateBuilder.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfiguration.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java)3
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/UrlTemplateParameters.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java9
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java15
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java3
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java9
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java13
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreator.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsService.java55
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/EventDateTimeFormatter.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatter.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/TopicValidator.java2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/DmiSubJobRequestHandlerSpec.groovy41
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/OpenTelemetryCmNotificationSubscriptionConfigSpec.groovy81
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeBaseSpec.groovy54
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeHelperSpec.groovy85
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/CpsApplicationContextSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContextSpec.groovy)2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/HttpClientConfigurationSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy)11
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/KafkaConfigSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfigSpec.groovy)2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/OpenTelemetryConfigSpec.groovy113
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/EventsFacadeSpec.groovy58
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/MappersFacadeSpec.groovy65
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/cache/DmiCacheHandlerSpec.groovy31
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/cmavc/CmAvcEventConsumerSpec.groovy7
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiCmSubscriptionDetailsPerDmiMapperSpec.groovy52
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumerSpec.groovy18
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImplSpec.groovy101
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumerSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventMapperSpec.groovy6
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy29
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/utils/CmSubscriptionPersistenceServiceSpec.groovy15
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy18
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandlerSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy73
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/CpsAsyncRequestResponseEventIntegrationSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/DataOperationEventConsumerSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/FilterStrategiesIntegrationSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/SerializationIntegrationSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImplSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/DataJobServiceImplSpec.groovy)18
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy54
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandlerSpec.groovy40
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/WriteRequestExaminerSpec.groovy)0
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/DmiOperationsBaseSpec.groovy)3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiPropertiesSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiPropertiesSpec.groovy)3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy)18
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilderSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/url/builder/DmiServiceUrlTemplateBuilderSpec.groovy)3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfigurationSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfigurationSpec.groovy)4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy11
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy13
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditionsSpec.groovy12
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy13
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsPublisherSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsServiceSpec.groovy55
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/EventDateTimeFormatterSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatterSpec.groovy)3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/AbstractModelLoaderSpec.groovy6
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoaderSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/CmAvcEventPublisherSpec.groovy3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/ConsumerBaseSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/kafka/ConsumerBaseSpec.groovy)3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/MessagingBaseSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/kafka/MessagingBaseSpec.groovy)2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/TopicValidatorSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/resources/application.yml16
-rw-r--r--cps-ncmp-service/src/test/resources/sampleAvcInputEvent.json7
-rw-r--r--cps-parent/pom.xml3
-rw-r--r--cps-path-parser/pom.xml2
-rw-r--r--cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java4
-rw-r--r--cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy19
-rw-r--r--cps-rest/docs/openapi/components.yml14
-rw-r--r--cps-rest/docs/openapi/cpsData.yml27
-rw-r--r--cps-rest/docs/openapi/cpsDataV2.yml8
-rw-r--r--cps-rest/docs/openapi/openapi.yml13
-rw-r--r--cps-rest/pom.xml2
-rwxr-xr-xcps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java34
-rwxr-xr-xcps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy63
-rw-r--r--cps-ri/pom.xml2
-rw-r--r--cps-service/pom.xml2
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/CpsDataService.java27
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java26
-rw-r--r--cps-service/src/main/java/org/onap/cps/utils/YangParserHelper.java10
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy71
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy2
-rw-r--r--csit/plans/cps/pnfsim/docker-compose.yml3
-rw-r--r--csit/plans/cps/pnfsim/tls/ca.pem23
-rw-r--r--csit/plans/cps/pnfsim/tls/server_cert.pem21
-rw-r--r--csit/plans/cps/pnfsim/tls/server_key.pem28
-rw-r--r--csit/plans/cps/sdnc/certs/keys0.zipbin5057 -> 3769 bytes
-rwxr-xr-xcsit/plans/cps/teardown.sh10
-rw-r--r--csit/plans/cps/testplanNcmp.txt2
-rwxr-xr-xcsit/run-csit.sh1
-rw-r--r--csit/tests/cps-data-sync/cps-data-sync.robot2
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml113
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/config/NcmpRequestLoggingConfig.java45
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml61
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java323
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DataOperationRequest.java39
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/utils/ResourceFileReaderUtil.java51
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/application.yml64
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/data/operational/ietf-network-topology-sample-rfc8345.json76
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/ietfYang-ModuleResourcesResponse.json52
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/ietfYang-ModuleResponse.json44
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagA-ModuleResourcesResponse.json12
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagA-ModuleResponse.json12
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagB-ModuleResourcesResponse.json12
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagB-ModuleResponse.json12
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagC-ModuleResourcesResponse.json12
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagC-ModuleResponse.json12
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagD-ModuleResourcesResponse.json12
-rw-r--r--dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagD-ModuleResponse.json12
-rw-r--r--dmi-plugin-demo-and-csit-stub/pom.xml42
-rw-r--r--docker-compose/docker-compose.yml54
-rw-r--r--docker-compose/nginx.conf52
-rw-r--r--docker-compose/proxy_params4
-rw-r--r--docs/api/swagger/policy-executor/openapi.yaml86
-rw-r--r--docs/cm-notification-subscriptions.rst48
-rw-r--r--docs/cps-events.rst1
-rw-r--r--docs/ncmp-inventory-querying.rst20
-rw-r--r--docs/release-notes.rst35
-rw-r--r--docs/schemas/ncmp-in-event-schema-1.0.0.json73
-rw-r--r--docs/schemas/ncmp-out-event-schema-1.0.0.json63
-rw-r--r--docs/schemas/policy-executor/ncmp-create-schema-1.0.0.json29
-rw-r--r--docs/schemas/policy-executor/ncmp-delete-schema-1.0.0.json25
-rw-r--r--docs/schemas/policy-executor/ncmp-patch-schema-1.0.0.json29
-rw-r--r--docs/schemas/policy-executor/ncmp-update-schema-1.0.0.json29
-rw-r--r--integration-test/pom.xml7
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy38
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy61
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/AnchorServiceIntegrationSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsAnchorServiceIntegrationSpec.groovy)6
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataServiceIntegrationSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy)20
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataspaceServiceIntegrationSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataspaceServiceIntegrationSpec.groovy)6
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy)4
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsQueryServiceIntegrationSpec.groovy)9
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/SessionManagerIntegrationSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/SessionManagerIntegrationSpec.groovy)2
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/BearerTokenPassthroughSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpBearerTokenPassthroughSpec.groovy)37
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpCmHandleCreateSpec.groovy)84
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpCmHandleUpgradeSpec.groovy)69
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmNotificationSubscriptionSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpCmNotificationSubscriptionSpec.groovy)4
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobStatusServiceSpec.groovy24
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DmiUrlEncodingPassthroughSpec.groovy65
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpRestApiSpec.groovy)18
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/WriteSubJobSpec.groovy75
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy6
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/UpdatePerfTest.groovy4
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/WritePerfTest.groovy5
-rw-r--r--integration-test/src/test/java/org/onap/cps/integration/DmiStubTestContainer.java61
-rw-r--r--integration-test/src/test/resources/application.yml4
-rw-r--r--jacoco-report/pom.xml8
-rw-r--r--k6-tests/README.md5
-rw-r--r--k6-tests/ncmp/1-create-cmhandles.js44
-rw-r--r--k6-tests/ncmp/10-mixed-load-test.js75
-rw-r--r--k6-tests/ncmp/11-delete-cmhandles.js44
-rw-r--r--k6-tests/ncmp/common/cmhandle-crud.js75
-rw-r--r--k6-tests/ncmp/common/passthrough-crud.js (renamed from k6-tests/ncmp/common/passthrough-read.js)39
-rw-r--r--k6-tests/ncmp/common/search-base.js28
-rw-r--r--k6-tests/ncmp/common/utils.js56
-rw-r--r--k6-tests/ncmp/ncmp-kpi.js168
-rwxr-xr-xk6-tests/ncmp/run-all-tests.sh43
-rwxr-xr-xk6-tests/setup.sh12
-rw-r--r--policy-executor-stub/pom.xml207
-rw-r--r--policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/PolicyExecutorApplication.java (renamed from dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/DmiDemoApplication.java)11
-rw-r--r--policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java107
-rw-r--r--policy-executor-stub/src/main/resources/application.yml20
-rw-r--r--policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/PolicyExecutorApplicationSpec.groovy (renamed from dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DmiDataOperationRequest.java)21
-rw-r--r--policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy155
-rw-r--r--pom.xml4
-rw-r--r--postman-collections/CPS Environment.postman_environment.json24
-rw-r--r--postman-collections/DMI Stub.postman_collection.json161
-rw-r--r--releases/3.5.1-container.yaml8
-rw-r--r--releases/3.5.1.yaml4
-rw-r--r--spotbugs/pom.xml2
-rw-r--r--version.properties2
239 files changed, 3513 insertions, 2916 deletions
diff --git a/checkstyle/pom.xml b/checkstyle/pom.xml
index 0f328e6ce..b0a46aac7 100644
--- a/checkstyle/pom.xml
+++ b/checkstyle/pom.xml
@@ -26,7 +26,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.cps</groupId>
<artifactId>checkstyle</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<profiles>
<profile>
diff --git a/cps-application/pom.xml b/cps-application/pom.xml
index 8ab314ea5..dbc92b9fc 100644
--- a/cps-application/pom.xml
+++ b/cps-application/pom.xml
@@ -28,7 +28,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-application/src/main/resources/application.yml b/cps-application/src/main/resources/application.yml
index 6f0807113..83494d654 100644
--- a/cps-application/src/main/resources/application.yml
+++ b/cps-application/src/main/resources/application.yml
@@ -160,6 +160,7 @@ cps:
endpoint: ${ONAP_OTEL_EXPORTER_ENDPOINT:http://onap-otel-collector:4317}
protocol: ${ONAP_OTEL_EXPORTER_PROTOCOL:grpc}
enabled: ${ONAP_TRACING_ENABLED:false}
+ excluded-observation-names: ${ONAP_EXCLUDED_OBSERVATION_NAMES:tasks.scheduled.execution}
# Actuator
management:
diff --git a/cps-bom/pom.xml b/cps-bom/pom.xml
index 93274b810..d1abc2730 100644
--- a/cps-bom/pom.xml
+++ b/cps-bom/pom.xml
@@ -25,7 +25,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.cps</groupId>
<artifactId>cps-bom</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<packaging>pom</packaging>
<description>This artifact contains dependencyManagement declarations of all published CPS components.</description>
diff --git a/cps-dependencies/pom.xml b/cps-dependencies/pom.xml
index 380c00a39..844f0be9f 100644
--- a/cps-dependencies/pom.xml
+++ b/cps-dependencies/pom.xml
@@ -27,7 +27,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.cps</groupId>
<artifactId>cps-dependencies</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<packaging>pom</packaging>
<name>${project.groupId}:${project.artifactId}</name>
@@ -146,7 +146,7 @@
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-spring</artifactId>
- <version>5.3.1</version>
+ <version>5.3.7</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
@@ -249,7 +249,7 @@
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
- <version>4.21.0</version>
+ <version>4.28.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
diff --git a/cps-events/pom.xml b/cps-events/pom.xml
index 1af13cc91..f53998a6f 100644
--- a/cps-events/pom.xml
+++ b/cps-events/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-ncmp-events/pom.xml b/cps-ncmp-events/pom.xml
index befae04f8..a15177ecf 100644
--- a/cps-ncmp-events/pom.xml
+++ b/cps-ncmp-events/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-ncmp-events/src/main/resources/schemas/cmnotificationsubscription/ncmp-out-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/cmnotificationsubscription/ncmp-out-event-schema-1.0.0.json
index 0c8d02a61..11dc4e111 100644
--- a/cps-ncmp-events/src/main/resources/schemas/cmnotificationsubscription/ncmp-out-event-schema-1.0.0.json
+++ b/cps-ncmp-events/src/main/resources/schemas/cmnotificationsubscription/ncmp-out-event-schema-1.0.0.json
@@ -28,32 +28,26 @@
"description": "The unique subscription id"
},
"acceptedTargets": {
- "type": "array",
- "description": "List of accepted targets",
- "items": {
- "type": "string"
- }
+ "type": "object",
+ "existingJavaType": "java.util.Collection<String>",
+ "description": "Unique Collection of accepted targets"
},
"rejectedTargets": {
- "type": "array",
- "description": "List of rejected targets",
- "items": {
- "type": "string"
- }
+ "type": "object",
+ "existingJavaType": "java.util.Collection<String>",
+ "description": "Unique Collection of rejected targets"
},
"pendingTargets": {
- "type": "array",
- "description": "List of pending targets",
- "items": {
- "type": "string"
- }
+ "type": "object",
+ "existingJavaType": "java.util.Collection<String>",
+ "description": "Unique Collection of pending targets"
}
},
"required": [
+ "subscriptionId",
"acceptedTargets",
- "pendingTargets",
"rejectedTargets",
- "subscriptionId"
+ "pendingTargets"
],
"title": "Data"
}
diff --git a/cps-ncmp-events/src/main/resources/schemas/dmidataavc/avc-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/dmidataavc/avc-event-schema-1.0.0.json
index a5bed939b..474520d14 100644
--- a/cps-ncmp-events/src/main/resources/schemas/dmidataavc/avc-event-schema-1.0.0.json
+++ b/cps-ncmp-events/src/main/resources/schemas/dmidataavc/avc-event-schema-1.0.0.json
@@ -16,7 +16,8 @@
"type": "string"
},
"value": {
- "$ref": "#/definitions/Value"
+ "type": "object",
+ "existingJavaType": "java.lang.Object"
}
},
"required": [
@@ -25,25 +26,6 @@
"target"
]
},
- "Value": {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "attributes": {
- "type": "array",
- "items": {
- "type": "object",
- "existingJavaType": "java.util.Map<String,Object>",
- "additionalProperties": false,
- "properties": {
- "isHoAllowed": {
- "type": "boolean"
- }
- }
- }
- }
- }
- },
"AvcEvent": {
"description": "The payload for AVC event.",
"type": "object",
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml
index 6e21c0475..3125cd375 100644
--- a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml
@@ -22,7 +22,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-ncmp-rest-stub</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
</parent>
<artifactId>cps-ncmp-rest-stub-app</artifactId>
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
index 15c79683f..2bf68de39 100644
--- a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-ncmp-rest-stub</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
</parent>
<artifactId>cps-ncmp-rest-stub-service</artifactId>
diff --git a/cps-ncmp-rest-stub/pom.xml b/cps-ncmp-rest-stub/pom.xml
index 9fad29317..b08b26318 100644
--- a/cps-ncmp-rest-stub/pom.xml
+++ b/cps-ncmp-rest-stub/pom.xml
@@ -22,7 +22,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml
index d0b1f35ea..6972463e3 100755
--- a/cps-ncmp-rest/docs/openapi/ncmp.yml
+++ b/cps-ncmp-rest/docs/openapi/ncmp.yml
@@ -194,7 +194,7 @@ dataOperationForCmHandle:
tags:
- network-cm-proxy
summary: Execute a data operation for group of cm handle ids
- description: This request will be handled asynchronously using messaging to the supplied topic. The rest response will be an acknowledge with a requestId to identify the relevant messages. A maximum of 50 cm handles per operation is supported.
+ description: This request will be handled asynchronously using messaging to the supplied topic. The rest response will be an acknowledge with a requestId to identify the relevant messages. A maximum of 200 cm handles per operation is supported.
operationId: executeDataOperationForCmHandles
parameters:
- $ref: 'components.yaml#/components/parameters/requiredTopicParamInQuery'
diff --git a/cps-ncmp-rest/docs/openapi/openapi-inventory.yml b/cps-ncmp-rest/docs/openapi/openapi-inventory.yml
index b79408287..d68cd8b14 100755
--- a/cps-ncmp-rest/docs/openapi/openapi-inventory.yml
+++ b/cps-ncmp-rest/docs/openapi/openapi-inventory.yml
@@ -21,7 +21,7 @@ openapi: 3.0.3
info:
title: NCMP Inventory API
description: NCMP Inventory API
- version: "1.0"
+ version: "3.5.1"
servers:
- url: /ncmpInventory
components:
diff --git a/cps-ncmp-rest/docs/openapi/openapi.yml b/cps-ncmp-rest/docs/openapi/openapi.yml
index dd6d7c8ba..bf23e4af4 100755
--- a/cps-ncmp-rest/docs/openapi/openapi.yml
+++ b/cps-ncmp-rest/docs/openapi/openapi.yml
@@ -22,7 +22,7 @@ openapi: 3.0.3
info:
title: NCMP to CPS Proxy API
description: NCMP to CPS Proxy API
- version: "1.0"
+ version: "3.5.1"
servers:
- url: /ncmp
components:
diff --git a/cps-ncmp-rest/pom.xml b/cps-ncmp-rest/pom.xml
index 7faec78ec..502e8e894 100644
--- a/cps-ncmp-rest/pom.xml
+++ b/cps-ncmp-rest/pom.xml
@@ -27,7 +27,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
index bb2332d61..a482cf5a3 100755
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
@@ -121,7 +121,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
/**
* Query resource data from datastore.
*
- * @param datastoreName name of the datastore
+ * @param datastoreName name of the datastore (currently only supports "ncmp-datastore:operational")
* @param cmHandle cm handle identifier
* @param cpsPath CPS Path
* @param optionsParamInQuery options query parameter
@@ -144,9 +144,9 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
}
/**
- * Patch resource data from passthrough-running.
+ * Patch resource data.
*
- * @param datastoreName name of the datastore
+ * @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
* @param cmHandle cm handle identifier
* @param resourceIdentifier resource identifier
* @param requestBody the request body
@@ -173,9 +173,9 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
}
/**
- * Create resource data in datastore pass-through running for given cm-handle.
+ * Create resource data for given cm-handle.
*
- * @param datastoreName name of the datastore
+ * @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
* @param cmHandle cm handle identifier
* @param resourceIdentifier resource identifier
* @param requestBody the request body
@@ -198,9 +198,9 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
}
/**
- * Update resource data in datastore pass-through running for given cm-handle.
+ * Update resource data for given cm-handle.
*
- * @param datastoreName name of the datastore
+ * @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
* @param cmHandle cm handle identifier
* @param resourceIdentifier resource identifier
* @param requestBody the request body
@@ -224,9 +224,9 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
}
/**
- * Delete resource data in datastore pass-through running for a given cm-handle.
+ * Delete resource data for a given cm-handle.
*
- * @param datastoreName name of the datastore
+ * @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
* @param cmHandle cm handle identifier
* @param resourceIdentifier resource identifier
* @param contentType content type of the body
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandler.java
index d8c4af53b..d61d30dc2 100644
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandler.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandler.java
@@ -26,12 +26,12 @@ import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.data.exceptions.InvalidDatastoreException;
import org.onap.cps.ncmp.api.data.exceptions.InvalidOperationException;
import org.onap.cps.ncmp.api.data.exceptions.OperationNotSupportedException;
-import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException;
-import org.onap.cps.ncmp.api.impl.exception.DmiRequestException;
-import org.onap.cps.ncmp.api.impl.exception.NcmpException;
-import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException;
-import org.onap.cps.ncmp.exceptions.InvalidTopicException;
-import org.onap.cps.ncmp.exceptions.PayloadTooLargeException;
+import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException;
+import org.onap.cps.ncmp.api.exceptions.DmiRequestException;
+import org.onap.cps.ncmp.api.exceptions.InvalidTopicException;
+import org.onap.cps.ncmp.api.exceptions.NcmpException;
+import org.onap.cps.ncmp.api.exceptions.PayloadTooLargeException;
+import org.onap.cps.ncmp.api.exceptions.ServerNcmpException;
import org.onap.cps.ncmp.rest.model.DmiErrorMessage;
import org.onap.cps.ncmp.rest.model.DmiErrorMessageDmiResponse;
import org.onap.cps.ncmp.rest.model.ErrorMessage;
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy
index b0dca6cc0..97f3e03c6 100644
--- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy
@@ -26,11 +26,11 @@ import org.mapstruct.factory.Mappers
import org.onap.cps.TestUtils
import org.onap.cps.ncmp.api.data.exceptions.InvalidOperationException
import org.onap.cps.ncmp.api.data.exceptions.OperationNotSupportedException
-import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException
-import org.onap.cps.ncmp.api.impl.exception.DmiRequestException
-import org.onap.cps.ncmp.api.impl.exception.ServerNcmpException
+import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException
+import org.onap.cps.ncmp.api.exceptions.DmiRequestException
+import org.onap.cps.ncmp.api.exceptions.PayloadTooLargeException
+import org.onap.cps.ncmp.api.exceptions.ServerNcmpException
import org.onap.cps.ncmp.api.inventory.NetworkCmProxyInventoryFacade
-import org.onap.cps.ncmp.exceptions.PayloadTooLargeException
import org.onap.cps.ncmp.impl.data.NcmpCachedResourceRequestHandler
import org.onap.cps.ncmp.impl.data.NcmpPassthroughResourceRequestHandler
import org.onap.cps.ncmp.impl.data.NetworkCmProxyFacade
diff --git a/cps-ncmp-rest/src/test/resources/application.yml b/cps-ncmp-rest/src/test/resources/application.yml
index 9df1e580f..aa5716716 100644
--- a/cps-ncmp-rest/src/test/resources/application.yml
+++ b/cps-ncmp-rest/src/test/resources/application.yml
@@ -26,4 +26,4 @@ notification:
enabled: true
async:
executor:
- time-out-value-in-ms: 2000 \ No newline at end of file
+ time-out-value-in-ms: 2000
diff --git a/cps-ncmp-service/pom.xml b/cps-ncmp-service/pom.xml
index 1f94b34ea..7fa5917f7 100644
--- a/cps-ncmp-service/pom.xml
+++ b/cps-ncmp-service/pom.xml
@@ -27,7 +27,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobService.java
index 6ff79a934..255b3847e 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobService.java
@@ -31,20 +31,27 @@ public interface DataJobService {
/**
* process read data job operations.
*
- * @param dataJobId Unique identifier of the job within the request
+ * @param authorization the authorization header from the REST request
+ * @param dataJobId unique identifier of the job within the request
* @param dataJobMetadata data job request headers
* @param dataJobReadRequest read data job request
*/
- void readDataJob(String dataJobId, DataJobMetadata dataJobMetadata, DataJobReadRequest dataJobReadRequest);
+ void readDataJob(String authorization,
+ String dataJobId,
+ DataJobMetadata dataJobMetadata,
+ DataJobReadRequest dataJobReadRequest);
/**
* process write data job operations.
*
- * @param dataJobId Unique identifier of the job within the request
+ * @param authorization the authorization header from the REST request
+ * @param dataJobId unique identifier of the job within the request
* @param dataJobMetadata data job request headers
* @param dataJobWriteRequest write data job request
* @return a list of sub-job write responses
*/
- List<SubJobWriteResponse> writeDataJob(String dataJobId, DataJobMetadata dataJobMetadata,
+ List<SubJobWriteResponse> writeDataJob(String authorization,
+ String dataJobId,
+ DataJobMetadata dataJobMetadata,
DataJobWriteRequest dataJobWriteRequest);
} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobStatusService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobStatusService.java
new file mode 100644
index 000000000..50d96f858
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobStatusService.java
@@ -0,0 +1,45 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.datajobs;
+
+/**
+ * Service interface to check the status of a data job.
+ * The operations interact with a DMI Plugin to retrieve data job statuses.
+ */
+public interface DataJobStatusService {
+
+ /**
+ * Retrieves the current status of a specific data job.
+ *
+ * @param authorization The authorization header from the REST request.
+ * @param dmiServiceName The name of the DMI Service relevant to the data job.
+ * @param requestId The unique identifier for the overall data job request.
+ * @param dataProducerJobId The identifier of the data producer job within the DMI system.
+ * @param dataProducerId The ID of the producer registered by DMI, used for operations related to this request.
+ * This could include alternate IDs or specific identifiers.
+ * @return The current status of the data job as a String.
+ */
+ String getDataJobStatus(final String authorization,
+ final String dmiServiceName,
+ final String requestId,
+ final String dataProducerJobId,
+ final String dataProducerId);
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteRequest.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteRequest.java
index 432b21b8c..0e0498ec4 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteRequest.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteRequest.java
@@ -23,7 +23,7 @@ package org.onap.cps.ncmp.api.datajobs.models;
import java.util.Collection;
/**
- * Response data for a write operation by the DMI Plugin.
+ * Request data for a write operation by the DMI Plugin.
*
* @param dataAcceptType Define the data response accept type.
* e.g. "application/vnd.3gpp.object-tree-hierarchical+json",
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiClientRequestException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiClientRequestException.java
index ab0fa6893..65ccba801 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiClientRequestException.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiClientRequestException.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.exception;
+package org.onap.cps.ncmp.api.exceptions;
import lombok.Getter;
import org.onap.cps.ncmp.api.NcmpResponseStatus;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiRequestException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiRequestException.java
index d41ca70bc..b2cfbc01b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiRequestException.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/DmiRequestException.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.exception;
+package org.onap.cps.ncmp.api.exceptions;
/**
* Client Based Network CM Proxy exception.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/InvalidTopicException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/InvalidTopicException.java
index fcf2a28cc..07b186dae 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/InvalidTopicException.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/InvalidTopicException.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.exceptions;
+package org.onap.cps.ncmp.api.exceptions;
import lombok.Getter;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/NcmpException.java
index 2c75b5d99..675496586 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/NcmpException.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.exception;
+package org.onap.cps.ncmp.api.exceptions;
import lombok.Getter;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/PayloadTooLargeException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PayloadTooLargeException.java
index dc7057af7..edb295dbb 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/PayloadTooLargeException.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PayloadTooLargeException.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.exceptions;
+package org.onap.cps.ncmp.api.exceptions;
public class PayloadTooLargeException extends RuntimeException {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/ServerNcmpException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/ServerNcmpException.java
index a03a2d3e6..03dc3bc8d 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/ServerNcmpException.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/ServerNcmpException.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.exception;
+package org.onap.cps.ncmp.api.exceptions;
/**
* Server Based Network CM Proxy exception.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DataNodeHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DataNodeHelper.java
deleted file mode 100644
index c032d1e8a..000000000
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DataNodeHelper.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * ============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.utils;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.onap.cps.spi.model.DataNode;
-
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class DataNodeHelper {
-
- /**
- * The nested DataNode object is being flattened.
- *
- * @param dataNode object.
- * @return DataNode as stream.
- */
- public static Stream<DataNode> flatten(final DataNode dataNode) {
- return Stream.concat(Stream.of(dataNode),
- dataNode.getChildDataNodes().stream().flatMap(DataNodeHelper::flatten));
- }
-
- /**
- * The leaves for each DataNode is listed as map.
- *
- * @param dataNodes as collection
- * @return list of map for the all leaves
- */
- public static List<Map<String, Serializable>> getDataNodeLeaves(final Collection<DataNode> dataNodes) {
- return dataNodes.stream()
- .flatMap(DataNodeHelper::flatten)
- .map(DataNode::getLeaves)
- .collect(Collectors.toList());
- }
-
- /**
- * Extracts the mapping of cm handle id to status with details from nodes leaves.
- *
- * @param dataNodeLeaves as a list of map
- * @return cm handle id to status and details mapping
- */
- public static Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMap(
- final List<Map<String, Serializable>> dataNodeLeaves) {
- return dataNodeLeaves.stream()
- .filter(entryset -> entryset.values().contains("PENDING")
- || entryset.values().contains("ACCEPTED")
- || entryset.values().contains("REJECTED"))
- .collect(
- HashMap<String, Map<String, String>>::new,
- (result, entry) -> {
- final String cmHandleId = (String) entry.get("cmHandleId");
- final String status = (String) entry.get("status");
- final String details = (String) entry.get("details");
-
- if (cmHandleId != null && status != null) {
- result.put(cmHandleId, new HashMap<>());
- result.get(cmHandleId).put("status", status);
- result.get(cmHandleId).put("details", details == null ? "" : details);
- }
- },
- HashMap::putAll
- );
- }
-
- /**
- * Extracts the mapping of cm handle id to status with details from data node collection.
- *
- * @param dataNodes as a collection
- * @return cm handle id to status and details mapping
- */
- public static Map<String, Map<String, String>> cmHandleIdToStatusAndDetailsAsMapFromDataNode(
- final Collection<DataNode> dataNodes) {
- return cmHandleIdToStatusAndDetailsAsMap(getDataNodeLeaves(dataNodes));
- }
-}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java
index a5002e790..44e2ebe32 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java
@@ -27,8 +27,8 @@ import java.util.Collections;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
-import org.onap.cps.ncmp.api.impl.exception.DmiRequestException;
-import org.onap.cps.ncmp.api.impl.exception.NcmpException;
+import org.onap.cps.ncmp.api.exceptions.DmiRequestException;
+import org.onap.cps.ncmp.api.exceptions.NcmpException;
/**
* Dmi Registry request object.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContext.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/CpsApplicationContext.java
index b14cf0d0d..fbc31adcf 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContext.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/CpsApplicationContext.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils.context;
+package org.onap.cps.ncmp.config;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -48,4 +48,4 @@ public class CpsApplicationContext implements ApplicationContextAware {
private static synchronized void setCpsApplicationContext(final ApplicationContext cpsApplicationContext) {
CpsApplicationContext.applicationContext = cpsApplicationContext;
}
-} \ No newline at end of file
+}
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/config/HttpClientConfiguration.java
index 0acbabbba..583d4bb6a 100644
--- 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/config/HttpClientConfiguration.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config;
+package org.onap.cps.ncmp.config;
import lombok.Getter;
import lombok.Setter;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/KafkaConfig.java
index cf6f1c5b1..3d3c3db48 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/KafkaConfig.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config.kafka;
+package org.onap.cps.ncmp.config;
import io.cloudevents.CloudEvent;
import io.opentelemetry.instrumentation.kafkaclients.v2_6.TracingConsumerInterceptor;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/OpenTelemetryConfig.java
index bcbacbd42..a6a82b793 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/OpenTelemetryConfig.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config;
+package org.onap.cps.ncmp.config;
import io.micrometer.observation.ObservationPredicate;
import io.micrometer.observation.ObservationRegistry;
@@ -26,7 +26,11 @@ import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler;
import io.opentelemetry.sdk.trace.samplers.Sampler;
+import jakarta.annotation.PostConstruct;
import java.time.Duration;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryCustomizer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
@@ -37,11 +41,14 @@ import org.springframework.http.server.observation.ServerRequestObservationConte
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
+/**
+ * Configuration class for setting up OpenTelemetry tracing in a Spring Boot application.
+ * This class provides beans for OTLP exporters (gRPC and HTTP), a Jaeger remote sampler,
+ * and customizes the ObservationRegistry to exclude certain endpoints from being observed.
+ */
@Configuration
public class OpenTelemetryConfig {
- public static final int JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND = 30;
-
@Value("${spring.application.name:cps-application}")
private String serviceId;
@@ -51,9 +58,29 @@ public class OpenTelemetryConfig {
@Value("${cps.tracing.sampler.jaeger_remote.endpoint:http://onap-otel-collector:14250}")
private String jaegerRemoteSamplerUrl;
+ @Value("${cps.tracing.excluded-observation-names:tasks.scheduled.execution}")
+ private String excludedObservationNamesAsCsv;
+
+ private static final int JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECONDS = 30;
+
+ private List<String> excludedObservationNames;
+
/**
- * OTLP Exporter with Grpc exporter protocol.
- */
+ * Initializes the excludedObservationNames after the bean's properties have been set.
+ * This method is called by the Spring container during bean initialization.
+ */
+ @PostConstruct
+ public void init() {
+ excludedObservationNames = Arrays.stream(excludedObservationNamesAsCsv.split(","))
+ .map(String::trim)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Creates an OTLP Exporter with gRPC protocol.
+ *
+ * @return OtlpGrpcSpanExporter bean if tracing is enabled and the exporter protocol is gRPC
+ */
@Bean
@ConditionalOnExpression(
"${cps.tracing.enabled} && 'grpc'.equals('${cps.tracing.exporter.protocol}')")
@@ -62,7 +89,9 @@ public class OpenTelemetryConfig {
}
/**
- * OTLP Exporter with HTTP exporter protocol.
+ * Creates an OTLP Exporter with HTTP protocol.
+ *
+ * @return OtlpHttpSpanExporter bean if tracing is enabled and the exporter protocol is HTTP
*/
@Bean
@ConditionalOnExpression(
@@ -72,40 +101,41 @@ public class OpenTelemetryConfig {
}
/**
- * Jaeger Remote Sampler.
+ * Creates a Jaeger Remote Sampler.
+ *
+ * @return JaegerRemoteSampler bean if tracing is enabled
*/
@Bean
@ConditionalOnProperty("cps.tracing.enabled")
public JaegerRemoteSampler createJaegerRemoteSampler() {
return JaegerRemoteSampler.builder()
- .setEndpoint(jaegerRemoteSamplerUrl)
- .setPollingInterval(Duration.ofSeconds(JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND))
- .setInitialSampler(Sampler.alwaysOff())
- .setServiceName(serviceId)
- .build();
+ .setEndpoint(jaegerRemoteSamplerUrl)
+ .setPollingInterval(Duration.ofSeconds(JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECONDS))
+ .setInitialSampler(Sampler.alwaysOff())
+ .setServiceName(serviceId)
+ .build();
}
/**
- * Excluding /actuator/** endpoints.
- */
+ * Customizes the ObservationRegistry to exclude /actuator/** endpoints from being observed.
+ *
+ * @return ObservationRegistryCustomizer bean if tracing is enabled
+ */
@Bean
@ConditionalOnProperty("cps.tracing.enabled")
- ObservationRegistryCustomizer<ObservationRegistry> skipActuatorEndpointsFromObservation() {
+ public ObservationRegistryCustomizer<ObservationRegistry> skipActuatorEndpointsFromObservation() {
final PathMatcher pathMatcher = new AntPathMatcher("/");
return registry ->
- registry.observationConfig().observationPredicate(observationPredicate(pathMatcher));
+ registry.observationConfig().observationPredicate(observationPredicate(pathMatcher));
}
- /**
- * Excluding /actuator/** endpoints.
- */
- static ObservationPredicate observationPredicate(final PathMatcher pathMatcher) {
- return (name, context) -> {
+ private ObservationPredicate observationPredicate(final PathMatcher pathMatcher) {
+ return (observationName, context) -> {
if (context instanceof ServerRequestObservationContext observationContext) {
return !pathMatcher.match("/actuator/**", observationContext.getCarrier().getRequestURI());
} else {
- return true;
+ return !excludedObservationNames.contains(observationName);
}
};
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpStartUpException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NcmpStartUpException.java
index 7ac26f54f..7ffbe2e5c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpStartUpException.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NcmpStartUpException.java
@@ -18,7 +18,9 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.exception;
+package org.onap.cps.ncmp.exceptions;
+
+import org.onap.cps.ncmp.api.exceptions.NcmpException;
/**
* NCMP start up exception.
@@ -34,4 +36,4 @@ public class NcmpStartUpException extends NcmpException {
public NcmpStartUpException(final String message, final String details) {
super(message, details);
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java
index 510a6f51a..7c5fc3be2 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java
@@ -21,7 +21,7 @@
package org.onap.cps.ncmp.exceptions;
import java.io.Serial;
-import org.onap.cps.ncmp.api.impl.exception.NcmpException;
+import org.onap.cps.ncmp.api.exceptions.NcmpException;
public class NoAlternateIdMatchFoundException extends NcmpException {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/EventsFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/EventsFacade.java
deleted file mode 100644
index fbe21267d..000000000
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/EventsFacade.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (c) 2024 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.impl.cmnotificationsubscription;
-
-import lombok.RequiredArgsConstructor;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi.DmiInEventProducer;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp.NcmpOutEventProducer;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.DmiInEvent;
-import org.springframework.stereotype.Component;
-
-@Component
-@RequiredArgsConstructor
-public class EventsFacade {
- private final NcmpOutEventProducer ncmpOutEventProducer;
- private final DmiInEventProducer dmiInEventProducer;
-
- /**
- * Publish the event to the client who requested the subscription with key as subscription id and event is Cloud
- * Event compliant.
- *
- * @param subscriptionId Cm Subscription id
- * @param eventType Type of event
- * @param ncmpOutEvent Cm Notification Subscription Event for the
- * client
- * @param isScheduledEvent Determines if the event is to be scheduled
- * or published now
- */
- public void publishNcmpOutEvent(final String subscriptionId, final String eventType,
- final NcmpOutEvent ncmpOutEvent, final boolean isScheduledEvent) {
- ncmpOutEventProducer.publishNcmpOutEvent(subscriptionId, eventType, ncmpOutEvent, isScheduledEvent);
- }
-
- /**
- * Publish the event to the provided dmi plugin with key as subscription id and the event is in Cloud Event format.
- *
- * @param subscriptionId Cm Subscription id
- * @param dmiPluginName Dmi Plugin Name
- * @param eventType Type of event
- * @param dmiInEvent Cm Notification Subscription event for Dmi
- */
- public void publishDmiInEvent(final String subscriptionId, final String dmiPluginName,
- final String eventType, final DmiInEvent dmiInEvent) {
- dmiInEventProducer.publishDmiInEvent(subscriptionId,
- dmiPluginName, eventType, dmiInEvent);
- }
-}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/MappersFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/MappersFacade.java
deleted file mode 100644
index e79b4e644..000000000
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/MappersFacade.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2024 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.impl.cmnotificationsubscription;
-
-import java.util.List;
-import java.util.Map;
-import lombok.RequiredArgsConstructor;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi.DmiInEventMapper;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionDetails;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionPredicate;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp.NcmpOutEventMapper;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.DmiInEvent;
-import org.springframework.stereotype.Component;
-
-@Component
-@RequiredArgsConstructor
-public class MappersFacade {
-
- private final DmiInEventMapper dmiInEventMapper;
- private final NcmpOutEventMapper ncmpOutEventMapper;
-
- /**
- * Mapper to form a request for the DMI Plugin for the Cm Notification Subscription.
- *
- * @param dmiCmSubscriptionPredicates Collection of Cm Notification Subscription predicates
- * @return cm notification subscription dmi in event
- */
- public DmiInEvent toDmiInEvent(
- final List<DmiCmSubscriptionPredicate> dmiCmSubscriptionPredicates) {
- return dmiInEventMapper.toDmiInEvent(dmiCmSubscriptionPredicates);
- }
-
- /**
- * Mapper to form a response for the client for the Cm Notification Subscription.
- *
- * @param subscriptionId Cm Notification Subscription id
- * @param dmiSubscriptionsPerDmi contains CmNotificationSubscriptionDetails per dmi plugin
- * @return CmNotificationSubscriptionNcmpOutEvent to sent back to the client
- */
- public NcmpOutEvent toNcmpOutEvent(final String subscriptionId,
- final Map<String, DmiCmSubscriptionDetails> dmiSubscriptionsPerDmi) {
- return ncmpOutEventMapper.toNcmpOutEvent(subscriptionId,
- dmiSubscriptionsPerDmi);
- }
-
- /**
- * Mapper to form a rejected response for the client for the Cm Notification Subscription Request.
- *
- * @param subscriptionId subscription id
- * @param rejectedTargetFilters list of rejected target filters for the subscription request
- * @return to sent back to the client
- */
- public NcmpOutEvent toNcmpOutEventForRejectedRequest(
- final String subscriptionId, final List<String> rejectedTargetFilters) {
- return ncmpOutEventMapper.toNcmpOutEventForRejectedRequest(
- subscriptionId, rejectedTargetFilters);
- }
-}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/cache/DmiCacheHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/cache/DmiCacheHandler.java
index c5052f140..b5ab7f652 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/cache/DmiCacheHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/cache/DmiCacheHandler.java
@@ -50,7 +50,7 @@ public class DmiCacheHandler {
private final InventoryPersistence inventoryPersistence;
/**
- * Adds new subscription to the subscription cache.
+ * Adds subscription to the subscription cache.
*
* @param subscriptionId subscription id
* @param predicates subscription request predicates
@@ -60,6 +60,18 @@ public class DmiCacheHandler {
}
/**
+ * Adds subscription to the subscription cache.
+ *
+ * @param subscriptionId subscription id
+ * @param dmiCmSubscriptionDetailsPerDmi map of dmi cm notification subscription details per dmi
+ */
+ public void add(final String subscriptionId,
+ final Map<String, DmiCmSubscriptionDetails>
+ dmiCmSubscriptionDetailsPerDmi) {
+ cmNotificationSubscriptionCache.put(subscriptionId, dmiCmSubscriptionDetailsPerDmi);
+ }
+
+ /**
* Get cm notification subscription cache entry via subscription id.
*
* @param subscriptionId subscription id
@@ -122,8 +134,8 @@ public class DmiCacheHandler {
* @param status String of status
*
*/
- public void updateDmiSubscriptionStatusPerDmi(final String subscriptionId, final String dmiServiceName,
- final CmSubscriptionStatus status) {
+ public void updateDmiSubscriptionStatus(final String subscriptionId, final String dmiServiceName,
+ final CmSubscriptionStatus status) {
final Map<String, DmiCmSubscriptionDetails> dmiSubscriptionsPerDmi =
cmNotificationSubscriptionCache.get(subscriptionId);
dmiSubscriptionsPerDmi.get(dmiServiceName).setCmSubscriptionStatus(status);
@@ -162,7 +174,7 @@ public class DmiCacheHandler {
* @param dmiServiceName String of dmiServiceName
*
*/
- public void removeFromDatabasePerDmi(final String subscriptionId, final String dmiServiceName) {
+ public void removeFromDatabase(final String subscriptionId, final String dmiServiceName) {
final List<DmiCmSubscriptionPredicate> dmiCmSubscriptionPredicates =
cmNotificationSubscriptionCache.get(subscriptionId).get(dmiServiceName)
.getDmiCmSubscriptionPredicates();
@@ -210,6 +222,6 @@ public class DmiCacheHandler {
private boolean isAcceptedOrRejected(final DmiCmSubscriptionDetails dmiCmSubscription) {
return dmiCmSubscription.getCmSubscriptionStatus().toString().equals("ACCEPTED")
- || dmiCmSubscription.getCmSubscriptionStatus().toString().equals("REJECTED");
+ || dmiCmSubscription.getCmSubscriptionStatus().toString().equals("REJECTED");
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/cmavc/CmAvcEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/cmavc/CmAvcEventConsumer.java
index 0207fb90e..9e90eabbc 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/cmavc/CmAvcEventConsumer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/cmavc/CmAvcEventConsumer.java
@@ -21,8 +21,6 @@
package org.onap.cps.ncmp.impl.cmnotificationsubscription.cmavc;
import io.cloudevents.CloudEvent;
-import io.cloudevents.core.builder.CloudEventBuilder;
-import java.util.UUID;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
@@ -56,11 +54,8 @@ public class CmAvcEventConsumer {
containerFactory = "cloudEventConcurrentKafkaListenerContainerFactory")
public void consumeAndForward(
final ConsumerRecord<String, CloudEvent> cmAvcEventAsConsumerRecord) {
- log.debug("Consuming AVC event {} ...", cmAvcEventAsConsumerRecord.value());
- final String newEventId = UUID.randomUUID().toString();
- final CloudEvent outgoingAvcEvent =
- CloudEventBuilder.from(cmAvcEventAsConsumerRecord.value()).withId(newEventId)
- .build();
- eventsPublisher.publishCloudEvent(cmEventsTopicName, newEventId, outgoingAvcEvent);
+ final CloudEvent outgoingAvcEvent = cmAvcEventAsConsumerRecord.value();
+ log.debug("Consuming AVC event {} ...", outgoingAvcEvent);
+ eventsPublisher.publishCloudEvent(cmEventsTopicName, outgoingAvcEvent.getId(), outgoingAvcEvent);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiCmSubscriptionDetailsPerDmiMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiCmSubscriptionDetailsPerDmiMapper.java
new file mode 100644
index 000000000..423c603a9
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiCmSubscriptionDetailsPerDmiMapper.java
@@ -0,0 +1,103 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.impl.cmnotificationsubscription.dmi;
+
+import static org.onap.cps.ncmp.api.data.models.DatastoreType.fromDatastoreName;
+import static org.onap.cps.ncmp.impl.cmnotificationsubscription.models.CmSubscriptionStatus.PENDING;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.onap.cps.ncmp.api.data.models.DatastoreType;
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionDetails;
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionKey;
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionPredicate;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DmiCmSubscriptionDetailsPerDmiMapper {
+
+ /**
+ * Maps Dmi Subscription Keys grouped by Dmi Plugin to DmiCmSubscriptionDetails per Dmi plugin.
+ *
+ * @param subscribersPerDmi Details managed by each dmi plugin
+ * @return Grouped Dmi Subscription details per dmi plugin
+ */
+ public Map<String, DmiCmSubscriptionDetails> toDmiCmSubscriptionsPerDmi(
+ final Map<String, Collection<DmiCmSubscriptionKey>> subscribersPerDmi) {
+
+ final Map<String, DmiCmSubscriptionDetails> dmiSubscriptionsPerDmi = new HashMap<>();
+
+ subscribersPerDmi.forEach((dmiPluginName, dmiCmSubscriptionKeys) -> {
+ final Map<DatastoreTypeAndXpath, List<DmiCmSubscriptionKey>> groupedByDatastoreTypeAndXpath =
+ groupByDatastoreTypeAndXpath(dmiCmSubscriptionKeys);
+
+ final List<DmiCmSubscriptionPredicate> dmiSubscriptionPredicates =
+ createDmiCmSubscriptionPredicates(groupedByDatastoreTypeAndXpath);
+
+ final DmiCmSubscriptionDetails dmiCmSubscriptionDetails =
+ new DmiCmSubscriptionDetails(dmiSubscriptionPredicates, PENDING);
+
+ dmiSubscriptionsPerDmi.put(dmiPluginName, dmiCmSubscriptionDetails);
+ });
+
+ return dmiSubscriptionsPerDmi;
+ }
+
+ private static Map<DatastoreTypeAndXpath, List<DmiCmSubscriptionKey>> groupByDatastoreTypeAndXpath(
+ final Collection<DmiCmSubscriptionKey> dmiCmSubscriptionKeys) {
+ return dmiCmSubscriptionKeys.stream().collect(Collectors.groupingBy(
+ datastoreTypeAndXpath -> new DatastoreTypeAndXpath(
+ fromDatastoreName(datastoreTypeAndXpath.datastoreName()), datastoreTypeAndXpath.xpath())));
+ }
+
+ private static List<DmiCmSubscriptionPredicate> createDmiCmSubscriptionPredicates(
+ final Map<DatastoreTypeAndXpath, List<DmiCmSubscriptionKey>> groupedByDatastoreTypeAndXpath) {
+ final List<DmiCmSubscriptionPredicate> dmiCmSubscriptionPredicates = new ArrayList<>();
+
+ for (final Map.Entry<DatastoreTypeAndXpath, List<DmiCmSubscriptionKey>> datastoreTypeXpathGroupEntry :
+ groupedByDatastoreTypeAndXpath.entrySet()) {
+ final DatastoreTypeAndXpath datastoreTypeAndXpath = datastoreTypeXpathGroupEntry.getKey();
+ final Set<String> cmHandleIds = new HashSet<>();
+
+ for (final DmiCmSubscriptionKey dmiCmSubscriptionKey : datastoreTypeXpathGroupEntry.getValue()) {
+ cmHandleIds.add(dmiCmSubscriptionKey.cmHandleId());
+ }
+
+ final Set<String> xpaths = Collections.singleton(datastoreTypeAndXpath.xpath());
+ dmiCmSubscriptionPredicates.add(
+ new DmiCmSubscriptionPredicate(cmHandleIds, datastoreTypeAndXpath.datastoreType(), xpaths));
+ }
+
+ return dmiCmSubscriptionPredicates;
+ }
+
+
+ private record DatastoreTypeAndXpath(DatastoreType datastoreType, String xpath) { }
+
+}
+
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumer.java
index 2a4581862..20c7c7b13 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumer.java
@@ -30,11 +30,11 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.onap.cps.ncmp.api.NcmpResponseStatus;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.EventsFacade;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.MappersFacade;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.CmSubscriptionStatus;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionDetails;
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp.NcmpOutEventMapper;
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp.NcmpOutEventProducer;
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.dmi_to_ncmp.Data;
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.dmi_to_ncmp.DmiOutEvent;
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent;
@@ -47,8 +47,8 @@ import org.springframework.stereotype.Component;
public class DmiOutEventConsumer {
private final DmiCacheHandler dmiCacheHandler;
- private final EventsFacade eventsFacade;
- private final MappersFacade mappersFacade;
+ private final NcmpOutEventProducer ncmpOutEventProducer;
+ private final NcmpOutEventMapper ncmpOutEventMapper;
private static final String CM_SUBSCRIPTION_CORRELATION_ID_SEPARATOR = "#";
@@ -80,7 +80,7 @@ public class DmiOutEventConsumer {
dmiCacheHandler.persistIntoDatabasePerDmi(subscriptionId, dmiPluginName);
}
if (eventType.equals("subscriptionDeleteResponse")) {
- dmiCacheHandler.removeFromDatabasePerDmi(subscriptionId, dmiPluginName);
+ dmiCacheHandler.removeFromDatabase(subscriptionId, dmiPluginName);
}
handleEventsStatusPerDmi(subscriptionId, eventType);
}
@@ -96,17 +96,14 @@ public class DmiOutEventConsumer {
private void handleCacheStatusPerDmi(final String subscriptionId, final String dmiPluginName,
final CmSubscriptionStatus cmSubscriptionStatus) {
- dmiCacheHandler.updateDmiSubscriptionStatusPerDmi(subscriptionId, dmiPluginName,
+ dmiCacheHandler.updateDmiSubscriptionStatus(subscriptionId, dmiPluginName,
cmSubscriptionStatus);
}
private void handleEventsStatusPerDmi(final String subscriptionId, final String eventType) {
- final Map<String, DmiCmSubscriptionDetails> dmiSubscriptionsPerDmi =
- dmiCacheHandler.get(subscriptionId);
- final NcmpOutEvent ncmpOutEvent = mappersFacade.toNcmpOutEvent(subscriptionId,
- dmiSubscriptionsPerDmi);
- eventsFacade.publishNcmpOutEvent(subscriptionId, eventType,
- ncmpOutEvent, false);
+ final Map<String, DmiCmSubscriptionDetails> dmiSubscriptionsPerDmi = dmiCacheHandler.get(subscriptionId);
+ final NcmpOutEvent ncmpOutEvent = ncmpOutEventMapper.toNcmpOutEvent(subscriptionId, dmiSubscriptionsPerDmi);
+ ncmpOutEventProducer.publishNcmpOutEvent(subscriptionId, eventType, ncmpOutEvent, false);
}
private boolean checkStatusCodeAndMessage(final NcmpResponseStatus ncmpResponseStatus,
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DmiOperationCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/models/DmiCmSubscriptionKey.java
index 5cb24bc39..edc3c566b 100644
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DmiOperationCmHandle.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/models/DmiCmSubscriptionKey.java
@@ -1,6 +1,6 @@
/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,20 +15,16 @@
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
+ * ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.dmi.rest.stub.model.data.operational;
+package org.onap.cps.ncmp.impl.cmnotificationsubscription.models;
-import java.util.HashMap;
-import java.util.Map;
-import lombok.Getter;
-import lombok.Setter;
-
-@Setter
-@Getter
-public class DmiOperationCmHandle {
- private String id;
- private Map<String, String> cmHandleProperties = new HashMap<>();
- private String moduleSetTag;
-}
+/**
+ * Key used to find the records to be sent to the DMI plugin.
+ *
+ * @param datastoreName datastore name
+ * @param cmHandleId cmhandle id
+ * @param xpath xpath
+ */
+public record DmiCmSubscriptionKey(String datastoreName, String cmHandleId, String xpath) { }
diff --git a/k6-tests/ncmp/2-wait-for-cmhandles-to-be-ready.js b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/models/DmiCmSubscriptionTuple.java
index cce85ab7c..cd4a15af4 100644
--- a/k6-tests/ncmp/2-wait-for-cmhandles-to-be-ready.js
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/models/DmiCmSubscriptionTuple.java
@@ -15,28 +15,20 @@
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
+ * ============LICENSE_END=========================================================
*/
-import { makeCustomSummaryReport } from './common/utils.js';
-import { waitForCmHandlesToBeReady } from './common/cmhandle-crud.js';
+package org.onap.cps.ncmp.impl.cmnotificationsubscription.models;
-export const options = {
- vus: 1,
- iterations: 1,
- thresholds: {
- http_req_failed: ['rate == 0'],
- iteration_duration: ['max <= 260000'], // 4m20s
- },
-};
+import java.util.Collection;
+import java.util.Map;
-export default function () {
- const timeOutInSeconds = 6 * 60;
- waitForCmHandlesToBeReady(timeOutInSeconds);
-}
-
-export function handleSummary(data) {
- return {
- stdout: makeCustomSummaryReport(data, options),
- };
+/**
+ * Tuple to be used during for to delete usecase.
+ *
+ * @param lastRemainingSubscriptionsPerDmi subscriptions that are used by only one subscriber grouped per dmi
+ * @param overlappingSubscriptionsPerDmi subscriptions that are shared by multiple subscribers grouped per dmi
+ */
+public record DmiCmSubscriptionTuple(Map<String, Collection<DmiCmSubscriptionKey>> lastRemainingSubscriptionsPerDmi,
+ Map<String, Collection<DmiCmSubscriptionKey>> overlappingSubscriptionsPerDmi) {
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandler.java
index 3a9b2066b..90c5c575e 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandler.java
@@ -37,8 +37,7 @@ public interface CmSubscriptionHandler {
* Process cm notification subscription delete request.
*
* @param subscriptionId subscription id
- * @param predicates subscription predicates
*/
- void processSubscriptionDeleteRequest(final String subscriptionId, final List<Predicate> predicates);
+ void processSubscriptionDeleteRequest(final String subscriptionId);
} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImpl.java
index e225b705d..1cdc7ed3e 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImpl.java
@@ -21,32 +21,50 @@
package org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.EventsFacade;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.MappersFacade;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler;
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi.DmiCmSubscriptionDetailsPerDmiMapper;
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi.DmiInEventMapper;
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi.DmiInEventProducer;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.CmSubscriptionStatus;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionDetails;
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionKey;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionPredicate;
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionTuple;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.utils.CmSubscriptionPersistenceService;
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.client_to_ncmp.Predicate;
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent;
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.DmiInEvent;
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
+import org.onap.cps.spi.model.DataNode;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class CmSubscriptionHandlerImpl implements CmSubscriptionHandler {
+ private static final Pattern SUBSCRIPTION_KEY_FROM_XPATH_PATTERN = Pattern.compile(
+ "^/datastores/datastore\\[@name='([^']*)']/cm-handles/cm-handle\\[@id='([^']*)']/"
+ + "filters/filter\\[@xpath='(.*)']$");
+
private final CmSubscriptionPersistenceService cmSubscriptionPersistenceService;
private final CmSubscriptionComparator cmSubscriptionComparator;
- private final MappersFacade mappersFacade;
- private final EventsFacade eventsFacade;
+ private final NcmpOutEventMapper ncmpOutEventMapper;
+ private final DmiInEventMapper dmiInEventMapper;
+ private final DmiCmSubscriptionDetailsPerDmiMapper dmiCmSubscriptionDetailsPerDmiMapper;
+ private final NcmpOutEventProducer ncmpOutEventProducer;
+ private final DmiInEventProducer dmiInEventProducer;
private final DmiCacheHandler dmiCacheHandler;
+ private final InventoryPersistence inventoryPersistence;
@Override
public void processSubscriptionCreateRequest(final String subscriptionId, final List<Predicate> predicates) {
@@ -60,23 +78,71 @@ public class CmSubscriptionHandlerImpl implements CmSubscriptionHandler {
}
@Override
- public void processSubscriptionDeleteRequest(final String subscriptionId, final List<Predicate> predicates) {
- dmiCacheHandler.add(subscriptionId, predicates);
- sendSubscriptionDeleteRequestToDmi(subscriptionId);
- scheduleNcmpOutEventResponse(subscriptionId, "subscriptionDeleteResponse");
+ public void processSubscriptionDeleteRequest(final String subscriptionId) {
+ final Collection<DataNode> subscriptionDataNodes =
+ cmSubscriptionPersistenceService.getAllNodesForSubscriptionId(subscriptionId);
+ final DmiCmSubscriptionTuple dmiCmSubscriptionTuple =
+ getLastRemainingAndOverlappingSubscriptionsPerDmi(subscriptionDataNodes);
+ dmiCacheHandler.add(subscriptionId, mergeDmiCmSubscriptionDetailsPerDmiMaps(dmiCmSubscriptionTuple));
+ if (dmiCmSubscriptionTuple.lastRemainingSubscriptionsPerDmi().isEmpty()) {
+ acceptAndPublishDeleteRequest(subscriptionId);
+ } else {
+ sendSubscriptionDeleteRequestToDmi(subscriptionId,
+ dmiCmSubscriptionDetailsPerDmiMapper.toDmiCmSubscriptionsPerDmi(
+ dmiCmSubscriptionTuple.lastRemainingSubscriptionsPerDmi()));
+ scheduleNcmpOutEventResponse(subscriptionId, "subscriptionDeleteResponse");
+ }
+ }
+
+ private Map<String, DmiCmSubscriptionDetails> mergeDmiCmSubscriptionDetailsPerDmiMaps(
+ final DmiCmSubscriptionTuple dmiCmSubscriptionTuple) {
+ final Map<String, DmiCmSubscriptionDetails> lastRemainingDmiSubscriptionsPerDmi =
+ dmiCmSubscriptionDetailsPerDmiMapper.toDmiCmSubscriptionsPerDmi(
+ dmiCmSubscriptionTuple.lastRemainingSubscriptionsPerDmi());
+ final Map<String, DmiCmSubscriptionDetails> overlappingDmiSubscriptionsPerDmi =
+ dmiCmSubscriptionDetailsPerDmiMapper.toDmiCmSubscriptionsPerDmi(
+ dmiCmSubscriptionTuple.overlappingSubscriptionsPerDmi());
+ final Map<String, DmiCmSubscriptionDetails> mergedDmiSubscriptionsPerDmi =
+ new HashMap<>(lastRemainingDmiSubscriptionsPerDmi);
+ overlappingDmiSubscriptionsPerDmi.forEach((dmiServiceName, dmiCmSubscriptionDetails) ->
+ mergedDmiSubscriptionsPerDmi.merge(dmiServiceName, dmiCmSubscriptionDetails,
+ this::mergeDmiCmSubscriptionDetails));
+ return mergedDmiSubscriptionsPerDmi;
+ }
+
+ private DmiCmSubscriptionDetails mergeDmiCmSubscriptionDetails(
+ final DmiCmSubscriptionDetails dmiCmSubscriptionDetails,
+ final DmiCmSubscriptionDetails otherDmiCmSubscriptionDetails) {
+ final List<DmiCmSubscriptionPredicate> mergedDmiCmSubscriptionPredicates =
+ new ArrayList<>(dmiCmSubscriptionDetails.getDmiCmSubscriptionPredicates());
+ mergedDmiCmSubscriptionPredicates.addAll(otherDmiCmSubscriptionDetails.getDmiCmSubscriptionPredicates());
+ return new DmiCmSubscriptionDetails(mergedDmiCmSubscriptionPredicates, CmSubscriptionStatus.PENDING);
}
private void scheduleNcmpOutEventResponse(final String subscriptionId, final String eventType) {
- eventsFacade.publishNcmpOutEvent(subscriptionId, eventType, null, true);
+ ncmpOutEventProducer.publishNcmpOutEvent(subscriptionId, eventType, null, true);
}
private void rejectAndPublishCreateRequest(final String subscriptionId, final List<Predicate> predicates) {
final Set<String> subscriptionTargetFilters =
predicates.stream().flatMap(predicate -> predicate.getTargetFilter().stream())
.collect(Collectors.toSet());
- final NcmpOutEvent ncmpOutEvent = mappersFacade.toNcmpOutEventForRejectedRequest(subscriptionId,
+ final NcmpOutEvent ncmpOutEvent = ncmpOutEventMapper.toNcmpOutEventForRejectedRequest(subscriptionId,
new ArrayList<>(subscriptionTargetFilters));
- eventsFacade.publishNcmpOutEvent(subscriptionId, "subscriptionCreateResponse", ncmpOutEvent, false);
+ ncmpOutEventProducer.publishNcmpOutEvent(subscriptionId, "subscriptionCreateResponse", ncmpOutEvent, false);
+ }
+
+ private void acceptAndPublishDeleteRequest(final String subscriptionId) {
+ final Set<String> dmiServiceNames = dmiCacheHandler.get(subscriptionId).keySet();
+ for (final String dmiServiceName : dmiServiceNames) {
+ dmiCacheHandler.updateDmiSubscriptionStatus(subscriptionId, dmiServiceName,
+ CmSubscriptionStatus.ACCEPTED);
+ dmiCacheHandler.removeFromDatabase(subscriptionId, dmiServiceName);
+ }
+ final NcmpOutEvent ncmpOutEvent = ncmpOutEventMapper.toNcmpOutEvent(subscriptionId,
+ dmiCacheHandler.get(subscriptionId));
+ ncmpOutEventProducer.publishNcmpOutEvent(subscriptionId, "subscriptionDeleteResponse", ncmpOutEvent,
+ false);
}
private void handleNewCmSubscription(final String subscriptionId) {
@@ -88,7 +154,7 @@ public class CmSubscriptionHandlerImpl implements CmSubscriptionHandler {
dmiSubscriptionDetails.getDmiCmSubscriptionPredicates());
if (dmiCmSubscriptionPredicates.isEmpty()) {
- acceptAndPublishNcmpOutEventPerDmi(subscriptionId, dmiPluginName);
+ acceptAndPersistCmSubscriptionPerDmi(subscriptionId, dmiPluginName);
} else {
publishDmiInEventPerDmi(subscriptionId, dmiPluginName, dmiCmSubscriptionPredicates);
}
@@ -96,26 +162,68 @@ public class CmSubscriptionHandlerImpl implements CmSubscriptionHandler {
}
private void publishDmiInEventPerDmi(final String subscriptionId, final String dmiPluginName,
- final List<DmiCmSubscriptionPredicate> dmiCmSubscriptionPredicates) {
- final DmiInEvent dmiInEvent = mappersFacade.toDmiInEvent(dmiCmSubscriptionPredicates);
- eventsFacade.publishDmiInEvent(subscriptionId, dmiPluginName,
+ final List<DmiCmSubscriptionPredicate> dmiCmSubscriptionPredicates) {
+ final DmiInEvent dmiInEvent = dmiInEventMapper.toDmiInEvent(dmiCmSubscriptionPredicates);
+ dmiInEventProducer.publishDmiInEvent(subscriptionId, dmiPluginName,
"subscriptionCreateRequest", dmiInEvent);
}
- private void acceptAndPublishNcmpOutEventPerDmi(final String subscriptionId, final String dmiPluginName) {
- dmiCacheHandler.updateDmiSubscriptionStatusPerDmi(subscriptionId, dmiPluginName,
+ private void acceptAndPersistCmSubscriptionPerDmi(final String subscriptionId, final String dmiPluginName) {
+ dmiCacheHandler.updateDmiSubscriptionStatus(subscriptionId, dmiPluginName,
CmSubscriptionStatus.ACCEPTED);
dmiCacheHandler.persistIntoDatabasePerDmi(subscriptionId, dmiPluginName);
}
- private void sendSubscriptionDeleteRequestToDmi(final String subscriptionId) {
- final Map<String, DmiCmSubscriptionDetails> dmiSubscriptionsPerDmi =
- dmiCacheHandler.get(subscriptionId);
- dmiSubscriptionsPerDmi.forEach((dmiPluginName, dmiSubscriptionDetails) -> {
- final DmiInEvent dmiInEvent = mappersFacade.toDmiInEvent(
- dmiSubscriptionDetails.getDmiCmSubscriptionPredicates());
- eventsFacade.publishDmiInEvent(subscriptionId, dmiPluginName,
- "subscriptionDeleteRequest", dmiInEvent);
+ private void sendSubscriptionDeleteRequestToDmi(final String subscriptionId,
+ final Map<String, DmiCmSubscriptionDetails>
+ dmiCmSubscriptionsPerDmi) {
+ dmiCmSubscriptionsPerDmi.forEach((dmiPluginName, dmiCmSubscriptionDetails) -> {
+ final DmiInEvent dmiInEvent =
+ dmiInEventMapper.toDmiInEvent(
+ dmiCmSubscriptionDetails.getDmiCmSubscriptionPredicates());
+ dmiInEventProducer.publishDmiInEvent(subscriptionId,
+ dmiPluginName, "subscriptionDeleteRequest", dmiInEvent);
});
}
+
+
+ private DmiCmSubscriptionTuple getLastRemainingAndOverlappingSubscriptionsPerDmi(
+ final Collection<DataNode> subscriptionNodes) {
+ final Map<String, Collection<DmiCmSubscriptionKey>> lastRemainingSubscriptionsPerDmi = new HashMap<>();
+ final Map<String, Collection<DmiCmSubscriptionKey>> overlappingSubscriptionsPerDmi = new HashMap<>();
+
+ for (final DataNode subscriptionNode : subscriptionNodes) {
+ final DmiCmSubscriptionKey dmiCmSubscriptionKey = extractCmSubscriptionKey(subscriptionNode.getXpath());
+ final String dmiServiceName = inventoryPersistence.getYangModelCmHandle(
+ dmiCmSubscriptionKey.cmHandleId()).getDmiServiceName();
+ final List<String> subscribers = (List<String>) subscriptionNode.getLeaves().get("subscriptionIds");
+ populateDmiCmSubscriptionTuple(subscribers, overlappingSubscriptionsPerDmi,
+ lastRemainingSubscriptionsPerDmi, dmiServiceName, dmiCmSubscriptionKey);
+ }
+ return new DmiCmSubscriptionTuple(lastRemainingSubscriptionsPerDmi, overlappingSubscriptionsPerDmi);
+ }
+
+ private static void populateDmiCmSubscriptionTuple(final List<String> subscribers,
+ final Map<String, Collection<DmiCmSubscriptionKey>>
+ overlappingSubscriptionsPerDmi,
+ final Map<String, Collection<DmiCmSubscriptionKey>>
+ lastRemainingSubscriptionsPerDmi,
+ final String dmiServiceName,
+ final DmiCmSubscriptionKey dmiCmSubscriptionKey) {
+ final Map<String, Collection<DmiCmSubscriptionKey>> targetMap =
+ subscribers.size() > 1 ? overlappingSubscriptionsPerDmi : lastRemainingSubscriptionsPerDmi;
+ targetMap.computeIfAbsent(dmiServiceName, dmiName -> new HashSet<>()).add(dmiCmSubscriptionKey);
+ }
+
+ private DmiCmSubscriptionKey extractCmSubscriptionKey(final String xpath) {
+ final Matcher matcher = SUBSCRIPTION_KEY_FROM_XPATH_PATTERN.matcher(xpath);
+ if (matcher.find()) {
+ final String datastoreName = matcher.group(1);
+ final String cmHandleId = matcher.group(2);
+ final String filterXpath = matcher.group(3);
+ return new DmiCmSubscriptionKey(datastoreName, cmHandleId, filterXpath);
+ }
+ throw new IllegalArgumentException("DataNode xpath does not represent a subscription key");
+ }
+
} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumer.java
index 1e1359dd0..cba64e0e9 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumer.java
@@ -63,7 +63,7 @@ public class NcmpInEventConsumer {
if ("subscriptionDeleteRequest".equals(cloudEvent.getType())) {
log.info("Subscription delete request for source {} with subscription id {} ...",
cloudEvent.getSource(), subscriptionId);
- cmSubscriptionHandler.processSubscriptionDeleteRequest(subscriptionId, predicates);
+ cmSubscriptionHandler.processSubscriptionDeleteRequest(subscriptionId);
}
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventMapper.java
index ffd4b014f..afff9d129 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventMapper.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventMapper.java
@@ -21,6 +21,8 @@
package org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
@@ -76,9 +78,9 @@ public class NcmpOutEventMapper {
final Map<String, DmiCmSubscriptionDetails> dmiSubscriptionsPerDmi,
final Data cmSubscriptionData) {
- final List<String> acceptedCmHandleIds = new ArrayList<>();
- final List<String> pendingCmHandleIds = new ArrayList<>();
- final List<String> rejectedCmHandleIds = new ArrayList<>();
+ final Collection<String> acceptedCmHandleIds = new HashSet<>();
+ final Collection<String> pendingCmHandleIds = new HashSet<>();
+ final Collection<String> rejectedCmHandleIds = new HashSet<>();
dmiSubscriptionsPerDmi.forEach((dmiPluginName, dmiSubscriptionDetails) -> {
final CmSubscriptionStatus cmSubscriptionStatus =
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java
index 92800f4af..3371d59f7 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java
@@ -33,7 +33,6 @@ import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.events.EventsPublisher;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.MappersFacade;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler;
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent;
import org.onap.cps.utils.JsonObjectMapper;
@@ -55,10 +54,11 @@ public class NcmpOutEventProducer {
private final EventsPublisher<CloudEvent> eventsPublisher;
private final JsonObjectMapper jsonObjectMapper;
- private final MappersFacade mappersFacade;
+ private final NcmpOutEventMapper ncmpOutEventMapper;
private final DmiCacheHandler dmiCacheHandler;
private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
- private static final Map<String, ScheduledFuture<?>> scheduledTasksPerSubscriptionId = new ConcurrentHashMap<>();
+ private static final Map<String, ScheduledFuture<?>> scheduledTasksPerSubscriptionIdAndEventType =
+ new ConcurrentHashMap<>();
/**
* Publish the event to the client who requested the subscription with key as subscription id and event is Cloud
@@ -74,31 +74,37 @@ public class NcmpOutEventProducer {
public void publishNcmpOutEvent(final String subscriptionId, final String eventType,
final NcmpOutEvent ncmpOutEvent, final boolean isScheduledEvent) {
- if (isScheduledEvent && !scheduledTasksPerSubscriptionId.containsKey(subscriptionId)) {
+ final String taskKey = subscriptionId.concat(eventType);
+
+ if (isScheduledEvent && !scheduledTasksPerSubscriptionIdAndEventType.containsKey(taskKey)) {
final ScheduledFuture<?> scheduledFuture = scheduleAndPublishNcmpOutEvent(subscriptionId, eventType);
- scheduledTasksPerSubscriptionId.putIfAbsent(subscriptionId, scheduledFuture);
- log.debug("Scheduled the CmNotificationSubscriptionEvent for subscriptionId : {}", subscriptionId);
+ scheduledTasksPerSubscriptionIdAndEventType.putIfAbsent(taskKey, scheduledFuture);
+ log.debug("Scheduled the Cm Subscription Event for subscriptionId : {} and eventType : {}", subscriptionId,
+ eventType);
} else {
- cancelScheduledTaskForSubscriptionId(subscriptionId);
- publishNcmpOutEventNow(subscriptionId, eventType, ncmpOutEvent);
- log.info("Published CmNotificationSubscriptionEvent on demand for subscriptionId : {}", subscriptionId);
+ cancelScheduledTask(taskKey);
+ if (ncmpOutEvent != null) {
+ publishNcmpOutEventNow(subscriptionId, eventType, ncmpOutEvent);
+ log.debug("Published Cm Subscription Event on demand for subscriptionId : {} and eventType : {}",
+ subscriptionId, eventType);
+ }
}
}
private ScheduledFuture<?> scheduleAndPublishNcmpOutEvent(final String subscriptionId, final String eventType) {
final NcmpOutEventPublishingTask ncmpOutEventPublishingTask =
new NcmpOutEventPublishingTask(ncmpOutEventTopic, subscriptionId, eventType, eventsPublisher,
- jsonObjectMapper, mappersFacade, dmiCacheHandler);
+ jsonObjectMapper, ncmpOutEventMapper, dmiCacheHandler);
return scheduledExecutorService.schedule(ncmpOutEventPublishingTask, dmiOutEventTimeoutInMs,
TimeUnit.MILLISECONDS);
}
- private void cancelScheduledTaskForSubscriptionId(final String subscriptionId) {
+ private void cancelScheduledTask(final String taskKey) {
- final ScheduledFuture<?> scheduledFuture = scheduledTasksPerSubscriptionId.get(subscriptionId);
+ final ScheduledFuture<?> scheduledFuture = scheduledTasksPerSubscriptionIdAndEventType.get(taskKey);
if (scheduledFuture != null) {
scheduledFuture.cancel(true);
- scheduledTasksPerSubscriptionId.remove(subscriptionId);
+ scheduledTasksPerSubscriptionIdAndEventType.remove(taskKey);
}
}
@@ -107,10 +113,8 @@ public class NcmpOutEventProducer {
private void publishNcmpOutEventNow(final String subscriptionId, final String eventType,
final NcmpOutEvent ncmpOutEvent) {
final CloudEvent ncmpOutEventAsCloudEvent =
- buildAndGetNcmpOutEventAsCloudEvent(jsonObjectMapper, subscriptionId, eventType,
- ncmpOutEvent);
- eventsPublisher.publishCloudEvent(ncmpOutEventTopic, subscriptionId,
- ncmpOutEventAsCloudEvent);
+ buildAndGetNcmpOutEventAsCloudEvent(jsonObjectMapper, subscriptionId, eventType, ncmpOutEvent);
+ eventsPublisher.publishCloudEvent(ncmpOutEventTopic, subscriptionId, ncmpOutEventAsCloudEvent);
dmiCacheHandler.removeAcceptedAndRejectedDmiSubscriptionEntries(subscriptionId);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java
index 563623756..f8f253d27 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java
@@ -27,7 +27,6 @@ import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.events.EventsPublisher;
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.MappersFacade;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler;
import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionDetails;
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent;
@@ -42,7 +41,7 @@ public class NcmpOutEventPublishingTask implements Runnable {
private final String eventType;
private final EventsPublisher<CloudEvent> eventsPublisher;
private final JsonObjectMapper jsonObjectMapper;
- private final MappersFacade mappersFacade;
+ private final NcmpOutEventMapper ncmpOutEventMapper;
private final DmiCacheHandler dmiCacheHandler;
/**
@@ -53,7 +52,7 @@ public class NcmpOutEventPublishingTask implements Runnable {
public void run() {
final Map<String, DmiCmSubscriptionDetails> dmiSubscriptionsPerDmi =
dmiCacheHandler.get(subscriptionId);
- final NcmpOutEvent ncmpOutEvent = mappersFacade.toNcmpOutEvent(subscriptionId,
+ final NcmpOutEvent ncmpOutEvent = ncmpOutEventMapper.toNcmpOutEvent(subscriptionId,
dmiSubscriptionsPerDmi);
eventsPublisher.publishCloudEvent(topicName, subscriptionId,
buildAndGetNcmpOutEventAsCloudEvent(jsonObjectMapper, subscriptionId, eventType,
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/utils/CmSubscriptionPersistenceService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/utils/CmSubscriptionPersistenceService.java
index c24507a1a..6b5ed908b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/utils/CmSubscriptionPersistenceService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/utils/CmSubscriptionPersistenceService.java
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2024 Nordix Foundation
+ * Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -159,6 +160,18 @@ public class CmSubscriptionPersistenceService {
}
}
+ /**
+ * Retrieve all existing dataNodes for given subscription id.
+ *
+ * @param subscriptionId subscription id
+ * @return collection of DataNodes
+ */
+ public Collection<DataNode> getAllNodesForSubscriptionId(final String subscriptionId) {
+ return cpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME,
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_ID.formatted(subscriptionId),
+ OMIT_DESCENDANTS);
+ }
+
private void deleteListOfSubscriptionsFor(final DatastoreType datastoreType, final String cmHandleId,
final String xpath) {
cpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME,
@@ -204,7 +217,7 @@ public class CmSubscriptionPersistenceService {
cpsDataService.saveListElements(NCMP_DATASPACE_NAME, CM_SUBSCRIPTIONS_ANCHOR_NAME,
CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE.formatted(
datastoreType.getDatastoreName(), cmHandleId), subscriptionDetailsAsJson,
- OffsetDateTime.now());
+ OffsetDateTime.now(), ContentType.JSON);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
index efe0335e8..4cbf9d4b3 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
@@ -37,15 +37,15 @@ import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.data.models.CmResourceAddress;
import org.onap.cps.ncmp.api.data.models.DataOperationRequest;
import org.onap.cps.ncmp.api.data.models.OperationType;
-import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
-import org.onap.cps.ncmp.api.impl.config.DmiProperties;
-import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException;
-import org.onap.cps.ncmp.api.impl.utils.url.builder.DmiServiceUrlTemplateBuilder;
-import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters;
+import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException;
import org.onap.cps.ncmp.impl.data.models.DmiDataOperation;
import org.onap.cps.ncmp.impl.data.models.DmiDataOperationRequest;
import org.onap.cps.ncmp.impl.data.models.DmiOperationCmHandle;
import org.onap.cps.ncmp.impl.data.utils.DmiDataOperationsHelper;
+import org.onap.cps.ncmp.impl.dmi.DmiProperties;
+import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
+import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
@@ -71,6 +71,7 @@ public class DmiDataOperations {
private final JsonObjectMapper jsonObjectMapper;
private final DmiProperties dmiProperties;
private final DmiRestClient dmiRestClient;
+ private final PolicyExecutor policyExecutor;
/**
* This method fetches the resource data from the operational data store for a given CM handle
@@ -170,6 +171,9 @@ public class DmiDataOperations {
final String dataType,
final String authorization) {
final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
+
+ policyExecutor.checkPermission(yangModelCmHandle, operationType, authorization, resourceId, requestData);
+
final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java
index be2dde230..a21210c37 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NcmpPassthroughResourceRequestHandler.java
@@ -32,7 +32,7 @@ import org.onap.cps.ncmp.api.data.models.CmResourceAddress;
import org.onap.cps.ncmp.api.data.models.DataOperationRequest;
import org.onap.cps.ncmp.api.data.models.DatastoreType;
import org.onap.cps.ncmp.api.data.models.OperationType;
-import org.onap.cps.ncmp.exceptions.PayloadTooLargeException;
+import org.onap.cps.ncmp.api.exceptions.PayloadTooLargeException;
import org.onap.cps.ncmp.utils.events.TopicValidator;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/PolicyExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/PolicyExecutor.java
new file mode 100644
index 000000000..2b5eb9e79
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/PolicyExecutor.java
@@ -0,0 +1,74 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.impl.data;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.data.models.OperationType;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class PolicyExecutor {
+
+ @Value("${ncmp.policy-executor.enabled:false}")
+ private boolean enabled;
+
+ @Value("${ncmp.policy-executor.server.address:http://policy-executor}")
+ private String serverAddress;
+
+ @Value("${ncmp.policy-executor.server.port:8080}")
+ private String serverPort;
+
+ private static final String PAYLOAD_TYPE_PREFIX = "cm_";
+
+ /**
+ * Use the Policy Executor to check permission for a cm write operation.
+ * Wil throw an exception when the operation is not permitted (work in progress)
+ *
+ * @param yangModelCmHandle the cm handle involved
+ * @param operationType the write operation
+ * @param authorization the original rest authorization token (can be used to determine the client)
+ * @param resourceIdentifier the resource identifier (can be blank)
+ * @param changeRequestAsJson the change details from the original rest request in json format
+ */
+ public void checkPermission(final YangModelCmHandle yangModelCmHandle,
+ final OperationType operationType,
+ final String authorization,
+ final String resourceIdentifier,
+ final String changeRequestAsJson) {
+ if (enabled) {
+ final String payloadType = PAYLOAD_TYPE_PREFIX + operationType.getOperationName();
+ log.info("Policy Executor Enabled");
+ log.info("Address : {}", serverAddress);
+ log.info("Port : {}", serverPort);
+ log.info("Authorization : {}", authorization);
+ log.info("Payload Type : {}", payloadType);
+ log.info("Target FDN : {}", yangModelCmHandle.getAlternateId());
+ log.info("CM Handle Id : {}", yangModelCmHandle.getId());
+ log.info("Resource Identifier : {}", resourceIdentifier);
+ log.info("Change Request (json) : {}", changeRequestAsJson);
+ }
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java
index ab2f10644..3104be553 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelper.java
@@ -39,10 +39,10 @@ import org.onap.cps.events.EventsPublisher;
import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.data.models.DataOperationDefinition;
import org.onap.cps.ncmp.api.data.models.DataOperationRequest;
-import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer;
-import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext;
+import org.onap.cps.ncmp.config.CpsApplicationContext;
import org.onap.cps.ncmp.impl.data.models.DmiDataOperation;
import org.onap.cps.ncmp.impl.data.models.DmiOperationCmHandle;
+import org.onap.cps.ncmp.impl.dmi.DmiServiceNameOrganizer;
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.springframework.util.LinkedMultiValueMap;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImpl.java
index 56ed6e30d..04c3ad2fc 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImpl.java
@@ -42,19 +42,26 @@ public class DataJobServiceImpl implements DataJobService {
private final WriteRequestExaminer writeRequestExaminer;
@Override
- public void readDataJob(final String dataJobId, final DataJobMetadata dataJobMetadata,
+ public void readDataJob(final String authorization,
+ final String dataJobId,
+ final DataJobMetadata dataJobMetadata,
final DataJobReadRequest dataJobReadRequest) {
log.info("data job id for read operation is: {}", dataJobId);
}
@Override
- public List<SubJobWriteResponse> writeDataJob(final String dataJobId, final DataJobMetadata dataJobMetadata,
+ public List<SubJobWriteResponse> writeDataJob(final String authorization,
+ final String dataJobId,
+ final DataJobMetadata dataJobMetadata,
final DataJobWriteRequest dataJobWriteRequest) {
log.info("data job id for write operation is: {}", dataJobId);
final Map<ProducerKey, List<DmiWriteOperation>> dmiWriteOperationsPerProducerKey =
writeRequestExaminer.splitDmiWriteOperationsFromRequest(dataJobId, dataJobWriteRequest);
- return dmiSubJobClient.sendRequestsToDmi(dataJobId, dataJobMetadata, dmiWriteOperationsPerProducerKey);
+ return dmiSubJobClient.sendRequestsToDmi(authorization,
+ dataJobId,
+ dataJobMetadata,
+ dmiWriteOperationsPerProducerKey);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java
new file mode 100644
index 000000000..a6ecaa109
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java
@@ -0,0 +1,67 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.impl.datajobs;
+
+import lombok.RequiredArgsConstructor;
+import org.onap.cps.ncmp.api.datajobs.DataJobStatusService;
+import org.onap.cps.ncmp.impl.dmi.DmiProperties;
+import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
+import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
+import org.springframework.stereotype.Service;
+
+/**
+ * Implementation of {@link DataJobStatusService} interface.
+ * The operations interact with a DMI Plugin to retrieve data job statuses.
+ */
+@Service
+@RequiredArgsConstructor
+public class DataJobStatusServiceImpl implements DataJobStatusService {
+
+ private final DmiRestClient dmiRestClient;
+ private final DmiProperties dmiProperties;
+
+ @Override
+ public String getDataJobStatus(final String authorization,
+ final String dmiServiceName,
+ final String requestId,
+ final String dataProducerJobId,
+ final String dataProducerId) {
+
+ final UrlTemplateParameters urlTemplateParameters = buildUrlParameters(dmiServiceName, requestId,
+ dataProducerJobId, dataProducerId);
+ return dmiRestClient.getDataJobStatus(urlTemplateParameters, authorization).block();
+ }
+
+ private UrlTemplateParameters buildUrlParameters(final String dmiServiceName,
+ final String requestId,
+ final String dataProducerJobId,
+ final String dataProducerId) {
+ return DmiServiceUrlTemplateBuilder.newInstance()
+ .fixedPathSegment("dataJob")
+ .variablePathSegment("requestId", requestId)
+ .fixedPathSegment("dataProducerJob")
+ .variablePathSegment("dataProducerJobId", dataProducerJobId)
+ .fixedPathSegment("status")
+ .queryParameter("dataProducerId", dataProducerId)
+ .createUrlTemplateParameters(dmiServiceName, dmiProperties.getDmiBasePath());
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java
index 973a2a9b2..c93709ce7 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java
@@ -31,10 +31,10 @@ import org.onap.cps.ncmp.api.datajobs.models.DmiWriteOperation;
import org.onap.cps.ncmp.api.datajobs.models.ProducerKey;
import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteRequest;
import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteResponse;
-import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
-import org.onap.cps.ncmp.api.impl.config.DmiProperties;
-import org.onap.cps.ncmp.api.impl.utils.url.builder.DmiServiceUrlTemplateBuilder;
-import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters;
+import org.onap.cps.ncmp.impl.dmi.DmiProperties;
+import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
+import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
import org.onap.cps.ncmp.impl.models.RequiredDmiService;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.ResponseEntity;
@@ -48,22 +48,24 @@ public class DmiSubJobRequestHandler {
private final DmiRestClient dmiRestClient;
private final DmiProperties dmiProperties;
private final JsonObjectMapper jsonObjectMapper;
- static final String NO_AUTH_HEADER = null;
/**
* Sends sub-job write requests to the DMI Plugin.
*
- * @param dataJobId data ojb identifier
+ * @param authorization the authorization header from the REST request
+ * @param dataJobId data job identifier
* @param dataJobMetadata the data job's metadata
- * @param dmiWriteOperationsPerProducerKey a collection of write requests per producer key.
+ * @param dmiWriteOperationsPerProducerKey a collection of write requests per producer key
* @return a list of sub-job write responses
*/
- public List<SubJobWriteResponse> sendRequestsToDmi(final String dataJobId, final DataJobMetadata dataJobMetadata,
+ public List<SubJobWriteResponse> sendRequestsToDmi(final String authorization,
+ final String dataJobId,
+ final DataJobMetadata dataJobMetadata,
final Map<ProducerKey, List<DmiWriteOperation>> dmiWriteOperationsPerProducerKey) {
final List<SubJobWriteResponse> subJobWriteResponses = new ArrayList<>(dmiWriteOperationsPerProducerKey.size());
dmiWriteOperationsPerProducerKey.forEach((producerKey, dmi3ggpWriteOperations) -> {
final SubJobWriteRequest subJobWriteRequest = new SubJobWriteRequest(dataJobMetadata.dataAcceptType(),
- dataJobMetadata.dataContentType(), dataJobId, dmi3ggpWriteOperations);
+ dataJobMetadata.dataContentType(), producerKey.dataProducerIdentifier(), dmi3ggpWriteOperations);
final UrlTemplateParameters urlTemplateParameters = getUrlTemplateParameters(dataJobId, producerKey);
final ResponseEntity<Object> responseEntity = dmiRestClient.synchronousPostOperationWithJsonData(
@@ -71,8 +73,9 @@ public class DmiSubJobRequestHandler {
urlTemplateParameters,
jsonObjectMapper.asJsonString(subJobWriteRequest),
OperationType.CREATE,
- NO_AUTH_HEADER);
- final SubJobWriteResponse subJobWriteResponse = (SubJobWriteResponse) responseEntity.getBody();
+ authorization);
+ final SubJobWriteResponse subJobWriteResponse = jsonObjectMapper
+ .convertToValueType(responseEntity.getBody(), SubJobWriteResponse.class);
log.debug("Sub job write response: {}", subJobWriteResponse);
subJobWriteResponses.add(subJobWriteResponse);
});
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiProperties.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiProperties.java
index 5453efecd..2f60460da 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiProperties.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiProperties.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config;
+package org.onap.cps.ncmp.impl.dmi;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java
index ac7728da9..ba6bba9c5 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java
@@ -19,7 +19,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.client;
+package org.onap.cps.ncmp.impl.dmi;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA;
@@ -32,9 +32,7 @@ import java.util.Locale;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.data.models.OperationType;
-import org.onap.cps.ncmp.api.impl.config.DmiProperties;
-import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException;
-import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters;
+import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException;
import org.onap.cps.ncmp.impl.models.RequiredDmiService;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -146,6 +144,26 @@ public class DmiRestClient {
.defaultIfEmpty(NOT_SPECIFIED);
}
+ /**
+ * Retrieves the status of a data job from the DMI service.
+ *
+ * @param urlTemplateParameters The URL template parameters for the DMI data job status endpoint.
+ * @param authorization The authorization token to be added to the request headers.
+ * @return A Mono emitting the status of the data job as a String.
+ * @throws DmiClientRequestException If there is an error during the DMI request.
+ */
+ public Mono<String> getDataJobStatus(final UrlTemplateParameters urlTemplateParameters,
+ final String authorization) {
+
+ return dataServicesWebClient.get()
+ .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables())
+ .headers(httpHeaders -> configureHttpHeaders(httpHeaders, authorization))
+ .retrieve()
+ .bodyToMono(JsonNode.class)
+ .map(responseHealthStatus -> responseHealthStatus.path("status").asText())
+ .onErrorMap(throwable -> handleDmiClientException(throwable, OperationType.READ.getOperationName()));
+ }
+
private WebClient getWebClient(final RequiredDmiService requiredDmiService) {
return requiredDmiService.equals(RequiredDmiService.DATA) ? dataServicesWebClient : modelServicesWebClient;
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameOrganizer.java
index 67880648b..37e982d8c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceNameOrganizer.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils;
+package org.onap.cps.ncmp.impl.dmi;
import java.util.Collection;
import java.util.HashMap;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/DmiServiceUrlTemplateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java
index b89b7b322..e7dbea83f 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/DmiServiceUrlTemplateBuilder.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils.url.builder;
+package org.onap.cps.ncmp.impl.dmi;
import java.util.Collections;
import java.util.HashMap;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfiguration.java
index be46105d1..c176e4022 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfiguration.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config;
+package org.onap.cps.ncmp.impl.dmi;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.netty.channel.ChannelOption;
@@ -28,6 +28,7 @@ import io.netty.resolver.DefaultAddressResolverGroup;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
+import org.onap.cps.ncmp.config.HttpClientConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/UrlTemplateParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java
index edf56197b..f51511116 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/url/builder/UrlTemplateParameters.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils.url.builder;
+package org.onap.cps.ncmp.impl.dmi;
import java.util.Map;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
index 2930d4f87..0ca2cd340 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* Copyright (C) 2022-2024 Nordix Foundation
* Modifications Copyright (C) 2022 Bell Canada
- * Modifications Copyright (C) 2023 TechMahindra Ltd.
+ * Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,6 +47,7 @@ import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.model.ModuleDefinition;
import org.onap.cps.spi.model.ModuleReference;
import org.onap.cps.spi.utils.CpsValidator;
+import org.onap.cps.utils.ContentType;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.stereotype.Component;
@@ -95,7 +96,7 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
public void saveCmHandleState(final String cmHandleId, final CompositeState compositeState) {
final String cmHandleJsonData = createStateJsonData(jsonObjectMapper.asJsonString(compositeState));
cpsDataService.updateDataNodeAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- getXPathForCmHandleById(cmHandleId), cmHandleJsonData, OffsetDateTime.now());
+ getXPathForCmHandleById(cmHandleId), cmHandleJsonData, OffsetDateTime.now(), ContentType.JSON);
}
@Override
@@ -105,7 +106,7 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
getXPathForCmHandleById(cmHandleId),
createStateJsonData(jsonObjectMapper.asJsonString(compositeState))));
cpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- cmHandlesJsonDataMap, OffsetDateTime.now());
+ cmHandlesJsonDataMap, OffsetDateTime.now(), ContentType.JSON);
}
@Override
@@ -161,7 +162,7 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
Lists.partition(yangModelCmHandles, CMHANDLE_BATCH_SIZE)) {
final String cmHandlesJsonData = createCmHandlesJsonData(yangModelCmHandleBatch);
cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- NCMP_DMI_REGISTRY_PARENT, cmHandlesJsonData, NO_TIMESTAMP);
+ NCMP_DMI_REGISTRY_PARENT, cmHandlesJsonData, NO_TIMESTAMP, ContentType.JSON);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java
index 45922454f..34eeaccf8 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java
@@ -66,19 +66,20 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
public Collection<String> queryCmHandleIds(
final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
return executeQueries(cmHandleQueryServiceParameters,
- this::executeCpsPathQuery,
- this::queryCmHandlesByPublicProperties,
- this::executeModuleNameQuery,
+ this::executeCpsPathQuery,
+ this::queryCmHandlesByPublicProperties,
+ this::executeModuleNameQuery,
this::queryCmHandlesByTrustLevel);
}
@Override
public Collection<String> queryCmHandleIdsForInventory(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
return executeQueries(cmHandleQueryServiceParameters,
- this::queryCmHandlesByPublicProperties,
- this::queryCmHandlesByPrivateProperties,
- this::queryCmHandlesByDmiPlugin);
+ this::executeCpsPathQuery,
+ this::queryCmHandlesByPublicProperties,
+ this::queryCmHandlesByPrivateProperties,
+ this::queryCmHandlesByDmiPlugin);
}
@Override
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java
index fce285b41..e0b54d219 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java
@@ -32,7 +32,8 @@ public enum InventoryQueryConditions {
HAS_ALL_PROPERTIES("hasAllProperties"),
HAS_ALL_ADDITIONAL_PROPERTIES("hasAllAdditionalProperties"),
- CM_HANDLE_WITH_DMI_PLUGIN("cmHandleWithDmiPlugin");
+ CM_HANDLE_WITH_DMI_PLUGIN("cmHandleWithDmiPlugin"),
+ WITH_CPS_PATH("cmHandleWithCpsPath");
public static final List<String> ALL_CONDITION_NAMES = Arrays.stream(InventoryQueryConditions.values())
.map(InventoryQueryConditions::getName).collect(Collectors.toList());
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java
index 45f636784..c3973236f 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 Nordix Foundation
+ * Copyright (C) 2022-2024 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,21 +60,22 @@ public class DataSyncWatchdog {
moduleOperationsUtils.getUnsynchronizedReadyCmHandles().forEach(unSynchronizedReadyCmHandle -> {
final String cmHandleId = unSynchronizedReadyCmHandle.getId();
if (hasPushedIntoSemaphoreMap(cmHandleId)) {
- log.debug("Executing data sync on {}", cmHandleId);
+ log.info("Executing data sync on {}", cmHandleId);
final CompositeState compositeState = inventoryPersistence
.getCmHandleState(cmHandleId);
final String resourceData = moduleOperationsUtils.getResourceData(cmHandleId);
if (resourceData == null) {
- log.debug("Error retrieving resource data for Cm-Handle: {}", cmHandleId);
+ log.error("Error retrieving resource data for Cm-Handle: {}", cmHandleId);
} else {
cpsDataService.saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId,
resourceData, OffsetDateTime.now());
setSyncStateToSynchronized().accept(compositeState);
inventoryPersistence.saveCmHandleState(cmHandleId, compositeState);
updateDataSyncSemaphoreMap(cmHandleId);
+ log.info("Data sync finished for {}", cmHandleId);
}
} else {
- log.debug("{} already processed by another instance", cmHandleId);
+ log.info("{} already processed by another instance", cmHandleId);
}
});
log.debug("No Cm-Handles currently found in READY State and Operational Sync State is UNSYNCHRONIZED");
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java
index 7d6677ca3..433c67f10 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java
@@ -25,9 +25,7 @@ import static org.onap.cps.ncmp.api.data.models.OperationType.READ;
import static org.onap.cps.ncmp.impl.models.RequiredDmiService.MODEL;
import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -35,11 +33,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
-import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
-import org.onap.cps.ncmp.api.impl.config.DmiProperties;
-import org.onap.cps.ncmp.api.impl.utils.url.builder.DmiServiceUrlTemplateBuilder;
-import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters;
import org.onap.cps.ncmp.api.inventory.models.YangResource;
+import org.onap.cps.ncmp.impl.dmi.DmiProperties;
+import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
+import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.ncmp.impl.models.DmiRequestBody;
import org.onap.cps.spi.model.ModuleReference;
@@ -126,8 +124,7 @@ public class DmiModelOperations {
data.add("modules", moduleReferencesAsJson);
final JsonObject jsonRequestObject = new JsonObject();
if (!moduleSetTag.isEmpty()) {
- final JsonElement moduleSetTagAsJson = JsonParser.parseString(moduleSetTag);
- jsonRequestObject.add("moduleSetTag", moduleSetTagAsJson);
+ jsonRequestObject.addProperty("moduleSetTag", moduleSetTag);
}
jsonRequestObject.add("data", data);
jsonRequestObject.add("cmHandleProperties", toJsonObject(dmiProperties));
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreator.java
index 3ce6b9159..513751575 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreator.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCreator.java
@@ -26,12 +26,12 @@ import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.impl.utils.EventDateTimeFormatter;
import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
import org.onap.cps.ncmp.events.lcm.v1.Event;
import org.onap.cps.ncmp.events.lcm.v1.LcmEvent;
import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader;
import org.onap.cps.ncmp.events.lcm.v1.Values;
+import org.onap.cps.ncmp.impl.utils.EventDateTimeFormatter;
import org.springframework.stereotype.Component;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsService.java
index 10aebfa45..192667175 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsService.java
@@ -20,13 +20,18 @@
package org.onap.cps.ncmp.impl.inventory.sync.lcm;
-import io.micrometer.core.annotation.Timed;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.Timer;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.events.EventsPublisher;
import org.onap.cps.ncmp.events.lcm.v1.LcmEvent;
import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader;
+import org.onap.cps.ncmp.events.lcm.v1.Values;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.KafkaException;
@@ -41,8 +46,12 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor
public class LcmEventsService {
+ private static final Tag TAG_METHOD = Tag.of("method", "publishLcmEvent");
+ private static final Tag TAG_CLASS = Tag.of("class", LcmEventsService.class.getName());
+ private static final String UNAVAILABLE_CM_HANDLE_STATE = "N/A";
private final EventsPublisher<LcmEvent> eventsPublisher;
private final JsonObjectMapper jsonObjectMapper;
+ private final MeterRegistry meterRegistry;
@Value("${app.lcm.events.topic:ncmp-events}")
private String topicName;
@@ -51,24 +60,58 @@ public class LcmEventsService {
private boolean notificationsEnabled;
/**
- * Publish the LcmEvent with header to the public topic.
+ * Publishes an LCM event to the dedicated topic with optional notification headers.
+ * Capture and log KafkaException If an error occurs while publishing the event to Kafka
*
- * @param cmHandleId Cm Handle Id
- * @param lcmEvent Lcm Event
- * @param lcmEventHeader Lcm Event Header
+ * @param cmHandleId Cm Handle Id associated with the LCM event
+ * @param lcmEvent The LCM event object to be published
+ * @param lcmEventHeader Optional headers associated with the LCM event
*/
- @Timed(value = "cps.ncmp.lcm.events.publish", description = "Time taken to publish a LCM event")
public void publishLcmEvent(final String cmHandleId, final LcmEvent lcmEvent, final LcmEventHeader lcmEventHeader) {
+
if (notificationsEnabled) {
+ final Timer.Sample timerSample = Timer.start(meterRegistry);
try {
final Map<String, Object> lcmEventHeadersMap =
jsonObjectMapper.convertToValueType(lcmEventHeader, Map.class);
eventsPublisher.publishEvent(topicName, cmHandleId, lcmEventHeadersMap, lcmEvent);
} catch (final KafkaException e) {
log.error("Unable to publish message to topic : {} and cause : {}", topicName, e.getMessage());
+ } finally {
+ recordMetrics(lcmEvent, timerSample);
}
} else {
log.debug("Notifications disabled.");
}
}
+
+ private void recordMetrics(final LcmEvent lcmEvent, final Timer.Sample timerSample) {
+ final List<Tag> tags = new ArrayList<>(4);
+ tags.add(TAG_CLASS);
+ tags.add(TAG_METHOD);
+
+ final String oldCmHandleState = extractCmHandleStateValue(lcmEvent.getEvent().getOldValues());
+ tags.add(Tag.of("oldCmHandleState", oldCmHandleState));
+
+ final String newCmHandleState = extractCmHandleStateValue(lcmEvent.getEvent().getNewValues());
+ tags.add(Tag.of("newCmHandleState", newCmHandleState));
+
+ timerSample.stop(Timer.builder("cps.ncmp.lcm.events.publish")
+ .description("Time taken to publish a LCM event")
+ .tags(tags)
+ .register(meterRegistry));
+ }
+
+ /**
+ * Extracts the CM handle state value from the given Values object.
+ * If the provided Values object or its CM handle state is null, returns a default value.
+ *
+ * @param values The Values object containing CM handle state information.
+ * @return The CM handle state value as a string, or a default value if null.
+ */
+ private String extractCmHandleStateValue(final Values values) {
+ return (values != null && values.getCmHandleState() != null)
+ ? values.getCmHandleState().value()
+ : UNAVAILABLE_CM_HANDLE_STATE;
+ }
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java
index 8be8ead44..c81e9b784 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java
@@ -24,10 +24,10 @@ import java.util.Collection;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
-import org.onap.cps.ncmp.api.impl.utils.url.builder.DmiServiceUrlTemplateBuilder;
-import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters;
import org.onap.cps.ncmp.api.inventory.models.TrustLevel;
+import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
+import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Scheduled;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/EventDateTimeFormatter.java
index 5dd682712..9284c0fab 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatter.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/EventDateTimeFormatter.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils;
+package org.onap.cps.ncmp.impl.utils;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java
index 554501127..6d51eb48b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java
@@ -33,7 +33,7 @@ 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.ncmp.exceptions.NcmpStartUpException;
import org.onap.cps.spi.CascadeDeleteAllowed;
import org.onap.cps.spi.exceptions.AlreadyDefinedException;
import org.onap.cps.utils.JsonObjectMapper;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java
index 259270344..780b240b6 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoader.java
@@ -30,7 +30,7 @@ import org.onap.cps.api.CpsDataService;
import org.onap.cps.api.CpsDataspaceService;
import org.onap.cps.api.CpsModuleService;
import org.onap.cps.ncmp.api.data.models.DatastoreType;
-import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException;
+import org.onap.cps.ncmp.exceptions.NcmpStartUpException;
import org.onap.cps.spi.exceptions.AlreadyDefinedException;
import org.springframework.stereotype.Service;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java
index 67128bd15..8d3190eb0 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java
@@ -27,8 +27,8 @@ import java.util.Map;
import java.util.UUID;
import lombok.Builder;
import org.apache.commons.lang3.StringUtils;
-import org.onap.cps.ncmp.api.impl.utils.EventDateTimeFormatter;
-import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext;
+import org.onap.cps.ncmp.config.CpsApplicationContext;
+import org.onap.cps.ncmp.impl.utils.EventDateTimeFormatter;
import org.onap.cps.utils.JsonObjectMapper;
@Builder
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/TopicValidator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/TopicValidator.java
index a7ad86cda..07da7f76a 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/TopicValidator.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/TopicValidator.java
@@ -23,7 +23,7 @@ package org.onap.cps.ncmp.utils.events;
import java.util.regex.Pattern;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
-import org.onap.cps.ncmp.exceptions.InvalidTopicException;
+import org.onap.cps.ncmp.api.exceptions.InvalidTopicException;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class TopicValidator {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/DmiSubJobRequestHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/DmiSubJobRequestHandlerSpec.groovy
deleted file mode 100644
index 6dcd022c0..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/DmiSubJobRequestHandlerSpec.groovy
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.onap.cps.ncmp.api.impl
-
-import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.ncmp.api.data.models.OperationType
-import org.onap.cps.ncmp.api.datajobs.models.DataJobMetadata
-import org.onap.cps.ncmp.api.datajobs.models.DmiWriteOperation
-import org.onap.cps.ncmp.api.datajobs.models.ProducerKey
-import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteResponse
-import org.onap.cps.ncmp.api.impl.client.DmiRestClient
-import org.onap.cps.ncmp.api.impl.config.DmiProperties
-import org.onap.cps.ncmp.impl.datajobs.DmiSubJobRequestHandler
-import org.onap.cps.ncmp.impl.models.RequiredDmiService
-import org.onap.cps.utils.JsonObjectMapper
-import org.springframework.http.HttpStatus
-import org.springframework.http.ResponseEntity
-import spock.lang.Specification
-
-class DmiSubJobRequestHandlerSpec extends Specification {
-
- def mockDmiRestClient = Mock(DmiRestClient)
- def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
- def mockDmiProperties = Mock(DmiProperties)
- def static NO_AUTH = null
- def objectUnderTest = new DmiSubJobRequestHandler(mockDmiRestClient, mockDmiProperties, jsonObjectMapper)
-
- def 'Send a sub-job request to the DMI Plugin.'() {
- given: 'a data job id, metadata and a map of producer keys and write operations to create a request'
- def dataJobId = 'some-job-id'
- def dataJobMetadata = new DataJobMetadata('', '', '')
- def dmiWriteOperation = new DmiWriteOperation('', '', '', null, '', [:])
- def dmiWriteOperationsPerProducerKey = [new ProducerKey('', ''): [dmiWriteOperation]]
- def response = new ResponseEntity<>(new SubJobWriteResponse('my-sub-job-id', '', ''), HttpStatus.OK)
- when: 'sending request to DMI invoked'
- objectUnderTest.sendRequestsToDmi(dataJobId, dataJobMetadata, dmiWriteOperationsPerProducerKey)
- then: 'the dmi rest client is called'
- 1 * mockDmiRestClient.synchronousPostOperationWithJsonData(RequiredDmiService.DATA, _, _, OperationType.CREATE, NO_AUTH) >> response
- and: 'the result contains the expected sub-job write responses'
- def result = response.body
- assert result.subJobId() == 'my-sub-job-id'
- }
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/OpenTelemetryCmNotificationSubscriptionConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/OpenTelemetryCmNotificationSubscriptionConfigSpec.groovy
deleted file mode 100644
index 07395cf5b..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/OpenTelemetryCmNotificationSubscriptionConfigSpec.groovy
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2024 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 io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter
-import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
-import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler
-import org.spockframework.spring.SpringBean
-import org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryCustomizer
-import spock.lang.Shared
-import spock.lang.Specification
-
-class OpenTelemetryConfigSpec extends Specification{
-
- @Shared
- @SpringBean
- OpenTelemetryConfig openTelemetryConfig = new OpenTelemetryConfig()
-
- def setupSpec() {
- openTelemetryConfig.tracingExporterEndpointUrl="http://tracingExporterEndpointUrl"
- openTelemetryConfig.jaegerRemoteSamplerUrl="http://jaegerremotesamplerurl"
- openTelemetryConfig.serviceId ="cps-application"
- }
-
- def 'OpenTelemetryConfig Construction.'() {
- expect: 'the system can create an instance'
- new OpenTelemetryConfig() != null
- }
-
- def 'OTLP Exporter creation with Grpc protocol'(){
- when: 'an OTLP exporter is created'
- def result = openTelemetryConfig.createOtlpExporterGrpc()
- then: 'an OTLP Exporter is created'
- assert result instanceof OtlpGrpcSpanExporter
- }
-
- def 'OTLP Exporter creation with HTTP protocol'(){
- when: 'an OTLP exporter is created'
- def result = openTelemetryConfig.createOtlpExporterHttp()
- then: 'an OTLP Exporter is created'
- assert result instanceof OtlpHttpSpanExporter
- and:
- assert result.builder.endpoint=="http://tracingExporterEndpointUrl"
- }
-
- def 'Jaeger Remote Sampler Creation'(){
- when: 'an OTLP exporter is created'
- def result = openTelemetryConfig.createJaegerRemoteSampler()
- then: 'an OTLP Exporter is created'
- assert result instanceof JaegerRemoteSampler
- and:
- assert result.delegate.type=="remoteSampling"
- and:
- assert result.delegate.url.toString().startsWith("http://jaegerremotesamplerurl")
- }
-
- def 'Skipping Acutator endpoints'(){
- when: 'an OTLP exporter is created'
- def result = openTelemetryConfig.skipActuatorEndpointsFromObservation()
- then: 'an OTLP Exporter is created'
- assert result instanceof ObservationRegistryCustomizer
- }
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeBaseSpec.groovy
deleted file mode 100644
index 2e0469430..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeBaseSpec.groovy
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * ============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.utils
-
-import org.onap.cps.spi.model.DataNodeBuilder
-import spock.lang.Specification
-
-import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME
-
-class DataNodeBaseSpec extends Specification {
-
- def leaves1 = [status:'PENDING', cmHandleId:'CMHandle3', details:'Subscription forwarded to dmi plugin'] as Map
- def dataNode1 = createDataNodeWithLeaves(leaves1)
-
- def leaves2 = [status:'ACCEPTED', cmHandleId:'CMHandle2', details:''] as Map
- def dataNode2 = createDataNodeWithLeaves(leaves2)
-
- def leaves3 = [status:'REJECTED', cmHandleId:'CMHandle1', details:'Cm handle does not exist'] as Map
- def dataNode3 = createDataNodeWithLeaves(leaves3)
-
- def leaves4 = [datastore:'passthrough-running'] as Map
- def dataNode4 = createDataNodeWithLeavesAndChildDataNodes(leaves4, [dataNode1, dataNode2, dataNode3])
-
- static def createDataNodeWithLeaves(leaves) {
- return new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME)
- .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription')
- .withLeaves(leaves).build()
- }
-
- static def createDataNodeWithLeavesAndChildDataNodes(leaves, dataNodes) {
- return new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME)
- .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription')
- .withLeaves(leaves).withChildDataNodes(dataNodes)
- .build()
- }
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeHelperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeHelperSpec.groovy
deleted file mode 100644
index 9481613d4..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeHelperSpec.groovy
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * ============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.utils
-
-import org.onap.cps.spi.model.DataNodeBuilder
-
-import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME
-
-class DataNodeHelperSpec extends DataNodeBaseSpec {
-
- def 'Get data node leaves as expected from a nested data node.'() {
- given: 'a nested data node'
- def dataNode = new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME)
- .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription')
- .withLeaves([clientID:'SCO-9989752', isTagged:false, subscriptionName:'cm-subscription-001'])
- .withChildDataNodes([dataNode4]).build()
- when: 'the nested data node is flatten and retrieves the leaves '
- def result = DataNodeHelper.getDataNodeLeaves([dataNode])
- then: 'the result list size is 5'
- result.size() == 5
- and: 'all the leaves result list are equal to given leaves of data nodes'
- result[0] == [clientID:'SCO-9989752', isTagged:false, subscriptionName:'cm-subscription-001']
- result[1] == [datastore:'passthrough-running']
- result[2] == [status:'PENDING', cmHandleId:'CMHandle3', details:'Subscription forwarded to dmi plugin']
- result[3] == [status:'ACCEPTED', cmHandleId:'CMHandle2', details:'']
- result[4] == [status:'REJECTED', cmHandleId:'CMHandle1', details:'Cm handle does not exist']
- }
-
- def 'Get cm handle id to status as expected from a nested data node.'() {
- given: 'a nested data node'
- def dataNode = new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME)
- .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription')
- .withLeaves([clientID:'SCO-9989752', isTagged:false, subscriptionName:'cm-subscription-001'])
- .withChildDataNodes([dataNode4]).build()
- and: 'the nested data node is flatten and retrieves the leaves '
- def leaves = DataNodeHelper.getDataNodeLeaves([dataNode])
- when:'cm handle id to status is retrieved'
- def result = DataNodeHelper.cmHandleIdToStatusAndDetailsAsMap(leaves)
- then: 'the result list size is 3'
- result.size() == 3
- and: 'the result contains expected values'
- result == [
- CMHandle3: [details:'Subscription forwarded to dmi plugin',status:'PENDING'] as Map,
- CMHandle2: [details:'',status:'ACCEPTED'] as Map,
- CMHandle1: [details:'Cm handle does not exist',status:'REJECTED'] as Map
- ] as Map
-
- }
-
- def 'Get cm handle id to status map as expected from a nested data node.'() {
- given: 'a nested data node'
- def dataNode = new DataNodeBuilder().withDataspace(NCMP_DATASPACE_NAME)
- .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription')
- .withLeaves([clientID:'SCO-9989752', isTagged:false, subscriptionName:'cm-subscription-001'])
- .withChildDataNodes([dataNode4]).build()
- when:'cm handle id to status is being extracted'
- def result = DataNodeHelper.cmHandleIdToStatusAndDetailsAsMapFromDataNode([dataNode]);
- then: 'the result list size is 3'
- result.size() == 3
- and: 'the result contains expected values'
- result == [
- CMHandle3: [details:'Subscription forwarded to dmi plugin',status:'PENDING'] as Map,
- CMHandle2: [details:'',status:'ACCEPTED'] as Map,
- CMHandle1: [details:'Cm handle does not exist',status:'REJECTED'] as Map
- ] as Map
- }
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContextSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/CpsApplicationContextSpec.groovy
index ee117160c..215ea6c21 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContextSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/CpsApplicationContextSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils.context
+package org.onap.cps.ncmp.config
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.utils.JsonObjectMapper
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/config/HttpClientConfigurationSpec.groovy
index 228f41277..1d3b22fb7 100644
--- 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/config/HttpClientConfigurationSpec.groovy
@@ -18,29 +18,28 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config
+package org.onap.cps.ncmp.config
+
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 spock.lang.Specification
@SpringBootTest
@ContextConfiguration(classes = [HttpClientConfiguration])
-@EnableConfigurationProperties(HttpClientConfiguration.class)
-@TestPropertySource(properties = ["ncmp.dmi.httpclient.data-services.readTimeoutInSeconds=789", "ncmp.dmi.httpclient.model-services.maximumConnectionsTotal=111"])
+@EnableConfigurationProperties(HttpClientConfiguration)
class HttpClientConfigurationSpec extends Specification {
@Autowired
- private HttpClientConfiguration httpClientConfiguration
+ HttpClientConfiguration httpClientConfiguration
def 'Test http client configuration properties of data with custom and default values'() {
expect: 'properties are populated correctly for data'
with(httpClientConfiguration.dataServices) {
assert connectionTimeoutInSeconds == 123
- assert readTimeoutInSeconds == 789
+ assert readTimeoutInSeconds == 33
assert writeTimeoutInSeconds == 30
assert maximumConnectionsTotal == 100
assert pendingAcquireMaxCount == 22
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/KafkaConfigSpec.groovy
index 4d3fd6616..9e1649ef9 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfigSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/KafkaConfigSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config.kafka
+package org.onap.cps.ncmp.config
import io.cloudevents.CloudEvent
import io.cloudevents.kafka.CloudEventDeserializer
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/OpenTelemetryConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/OpenTelemetryConfigSpec.groovy
new file mode 100644
index 000000000..cbff73113
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/OpenTelemetryConfigSpec.groovy
@@ -0,0 +1,113 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.config
+
+import io.micrometer.observation.ObservationPredicate
+import io.micrometer.observation.ObservationRegistry
+import io.micrometer.observation.ObservationRegistry.ObservationConfig
+import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter
+import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
+import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.http.server.observation.ServerRequestObservationContext
+import org.springframework.mock.web.MockHttpServletRequest
+import org.springframework.util.AntPathMatcher
+import spock.lang.Specification
+
+@SpringBootTest(classes = [OpenTelemetryConfig])
+class OpenTelemetryConfigSpec extends Specification {
+
+ def objectUnderTest
+
+ @Value('${cps.tracing.exporter.endpoint}')
+ def tracingExporterEndpointUrl
+
+ @Value('${cps.tracing.sampler.jaeger_remote.endpoint}')
+ def jaegerRemoteSamplerUrl
+
+ def setup() {
+ objectUnderTest = new OpenTelemetryConfig(
+ serviceId: 'sample-app',
+ tracingExporterEndpointUrl: tracingExporterEndpointUrl,
+ jaegerRemoteSamplerUrl: jaegerRemoteSamplerUrl,
+ excludedObservationNames: ['excluded-task-name'])
+ }
+
+ def 'OTLP exporter creation with Grpc protocol'() {
+ when: 'an OTLP exporter is created'
+ def result = objectUnderTest.createOtlpExporterGrpc()
+ then: 'expected an instance of OtlpGrpcSpanExporter'
+ assert result instanceof OtlpGrpcSpanExporter
+ }
+
+ def 'OTLP exporter creation with HTTP protocol'() {
+ when: 'an OTLP exporter is created'
+ def result = objectUnderTest.createOtlpExporterHttp()
+ then: 'an OTLP Exporter is created'
+ assert result instanceof OtlpHttpSpanExporter
+ and: 'the endpoint is correctly set'
+ assert result.builder.endpoint == 'http://exporter-test-url'
+ }
+
+ def 'Jaeger Remote Sampler Creation'() {
+ when: 'a Jaeger remote sampler is created'
+ def result = objectUnderTest.createJaegerRemoteSampler()
+ then: 'a Jaeger remote sampler is created'
+ assert result instanceof JaegerRemoteSampler
+ and: 'the sampler type is correct'
+ assert result.delegate.type == 'remoteSampling'
+ and: 'the sampler endpoint is correctly set'
+ assert result.delegate.url.toString().startsWith('http://jaeger-remote-test-url')
+ }
+
+ def 'Skipping actuator endpoints'() {
+ given: 'a mocked observation registry and config'
+ def observationRegistry = Mock(ObservationRegistry.class)
+ def observationConfig = Mock(ObservationConfig.class)
+ observationRegistry.observationConfig() >> observationConfig
+ when: 'an observation registry customizer is created and applied'
+ def result = objectUnderTest.skipActuatorEndpointsFromObservation()
+ result.customize(observationRegistry)
+ then: 'the observation predicate is set correctly'
+ 1 * observationConfig.observationPredicate(_) >> { ObservationPredicate observationPredicate ->
+ def mockedHttpServletRequest = new MockHttpServletRequest(_ as String, requestUrl)
+ def serverRequestObservationContext = new ServerRequestObservationContext(mockedHttpServletRequest, null)
+ and: 'expected predicate for endpoint'
+ assert observationPredicate.test('some-name', serverRequestObservationContext) == expectedPredicate
+ }
+ where: 'the following parameters are used'
+ scenario | requestUrl || expectedPredicate
+ 'an actuator' | '/actuator' || false
+ 'a non actuator' | '/some-api' || true
+ }
+
+ def 'Observation predicate is configured to filter out excluded tasks by name'() {
+ when: 'a path matcher and observation predicate'
+ def observationPredicate = objectUnderTest.observationPredicate(new AntPathMatcher('/'))
+ then: 'a task name is provided'
+ assert observationPredicate.test(taskName, null) == expectedPredicate
+ where: 'the following parameters are used'
+ taskName || expectedPredicate
+ 'excluded-task-name' || false
+ 'non-excluded-task-name' || true
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/EventsFacadeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/EventsFacadeSpec.groovy
deleted file mode 100644
index bc2df10ce..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/EventsFacadeSpec.groovy
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (c) 2024 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.impl.cmnotificationsubscription
-
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi.DmiInEventProducer
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp.NcmpOutEventProducer
-import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent
-import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.DmiInEvent
-import spock.lang.Specification
-
-class EventsFacadeSpec extends Specification {
-
- def mockCmNotificationSubscriptionNcmpOutEventProducer = Mock(NcmpOutEventProducer)
- def mockCmNotificationSubscriptionDmiInEventProducer = Mock(DmiInEventProducer)
-
- def objectUnderTest = new EventsFacade(mockCmNotificationSubscriptionNcmpOutEventProducer,
- mockCmNotificationSubscriptionDmiInEventProducer)
-
- def 'Publish cm notification subscription ncmp out event'() {
- given: 'an ncmp out event'
- def ncmpOutEvent = new NcmpOutEvent()
- when: 'the method to publish cm notification subscription ncmp out event is called'
- objectUnderTest.publishNcmpOutEvent("some-id",
- "some-event", ncmpOutEvent, true)
- then: 'the parameters is delegated to the correct method once'
- 1 * mockCmNotificationSubscriptionNcmpOutEventProducer.publishNcmpOutEvent(
- "some-id", "some-event", ncmpOutEvent, true)
- }
-
- def 'Publish cm notification subscription dmi in event'() {
- given: 'a dmi in event'
- def dmiInEvent = new DmiInEvent()
- when: 'the method to publish cm notification subscription ncmp out event is called'
- objectUnderTest.publishDmiInEvent("some-id",
- "some-dmi", "some-event", dmiInEvent)
- then: 'the parameters is delegated to the correct method once'
- 1 * mockCmNotificationSubscriptionDmiInEventProducer.publishDmiInEvent("some-id",
- "some-dmi", "some-event", dmiInEvent)
- }
-} \ No newline at end of file
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/MappersFacadeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/MappersFacadeSpec.groovy
deleted file mode 100644
index 79b9ad578..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/MappersFacadeSpec.groovy
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2024 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.impl.cmnotificationsubscription
-
-
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi.DmiInEventMapper
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp.NcmpOutEventMapper
-import spock.lang.Specification
-
-class MappersFacadeSpec extends Specification{
-
- def mockCmNotificationDmiInEventMapper = Mock(DmiInEventMapper)
- def mockCmNotificationNcmpOutEventMapper = Mock(NcmpOutEventMapper)
-
- def objectUnderTest = new MappersFacade(mockCmNotificationDmiInEventMapper,
- mockCmNotificationNcmpOutEventMapper)
-
- def 'Get cm notification subscription DMI in event'() {
- given: 'a list of predicates'
- def testListOfPredicates = []
- when: 'method to create a cm notification subscription dmi in event is called with predicates'
- objectUnderTest.toDmiInEvent(testListOfPredicates)
- then: 'the parameters is delegated to the correct dmi in event mapper method'
- 1 * mockCmNotificationDmiInEventMapper.toDmiInEvent(testListOfPredicates)
- }
-
- def 'Get cm notification subscription ncmp out event'() {
- given: 'a subscription details map'
- def testSubscriptionDetailsMap = [:]
- when: 'method to create cm notification subscription ncmp out event is called with the following parameters'
- objectUnderTest.toNcmpOutEvent("test-id", testSubscriptionDetailsMap)
- then: 'the parameters is delegated to the correct ncmp out event mapper method'
- 1 * mockCmNotificationNcmpOutEventMapper.toNcmpOutEvent("test-id",
- testSubscriptionDetailsMap)
- }
-
- def 'Get cm notification subscription ncmp out event for a rejected request'() {
- given: 'a list of target filters'
- def testRejectedTargetFilters = []
- when: 'method to create cm notification subscription ncmp out event is called with the following parameters'
- objectUnderTest.toNcmpOutEventForRejectedRequest(
- "test-id", testRejectedTargetFilters)
- then: 'the parameters is delegated to the correct ncmp out event mapper method'
- 1 * mockCmNotificationNcmpOutEventMapper.toNcmpOutEventForRejectedRequest(
- "test-id", testRejectedTargetFilters)
- }
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/cache/DmiCacheHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/cache/DmiCacheHandlerSpec.groovy
index b335843bb..791a15460 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/cache/DmiCacheHandlerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/cache/DmiCacheHandlerSpec.groovy
@@ -24,7 +24,6 @@ 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.kafka.MessagingBaseSpec
import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.CmSubscriptionStatus
import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionDetails
import org.onap.cps.ncmp.impl.cmnotificationsubscription.utils.CmSubscriptionPersistenceService
@@ -32,6 +31,7 @@ import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.client_to_ncmp.Nc
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.ncmp.utils.TestUtils
+import org.onap.cps.ncmp.utils.events.MessagingBaseSpec
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
@@ -65,17 +65,34 @@ class DmiCacheHandlerSpec extends MessagingBaseSpec {
initialiseMockInventoryPersistenceResponses()
}
- def 'Load CM subscription event to cache'() {
- given: 'a valid subscription event with Id'
+ def 'Load CM subscription event to cache with predicates'() {
+ given: 'a subscription event with id'
def subscriptionId = ncmpInEvent.getData().getSubscriptionId()
and: 'list of predicates'
def predicates = ncmpInEvent.getData().getPredicates()
- when: 'a valid event object loaded in cache'
+ when: 'subscription is loaded to cache with predicates'
objectUnderTest.add(subscriptionId, predicates)
- then: 'the cache contains the correct entry with #subscriptionId subscription ID'
+ then: 'the number of entries in cache is correct'
+ assert testCache.size() == 1
+ and: 'the cache contains the correct entries'
assert testCache.containsKey(subscriptionId)
}
+ def 'Load CM subscription event to cache with dmi subscription details per dmi'() {
+ given: 'a subscription event with id'
+ def subscriptionId = ncmpInEvent.getData().getSubscriptionId()
+ and: 'dmi subscription details per dmi'
+ def dmiSubscriptionsPerDmi = [:]
+ when: 'subscription is loaded to cache with dmi subscription details per dmi'
+ objectUnderTest.add(subscriptionId, dmiSubscriptionsPerDmi)
+ then: 'the number of entries in cache is correct'
+ assert testCache.size() == 1
+ and: 'the cache contains the correct entries'
+ assert testCache.containsKey(subscriptionId)
+ and: 'the entry for the subscription ID matches the provided DMI subscription details'
+ assert testCache.get(subscriptionId) == dmiSubscriptionsPerDmi
+ }
+
def 'Get cache entry via subscription id'() {
given: 'the cache contains value for some-id'
testCache.put('some-id',[:])
@@ -157,7 +174,7 @@ class DmiCacheHandlerSpec extends MessagingBaseSpec {
def subscriptionId = ncmpInEvent.getData().getSubscriptionId()
objectUnderTest.add(subscriptionId, predicates)
when: 'subscription status per dmi is updated in cache'
- objectUnderTest.updateDmiSubscriptionStatusPerDmi(subscriptionId,'dmi-1', CmSubscriptionStatus.ACCEPTED)
+ objectUnderTest.updateDmiSubscriptionStatus(subscriptionId,'dmi-1', CmSubscriptionStatus.ACCEPTED)
then: 'verify status has been updated in cache'
def predicate = testCache.get(subscriptionId)
assert predicate.get('dmi-1').cmSubscriptionStatus == CmSubscriptionStatus.ACCEPTED
@@ -180,7 +197,7 @@ class DmiCacheHandlerSpec extends MessagingBaseSpec {
def subscriptionId = ncmpInEvent.getData().getSubscriptionId()
objectUnderTest.add(subscriptionId, predicates)
when: 'subscription is persisted in database'
- objectUnderTest.removeFromDatabasePerDmi(subscriptionId,'dmi-1')
+ objectUnderTest.removeFromDatabase(subscriptionId,'dmi-1')
then: 'persistence service is called the correct number of times per dmi'
4 * mockCmSubscriptionPersistenceService.removeCmSubscription(_,_,_,subscriptionId)
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/cmavc/CmAvcEventConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/cmavc/CmAvcEventConsumerSpec.groovy
index 98cc383e7..06651be91 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/cmavc/CmAvcEventConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/cmavc/CmAvcEventConsumerSpec.groovy
@@ -28,16 +28,15 @@ import io.cloudevents.kafka.impl.KafkaHeaders
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.clients.consumer.KafkaConsumer
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
import org.onap.cps.ncmp.events.avc1_0_0.AvcEvent
import org.onap.cps.ncmp.utils.TestUtils
+import org.onap.cps.ncmp.utils.events.MessagingBaseSpec
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.annotation.DirtiesContext
import org.testcontainers.spock.Testcontainers
-
import java.time.Duration
import static org.onap.cps.ncmp.utils.events.CloudEventMapper.toTargetEvent
@@ -86,8 +85,8 @@ class CmAvcEventConsumerSpec extends MessagingBaseSpec {
def convertedAvcEvent = toTargetEvent(cloudEvent, AvcEvent.class)
and: 'we have correct headers forwarded where correlation id matches'
assert KafkaHeaders.getParsedKafkaHeader(record.headers(), 'ce_correlationid') == 'test-cmhandle1'
- and: 'event id differs(as per requirement) between consumed and forwarded'
- assert KafkaHeaders.getParsedKafkaHeader(record.headers(), 'ce_id') != 'sample-eventid'
+ and: 'event id is same between consumed and forwarded'
+ assert KafkaHeaders.getParsedKafkaHeader(record.headers(), 'ce_id') == 'sample-eventid'
and: 'the event payload still matches'
assert testEventSent == convertedAvcEvent
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiCmSubscriptionDetailsPerDmiMapperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiCmSubscriptionDetailsPerDmiMapperSpec.groovy
new file mode 100644
index 000000000..5d74f45bb
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiCmSubscriptionDetailsPerDmiMapperSpec.groovy
@@ -0,0 +1,52 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.impl.cmnotificationsubscription.dmi
+
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionKey
+import spock.lang.Specification
+
+class DmiCmSubscriptionDetailsPerDmiMapperSpec extends Specification {
+
+ def objectUnderTest = new DmiCmSubscriptionDetailsPerDmiMapper()
+
+ def 'Check for grouping of Dmi Subscription Details'() {
+ given: 'details in the form of datastore , cmhandle and xpath'
+ def subscribersPerDmi = [
+ 'dmi-1': [
+ new DmiCmSubscriptionKey('ncmp-datastore:passthrough-operational', 'ch-1', '/a/b'),
+ new DmiCmSubscriptionKey('ncmp-datastore:passthrough-operational', 'ch-2', '/a/b')
+ ],
+ 'dmi-2': [
+ new DmiCmSubscriptionKey('ncmp-datastore:passthrough-running', 'ch-3', '/c/d'),
+ new DmiCmSubscriptionKey('ncmp-datastore:passthrough-running', 'ch-3', '/e/f')
+ ]
+ ]
+ when: 'we try to map the values based on datastore and xpath'
+ def result = objectUnderTest.toDmiCmSubscriptionsPerDmi(subscribersPerDmi)
+ then: 'the mapped values are grouped as expected for dmi-1'
+ assert result['dmi-1'].dmiCmSubscriptionPredicates.size() == 1
+ assert result['dmi-1'].dmiCmSubscriptionPredicates[0].targetCmHandleIds.containsAll(['ch-1', 'ch-2'])
+ and: 'similarly for dmi-2'
+ assert result['dmi-2'].dmiCmSubscriptionPredicates.size() == 2
+ assert result['dmi-2'].dmiCmSubscriptionPredicates[0].targetCmHandleIds.contains('ch-3')
+ assert result['dmi-2'].dmiCmSubscriptionPredicates[1].targetCmHandleIds.contains('ch-3')
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumerSpec.groovy
index 44e24042a..bcf878087 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiOutEventConsumerSpec.groovy
@@ -28,13 +28,13 @@ 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.kafka.MessagingBaseSpec
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.EventsFacade
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.MappersFacade
import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp.NcmpOutEventMapper
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp.NcmpOutEventProducer
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.dmi_to_ncmp.Data
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.dmi_to_ncmp.DmiOutEvent
import org.onap.cps.ncmp.utils.TestUtils
+import org.onap.cps.ncmp.utils.events.MessagingBaseSpec
import org.onap.cps.utils.JsonObjectMapper
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
@@ -53,10 +53,10 @@ class DmiOutEventConsumerSpec extends MessagingBaseSpec {
ObjectMapper objectMapper
def mockDmiCacheHandler = Mock(DmiCacheHandler)
- def mockEventsHandler = Mock(EventsFacade)
- def mockMappersHandler = Mock(MappersFacade)
+ def mockNcmpOutEventProducer = Mock(NcmpOutEventProducer)
+ def mockNcmpOutEventMapper = Mock(NcmpOutEventMapper)
- def objectUnderTest = new DmiOutEventConsumer(mockDmiCacheHandler, mockEventsHandler, mockMappersHandler)
+ def objectUnderTest = new DmiOutEventConsumer(mockDmiCacheHandler, mockNcmpOutEventProducer, mockNcmpOutEventMapper)
def logger = Spy(ListAppender<ILoggingEvent>)
void setup() {
@@ -103,13 +103,13 @@ class DmiOutEventConsumerSpec extends MessagingBaseSpec {
when: 'the event is consumed'
objectUnderTest.consumeDmiOutEvent(consumerRecord)
then: 'correct number of calls to cache'
- expectedCacheCalls * mockDmiCacheHandler.updateDmiSubscriptionStatusPerDmi('sub-1','test-dmi-plugin-name', subscriptionStatus)
+ expectedCacheCalls * mockDmiCacheHandler.updateDmiSubscriptionStatus('sub-1','test-dmi-plugin-name', subscriptionStatus)
and: 'correct number of calls to persist cache'
expectedPersistenceCalls * mockDmiCacheHandler.persistIntoDatabasePerDmi('sub-1','test-dmi-plugin-name')
and: 'correct number of calls to map the ncmp out event'
- 1 * mockMappersHandler.toNcmpOutEvent('sub-1', _)
+ 1 * mockNcmpOutEventMapper.toNcmpOutEvent('sub-1', _)
and: 'correct number of calls to publish the ncmp out event to client'
- 1 * mockEventsHandler.publishNcmpOutEvent('sub-1', 'subscriptionCreateResponse', _, false)
+ 1 * mockNcmpOutEventProducer.publishNcmpOutEvent('sub-1', 'subscriptionCreateResponse', _, false)
where: 'the following parameters are used'
scenario | subscriptionStatus | statusCode || expectedCacheCalls | expectedPersistenceCalls
'Accepted Status' | ACCEPTED | '1' || 1 | 1
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImplSpec.groovy
index caefdeea1..f902c6048 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/CmSubscriptionHandlerImplSpec.groovy
@@ -21,16 +21,20 @@
package org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp
import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.EventsFacade
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.MappersFacade
import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi.DmiCmSubscriptionDetailsPerDmiMapper
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi.DmiInEventMapper
+import org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi.DmiInEventProducer
import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionDetails
import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionPredicate
import org.onap.cps.ncmp.impl.cmnotificationsubscription.utils.CmSubscriptionPersistenceService
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.client_to_ncmp.NcmpInEvent
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.DmiInEvent
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.ncmp.utils.TestUtils
+import org.onap.cps.spi.model.DataNode
import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Specification
@@ -41,15 +45,19 @@ import static org.onap.cps.ncmp.impl.cmnotificationsubscription.models.CmSubscri
class CmSubscriptionHandlerImplSpec extends Specification {
def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
- def mockCmSubscriptionPersistenceService = Mock(CmSubscriptionPersistenceService);
- def mockCmSubscriptionComparator = Mock(CmSubscriptionComparator);
- def mockMappersFacade = Mock(MappersFacade);
- def mockEventsFacade = Mock(EventsFacade);
- def mockDmiCacheHandler = Mock(DmiCacheHandler);
+ def mockCmSubscriptionPersistenceService = Mock(CmSubscriptionPersistenceService)
+ def mockCmSubscriptionComparator = Mock(CmSubscriptionComparator)
+ def mockNcmpOutEventMapper = Mock(NcmpOutEventMapper)
+ def mockDmiInEventMapper = Mock(DmiInEventMapper)
+ def dmiCmSubscriptionDetailsPerDmiMapper = new DmiCmSubscriptionDetailsPerDmiMapper()
+ def mockNcmpOutEventProducer = Mock(NcmpOutEventProducer)
+ def mockDmiInEventProducer = Mock(DmiInEventProducer)
+ def mockDmiCacheHandler = Mock(DmiCacheHandler)
+ def mockInventoryPersistence = Mock(InventoryPersistence)
def objectUnderTest = new CmSubscriptionHandlerImpl(mockCmSubscriptionPersistenceService,
- mockCmSubscriptionComparator, mockMappersFacade,
- mockEventsFacade, mockDmiCacheHandler)
+ mockCmSubscriptionComparator, mockNcmpOutEventMapper, mockDmiInEventMapper, dmiCmSubscriptionDetailsPerDmiMapper,
+ mockNcmpOutEventProducer, mockDmiInEventProducer, mockDmiCacheHandler, mockInventoryPersistence)
def testDmiSubscriptionsPerDmi = ["dmi-1": new DmiCmSubscriptionDetails([], PENDING)]
@@ -68,17 +76,16 @@ class CmSubscriptionHandlerImplSpec extends Specification {
1 * mockCmSubscriptionComparator.getNewDmiSubscriptionPredicates(_) >> testListOfDeltaPredicates
and: 'the DMI in event mapper returns cm notification subscription event'
def testDmiInEvent = new DmiInEvent()
- 1 * mockMappersFacade
- .toDmiInEvent(testListOfDeltaPredicates) >> testDmiInEvent
+ 1 * mockDmiInEventMapper.toDmiInEvent(testListOfDeltaPredicates) >> testDmiInEvent
when: 'the valid and unique event is consumed'
objectUnderTest.processSubscriptionCreateRequest(subscriptionId, predicates)
then: 'the subscription cache handler is called once'
1 * mockDmiCacheHandler.add('test-id', _)
and: 'the events handler method to publish DMI event is called correct number of times with the correct parameters'
- testDmiSubscriptionsPerDmi.size() * mockEventsFacade.publishDmiInEvent(
+ testDmiSubscriptionsPerDmi.size() * mockDmiInEventProducer.publishDmiInEvent(
"test-id", "dmi-1", "subscriptionCreateRequest", testDmiInEvent)
and: 'we schedule to send the response after configured time from the cache'
- 1 * mockEventsFacade.publishNcmpOutEvent('test-id', 'subscriptionCreateResponse', null, true)
+ 1 * mockNcmpOutEventProducer.publishNcmpOutEvent('test-id', 'subscriptionCreateResponse', null, true)
}
def 'Consume valid and Overlapping Cm Notification Subscription NcmpIn Event'() {
@@ -96,9 +103,9 @@ class CmSubscriptionHandlerImplSpec extends Specification {
then: 'the subscription cache handler is called once'
1 * mockDmiCacheHandler.add('test-id', _)
and: 'the subscription details are updated in the cache'
- 1 * mockDmiCacheHandler.updateDmiSubscriptionStatusPerDmi('test-id', _, ACCEPTED)
+ 1 * mockDmiCacheHandler.updateDmiSubscriptionStatus('test-id', _, ACCEPTED)
and: 'we schedule to send the response after configured time from the cache'
- 1 * mockEventsFacade.publishNcmpOutEvent('test-id', 'subscriptionCreateResponse', null, true)
+ 1 * mockNcmpOutEventProducer.publishNcmpOutEvent('test-id', 'subscriptionCreateResponse', null, true)
}
def 'Consume valid and but non-unique CmNotificationSubscription create message'() {
@@ -111,35 +118,55 @@ class CmSubscriptionHandlerImplSpec extends Specification {
def predicates = testEventConsumed.getData().getPredicates()
and: 'the NCMP out in event mapper returns an event for rejected request'
def testNcmpOutEvent = new NcmpOutEvent()
- 1 * mockMappersFacade.toNcmpOutEventForRejectedRequest(
+ 1 * mockNcmpOutEventMapper.toNcmpOutEventForRejectedRequest(
"test-id", _) >> testNcmpOutEvent
when: 'the valid but non-unique event is consumed'
objectUnderTest.processSubscriptionCreateRequest(subscriptionId, predicates)
then: 'the events handler method to publish DMI event is never called'
- 0 * mockEventsFacade.publishDmiInEvent(_, _, _, _)
+ 0 * mockDmiInEventProducer.publishDmiInEvent(_, _, _, _)
and: 'the events handler method to publish NCMP out event is called once'
- 1 * mockEventsFacade.publishNcmpOutEvent('test-id', 'subscriptionCreateResponse', testNcmpOutEvent, false)
+ 1 * mockNcmpOutEventProducer.publishNcmpOutEvent('test-id', 'subscriptionCreateResponse', testNcmpOutEvent, false)
}
def 'Consume valid CmNotificationSubscriptionNcmpInEvent delete message'() {
- given: 'a cmNotificationSubscriptionNcmp in event for delete'
- def jsonData = TestUtils.getResourceFileContent('cmSubscription/cmNotificationSubscriptionNcmpInEvent.json')
- def testEventConsumed = jsonObjectMapper.convertJsonString(jsonData, NcmpInEvent.class)
- and: 'relevant details is extracted from the event'
- def subscriptionId = testEventConsumed.getData().getSubscriptionId()
- def predicates = testEventConsumed.getData().getPredicates()
- and: 'the cache handler returns for relevant subscription id'
- 1 * mockDmiCacheHandler.get('test-id') >> testDmiSubscriptionsPerDmi
- when: 'the valid and unique event is consumed'
- objectUnderTest.processSubscriptionDeleteRequest(subscriptionId, predicates)
- then: 'the subscription cache handler is called once'
- 1 * mockDmiCacheHandler.add('test-id', predicates)
- and: 'the mapper handler to get DMI in event is called once'
- 1 * mockMappersFacade.toDmiInEvent(_)
- and: 'the events handler method to publish DMI event is called correct number of times with the correct parameters'
- testDmiSubscriptionsPerDmi.size() * mockEventsFacade.publishDmiInEvent(
- 'test-id', 'dmi-1', 'subscriptionDeleteRequest', _)
- and: 'we schedule to send the response after configured time from the cache'
- 1 * mockEventsFacade.publishNcmpOutEvent('test-id', 'subscriptionDeleteResponse', null, true)
+ given: 'a test subscription id'
+ def subscriptionId = 'test-id'
+ and: 'the persistence service returns datanodes'
+ 1 * mockCmSubscriptionPersistenceService.getAllNodesForSubscriptionId(subscriptionId) >>
+ [new DataNode(xpath: "/datastores/datastore[@name='ncmp-datastore:passthrough-running']/cm-handles/cm-handle[@id='ch-1']/filters/filter[@xpath='x/y']", leaves: ['xpath': 'x/y', 'subscriptionIds': ['test-id']]),
+ new DataNode(xpath: "/datastores/datastore[@name='ncmp-datastore:passthrough-running']/cm-handles/cm-handle[@id='ch-2']/filters/filter[@xpath='y/z']", leaves: ['xpath': 'y/z', 'subscriptionIds': ['test-id']])]
+ and: 'the inventory persistence returns yang model cm handles'
+ 1 * mockInventoryPersistence.getYangModelCmHandle('ch-1') >> new YangModelCmHandle(dmiServiceName: 'dmi-1')
+ 1 * mockInventoryPersistence.getYangModelCmHandle('ch-2') >> new YangModelCmHandle(dmiServiceName: 'dmi-2')
+ when: 'the subscription delete request is processed'
+ objectUnderTest.processSubscriptionDeleteRequest(subscriptionId)
+ then: 'the method to publish a dmi event is called with correct parameters'
+ 1 * mockDmiInEventProducer.publishDmiInEvent(subscriptionId,'dmi-1','subscriptionDeleteRequest',_)
+ 1 * mockDmiInEventProducer.publishDmiInEvent(subscriptionId,'dmi-2','subscriptionDeleteRequest',_)
+ and: 'the method to publish nmcp out event is called with correct parameters'
+ 1 * mockNcmpOutEventProducer.publishNcmpOutEvent(subscriptionId, 'subscriptionDeleteResponse', null, true)
+ }
+
+ def 'Delete a subscriber for fully overlapping subscriptions'() {
+ given: 'a test subscription id'
+ def subscriptionId = 'test-id'
+ and: 'the persistence service returns datanodes with multiple subscribers'
+ 1 * mockCmSubscriptionPersistenceService.getAllNodesForSubscriptionId(subscriptionId) >>
+ [new DataNode(xpath: "/datastores/datastore[@name='ncmp-datastore:passthrough-running']/cm-handles/cm-handle[@id='ch-1']/filters/filter[@xpath='x/y']", leaves: ['xpath': 'x/y', 'subscriptionIds': ['test-id','other-id']]),
+ new DataNode(xpath: "/datastores/datastore[@name='ncmp-datastore:passthrough-running']/cm-handles/cm-handle[@id='ch-2']/filters/filter[@xpath='y/z']", leaves: ['xpath': 'y/z', 'subscriptionIds': ['test-id','other-id']])]
+ and: 'the inventory persistence returns yang model cm handles'
+ 1 * mockInventoryPersistence.getYangModelCmHandle('ch-1') >> new YangModelCmHandle(dmiServiceName: 'dmi-1')
+ 1 * mockInventoryPersistence.getYangModelCmHandle('ch-2') >> new YangModelCmHandle(dmiServiceName: 'dmi-2')
+ and: 'the cache handler returns the relevant maps whenever called'
+ 2 * mockDmiCacheHandler.get(subscriptionId) >> ['dmi-1':[:],'dmi-2':[:]]
+ when: 'the subscription delete request is processed'
+ objectUnderTest.processSubscriptionDeleteRequest(subscriptionId)
+ then: 'the method to publish a dmi event is never called'
+ 0 * mockDmiInEventProducer.publishDmiInEvent(_,_,_,_)
+ and: 'the cache handler is called to remove subscriber from database per dmi'
+ 1 * mockDmiCacheHandler.removeFromDatabase('test-id', 'dmi-1')
+ 1 * mockDmiCacheHandler.removeFromDatabase('test-id', 'dmi-2')
+ and: 'the method to publish nmcp out event is called with correct parameters'
+ 1 * mockNcmpOutEventProducer.publishNcmpOutEvent(subscriptionId, 'subscriptionDeleteResponse', null, false)
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumerSpec.groovy
index 637e9ebfe..9c24e2b00 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpInEventConsumerSpec.groovy
@@ -28,9 +28,9 @@ 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.kafka.MessagingBaseSpec
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.client_to_ncmp.NcmpInEvent
import org.onap.cps.ncmp.utils.TestUtils
+import org.onap.cps.ncmp.utils.events.MessagingBaseSpec
import org.onap.cps.utils.JsonObjectMapper
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
@@ -100,7 +100,7 @@ class NcmpInEventConsumerSpec extends MessagingBaseSpec {
and: 'the log indicates the task completed successfully'
assert loggingEvent.formattedMessage == 'Subscription delete request for source some-resource with subscription id test-id ...'
and: 'the subscription handler service is called once'
- 1 * mockCmSubscriptionHandler.processSubscriptionDeleteRequest('test-id',_)
+ 1 * mockCmSubscriptionHandler.processSubscriptionDeleteRequest('test-id')
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventMapperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventMapperSpec.groovy
index 2251a3346..d3c402696 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventMapperSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventMapperSpec.groovy
@@ -53,9 +53,9 @@ class NcmpOutEventMapperSpec extends Specification {
then: 'event is mapped correctly for the subscription'
result.data.subscriptionId == 'test-subscription'
and: 'the cm handle ids are part of correct list'
- result.data.pendingTargets == ['ch-A']
- result.data.acceptedTargets == ['ch-B']
- result.data.rejectedTargets == ['ch-C']
+ result.data.pendingTargets == ['ch-A'] as Set
+ result.data.acceptedTargets == ['ch-B'] as Set
+ result.data.rejectedTargets == ['ch-C'] as Set
}
def 'Check for Cm Notification Rejected Subscription Outgoing event mapping'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy
index f96f3df78..afa2e9874 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy
@@ -3,7 +3,6 @@ package org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp
import com.fasterxml.jackson.databind.ObjectMapper
import io.cloudevents.CloudEvent
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.impl.cmnotificationsubscription.MappersFacade
import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.Data
import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent
@@ -15,11 +14,10 @@ class NcmpOutEventProducerSpec extends Specification {
def mockEventsPublisher = Mock(EventsPublisher)
def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
- def mockCmNotificationSubscriptionMappersHandler = Mock(MappersFacade)
- def mockDmiCmNotificationSubscriptionCacheHandler = Mock(DmiCacheHandler)
+ def mockNcmpOutEventMapper = Mock(NcmpOutEventMapper)
+ def mockDmiCacheHandler = Mock(DmiCacheHandler)
- def objectUnderTest = new NcmpOutEventProducer(mockEventsPublisher, jsonObjectMapper,
- mockCmNotificationSubscriptionMappersHandler, mockDmiCmNotificationSubscriptionCacheHandler)
+ def objectUnderTest = new NcmpOutEventProducer(mockEventsPublisher, jsonObjectMapper, mockNcmpOutEventMapper, mockDmiCacheHandler)
def 'Create and #scenario Cm Notification Subscription NCMP out event'() {
given: 'a cm subscription response for the client'
@@ -82,7 +80,26 @@ class NcmpOutEventProducerSpec extends Specification {
}
}
then: 'the cache handler is called once to remove accepted and rejected entries in cache'
- 1 * mockDmiCmNotificationSubscriptionCacheHandler.removeAcceptedAndRejectedDmiSubscriptionEntries(subscriptionId)
+ 1 * mockDmiCacheHandler.removeAcceptedAndRejectedDmiSubscriptionEntries(subscriptionId)
+ }
+
+ def 'No event published when NCMP out event is null'() {
+ given: 'a cm subscription response for the client'
+ def subscriptionId = 'test-subscription-id-3'
+ def eventType = 'subscriptionCreateResponse'
+ def ncmpOutEvent = null
+ and: 'also we have target topic for publishing to client'
+ objectUnderTest.ncmpOutEventTopic = 'client-test-topic'
+ and: 'a deadline to an event'
+ objectUnderTest.dmiOutEventTimeoutInMs = 1000
+ when: 'the event is scheduled to be published'
+ objectUnderTest.publishNcmpOutEvent(subscriptionId, eventType, ncmpOutEvent, true)
+ then: 'we wait for 10ms and then we receive response from DMI'
+ Thread.sleep(10)
+ and: 'we receive NO response from DMI so we publish the message on demand'
+ objectUnderTest.publishNcmpOutEvent(subscriptionId, eventType, ncmpOutEvent, false)
+ and: 'no event published'
+ 0 * mockEventsPublisher.publishCloudEvent(*_)
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/utils/CmSubscriptionPersistenceServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/utils/CmSubscriptionPersistenceServiceSpec.groovy
index d32d143ad..2b9106559 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/utils/CmSubscriptionPersistenceServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/utils/CmSubscriptionPersistenceServiceSpec.groovy
@@ -142,7 +142,7 @@ class CmSubscriptionPersistenceServiceSpec extends Specification {
'NCMP-Admin',
'cm-data-subscriptions',
parentNodeXpath.formatted(datastoreName, 'ch-1'),
- objectUnderTest.getSubscriptionDetailsAsJson('/x/y', ['newSubId']), _)
+ objectUnderTest.getSubscriptionDetailsAsJson('/x/y', ['newSubId']), _, ContentType.JSON)
where:
scenario | datastoreType || datastoreName
'passthrough_running' | PASSTHROUGH_RUNNING || 'ncmp-datastore:passthrough-running'
@@ -188,4 +188,17 @@ class CmSubscriptionPersistenceServiceSpec extends Specification {
'cm handle in same datastore is NOT used for other subscriptions' | [] || 1
}
+ def 'Get all nodes for subscription id'() {
+ given: 'the query service returns nodes for subscription id'
+ def expectedDataNode = new DataNode(xpath: '/some/xpath')
+ def queryServiceResponse = [expectedDataNode].asCollection()
+ 1 * mockCpsQueryService.queryDataNodes('NCMP-Admin', 'cm-data-subscriptions', '//filter/subscriptionIds[text()=\'some-id\']', OMIT_DESCENDANTS) >> queryServiceResponse
+ when: 'retrieving all nodes for subscription id'
+ def result = objectUnderTest.getAllNodesForSubscriptionId('some-id')
+ then: 'the result returns correct number of datanodes'
+ assert result.size() == 1
+ and: 'the attribute of the datanode is as expected'
+ assert result.iterator().next().xpath == expectedDataNode.xpath
+ }
+
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
index 3a199ff41..970444f64 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
@@ -25,17 +25,18 @@ import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.events.EventsPublisher
import org.onap.cps.ncmp.api.data.models.CmResourceAddress
import org.onap.cps.ncmp.api.data.models.DataOperationRequest
-import org.onap.cps.ncmp.api.impl.config.DmiProperties
-import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException
-import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext
-import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters
+import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException
+import org.onap.cps.ncmp.config.CpsApplicationContext
import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent
-import org.onap.cps.ncmp.impl.DmiOperationsBaseSpec
+import org.onap.cps.ncmp.impl.dmi.DmiOperationsBaseSpec
+import org.onap.cps.ncmp.impl.dmi.DmiProperties
+import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
import org.onap.cps.ncmp.utils.TestUtils
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootContextLoader
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
@@ -53,7 +54,7 @@ import static org.onap.cps.ncmp.impl.models.RequiredDmiService.DATA
import static org.onap.cps.ncmp.utils.events.CloudEventMapper.toTargetEvent
@SpringBootTest
-@ContextConfiguration(classes = [EventsPublisher, CpsApplicationContext, DmiProperties, DmiDataOperations])
+@ContextConfiguration(classes = [EventsPublisher, CpsApplicationContext, DmiProperties, DmiDataOperations, PolicyExecutor])
class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def NO_TOPIC = null
@@ -72,6 +73,9 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
@SpringBean
EventsPublisher eventsPublisher = Stub()
+ @SpringBean
+ PolicyExecutor policyExecutor = Mock()
+
def 'call get resource data for #expectedDataStore from DMI without topic #scenario.'() {
given: 'a cm handle for #cmHandleId'
mockYangModelCmHandleRetrieval(dmiProperties)
@@ -161,6 +165,8 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def result = objectUnderTest.writeResourceDataPassThroughRunningFromDmi(cmHandleId, 'parent/child', operation, 'requestData', 'some data type', NO_AUTH_HEADER)
then: 'the result is the response from the DMI service'
assert result == responseFromDmi
+ and: 'the permission was checked with the policy executor'
+ 1 * policyExecutor.checkPermission(_, operation, NO_AUTH_HEADER, resourceIdentifier, 'requestData' )
where: 'the following operation is performed'
operation || expectedOperationInUrl
CREATE || 'create'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandlerSpec.groovy
index 39701d8e7..d5db24cc3 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandlerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NcmpDatastoreRequestHandlerSpec.groovy
@@ -26,7 +26,7 @@ import org.onap.cps.ncmp.api.data.exceptions.OperationNotSupportedException
import org.onap.cps.ncmp.api.data.models.CmResourceAddress
import org.onap.cps.ncmp.api.data.models.DataOperationDefinition
import org.onap.cps.ncmp.api.data.models.DataOperationRequest
-import org.onap.cps.ncmp.exceptions.PayloadTooLargeException
+import org.onap.cps.ncmp.api.exceptions.PayloadTooLargeException
import org.springframework.http.ResponseEntity
import reactor.core.publisher.Mono
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy
new file mode 100644
index 000000000..654206776
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy
@@ -0,0 +1,73 @@
+package org.onap.cps.ncmp.impl.data
+
+import ch.qos.logback.classic.Level
+import ch.qos.logback.classic.Logger
+import ch.qos.logback.classic.spi.ILoggingEvent
+import ch.qos.logback.core.read.ListAppender
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
+import org.slf4j.LoggerFactory
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.ContextConfiguration
+import spock.lang.Specification
+
+import static org.onap.cps.ncmp.api.data.models.OperationType.PATCH
+
+@SpringBootTest
+@ContextConfiguration(classes = [PolicyExecutor])
+class PolicyExecutorSpec extends Specification {
+
+ @Autowired
+ PolicyExecutor objectUnderTest
+
+ def logAppender = Spy(ListAppender<ILoggingEvent>)
+
+ def setup() {
+ setupLogger()
+ }
+
+ def cleanup() {
+ ((Logger) LoggerFactory.getLogger(PolicyExecutor)).detachAndStopAllAppenders()
+ }
+
+ def 'Configuration properties.'() {
+ expect: 'properties used from application.yml'
+ assert objectUnderTest.enabled
+ assert objectUnderTest.serverAddress == 'http://localhost'
+ assert objectUnderTest.serverPort == '8785'
+ }
+
+ def 'Permission check logging.'() {
+ when: 'permission is checked for an operation'
+ def yangModelCmHandle = new YangModelCmHandle(id:'ch-1', alternateId:'fdn1')
+ objectUnderTest.checkPermission(yangModelCmHandle, PATCH, 'my credentials','my resource','my change')
+ then: 'correct details are logged '
+ assert getLogEntry(0) == 'Policy Executor Enabled'
+ assert getLogEntry(3).contains('my credentials')
+ assert getLogEntry(4).contains('cm_patch')
+ assert getLogEntry(5).contains('fdn1')
+ assert getLogEntry(6).contains('ch-1')
+ assert getLogEntry(7).contains('my resource')
+ assert getLogEntry(8).contains('my change')
+ }
+
+ def 'Permission check with feature disabled.'() {
+ given: 'feature is disabled'
+ objectUnderTest.enabled = false
+ when: 'permission is checked for an operation'
+ objectUnderTest.checkPermission(new YangModelCmHandle(), PATCH, 'my credentials','my resource','my change')
+ then: 'nothing is logged'
+ assert logAppender.list.isEmpty()
+ }
+
+ def setupLogger() {
+ def logger = LoggerFactory.getLogger(PolicyExecutor)
+ logger.setLevel(Level.DEBUG)
+ logger.addAppender(logAppender)
+ logAppender.start()
+ }
+
+ def getLogEntry(index) {
+ logAppender.list[index].formattedMessage
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/CpsAsyncRequestResponseEventIntegrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/CpsAsyncRequestResponseEventIntegrationSpec.groovy
index ad7d741ae..4bcafe8c6 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/CpsAsyncRequestResponseEventIntegrationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/CpsAsyncRequestResponseEventIntegrationSpec.groovy
@@ -25,10 +25,10 @@ import org.apache.kafka.clients.consumer.KafkaConsumer
import org.apache.kafka.common.serialization.StringDeserializer
import org.mapstruct.factory.Mappers
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
import org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent
import org.onap.cps.ncmp.event.model.NcmpAsyncRequestResponseEvent
import org.onap.cps.ncmp.utils.TestUtils
+import org.onap.cps.ncmp.utils.events.MessagingBaseSpec
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/DataOperationEventConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/DataOperationEventConsumerSpec.groovy
index 7e9f5089b..afb594ab0 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/DataOperationEventConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/DataOperationEventConsumerSpec.groovy
@@ -30,9 +30,9 @@ import org.apache.kafka.clients.consumer.ConsumerRecord
import org.apache.kafka.clients.consumer.KafkaConsumer
import org.apache.kafka.common.header.internals.RecordHeaders
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent
import org.onap.cps.ncmp.utils.TestUtils
+import org.onap.cps.ncmp.utils.events.MessagingBaseSpec
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/FilterStrategiesIntegrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/FilterStrategiesIntegrationSpec.groovy
index 0643dbcf1..01d2a3666 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/FilterStrategiesIntegrationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/FilterStrategiesIntegrationSpec.groovy
@@ -22,9 +22,9 @@ package org.onap.cps.ncmp.impl.data.async
import io.cloudevents.core.builder.CloudEventBuilder
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.api.impl.config.kafka.KafkaConfig
-import org.onap.cps.ncmp.api.kafka.ConsumerBaseSpec
+import org.onap.cps.ncmp.config.KafkaConfig
import org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent
+import org.onap.cps.ncmp.utils.events.ConsumerBaseSpec
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/SerializationIntegrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/SerializationIntegrationSpec.groovy
index 94ebc38a4..3fe7ec222 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/SerializationIntegrationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/async/SerializationIntegrationSpec.groovy
@@ -23,13 +23,13 @@ package org.onap.cps.ncmp.impl.data.async
import com.fasterxml.jackson.databind.ObjectMapper
import io.cloudevents.core.builder.CloudEventBuilder
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.api.impl.config.kafka.KafkaConfig
-import org.onap.cps.ncmp.api.kafka.ConsumerBaseSpec
+import org.onap.cps.ncmp.config.KafkaConfig
import org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent
import org.onap.cps.ncmp.event.model.NcmpAsyncRequestResponseEvent
import org.onap.cps.ncmp.events.async1_0_0.Data
import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent
import org.onap.cps.ncmp.events.async1_0_0.Response
+import org.onap.cps.ncmp.utils.events.ConsumerBaseSpec
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy
index cdf9eae40..84eafb0da 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/utils/DmiDataOperationsHelperSpec.groovy
@@ -28,13 +28,13 @@ import org.apache.kafka.clients.consumer.KafkaConsumer
import org.onap.cps.events.EventsPublisher
import org.onap.cps.ncmp.api.data.models.DataOperationRequest
import org.onap.cps.ncmp.api.data.models.OperationType
-import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext
import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder
-import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
+import org.onap.cps.ncmp.config.CpsApplicationContext
import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent
import org.onap.cps.ncmp.impl.data.models.DmiDataOperation
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.ncmp.utils.TestUtils
+import org.onap.cps.ncmp.utils.events.MessagingBaseSpec
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.test.context.ContextConfiguration
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/DataJobServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImplSpec.groovy
index 9cee2bdba..4b536b971 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/DataJobServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImplSpec.groovy
@@ -18,21 +18,18 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl
+package org.onap.cps.ncmp.impl.datajobs
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.core.read.ListAppender
-import org.onap.cps.ncmp.impl.datajobs.DataJobServiceImpl
-import org.onap.cps.ncmp.impl.datajobs.DmiSubJobRequestHandler
-import org.onap.cps.ncmp.impl.datajobs.WriteRequestExaminer
-import org.slf4j.LoggerFactory
+import org.onap.cps.ncmp.api.datajobs.models.DataJobMetadata
import org.onap.cps.ncmp.api.datajobs.models.DataJobReadRequest
import org.onap.cps.ncmp.api.datajobs.models.DataJobWriteRequest
-import org.onap.cps.ncmp.api.datajobs.models.DataJobMetadata
import org.onap.cps.ncmp.api.datajobs.models.ReadOperation
import org.onap.cps.ncmp.api.datajobs.models.WriteOperation
+import org.slf4j.LoggerFactory
import spock.lang.Specification
class DataJobServiceImplSpec extends Specification {
@@ -43,6 +40,7 @@ class DataJobServiceImplSpec extends Specification {
def objectUnderTest = new DataJobServiceImpl(mockDmiSubJobRequestHandler, mockWriteRequestExaminer)
def myDataJobMetadata = new DataJobMetadata('', '', '')
+ def authorization = 'my authorization header'
def logger = Spy(ListAppender<ILoggingEvent>)
@@ -57,7 +55,7 @@ class DataJobServiceImplSpec extends Specification {
def 'Read data job request.'() {
when: 'read data job request is processed'
def readOperation = new ReadOperation('', '', '', [], [], '', '', 1)
- objectUnderTest.readDataJob('my-job-id', myDataJobMetadata, new DataJobReadRequest([readOperation]))
+ objectUnderTest.readDataJob(authorization, 'my-job-id', myDataJobMetadata, new DataJobReadRequest([readOperation]))
then: 'the data job id is correctly logged'
def loggingEvent = logger.list[0]
assert loggingEvent.level == Level.INFO
@@ -70,11 +68,11 @@ class DataJobServiceImplSpec extends Specification {
and: 'a map of producer key and dmi 3gpp write operation'
def dmiWriteOperationsPerProducerKey = [:]
when: 'write data job request is processed'
- objectUnderTest.writeDataJob('my-job-id', myDataJobMetadata, dataJobWriteRequest)
+ objectUnderTest.writeDataJob(authorization, 'my-job-id', myDataJobMetadata, dataJobWriteRequest)
then: 'the examiner service is called and a map is returned'
1 * mockWriteRequestExaminer.splitDmiWriteOperationsFromRequest('my-job-id', dataJobWriteRequest) >> dmiWriteOperationsPerProducerKey
and: 'the dmi request handler is called with the result from the examiner'
- 1 * mockDmiSubJobRequestHandler.sendRequestsToDmi('my-job-id', myDataJobMetadata, dmiWriteOperationsPerProducerKey)
+ 1 * mockDmiSubJobRequestHandler.sendRequestsToDmi(authorization, 'my-job-id', myDataJobMetadata, dmiWriteOperationsPerProducerKey)
}
def setupLogger() {
@@ -83,4 +81,4 @@ class DataJobServiceImplSpec extends Specification {
setupLogger.addAppender(logger)
logger.start()
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy
new file mode 100644
index 000000000..cc042988f
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy
@@ -0,0 +1,54 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.impl.datajobs
+
+import org.onap.cps.ncmp.impl.dmi.DmiProperties
+import org.onap.cps.ncmp.impl.dmi.DmiRestClient
+import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters
+import reactor.core.publisher.Mono
+import spock.lang.Specification
+
+class DataJobStatusServiceImplSpec extends Specification {
+
+ def mockDmiRestClient = Mock(DmiRestClient)
+ def mockDmiProperties = Mock(DmiProperties)
+ def objectUnderTest = new DataJobStatusServiceImpl(mockDmiRestClient, mockDmiProperties)
+
+ def setup() {
+ mockDmiProperties.dmiBasePath >> 'dmi'
+ }
+
+ def 'Forward a data job status query to DMI.' () {
+ given: 'the required parameters for querying'
+ def dmiServiceName = 'some-dmi-service'
+ def requestId = 'some-request-id'
+ def dataProducerJobId = 'some-data-producer-job-id'
+ def dataJobId = 'some-data-job-id'
+ def authorization = 'my authorization header'
+ def urlParams = new UrlTemplateParameters('some-dmi-service/dmi/v1/dataJob/{requestId}/dataProducerJob/{dataProducerJobId}/status?dataProducerId={dataProducerId}', ['dataProducerJobId':'some-data-producer-job-id', 'dataProducerId':'some-data-job-id', 'requestId':'some-request-id'])
+ and: 'the rest client returns a status for the given parameters'
+ mockDmiRestClient.getDataJobStatus(urlParams, authorization) >> Mono.just('some status')
+ when: 'the job status is queried'
+ def status = objectUnderTest.getDataJobStatus(authorization, dmiServiceName, requestId, dataProducerJobId, dataJobId)
+ then: 'the status from the rest client is returned'
+ assert status == 'some status'
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandlerSpec.groovy
new file mode 100644
index 000000000..b3dd02dec
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandlerSpec.groovy
@@ -0,0 +1,40 @@
+package org.onap.cps.ncmp.impl.datajobs
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.ncmp.api.data.models.OperationType
+import org.onap.cps.ncmp.api.datajobs.models.DataJobMetadata
+import org.onap.cps.ncmp.api.datajobs.models.DmiWriteOperation
+import org.onap.cps.ncmp.api.datajobs.models.ProducerKey
+import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteResponse
+import org.onap.cps.ncmp.impl.dmi.DmiProperties
+import org.onap.cps.ncmp.impl.dmi.DmiRestClient
+import org.onap.cps.ncmp.impl.models.RequiredDmiService
+import org.onap.cps.utils.JsonObjectMapper
+import org.springframework.http.HttpStatus
+import org.springframework.http.ResponseEntity
+import spock.lang.Specification
+
+class DmiSubJobRequestHandlerSpec extends Specification {
+
+ def mockDmiRestClient = Mock(DmiRestClient)
+ def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+ def mockDmiProperties = Mock(DmiProperties)
+ def objectUnderTest = new DmiSubJobRequestHandler(mockDmiRestClient, mockDmiProperties, jsonObjectMapper)
+
+ def 'Send a sub-job request to the DMI Plugin.'() {
+ given: 'a data job id, metadata and a map of producer keys and write operations to create a request'
+ def dataJobId = 'some-job-id'
+ def dataJobMetadata = new DataJobMetadata('d1', 't1', 't2')
+ def dmiWriteOperation = new DmiWriteOperation('p', 'operation', 'tag', null, 'o1', [:])
+ def dmiWriteOperationsPerProducerKey = [new ProducerKey('dmi1', 'prod1'): [dmiWriteOperation]]
+ def authorization = 'my authorization header'
+ and: 'the dmi rest client will return a response (for the correct parameters)'
+ def responseEntity = new ResponseEntity<>(new SubJobWriteResponse('my-sub-job-id', 'dmi1', 'prod1'), HttpStatus.OK)
+ def expectedJson = '{"dataAcceptType":"t1","dataContentType":"t2","dataProducerId":"prod1","data":[{"path":"p","op":"operation","moduleSetTag":"tag","value":null,"operationId":"o1","privateProperties":{}}]}'
+ mockDmiRestClient.synchronousPostOperationWithJsonData(RequiredDmiService.DATA, _, expectedJson, OperationType.CREATE, authorization) >> responseEntity
+ when: 'sending request to DMI invoked'
+ objectUnderTest.sendRequestsToDmi(authorization, dataJobId, dataJobMetadata, dmiWriteOperationsPerProducerKey)
+ then: 'the result contains the expected sub-job id'
+ assert responseEntity.body.subJobId == 'my-sub-job-id'
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/WriteRequestExaminerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy
index 84eb78b75..84eb78b75 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/WriteRequestExaminerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
index 050932f65..affbf2aa4 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/DmiOperationsBaseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
@@ -18,10 +18,9 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.impl
+package org.onap.cps.ncmp.impl.dmi
import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.ncmp.api.impl.client.DmiRestClient
import org.onap.cps.ncmp.api.inventory.models.CompositeState
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiPropertiesSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiPropertiesSpec.groovy
index c763c522c..418b3bb3c 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiPropertiesSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiPropertiesSpec.groovy
@@ -18,7 +18,8 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config
+package org.onap.cps.ncmp.impl.dmi
+
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy
index a935d70ce..3444d7b86 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy
@@ -19,14 +19,12 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.client
+package org.onap.cps.ncmp.impl.dmi
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.ObjectNode
-import org.onap.cps.ncmp.api.impl.config.DmiProperties
-import org.onap.cps.ncmp.api.impl.exception.DmiClientRequestException
-import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters
+import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException
import org.onap.cps.ncmp.utils.TestUtils
import org.onap.cps.utils.JsonObjectMapper
import org.springframework.http.HttpHeaders
@@ -165,4 +163,16 @@ class DmiRestClientSpec extends Specification {
'DMI basic auth disabled, with NCMP bearer token' | false | BEARER_AUTH_HEADER || BEARER_AUTH_HEADER
'DMI basic auth disabled, with NCMP basic auth' | false | BASIC_AUTH_HEADER || NO_AUTH_HEADER
}
+
+ def 'DMI GET Operation for DMI Data Service '() {
+ given: 'the Data web client returns a valid response entity for the expected parameters'
+ mockDataServicesWebClient.get() >> mockRequestBody
+ def jsonNode = jsonObjectMapper.convertJsonString('{"status":"some status"}', JsonNode.class)
+ ((ObjectNode) jsonNode).put('status', 'some status')
+ mockResponse.bodyToMono(JsonNode.class) >> Mono.just(jsonNode)
+ when: 'GET operation is invoked for Data Service'
+ def response = objectUnderTest.getDataJobStatus(urlTemplateParameters, NO_AUTH_HEADER).block()
+ then: 'the response equals to the expected value'
+ assert response == 'some status'
+ }
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/url/builder/DmiServiceUrlTemplateBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilderSpec.groovy
index 6d56f432d..9e1b37023 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/url/builder/DmiServiceUrlTemplateBuilderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilderSpec.groovy
@@ -18,7 +18,8 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils.url.builder
+package org.onap.cps.ncmp.impl.dmi
+
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfigurationSpec.groovy
index fa995aa7c..fca47d8c2 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfigurationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfigurationSpec.groovy
@@ -18,8 +18,10 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config
+package org.onap.cps.ncmp.impl.dmi
+
+import org.onap.cps.ncmp.config.HttpClientConfiguration
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ContextConfiguration
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy
index 4ff56312a..0c702abea 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy
@@ -24,7 +24,7 @@ package org.onap.cps.ncmp.impl.inventory
import com.hazelcast.map.IMap
import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
-import org.onap.cps.ncmp.api.impl.exception.DmiRequestException
+import org.onap.cps.ncmp.api.exceptions.DmiRequestException
import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse
import org.onap.cps.ncmp.api.inventory.models.CompositeState
import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
index d58a1dfa0..e60bacbdc 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* Copyright (C) 2022-2024 Nordix Foundation
* Modifications Copyright (C) 2022 Bell Canada
- * Modifications Copyright (C) 2023 TechMahindra Ltd.
+ * Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import org.onap.cps.spi.model.DataNode
import org.onap.cps.spi.model.ModuleDefinition
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.spi.utils.CpsValidator
+import org.onap.cps.utils.ContentType
import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Shared
import spock.lang.Specification
@@ -166,7 +167,7 @@ class InventoryPersistenceImplSpec extends Specification {
when: 'update cm handle state is invoked with the #scenario state'
objectUnderTest.saveCmHandleState(cmHandleId, compositeState)
then: 'update node leaves is invoked with the correct params'
- 1 * mockCpsDataService.updateDataNodeAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@id=\'Some-Cm-Handle\']', expectedJsonData, _ as OffsetDateTime)
+ 1 * mockCpsDataService.updateDataNodeAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@id=\'Some-Cm-Handle\']', expectedJsonData, _ as OffsetDateTime, ContentType.JSON)
where: 'the following states are used'
scenario | cmHandleState || expectedJsonData
'READY' | CmHandleState.READY || '{"state":{"cm-handle-state":"READY","last-update-time":"2022-12-31T20:30:40.000+0000"}}'
@@ -182,7 +183,7 @@ class InventoryPersistenceImplSpec extends Specification {
def cmHandleStateMap = ['Some-Cm-Handle1' : compositeState1, 'Some-Cm-Handle2' : compositeState2]
objectUnderTest.saveCmHandleStateBatch(cmHandleStateMap)
then: 'update node leaves is invoked with the correct params'
- 1 * mockCpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandlesJsonDataMap, _ as OffsetDateTime)
+ 1 * mockCpsDataService.updateDataNodesAndDescendants(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandlesJsonDataMap, _ as OffsetDateTime, ContentType.JSON)
where: 'the following states are used'
scenario | cmHandleState || cmHandlesJsonDataMap
'READY' | CmHandleState.READY || ['/dmi-registry/cm-handles[@id=\'Some-Cm-Handle1\']':'{"state":{"cm-handle-state":"READY","last-update-time":"2022-12-31T20:30:40.000+0000"}}', '/dmi-registry/cm-handles[@id=\'Some-Cm-Handle2\']':'{"state":{"cm-handle-state":"READY","last-update-time":"2022-12-31T20:30:40.000+0000"}}']
@@ -231,7 +232,7 @@ class InventoryPersistenceImplSpec extends Specification {
objectUnderTest.saveCmHandle(yangModelCmHandle)
then: 'the data service method to save list elements is called once'
1 * mockCpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT,
- _,null) >> {
+ _,null, ContentType.JSON) >> {
args -> {
assert args[3].startsWith('{"cm-handles":[{"id":"cmhandle","additional-properties":[],"public-properties":[]}]}')
}
@@ -246,7 +247,7 @@ class InventoryPersistenceImplSpec extends Specification {
objectUnderTest.saveCmHandleBatch([yangModelCmHandle1, yangModelCmHandle2])
then: 'CPS Data Service persists both cm handles as a batch'
1 * mockCpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- NCMP_DMI_REGISTRY_PARENT, _,null) >> {
+ NCMP_DMI_REGISTRY_PARENT, _,null, ContentType.JSON) >> {
args -> {
def jsonData = (args[3] as String)
jsonData.contains('cmhandle1')
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy
index dfd549e63..013bace04 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy
@@ -57,6 +57,19 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
assert result == ['some-cmhandle-id'] as Set
}
+ def 'Query cm handle where cps path itself is ancestor axis.'() {
+ given: 'a cmHandleWithCpsPath condition property'
+ def cmHandleQueryParameters = new CmHandleQueryServiceParameters()
+ def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']])
+ cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
+ and: 'the query get the cm handle data nodes excluding all descendants returns a datanode'
+ cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])]
+ when: 'the query is executed for cm handle ids'
+ def result = objectUnderTest.queryCmHandleIdsForInventory(cmHandleQueryParameters)
+ then: 'the correct expected cm handles ids are returned'
+ assert result == ['some-cmhandle-id'] as Set
+ }
+
def 'Cm handle ids query with error: #scenario.'() {
given: 'a cmHandleWithCpsPath condition property'
def cmHandleQueryParameters = new CmHandleQueryServiceParameters()
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditionsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditionsSpec.groovy
index 51c1f4bb1..2e7122268 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditionsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditionsSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START========================================================
- * Copyright (c) 2022 Nordix Foundation.
+ * Copyright (c) 2022-2024 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,18 +20,16 @@
package org.onap.cps.ncmp.impl.inventory.models
-
import spock.lang.Specification
class InventoryQueryConditionsSpec extends Specification {
def 'Inventory query condition names.'() {
- expect: '3 conditions with the correct names'
- assert InventoryQueryConditions.ALL_CONDITION_NAMES.size() == 3
+ expect: '4 conditions with the correct names'
+ assert InventoryQueryConditions.ALL_CONDITION_NAMES.size() == 4
assert InventoryQueryConditions.ALL_CONDITION_NAMES.containsAll('hasAllProperties',
'hasAllAdditionalProperties',
- 'cmHandleWithDmiPlugin')
+ 'cmHandleWithDmiPlugin',
+ 'cmHandleWithCpsPath')
}
-
-
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy
index 1268bc768..196a1cd36 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy
@@ -23,11 +23,11 @@ package org.onap.cps.ncmp.impl.inventory.sync
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.ncmp.api.impl.config.DmiProperties
-import org.onap.cps.ncmp.impl.DmiOperationsBaseSpec
+import org.onap.cps.ncmp.impl.dmi.DmiOperationsBaseSpec
+import org.onap.cps.ncmp.impl.dmi.DmiProperties
+import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.utils.JsonObjectMapper
-import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
@@ -170,9 +170,10 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
then: 'the result is the response from DMI service'
assert result == [mod1:'some yang source']
where: 'the following Module Set Tags are used'
- scenario | moduleSetTag || expectedModuleSetTagInRequest
- 'Without module set tag' | '' || ''
- 'With module set tag' | 'moduleSetTag1' || '"moduleSetTag":"moduleSetTag1",'
+ scenario | moduleSetTag || expectedModuleSetTagInRequest
+ 'Without module set tag' | '' || ''
+ 'With module set tag' | 'moduleSetTag1' || '"moduleSetTag":"moduleSetTag1",'
+ 'Special characters in module set tag' | 'module:set#tag$2' || '"moduleSetTag":"module:set#tag$2",'
}
def 'Retrieving yang resources from DMI with no module references.'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsPublisherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsPublisherSpec.groovy
index e7674761c..3e7ed9aff 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsPublisherSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsPublisherSpec.groovy
@@ -24,10 +24,10 @@ import com.fasterxml.jackson.databind.ObjectMapper
import org.apache.kafka.clients.consumer.KafkaConsumer
import org.apache.kafka.common.serialization.StringDeserializer
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
import org.onap.cps.ncmp.events.lcm.v1.Event
import org.onap.cps.ncmp.events.lcm.v1.LcmEvent
import org.onap.cps.ncmp.utils.TestUtils
+import org.onap.cps.ncmp.utils.events.MessagingBaseSpec
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsServiceSpec.groovy
index b745734f0..73c66089a 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsServiceSpec.groovy
@@ -20,9 +20,16 @@
package org.onap.cps.ncmp.impl.inventory.sync.lcm
+import static org.onap.cps.ncmp.events.lcm.v1.Values.CmHandleState.ADVISED
+import static org.onap.cps.ncmp.events.lcm.v1.Values.CmHandleState.READY
+
+import io.micrometer.core.instrument.Tag
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry
import org.onap.cps.events.EventsPublisher
+import org.onap.cps.ncmp.events.lcm.v1.Event
import org.onap.cps.ncmp.events.lcm.v1.LcmEvent
import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader
+import org.onap.cps.ncmp.events.lcm.v1.Values
import org.onap.cps.utils.JsonObjectMapper
import org.springframework.kafka.KafkaException
import spock.lang.Specification
@@ -31,14 +38,16 @@ class LcmEventsServiceSpec extends Specification {
def mockLcmEventsPublisher = Mock(EventsPublisher)
def mockJsonObjectMapper = Mock(JsonObjectMapper)
+ def meterRegistry = new SimpleMeterRegistry()
- def objectUnderTest = new LcmEventsService(mockLcmEventsPublisher, mockJsonObjectMapper)
+ def objectUnderTest = new LcmEventsService(mockLcmEventsPublisher, mockJsonObjectMapper, meterRegistry)
def 'Create and Publish lcm event where events are #scenario'() {
given: 'a cm handle id, Lcm Event, and headers'
def cmHandleId = 'test-cm-handle-id'
def eventId = UUID.randomUUID().toString()
- def lcmEvent = new LcmEvent(eventId: eventId, eventCorrelationId: cmHandleId)
+ def event = getEventWithCmHandleState(ADVISED, READY)
+ def lcmEvent = new LcmEvent(event: event, eventId: eventId, eventCorrelationId: cmHandleId)
and: 'we also have a lcm event header'
def lcmEventHeader = new LcmEventHeader(eventId: eventId, eventCorrelationId: cmHandleId)
and: 'notificationsEnabled is #notificationsEnabled and it will be true as default'
@@ -57,6 +66,16 @@ class LcmEventsServiceSpec extends Specification {
assert eventHeaders.get('eventCorrelationId') == cmHandleId
}
}
+ and: 'metrics are recorded with correct tags'
+ def timer = meterRegistry.find('cps.ncmp.lcm.events.publish').timer()
+ if (notificationsEnabled) {
+ assert timer != null
+ assert timer.count() == expectedTimesMethodCalled
+ def tags = timer.getId().getTags()
+ assert tags.containsAll(Tag.of('oldCmHandleState', ADVISED.value()), Tag.of('newCmHandleState', READY.value()))
+ } else {
+ assert timer == null
+ }
where: 'the following values are used'
scenario | notificationsEnabled || expectedTimesMethodCalled
'enabled' | true || 1
@@ -67,7 +86,8 @@ class LcmEventsServiceSpec extends Specification {
given: 'a cm handle id and Lcm Event and notification enabled'
def cmHandleId = 'test-cm-handle-id'
def eventId = UUID.randomUUID().toString()
- def lcmEvent = new LcmEvent(eventId: eventId, eventCorrelationId: cmHandleId)
+ and: 'event #event'
+ def lcmEvent = new LcmEvent(event: event, eventId: eventId, eventCorrelationId: cmHandleId)
def lcmEventHeader = new LcmEventHeader(eventId: eventId, eventCorrelationId: cmHandleId)
objectUnderTest.notificationsEnabled = true
when: 'publisher set to throw an exception'
@@ -76,6 +96,35 @@ class LcmEventsServiceSpec extends Specification {
objectUnderTest.publishLcmEvent(cmHandleId, lcmEvent, lcmEventHeader)
then: 'the exception is just logged and not bubbled up'
noExceptionThrown()
+ and: 'metrics are recorded with error tags'
+ def timer = meterRegistry.find('cps.ncmp.lcm.events.publish').timer()
+ assert timer != null
+ assert timer.count() == 1
+ def expectedTags = [Tag.of('oldCmHandleState', 'N/A'), Tag.of('newCmHandleState', 'N/A')]
+ def tags = timer.getId().getTags()
+ assert tags.containsAll(expectedTags)
+ where: 'the following values are used'
+ scenario | event
+ 'without values' | new Event()
+ 'without cm handle state' | getEvent()
}
+ def getEvent() {
+ def event = new Event()
+ def values = new Values()
+ event.setOldValues(values)
+ event.setNewValues(values)
+ event
+ }
+
+ def getEventWithCmHandleState(oldCmHandleState, newCmHandleState) {
+ def event = new Event()
+ def advisedCmHandleStateValues = new Values()
+ advisedCmHandleStateValues.setCmHandleState(oldCmHandleState)
+ event.setOldValues(advisedCmHandleStateValues)
+ def readyCmHandleStateValues = new Values()
+ readyCmHandleStateValues.setCmHandleState(newCmHandleState)
+ event.setNewValues(readyCmHandleStateValues)
+ return event
+ }
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy
index f975d23ba..0a34d267c 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy
@@ -20,9 +20,9 @@
package org.onap.cps.ncmp.impl.inventory.trustlevel
-import org.onap.cps.ncmp.api.impl.client.DmiRestClient
-import org.onap.cps.ncmp.api.impl.utils.url.builder.UrlTemplateParameters
import org.onap.cps.ncmp.api.inventory.models.TrustLevel
+import org.onap.cps.ncmp.impl.dmi.DmiRestClient
+import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters
import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService
import reactor.core.publisher.Mono
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatterSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/EventDateTimeFormatterSpec.groovy
index c72eb9e4c..7f07165df 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatterSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/EventDateTimeFormatterSpec.groovy
@@ -18,9 +18,10 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils
+package org.onap.cps.ncmp.impl.utils
import spock.lang.Specification
+
import java.time.Year
class EventDateTimeFormatterSpec extends Specification {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/AbstractModelLoaderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/AbstractModelLoaderSpec.groovy
index 162a9831c..38eeaa589 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/AbstractModelLoaderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/AbstractModelLoaderSpec.groovy
@@ -23,15 +23,15 @@ 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.CpsDataspaceService
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.ncmp.exceptions.NcmpStartUpException
import org.onap.cps.spi.CascadeDeleteAllowed
import org.onap.cps.spi.exceptions.AlreadyDefinedException
-import org.springframework.boot.SpringApplication
import org.slf4j.LoggerFactory
+import org.springframework.boot.SpringApplication
import org.springframework.boot.context.event.ApplicationStartedEvent
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoaderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoaderSpec.groovy
index dd1fd0b46..caaad8d34 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoaderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoaderSpec.groovy
@@ -27,7 +27,7 @@ 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.ncmp.exceptions.NcmpStartUpException
import org.onap.cps.spi.exceptions.AlreadyDefinedException
import org.onap.cps.spi.model.Dataspace
import org.slf4j.LoggerFactory
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/CmAvcEventPublisherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/CmAvcEventPublisherSpec.groovy
index 247f32183..051f5df4c 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/CmAvcEventPublisherSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/CmAvcEventPublisherSpec.groovy
@@ -23,8 +23,7 @@ package org.onap.cps.ncmp.utils.events
import com.fasterxml.jackson.databind.ObjectMapper
import io.cloudevents.CloudEvent
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext
-import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
+import org.onap.cps.ncmp.config.CpsApplicationContext
import org.onap.cps.ncmp.events.avc.ncmp_to_client.Avc
import org.onap.cps.ncmp.events.avc.ncmp_to_client.AvcEvent
import org.onap.cps.utils.JsonObjectMapper
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/kafka/ConsumerBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/ConsumerBaseSpec.groovy
index 28f8b0288..73dc2a37c 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/kafka/ConsumerBaseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/ConsumerBaseSpec.groovy
@@ -18,7 +18,8 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.kafka
+package org.onap.cps.ncmp.utils.events
+
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/kafka/MessagingBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/MessagingBaseSpec.groovy
index 0356c3fcd..377a1a663 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/kafka/MessagingBaseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/MessagingBaseSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.kafka
+package org.onap.cps.ncmp.utils.events
import io.cloudevents.CloudEvent
import io.cloudevents.kafka.CloudEventSerializer
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/TopicValidatorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/TopicValidatorSpec.groovy
index 26148f870..8fc3e18c7 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/TopicValidatorSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/events/TopicValidatorSpec.groovy
@@ -20,7 +20,7 @@
package org.onap.cps.ncmp.utils.events
-import org.onap.cps.ncmp.exceptions.InvalidTopicException
+import org.onap.cps.ncmp.api.exceptions.InvalidTopicException
import spock.lang.Specification
class TopicValidatorSpec extends Specification {
diff --git a/cps-ncmp-service/src/test/resources/application.yml b/cps-ncmp-service/src/test/resources/application.yml
index 5b10e7376..759de834a 100644
--- a/cps-ncmp-service/src/test/resources/application.yml
+++ b/cps-ncmp-service/src/test/resources/application.yml
@@ -16,6 +16,15 @@
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=========================================================
+cps:
+ tracing:
+ sampler:
+ jaeger_remote:
+ endpoint: http://jaeger-Remote-test-url
+ exporter:
+ endpoint: http://exporter-test-url
+ enabled: true
+
spring:
kafka:
producer:
@@ -41,10 +50,12 @@ ncmp:
pendingAcquireMaxCount: 22
connectionTimeoutInSeconds: 123
maximumInMemorySizeInMegabytes: 7
+ readTimeoutInSeconds: 33
model-services:
pendingAcquireMaxCount: 44
connectionTimeoutInSeconds: 456
maximumInMemorySizeInMegabytes: 8
+ maximumConnectionsTotal: 111
auth:
username: some-user
password: some-password
@@ -59,6 +70,11 @@ ncmp:
async-executor:
parallelism-level: 3
+ policy-executor:
+ enabled: true
+ server:
+ address: "http://localhost"
+ port: "8785"
# Custom Hazelcast Config.
hazelcast:
diff --git a/cps-ncmp-service/src/test/resources/sampleAvcInputEvent.json b/cps-ncmp-service/src/test/resources/sampleAvcInputEvent.json
index 5b297c86c..1dc14bd65 100644
--- a/cps-ncmp-service/src/test/resources/sampleAvcInputEvent.json
+++ b/cps-ncmp-service/src/test/resources/sampleAvcInputEvent.json
@@ -10,11 +10,8 @@
"operation":"replace",
"target":"ran-network:ran-network/NearRTRIC[@id='22']/GNBCUCPFunction[@id='cucpserver2']/NRCellCU[@id='15549']/NRCellRelation[@id='14427']",
"value":{
- "attributes":[
- {
- "isHoAllowed":true
- }
- ]
+ "color": "yellow",
+ "name": "Apple"
}
},
{
diff --git a/cps-parent/pom.xml b/cps-parent/pom.xml
index 591095aba..29e8d9fc8 100644
--- a/cps-parent/pom.xml
+++ b/cps-parent/pom.xml
@@ -32,7 +32,7 @@
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
@@ -368,6 +368,7 @@
<exclude>org/onap/cps/ncmp/rest/model/*</exclude>
<exclude>org/onap/cps/**/*MapperImpl.class</exclude>
<exclude>org/onap/cps/ncmp/rest/stub/*</exclude>
+ <exclude>org/onap/cps/policyexecutor/stub/model/*</exclude>
</excludes>
</configuration>
<executions>
diff --git a/cps-path-parser/pom.xml b/cps-path-parser/pom.xml
index 633ec6bb8..0eb424862 100644
--- a/cps-path-parser/pom.xml
+++ b/cps-path-parser/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
index de261e64b..0bb09235f 100644
--- a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
+++ b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
@@ -165,6 +165,10 @@ public class CpsPathBuilder extends CpsPathBaseListener {
cpsPathQuery.setContainerNames(containerNames);
cpsPathQuery.setBooleanOperators(booleanOperators);
cpsPathQuery.setComparativeOperators(comparativeOperators);
+ if (cpsPathQuery.hasAncestorAxis() && cpsPathQuery.getXpathPrefix()
+ .endsWith("/" + cpsPathQuery.getAncestorSchemaNodeIdentifier())) {
+ cpsPathQuery.setAncestorSchemaNodeIdentifier("");
+ }
return cpsPathQuery;
}
diff --git a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
index ae7ee598a..15f6b1182 100644
--- a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
+++ b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation
+ * Copyright (C) 2021-2024 Nordix Foundation
* Modifications Copyright (C) 2023 TechMahindra Ltd
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -253,4 +253,21 @@ class CpsPathQuerySpec extends Specification {
'/test[@name2="value2" and @name1="value1"]' || 'name2' | 'name1'
}
+ def 'Ancestor axis matching prefix'() {
+ when: 'building a cps path query'
+ def result = parseXPathAndBuild(xpath)
+ then: 'ancestor axis is removed when same as prefix'
+ assert result.hasAncestorAxis() == expectAncestorAxis
+ where: 'the following xpaths are used'
+ xpath || expectAncestorAxis
+ '//abc/def/ancestor::abc' || true
+ '//abc/def/ancestor::def' || false
+ '//abc/def/ancestor::ef' || true
+ }
+
+ def parseXPathAndBuild(xpath) {
+ def cpsPathBuilder = CpsPathUtil.getCpsPathBuilder(xpath)
+ cpsPathBuilder.build()
+ }
+
}
diff --git a/cps-rest/docs/openapi/components.yml b/cps-rest/docs/openapi/components.yml
index 01375f503..850ecb6f7 100644
--- a/cps-rest/docs/openapi/components.yml
+++ b/cps-rest/docs/openapi/components.yml
@@ -183,6 +183,14 @@ components:
schema:
type: string
example: my-anchor
+ sourceAnchorNameInPath:
+ name: source-anchor-name
+ in: path
+ description: source-anchor-name
+ required: true
+ schema:
+ type: string
+ example: my-anchor
schemaSetNameInQuery:
name: schema-set-name
in: query
@@ -279,10 +287,10 @@ components:
type: string
enum: [v1, v2]
default: v2
- contentTypeHeader:
+ contentTypeInHeader:
name: Content-Type
in: header
- description: Content type header
+ description: Content type in header
schema:
type: string
example: 'application/json'
@@ -376,7 +384,7 @@ components:
Created:
description: Created
content:
- text/plain:
+ application/json:
schema:
type: string
example: my-resource
diff --git a/cps-rest/docs/openapi/cpsData.yml b/cps-rest/docs/openapi/cpsData.yml
index d13c28581..4418a3b9b 100644
--- a/cps-rest/docs/openapi/cpsData.yml
+++ b/cps-rest/docs/openapi/cpsData.yml
@@ -32,15 +32,24 @@ listElementByDataspaceAndAnchor:
- $ref: 'components.yml#/components/parameters/anchorNameInPath'
- $ref: 'components.yml#/components/parameters/requiredXpathInQuery'
- $ref: 'components.yml#/components/parameters/observedTimestampInQuery'
+ - $ref: 'components.yml#/components/parameters/contentTypeInHeader'
requestBody:
required: true
content:
application/json:
schema:
- type: object
+ type: string
examples:
dataSample:
$ref: 'components.yml#/components/examples/dataSample'
+ application/xml:
+ schema:
+ type: object
+ xml:
+ name: stores
+ examples:
+ dataSample:
+ $ref: 'components.yml#/components/examples/dataSampleXml'
responses:
'201':
$ref: 'components.yml#/components/responses/Created'
@@ -94,7 +103,7 @@ nodesByDataspaceAndAnchor:
- $ref: 'components.yml#/components/parameters/anchorNameInPath'
- $ref: 'components.yml#/components/parameters/xpathInQuery'
- $ref: 'components.yml#/components/parameters/observedTimestampInQuery'
- - $ref: 'components.yml#/components/parameters/contentTypeHeader'
+ - $ref: 'components.yml#/components/parameters/contentTypeInHeader'
requestBody:
required: true
content:
@@ -112,7 +121,6 @@ nodesByDataspaceAndAnchor:
examples:
dataSample:
$ref: 'components.yml#/components/examples/dataSampleXml'
-
responses:
'201':
$ref: 'components.yml#/components/responses/Created'
@@ -137,7 +145,7 @@ nodesByDataspaceAndAnchor:
- $ref: 'components.yml#/components/parameters/anchorNameInPath'
- $ref: 'components.yml#/components/parameters/xpathInQuery'
- $ref: 'components.yml#/components/parameters/observedTimestampInQuery'
- - $ref: 'components.yml#/components/parameters/contentTypeHeader'
+ - $ref: 'components.yml#/components/parameters/contentTypeInHeader'
requestBody:
required: true
content:
@@ -197,15 +205,24 @@ nodesByDataspaceAndAnchor:
- $ref: 'components.yml#/components/parameters/anchorNameInPath'
- $ref: 'components.yml#/components/parameters/xpathInQuery'
- $ref: 'components.yml#/components/parameters/observedTimestampInQuery'
+ - $ref: 'components.yml#/components/parameters/contentTypeInHeader'
requestBody:
required: true
content:
application/json:
schema:
- type: object
+ type: string
examples:
dataSample:
$ref: 'components.yml#/components/examples/dataSample'
+ application/xml:
+ schema:
+ type: object
+ xml:
+ name: stores
+ examples:
+ dataSample:
+ $ref: 'components.yml#/components/examples/dataSampleXml'
responses:
'200':
$ref: 'components.yml#/components/responses/Ok'
diff --git a/cps-rest/docs/openapi/cpsDataV2.yml b/cps-rest/docs/openapi/cpsDataV2.yml
index a1433badf..d5a8ef389 100644
--- a/cps-rest/docs/openapi/cpsDataV2.yml
+++ b/cps-rest/docs/openapi/cpsDataV2.yml
@@ -46,7 +46,7 @@ nodeByDataspaceAndAnchor:
$ref: 'components.yml#/components/responses/InternalServerError'
x-codegen-request-body-name: xpath
-deltaByDataspaceAndAnchors:
+delta:
get:
description: Get delta between two anchors within a given dataspace
tags:
@@ -55,7 +55,7 @@ deltaByDataspaceAndAnchors:
operationId: getDeltaByDataspaceAndAnchors
parameters:
- $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
- - $ref: 'components.yml#/components/parameters/anchorNameInPath'
+ - $ref: 'components.yml#/components/parameters/sourceAnchorNameInPath'
- $ref: 'components.yml#/components/parameters/targetAnchorNameInQuery'
- $ref: 'components.yml#/components/parameters/xpathInQuery'
- $ref: 'components.yml#/components/parameters/descendantsInQuery'
@@ -76,8 +76,6 @@ deltaByDataspaceAndAnchors:
'500':
$ref: 'components.yml#/components/responses/InternalServerError'
x-codegen-request-body-name: xpath
-
-deltaByDataspaceAnchorAndPayload:
post:
description: Get delta between an anchor in a dataspace and JSON payload
tags:
@@ -86,7 +84,7 @@ deltaByDataspaceAnchorAndPayload:
operationId: getDeltaByDataspaceAnchorAndPayload
parameters:
- $ref: 'components.yml#/components/parameters/dataspaceNameInPath'
- - $ref: 'components.yml#/components/parameters/anchorNameInPath'
+ - $ref: 'components.yml#/components/parameters/sourceAnchorNameInPath'
- $ref: 'components.yml#/components/parameters/xpathInQuery'
requestBody:
content:
diff --git a/cps-rest/docs/openapi/openapi.yml b/cps-rest/docs/openapi/openapi.yml
index b4e0b7040..19494fcae 100644
--- a/cps-rest/docs/openapi/openapi.yml
+++ b/cps-rest/docs/openapi/openapi.yml
@@ -23,7 +23,7 @@ openapi: 3.0.3
info:
title: ONAP Open API v3 Configuration Persistence Service
description: Configuration Persistence Service is a Model Driven Generic Database
- version: "1.0.0"
+ version: "3.5.1"
contact:
name: ONAP
url: "https://onap.readthedocs.io"
@@ -31,10 +31,6 @@ info:
license:
name: "Apache 2.0"
url: "http://www.apache.org/licenses/LICENSE-2.0"
- x-planned-retirement-date: "202212"
- x-component: "Modeling"
- x-logo:
- url: "cps_logo.png"
servers:
- url: /cps/api
@@ -104,11 +100,8 @@ paths:
/{apiVersion}/dataspaces/{dataspace-name}/anchors/{anchor-name}/list-nodes:
$ref: 'cpsData.yml#/listElementByDataspaceAndAnchor'
- /v2/dataspaces/{dataspace-name}/anchors/{anchor-name}/deltaAnchors:
- $ref: 'cpsDataV2.yml#/deltaByDataspaceAndAnchors'
-
- /v2/dataspaces/{dataspace-name}/anchors/{anchor-name}/deltaPayload:
- $ref: 'cpsDataV2.yml#/deltaByDataspaceAnchorAndPayload'
+ /v2/dataspaces/{dataspace-name}/anchors/{source-anchor-name}/delta:
+ $ref: 'cpsDataV2.yml#/delta'
/v1/dataspaces/{dataspace-name}/anchors/{anchor-name}/nodes/query:
$ref: 'cpsQueryV1Deprecated.yml#/nodesByDataspaceAndAnchorAndCpsPath'
diff --git a/cps-rest/pom.xml b/cps-rest/pom.xml
index f7ddd6c38..7f25ebc47 100644
--- a/cps-rest/pom.xml
+++ b/cps-rest/pom.xml
@@ -27,7 +27,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java b/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
index f579c82d2..6015e0e3a 100755
--- a/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
+++ b/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
@@ -49,7 +49,6 @@ import org.onap.cps.utils.PrefixResolver;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@@ -70,11 +69,10 @@ public class DataRestController implements CpsDataApi {
@Override
public ResponseEntity<String> createNode(final String apiVersion,
final String dataspaceName, final String anchorName,
- @RequestHeader(value = "Content-Type") final String contentTypeHeader,
+ final String contentTypeInHeader,
final String nodeData, final String parentNodeXpath,
final String observedTimestamp) {
- final ContentType contentType = contentTypeHeader.contains(MediaType.APPLICATION_XML_VALUE) ? ContentType.XML
- : ContentType.JSON;
+ final ContentType contentType = getContentTypeFromHeader(contentTypeInHeader);
if (isRootXpath(parentNodeXpath)) {
cpsDataService.saveData(dataspaceName, anchorName, nodeData,
toOffsetDateTime(observedTimestamp), contentType);
@@ -97,9 +95,11 @@ public class DataRestController implements CpsDataApi {
@Override
public ResponseEntity<String> addListElements(final String apiVersion, final String dataspaceName,
final String anchorName, final String parentNodeXpath,
- final Object jsonData, final String observedTimestamp) {
+ final String contentTypeInHeader, final String nodeData,
+ final String observedTimestamp) {
+ final ContentType contentType = getContentTypeFromHeader(contentTypeInHeader);
cpsDataService.saveListElements(dataspaceName, anchorName, parentNodeXpath,
- jsonObjectMapper.asJsonString(jsonData), toOffsetDateTime(observedTimestamp));
+ nodeData, toOffsetDateTime(observedTimestamp), contentType);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@@ -137,23 +137,23 @@ public class DataRestController implements CpsDataApi {
@Override
public ResponseEntity<Object> updateNodeLeaves(final String apiVersion, final String dataspaceName,
- final String anchorName, final String contentTypeHeader,
+ final String anchorName, final String contentTypeInHeader,
final String nodeData, final String parentNodeXpath,
final String observedTimestamp) {
- final ContentType contentType = contentTypeHeader.contains(MediaType.APPLICATION_XML_VALUE) ? ContentType.XML
- : ContentType.JSON;
+ final ContentType contentType = getContentTypeFromHeader(contentTypeInHeader);
cpsDataService.updateNodeLeaves(dataspaceName, anchorName, parentNodeXpath,
nodeData, toOffsetDateTime(observedTimestamp), contentType);
return new ResponseEntity<>(HttpStatus.OK);
}
@Override
- public ResponseEntity<Object> replaceNode(final String apiVersion,
- final String dataspaceName, final String anchorName,
- final Object jsonData, final String parentNodeXpath, final String observedTimestamp) {
- cpsDataService
- .updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath,
- jsonObjectMapper.asJsonString(jsonData), toOffsetDateTime(observedTimestamp));
+ public ResponseEntity<Object> replaceNode(final String apiVersion, final String dataspaceName,
+ final String anchorName, final String contentTypeInHeader,
+ final String nodeData, final String parentNodeXpath,
+ final String observedTimestamp) {
+ final ContentType contentType = getContentTypeFromHeader(contentTypeInHeader);
+ cpsDataService.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath,
+ nodeData, toOffsetDateTime(observedTimestamp), contentType);
return new ResponseEntity<>(HttpStatus.OK);
}
@@ -213,6 +213,10 @@ public class DataRestController implements CpsDataApi {
return new ResponseEntity<>(jsonObjectMapper.asJsonString(deltaBetweenAnchors), HttpStatus.OK);
}
+ private static ContentType getContentTypeFromHeader(final String contentTypeInHeader) {
+ return contentTypeInHeader.contains(MediaType.APPLICATION_XML_VALUE) ? ContentType.XML : ContentType.JSON;
+ }
+
private static boolean isRootXpath(final String xpath) {
return ROOT_XPATH.equals(xpath);
}
diff --git a/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy b/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy
index 317b9c5b7..d696af2e6 100755
--- a/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy
+++ b/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy
@@ -192,22 +192,25 @@ class DataRestControllerSpec extends Specification {
def rootNodeXpath = '/'
when: 'list-node endpoint is invoked with post (create) operation'
def postRequestBuilder = post("$dataNodeBaseEndpointV1/anchors/$anchorName/list-nodes")
- .contentType(MediaType.APPLICATION_JSON)
+ .contentType(contentType)
.param('xpath', rootNodeXpath )
- .content(requestBodyJson)
+ .content(requestBody)
if (observedTimestamp != null)
postRequestBuilder.param('observed-timestamp', observedTimestamp)
def response = mvc.perform(postRequestBuilder).andReturn().response
then: 'a created response is returned'
response.status == expectedHttpStatus.value()
then: 'the java API was called with the correct parameters'
- expectedApiCount * mockCpsDataService.saveListElements(dataspaceName, anchorName, rootNodeXpath, expectedJsonData,
- { it == DateTimeUtility.toOffsetDateTime(observedTimestamp) })
+ expectedApiCount * mockCpsDataService.saveListElements(dataspaceName, anchorName, rootNodeXpath, expectedData,
+ { it == DateTimeUtility.toOffsetDateTime(observedTimestamp) }, expectedContentType)
where:
- scenario | observedTimestamp || expectedApiCount | expectedHttpStatus
- 'with observed-timestamp' | '2021-03-03T23:59:59.999-0400' || 1 | HttpStatus.CREATED
- 'without observed-timestamp' | null || 1 | HttpStatus.CREATED
- 'with invalid observed-timestamp' | 'invalid' || 0 | HttpStatus.BAD_REQUEST
+ scenario | observedTimestamp | contentType | requestBody || expectedApiCount | expectedHttpStatus | expectedData | expectedContentType
+ 'Content type JSON with observed-timestamp' | '2021-03-03T23:59:59.999-0400' | MediaType.APPLICATION_JSON | requestBodyJson || 1 | HttpStatus.CREATED | expectedJsonData | ContentType.JSON
+ 'Content type JSON without observed-timestamp' | null | MediaType.APPLICATION_JSON | requestBodyJson || 1 | HttpStatus.CREATED | expectedJsonData | ContentType.JSON
+ 'Content type JSON with invalid observed-timestamp' | 'invalid' | MediaType.APPLICATION_JSON | requestBodyJson || 0 | HttpStatus.BAD_REQUEST | expectedJsonData | ContentType.JSON
+ 'Content type XML with observed-timestamp' | '2021-03-03T23:59:59.999-0400' | MediaType.APPLICATION_XML | requestBodyXml || 1 | HttpStatus.CREATED | expectedXmlData | ContentType.XML
+ 'Content type XML without observed-timestamp' | null | MediaType.APPLICATION_XML | requestBodyXml || 1 | HttpStatus.CREATED | expectedXmlData | ContentType.XML
+ 'Content type XML with invalid observed-timestamp' | 'invalid' | MediaType.APPLICATION_XML | requestBodyXml || 0 | HttpStatus.BAD_REQUEST | expectedXmlData | ContentType.XML
}
def 'Save list elements #scenario.'() {
@@ -215,22 +218,25 @@ class DataRestControllerSpec extends Specification {
def parentNodeXpath = 'parent node xpath'
when: 'list-node endpoint is invoked with post (create) operation'
def postRequestBuilder = post("$dataNodeBaseEndpointV1/anchors/$anchorName/list-nodes")
- .contentType(MediaType.APPLICATION_JSON)
+ .contentType(contentType)
.param('xpath', parentNodeXpath)
- .content(requestBodyJson)
+ .content(requestBody)
if (observedTimestamp != null)
postRequestBuilder.param('observed-timestamp', observedTimestamp)
def response = mvc.perform(postRequestBuilder).andReturn().response
then: 'a created response is returned'
response.status == expectedHttpStatus.value()
then: 'the java API was called with the correct parameters'
- expectedApiCount * mockCpsDataService.saveListElements(dataspaceName, anchorName, parentNodeXpath, expectedJsonData,
- { it == DateTimeUtility.toOffsetDateTime(observedTimestamp) })
+ expectedApiCount * mockCpsDataService.saveListElements(dataspaceName, anchorName, parentNodeXpath, expectedData,
+ { it == DateTimeUtility.toOffsetDateTime(observedTimestamp) }, expectedContentType)
where:
- scenario | observedTimestamp || expectedApiCount | expectedHttpStatus
- 'with observed-timestamp' | '2021-03-03T23:59:59.999-0400' || 1 | HttpStatus.CREATED
- 'without observed-timestamp' | null || 1 | HttpStatus.CREATED
- 'with invalid observed-timestamp' | 'invalid' || 0 | HttpStatus.BAD_REQUEST
+ scenario | observedTimestamp | contentType | requestBody || expectedApiCount | expectedHttpStatus | expectedData | expectedContentType
+ 'Content type JSON with observed-timestamp' | '2021-03-03T23:59:59.999-0400' | MediaType.APPLICATION_JSON | requestBodyJson || 1 | HttpStatus.CREATED | expectedJsonData | ContentType.JSON
+ 'Content type JSON without observed-timestamp' | null | MediaType.APPLICATION_JSON | requestBodyJson || 1 | HttpStatus.CREATED | expectedJsonData | ContentType.JSON
+ 'Content type JSON with invalid observed-timestamp' | 'invalid' | MediaType.APPLICATION_JSON | requestBodyJson || 0 | HttpStatus.BAD_REQUEST | expectedJsonData | ContentType.JSON
+ 'Content type XML with observed-timestamp' | '2021-03-03T23:59:59.999-0400' | MediaType.APPLICATION_XML | requestBodyXml || 1 | HttpStatus.CREATED | expectedXmlData | ContentType.XML
+ 'Content type XML without observed-timestamp' | null | MediaType.APPLICATION_XML | requestBodyXml || 1 | HttpStatus.CREATED | expectedXmlData | ContentType.XML
+ 'Content type XML with invalid observed-timestamp' | 'invalid' | MediaType.APPLICATION_XML | requestBodyXml || 0 | HttpStatus.BAD_REQUEST | expectedXmlData | ContentType.XML
}
def 'Get data node with leaves'() {
@@ -346,7 +352,7 @@ class DataRestControllerSpec extends Specification {
given: 'the service returns a list containing delta reports'
def deltaReports = new DeltaReportBuilder().actionUpdate().withXpath('some xpath').withSourceData('some key': 'some value').withTargetData('some key': 'some value').build()
def xpath = 'some xpath'
- def endpoint = "$dataNodeBaseEndpointV2/anchors/sourceAnchor/deltaAnchors"
+ def endpoint = "$dataNodeBaseEndpointV2/anchors/sourceAnchor/delta"
mockCpsDataService.getDeltaByDataspaceAndAnchors(dataspaceName, 'sourceAnchor', 'targetAnchor', xpath, OMIT_DESCENDANTS) >> [deltaReports]
when: 'get delta request is performed using REST API'
def response =
@@ -364,7 +370,7 @@ class DataRestControllerSpec extends Specification {
given: 'sample delta report, xpath, yang model file and json payload'
def deltaReports = new DeltaReportBuilder().actionAdd().withXpath('some xpath').build()
def xpath = 'some xpath'
- def endpoint = "$dataNodeBaseEndpointV2/anchors/$anchorName/deltaPayload"
+ def endpoint = "$dataNodeBaseEndpointV2/anchors/$anchorName/delta"
and: 'the service layer returns a list containing delta reports'
mockCpsDataService.getDeltaByDataspaceAnchorAndPayload(dataspaceName, anchorName, xpath, ['filename.yang':'content'], expectedJsonData, INCLUDE_ALL_DESCENDANTS) >> [deltaReports]
when: 'get delta request is performed using REST API'
@@ -385,7 +391,7 @@ class DataRestControllerSpec extends Specification {
given: 'sample delta report, xpath, and json payload'
def deltaReports = new DeltaReportBuilder().actionRemove().withXpath('some xpath').build()
def xpath = 'some xpath'
- def endpoint = "$dataNodeBaseEndpointV2/anchors/$anchorName/deltaPayload"
+ def endpoint = "$dataNodeBaseEndpointV2/anchors/$anchorName/delta"
and: 'the service layer returns a list containing delta reports'
mockCpsDataService.getDeltaByDataspaceAnchorAndPayload(dataspaceName, anchorName, xpath, [:], expectedJsonData, INCLUDE_ALL_DESCENDANTS) >> [deltaReports]
when: 'get delta request is performed using REST API'
@@ -456,19 +462,22 @@ class DataRestControllerSpec extends Specification {
def response =
mvc.perform(
put(endpoint)
- .contentType(MediaType.APPLICATION_JSON)
- .content(requestBodyJson)
+ .contentType(contentType)
+ .content(requestBody)
.param('xpath', inputXpath))
.andReturn().response
then: 'the service method is invoked with expected parameters'
- 1 * mockCpsDataService.updateDataNodeAndDescendants(dataspaceName, anchorName, xpathServiceParameter, expectedJsonData, noTimestamp)
+ 1 * mockCpsDataService.updateDataNodeAndDescendants(dataspaceName, anchorName, xpathServiceParameter, expectedData, noTimestamp, expectedContentType)
and: 'response status indicates success'
response.status == HttpStatus.OK.value()
where:
- scenario | inputXpath || xpathServiceParameter
- 'root node by default' | '' || '/'
- 'root node by choice' | '/' || '/'
- 'some xpath by parent' | '/some/xpath' || '/some/xpath'
+ scenario | inputXpath | contentType || xpathServiceParameter | requestBody | expectedData | expectedContentType
+ 'JSON content: root node by default' | '' | MediaType.APPLICATION_JSON || '/' | requestBodyJson | expectedJsonData | ContentType.JSON
+ 'JSON content: root node by choice' | '/' | MediaType.APPLICATION_JSON || '/' | requestBodyJson | expectedJsonData | ContentType.JSON
+ 'JSON content: some xpath by parent' | '/some/xpath' | MediaType.APPLICATION_JSON || '/some/xpath' | requestBodyJson | expectedJsonData | ContentType.JSON
+ 'XML content: root node by default' | '' | MediaType.APPLICATION_XML || '/' | requestBodyXml | expectedXmlData | ContentType.XML
+ 'XML content: root node by choice' | '/' | MediaType.APPLICATION_XML || '/' | requestBodyXml | expectedXmlData | ContentType.XML
+ 'XML content: some xpath by parent' | '/some/xpath' | MediaType.APPLICATION_XML || '/some/xpath' | requestBodyXml | expectedXmlData | ContentType.XML
}
def 'Update data node and descendants with observedTimestamp.'() {
@@ -485,7 +494,7 @@ class DataRestControllerSpec extends Specification {
.andReturn().response
then: 'the service method is invoked with expected parameters'
expectedApiCount * mockCpsDataService.updateDataNodeAndDescendants(dataspaceName, anchorName, '/', expectedJsonData,
- { it == DateTimeUtility.toOffsetDateTime(observedTimestamp) })
+ { it == DateTimeUtility.toOffsetDateTime(observedTimestamp) }, ContentType.JSON)
and: 'response status indicates success'
response.status == expectedHttpStatus.value()
where:
diff --git a/cps-ri/pom.xml b/cps-ri/pom.xml
index 14a091fcb..12300cad5 100644
--- a/cps-ri/pom.xml
+++ b/cps-ri/pom.xml
@@ -26,7 +26,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-service/pom.xml b/cps-service/pom.xml
index 2564ceb98..51faf6a63 100644
--- a/cps-service/pom.xml
+++ b/cps-service/pom.xml
@@ -29,7 +29,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java b/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java
index f396b49e6..68e1880d7 100644
--- a/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java
+++ b/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java
@@ -55,7 +55,7 @@ public interface CpsDataService {
* @param anchorName anchor name
* @param nodeData node data
* @param observedTimestamp observedTimestamp
- * @param contentType node data content type
+ * @param contentType JSON/XML content type
*/
void saveData(String dataspaceName, String anchorName, String nodeData, OffsetDateTime observedTimestamp,
ContentType contentType);
@@ -80,7 +80,7 @@ public interface CpsDataService {
* @param parentNodeXpath parent node xpath
* @param nodeData node data
* @param observedTimestamp observedTimestamp
- * @param contentType node data content type
+ * @param contentType JSON/XML content type
*
*/
void saveData(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData,
@@ -93,11 +93,12 @@ public interface CpsDataService {
* @param dataspaceName dataspace name
* @param anchorName anchor name
* @param parentNodeXpath parent node xpath
- * @param jsonData json data representing list element(s)
+ * @param nodeData node data representing list element(s)
* @param observedTimestamp observedTimestamp
+ * @param contentType JSON/XML content type
*/
- void saveListElements(String dataspaceName, String anchorName, String parentNodeXpath, String jsonData,
- OffsetDateTime observedTimestamp);
+ void saveListElements(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData,
+ OffsetDateTime observedTimestamp, ContentType contentType);
/**
* Retrieves all the datanodes by XPath for given dataspace and anchor.
@@ -134,7 +135,7 @@ public interface CpsDataService {
* @param parentNodeXpath xpath to parent node
* @param nodeData node data
* @param observedTimestamp observedTimestamp
- * @param contentType node data content type
+ * @param contentType JSON/XML content type
*/
void updateNodeLeaves(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData,
OffsetDateTime observedTimestamp, ContentType contentType);
@@ -145,22 +146,24 @@ public interface CpsDataService {
* @param dataspaceName dataspace name
* @param anchorName anchor name
* @param parentNodeXpath xpath to parent node
- * @param jsonData json data
+ * @param nodeData node data
* @param observedTimestamp observedTimestamp
+ * @param contentType JSON/XML content type
*/
- void updateDataNodeAndDescendants(String dataspaceName, String anchorName, String parentNodeXpath, String jsonData,
- OffsetDateTime observedTimestamp);
+ void updateDataNodeAndDescendants(String dataspaceName, String anchorName, String parentNodeXpath, String nodeData,
+ OffsetDateTime observedTimestamp, ContentType contentType);
/**
* Replaces multiple existing data nodes' content including descendants in a batch operation.
*
* @param dataspaceName dataspace name
* @param anchorName anchor name
- * @param nodesJsonData map of xpath and node JSON data
+ * @param nodeDataPerXPath map of xpath and node JSON/XML data
* @param observedTimestamp observedTimestamp
+ * @param contentType JSON/XML content type
*/
- void updateDataNodesAndDescendants(String dataspaceName, String anchorName, Map<String, String> nodesJsonData,
- OffsetDateTime observedTimestamp);
+ void updateDataNodesAndDescendants(String dataspaceName, String anchorName, Map<String, String> nodeDataPerXPath,
+ OffsetDateTime observedTimestamp, ContentType contentType);
/**
* Replaces list content by removing all existing elements and inserting the given new elements as json
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
index 5a4842877..165d62ced 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
@@ -119,12 +119,13 @@ public class CpsDataServiceImpl implements CpsDataService {
@Override
@Timed(value = "cps.data.service.list.element.save",
description = "Time taken to save list elements")
- public void saveListElements(final String dataspaceName, final String anchorName, final String parentNodeXpath,
- final String jsonData, final OffsetDateTime observedTimestamp) {
+ public void saveListElements(final String dataspaceName, final String anchorName,
+ final String parentNodeXpath, final String nodeData,
+ final OffsetDateTime observedTimestamp, final ContentType contentType) {
cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
final Collection<DataNode> listElementDataNodeCollection =
- buildDataNodesWithParentNodeXpath(anchor, parentNodeXpath, jsonData, ContentType.JSON);
+ buildDataNodesWithParentNodeXpath(anchor, parentNodeXpath, nodeData, contentType);
if (isRootNodeXpath(parentNodeXpath)) {
cpsDataPersistenceService.storeDataNodes(dataspaceName, anchorName, listElementDataNodeCollection);
} else {
@@ -251,12 +252,12 @@ public class CpsDataServiceImpl implements CpsDataService {
@Timed(value = "cps.data.service.datanode.descendants.update",
description = "Time taken to update a data node and descendants")
public void updateDataNodeAndDescendants(final String dataspaceName, final String anchorName,
- final String parentNodeXpath, final String jsonData,
- final OffsetDateTime observedTimestamp) {
+ final String parentNodeXpath, final String nodeData,
+ final OffsetDateTime observedTimestamp, final ContentType contentType) {
cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
final Collection<DataNode> dataNodes =
- buildDataNodesWithParentNodeXpath(anchor, parentNodeXpath, jsonData, ContentType.JSON);
+ buildDataNodesWithParentNodeXpath(anchor, parentNodeXpath, nodeData, contentType);
cpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, dataNodes);
sendDataUpdatedEvent(anchor, parentNodeXpath, Operation.UPDATE, observedTimestamp);
}
@@ -265,13 +266,13 @@ public class CpsDataServiceImpl implements CpsDataService {
@Timed(value = "cps.data.service.datanode.descendants.batch.update",
description = "Time taken to update a batch of data nodes and descendants")
public void updateDataNodesAndDescendants(final String dataspaceName, final String anchorName,
- final Map<String, String> nodesJsonData,
- final OffsetDateTime observedTimestamp) {
+ final Map<String, String> nodeDataPerXPath,
+ final OffsetDateTime observedTimestamp, final ContentType contentType) {
cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final Anchor anchor = cpsAnchorService.getAnchor(dataspaceName, anchorName);
- final Collection<DataNode> dataNodes = buildDataNodesWithParentNodeXpath(anchor, nodesJsonData);
+ final Collection<DataNode> dataNodes = buildDataNodesWithParentNodeXpath(anchor, nodeDataPerXPath, contentType);
cpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, dataNodes);
- nodesJsonData.keySet().forEach(nodeXpath ->
+ nodeDataPerXPath.keySet().forEach(nodeXpath ->
sendDataUpdatedEvent(anchor, nodeXpath, Operation.UPDATE, observedTimestamp));
}
@@ -408,11 +409,12 @@ public class CpsDataServiceImpl implements CpsDataService {
}
private Collection<DataNode> buildDataNodesWithParentNodeXpath(final Anchor anchor,
- final Map<String, String> nodesJsonData) {
+ final Map<String, String> nodesJsonData,
+ final ContentType contentType) {
final Collection<DataNode> dataNodes = new ArrayList<>();
for (final Map.Entry<String, String> nodeJsonData : nodesJsonData.entrySet()) {
dataNodes.addAll(buildDataNodesWithParentNodeXpath(anchor, nodeJsonData.getKey(),
- nodeJsonData.getValue(), ContentType.JSON));
+ nodeJsonData.getValue(), contentType));
}
return dataNodes;
}
diff --git a/cps-service/src/main/java/org/onap/cps/utils/YangParserHelper.java b/cps-service/src/main/java/org/onap/cps/utils/YangParserHelper.java
index 5cadd2936..597164598 100644
--- a/cps-service/src/main/java/org/onap/cps/utils/YangParserHelper.java
+++ b/cps-service/src/main/java/org/onap/cps/utils/YangParserHelper.java
@@ -120,13 +120,9 @@ public class YangParserHelper {
try (jsonParserStream) {
jsonParserStream.parse(jsonReader);
- } catch (final IOException | JsonSyntaxException exception) {
+ } catch (final IOException | JsonSyntaxException | IllegalStateException | IllegalArgumentException exception) {
throw new DataValidationException(
- "Failed to parse json data: " + jsonData, exception.getMessage(), exception);
- } catch (final IllegalStateException | IllegalArgumentException exception) {
- throw new DataValidationException(
- "Failed to parse json data. Unsupported xpath or json data:" + jsonData, exception
- .getMessage(), exception);
+ "Data Validation Failed", "Failed to parse json data. " + exception.getMessage(), exception);
}
return dataContainerNodeBuilder.build();
}
@@ -168,7 +164,7 @@ public class YangParserHelper {
} catch (final XMLStreamException | URISyntaxException | IOException | SAXException | NullPointerException
| ParserConfigurationException | TransformerException exception) {
throw new DataValidationException(
- "Failed to parse xml data: " + xmlData, exception.getMessage(), exception);
+ "Data Validation Failed", "Failed to parse xml data: " + exception.getMessage(), exception);
}
final DataContainerChild dataContainerChild =
(DataContainerChild) getFirstChildXmlRoot(normalizedNodeResult.getResult());
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
index 4e5807ec8..a296716b5 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
@@ -132,8 +132,8 @@ class CpsDataServiceImplSpec extends Specification {
where: 'given parameters'
scenario | invalidData | contentType || expectedMessage
'no data nodes' | '{}' | ContentType.JSON || 'No data nodes'
- 'invalid json' | '{invalid json' | ContentType.JSON || 'Failed to parse json data'
- 'invalid xml' | '<invalid xml' | ContentType.XML || 'Failed to parse xml data'
+ 'invalid json' | '{invalid json' | ContentType.JSON || 'Data Validation Failed'
+ 'invalid xml' | '<invalid xml' | ContentType.XML || 'Data Validation Failed'
}
def 'Saving list element data fragment under Root node.'() {
@@ -141,7 +141,7 @@ class CpsDataServiceImplSpec extends Specification {
setupSchemaSetMocks('bookstore.yang')
when: 'save data method is invoked with list element json data'
def jsonData = '{"bookstore-address":[{"bookstore-name":"Easons","address":"Dublin,Ireland","postal-code":"D02HA21"}]}'
- objectUnderTest.saveListElements(dataspaceName, anchorName, '/', jsonData, observedTimestamp)
+ objectUnderTest.saveListElements(dataspaceName, anchorName, '/', jsonData, observedTimestamp, ContentType.JSON)
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.storeDataNodes(dataspaceName, anchorName,
{ dataNodeCollection ->
@@ -169,12 +169,11 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
}
- def 'Saving list element data fragment under existing node.'() {
+ def 'Saving list element data fragment under existing JSON/XML node.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
- when: 'save data method is invoked with list element json data'
- def jsonData = '{"branch": [{"name": "A"}, {"name": "B"}]}'
- objectUnderTest.saveListElements(dataspaceName, anchorName, '/test-tree', jsonData, observedTimestamp)
+ when: 'save data method is invoked with list element data'
+ objectUnderTest.saveListElements(dataspaceName, anchorName, '/test-tree', data, observedTimestamp, contentType)
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.addListElements(dataspaceName, anchorName, '/test-tree',
{ dataNodeCollection ->
@@ -187,16 +186,23 @@ class CpsDataServiceImplSpec extends Specification {
)
and: 'the CpsValidator is called on the dataspaceName and AnchorName'
1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
+ where:
+ data | contentType
+ '{"branch": [{"name": "A"}, {"name": "B"}]}' | ContentType.JSON
+ '<test-tree xmlns="org:onap:cps:test:test-tree"><branch><name>A</name></branch><branch><name>B</name></branch></test-tree>' | ContentType.XML
}
- def 'Saving empty list element data fragment.'() {
+ def 'Saving empty list element data fragment for JSON/XML data.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
when: 'save data method is invoked with an empty list'
- def jsonData = '{"branch": []}'
- objectUnderTest.saveListElements(dataspaceName, anchorName, '/test-tree', jsonData, observedTimestamp)
+ objectUnderTest.saveListElements(dataspaceName, anchorName, '/test-tree', data, observedTimestamp, contentType)
then: 'invalid data exception is thrown'
thrown(DataValidationException)
+ where:
+ data | contentType
+ '{"branch": []}' | ContentType.JSON
+ '<test-tree><branch></branch></test-tree>' | ContentType.XML
}
def 'Get all data nodes #scenario.'() {
@@ -362,11 +368,11 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
}
- def 'Replace data node using singular data node: #scenario.'() {
+ def 'Replace data node using singular JSON data node: #scenario.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
when: 'replace data method is invoked with json data #jsonData and parent node xpath #parentNodeXpath'
- objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, jsonData, observedTimestamp)
+ objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, jsonData, observedTimestamp, ContentType.JSON)
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
{ dataNode -> dataNode.xpath == expectedNodeXpath})
@@ -379,30 +385,63 @@ class CpsDataServiceImplSpec extends Specification {
'json list' | '/test-tree' | '{"branch": [{"name":"Name1"}, {"name":"Name2"}]}' || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"]
}
- def 'Replace data node using multiple data nodes: #scenario.'() {
+ def 'Replace data node using singular XML data node: #scenario.'() {
+ given: 'schema set for given anchor and dataspace references test-tree model'
+ setupSchemaSetMocks('test-tree.yang')
+ when: 'replace data method is invoked with XML data #xmlData and parent node xpath #parentNodeXpath'
+ objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, xmlData, observedTimestamp, ContentType.XML)
+ then: 'the persistence service method is invoked with correct parameters'
+ 1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
+ { dataNode -> dataNode.xpath == expectedNodeXpath })
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
+ where: 'following parameters were used'
+ scenario | parentNodeXpath | xmlData || expectedNodeXpath
+ 'level 2 node' | '/test-tree' | '<branch><name>Name</name></branch>' || ['/test-tree/branch[@name=\'Name\']']
+ 'xml list' | '/test-tree' | '<test-tree xmlns="org:onap:cps:test:test-tree"><branch><name>Name1</name></branch>' + '<branch><name>Name2</name></branch></test-tree>' || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"]
+ }
+
+ def 'Replace data node using multiple JSON data nodes: #scenario.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
when: 'replace data method is invoked with a map of xpaths and json data'
- objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, nodesJsonData, observedTimestamp)
+ objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, nodeDataPerXPath, observedTimestamp, ContentType.JSON)
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
{ dataNode -> dataNode.xpath == expectedNodeXpath})
and: 'the CpsValidator is called on the dataspaceName and AnchorName'
1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
where: 'following parameters were used'
- scenario | nodesJsonData || expectedNodeXpath
+ scenario | nodeDataPerXPath || expectedNodeXpath
'top level node' | ['/' : '{"test-tree": {"branch": []}}', '/test-tree' : '{"branch": [{"name":"Name"}]}'] || ["/test-tree", "/test-tree/branch[@name='Name']"]
'level 2 node' | ['/test-tree' : '{"branch": [{"name":"Name"}]}', '/test-tree/branch[@name=\'Name\']':'{"nest":{"name":"nestName"}}'] || ["/test-tree/branch[@name='Name']", "/test-tree/branch[@name='Name']/nest"]
'json list' | ['/test-tree' : '{"branch": [{"name":"Name1"}, {"name":"Name2"}]}'] || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"]
}
+ def 'Replace data node using multiple XML data nodes: #scenario.'() {
+ given: 'schema set for given anchor and dataspace references test-tree model'
+ setupSchemaSetMocks('test-tree.yang')
+ when: 'replace data method is invoked with a map of xpaths and XML data'
+ objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, nodeXmlDataPerXPath, observedTimestamp, ContentType.XML)
+ then: 'the persistence service method is invoked with correct parameters'
+ 1 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName,
+ { dataNode -> dataNode.xpath == expectedNodeXpath })
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
+ where: 'following parameters were used'
+ scenario | nodeXmlDataPerXPath || expectedNodeXpath
+ 'top level node' | ['/test-tree': '<branch><name>Name</name></branch>'] || ["/test-tree/branch[@name='Name']"]
+ 'level 2 node' | ['/test-tree': '<branch><name>Name</name></branch>', '/test-tree/branch[@name=\'Name\']': '<nest><name>nestName</name></nest>'] || ["/test-tree/branch[@name='Name']", "/test-tree/branch[@name='Name']/nest"]
+ 'xml list' | ['/test-tree': '<test-tree xmlns="org:onap:cps:test:test-tree"><branch><name>Name1</name></branch>' + '<branch><name>Name2</name></branch></test-tree>'] || ["/test-tree/branch[@name='Name1']", "/test-tree/branch[@name='Name2']"]
+ }
+
def 'Replace data node with concurrency exception in persistence layer.'() {
given: 'the persistence layer throws an concurrency exception'
def originalException = new ConcurrencyException('message', 'details')
mockCpsDataPersistenceService.updateDataNodesAndDescendants(*_) >> { throw originalException }
setupSchemaSetMocks('test-tree.yang')
when: 'attempt to replace data node'
- objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, ['/' : '{"test-tree": {}}'] , observedTimestamp)
+ objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, ['/' : '{"test-tree": {}}'] , observedTimestamp, ContentType.JSON)
then: 'the same exception is thrown up'
def thrownUp = thrown(ConcurrencyException)
assert thrownUp == originalException
diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy
index 8cbd49355..09d45b92c 100644
--- a/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/utils/JsonObjectMapperSpec.groovy
@@ -42,7 +42,7 @@ class JsonObjectMapperSpec extends Specification {
def contentMap = new JsonSlurper().parseText(new String(content))
and: 'the parsed content is as expected'
assert contentMap.'test:bookstore'.'bookstore-name' == 'Chapters/Easons'
- where: 'the following data stores are used'
+ where: 'the following content types are used'
type << ['String', 'bytes']
}
diff --git a/csit/plans/cps/pnfsim/docker-compose.yml b/csit/plans/cps/pnfsim/docker-compose.yml
index e0f21a2ce..4438729f2 100644
--- a/csit/plans/cps/pnfsim/docker-compose.yml
+++ b/csit/plans/cps/pnfsim/docker-compose.yml
@@ -1,5 +1,5 @@
# ============LICENSE_START=======================================================
-# Modifications Copyright (C) 2022 Nordix Foundation
+# Modifications Copyright (C) 2022-2024 Nordix Foundation
# ================================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,3 +24,4 @@ services:
- "6512:6513"
volumes:
- ./netconf-config:/config/modules/stores
+ - ./tls:/config/tls
diff --git a/csit/plans/cps/pnfsim/tls/ca.pem b/csit/plans/cps/pnfsim/tls/ca.pem
new file mode 100644
index 000000000..4c4473815
--- /dev/null
+++ b/csit/plans/cps/pnfsim/tls/ca.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID2zCCAsOgAwIBAgIUWDactJMMP2Q2mw0yBnUfQXRsXZMwDQYJKoZIhvcNAQEF
+BQAwfTELMAkGA1UEBhMCSUUxEjAQBgNVBAgMCVdlc3RtZWF0aDEQMA4GA1UEBwwH
+QXRobG9uZTEPMA0GA1UECgwGTm9yZGl4MRMwEQYDVQQDDApleGFtcGxlIENBMSIw
+IAYJKoZIhvcNAQkBFhNleGFtcGxlY2FAbG9jYWxob3N0MB4XDTI0MDcyNDExMzMw
+N1oXDTM0MDcyMjExMzMwN1owfTELMAkGA1UEBhMCSUUxEjAQBgNVBAgMCVdlc3Rt
+ZWF0aDEQMA4GA1UEBwwHQXRobG9uZTEPMA0GA1UECgwGTm9yZGl4MRMwEQYDVQQD
+DApleGFtcGxlIENBMSIwIAYJKoZIhvcNAQkBFhNleGFtcGxlY2FAbG9jYWxob3N0
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1mNXPz3Vx4l9zhKt7uBm
+8RFebZchO1WjAN5NiIVhVG9Vfktz3DVCbWYpZKwjRrf0g1vBbZk//6qCp6qhHB9m
+4KoDPR1Eu9SX9rri3TD1HWW05HRgxa5j/pk5PCt3/4+eZ31hKcJGsfJ1SwYDk3F/
+bUzgfZ5e4+2LDMgKmKtuhTzQP6ITmqpCN02nEKElDUXgTffo8QBwqnUN91vRmYnC
+9nfD68ipu2Nl19Jam0MRVue2kaZUXF4nisomY4Zmpcf45D6XAdUKMx5wr/kWULIc
+Dz2jE0BkOb/2GCT+sOMnI9riq2X3CoII2wn0NUw0oLYA6lKO5ICZ40w9LfCjeo/r
+yQIDAQABo1MwUTAdBgNVHQ4EFgQUa9fiOtMAq5lM20SZe3jHUnwaQHMwHwYDVR0j
+BBgwFoAUa9fiOtMAq5lM20SZe3jHUnwaQHMwDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQUFAAOCAQEADys2rDXMYcjzhMhx0XJtty8STfBsWcsBfcVgwmt1vVwt
+buVn03vCVd90lj+5yqzr9OIntGEt/Mcw4Ca6rxl9bs+XGFxWo0McTxxXEZ5SRFK5
+ISRhWXWfmkxfiZalEymqKT4Xia8+Kydt0jsl93nUNA90GCQki7ngSCkOwoR4yizI
+eT6D/G5oTymEaKt8CuU+eBxQdD1kd6sSeKqXn4WY0dAClPk2VCjMuMYeYB6UWSL3
+HjSaDV4SQnCrvRNQzMJs/zONLPnt05N2GUho30LrXQ0h7zmkYl8AglfEtoCdXnRn
+ikOwkZ/N9V5K8NWJ0yQ5axftH6uxLMQgWIdhL32S0Q==
+-----END CERTIFICATE-----
diff --git a/csit/plans/cps/pnfsim/tls/server_cert.pem b/csit/plans/cps/pnfsim/tls/server_cert.pem
new file mode 100644
index 000000000..a022dc56c
--- /dev/null
+++ b/csit/plans/cps/pnfsim/tls/server_cert.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDijCCAnICFHAVskmbiSw4Q3eiKO6EJw48IS9EMA0GCSqGSIb3DQEBBQUAMH0x
+CzAJBgNVBAYTAklFMRIwEAYDVQQIDAlXZXN0bWVhdGgxEDAOBgNVBAcMB0F0aGxv
+bmUxDzANBgNVBAoMBk5vcmRpeDETMBEGA1UEAwwKZXhhbXBsZSBDQTEiMCAGCSqG
+SIb3DQEJARYTZXhhbXBsZWNhQGxvY2FsaG9zdDAeFw0yNDA3MjQxMTMzMzhaFw0z
+NDA3MjIxMTMzMzhaMIGFMQswCQYDVQQGEwJJRTESMBAGA1UECAwJV2VzdG1lYXRo
+MRAwDgYDVQQHDAdBdGhsb25lMQ8wDQYDVQQKDAZOb3JkaXgxFzAVBgNVBAMMDmV4
+YW1wbGUgc2VydmVyMSYwJAYJKoZIhvcNAQkBFhdleGFtcGxlc2VydmVyQGxvY2Fs
+aG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALyFCBXEqZ39N7ZZ
+TEU8VJ03bY+kbTCfx9SOL/rP3X9zFOfv0g1TXEx2Yzl/LfRe1N5SgOB24tE34obA
+f++bOGXrsptrZMC5aqlG7cOfjELybUJaUIqMEDX+dte1f7OmPGs0mt2gG4DSU47j
+zGg3KshexLZUGc1fwPnUrBnEPFRCMWIqgSWkC4RrhB9R/uo/eBMh1coH+rSUE/Ba
+vcHlI8orbPu/mupt7tBKapb85nmSglatkZ/YCmfrrm4g5n8jap3e5rO8bs62yYeN
+BF2mHRLOwU+2VmQ1h6L+X0m6hC54UF9WdWyEd02o0HHDr1hDrg3aqrah+dnU+rgM
+hPu8ofkCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAzoHPz0msIst3sT0fQxjqYxYo
+TnU0XzFsMvGC08wbz/iNOS+nvcMuRgG06CUj53BJvdmZPhSfqiYcInM3F4m1MrbM
+dK6L6Vk2eWaL4GwV6B7FR0CWjtTdlETkLSMBNufiqgHebZCT88JDAZAeqhdEbsqk
+7bnZVDdD0qA1Z9ClXFU3jO6n8f5EFn9Ai7FhD7floLHb9M0lheE8xO60RPXNmq/r
+Vf8HrBGHqpiumsMyAuwJONliuSEXNGuB+J+XeQJG91O1oR4Of34HUEZBT/BkoM0X
+iFB+xrLbShsTh1RbAdd1+t76Lsc1lkDVoupaTpdTXA0EmouS9O3CAFWfTjlcGg==
+-----END CERTIFICATE-----
diff --git a/csit/plans/cps/pnfsim/tls/server_key.pem b/csit/plans/cps/pnfsim/tls/server_key.pem
new file mode 100644
index 000000000..02fd68846
--- /dev/null
+++ b/csit/plans/cps/pnfsim/tls/server_key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8hQgVxKmd/Te2
+WUxFPFSdN22PpG0wn8fUji/6z91/cxTn79INU1xMdmM5fy30XtTeUoDgduLRN+KG
+wH/vmzhl67Kba2TAuWqpRu3Dn4xC8m1CWlCKjBA1/nbXtX+zpjxrNJrdoBuA0lOO
+48xoNyrIXsS2VBnNX8D51KwZxDxUQjFiKoElpAuEa4QfUf7qP3gTIdXKB/q0lBPw
+Wr3B5SPKK2z7v5rqbe7QSmqW/OZ5koJWrZGf2Apn665uIOZ/I2qd3uazvG7OtsmH
+jQRdph0SzsFPtlZkNYei/l9JuoQueFBfVnVshHdNqNBxw69YQ64N2qq2ofnZ1Pq4
+DIT7vKH5AgMBAAECggEAAJNHWwmmmtzS9rN/EBcHCxPIOc/+pU9XhMaKTvGjc2ge
+gDazJWdDuNgDpYFF2qEPdT47NnQmbQ0Gm/KqcUi/+0+k0+SYAh6OvMWCpD4wZ2Pm
+AXXVGRckVYXZRv8+zIWNWaZncpWyf8okhyMa1JaWgtYHM6c+DOpl5F1JySpYJMmt
+laWH0fMCYdYM5N8RisXfImmf+bBcehIZFvq47f5LefvPBHCss/L+Nym/ypMl+qo1
+MvVPkMNIhJFb/NQSYknp5ino2uo06RNOhftu/ig8CgzuSYvK18Ia9NEAKd2kS/y7
+MtYipgBCQqax5ulYmDAmnSrm+KpNhfk+CcMBlW9yoQKBgQDboMRpUMyinK9jrY7R
+GqISWcrDRFEwKfPr0rFtBZM/0ODjZBXMDSej28LwCo+6Vo8dF4G9fValuyyrNMQl
+T0OpcDxBKV3yCHZoXmzTKx/vcF56hOgkpwT8gHWpVsqVxcjIyERZrynblMnZixcv
+ppF33YJv8A7oParHGnj9zqWvVwKBgQDbvWlV7/CV5y5kYnNKLIZ51xaTZpAt1CE7
+N4B4x41y+jTGtscQoDlIMgOydC8F+dBeolvMXEyN002pYj8K9yxQcHCz2F62A2na
+ZA+Vj6xTq2/YGhBBrJ21eaEOcKBc9rrP0s2lzhzVb/fbPq0hkgWqQuJKsHaq2y9O
+fYUBfbB3LwKBgEexPgwmzPXT8ci28eS+LeORngeJuHrhZvc26qXs6Pku5Qo1NIxM
+SwFJDmQu/mXUNZlIgBhr3qnw5I7qhZCsRCj+Mx0ONNV5/7ToBdwUurL9WkniMqks
+QAtwn3fsleq4CmfIP8+Kxz4fXph9t87dL6USEK8bjLIw1xtxP8eR+jG3AoGAcuM4
+ZLcbqbSCW/fhYWGgOanMYurX7S4g5c4h/IQRH5FT8KV1tOqgqG+F4VK/lzdCy4fF
+yTZkzC4zR6FXZstOvwva0R0Kf82PFaEFSOQibGiRBIK0BzJSDqT2IQ+fuJtDlw8X
+eF4oUyvEgjvl10x6a8emeviCQthwhnA4D0yA6/8CgYEA14WLsOllb6IjO3c+mwFp
+Gs8pDrB/XPH7bPH1fVO+60OMT5OMTlEa/cVlhbNWuHVR7+yVQCh7HuzVPBtSdyNW
+4+8UuAz3eLm93he6DiH7D4U7Zx2TKB2B6PBbHz9aEh96l67TfAHy+u3x0mVFziZ7
+HNe49uMd7A5r4QgflshgDgs=
+-----END PRIVATE KEY-----
diff --git a/csit/plans/cps/sdnc/certs/keys0.zip b/csit/plans/cps/sdnc/certs/keys0.zip
index 48b4d90a1..b2dec5c7b 100644
--- a/csit/plans/cps/sdnc/certs/keys0.zip
+++ b/csit/plans/cps/sdnc/certs/keys0.zip
Binary files differ
diff --git a/csit/plans/cps/teardown.sh b/csit/plans/cps/teardown.sh
index 7beb90722..e2ecd885b 100755
--- a/csit/plans/cps/teardown.sh
+++ b/csit/plans/cps/teardown.sh
@@ -17,18 +17,24 @@
# Modifications copyright (c) 2017 AT&T Intellectual Property
# Modifications copyright (c) 2020 Samsung Electronics Co., Ltd.
# Modifications Copyright (C) 2021 Pantheon.tech
-# Modifications Copyright (C) 2021 Nordix Foundation
+# Modifications Copyright (C) 2021-2024 Nordix Foundation
# Branched from ccsdk/distribution to this repository Feb 23, 2021
#
echo '================================== docker info =========================='
docker ps -a
echo '================================== CPS-NCMP Logs ========================'
-docker logs cps-and-ncmp
+for CONTAINER_ID in $(docker ps --filter "name=cps-and-ncmp" --format "{{.ID}}"); do
+ echo "CPS-NCMP Logs for container: $CONTAINER_ID"
+ docker logs "$CONTAINER_ID"
+done
echo '================================== DMI Logs ============================='
docker logs ncmp-dmi-plugin
+echo '================================== DMI Stub Logs ========================'
+docker logs ncmp-dmi-plugin-demo-and-csit-stub
+
echo '================================== SDNC Logs ============================'
docker logs sdnc
diff --git a/csit/plans/cps/testplanNcmp.txt b/csit/plans/cps/testplanNcmp.txt
index e80f0d98a..24c7745c7 100644
--- a/csit/plans/cps/testplanNcmp.txt
+++ b/csit/plans/cps/testplanNcmp.txt
@@ -21,4 +21,4 @@ cps-data-sync
ncmp-passthrough
cm-handle-query
cps-trust-level
-cps-data-operations \ No newline at end of file
+cps-data-operations
diff --git a/csit/run-csit.sh b/csit/run-csit.sh
index 0981fc6ed..93941e216 100755
--- a/csit/run-csit.sh
+++ b/csit/run-csit.sh
@@ -2,6 +2,7 @@
#
# Copyright 2016-2017 Huawei Technologies Co., Ltd.
# Modification Copyright 2019-2021 © Samsung Electronics Co., Ltd.
+# Modification Copyright (C) 2024 Nordix Foundation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
diff --git a/csit/tests/cps-data-sync/cps-data-sync.robot b/csit/tests/cps-data-sync/cps-data-sync.robot
index c0ee4da67..2de03b073 100644
--- a/csit/tests/cps-data-sync/cps-data-sync.robot
+++ b/csit/tests/cps-data-sync/cps-data-sync.robot
@@ -54,7 +54,7 @@ Operational state goes to UNSYNCHRONIZED when data sync (flag) is enabled
Operational state goes to SYNCHRONIZED after sometime when data sync (flag) is enabled
${uri}= Set Variable ${ncmpBasePath}/v1/ch/ietfYang-PNFDemo/state
${headers}= Create Dictionary Authorization=${auth}
- Wait Until Keyword Succeeds 10sec 100ms Is CM Handle State SYNCHRONIZED ${uri} ${headers}
+ Wait Until Keyword Succeeds 40sec 100ms Is CM Handle State SYNCHRONIZED ${uri} ${headers}
*** Keywords ***
Is CM Handle READY
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml
deleted file mode 100644
index 3a678f6dd..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ============LICENSE_START=======================================================
- Copyright (C) 2023-2024 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=========================================================
--->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.onap.cps</groupId>
- <artifactId>dmi-plugin-demo-and-csit-stub</artifactId>
- <version>3.5.1-SNAPSHOT</version>
- </parent>
-
- <artifactId>dmi-plugin-demo-and-csit-stub-app</artifactId>
-
- <properties>
- <app>org.onap.cps.ncmp.dmi.rest.stub.DmiDemoApplication</app>
- <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
- <base.image>${docker.pull.registry}/onap/integration-java17:12.0.0</base.image>
- <image.tag>${project.version}-${maven.build.timestamp}</image.tag>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
-
- <build>
- <pluginManagement>
- <plugins>
- <plugin>
- <groupId>com.google.cloud.tools</groupId>
- <artifactId>jib-maven-plugin</artifactId>
- <configuration>
- <container>
- <mainClass>${app}</mainClass>
- <creationTime>USE_CURRENT_TIMESTAMP</creationTime>
- </container>
- <from>
- <image>${base.image}</image>
- </from>
- <to>
- <tags>
- <tag>latest</tag>
- </tags>
- <image>${docker.push.registry}/onap/${image.name}:${image.tag}</image>
- </to>
- </configuration>
- <executions>
- <execution>
- <phase>package</phase>
- <id>build</id>
- <goals>
- <goal>dockerBuild</goal>
- </goals>
- </execution>
- <execution>
- <phase>deploy</phase>
- <id>buildAndPush</id>
- <goals>
- <goal>build</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </pluginManagement>
- </build>
-
- <profiles>
- <profile>
- <id>docker</id>
- <activation>
- <activeByDefault>true</activeByDefault>
- </activation>
- <properties>
- <image.name>dmi-plugin-demo-and-csit-stub</image.name>
- </properties>
- <build>
- <plugins>
- <plugin>
- <groupId>com.google.cloud.tools</groupId>
- <artifactId>jib-maven-plugin</artifactId>
- <version>3.3.2</version>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
- <dependencies>
- <dependency>
- <groupId>org.onap.cps</groupId>
- <artifactId>dmi-plugin-demo-and-csit-stub-service</artifactId>
- <version>${project.version}</version>
- <exclusions>
- <exclusion>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- </dependencies>
-</project> \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/config/NcmpRequestLoggingConfig.java b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/config/NcmpRequestLoggingConfig.java
deleted file mode 100644
index e91f48f78..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/config/NcmpRequestLoggingConfig.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2024 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.dmi.rest.stub.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.filter.CommonsRequestLoggingFilter;
-
-@Configuration
-public class NcmpRequestLoggingConfig {
-
- /**
- * Configuration class to log NCMP request headers and payload.
- * logged request information before it is processed.
- */
- @Bean
- public CommonsRequestLoggingFilter logNcmpRequestInfo() {
- final CommonsRequestLoggingFilter commonsRequestLoggingFilter = new CommonsRequestLoggingFilter();
- commonsRequestLoggingFilter.setIncludeHeaders(true);
- commonsRequestLoggingFilter.setIncludeQueryString(true);
- commonsRequestLoggingFilter.setIncludePayload(true);
- commonsRequestLoggingFilter.setMaxPayloadLength(1000);
- commonsRequestLoggingFilter.setAfterMessagePrefix("NCMP REQUEST DATA: ");
- return commonsRequestLoggingFilter;
- }
-}
-
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml
deleted file mode 100644
index 73469de59..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<!--
- ============LICENSE_START=======================================================
- Copyright (C) 2023-2024 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=========================================================
--->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.onap.cps</groupId>
- <artifactId>dmi-plugin-demo-and-csit-stub</artifactId>
- <version>3.5.1-SNAPSHOT</version>
- </parent>
- <artifactId>dmi-plugin-demo-and-csit-stub-service</artifactId>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- <exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-tomcat</artifactId>
- </exclusion>
- </exclusions>
- <scope>compile</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
- <dependency>
- <groupId>com.googlecode.json-simple</groupId>
- <artifactId>json-simple</artifactId>
- <version>1.1.1</version>
- <exclusions>
- <exclusion>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>org.onap.cps</groupId>
- <artifactId>cps-ncmp-rest</artifactId>
- </dependency>
- </dependencies>
-</project>
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java
deleted file mode 100644
index 005aa2237..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2023-2024 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.dmi.rest.stub.controller;
-
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.SUCCESS;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import io.cloudevents.CloudEvent;
-import io.cloudevents.core.builder.CloudEventBuilder;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.json.simple.parser.JSONParser;
-import org.json.simple.parser.ParseException;
-import org.onap.cps.ncmp.api.impl.utils.EventDateTimeFormatter;
-import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.DataOperationRequest;
-import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.DmiDataOperationRequest;
-import org.onap.cps.ncmp.dmi.rest.stub.model.data.operational.DmiOperationCmHandle;
-import org.onap.cps.ncmp.dmi.rest.stub.utils.ResourceFileReaderUtil;
-import org.onap.cps.ncmp.events.async1_0_0.Data;
-import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent;
-import org.onap.cps.ncmp.events.async1_0_0.Response;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.ApplicationContext;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.ResourceLoader;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.kafka.core.KafkaTemplate;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
-@RestController
-@RequestMapping("${rest.api.dmi-stub-base-path}")
-@RequiredArgsConstructor
-@Slf4j
-public class DmiRestStubController {
-
- private static final String DEFAULT_TAG = "tagD";
- private static final String dataOperationEventType = "org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent";
- private static final Map<String, String> moduleSetTagPerCmHandleId = new HashMap<>();
- private final KafkaTemplate<String, CloudEvent> cloudEventKafkaTemplate;
- private final ObjectMapper objectMapper;
- private final ApplicationContext applicationContext;
- @Value("${app.ncmp.async-m2m.topic}")
- private String ncmpAsyncM2mTopic;
- @Value("${delay.module-references-delay-ms}")
- private long moduleReferencesDelayMs;
- @Value("${delay.module-resources-delay-ms}")
- private long moduleResourcesDelayMs;
- @Value("${delay.data-for-cm-handle-delay-ms}")
- private long dataForCmHandleDelayMs;
-
- /**
- * This code defines a REST API endpoint for adding new the module set tag mapping. The endpoint receives the
- * cmHandleId and moduleSetTag as request body and add into moduleSetTagPerCmHandleId map with the provided
- * values.
- *
- * @param requestBody map of cmHandleId and moduleSetTag
- * @return a ResponseEntity object containing the updated moduleSetTagPerCmHandleId map as the response body
- */
- @PostMapping("/v1/tagMapping")
- public ResponseEntity<Map<String, String>> addTagForMapping(@RequestBody final Map<String, String> requestBody) {
- moduleSetTagPerCmHandleId.putAll(requestBody);
- return new ResponseEntity<>(requestBody, HttpStatus.CREATED);
- }
-
- /**
- * This code defines a GET endpoint of module set tag mapping.
- *
- * @return The map represents the module set tag mapping.
- */
- @GetMapping("/v1/tagMapping")
- public ResponseEntity<Map<String, String>> getTagMapping() {
- return ResponseEntity.ok(moduleSetTagPerCmHandleId);
- }
-
- /**
- * This code defines a GET endpoint of module set tag by cm handle ID.
- *
- * @return The map represents the module set tag mapping filtered by cm handle ID.
- */
- @GetMapping("/v1/tagMapping/ch/{cmHandleId}")
- public ResponseEntity<String> getTagMappingByCmHandleId(@PathVariable final String cmHandleId) {
- return ResponseEntity.ok(moduleSetTagPerCmHandleId.get(cmHandleId));
- }
-
- /**
- * This code defines a REST API endpoint for updating the module set tag mapping. The endpoint receives the
- * cmHandleId and moduleSetTag as request body and updates the moduleSetTagPerCmHandleId map with the provided
- * values.
- *
- * @param requestBody map of cmHandleId and moduleSetTag
- * @return a ResponseEntity object containing the updated moduleSetTagPerCmHandleId map as the response body
- */
-
- @PutMapping("/v1/tagMapping")
- public ResponseEntity<Map<String, String>> updateTagMapping(@RequestBody final Map<String, String> requestBody) {
- moduleSetTagPerCmHandleId.putAll(requestBody);
- return ResponseEntity.noContent().build();
- }
-
- /**
- * It contains a method to delete an entry from the moduleSetTagPerCmHandleId map.
- * The method takes a cmHandleId as a parameter and removes the corresponding entry from the map.
- *
- * @return a ResponseEntity containing the updated map.
- */
- @DeleteMapping("/v1/tagMapping/ch/{cmHandleId}")
- public ResponseEntity<String> deleteTagMappingByCmHandleId(@PathVariable final String cmHandleId) {
- moduleSetTagPerCmHandleId.remove(cmHandleId);
- return ResponseEntity.ok(String.format("Mapping of %s is deleted successfully", cmHandleId));
- }
-
- /**
- * Get all modules for given cm handle.
- *
- * @param cmHandleId The identifier for a network function, network element, subnetwork,
- * or any other cm object by managed Network CM Proxy
- * @param moduleReferencesRequest module references request body
- * @return ResponseEntity response entity having module response as json string.
- */
- @PostMapping("/v1/ch/{cmHandleId}/modules")
- public ResponseEntity<String> getModuleReferences(@PathVariable("cmHandleId") final String cmHandleId,
- @RequestBody final Object moduleReferencesRequest) {
- delay(moduleReferencesDelayMs);
- try {
- log.info("Incoming DMI request body: {}",
- objectMapper.writeValueAsString(moduleReferencesRequest));
- } catch (final JsonProcessingException jsonProcessingException) {
- log.info("Unable to parse dmi data operation request to json string");
- }
- final String moduleResponseContent = getModuleResourceResponse(cmHandleId,
- "ModuleResponse.json");
- log.info("cm handle: {} requested for modules", cmHandleId);
- return ResponseEntity.ok(moduleResponseContent);
- }
-
- /**
- * Retrieves module resources for a given cmHandleId.
- *
- * @param cmHandleId The identifier for a network function, network element, subnetwork,
- * or any other cm object by managed Network CM Proxy
- * @param moduleResourcesReadRequest module resources read request body
- * @return ResponseEntity response entity having module resources response as json string.
- */
- @PostMapping("/v1/ch/{cmHandleId}/moduleResources")
- public ResponseEntity<String> retrieveModuleResources(
- @PathVariable("cmHandleId") final String cmHandleId,
- @RequestBody final Object moduleResourcesReadRequest) {
- delay(moduleResourcesDelayMs);
- final String moduleResourcesResponseContent = getModuleResourceResponse(cmHandleId,
- "ModuleResourcesResponse.json");
- log.info("cm handle: {} requested for modules resources", cmHandleId);
- return ResponseEntity.ok(moduleResourcesResponseContent);
- }
-
- /**
- * Create resource data from passthrough operational or running for a cm handle.
- *
- * @param cmHandleId The identifier for a network function, network element, subnetwork,
- * or any other cm object by managed Network CM Proxy
- * @param datastoreName datastore name
- * @param resourceIdentifier resource identifier
- * @param options options
- * @param topic client given topic name
- * @return (@ code ResponseEntity) response entity
- */
- @PostMapping("/v1/ch/{cmHandleId}/data/ds/{datastoreName}")
- public ResponseEntity<String> getResourceDataForCmHandle(
- @PathVariable("cmHandleId") final String cmHandleId,
- @PathVariable("datastoreName") final String datastoreName,
- @RequestParam(value = "resourceIdentifier") final String resourceIdentifier,
- @RequestParam(value = "options", required = false) final String options,
- @RequestParam(value = "topic", required = false) final String topic,
- @RequestHeader(value = "Authorization", required = false) final String authorization,
- @RequestBody final String requestBody) {
- log.info("DMI AUTH HEADER: {}", authorization);
- delay(dataForCmHandleDelayMs);
- log.info("Logging request body {}", requestBody);
-
- final String sampleJson = ResourceFileReaderUtil.getResourceFileContent(applicationContext.getResource(
- ResourceLoader.CLASSPATH_URL_PREFIX + "data/operational/ietf-network-topology-sample-rfc8345.json"));
- return ResponseEntity.ok(sampleJson);
- }
-
- /**
- * This method is not implemented for ONAP DMI plugin.
- *
- * @param topic client given topic name
- * @param requestId requestId generated by NCMP as an ack for client
- * @param dmiDataOperationRequest list of operation details
- * @return (@ code ResponseEntity) response entity
- */
- @PostMapping("/v1/data")
- public ResponseEntity<Void> getResourceDataForCmHandleDataOperation(
- @RequestParam(value = "topic") final String topic,
- @RequestParam(value = "requestId") final String requestId,
- @RequestBody final DmiDataOperationRequest dmiDataOperationRequest) {
- delay(dataForCmHandleDelayMs);
- try {
- log.info("Request received from the NCMP to DMI Plugin: {}",
- objectMapper.writeValueAsString(dmiDataOperationRequest));
- } catch (final JsonProcessingException jsonProcessingException) {
- log.info("Unable to process dmi data operation request to json string");
- }
- dmiDataOperationRequest.getOperations().forEach(dmiDataOperation -> {
- final DataOperationEvent dataOperationEvent = getDataOperationEvent(dmiDataOperation);
- dmiDataOperation.getCmHandles().forEach(dmiOperationCmHandle -> {
- log.info("Module Set Tag received: {}", dmiOperationCmHandle.getModuleSetTag());
- dataOperationEvent.getData().getResponses().get(0).setIds(List.of(dmiOperationCmHandle.getId()));
- final CloudEvent cloudEvent = buildAndGetCloudEvent(topic, requestId, dataOperationEvent);
- cloudEventKafkaTemplate.send(ncmpAsyncM2mTopic, UUID.randomUUID().toString(), cloudEvent);
- });
- });
- return new ResponseEntity<>(HttpStatus.ACCEPTED);
- }
-
- private CloudEvent buildAndGetCloudEvent(final String topic, final String requestId,
- final DataOperationEvent dataOperationEvent) {
- CloudEvent cloudEvent = null;
- try {
- cloudEvent = CloudEventBuilder.v1()
- .withId(UUID.randomUUID().toString())
- .withSource(URI.create("DMI"))
- .withType(dataOperationEventType)
- .withDataSchema(URI.create("urn:cps:" + dataOperationEventType + ":1.0.0"))
- .withTime(EventDateTimeFormatter.toIsoOffsetDateTime(
- EventDateTimeFormatter.getCurrentIsoFormattedDateTime()))
- .withData(objectMapper.writeValueAsBytes(dataOperationEvent))
- .withExtension("destination", topic)
- .withExtension("correlationid", requestId)
- .build();
- } catch (final JsonProcessingException jsonProcessingException) {
- log.error("Unable to parse event into bytes. cause : {}", jsonProcessingException.getMessage());
- }
- return cloudEvent;
- }
-
- private DataOperationEvent getDataOperationEvent(final DataOperationRequest dataOperationRequest) {
- final Response response = new Response();
-
- response.setOperationId(dataOperationRequest.getOperationId());
- response.setStatusCode(SUCCESS.getCode());
- response.setStatusMessage(SUCCESS.getMessage());
- response.setIds(dataOperationRequest.getCmHandles().stream().map(DmiOperationCmHandle::getId).toList());
- response.setResourceIdentifier(dataOperationRequest.getResourceIdentifier());
- response.setOptions(dataOperationRequest.getOptions());
- final String ietfNetworkTopologySample = ResourceFileReaderUtil
- .getResourceFileContent(applicationContext.getResource(
- ResourceLoader.CLASSPATH_URL_PREFIX
- + "data/operational/ietf-network-topology-sample-rfc8345.json"));
- final JSONParser jsonParser = new JSONParser();
- try {
- response.setResult(jsonParser.parse(ietfNetworkTopologySample));
- } catch (final ParseException parseException) {
- log.error("Unable to parse event result as json object. cause : {}", parseException.getMessage());
- }
- final List<Response> responseList = new ArrayList<>(1);
- responseList.add(response);
- final Data data = new Data();
- data.setResponses(responseList);
- final DataOperationEvent dataOperationEvent = new DataOperationEvent();
- dataOperationEvent.setData(data);
- return dataOperationEvent;
- }
-
- private String getModuleResourceResponse(final String cmHandleId, final String moduleResponseType) {
- if (moduleSetTagPerCmHandleId.isEmpty()) {
- log.info("Using default module responses of type ietfYang");
- return ResourceFileReaderUtil.getResourceFileContent(applicationContext.getResource(
- ResourceLoader.CLASSPATH_URL_PREFIX
- + String.format("module/ietfYang-%s", moduleResponseType)));
- }
- final String moduleSetTag = moduleSetTagPerCmHandleId.getOrDefault(cmHandleId, DEFAULT_TAG);
- final String moduleResponseFilePath = String.format("module/%s-%s", moduleSetTag, moduleResponseType);
- final Resource moduleResponseResource = applicationContext.getResource(
- ResourceLoader.CLASSPATH_URL_PREFIX + moduleResponseFilePath);
- log.info("Using module responses from : {}", moduleResponseFilePath);
- return ResourceFileReaderUtil.getResourceFileContent(moduleResponseResource);
- }
-
- private void delay(final long milliseconds) {
- try {
- Thread.sleep(milliseconds);
- } catch (final InterruptedException e) {
- log.error("Thread sleep interrupted: {}", e.getMessage());
- Thread.currentThread().interrupt();
- }
- }
-}
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DataOperationRequest.java b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DataOperationRequest.java
deleted file mode 100644
index 410774932..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DataOperationRequest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * ============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.dmi.rest.stub.model.data.operational;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import java.util.ArrayList;
-import java.util.List;
-import lombok.Getter;
-import lombok.Setter;
-
-@JsonInclude(JsonInclude.Include.NON_NULL)
-@Setter
-@Getter
-public class DataOperationRequest {
- private String operation;
- private String operationId;
- private String datastore;
- private String options;
- private String resourceIdentifier;
- private List<DmiOperationCmHandle> cmHandles = new ArrayList<>();
-}
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/utils/ResourceFileReaderUtil.java b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/utils/ResourceFileReaderUtil.java
deleted file mode 100644
index 0d2adee43..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/utils/ResourceFileReaderUtil.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * ============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.dmi.rest.stub.utils;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.core.io.Resource;
-import org.springframework.util.StreamUtils;
-
-/**
- * Common convenience methods for reading resource file content.
- */
-@Slf4j
-public class ResourceFileReaderUtil {
-
- /**
- * Converts a resource file content into string.
- *
- * @param fileClasspath to name of the file in test/resources
- * @return the content of the file as a String
- * @throws IOException when there is an IO issue
- */
- public static String getResourceFileContent(final Resource fileClasspath) {
- String fileContent = null;
- try {
- fileContent = StreamUtils.copyToString(fileClasspath.getInputStream(), StandardCharsets.UTF_8);
- } catch (final IOException ioException) {
- log.debug("unable to read resource file content. cause : {}", ioException.getMessage());
- }
- return fileContent;
- }
-}
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/application.yml b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/application.yml
deleted file mode 100644
index b78a5b2db..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/application.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-# ============LICENSE_START=======================================================
-# Copyright (C) 2023-2024 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=========================================================
-server:
- port: 8092
- jetty:
- threads:
- max: 25
-
-rest:
- api:
- dmi-stub-base-path: /dmi
-
-spring:
- main:
- banner-mode: "off"
- application:
- name: "dmi-plugin-demo-and-csit-stub"
-
- kafka:
- bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVER:localhost:19092}
- security:
- protocol: PLAINTEXT
- producer:
- value-serializer: io.cloudevents.kafka.CloudEventSerializer
- client-id: cps-core
-
-management:
- endpoints:
- web:
- exposure:
- include: health
-
-app:
- ncmp:
- async-m2m:
- topic: ${NCMP_ASYNC_M2M_TOPIC:ncmp-async-m2m}
-
-delay:
- module-references-delay-ms: ${MODULE_REFERENCES_DELAY_MS:100}
- module-resources-delay-ms: ${MODULE_RESOURCES_DELAY_MS:1000}
- data-for-cm-handle-delay-ms: ${DATA_FOR_CM_HANDLE_DELAY_MS:2500}
-
-logging:
- level:
- org:
- springframework:
- web:
- filter:
- CommonsRequestLoggingFilter: DEBUG \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/data/operational/ietf-network-topology-sample-rfc8345.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/data/operational/ietf-network-topology-sample-rfc8345.json
deleted file mode 100644
index 8f9dbc225..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/data/operational/ietf-network-topology-sample-rfc8345.json
+++ /dev/null
@@ -1,76 +0,0 @@
-{
- "ietf-network:networks": {
- "network": [
- {
- "network-types": {
- },
- "network-id": "otn-hc",
- "node": [
- {
- "node-id": "D1",
- "termination-point": [
- {
- "tp-id": "1-0-1"
- },
- {
- "tp-id": "1-2-1"
- },
- {
- "tp-id": "1-3-1"
- }
- ]
- },
- {
- "node-id": "D2",
- "termination-point": [
- {
- "tp-id": "2-0-1"
- },
- {
- "tp-id": "2-1-1"
- },
- {
- "tp-id": "2-3-1"
- }
- ]
- },
- {
- "node-id": "D3",
- "termination-point": [
- {
- "tp-id": "3-1-1"
- },
- {
- "tp-id": "3-2-1"
- }
- ]
- }
- ],
- "ietf-network-topology:link": [
- {
- "link-id": "D1,1-2-1,D2,2-1-1",
- "source": {
- "source-node": "D1",
- "source-tp": "1-2-1"
- },
- "destination": {
- "dest-node": "D2",
- "dest-tp": "2-1-1"
- }
- },
- {
- "link-id": "D2,2-1-1,D1,1-2-1",
- "source": {
- "source-node": "D2",
- "source-tp": "2-1-1"
- },
- "destination": {
- "dest-node": "D1",
- "dest-tp": "1-2-1"
- }
- }
- ]
- }
- ]
- }
- }
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/ietfYang-ModuleResourcesResponse.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/ietfYang-ModuleResourcesResponse.json
deleted file mode 100644
index 4326733f5..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/ietfYang-ModuleResourcesResponse.json
+++ /dev/null
@@ -1,52 +0,0 @@
-[
- {
- "moduleName": "ietf-yang-types-1",
- "revision": "2013-07-15",
- "yangSource": "module ietf-yang-types-1 {\n\n namespace \"urn:ietf:params:xml:ns:yang:ietf-yang-types-1\";\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"
- },
- {
- "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-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-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-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-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-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-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-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-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-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"
- }
-] \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/ietfYang-ModuleResponse.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/ietfYang-ModuleResponse.json
deleted file mode 100644
index 2cbd8d131..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/ietfYang-ModuleResponse.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "schemas": [
- {
- "moduleName": "ietf-yang-types-1",
- "revision": "2013-07-15"
- },
- {
- "moduleName": "ietf-yang-types-2",
- "revision": "2013-07-16"
- },
- {
- "moduleName": "ietf-yang-types-3",
- "revision": "2013-07-17"
- },
- {
- "moduleName": "ietf-yang-types-4",
- "revision": "2013-07-18"
- },
- {
- "moduleName": "ietf-yang-types-5",
- "revision": "2013-07-19"
- },
- {
- "moduleName": "ietf-yang-types-6",
- "revision": "2013-07-20"
- },
- {
- "moduleName": "ietf-yang-types-7",
- "revision": "2013-07-21"
- },
- {
- "moduleName": "ietf-yang-types-8",
- "revision": "2013-07-22"
- },
- {
- "moduleName": "ietf-yang-types-9",
- "revision": "2013-07-23"
- },
- {
- "moduleName": "ietf-yang-types-10",
- "revision": "2013-07-24"
- }
- ]
-} \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagA-ModuleResourcesResponse.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagA-ModuleResourcesResponse.json
deleted file mode 100644
index 5d713914d..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagA-ModuleResourcesResponse.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[
- {
- "moduleName": "M1",
- "revision": "2024-01-01",
- "yangSource": "module M1 {\n\n namespace \"urn:ietf:params:xml:ns:yang:M1\";\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 2024-01-01 {\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": "M2",
- "revision": "2024-01-02",
- "yangSource": "module M2 {\n\n namespace \"urn:ietf:params:xml:ns:yang:M2\";\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 2024-01-02 {\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"
- }
-] \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagA-ModuleResponse.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagA-ModuleResponse.json
deleted file mode 100644
index 9f20564f0..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagA-ModuleResponse.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "schemas": [
- {
- "moduleName": "M1",
- "revision": "2024-01-01"
- },
- {
- "moduleName": "M2",
- "revision": "2024-01-02"
- }
- ]
-} \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagB-ModuleResourcesResponse.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagB-ModuleResourcesResponse.json
deleted file mode 100644
index ef9b85f92..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagB-ModuleResourcesResponse.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[
- {
- "moduleName": "M1",
- "revision": "2024-01-01",
- "yangSource": "module M1 {\n\n namespace \"urn:ietf:params:xml:ns:yang:M1\";\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 2024-01-01 {\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": "M3",
- "revision": "2024-01-03",
- "yangSource": "module M3 {\n\n namespace \"urn:ietf:params:xml:ns:yang:M3\";\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 2024-01-03 {\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"
- }
-] \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagB-ModuleResponse.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagB-ModuleResponse.json
deleted file mode 100644
index 513c749a2..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagB-ModuleResponse.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "schemas": [
- {
- "moduleName": "M1",
- "revision": "2024-01-01"
- },
- {
- "moduleName": "M3",
- "revision": "2024-01-03"
- }
- ]
-} \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagC-ModuleResourcesResponse.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagC-ModuleResourcesResponse.json
deleted file mode 100644
index 8fb696bb7..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagC-ModuleResourcesResponse.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[
- {
- "moduleName": "M4",
- "revision": "2024-01-04",
- "yangSource": "module M4 {\n\n namespace \"urn:ietf:params:xml:ns:yang:M1\";\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 2024-01-04 {\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": "M5",
- "revision": "2024-01-05",
- "yangSource": "module M5 {\n\n namespace \"urn:ietf:params:xml:ns:yang:M2\";\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 2024-01-05 {\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"
- }
-] \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagC-ModuleResponse.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagC-ModuleResponse.json
deleted file mode 100644
index ea22d8b6d..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagC-ModuleResponse.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "schemas": [
- {
- "moduleName": "M4",
- "revision": "2024-01-04"
- },
- {
- "moduleName": "M5",
- "revision": "2024-01-05"
- }
- ]
-} \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagD-ModuleResourcesResponse.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagD-ModuleResourcesResponse.json
deleted file mode 100644
index 5d713914d..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagD-ModuleResourcesResponse.json
+++ /dev/null
@@ -1,12 +0,0 @@
-[
- {
- "moduleName": "M1",
- "revision": "2024-01-01",
- "yangSource": "module M1 {\n\n namespace \"urn:ietf:params:xml:ns:yang:M1\";\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 2024-01-01 {\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": "M2",
- "revision": "2024-01-02",
- "yangSource": "module M2 {\n\n namespace \"urn:ietf:params:xml:ns:yang:M2\";\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 2024-01-02 {\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"
- }
-] \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagD-ModuleResponse.json b/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagD-ModuleResponse.json
deleted file mode 100644
index 9f20564f0..000000000
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/resources/module/tagD-ModuleResponse.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "schemas": [
- {
- "moduleName": "M1",
- "revision": "2024-01-01"
- },
- {
- "moduleName": "M2",
- "revision": "2024-01-02"
- }
- ]
-} \ No newline at end of file
diff --git a/dmi-plugin-demo-and-csit-stub/pom.xml b/dmi-plugin-demo-and-csit-stub/pom.xml
deleted file mode 100644
index a61c98579..000000000
--- a/dmi-plugin-demo-and-csit-stub/pom.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ============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=========================================================
--->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.onap.cps</groupId>
- <artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
- <relativePath>../cps-parent/pom.xml</relativePath>
- </parent>
-
- <artifactId>dmi-plugin-demo-and-csit-stub</artifactId>
- <packaging>pom</packaging>
-
- <properties>
- <parent.directory>${project.parent.basedir}/..</parent.directory>
- <sonar.skip>true</sonar.skip>
- <jacoco.skip>true</jacoco.skip>
- </properties>
-
- <modules>
- <module>dmi-plugin-demo-and-csit-stub-service</module>
- <module>dmi-plugin-demo-and-csit-stub-app</module>
- </modules>
-</project> \ No newline at end of file
diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml
index 5620c4c17..5af325a50 100644
--- a/docker-compose/docker-compose.yml
+++ b/docker-compose/docker-compose.yml
@@ -20,6 +20,7 @@ services:
### docker-compose --profile dmi-service up -d -> run CPS services incl. dmi-plugin ###
### docker-compose --profile dmi-stub --profile monitoring up -d -> run CPS with stubbed dmi-plugin (for registration performance testing)
+ ### docker-compose --profile dmi-stub --profile tracing up -d -> run CPS with stubbed dmi-plugin (for open telemetry tracing testing make ONAP_TRACING_ENABLED "true" later "http://localhost:16686" can be accessed from browser)
### to disable notifications make notification.enabled to false & comment out kafka/zookeeper services ###
dbpostgresql:
@@ -43,11 +44,7 @@ services:
memory: 3G
cps-and-ncmp:
- container_name: cps-and-ncmp
image: ${DOCKER_REPO:-nexus3.onap.org:10003}/onap/cps-and-ncmp:${CPS_VERSION:-latest}
- ports:
- - ${CPS_CORE_PORT:-8883}:8080
- # - ${CPS_CORE_DEBUG_PORT:-5005}:5005
environment:
CPS_USERNAME: ${CPS_CORE_USERNAME:-cpsuser}
CPS_PASSWORD: ${CPS_CORE_PASSWORD:-cpsr0cks!}
@@ -58,11 +55,14 @@ services:
DMI_PASSWORD: ${DMI_PASSWORD:-cpsr0cks!}
KAFKA_BOOTSTRAP_SERVER: kafka:29092
notification.enabled: 'true'
- # JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
+ ONAP_TRACING_ENABLED: 'false'
+ ONAP_OTEL_SAMPLER_JAEGER_REMOTE_ENDPOINT: http://jaeger-service:14250
+ ONAP_OTEL_EXPORTER_ENDPOINT: http://jaeger-service:4317
restart: unless-stopped
depends_on:
- dbpostgresql
deploy:
+ replicas: 2
resources:
reservations:
cpus: '2'
@@ -71,6 +71,17 @@ services:
cpus: '3'
memory: 3G
+ nginx:
+ container_name: nginx-loadbalancer
+ image: nginx:latest
+ ports:
+ - ${CPS_CORE_PORT:-8883}:80
+ depends_on:
+ - cps-and-ncmp
+ volumes:
+ - ./nginx.conf:/etc/nginx/nginx.conf
+ - ./proxy_params:/etc/nginx/proxy_params
+
### if kafka is not required comment out zookeeper and kafka ###
zookeeper:
image: confluentinc/cp-zookeeper:6.2.1
@@ -130,12 +141,22 @@ services:
NCMP_ASYNC_M2M_TOPIC: ncmp-async-m2m
MODULE_REFERENCES_DELAY_MS: 100
MODULE_RESOURCES_DELAY_MS: 1000
- DATA_FOR_CM_HANDLE_DELAY_MS: 2500
+ READ_DATA_FOR_CM_HANDLE_DELAY_MS: 300
+ WRITE_DATA_FOR_CM_HANDLE_DELAY_MS: 670
restart: unless-stopped
profiles:
- dmi-stub
- dmi-service
+ policy-executor-stub:
+ container_name: policy-executor-stub
+ image: ${DOCKER_REPO:-nexus3.onap.org:10003}/onap/policy-executor-stub:latest
+ ports:
+ - 8785:8080
+ restart: unless-stopped
+ profiles:
+ - policy-executor-stub
+
prometheus:
container_name: prometheus-container
image: prom/prometheus:latest
@@ -164,5 +185,26 @@ services:
profiles:
- monitoring
+ kafka-ui:
+ container_name: kafka-ui
+ image: provectuslabs/kafka-ui:latest
+ ports:
+ - 8089:8080
+ environment:
+ DYNAMIC_CONFIG_ENABLED: 'true'
+ KAFKA_CLUSTERS_0_NAME: 'cps-kafka-local'
+ KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:29092
+ profiles:
+ - monitoring
+
+ jaeger-service:
+ container_name: jaeger-service
+ image: jaegertracing/all-in-one:latest
+ ports:
+ - 16686:16686
+ restart: unless-stopped
+ profiles:
+ - tracing
+
volumes:
grafana:
diff --git a/docker-compose/nginx.conf b/docker-compose/nginx.conf
new file mode 100644
index 000000000..17fad1b87
--- /dev/null
+++ b/docker-compose/nginx.conf
@@ -0,0 +1,52 @@
+# ============LICENSE_START===============================================
+# Copyright (C) 2024 Nordix Foundation. All rights reserved.
+# ========================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=================================================
+
+events { }
+
+http {
+
+ # Add more server entries here for scaling or load balancing
+ upstream cps-and-ncmp {
+ server cps-and-ncmp:8080;
+ }
+
+ server {
+ listen 80;
+
+ # Root location proxying
+ location / {
+ proxy_pass http://cps-and-ncmp;
+ include /etc/nginx/proxy_params; # Include common proxy parameters
+ }
+
+ location /swagger-ui/ { # Swagger UI location
+ proxy_pass http://cps-and-ncmp/swagger-ui/;
+ }
+
+ location /v3/api-docs/ { # API docs location
+ proxy_pass http://cps-and-ncmp/v3/api-docs/;
+ }
+
+ location /actuator/health { # Actuator health endpoint
+ proxy_pass http://cps-and-ncmp/actuator/health;
+ }
+
+ location /actuator/health/readiness { # Actuator readiness endpoint
+ proxy_pass http://cps-and-ncmp/actuator/health/readiness;
+ }
+
+ }
+}
diff --git a/docker-compose/proxy_params b/docker-compose/proxy_params
new file mode 100644
index 000000000..ab092a98f
--- /dev/null
+++ b/docker-compose/proxy_params
@@ -0,0 +1,4 @@
+proxy_set_header Host $host;
+proxy_set_header X-Real-IP $remote_addr;
+proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+proxy_set_header X-Forwarded-Proto $scheme; \ No newline at end of file
diff --git a/docs/api/swagger/policy-executor/openapi.yaml b/docs/api/swagger/policy-executor/openapi.yaml
index 868f2da81..f80b99836 100644
--- a/docs/api/swagger/policy-executor/openapi.yaml
+++ b/docs/api/swagger/policy-executor/openapi.yaml
@@ -19,25 +19,26 @@
openapi: 3.0.3
info:
title: Policy Executor
- description: "Allows NCMP to execute a policy defined by a third party implementation before proceeding with an operation"
+ description: "Allows NCMP to execute a policy defined by a third party implementation before proceeding with a CM operation"
version: 1.0.0
servers:
- - url: /policy-executor
+ - url: /policy-executor/api
tags:
- name: policy-executor
description: "Execute all your policies"
paths:
- /policy-executor/api/v1/{action}:
+ /v1/{action}:
post:
description: "Fire a Policy action"
operationId: executePolicyAction
parameters:
+ - $ref: '#/components/parameters/authorizationInHeader'
- $ref: '#/components/parameters/actionInPath'
requestBody:
required: true
description: "The action request body"
content:
- application/3gpp-json-patch+json:
+ application/json:
schema:
$ref: '#/components/schemas/PolicyExecutionRequest'
tags:
@@ -51,6 +52,8 @@ paths:
$ref: '#/components/schemas/PolicyExecutionResponse'
'400':
$ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
@@ -74,48 +77,34 @@ components:
details:
type: string
- Payload:
+ Request:
type: object
properties:
- targetFdn:
+ schema:
type: string
- description: "The complete FDN (Fully Distinguished Name) for the element to be changed"
- example: "/Subnetwork=Ireland/MeContext=Athlone/ManagedElement=Athlone/SomeFunction=1/Cell=12"
- cmHandleId:
- type: string
- description: "The CM handle ID (optional)"
- example: "F811AF64F5146DFC545EC60B73DE948E"
- resourceIdentifier:
- type: string
- description: "The resource identifier (optional)"
- example: "ManagedElement=Athlone/SomeFunction=1/Cell=12"
- cmChangeRequest:
+ description: "The schema for the data in this request. The schema name should include the type of operation"
+ example: "org.onap.cps.ncmp.policy-executor:ncmp-create-schema:1.0.0"
+ data:
type: object
- description: "The content of the change to be made"
- example: '{"Cell":[{"id":"Cell-id","attributes":{"administrativeState":"UNLOCKED"}}]}'
+ description: "The data related to the request. The format of the object is determined by the schema"
required:
- - targetFdn
- - cmChangeRequest
+ - schema
+ - data
PolicyExecutionRequest:
type: object
properties:
- payloadType:
- type: string
- description: "The type of payload. Currently supported options: 'CM_Write'"
- example: "CM_Write"
decisionType:
type: string
- description: "The type of decision. Currently supported options: 'Allow'"
- example: "Allow"
- payload:
+ description: "The type of decision. Currently supported options: 'allow'"
+ example: "allow"
+ requests:
type: array
items:
- $ref: '#/components/schemas/Payload'
+ $ref: '#/components/schemas/Request'
required:
- - payloadType
- decisionType
- - payload
+ - requests
PolicyExecutionResponse:
type: object
@@ -126,8 +115,8 @@ components:
example: "550e8400-e29b-41d4-a716-446655440000"
decision:
type: string
- description: "The decision outcome. Currently supported values: 'Allow','Deny'"
- example: "Deny"
+ description: "The decision outcome. Currently supported values: 'allow','deny'"
+ example: "deny"
message:
type: string
description: "Additional information regarding the decision outcome"
@@ -138,16 +127,16 @@ components:
- message
responses:
- NotFound:
- description: "The specified resource was not found"
+ BadRequest:
+ description: "Bad request"
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
example:
- status: 404
- message: "Resource Not Found"
- details: "The requested resource is not found"
+ status: 400
+ message: "Bad Request"
+ details: "The provided request is not valid"
Unauthorized:
description: "Unauthorized request"
content:
@@ -168,16 +157,6 @@ components:
status: 403
message: "Request Forbidden"
details: "This request is forbidden"
- BadRequest:
- description: "Bad request"
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/ErrorMessage'
- example:
- status: 400
- message: "Bad Request"
- details: "The provided request is not valid"
InternalServerError:
description: "Internal server error"
@@ -205,10 +184,17 @@ components:
actionInPath:
name: action
in: path
- description: "The policy action. Currently supported options: 'Execute'"
+ description: "The policy action. Currently supported options: 'execute'"
required: true
schema:
type: string
- example: "Execute"
+ example: "execute"
+ authorizationInHeader:
+ name: Authorization
+ in: header
+ description: "Bearer token may be used to identify client as part of a policy"
+ schema:
+ type: string
+
security:
- bearerAuth: []
diff --git a/docs/cm-notification-subscriptions.rst b/docs/cm-notification-subscriptions.rst
new file mode 100644
index 000000000..14e871add
--- /dev/null
+++ b/docs/cm-notification-subscriptions.rst
@@ -0,0 +1,48 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. Copyright (C) 2024 Nordix Foundation
+
+.. DO NOT CHANGE THIS LABEL FOR RELEASE NOTES - EVEN THOUGH IT GIVES A WARNING
+.. _cmNotificationSubscriptions:
+
+
+CM Data Subscriptions
+#####################
+
+.. toctree::
+ :maxdepth: 1
+
+Introduction
+============
+CM Subscriptions are created to subscribe to notifications for CM related changes that happened in the network based on predicates.
+Predicates can be used to filter on CM Handle (id), Datastore and Xpath.
+
+The CM Subscription flow is event driven and adheres to the CNCF Cloud Events Specifications.
+
+Event to create and delete a subscription.
+
+:download:`CM Subscription Event Schema <schemas/ncmp-in-event-schema-1.0.0.json>`
+
+Event to receive status of participants in a subscription.
+
+:download:`CM Subscription Response Event Schema <schemas/ncmp-out-event-schema-1.0.0.json>`
+
+CM Subscriptions Creation
+-------------------------
+To create a subscription, a client sends an event to a configured topic to register its interest with NCMP allowing the client to receive notifications based on the subscription.
+
+CM Subscriptions Deletion
+-------------------------
+If a client no longer wishes to receive notifications based on a registered subscription, the client can delete the subscription by providing the subscription id.
+
+CM Subscriptions Response
+-------------------------
+The response for the involved subscription participants for the Create and Delete flow can be as follows based on how the DMI Plugin responds back to NCMP.
+ - **ACCEPTED:** DMI Plugin successfully applied the subscription.
+ - **REJECTED:** DMI Plugin failed to apply the subscription.
+ - **PENDING:** DMI Plugin failed to respond within a configured time.
+
+**Note.** The Cm Subscription feature relies on the DMI Plugin support for applying the subscriptions. This support is currently not implemented in the ONAP DMI Plugin.
+
+
+
diff --git a/docs/cps-events.rst b/docs/cps-events.rst
index 25a253bad..47aa73f12 100644
--- a/docs/cps-events.rst
+++ b/docs/cps-events.rst
@@ -13,6 +13,7 @@ CPS Events
cm-handle-lcm-events.rst
data-operation-events.rst
+ cm-notification-subscriptions.rst
.. note::
Legacy async response on a client supplied topic for single cm handle data request are no longer supported. Click link below for the legacy specification.
diff --git a/docs/ncmp-inventory-querying.rst b/docs/ncmp-inventory-querying.rst
index 349b98496..084eaaf69 100644
--- a/docs/ncmp-inventory-querying.rst
+++ b/docs/ncmp-inventory-querying.rst
@@ -156,3 +156,23 @@ With the *cmHandleWithDmiPlugin* condition, we can provide a dmiPluginName. The
}
]
}
+
+CM Handle search with CPS Path
+------------------------------
+
+The *cmHandleWithCpsPath* condition allows any data of the CM Handle to be queried as long as it is accessible by CPS path. CPS path is described in detail in :doc:`cps-path`. For this endpoint, the ancestor axis for CM Handles is appended automatically so that a CM Handle is always returned. For example ``/dmi-registry/cm-handles[@module-set-tag='']`` will become ``/dmi-registry/cm-handles[@module-set-tag='']/ancestor::cm-handles``.
+
+.. code-block:: json
+
+ {
+ "cmHandleQueryParameters": [
+ {
+ "conditionName": "cmHandleWithCpsPath",
+ "conditionParameters": [
+ {
+ "cpsPath": "/dmi-registry/cm-handles[@module-set-tag='some-value or empty']"
+ }
+ ]
+ }
+ ]
+ } \ No newline at end of file
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
index 01735df61..1652997f6 100644
--- a/docs/release-notes.rst
+++ b/docs/release-notes.rst
@@ -16,6 +16,37 @@ CPS Release Notes
.. * * * OSLO * * *
.. ====================
+Version: 3.5.2
+==============
+
+Release Data
+------------
+
++--------------------------------------+--------------------------------------------------------+
+| **CPS Project** | |
+| | |
++--------------------------------------+--------------------------------------------------------+
+| **Docker images** | onap/cps-and-ncmp:3.5.2 |
+| | |
++--------------------------------------+--------------------------------------------------------+
+| **Release designation** | 3.5.2 Oslo |
+| | |
++--------------------------------------+--------------------------------------------------------+
+| **Release date** | Not yet released |
+| | |
++--------------------------------------+--------------------------------------------------------+
+
+Bug Fixes
+---------
+3.5.2
+ - `CPS-2306 <https://jira.onap.org/browse/CPS-2306>`_ Update response message for data validation failure and make it consistent across APIs
+ - `CPS-2319 <https://jira.onap.org/browse/CPS-2319>`_ Fix "Create a node" and "Add List Elements" APIs response code
+
+Features
+--------
+3.5.2
+ - `CPS-2326 <https://jira.onap.org/browse/CPS-2326>`_ Uplift liquibase-core dependency to 4.28.0
+
Version: 3.5.1
==============
@@ -32,18 +63,20 @@ Release Data
| **Release designation** | 3.5.1 Oslo |
| | |
+--------------------------------------+--------------------------------------------------------+
-| **Release date** | Not yet released |
+| **Release date** | 2024 July 15 |
| | |
+--------------------------------------+--------------------------------------------------------+
Bug Fixes
---------
3.5.1
+ - `CPS-2302 <https://jira.onap.org/browse/CPS-2302>`_ Fix handling of special characters in moduleSetTag.
Features
--------
3.5.1
- `CPS-2121 <https://jira.onap.org/browse/CPS-2121>`_ Enabled http client prometheus metrics and manage high cardinality using URL template.
+ - `CPS-2289 <https://jira.onap.org/browse/CPS-2289>`_ Support for CPS Path Query in NCMP Inventory Cm Handle Search.
Version: 3.5.0
==============
diff --git a/docs/schemas/ncmp-in-event-schema-1.0.0.json b/docs/schemas/ncmp-in-event-schema-1.0.0.json
new file mode 100644
index 000000000..f8b6c2e68
--- /dev/null
+++ b/docs/schemas/ncmp-in-event-schema-1.0.0.json
@@ -0,0 +1,73 @@
+{
+ "$id": "urn:cps:org.onap.cps.ncmp.events:cm-notification-subscription-ncmp-in-event:1.0.0",
+ "$ref": "#/definitions/NcmpInEvent",
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "definitions": {
+ "NcmpInEvent": {
+ "description": "The payload for subscription merge event.",
+ "javaType": "org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.client_to_ncmp.NcmpInEvent",
+ "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"]
+ },
+ "xpathFilter": {
+ "description": "Filter to be applied to the CM Handles through this event",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "xpathFilter"
+ ]
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "targetFilter"
+ ]
+ },
+ "additionalProperties": false
+ }
+ },
+ "required": [
+ "subscriptionId"
+ ],
+ "type": "object",
+ "additionalProperties": false
+ }
+ },
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "data"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/docs/schemas/ncmp-out-event-schema-1.0.0.json b/docs/schemas/ncmp-out-event-schema-1.0.0.json
new file mode 100644
index 000000000..d6ef55d06
--- /dev/null
+++ b/docs/schemas/ncmp-out-event-schema-1.0.0.json
@@ -0,0 +1,63 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "urn:cps:org.onap.cps.ncmp.events:cm-notification-subscription-ncmp-out-event-schema:1.0.0",
+ "$ref": "#/definitions/NcmpOutEvent",
+ "definitions": {
+ "NcmpOutEvent": {
+ "type": "object",
+ "description": "The payload applied cm subscription merge event coming out from NCMP.",
+ "javaType": "org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent",
+ "additionalProperties": false,
+ "properties": {
+ "data": {
+ "$ref": "#/definitions/Data"
+ }
+ },
+ "required": [
+ "data"
+ ],
+ "title": "NcmpOutEvent"
+ },
+ "Data": {
+ "type": "object",
+ "description": "Information about the targets and subscription",
+ "additionalProperties": false,
+ "properties": {
+ "subscriptionId": {
+ "type": "string",
+ "description": "The unique subscription id"
+ },
+ "acceptedTargets": {
+ "type": "array",
+ "description": "List of accepted targets",
+ "items": {
+ "type": "string"
+ }
+ },
+ "rejectedTargets": {
+ "type": "array",
+ "description": "List of rejected targets",
+ "items": {
+ "type": "string"
+ }
+ },
+ "pendingTargets": {
+ "type": "array",
+ "description": "List of pending targets",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": [
+ "subscriptionId",
+ "acceptedTargets",
+ "rejectedTargets",
+ "pendingTargets"
+ ],
+ "title": "Data"
+ }
+ }
+
+
+} \ No newline at end of file
diff --git a/docs/schemas/policy-executor/ncmp-create-schema-1.0.0.json b/docs/schemas/policy-executor/ncmp-create-schema-1.0.0.json
new file mode 100644
index 000000000..2ec9daf94
--- /dev/null
+++ b/docs/schemas/policy-executor/ncmp-create-schema-1.0.0.json
@@ -0,0 +1,29 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "urn:cps:org.onap.cps.ncmp.policy-executor:ncmp-create-schema:1.0.0",
+ "$ref": "#/definitions/NcmpCreate",
+ "definitions": {
+ "NcmpCreate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "cmHandleId": {
+ "type": "string"
+ },
+ "resourceIdentifier": {
+ "type": "string"
+ },
+ "targetIdentifier": {
+ "type": "string"
+ },
+ "cmChangeRequest": {
+ "type": "object"
+ }
+ },
+ "required": [
+ "targetIdentifier",
+ "cmChangeRequest"
+ ]
+ }
+ }
+}
diff --git a/docs/schemas/policy-executor/ncmp-delete-schema-1.0.0.json b/docs/schemas/policy-executor/ncmp-delete-schema-1.0.0.json
new file mode 100644
index 000000000..5df0325e3
--- /dev/null
+++ b/docs/schemas/policy-executor/ncmp-delete-schema-1.0.0.json
@@ -0,0 +1,25 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "urn:cps:org.onap.cps.ncmp.policy-executor:ncmp-delete-schema:1.0.0",
+ "$ref": "#/definitions/NcmpDelete",
+ "definitions": {
+ "NcmpDelete": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "cmHandleId": {
+ "type": "string"
+ },
+ "resourceIdentifier": {
+ "type": "string"
+ },
+ "targetIdentifier": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "targetIdentifier"
+ ]
+ }
+ }
+}
diff --git a/docs/schemas/policy-executor/ncmp-patch-schema-1.0.0.json b/docs/schemas/policy-executor/ncmp-patch-schema-1.0.0.json
new file mode 100644
index 000000000..e26c244c9
--- /dev/null
+++ b/docs/schemas/policy-executor/ncmp-patch-schema-1.0.0.json
@@ -0,0 +1,29 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "urn:cps:org.onap.cps.ncmp.policy-executor:ncmp-patch-schema:1.0.0",
+ "$ref": "#/definitions/NcmpPatch",
+ "definitions": {
+ "NcmpPatch": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "cmHandleId": {
+ "type": "string"
+ },
+ "resourceIdentifier": {
+ "type": "string"
+ },
+ "targetIdentifier": {
+ "type": "string"
+ },
+ "cmChangeRequest": {
+ "type": "object"
+ }
+ },
+ "required": [
+ "targetIdentifier",
+ "cmChangeRequest"
+ ]
+ }
+ }
+}
diff --git a/docs/schemas/policy-executor/ncmp-update-schema-1.0.0.json b/docs/schemas/policy-executor/ncmp-update-schema-1.0.0.json
new file mode 100644
index 000000000..0a497e38c
--- /dev/null
+++ b/docs/schemas/policy-executor/ncmp-update-schema-1.0.0.json
@@ -0,0 +1,29 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "urn:cps:org.onap.cps.ncmp.policy-executor:ncmp-update-schema:1.0.0",
+ "$ref": "#/definitions/NcmpUpdate",
+ "definitions": {
+ "NcmpUpdate": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "cmHandleId": {
+ "type": "string"
+ },
+ "resourceIdentifier": {
+ "type": "string"
+ },
+ "targetIdentifier": {
+ "type": "string"
+ },
+ "cmChangeRequest": {
+ "type": "object"
+ }
+ },
+ "required": [
+ "targetIdentifier",
+ "cmChangeRequest"
+ ]
+ }
+ }
+}
diff --git a/integration-test/pom.xml b/integration-test/pom.xml
index a3112661e..7e73c0fe9 100644
--- a/integration-test/pom.xml
+++ b/integration-test/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -107,6 +107,11 @@
<artifactId>spock</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-json</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<profiles>
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
index 0afdfa106..5e46e95a0 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
@@ -125,16 +125,22 @@ abstract class CpsIntegrationSpecBase extends Specification {
@Autowired
AlternateIdMatcher alternateIdMatcher
- MockWebServer mockDmiServer = null
- DmiDispatcher dmiDispatcher = new DmiDispatcher()
+ MockWebServer mockDmiServer1 = new MockWebServer()
+ MockWebServer mockDmiServer2 = new MockWebServer()
- def DMI_URL = null
+ DmiDispatcher dmiDispatcher1 = new DmiDispatcher()
+ DmiDispatcher dmiDispatcher2 = new DmiDispatcher()
+
+ def DMI1_URL = null
+ def DMI2_URL = null
static NO_MODULE_SET_TAG = ''
+ static NO_ALTERNATE_ID = ''
static GENERAL_TEST_DATASPACE = 'generalTestDataspace'
static BOOKSTORE_SCHEMA_SET = 'bookstoreSchemaSet'
+ static MODULE_SYNC_WAIT_TIME_IN_SECONDS = 10
- def static initialized = false
+ static initialized = false
def now = OffsetDateTime.now()
def setup() {
@@ -143,14 +149,19 @@ abstract class CpsIntegrationSpecBase extends Specification {
createStandardBookStoreSchemaSet(GENERAL_TEST_DATASPACE)
initialized = true
}
- mockDmiServer = new MockWebServer()
- mockDmiServer.setDispatcher(dmiDispatcher)
- mockDmiServer.start()
- DMI_URL = String.format("http://%s:%s", mockDmiServer.getHostName(), mockDmiServer.getPort())
+ mockDmiServer1.setDispatcher(dmiDispatcher1)
+ mockDmiServer1.start()
+
+ mockDmiServer2.setDispatcher(dmiDispatcher2)
+ mockDmiServer2.start()
+
+ DMI1_URL = String.format("http://%s:%s", mockDmiServer1.getHostName(), mockDmiServer1.getPort())
+ DMI2_URL = String.format("http://%s:%s", mockDmiServer2.getHostName(), mockDmiServer2.getPort())
}
def cleanup() {
- mockDmiServer.shutdown()
+ mockDmiServer1.shutdown()
+ mockDmiServer2.shutdown()
}
def static readResourceDataFile(filename) {
@@ -216,10 +227,13 @@ abstract class CpsIntegrationSpecBase extends Specification {
// *** NCMP Integration Test Utilities ***
def registerCmHandle(dmiPlugin, cmHandleId, moduleSetTag) {
- def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: cmHandleId, moduleSetTag: moduleSetTag)
+ registerCmHandle(dmiPlugin, cmHandleId, moduleSetTag, NO_ALTERNATE_ID)
+ }
+
+ def registerCmHandle(dmiPlugin, cmHandleId, moduleSetTag, alternateId) {
+ def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: cmHandleId, moduleSetTag: moduleSetTag, alternateId: alternateId)
networkCmProxyInventoryFacade.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: dmiPlugin, createdCmHandles: [cmHandleToCreate]))
- moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
- new PollingConditions().within(3, () -> {
+ new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
CmHandleState.READY == networkCmProxyInventoryFacade.getCmHandleCompositeState(cmHandleId).cmHandleState
})
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy
index 6676cb74c..5ce2475d7 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy
@@ -22,11 +22,12 @@ package org.onap.cps.integration.base
import static org.onap.cps.integration.base.CpsIntegrationSpecBase.readResourceDataFile
-import org.springframework.http.HttpHeaders
+import groovy.json.JsonSlurper
import java.util.regex.Matcher
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.RecordedRequest
+import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
@@ -54,39 +55,75 @@ class DmiDispatcher extends Dispatcher {
def isAvailable = true
- Map<String, List<String>> moduleNamesPerCmHandleId = [:]
+ def jsonSlurper = new JsonSlurper()
+ def moduleNamesPerCmHandleId = [:]
+ def receivedSubJobs = [:]
+ def lastAuthHeaderReceived
+ def dmiResourceDataUrl
@Override
MockResponse dispatch(RecordedRequest request) {
if (!isAvailable) {
- return new MockResponse().setResponseCode(HttpStatus.SERVICE_UNAVAILABLE.value())
+ return mockResponse(HttpStatus.SERVICE_UNAVAILABLE)
+ }
+ if (request.path == '/actuator/health') {
+ return mockResponseWithBody(HttpStatus.OK, '{"status":"UP"}')
}
+
+ lastAuthHeaderReceived = request.getHeader('Authorization')
switch (request.path) {
- case ~/^\/dmi\/v1\/ch\/(.*)\/modules$/:
+ // get module references for a CM-handle
+ case ~'^/dmi/v1/ch/(.*)/modules$':
def cmHandleId = Matcher.lastMatcher[0][1]
return getModuleReferencesResponse(cmHandleId)
- case ~/^\/dmi\/v1\/ch\/(.*)\/moduleResources$/:
+ // get module resources for a CM-handle
+ case ~'^/dmi/v1/ch/(.*)/moduleResources$':
def cmHandleId = Matcher.lastMatcher[0][1]
return getModuleResourcesResponse(cmHandleId)
+ // pass-through data operation for a CM-handle
+ case ~'^/dmi/v1/ch/(.*)/data/ds/(.*)$':
+ dmiResourceDataUrl = request.path
+ return mockResponseWithBody(HttpStatus.OK, '{}')
+
+ // legacy pass-through batch data operation
+ case ~'^/dmi/v1/data$':
+ return mockResponseWithBody(HttpStatus.ACCEPTED, '{}')
+
+ // get write sub job response
+ case ~'^/dmi/v1/writeJob/(.*)$':
+ return mockWriteJobResponse(request)
+
+ // get data job status
+ case ~'^/dmi/v1/dataJob/(.*)/dataProducerJob/(.*)/status(.*)$':
+ return mockResponseWithBody(HttpStatus.OK, '{"status":"status details from mock service"}')
+
default:
- throw new IllegalArgumentException('Mock DMI does not handle path ' + request.path)
+ throw new IllegalArgumentException('Mock DMI does not implement endpoint ' + request.path)
}
}
+ def mockWriteJobResponse(request) {
+ def requestId = Matcher.lastMatcher[0][1]
+ def subJobWriteRequest = jsonSlurper.parseText(request.getBody().readUtf8())
+ this.receivedSubJobs.put(requestId, subJobWriteRequest)
+ def response = '{"subJobId":"some sub job id", "dmiServiceName":"some dmi service name", "dataProducerId":"some data producer id"}'
+ return mockResponseWithBody(HttpStatus.OK, response)
+ }
+
private getModuleReferencesResponse(cmHandleId) {
def moduleReferences = '{"schemas":[' + getModuleNamesForCmHandle(cmHandleId).collect {
MODULE_REFERENCES_RESPONSE_TEMPLATE.replaceAll("<MODULE_NAME>", it)
}.join(',') + ']}'
- return mockOkResponseWithBody(moduleReferences)
+ return mockResponseWithBody(HttpStatus.OK, moduleReferences)
}
private getModuleResourcesResponse(cmHandleId) {
def moduleResources = '[' + getModuleNamesForCmHandle(cmHandleId).collect {
MODULE_RESOURCES_RESPONSE_TEMPLATE.replaceAll("<MODULE_NAME>", it)
}.join(',') + ']'
- return mockOkResponseWithBody(moduleResources)
+ return mockResponseWithBody(HttpStatus.OK, moduleResources)
}
private getModuleNamesForCmHandle(cmHandleId) {
@@ -96,9 +133,13 @@ class DmiDispatcher extends Dispatcher {
return moduleNamesPerCmHandleId.get(cmHandleId)
}
- private static mockOkResponseWithBody(responseBody) {
+ private static mockResponse(status) {
+ return new MockResponse().setResponseCode(status.value())
+ }
+
+ private static mockResponseWithBody(status, responseBody) {
return new MockResponse()
- .setResponseCode(HttpStatus.OK.value())
+ .setResponseCode(status.value())
.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
.setBody(responseBody)
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsAnchorServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/AnchorServiceIntegrationSpec.groovy
index 26857799a..240ff5114 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsAnchorServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/AnchorServiceIntegrationSpec.groovy
@@ -19,18 +19,18 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.cps
import java.time.OffsetDateTime
import org.onap.cps.api.CpsAnchorService
-import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.onap.cps.integration.base.FunctionalSpecBase
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.exceptions.AlreadyDefinedException
import org.onap.cps.spi.exceptions.AnchorNotFoundException
import org.onap.cps.utils.ContentType
-class CpsAnchorServiceIntegrationSpec extends CpsIntegrationSpecBase {
+class AnchorServiceIntegrationSpec extends FunctionalSpecBase {
CpsAnchorService objectUnderTest
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataServiceIntegrationSpec.groovy
index 779c0b84c..b274324d7 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataServiceIntegrationSpec.groovy
@@ -19,7 +19,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.cps
import org.onap.cps.api.CpsDataService
import org.onap.cps.integration.base.FunctionalSpecBase
@@ -39,7 +39,7 @@ 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
-class CpsDataServiceIntegrationSpec extends FunctionalSpecBase {
+class DataServiceIntegrationSpec extends FunctionalSpecBase {
CpsDataService objectUnderTest
def originalCountBookstoreChildNodes
@@ -224,7 +224,7 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase {
given: 'a new (multiple-data-tree:invoice) datanodes'
def json = '{"bookstore-address":[{"bookstore-name":"Easons","address":"Bangalore,India","postal-code":"560043"}]}'
when: 'the new list elements are saved'
- objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/', json, now)
+ objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/', json, now, ContentType.JSON)
then: 'they can be retrieved by their xpaths'
objectUnderTest.getDataNodes(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore-address[@bookstore-name="Easons"]', INCLUDE_ALL_DESCENDANTS)
and: 'there is one extra datanode'
@@ -239,7 +239,7 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase {
given: 'two new (categories) data nodes'
def json = '{"categories": [ {"code":"new1"}, {"code":"new2" } ] }'
when: 'the new list elements are saved'
- objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now)
+ objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now, ContentType.JSON)
then: 'they can be retrieved by their xpaths'
objectUnderTest.getDataNodes(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore/categories[@code="new1"]', DIRECT_CHILDREN_ONLY).size() == 1
objectUnderTest.getDataNodes(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore/categories[@code="new2"]', DIRECT_CHILDREN_ONLY).size() == 1
@@ -256,7 +256,7 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase {
given: 'two (categories) data nodes, one new and one existing'
def json = '{"categories": [ {"code":"1"}, {"code":"new1"} ] }'
when: 'attempt to save the list element'
- objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now)
+ objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now, ContentType.JSON)
then: 'an exception that (one cps paths is) already defined is thrown '
def exceptionThrown = thrown(AlreadyDefinedException)
exceptionThrown.alreadyDefinedObjectNames == ['/bookstore/categories[@code=\'1\']' ] as Set
@@ -270,7 +270,7 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase {
given: 'a new (categories) data nodes'
def json = '{"categories": [ {"code":"new1"} ] }'
and: 'the new list element is saved'
- objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now)
+ objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now, ContentType.JSON)
when: 'the new element is deleted'
objectUnderTest.deleteListOrListElement(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore/categories[@code="new1"]', now)
then: 'the original number of data nodes is restored'
@@ -281,7 +281,7 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase {
given: 'two new (categories) data nodes in a single batch'
def json = '{"categories": [ {"code":"new1"}, {"code":"new2"} ] }'
when: 'the batches of new list element(s) are saved'
- objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now)
+ objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now, ContentType.JSON)
then: 'they can be retrieved by their xpaths'
assert objectUnderTest.getDataNodes(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore/categories[@code="new1"]', DIRECT_CHILDREN_ONLY).size() == 1
assert objectUnderTest.getDataNodes(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore/categories[@code="new2"]', DIRECT_CHILDREN_ONLY).size() == 1
@@ -298,7 +298,7 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase {
given: 'one existing and one new (categories) data nodes in a single batch'
def json = '{"categories": [ {"code":"new1"}, {"code":"1"} ] }'
when: 'the batches of new list element(s) are saved'
- objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now)
+ objectUnderTest.saveListElements(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now, ContentType.JSON)
then: 'an already defined (batch) exception is thrown for the existing path'
def exceptionThrown = thrown(AlreadyDefinedException)
assert exceptionThrown.alreadyDefinedObjectNames == ['/bookstore/categories[@code=\'1\']' ] as Set
@@ -396,7 +396,7 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase {
objectUnderTest.saveData(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1 , '/bookstore', json, now)
when: 'the webinfo (container) is updated'
json = '{"webinfo": {"domain-name":"newdomain.com" ,"contact-email":"info@newdomain.com" }}'
- objectUnderTest.updateDataNodeAndDescendants(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore', json, now)
+ objectUnderTest.updateDataNodeAndDescendants(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore', json, now, ContentType.JSON)
then: 'webinfo has been updated with teh new details'
def result = objectUnderTest.getDataNodes(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore/webinfo', DIRECT_CHILDREN_ONLY)
result.leaves.'domain-name'[0] == 'newdomain.com'
@@ -408,7 +408,7 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase {
def 'Update bookstore top-level container data node.'() {
when: 'the bookstore top-level container is updated'
def json = '{ "bookstore": { "bookstore-name": "new bookstore" }}'
- objectUnderTest.updateDataNodeAndDescendants(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/', json, now)
+ objectUnderTest.updateDataNodeAndDescendants(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/', json, now, ContentType.JSON)
then: 'bookstore name has been updated'
def result = objectUnderTest.getDataNodes(FUNCTIONAL_TEST_DATASPACE_1, BOOKSTORE_ANCHOR_1, '/bookstore', DIRECT_CHILDREN_ONLY)
result.leaves.'bookstore-name'[0] == 'new bookstore'
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/cps/DataspaceServiceIntegrationSpec.groovy
index 739e80224..d69f6cca0 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataspaceServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/DataspaceServiceIntegrationSpec.groovy
@@ -18,15 +18,15 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.cps
import org.onap.cps.api.CpsDataspaceService
-import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.onap.cps.integration.base.FunctionalSpecBase
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 {
+class DataspaceServiceIntegrationSpec extends FunctionalSpecBase {
CpsDataspaceService objectUnderTest
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy
index b7b6fa11a..0e465d84a 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsModuleServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/ModuleServiceIntegrationSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.cps
import org.onap.cps.api.CpsModuleService
import org.onap.cps.integration.base.FunctionalSpecBase
@@ -31,7 +31,7 @@ import org.onap.cps.spi.exceptions.SchemaSetNotFoundException
import org.onap.cps.spi.model.ModuleDefinition
import org.onap.cps.spi.model.ModuleReference
-class CpsModuleServiceIntegrationSpec extends FunctionalSpecBase {
+class ModuleServiceIntegrationSpec extends FunctionalSpecBase {
CpsModuleService objectUnderTest
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsQueryServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
index 146ea95e8..69598a060 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsQueryServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation
+ * Copyright (C) 2023-2024 Nordix Foundation
* Modifications Copyright (C) 2023 TechMahindra Ltd
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the 'License');
@@ -19,7 +19,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.cps
import java.time.OffsetDateTime
import org.onap.cps.api.CpsQueryService
@@ -33,7 +33,7 @@ import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
import static org.onap.cps.spi.PaginationOption.NO_PAGINATION
-class CpsQueryServiceIntegrationSpec extends FunctionalSpecBase {
+class QueryServiceIntegrationSpec extends FunctionalSpecBase {
CpsQueryService objectUnderTest
@@ -271,6 +271,7 @@ class CpsQueryServiceIntegrationSpec extends FunctionalSpecBase {
'ancestor with parent list' | '//books/ancestor::bookstore/categories' || ["/bookstore/categories[@code='1']", "/bookstore/categories[@code='2']", "/bookstore/categories[@code='3']", "/bookstore/categories[@code='4']", "/bookstore/categories[@code='5']"]
'ancestor with parent list element' | '//books/ancestor::bookstore/categories[@code="2"]' || ["/bookstore/categories[@code='2']"]
'ancestor combined with text condition' | '//books/title[text()="Matilda"]/ancestor::bookstore' || ["/bookstore"]
+ 'ancestor same as target type' | '//books/title[text()="Matilda"]/ancestor::books' || ["/bookstore/categories[@code='1']/books[@title='Matilda']"]
}
def 'Cps Path query across anchors with #scenario descendants.'() {
@@ -382,7 +383,7 @@ class CpsQueryServiceIntegrationSpec extends FunctionalSpecBase {
def result = objectUnderTest.queryDataNodesAcrossAnchors(FUNCTIONAL_TEST_DATASPACE_1, '/bookstore', OMIT_DESCENDANTS, new PaginationOption(pageIndex, pageSize))
then: 'correct bookstore names are queried'
def bookstoreNames = result.collect { it.getLeaves().get('bookstore-name') }
- assert bookstoreNames.toList() == expectedBookstoreNames
+ assert bookstoreNames.toSet() == expectedBookstoreNames.toSet()
and: 'the correct number of page size is returned'
assert result.size() == expectedPageSize
and: 'the queried nodes have expected anchor names'
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/SessionManagerIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/SessionManagerIntegrationSpec.groovy
index e0a2602b2..428d5f901 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/SessionManagerIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/SessionManagerIntegrationSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.cps
import org.onap.cps.integration.base.FunctionalSpecBase
import org.onap.cps.spi.exceptions.SessionManagerException
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpBearerTokenPassthroughSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/BearerTokenPassthroughSpec.groovy
index 2a35313f7..99e80323c 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpBearerTokenPassthroughSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/BearerTokenPassthroughSpec.groovy
@@ -18,15 +18,10 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.ncmp
-import okhttp3.mockwebserver.Dispatcher
-import okhttp3.mockwebserver.MockResponse
-import okhttp3.mockwebserver.RecordedRequest
-import org.jetbrains.annotations.NotNull
import org.onap.cps.integration.base.CpsIntegrationSpecBase
import org.springframework.http.HttpHeaders
-import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import spock.util.concurrent.PollingConditions
@@ -38,31 +33,15 @@ import static org.springframework.http.HttpMethod.PUT
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
-class NcmpBearerTokenPassthroughSpec extends CpsIntegrationSpecBase {
-
- def lastAuthHeaderReceived = null
+class BearerTokenPassthroughSpec extends CpsIntegrationSpecBase {
def setup() {
- dmiDispatcher.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
- registerCmHandle(DMI_URL, 'ch-1', NO_MODULE_SET_TAG)
-
- mockDmiServer.setDispatcher(new Dispatcher() {
- @Override
- MockResponse dispatch(@NotNull RecordedRequest request) throws InterruptedException {
- if (request.path == '/actuator/health') {
- return new MockResponse()
- .addHeader("Content-Type", MediaType.APPLICATION_JSON).setBody('{"status":"UP"}')
- .setResponseCode(HttpStatus.OK.value())
- } else {
- lastAuthHeaderReceived = request.getHeader('Authorization')
- return new MockResponse().setResponseCode(HttpStatus.OK.value())
- }
- }
- })
+ dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG)
}
def cleanup() {
- deregisterCmHandle(DMI_URL, 'ch-1')
+ deregisterCmHandle(DMI1_URL, 'ch-1')
}
def 'Bearer token is passed from NCMP to DMI in pass-through data operations.'() {
@@ -75,7 +54,7 @@ class NcmpBearerTokenPassthroughSpec extends CpsIntegrationSpecBase {
.andExpect(status().is2xxSuccessful())
then: 'DMI has received request with bearer token'
- lastAuthHeaderReceived == 'Bearer some-bearer-token'
+ assert dmiDispatcher1.lastAuthHeaderReceived == 'Bearer some-bearer-token'
where: 'all HTTP operations are applied'
httpMethod << [GET, POST, PUT, PATCH, DELETE]
@@ -91,7 +70,7 @@ class NcmpBearerTokenPassthroughSpec extends CpsIntegrationSpecBase {
.andExpect(status().is2xxSuccessful())
then: 'DMI has received request with no authorization header'
- lastAuthHeaderReceived == null
+ assert dmiDispatcher1.lastAuthHeaderReceived == null
where: 'all HTTP operations are applied'
httpMethod << [GET, POST, PUT, PATCH, DELETE]
@@ -115,7 +94,7 @@ class NcmpBearerTokenPassthroughSpec extends CpsIntegrationSpecBase {
then: 'DMI will receive the async request with bearer token'
new PollingConditions().within(3, () -> {
- assert lastAuthHeaderReceived == 'Bearer some-bearer-token'
+ assert dmiDispatcher1.lastAuthHeaderReceived == 'Bearer some-bearer-token'
})
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpCmHandleCreateSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy
index 0f442a82f..3d526c6a4 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpCmHandleCreateSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.ncmp
import org.apache.kafka.common.TopicPartition
import org.apache.kafka.common.serialization.StringDeserializer
@@ -36,7 +36,7 @@ import spock.util.concurrent.PollingConditions
import java.time.Duration
import java.time.OffsetDateTime
-class NcmpCmHandleCreateSpec extends CpsIntegrationSpecBase {
+class CmHandleCreateSpec extends CpsIntegrationSpecBase {
NetworkCmProxyInventoryFacade objectUnderTest
@@ -48,14 +48,14 @@ class NcmpCmHandleCreateSpec extends CpsIntegrationSpecBase {
def 'CM Handle registration is successful.'() {
given: 'DMI will return modules when requested'
- dmiDispatcher.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
+ dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
and: 'consumer subscribed to topic'
kafkaConsumer.subscribe(['ncmp-events'])
when: 'a CM-handle is registered for creation'
def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: 'ch-1')
- def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI_URL, createdCmHandles: [cmHandleToCreate])
+ def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: [cmHandleToCreate])
def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
then: 'registration gives successful response'
@@ -64,11 +64,8 @@ class NcmpCmHandleCreateSpec extends CpsIntegrationSpecBase {
and: 'CM-handle is initially in ADVISED state'
assert CmHandleState.ADVISED == objectUnderTest.getCmHandleCompositeState('ch-1').cmHandleState
- when: 'module sync runs'
- moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
-
- then: 'CM-handle goes to READY state'
- new PollingConditions().within(3, () -> {
+ and: 'CM-handle goes to READY state after module sync'
+ new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState('ch-1').cmHandleState
})
@@ -84,23 +81,20 @@ class NcmpCmHandleCreateSpec extends CpsIntegrationSpecBase {
assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences('ch-1').moduleName.sort()
cleanup: 'deregister CM handle'
- deregisterCmHandle(DMI_URL, 'ch-1')
+ deregisterCmHandle(DMI1_URL, 'ch-1')
}
def 'CM Handle goes to LOCKED state when DMI gives error during module sync.'() {
given: 'DMI is not available to handle requests'
- dmiDispatcher.isAvailable = false
+ dmiDispatcher1.isAvailable = false
when: 'a CM-handle is registered for creation'
def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: 'ch-1')
- def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI_URL, createdCmHandles: [cmHandleToCreate])
+ def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: [cmHandleToCreate])
objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
- and: 'module sync runs'
- moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
-
then: 'CM-handle goes to LOCKED state with reason MODULE_SYNC_FAILED'
- new PollingConditions().within(3, () -> {
+ new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
def cmHandleCompositeState = objectUnderTest.getCmHandleCompositeState('ch-1')
assert cmHandleCompositeState.cmHandleState == CmHandleState.LOCKED
assert cmHandleCompositeState.lockReason.lockReasonCategory == LockReasonCategory.MODULE_SYNC_FAILED
@@ -110,23 +104,22 @@ class NcmpCmHandleCreateSpec extends CpsIntegrationSpecBase {
assert objectUnderTest.getYangResourcesModuleReferences('ch-1').empty
cleanup: 'deregister CM handle'
- deregisterCmHandle(DMI_URL, 'ch-1')
+ deregisterCmHandle(DMI1_URL, 'ch-1')
}
def 'Create a CM-handle with existing moduleSetTag.'() {
given: 'DMI will return modules when requested'
- dmiDispatcher.moduleNamesPerCmHandleId = ['ch-1': ['M1', 'M2'], 'ch-2': ['M1', 'M3']]
+ dmiDispatcher1.moduleNamesPerCmHandleId = ['ch-1': ['M1', 'M2'], 'ch-2': ['M1', 'M3']]
and: 'existing CM-handles cm-1 with moduleSetTag "A", and cm-2 with moduleSetTag "B"'
- registerCmHandle(DMI_URL, 'ch-1', 'A')
- registerCmHandle(DMI_URL, 'ch-2', 'B')
+ registerCmHandle(DMI1_URL, 'ch-1', 'A')
+ registerCmHandle(DMI1_URL, 'ch-2', 'B')
when: 'a CM-handle is registered for creation with moduleSetTag "B"'
def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: 'ch-3', moduleSetTag: 'B')
- objectUnderTest.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: DMI_URL, createdCmHandles: [cmHandleToCreate]))
+ objectUnderTest.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: [cmHandleToCreate]))
- then: 'the CM-handle goes to READY state after module sync'
- moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
- new PollingConditions().within(3, () -> {
+ then: 'the CM-handle goes to READY state'
+ new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState('ch-3').cmHandleState
})
@@ -137,53 +130,36 @@ class NcmpCmHandleCreateSpec extends CpsIntegrationSpecBase {
assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences('ch-3').moduleName.sort()
cleanup: 'deregister CM handles'
- deregisterCmHandles(DMI_URL, ['ch-1', 'ch-2', 'ch-3'])
+ deregisterCmHandles(DMI1_URL, ['ch-1', 'ch-2', 'ch-3'])
}
def 'CM Handle retry after failed module sync.'() {
given: 'DMI is not initially available to handle requests'
- dmiDispatcher.isAvailable = false
+ dmiDispatcher1.isAvailable = false
when: 'CM-handles are registered for creation'
def cmHandlesToCreate = [new NcmpServiceCmHandle(cmHandleId: 'ch-1'), new NcmpServiceCmHandle(cmHandleId: 'ch-2')]
- def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI_URL, createdCmHandles: cmHandlesToCreate)
+ def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: cmHandlesToCreate)
objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
- and: 'module sync runs'
- moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
then: 'CM-handles go to LOCKED state'
- new PollingConditions().within(3, () -> {
+ new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
assert objectUnderTest.getCmHandleCompositeState('ch-1').cmHandleState == CmHandleState.LOCKED
- assert objectUnderTest.getCmHandleCompositeState('ch-2').cmHandleState == CmHandleState.LOCKED
})
- when: 'we wait for LOCKED CM handle retry time (actually just subtract 3 minutes from handles lastUpdateTime)'
+ when: 'DMI is available for retry'
+ dmiDispatcher1.moduleNamesPerCmHandleId = ['ch-1': ['M1', 'M2']]
+ dmiDispatcher1.isAvailable = true
+ and: 'the LOCKED CM handle retry time elapses (actually just subtract 3 minutes from handles lastUpdateTime)'
overrideCmHandleLastUpdateTime('ch-1', OffsetDateTime.now().minusMinutes(3))
- overrideCmHandleLastUpdateTime('ch-2', OffsetDateTime.now().minusMinutes(3))
- and: 'failed CM handles are reset'
- moduleSyncWatchdog.resetPreviouslyFailedCmHandles()
- then: 'CM-handles are ADVISED state'
- assert objectUnderTest.getCmHandleCompositeState('ch-1').cmHandleState == CmHandleState.ADVISED
- assert objectUnderTest.getCmHandleCompositeState('ch-2').cmHandleState == CmHandleState.ADVISED
- when: 'DMI is available for retry'
- dmiDispatcher.isAvailable = true
- and: 'DMI will return expected modules'
- dmiDispatcher.moduleNamesPerCmHandleId = ['ch-1': ['M1', 'M2'], 'ch-2': ['M1', 'M3']]
- and: 'module sync runs'
- moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
- then: 'CM-handles go to READY state'
- new PollingConditions().within(3, () -> {
+ then: 'CM-handle goes to READY state'
+ new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
assert objectUnderTest.getCmHandleCompositeState('ch-1').cmHandleState == CmHandleState.READY
- assert objectUnderTest.getCmHandleCompositeState('ch-2').cmHandleState == CmHandleState.READY
})
- and: 'CM-handles have expected modules'
+ and: 'CM-handle has expected modules'
assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences('ch-1').moduleName.sort()
- assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences('ch-2').moduleName.sort()
- and: 'CM-handles have expected module set tags (blank)'
- assert objectUnderTest.getNcmpServiceCmHandle('ch-1').moduleSetTag == ''
- assert objectUnderTest.getNcmpServiceCmHandle('ch-2').moduleSetTag == ''
- cleanup: 'deregister CM handle'
- deregisterCmHandles(DMI_URL, ['ch-1', 'ch-2'])
+ cleanup: 'deregister CM handles'
+ deregisterCmHandles(DMI1_URL, ['ch-1', 'ch-2'])
}
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpCmHandleUpgradeSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy
index 72e798335..f93f58ce2 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpCmHandleUpgradeSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.ncmp
import org.onap.cps.integration.base.CpsIntegrationSpecBase
import org.onap.cps.ncmp.api.inventory.NetworkCmProxyInventoryFacade
@@ -29,7 +29,7 @@ import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory
import spock.util.concurrent.PollingConditions
-class NcmpCmHandleUpgradeSpec extends CpsIntegrationSpecBase {
+class CmHandleUpgradeSpec extends CpsIntegrationSpecBase {
NetworkCmProxyInventoryFacade objectUnderTest
@@ -42,14 +42,14 @@ class NcmpCmHandleUpgradeSpec extends CpsIntegrationSpecBase {
def 'Upgrade CM-handle with new moduleSetTag or no moduleSetTag.'() {
given: 'a CM-handle is created with expected initial modules: M1 and M2'
- dmiDispatcher.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M2']
- registerCmHandle(DMI_URL, CM_HANDLE_ID, initialModuleSetTag)
+ dmiDispatcher1.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M2']
+ registerCmHandle(DMI1_URL, CM_HANDLE_ID, initialModuleSetTag)
assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
when: "the CM-handle is upgraded with given moduleSetTag '${updatedModuleSetTag}'"
def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: updatedModuleSetTag)
def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistrationAndSyncModule(
- new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
+ new DmiPluginRegistration(dmiPlugin: DMI1_URL, upgradedCmHandles: cmHandlesToUpgrade))
then: 'registration gives successful response'
assert dmiPluginRegistrationResponse.upgradedCmHandles == [CmHandleRegistrationResponse.createSuccessResponse(CM_HANDLE_ID)]
@@ -61,15 +61,12 @@ class NcmpCmHandleUpgradeSpec extends CpsIntegrationSpecBase {
assert cmHandleCompositeState.lockReason.details == "Upgrade to ModuleSetTag: ${updatedModuleSetTag}"
when: 'DMI will return different modules for upgrade: M1 and M3'
- dmiDispatcher.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M3']
- and: 'module sync runs'
- moduleSyncWatchdog.resetPreviouslyFailedCmHandles()
- moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
+ dmiDispatcher1.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M3']
then: 'CM-handle goes to READY state'
- new PollingConditions().eventually {
+ new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
- }
+ })
and: 'the CM-handle has expected moduleSetTag'
assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == updatedModuleSetTag
@@ -78,7 +75,7 @@ class NcmpCmHandleUpgradeSpec extends CpsIntegrationSpecBase {
assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
cleanup: 'deregister CM-handle'
- deregisterCmHandle(DMI_URL, CM_HANDLE_ID)
+ deregisterCmHandle(DMI1_URL, CM_HANDLE_ID)
where:
initialModuleSetTag | updatedModuleSetTag
@@ -90,31 +87,27 @@ class NcmpCmHandleUpgradeSpec extends CpsIntegrationSpecBase {
def 'Upgrade CM-handle with existing moduleSetTag.'() {
given: 'DMI will return modules for registration'
- dmiDispatcher.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M2']
- dmiDispatcher.moduleNamesPerCmHandleId[CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG] = ['M1', 'M3']
+ dmiDispatcher1.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M2']
+ dmiDispatcher1.moduleNamesPerCmHandleId[CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG] = ['M1', 'M3']
and: "an existing CM-handle handle with moduleSetTag '${updatedModuleSetTag}'"
- registerCmHandle(DMI_URL, CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG, updatedModuleSetTag)
+ registerCmHandle(DMI1_URL, CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG, updatedModuleSetTag)
assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG).moduleName.sort()
and: "a CM-handle with moduleSetTag '${initialModuleSetTag}' which will be upgraded"
- registerCmHandle(DMI_URL, CM_HANDLE_ID, initialModuleSetTag)
+ registerCmHandle(DMI1_URL, CM_HANDLE_ID, initialModuleSetTag)
assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
when: "CM-handle is upgraded to moduleSetTag '${updatedModuleSetTag}'"
def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: updatedModuleSetTag)
def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistrationAndSyncModule(
- new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
+ new DmiPluginRegistration(dmiPlugin: DMI1_URL, upgradedCmHandles: cmHandlesToUpgrade))
then: 'registration gives successful response'
assert dmiPluginRegistrationResponse.upgradedCmHandles == [CmHandleRegistrationResponse.createSuccessResponse(CM_HANDLE_ID)]
- when: 'module sync runs'
- moduleSyncWatchdog.resetPreviouslyFailedCmHandles()
- moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
-
- then: 'CM-handle goes to READY state'
- new PollingConditions().eventually {
+ and: 'CM-handle goes to READY state'
+ new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
- }
+ })
and: 'the CM-handle has expected moduleSetTag'
assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == updatedModuleSetTag
@@ -123,7 +116,7 @@ class NcmpCmHandleUpgradeSpec extends CpsIntegrationSpecBase {
assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
cleanup: 'deregister CM-handle'
- deregisterCmHandles(DMI_URL, [CM_HANDLE_ID, CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG])
+ deregisterCmHandles(DMI1_URL, [CM_HANDLE_ID, CM_HANDLE_ID_WITH_EXISTING_MODULE_SET_TAG])
where:
initialModuleSetTag | updatedModuleSetTag
@@ -133,14 +126,14 @@ class NcmpCmHandleUpgradeSpec extends CpsIntegrationSpecBase {
def 'Skip upgrade of CM-handle with same moduleSetTag as before.'() {
given: 'an existing CM-handle with expected initial modules: M1 and M2'
- dmiDispatcher.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M2']
- registerCmHandle(DMI_URL, CM_HANDLE_ID, 'same')
+ dmiDispatcher1.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M2']
+ registerCmHandle(DMI1_URL, CM_HANDLE_ID, 'same')
assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
when: 'CM-handle is upgraded with the same moduleSetTag'
def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: 'same')
objectUnderTest.updateDmiRegistrationAndSyncModule(
- new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
+ new DmiPluginRegistration(dmiPlugin: DMI1_URL, upgradedCmHandles: cmHandlesToUpgrade))
then: 'CM-handle remains in READY state'
assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
@@ -152,37 +145,33 @@ class NcmpCmHandleUpgradeSpec extends CpsIntegrationSpecBase {
assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(CM_HANDLE_ID).moduleName.sort()
cleanup: 'deregister CM-handle'
- deregisterCmHandle(DMI_URL, CM_HANDLE_ID)
+ deregisterCmHandle(DMI1_URL, CM_HANDLE_ID)
}
def 'Upgrade of CM-handle fails due to DMI error.'() {
given: 'a CM-handle exists'
- dmiDispatcher.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M2']
- registerCmHandle(DMI_URL, CM_HANDLE_ID, 'oldTag')
+ dmiDispatcher1.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M2']
+ registerCmHandle(DMI1_URL, CM_HANDLE_ID, 'oldTag')
and: 'DMI is not available for upgrade'
- dmiDispatcher.isAvailable = false
+ dmiDispatcher1.isAvailable = false
when: 'the CM-handle is upgraded'
def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: 'newTag')
objectUnderTest.updateDmiRegistrationAndSyncModule(
- new DmiPluginRegistration(dmiPlugin: DMI_URL, upgradedCmHandles: cmHandlesToUpgrade))
-
- and: 'module sync runs'
- moduleSyncWatchdog.resetPreviouslyFailedCmHandles()
- moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
+ new DmiPluginRegistration(dmiPlugin: DMI1_URL, upgradedCmHandles: cmHandlesToUpgrade))
then: 'CM-handle goes to LOCKED state with reason MODULE_UPGRADE_FAILED'
- new PollingConditions(timeout: 3).eventually {
+ new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
def cmHandleCompositeState = objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID)
assert cmHandleCompositeState.cmHandleState == CmHandleState.LOCKED
assert cmHandleCompositeState.lockReason.lockReasonCategory == LockReasonCategory.MODULE_UPGRADE_FAILED
- }
+ })
and: 'the CM-handle has same moduleSetTag as before'
assert objectUnderTest.getNcmpServiceCmHandle(CM_HANDLE_ID).moduleSetTag == 'oldTag'
cleanup: 'deregister CM-handle'
- deregisterCmHandle(DMI_URL, CM_HANDLE_ID)
+ deregisterCmHandle(DMI1_URL, CM_HANDLE_ID)
}
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpCmNotificationSubscriptionSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmNotificationSubscriptionSpec.groovy
index 49a4b4d60..a5f7d08c5 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpCmNotificationSubscriptionSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmNotificationSubscriptionSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.ncmp
import org.onap.cps.integration.base.CpsIntegrationSpecBase
import org.onap.cps.ncmp.impl.cmnotificationsubscription.utils.CmSubscriptionPersistenceService
@@ -26,7 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired
import static org.onap.cps.ncmp.api.data.models.DatastoreType.PASSTHROUGH_RUNNING
-class NcmpCmNotificationSubscriptionSpec extends CpsIntegrationSpecBase {
+class CmNotificationSubscriptionSpec extends CpsIntegrationSpecBase {
@Autowired
CmSubscriptionPersistenceService cmSubscriptionPersistenceService
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobStatusServiceSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobStatusServiceSpec.groovy
new file mode 100644
index 000000000..fdcad2b47
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobStatusServiceSpec.groovy
@@ -0,0 +1,24 @@
+package org.onap.cps.integration.functional.ncmp
+
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.onap.cps.ncmp.api.datajobs.DataJobStatusService
+import org.springframework.beans.factory.annotation.Autowired
+
+class DataJobStatusServiceSpec extends CpsIntegrationSpecBase {
+
+ @Autowired
+ DataJobStatusService dataJobStatusService
+
+ def 'Get the status of a data job from DMI.'() {
+ given: 'the required data about the data job'
+ def dmiServiceName = DMI1_URL
+ def requestId = 'some-request-id'
+ def dataProducerJobId = 'some-data-producer-job-id'
+ def dataProducerId = 'some-data-producer-id'
+ def authorization = 'my authorization header'
+ when: 'the data job status checked'
+ def result = dataJobStatusService.getDataJobStatus(authorization, dmiServiceName, requestId, dataProducerJobId, dataProducerId)
+ then: 'the status is that defined in the mock service.'
+ assert result == 'status details from mock service'
+ }
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DmiUrlEncodingPassthroughSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DmiUrlEncodingPassthroughSpec.groovy
new file mode 100644
index 000000000..4e9b809ef
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DmiUrlEncodingPassthroughSpec.groovy
@@ -0,0 +1,65 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.ncmp
+
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.springframework.http.MediaType
+
+import static org.springframework.http.HttpMethod.DELETE
+import static org.springframework.http.HttpMethod.GET
+import static org.springframework.http.HttpMethod.PATCH
+import static org.springframework.http.HttpMethod.POST
+import static org.springframework.http.HttpMethod.PUT
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
+
+class DmiUrlEncodingPassthroughSpec extends CpsIntegrationSpecBase {
+
+ def setup() {
+ dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG)
+ }
+
+ def cleanup() {
+ deregisterCmHandle(DMI1_URL, 'ch-1')
+ }
+
+ def 'DMI URL encoding for pass-through operational data operations with GET request'() {
+ when: 'sending a GET pass-through data request to NCMP'
+ mvc.perform(request(GET, '/ncmp/v1/ch/ch-1/data/ds/ncmp-datastore:passthrough-operational')
+ .queryParam('resourceIdentifier', 'parent/child')
+ .queryParam('options', '(a=1,b=2)'))
+ .andExpect(status().is2xxSuccessful())
+ then: 'verify that DMI received the request with the correctly encoded URL'
+ assert dmiDispatcher1.dmiResourceDataUrl == '/dmi/v1/ch/ch-1/data/ds/ncmp-datastore%3Apassthrough-operational?resourceIdentifier=parent%2Fchild&options=%28a%3D1%2Cb%3D2%29'
+ }
+
+ def 'DMI URL encoding for pass-through running data operations with POST request'() {
+ when: 'sending a pass-through data request to NCMP with various HTTP methods'
+ mvc.perform(request(POST, '/ncmp/v1/ch/ch-1/data/ds/ncmp-datastore:passthrough-running')
+ .queryParam('resourceIdentifier', 'parent/child')
+ .contentType(MediaType.APPLICATION_JSON)
+ .content('{ "some-json": "data" }'))
+ .andExpect(status().is2xxSuccessful())
+ then: 'verify that DMI received the request with the correctly encoded URL'
+ assert dmiDispatcher1.dmiResourceDataUrl == '/dmi/v1/ch/ch-1/data/ds/ncmp-datastore%3Apassthrough-running?resourceIdentifier=parent%2Fchild'
+ }
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpRestApiSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy
index 5325f1a86..33973e547 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpRestApiSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.integration.functional
+package org.onap.cps.integration.functional.ncmp
import static org.hamcrest.Matchers.containsInAnyOrder
import static org.hamcrest.Matchers.hasSize
@@ -31,29 +31,27 @@ import org.onap.cps.integration.base.CpsIntegrationSpecBase
import org.springframework.http.MediaType
import spock.util.concurrent.PollingConditions
-class NcmpRestApiSpec extends CpsIntegrationSpecBase {
+class RestApiSpec extends CpsIntegrationSpecBase {
def 'Register CM Handles using REST API.'() {
given: 'DMI will return modules'
- dmiDispatcher.moduleNamesPerCmHandleId = [
+ dmiDispatcher1.moduleNamesPerCmHandleId = [
'ch-1': ['M1', 'M2'],
'ch-2': ['M1', 'M2'],
'ch-3': ['M1', 'M3']
]
- and: 'a POST request is made to register the CM Handles'
- def requestBody = '{"dmiPlugin":"'+DMI_URL+'","createdCmHandles":[{"cmHandle":"ch-1"},{"cmHandle":"ch-2"},{"cmHandle":"ch-3"}]}'
+ when: 'a POST request is made to register the CM Handles'
+ def requestBody = '{"dmiPlugin":"'+DMI1_URL+'","createdCmHandles":[{"cmHandle":"ch-1"},{"cmHandle":"ch-2"},{"cmHandle":"ch-3"}]}'
mvc.perform(post('/ncmpInventory/v1/ch').contentType(MediaType.APPLICATION_JSON).content(requestBody))
.andExpect(status().is2xxSuccessful())
- when: 'module sync runs'
- moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
then: 'CM-handles go to READY state'
- new PollingConditions().eventually {
+ new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
(1..3).each {
mvc.perform(get('/ncmp/v1/ch/ch-'+it))
.andExpect(status().isOk())
.andExpect(jsonPath('$.state.cmHandleState').value('READY'))
}
- }
+ })
}
def 'Search for CM Handles by module using REST API.'() {
@@ -80,7 +78,7 @@ class NcmpRestApiSpec extends CpsIntegrationSpecBase {
def 'De-register CM handles using REST API.'() {
when: 'a POST request is made to deregister the CM Handle'
- def requestBody = '{"dmiPlugin":"'+DMI_URL+'", "removedCmHandles": ["ch-1", "ch-2", "ch-3"]}'
+ def requestBody = '{"dmiPlugin":"'+DMI1_URL+'", "removedCmHandles": ["ch-1", "ch-2", "ch-3"]}'
mvc.perform(post('/ncmpInventory/v1/ch').contentType(MediaType.APPLICATION_JSON).content(requestBody))
.andExpect(status().is2xxSuccessful())
then: 'the CM handles are not found using GET'
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/WriteSubJobSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/WriteSubJobSpec.groovy
new file mode 100644
index 000000000..b73634f40
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/WriteSubJobSpec.groovy
@@ -0,0 +1,75 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.ncmp
+
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.onap.cps.ncmp.api.datajobs.DataJobService
+import org.onap.cps.ncmp.api.datajobs.models.DataJobMetadata
+import org.onap.cps.ncmp.api.datajobs.models.DataJobWriteRequest
+import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteResponse
+import org.onap.cps.ncmp.api.datajobs.models.WriteOperation
+import org.springframework.beans.factory.annotation.Autowired
+
+class WriteSubJobSpec extends CpsIntegrationSpecBase {
+
+ @Autowired
+ DataJobService dataJobService
+
+ def setup() {
+ dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1']
+ dmiDispatcher1.moduleNamesPerCmHandleId['ch-2'] = ['M2']
+ dmiDispatcher2.moduleNamesPerCmHandleId['ch-3'] = ['M3']
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, 'p1')
+ registerCmHandle(DMI1_URL, 'ch-2', NO_MODULE_SET_TAG, 'p2')
+ registerCmHandle(DMI2_URL, 'ch-3', NO_MODULE_SET_TAG, 'p3')
+ }
+
+ def cleanup() {
+ deregisterCmHandle(DMI1_URL, 'ch-1')
+ deregisterCmHandle(DMI1_URL, 'ch-2')
+ deregisterCmHandle(DMI2_URL, 'ch-3')
+ }
+
+ def 'Create a sub-job write request.'() {
+ given: 'the required input data for the write job'
+ def authorization = 'my authorization header'
+ def dataJobWriteRequest = new DataJobWriteRequest([new WriteOperation('p1', '', '', null), new WriteOperation('p2', '', '', null), new WriteOperation('p3', '', '', null)])
+ def myDataJobMetadata = new DataJobMetadata('', '', '')
+ def dataJobId = 'my-data-job-id'
+ when: 'sending a write job to NCMP with 2 sub-jobs for DMI 1 and 1 sub-job for DMI 2'
+ def response = dataJobService.writeDataJob(authorization, dataJobId, myDataJobMetadata, dataJobWriteRequest)
+ then: 'each DMI received the expected sub-jobs and the response has the expected values'
+ assert response.size() == 2
+ assert response[0].class == SubJobWriteResponse.class
+ assert response[0].subJobId == "some sub job id"
+ assert response[0].dmiServiceName == "some dmi service name"
+ assert response[0].dataProducerId == "some data producer id"
+ and: 'dmi 1 received the correct job details'
+ def receivedSubJobsForDispatcher1 = dmiDispatcher1.receivedSubJobs['my-data-job-id']['data'].collect()
+ assert receivedSubJobsForDispatcher1.size() == 2
+ assert receivedSubJobsForDispatcher1[0]['path'] == 'p1'
+ assert receivedSubJobsForDispatcher1[1]['path'] == 'p2'
+ and: 'dmi 2 received the correct job details'
+ def receivedSubJobsForDispatcher2 = dmiDispatcher2.receivedSubJobs['my-data-job-id']['data'].collect()
+ assert receivedSubJobsForDispatcher2.size() == 1
+ assert receivedSubJobsForDispatcher2[0]['path'] == 'p3'
+ }
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy
index 0ca200211..f6ae27d12 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2023-2024 Nordix Foundation
+ * Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
@@ -22,6 +23,7 @@ package org.onap.cps.integration.performance.base
import org.onap.cps.integration.ResourceMeter
import org.onap.cps.spi.FetchDescendantsOption
+import org.onap.cps.utils.ContentType
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
@@ -79,7 +81,7 @@ class NcmpPerfTestBase extends PerfTestBase {
def batchSize = 100
for (def i = 0; i < TOTAL_CM_HANDLES; i += batchSize) {
def data = '{ "cm-handles": [' + (1..batchSize).collect { innerNodeJsonTemplate.replace('CMHANDLE_ID_HERE', (it + i).toString()) }.join(',') + ']}'
- cpsDataService.saveListElements(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR, '/dmi-registry', data, now)
+ cpsDataService.saveListElements(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR, '/dmi-registry', data, now, ContentType.JSON)
}
}
@@ -91,7 +93,7 @@ class NcmpPerfTestBase extends PerfTestBase {
innerNodeJsonTemplate.replace('CM_HANDLE_ID_HERE', (it + i).toString())
.replace('ALTERNATE_ID_AS_PATH', (it + i).toString())
}.join(',') + ']}'
- cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry', data, now)
+ cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry', data, now, ContentType.JSON)
}
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/UpdatePerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/UpdatePerfTest.groovy
index 7bcec968e..03abdb4b3 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/UpdatePerfTest.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/UpdatePerfTest.groovy
@@ -50,7 +50,7 @@ class UpdatePerfTest extends CpsPerfTestBase {
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)
+ objectUnderTest.updateDataNodeAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR, '/', jsonData, now, ContentType.JSON)
then: 'there are the expected number of total nodes'
assert totalNodes == countDataNodes('/openroadm-devices/openroadm-device')
where:
@@ -68,7 +68,7 @@ class UpdatePerfTest extends CpsPerfTestBase {
def jsonData = '{ "openroadm-devices": ' + generateJsonForOpenRoadmDevices(startId, totalNodes, changeLeaves) + '}'
when: 'the container node is updated'
resourceMeter.start()
- objectUnderTest.updateDataNodeAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR, '/', jsonData, now)
+ objectUnderTest.updateDataNodeAndDescendants(CPS_PERFORMANCE_TEST_DATASPACE, UPDATE_TEST_ANCHOR, '/', jsonData, now, ContentType.JSON)
resourceMeter.stop()
then: 'there are the expected number of total nodes'
assert totalNodes == countDataNodes('/openroadm-devices/openroadm-device')
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/WritePerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/WritePerfTest.groovy
index 019561174..9f6c78d5f 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/WritePerfTest.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/cps/WritePerfTest.groovy
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2023-2024 Nordix Foundation
+ * Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
@@ -20,6 +21,8 @@
package org.onap.cps.integration.performance.cps
+import org.onap.cps.utils.ContentType
+
import java.time.OffsetDateTime
import org.onap.cps.integration.performance.base.CpsPerfTestBase
@@ -87,7 +90,7 @@ class WritePerfTest extends CpsPerfTestBase {
']}'
when: 'device nodes are added'
resourceMeter.start()
- cpsDataService.saveListElements(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, '/openroadm-devices', jsonListData, OffsetDateTime.now())
+ cpsDataService.saveListElements(CPS_PERFORMANCE_TEST_DATASPACE, WRITE_TEST_ANCHOR, '/openroadm-devices', jsonListData, OffsetDateTime.now(), ContentType.JSON)
resourceMeter.stop()
then: 'the operation takes less than #expectedDuration and memory used is within limit'
recordAndAssertResourceUsage("Saving list of ${totalNodes} devices",
diff --git a/integration-test/src/test/java/org/onap/cps/integration/DmiStubTestContainer.java b/integration-test/src/test/java/org/onap/cps/integration/DmiStubTestContainer.java
new file mode 100644
index 000000000..1bffb35c1
--- /dev/null
+++ b/integration-test/src/test/java/org/onap/cps/integration/DmiStubTestContainer.java
@@ -0,0 +1,61 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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;
+
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.utility.DockerImageName;
+
+public class DmiStubTestContainer extends GenericContainer<DmiStubTestContainer> {
+
+ public static final String IMAGE_NAME_AND_VERSION =
+ "nexus3.onap.org:10003/onap/dmi-plugin-demo-and-csit-stub:latest";
+ public static final String DMI_STUB_URL = "http://localhost:8784";
+
+ private static DmiStubTestContainer dmiStubTestContainer;
+
+ private DmiStubTestContainer() {
+ super(DockerImageName.parse(IMAGE_NAME_AND_VERSION));
+ }
+
+ /**
+ * Provides an instance of the Dmi Plugin Stub test container wrapper.
+ * This will allow to interact with the DMI Stub in our acceptance tests.
+ *
+ * @return DmiStubTestContainer
+ */
+ public static DmiStubTestContainer getInstance() {
+ if (dmiStubTestContainer == null) {
+ dmiStubTestContainer = new DmiStubTestContainer();
+ dmiStubTestContainer.addFixedExposedPort(8784, 8092);
+ Runtime.getRuntime().addShutdownHook(new Thread(dmiStubTestContainer::close));
+ }
+ return dmiStubTestContainer;
+ }
+
+ @Override
+ public void start() {
+ super.start();
+ }
+
+ @Override
+ public void stop() {
+ // Method intentionally left blank
+ }
+}
diff --git a/integration-test/src/test/resources/application.yml b/integration-test/src/test/resources/application.yml
index 58e628795..fefae345e 100644
--- a/integration-test/src/test/resources/application.yml
+++ b/integration-test/src/test/resources/application.yml
@@ -179,9 +179,9 @@ ncmp:
timers:
advised-modules-sync:
- sleep-time-ms: 100000
+ sleep-time-ms: 1000
locked-modules-sync:
- sleep-time-ms: 300000
+ sleep-time-ms: 1000
cm-handle-data-sync:
sleep-time-ms: 30000
subscription-forwarding:
diff --git a/jacoco-report/pom.xml b/jacoco-report/pom.xml
index 01d47bfb0..2ebf7b7c0 100644
--- a/jacoco-report/pom.xml
+++ b/jacoco-report/pom.xml
@@ -5,7 +5,7 @@
<parent>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -58,6 +58,12 @@
<artifactId>integration-test</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>policy-executor-stub</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
</dependencies>
<build>
diff --git a/k6-tests/README.md b/k6-tests/README.md
index e26b18609..9a385e100 100644
--- a/k6-tests/README.md
+++ b/k6-tests/README.md
@@ -4,8 +4,7 @@
k6 tests are written in JavaScript.
## k6 installation
-Follow the instructions in the [k6 installation guide](https://grafana.com/docs/k6/latest/set-up/install-k6/)
-to get started.
+Follow the instructions in the [build from source guide](https://github.com/mostafa/xk6-kafka) to get started.
## Running the k6 test suites
Simply run the main script. (The script assumes k6 and docker-compose have been installed).
@@ -21,5 +20,5 @@ docker-compose -f docker-compose/docker-compose.yml --profile dmi-stub up
To run an individual test from command line, use
```shell
-k6 run ncmp/1-create-cmhandles.js
+k6 run ncmp/ncmp-kpi.js
```
diff --git a/k6-tests/ncmp/1-create-cmhandles.js b/k6-tests/ncmp/1-create-cmhandles.js
deleted file mode 100644
index 1c64ab011..000000000
--- a/k6-tests/ncmp/1-create-cmhandles.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2024 Nordix Foundation
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-import exec from 'k6/execution';
-import { TOTAL_CM_HANDLES, REGISTRATION_BATCH_SIZE, makeBatchOfCmHandleIds, makeCustomSummaryReport } from './common/utils.js';
-import { createCmHandles } from './common/cmhandle-crud.js';
-
-export const options = {
- vus: 1,
- iterations: Math.ceil(TOTAL_CM_HANDLES / REGISTRATION_BATCH_SIZE),
- thresholds: {
- http_req_failed: ['rate == 0'],
- http_req_duration: ['avg <= 850'],
- },
-};
-
-export default function () {
- const batchNumber = exec.scenario.iterationInTest;
- const nextBatchOfCmHandleIds = makeBatchOfCmHandleIds(REGISTRATION_BATCH_SIZE, batchNumber);
- createCmHandles(nextBatchOfCmHandleIds);
-}
-
-export function handleSummary(data) {
- return {
- stdout: makeCustomSummaryReport(data, options),
- };
-}
diff --git a/k6-tests/ncmp/10-mixed-load-test.js b/k6-tests/ncmp/10-mixed-load-test.js
deleted file mode 100644
index a6b5b01e2..000000000
--- a/k6-tests/ncmp/10-mixed-load-test.js
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2024 Nordix Foundation
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-import { makeCustomSummaryReport } from './common/utils.js'
-import { executeCmHandleSearch, executeCmHandleIdSearch } from './common/search-base.js';
-import { passthroughRead } from './common/passthrough-read.js';
-
-const DURATION = '15m';
-
-export const options = {
- scenarios: {
- passthrough_read: {
- executor: 'constant-vus',
- exec: 'passthrough_read',
- vus: 10,
- duration: DURATION,
- },
- id_search_module: {
- executor: 'constant-vus',
- exec: 'id_search_module',
- vus: 3,
- duration: DURATION,
- },
- cm_search_module: {
- executor: 'constant-vus',
- exec: 'cm_search_module',
- vus: 3,
- duration: DURATION,
- },
- },
-
- thresholds: {
- 'http_req_failed{scenario:passthrough_read}': ['rate == 0'],
- 'http_req_failed{scenario:id_search_module}': ['rate == 0'],
- 'http_req_failed{scenario:cm_search_module}': ['rate == 0'],
- 'http_req_duration{scenario:passthrough_read}': ['avg <= 2600'], // DMI delay + 100 ms
- 'http_req_duration{scenario:id_search_module}': ['avg <= 625'],
- 'http_req_duration{scenario:cm_search_module}': ['avg <= 13000'],
- },
-};
-
-export function passthrough_read() {
- passthroughRead();
-}
-
-export function id_search_module() {
- executeCmHandleIdSearch('module');
-}
-
-export function cm_search_module() {
- executeCmHandleSearch('module');
-}
-
-export function handleSummary(data) {
- return {
- stdout: makeCustomSummaryReport(data, options),
- };
-}
diff --git a/k6-tests/ncmp/11-delete-cmhandles.js b/k6-tests/ncmp/11-delete-cmhandles.js
deleted file mode 100644
index 542754b5f..000000000
--- a/k6-tests/ncmp/11-delete-cmhandles.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2024 Nordix Foundation
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-import exec from 'k6/execution';
-import { TOTAL_CM_HANDLES, REGISTRATION_BATCH_SIZE, makeBatchOfCmHandleIds, makeCustomSummaryReport } from './common/utils.js';
-import { deleteCmHandles } from './common/cmhandle-crud.js';
-
-export const options = {
- vus: 1,
- iterations: Math.ceil(TOTAL_CM_HANDLES / REGISTRATION_BATCH_SIZE),
- thresholds: {
- http_req_failed: ['rate == 0'],
- http_req_duration: ['avg <= 1050'],
- },
-};
-
-export default function () {
- const batchNumber = exec.scenario.iterationInTest;
- const nextBatchOfCmHandleIds = makeBatchOfCmHandleIds(REGISTRATION_BATCH_SIZE, batchNumber);
- deleteCmHandles(nextBatchOfCmHandleIds);
-}
-
-export function handleSummary(data) {
- return {
- stdout: makeCustomSummaryReport(data, options),
- };
-}
diff --git a/k6-tests/ncmp/common/cmhandle-crud.js b/k6-tests/ncmp/common/cmhandle-crud.js
index 0c3e116a1..6d5aff7fc 100644
--- a/k6-tests/ncmp/common/cmhandle-crud.js
+++ b/k6-tests/ncmp/common/cmhandle-crud.js
@@ -19,10 +19,28 @@
*/
import http from 'k6/http';
-import { check, sleep, fail } from 'k6';
-import { NCMP_BASE_URL, DMI_PLUGIN_URL, TOTAL_CM_HANDLES } from './utils.js';
+import { check, sleep } from 'k6';
+import { NCMP_BASE_URL, DMI_PLUGIN_URL, TOTAL_CM_HANDLES, REGISTRATION_BATCH_SIZE, CONTENT_TYPE_JSON_PARAM, makeBatchOfCmHandleIds } from './utils.js';
+import { executeCmHandleIdSearch } from './search-base.js';
-export function createCmHandles(cmHandleIds) {
+export function registerAllCmHandles() {
+ forEachBatchOfCmHandles(createCmHandles);
+ waitForAllCmHandlesToBeReady();
+}
+
+export function deregisterAllCmHandles() {
+ forEachBatchOfCmHandles(deleteCmHandles);
+}
+
+function forEachBatchOfCmHandles(functionToExecute) {
+ const TOTAL_BATCHES = Math.ceil(TOTAL_CM_HANDLES / REGISTRATION_BATCH_SIZE);
+ for (let batchNumber = 0; batchNumber < TOTAL_BATCHES; batchNumber++) {
+ const nextBatchOfCmHandleIds = makeBatchOfCmHandleIds(REGISTRATION_BATCH_SIZE, batchNumber);
+ functionToExecute(nextBatchOfCmHandleIds);
+ }
+}
+
+function createCmHandles(cmHandleIds) {
const url = `${NCMP_BASE_URL}/ncmpInventory/v1/ch`;
const payload = {
"dmiPlugin": DMI_PLUGIN_URL,
@@ -36,55 +54,34 @@ export function createCmHandles(cmHandleIds) {
}
})),
};
- const params = {
- headers: {'Content-Type': 'application/json'}
- };
- const response = http.post(url, JSON.stringify(payload), params);
- check(response, {
- 'status equals 200': (r) => r.status === 200,
- });
+ const response = http.post(url, JSON.stringify(payload), CONTENT_TYPE_JSON_PARAM);
+ check(response, { 'create CM-handles status equals 200': (r) => r.status === 200 });
return response;
}
-export function deleteCmHandles(cmHandleIds) {
+function deleteCmHandles(cmHandleIds) {
const url = `${NCMP_BASE_URL}/ncmpInventory/v1/ch`;
const payload = {
"dmiPlugin": DMI_PLUGIN_URL,
"removedCmHandles": cmHandleIds,
};
- const params = {
- headers: {'Content-Type': 'application/json'}
- };
- const response = http.post(url, JSON.stringify(payload), params);
- check(response, {
- 'status equals 200': (r) => r.status === 200,
- });
+ const response = http.post(url, JSON.stringify(payload), CONTENT_TYPE_JSON_PARAM);
+ check(response, { 'delete CM-handles status equals 200': (r) => r.status === 200 });
return response;
}
-export function waitForCmHandlesToBeReady(timeOutInSeconds) {
- const pollingIntervalInSeconds = 10;
- const maxRetries = Math.ceil(timeOutInSeconds / pollingIntervalInSeconds);
+function waitForAllCmHandlesToBeReady() {
+ const POLLING_INTERVAL_SECONDS = 5;
let cmHandlesReady = 0;
- for (let currentTry = 0; currentTry <= maxRetries; currentTry++) {
- sleep(pollingIntervalInSeconds);
- try {
- cmHandlesReady = getNumberOfReadyCmHandles();
- } catch (error) {
- console.error(`Attempt ${currentTry + 1} - Error fetching CM handles: ${error.message}`);
- }
- console.log(`Attempt ${currentTry + 1} - ${cmHandlesReady}/${TOTAL_CM_HANDLES} CM handles are READY`);
- if (cmHandlesReady === TOTAL_CM_HANDLES) {
- console.log(`All ${TOTAL_CM_HANDLES} CM handles are READY`);
- return;
- }
- }
- fail(`Timed out after ${timeOutInSeconds} seconds waiting for ${TOTAL_CM_HANDLES} CM handles to be READY`);
+ do {
+ sleep(POLLING_INTERVAL_SECONDS);
+ cmHandlesReady = getNumberOfReadyCmHandles();
+ console.log(`${cmHandlesReady}/${TOTAL_CM_HANDLES} CM handles are READY`);
+ } while (cmHandlesReady < TOTAL_CM_HANDLES);
}
function getNumberOfReadyCmHandles() {
- const endpointUrl = `${NCMP_BASE_URL}/cps/api/v2/dataspaces/NCMP-Admin/anchors/ncmp-dmi-registry/node?xpath=/dmi-registry&descendants=all`;
- const jsonData = http.get(endpointUrl).json();
- const cmHandles = jsonData[0]["dmi-reg:dmi-registry"]["cm-handles"];
- return cmHandles.filter(cmhandle => cmhandle['state']['cm-handle-state'] === 'READY').length;
+ const response = executeCmHandleIdSearch('readyCmHandles');
+ const arrayOfCmHandleIds = JSON.parse(response.body);
+ return arrayOfCmHandleIds.length;
}
diff --git a/k6-tests/ncmp/common/passthrough-read.js b/k6-tests/ncmp/common/passthrough-crud.js
index e4e937c9c..76bda4e1b 100644
--- a/k6-tests/ncmp/common/passthrough-read.js
+++ b/k6-tests/ncmp/common/passthrough-crud.js
@@ -19,8 +19,12 @@
*/
import http from 'k6/http';
-import { check } from 'k6';
-import { NCMP_BASE_URL, getRandomCmHandleId } from './utils.js';
+import {
+ CONTENT_TYPE_JSON_PARAM,
+ getRandomCmHandleId,
+ NCMP_BASE_URL,
+ TOPIC_DATA_OPERATIONS_BATCH_READ
+} from './utils.js';
export function passthroughRead() {
const cmHandleId = getRandomCmHandleId();
@@ -29,8 +33,33 @@ export function passthroughRead() {
const datastoreName = 'ncmp-datastore:passthrough-operational';
const url = `${NCMP_BASE_URL}/ncmp/v1/ch/${cmHandleId}/data/ds/${datastoreName}?resourceIdentifier=${resourceIdentifier}&include-descendants=${includeDescendants}`
const response = http.get(url);
- check(response, {
- 'status equals 200': (r) => r.status === 200,
- });
return response;
}
+
+export function passthroughWrite() {
+ const cmHandleId = getRandomCmHandleId();
+ const resourceIdentifier = 'my-resource-identifier';
+ const datastoreName = 'ncmp-datastore:passthrough-running';
+ const url = `${NCMP_BASE_URL}/ncmp/v1/ch/${cmHandleId}/data/ds/${datastoreName}?resourceIdentifier=${resourceIdentifier}`
+ const body = `{"neType": "BaseStation"}`
+ const response = http.post(url, JSON.stringify(body), CONTENT_TYPE_JSON_PARAM);
+ return response;
+}
+
+export function batchRead(cmHandleIds) {
+ const url = `${NCMP_BASE_URL}/ncmp/v1/data?topic=${TOPIC_DATA_OPERATIONS_BATCH_READ}`
+ const payload = {
+ "operations": [
+ {
+ "resourceIdentifier": "parent/child",
+ "targetIds": cmHandleIds,
+ "datastore": "ncmp-datastore:passthrough-operational",
+ "options": "(fields=schemas/schema)",
+ "operationId": "12",
+ "operation": "read"
+ }
+ ]
+ };
+ const response = http.post(url, JSON.stringify(payload), CONTENT_TYPE_JSON_PARAM);
+ return response;
+} \ No newline at end of file
diff --git a/k6-tests/ncmp/common/search-base.js b/k6-tests/ncmp/common/search-base.js
index 816bacac5..bc964856a 100644
--- a/k6-tests/ncmp/common/search-base.js
+++ b/k6-tests/ncmp/common/search-base.js
@@ -19,8 +19,7 @@
*/
import http from 'k6/http';
-import { check } from 'k6';
-import { NCMP_BASE_URL, TOTAL_CM_HANDLES } from './utils.js';
+import { NCMP_BASE_URL, CONTENT_TYPE_JSON_PARAM } from './utils.js';
const SEARCH_PARAMETERS_PER_SCENARIO = {
'module': {
@@ -30,30 +29,29 @@ const SEARCH_PARAMETERS_PER_SCENARIO = {
'conditionParameters': [{'moduleName': 'ietf-yang-types-1'}]
}
]
+ },
+ 'readyCmHandles': {
+ 'cmHandleQueryParameters': [
+ {
+ 'conditionName': 'cmHandleWithCpsPath',
+ 'conditionParameters': [{'cpsPath': '//state[@cm-handle-state="READY"]'}]
+ }
+ ]
}
};
export function executeCmHandleSearch(scenario) {
- executeSearchRequest('searches', scenario);
+ return executeSearchRequest('searches', scenario);
}
export function executeCmHandleIdSearch(scenario) {
- executeSearchRequest('id-searches', scenario);
+ return executeSearchRequest('id-searches', scenario);
}
function executeSearchRequest(searchType, scenario) {
const searchParameters = SEARCH_PARAMETERS_PER_SCENARIO[scenario];
const payload = JSON.stringify(searchParameters);
const url = `${NCMP_BASE_URL}/ncmp/v1/ch/${searchType}`;
- const params = {
- headers: {'Content-Type': 'application/json'}
- };
- const response = http.post(url, payload, params);
- check(response, {
- 'status equals 200': (r) => r.status === 200,
- });
- const responseData = JSON.parse(response.body);
- check(responseData, {
- 'returned list has expected CM-handles': (arr) => arr.length === TOTAL_CM_HANDLES,
- });
+ const response = http.post(url, payload, CONTENT_TYPE_JSON_PARAM);
+ return response;
}
diff --git a/k6-tests/ncmp/common/utils.js b/k6-tests/ncmp/common/utils.js
index 55ef60a2e..f24edc50d 100644
--- a/k6-tests/ncmp/common/utils.js
+++ b/k6-tests/ncmp/common/utils.js
@@ -20,8 +20,22 @@
export const NCMP_BASE_URL = 'http://localhost:8883';
export const DMI_PLUGIN_URL = 'http://ncmp-dmi-plugin-demo-and-csit-stub:8092';
-export const TOTAL_CM_HANDLES = Number(__ENV.TOTAL_CM_HANDLES) || 20000;
-export const REGISTRATION_BATCH_SIZE = Number(__ENV.REGISTRATION_BATCH_SIZE) || 100;
+export const TOTAL_CM_HANDLES = 20000;
+export const REGISTRATION_BATCH_SIZE = 100;
+export const READ_DATA_FOR_CM_HANDLE_DELAY_MS = 300; // must have same value as in docker-compose.yml
+export const WRITE_DATA_FOR_CM_HANDLE_DELAY_MS = 670; // must have same value as in docker-compose.yml
+export const CONTENT_TYPE_JSON_PARAM = { headers: {'Content-Type': 'application/json'} };
+export const DATA_OPERATION_READ_BATCH_SIZE = 200;
+export const TOPIC_DATA_OPERATIONS_BATCH_READ = 'topic-data-operations-batch-read';
+export const KAFKA_BOOTSTRAP_SERVERS = ['localhost:9092'];
+
+export function recordTimeInSeconds(functionToExecute) {
+ const startTimeInMillis = Date.now();
+ functionToExecute();
+ const endTimeInMillis = Date.now();
+ const totalTimeInSeconds = (endTimeInMillis - startTimeInMillis) / 1000.0;
+ return totalTimeInSeconds;
+}
/**
* Generates a batch of CM-handle IDs based on batch size and number.
@@ -33,7 +47,7 @@ export function makeBatchOfCmHandleIds(batchSize, batchNumber) {
const batchOfIds = [];
const startIndex = 1 + batchNumber * batchSize;
for (let i = 0; i < batchSize; i++) {
- let cmHandleId = 'ch-' + (startIndex + i);
+ let cmHandleId = `ch-${startIndex + i}`;
batchOfIds.push(cmHandleId);
}
return batchOfIds;
@@ -43,22 +57,26 @@ export function getRandomCmHandleId() {
return `ch-${Math.floor(Math.random() * TOTAL_CM_HANDLES) + 1}`;
}
-function removeBracketsAndQuotes(str) {
- return str.replace(/\[|\]|"/g, '');
-}
-
export function makeCustomSummaryReport(data, options) {
- const moduleName = `${__ENV.K6_MODULE_NAME}`;
- let body = ``;
- for (const condition in options.thresholds) {
- let limit = JSON.stringify(options.thresholds[condition])
- limit = removeBracketsAndQuotes(limit)
- let limitKey = limit.split(' ')[0]
- const actual = Math.ceil(data.metrics[condition].values[limitKey])
- const result = data.metrics[condition].thresholds[limit].ok ? 'PASS' : 'FAIL'
- const row = `${moduleName}\t${condition}\t${limit}\t${actual}\t${result}\n`;
- body += row;
- }
- return body;
+ const summaryCsvLines = [
+ '#,Test Name,Unit,Limit,Actual',
+ makeSummaryCsvLine('1', 'Registration of CM-handles', 'CM-handles/second', 'cmhandles_created_per_second', data, options),
+ makeSummaryCsvLine('2', 'De-registration of CM-handles', 'CM-handles/second', 'cmhandles_deleted_per_second', data, options),
+ makeSummaryCsvLine('3', 'CM-handle ID search with Module filter', 'milliseconds', 'http_req_duration{scenario:id_search_module}', data, options),
+ makeSummaryCsvLine('4', 'CM-handle search with Module filter', 'milliseconds', 'http_req_duration{scenario:cm_search_module}', data, options),
+ makeSummaryCsvLine('5a', 'Synchronous single CM-handle pass-through read', 'requests/second', 'http_reqs{scenario:passthrough_read}', data, options),
+ makeSummaryCsvLine('5b', 'NCMP overhead for Synchronous single CM-handle pass-through read', 'milliseconds', 'ncmp_overhead_passthrough_read', data, options),
+ makeSummaryCsvLine('6a', 'Synchronous single CM-handle pass-through write', 'requests/second', 'http_reqs{scenario:passthrough_write}', data, options),
+ makeSummaryCsvLine('6b', 'NCMP overhead for Synchronous single CM-handle pass-through write', 'milliseconds', 'ncmp_overhead_passthrough_write', data, options),
+ makeSummaryCsvLine('7', 'Data operations batch read', 'events/second', 'data_operations_batch_read_cmhandles_per_second', data, options),
+ ];
+ return summaryCsvLines.join('\n') + '\n';
}
+function makeSummaryCsvLine(testCase, testName, unit, thresholdInK6, data, options) {
+ const thresholdArray = JSON.parse(JSON.stringify(options.thresholds[thresholdInK6]));
+ const thresholdString = thresholdArray[0];
+ const [thresholdKey, thresholdOperator, thresholdValue] = thresholdString.split(/\s+/);
+ const actualValue = data.metrics[thresholdInK6].values[thresholdKey].toFixed(3);
+ return `${testCase},${testName},${unit},${thresholdValue},${actualValue}`;
+}
diff --git a/k6-tests/ncmp/ncmp-kpi.js b/k6-tests/ncmp/ncmp-kpi.js
new file mode 100644
index 000000000..8ff9ec50b
--- /dev/null
+++ b/k6-tests/ncmp/ncmp-kpi.js
@@ -0,0 +1,168 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+import { check } from 'k6';
+import { Gauge, Trend } from 'k6/metrics';
+import {
+ TOTAL_CM_HANDLES, READ_DATA_FOR_CM_HANDLE_DELAY_MS, WRITE_DATA_FOR_CM_HANDLE_DELAY_MS,
+ makeCustomSummaryReport, recordTimeInSeconds, makeBatchOfCmHandleIds, DATA_OPERATION_READ_BATCH_SIZE,
+ TOPIC_DATA_OPERATIONS_BATCH_READ, KAFKA_BOOTSTRAP_SERVERS
+} from './common/utils.js';
+import { registerAllCmHandles, deregisterAllCmHandles } from './common/cmhandle-crud.js';
+import { executeCmHandleSearch, executeCmHandleIdSearch } from './common/search-base.js';
+import { passthroughRead, passthroughWrite, batchRead } from './common/passthrough-crud.js';
+import {
+ Reader,
+} from 'k6/x/kafka';
+
+let cmHandlesCreatedPerSecondGauge = new Gauge('cmhandles_created_per_second');
+let cmHandlesDeletedPerSecondGauge = new Gauge('cmhandles_deleted_per_second');
+let passthroughReadNcmpOverheadTrend = new Trend('ncmp_overhead_passthrough_read');
+let passthroughWriteNcmpOverheadTrend = new Trend('ncmp_overhead_passthrough_write');
+let dataOperationsBatchReadCmHandlePerSecondTrend = new Trend('data_operations_batch_read_cmhandles_per_second');
+
+const reader = new Reader({
+ brokers: KAFKA_BOOTSTRAP_SERVERS,
+ topic: TOPIC_DATA_OPERATIONS_BATCH_READ,
+});
+
+const DURATION = '15m';
+
+export const options = {
+ setupTimeout: '6m',
+ teardownTimeout: '6m',
+ scenarios: {
+ passthrough_read: {
+ executor: 'constant-vus',
+ exec: 'passthrough_read',
+ vus: 10,
+ duration: DURATION,
+ },
+ passthrough_write: {
+ executor: 'constant-vus',
+ exec: 'passthrough_write',
+ vus: 10,
+ duration: DURATION,
+ },
+ id_search_module: {
+ executor: 'constant-vus',
+ exec: 'id_search_module',
+ vus: 3,
+ duration: DURATION,
+ },
+ cm_search_module: {
+ executor: 'constant-vus',
+ exec: 'cm_search_module',
+ vus: 3,
+ duration: DURATION,
+ },
+ data_operation_send_async_http_request: {
+ executor: 'constant-arrival-rate',
+ exec: 'data_operation_send_async_http_request',
+ duration: DURATION,
+ rate: 1,
+ timeUnit: '1s',
+ preAllocatedVUs: 1,
+ },
+ data_operation_async_batch_read: {
+ executor: 'constant-arrival-rate',
+ exec: 'data_operation_async_batch_read',
+ duration: DURATION,
+ rate: 1,
+ timeUnit: '1s',
+ preAllocatedVUs: 1,
+ }
+ },
+ thresholds: {
+ 'cmhandles_created_per_second': ['value >= 22'],
+ 'cmhandles_deleted_per_second': ['value >= 22'],
+ 'http_reqs{scenario:passthrough_write}': ['rate >= 13'],
+ 'http_reqs{scenario:passthrough_read}': ['rate >= 25'],
+ 'ncmp_overhead_passthrough_read': ['avg <= 100'],
+ 'ncmp_overhead_passthrough_write': ['avg <= 100'],
+ 'http_req_duration{scenario:id_search_module}': ['avg <= 625'],
+ 'http_req_duration{scenario:cm_search_module}': ['avg <= 13000'],
+ 'http_req_failed{scenario:id_search_module}': ['rate == 0'],
+ 'http_req_failed{scenario:cm_search_module}': ['rate == 0'],
+ 'http_req_failed{scenario:passthrough_read}': ['rate == 0'],
+ 'http_req_failed{scenario:passthrough_write}': ['rate == 0'],
+ 'http_req_failed{scenario:data_operation_send_async_http_request}': ['rate == 0'],
+ 'kafka_reader_error_count{scenario:data_operation_consume_kafka_responses}': ['count == 0'],
+ 'data_operations_batch_read_cmhandles_per_second': ['avg >= 150'],
+ },
+};
+
+export function setup() {
+ const totalRegistrationTimeInSeconds = recordTimeInSeconds(registerAllCmHandles);
+ cmHandlesCreatedPerSecondGauge.add(TOTAL_CM_HANDLES / totalRegistrationTimeInSeconds);
+}
+
+export function teardown() {
+ const totalDeregistrationTimeInSeconds = recordTimeInSeconds(deregisterAllCmHandles);
+ cmHandlesDeletedPerSecondGauge.add(TOTAL_CM_HANDLES / totalDeregistrationTimeInSeconds);
+}
+
+export function passthrough_read() {
+ const response = passthroughRead();
+ check(response, { 'passthrough read status equals 200': (r) => r.status === 200 });
+ const overhead = response.timings.duration - READ_DATA_FOR_CM_HANDLE_DELAY_MS;
+ passthroughReadNcmpOverheadTrend.add(overhead);
+}
+
+export function passthrough_write() {
+ const response = passthroughWrite();
+ check(response, { 'passthrough write status equals 201': (r) => r.status === 201 });
+ const overhead = response.timings.duration - WRITE_DATA_FOR_CM_HANDLE_DELAY_MS;
+ passthroughWriteNcmpOverheadTrend.add(overhead);
+}
+
+export function id_search_module() {
+ const response = executeCmHandleIdSearch('module');
+ check(response, { 'module ID search status equals 200': (r) => r.status === 200 });
+ check(JSON.parse(response.body), { 'module ID search returned expected CM-handles': (arr) => arr.length === TOTAL_CM_HANDLES });
+}
+
+export function cm_search_module() {
+ const response = executeCmHandleSearch('module');
+ check(response, { 'module search status equals 200': (r) => r.status === 200 });
+ check(JSON.parse(response.body), { 'module search returned expected CM-handles': (arr) => arr.length === TOTAL_CM_HANDLES });
+}
+
+export function data_operation_send_async_http_request() {
+ const nextBatchOfCmHandleIds = makeBatchOfCmHandleIds(DATA_OPERATION_READ_BATCH_SIZE,1);
+ const response = batchRead(nextBatchOfCmHandleIds)
+ check(response, { 'data operation batch read status equals 200': (r) => r.status === 200 });
+}
+
+export function data_operation_async_batch_read() {
+ try {
+ let messages = reader.consume({ limit: DATA_OPERATION_READ_BATCH_SIZE });
+ dataOperationsBatchReadCmHandlePerSecondTrend.add(messages.length);
+ } catch (error) {
+ dataOperationsBatchReadCmHandlePerSecondTrend.add(0);
+ console.error(error);
+ }
+}
+
+export function handleSummary(data) {
+ return {
+ stdout: makeCustomSummaryReport(data, options),
+ };
+}
diff --git a/k6-tests/ncmp/run-all-tests.sh b/k6-tests/ncmp/run-all-tests.sh
index bf6370901..2db32ecd7 100755
--- a/k6-tests/ncmp/run-all-tests.sh
+++ b/k6-tests/ncmp/run-all-tests.sh
@@ -15,29 +15,36 @@
# limitations under the License.
#
-ALL_TEST_SCRIPTS=( \
-1-create-cmhandles.js \
-2-wait-for-cmhandles-to-be-ready.js \
-10-mixed-load-test.js \
-11-delete-cmhandles.js \
-)
+pushd "$(dirname "$0")" >/dev/null || exit 1
-pushd "$(dirname "$0")" || exit 1
+number_of_failures=0
+echo "Running K6 performance tests..."
+k6 --quiet run ncmp-kpi.js > summary.csv || ((number_of_failures++))
-printf "Test Case\tCondition\tLimit\tActual\tResult\n" > summary.log
+if [ -f summary.csv ]; then
-number_of_failures=0
-for test_script in "${ALL_TEST_SCRIPTS[@]}"; do
- echo "k6 run $test_script"
- k6 --quiet run -e K6_MODULE_NAME="$test_script" "$test_script" >> summary.log || ((number_of_failures++))
-done
+ # Output raw CSV for plotting job
+ echo '-- BEGIN CSV REPORT'
+ cat summary.csv
+ echo '-- END CSV REPORT'
+ echo
+
+ # Output human-readable report
+ echo '####################################################################################################'
+ echo '## K 6 P E R F O R M A N C E T E S T R E S U L T S ##'
+ echo '####################################################################################################'
+ column -t -s, summary.csv
+ echo
+
+ # Clean up
+ rm -f summary.csv
-echo '##############################################################################################################################'
-echo '## K 6 P E R F O R M A N C E T E S T R E S U L T S ##'
-echo '##############################################################################################################################'
-awk -F$'\t' '{printf "%-40s%-50s%-20s%-10s%-6s\n", $1, $2, $3, $4, $5}' summary.log
+else
+ echo "Error: Failed to generate summary.csv" >&2
+ ((number_of_failures++))
+fi
-popd || exit 1
+popd >/dev/null || exit 1
echo "NCMP TEST FAILURES: $number_of_failures"
exit $number_of_failures
diff --git a/k6-tests/setup.sh b/k6-tests/setup.sh
index 4805e2ea4..346b9c069 100755
--- a/k6-tests/setup.sh
+++ b/k6-tests/setup.sh
@@ -18,5 +18,13 @@
docker-compose -f ../docker-compose/docker-compose.yml --profile dmi-stub up -d
echo "Waiting for CPS to start..."
-READY_MESSAGE='Processing module sync fetched 0 advised cm handles from DB'
-docker logs cps-and-ncmp -f | grep -m 1 "$READY_MESSAGE" >/dev/null || true
+READY_MESSAGE="Processing module sync fetched 0 advised cm handles from DB"
+
+# Get the container IDs of the cps-and-ncmp replicas
+CONTAINER_IDS=$(docker ps --filter "name=cps-and-ncmp" --format "{{.ID}}")
+
+# Check the logs for each container
+for CONTAINER_ID in $CONTAINER_IDS; do
+ echo "Checking logs for container: $CONTAINER_ID"
+ docker logs "$CONTAINER_ID" -f | grep -m 1 "$READY_MESSAGE" >/dev/null && echo "CPS is ready in container: $CONTAINER_ID" || true
+done
diff --git a/policy-executor-stub/pom.xml b/policy-executor-stub/pom.xml
new file mode 100644
index 000000000..afdc1c7d3
--- /dev/null
+++ b/policy-executor-stub/pom.xml
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.cps</groupId>
+ <artifactId>cps-parent</artifactId>
+ <version>3.5.2-SNAPSHOT</version>
+ <relativePath>../cps-parent/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>policy-executor-stub</artifactId>
+
+ <properties>
+ <app>org.onap.cps.policyexecutor.stub.PolicyExecutorApplication</app>
+ <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
+ <base.image>${docker.pull.registry}/onap/integration-java17:12.0.0</base.image>
+ <image.name>policy-executor-stub</image.name>
+ <image.tag>${project.version}-${maven.build.timestamp}</image.tag>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <!-- S P R I N G D E P E N D E N C I E S -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-tomcat</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-jetty</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ </dependency>
+ <!-- O P E N A P I D E P E N D E N C I E S -->
+ <dependency>
+ <groupId>io.swagger.core.v3</groupId>
+ <artifactId>swagger-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springdoc</groupId>
+ <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+ </dependency>
+ <!-- T E S T D E P E N D E N C I E S -->
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy-json</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.spockframework</groupId>
+ <artifactId>spock-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.spockframework</groupId>
+ <artifactId>spock-spring</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>com.google.cloud.tools</groupId>
+ <artifactId>jib-maven-plugin</artifactId>
+ <configuration>
+ <container>
+ <mainClass>${app}</mainClass>
+ <creationTime>USE_CURRENT_TIMESTAMP</creationTime>
+ </container>
+ <from>
+ <image>${base.image}</image>
+ </from>
+ <to>
+ <tags>
+ <tag>latest</tag>
+ </tags>
+ <image>${docker.push.registry}/onap/${image.name}:${image.tag}</image>
+ </to>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <id>build</id>
+ <goals>
+ <goal>dockerBuild</goal>
+ </goals>
+ </execution>
+ <execution>
+ <phase>deploy</phase>
+ <id>buildAndPush</id>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <!-- Swagger code generation. -->
+ <plugin>
+ <groupId>org.openapitools</groupId>
+ <artifactId>openapi-generator-maven-plugin</artifactId>
+ <version>6.6.0</version>
+ <executions>
+ <execution>
+ <id>code-gen</id>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <configuration>
+ <inputSpec>${project.parent.basedir}/../docs/api/swagger/policy-executor/openapi.yaml</inputSpec>
+ <modelPackage>org.onap.cps.policyexecutor.stub.model</modelPackage>
+ <apiPackage>org.onap.cps.policyexecutor.stub.api</apiPackage>
+ <generatorName>spring</generatorName>
+ <generateSupportingFiles>false</generateSupportingFiles>
+ <configOptions>
+ <sourceFolder>src/gen/java</sourceFolder>
+ <dateLibrary>java11</dateLibrary>
+ <interfaceOnly>true</interfaceOnly>
+ <useSpringBoot3>true</useSpringBoot3>
+ <useTags>true</useTags>
+ <openApiNullable>false</openApiNullable>
+ <skipDefaultInterface>true</skipDefaultInterface>
+ </configOptions>
+ </configuration>
+ </execution>
+ <execution>
+ <id>openapi-yaml-gen</id>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <phase>compile</phase>
+ <configuration>
+ <inputSpec>${project.parent.basedir}/../docs/api/swagger/policy-executor/openapi.yaml</inputSpec>
+ <generatorName>openapi-yaml</generatorName>
+ <configOptions>
+ <outputFile>openapi.yaml</outputFile>
+ </configOptions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.jsonschema2pojo</groupId>
+ <artifactId>jsonschema2pojo-maven-plugin</artifactId>
+ <configuration>
+ <useJakartaValidation>true</useJakartaValidation>
+ <sourceDirectory>${project.parent.basedir}/../docs/schemas/policy-executor</sourceDirectory>
+ <targetPackage>org.onap.cps.policyexecutor.stub.model</targetPackage>
+ <generateBuilders>true</generateBuilders>
+ <serializable>true</serializable>
+ <includeJsr303Annotations>true</includeJsr303Annotations>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>docker</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.google.cloud.tools</groupId>
+ <artifactId>jib-maven-plugin</artifactId>
+ <version>3.3.2</version>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+
+</project>
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/DmiDemoApplication.java b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/PolicyExecutorApplication.java
index 2d4a2d8e8..367a470e2 100644
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/DmiDemoApplication.java
+++ b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/PolicyExecutorApplication.java
@@ -1,6 +1,6 @@
/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,15 +18,14 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.dmi.rest.stub;
+package org.onap.cps.policyexecutor.stub;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
-public class DmiDemoApplication {
-
+public class PolicyExecutorApplication {
public static void main(final String[] args) {
- SpringApplication.run(DmiDemoApplication.class, args);
+ SpringApplication.run(PolicyExecutorApplication.class, args);
}
}
diff --git a/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java
new file mode 100644
index 000000000..5b3a9931a
--- /dev/null
+++ b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java
@@ -0,0 +1,107 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.policyexecutor.stub.controller;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import lombok.RequiredArgsConstructor;
+import org.onap.cps.policyexecutor.stub.api.PolicyExecutorApi;
+import org.onap.cps.policyexecutor.stub.model.NcmpDelete;
+import org.onap.cps.policyexecutor.stub.model.PolicyExecutionRequest;
+import org.onap.cps.policyexecutor.stub.model.PolicyExecutionResponse;
+import org.onap.cps.policyexecutor.stub.model.Request;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.HttpStatusCode;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("${rest.api.policy-executor-base-path}")
+@RequiredArgsConstructor
+public class PolicyExecutorStubController implements PolicyExecutorApi {
+
+ private final ObjectMapper objectMapper;
+
+ private static final Pattern ERROR_CODE_PATTERN = Pattern.compile("(\\d{3})");
+
+ private int decisionCounter = 0;
+
+ @Override
+ public ResponseEntity<PolicyExecutionResponse> executePolicyAction(
+ final String action,
+ final PolicyExecutionRequest policyExecutionRequest,
+ final String authorization) {
+ if (policyExecutionRequest.getRequests().isEmpty()) {
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+ final Request firstRequest = policyExecutionRequest.getRequests().iterator().next();
+ if ("ncmp-delete-schema:1.0.0".equals(firstRequest.getSchema())) {
+ return handleNcmpDeleteSchema(firstRequest);
+ }
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+
+ private ResponseEntity<PolicyExecutionResponse> handleNcmpDeleteSchema(final Request request) {
+ final NcmpDelete ncmpDelete;
+ try {
+ ncmpDelete = objectMapper.readValue((String) request.getData(), NcmpDelete.class);
+ } catch (final JsonProcessingException e) {
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+
+ final String targetIdentifier = ncmpDelete.getTargetIdentifier();
+ if (targetIdentifier == null) {
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+
+ final Matcher matcher = ERROR_CODE_PATTERN.matcher(targetIdentifier);
+ if (matcher.find()) {
+ final int errorCode = Integer.parseInt(matcher.group(1));
+ return new ResponseEntity<>(HttpStatusCode.valueOf(errorCode));
+ }
+
+ return createPolicyExecutionResponse(targetIdentifier);
+ }
+
+ private ResponseEntity<PolicyExecutionResponse> createPolicyExecutionResponse(final String targetIdentifier) {
+ final String decisionId = String.valueOf(++decisionCounter);
+ final String decision;
+ final String message;
+
+ if (targetIdentifier.toLowerCase(Locale.getDefault()).contains("cps-is-great")) {
+ decision = "allow";
+ message = "All good";
+ } else {
+ decision = "deny";
+ message = "Only FDNs containing 'cps-is-great' are allowed";
+ }
+
+ final PolicyExecutionResponse policyExecutionResponse =
+ new PolicyExecutionResponse(decisionId, decision, message);
+
+ return ResponseEntity.ok(policyExecutionResponse);
+ }
+
+}
diff --git a/policy-executor-stub/src/main/resources/application.yml b/policy-executor-stub/src/main/resources/application.yml
new file mode 100644
index 000000000..f713a157f
--- /dev/null
+++ b/policy-executor-stub/src/main/resources/application.yml
@@ -0,0 +1,20 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2024 Nordix
+# ================================================================================
+# 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=========================================================
+
+rest:
+ api:
+ policy-executor-base-path: /policy-executor/api
diff --git a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DmiDataOperationRequest.java b/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/PolicyExecutorApplicationSpec.groovy
index ae78c0337..565932d9f 100644
--- a/dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/model/data/operational/DmiDataOperationRequest.java
+++ b/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/PolicyExecutorApplicationSpec.groovy
@@ -1,6 +1,6 @@
/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,16 +18,17 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.dmi.rest.stub.model.data.operational;
+package org.onap.cps.policyexecutor.stub
-import java.util.List;
-import lombok.Getter;
-import lombok.Setter;
+import spock.lang.Specification
-@Setter
-@Getter
-public class DmiDataOperationRequest {
+class PolicyExecutorApplicationSpec extends Specification {
- private List<DataOperationRequest> operations;
+ def 'Execute Policy Action.'() {
+ when: 'Starting the application (for coverage)'
+ PolicyExecutorApplication.main()
+ then: 'all goes well'
+ noExceptionThrown()
+ }
}
diff --git a/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy b/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy
new file mode 100644
index 000000000..efb12ac61
--- /dev/null
+++ b/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy
@@ -0,0 +1,155 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 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.policyexecutor.stub.controller
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.policyexecutor.stub.model.NcmpDelete
+import org.onap.cps.policyexecutor.stub.model.PolicyExecutionRequest
+import org.onap.cps.policyexecutor.stub.model.PolicyExecutionResponse
+import org.onap.cps.policyexecutor.stub.model.Request
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.springframework.test.web.servlet.MockMvc
+import spock.lang.Specification
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
+
+@WebMvcTest(PolicyExecutorStubController)
+class PolicyExecutorStubControllerSpec extends Specification {
+
+ @Autowired
+ MockMvc mockMvc
+
+ @Autowired
+ ObjectMapper objectMapper
+
+ def url = '/policy-executor/api/v1/some-action'
+
+ def 'Execute policy action.'() {
+ given: 'a policy execution request with target: #targetIdentifier'
+ def requestBody = createRequestBody(targetIdentifier)
+ when: 'request is posted'
+ def response = mockMvc.perform(post(url)
+ .header('Authorization','some string')
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(requestBody))
+ .andReturn().response
+ then: 'response status is Ok'
+ assert response.status == HttpStatus.OK.value()
+ and: 'the response body has the expected decision details'
+ def responseBody = response.contentAsString
+ def policyExecutionResponse = objectMapper.readValue(responseBody, PolicyExecutionResponse.class)
+ assert policyExecutionResponse.decisionId == expectedDecsisonId
+ assert policyExecutionResponse.decision == expectedDecision
+ assert policyExecutionResponse.message == expectedMessage
+ where: 'the following targets are used'
+ targetIdentifier || expectedDecsisonId | expectedDecision | expectedMessage
+ 'some fdn' || '1' | 'deny' | "Only FDNs containing 'cps-is-great' are allowed"
+ 'fdn with cps-is-great' || '2' | 'allow' | 'All good'
+ }
+
+ def 'Execute policy action with a HTTP error code.'() {
+ given: 'a policy execution request with a target fdn with a 3-digit error code'
+ def requestBody = createRequestBody('target with error code 418')
+ when: 'request is posted'
+ def response = mockMvc.perform(post(url)
+ .header('Authorization','some string')
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(requestBody))
+ .andReturn().response
+ then: 'response status the same error code as in target fdn'
+ assert response.status == 418
+ }
+
+ def 'Execute policy action without authorization header.'() {
+ given: 'a valid policy execution request'
+ def requestBody = createRequestBody('some target')
+ when: 'request is posted without authorization header'
+ def response = mockMvc.perform(post(url)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(requestBody))
+ .andReturn().response
+ then: 'response status is OK'
+ assert response.status == HttpStatus.OK.value()
+ }
+
+ def 'Execute policy action with no requests.'() {
+ given: 'a policy execution request'
+ def policyExecutionRequest = new PolicyExecutionRequest('some decision type', [])
+ def requestBody = objectMapper.writeValueAsString(policyExecutionRequest)
+ when: 'request is posted'
+ def response = mockMvc.perform(post(url)
+ .header('Authorization','some string')
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(requestBody))
+ .andReturn().response
+ then: 'response status is Bad Request'
+ assert response.status == HttpStatus.BAD_REQUEST.value()
+ }
+
+ def 'Execute policy action with invalid json for request data.'() {
+ given: 'a policy execution request'
+ def request = new Request('ncmp-delete-schema:1.0.0', 'invalid json')
+ def policyExecutionRequest = new PolicyExecutionRequest('some decision type', [request])
+ def requestBody = objectMapper.writeValueAsString(policyExecutionRequest)
+ when: 'request is posted'
+ def response = mockMvc.perform(post(url)
+ .header('Authorization','some string')
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(requestBody))
+ .andReturn().response
+ then: 'response status is Bad Request'
+ assert response.status == HttpStatus.BAD_REQUEST.value()
+ }
+
+ def 'Execute policy action with missing or invalid attributes.'() {
+ given: 'a policy execution request with decisionType=#decisionType, schema=#schema, targetIdentifier=#targetIdentifier'
+ def requestBody = createRequestBody(decisionType, schema, targetIdentifier)
+ when: 'request is posted'
+ def response = mockMvc.perform(post(url)
+ .header('Authorization','something')
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(requestBody))
+ .andReturn().response
+ then: 'response status as expected'
+ assert response.status == expectedStatus.value()
+ where: 'following parameters are used'
+ decisionType | schema | targetIdentifier || expectedStatus
+ 'something' | 'ncmp-delete-schema:1.0.0' | 'something' || HttpStatus.OK
+ null | 'ncmp-delete-schema:1.0.0' | 'something' || HttpStatus.BAD_REQUEST
+ 'something' | 'other schema' | 'something' || HttpStatus.BAD_REQUEST
+ 'something' | 'ncmp-delete-schema:1.0.0' | null || HttpStatus.BAD_REQUEST
+ }
+
+ def createRequestBody(decisionType, schema, targetIdentifier) {
+ def ncmpDelete = new NcmpDelete(targetIdentifier: targetIdentifier)
+ def request = new Request(schema, objectMapper.writeValueAsString(ncmpDelete))
+ def policyExecutionRequest = new PolicyExecutionRequest(decisionType, [request])
+ return objectMapper.writeValueAsString(policyExecutionRequest)
+ }
+
+ def createRequestBody(targetIdentifier) {
+ return createRequestBody('some decision type', 'ncmp-delete-schema:1.0.0', targetIdentifier)
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index fcead19e8..adc2bbb04 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,7 +32,7 @@
<groupId>org.onap.cps</groupId>
<artifactId>cps-aggregator</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<packaging>pom</packaging>
<name>cps</name>
@@ -61,12 +61,12 @@
<module>cps-ncmp-rest-stub</module>
<module>cps-path-parser</module>
<module>cps-ri</module>
- <module>dmi-plugin-demo-and-csit-stub</module>
<module>integration-test</module>
<module>checkstyle</module>
<module>spotbugs</module>
<module>cps-application</module>
<module>jacoco-report</module>
+ <module>policy-executor-stub</module>
</modules>
<build>
diff --git a/postman-collections/CPS Environment.postman_environment.json b/postman-collections/CPS Environment.postman_environment.json
index 84dcb642d..7ee9c6779 100644
--- a/postman-collections/CPS Environment.postman_environment.json
+++ b/postman-collections/CPS Environment.postman_environment.json
@@ -1,5 +1,5 @@
{
- "id": "e8e90dd2-20be-49be-813f-07db44c6a4c2",
+ "id": "fd705c16-c17e-434d-ad2e-ba040a7ed062",
"name": "CPS Environment",
"values": [
{
@@ -16,30 +16,18 @@
},
{
"key": "DMI_HOST",
- "value": "localhost",
+ "value": "ncmp-dmi-plugin-demo-and-csit-stub",
"type": "default",
"enabled": true
},
{
"key": "DMI_PORT",
- "value": "8784",
- "type": "default",
- "enabled": true
- },
- {
- "key": "SDNC_HOST",
- "value": "localhost",
- "type": "default",
- "enabled": true
- },
- {
- "key": "SDNC_PORT",
- "value": "8282",
+ "value": "8092",
"type": "default",
"enabled": true
}
],
"_postman_variable_scope": "environment",
- "_postman_exported_at": "2024-02-23T13:00:33.537Z",
- "_postman_exported_using": "Postman/10.23.4"
-} \ No newline at end of file
+ "_postman_exported_at": "2024-07-30T15:54:00.831Z",
+ "_postman_exported_using": "Postman/11.5.1"
+}
diff --git a/postman-collections/DMI Stub.postman_collection.json b/postman-collections/DMI Stub.postman_collection.json
deleted file mode 100644
index fe7250f7d..000000000
--- a/postman-collections/DMI Stub.postman_collection.json
+++ /dev/null
@@ -1,161 +0,0 @@
-{
- "info": {
- "_postman_id": "4baf7902-0f1e-49a9-9c6a-f68f412240af",
- "name": "DMI Stub",
- "description": "A collection of the DMI Stub endpoints.",
- "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
- "_exporter_id": "17907116"
- },
- "item": [
- {
- "name": "Execute a data operation for group of cm handle ids by supplied operation details",
- "request": {
- "method": "POST",
- "header": [],
- "body": {
- "mode": "raw",
- "raw": "{ \"operations\":\n [\n {\n \"resourceIdentifier\": \"some resource identifier\",\n \"datastore\": \"ncmp-datastore:passthrough-operational\",\n \"options\": \"some option\",\n \"operationId\": \"12\",\n \"cmHandles\": [\n {\n \"id\": \"cmHandle123\",\n \"cmHandleProperties\": {\n \"myProp\": \"some value\",\n \"otherProp\": \"other value\"\n }\n },\n {\n \"id\": \"cmHandle123\",\n \"cmHandleProperties\": {\n \"myProp\": \"some value\",\n \"otherProp\": \"other value\"\n }\n }\n ],\n \"operation\": \"read\"\n }\n ]\n}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "http://{{DMI_HOST}}:{{DMI_PORT}}/dmi/v1/data?topic=ncmp-async-m2m&requestId=4753fc1f-7de2-449a-b306-a6204b5370b33",
- "protocol": "http",
- "host": [
- "{{DMI_HOST}}"
- ],
- "port": "{{DMI_PORT}}",
- "path": [
- "dmi",
- "v1",
- "data"
- ],
- "query": [
- {
- "key": "topic",
- "value": "ncmp-async-m2m"
- },
- {
- "key": "requestId",
- "value": "4753fc1f-7de2-449a-b306-a6204b5370b33"
- }
- ]
- }
- },
- "response": []
- },
- {
- "name": "Retrieve module resources for one or more modules",
- "request": {
- "method": "POST",
- "header": [],
- "body": {
- "mode": "raw",
- "raw": "{}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "http://{{DMI_HOST}}:{{DMI_PORT}}/dmi/v1/ch/cm-bookStore/moduleResources",
- "protocol": "http",
- "host": [
- "{{DMI_HOST}}"
- ],
- "port": "{{DMI_PORT}}",
- "path": [
- "dmi",
- "v1",
- "ch",
- "cm-bookStore",
- "moduleResources"
- ]
- }
- },
- "response": []
- },
- {
- "name": "Get all modules for given cm handle",
- "protocolProfileBehavior": {
- "disabledSystemHeaders": {
- "accept": true
- }
- },
- "request": {
- "method": "POST",
- "header": [
- {
- "key": "Accept",
- "value": "application/json",
- "type": "text"
- }
- ],
- "body": {
- "mode": "raw",
- "raw": "{}",
- "options": {
- "raw": {
- "language": "json"
- }
- }
- },
- "url": {
- "raw": "http://{{DMI_HOST}}:{{DMI_PORT}}/dmi/v1/ch/cm-bookStore/modules",
- "protocol": "http",
- "host": [
- "{{DMI_HOST}}"
- ],
- "port": "{{DMI_PORT}}",
- "path": [
- "dmi",
- "v1",
- "ch",
- "cm-bookStore",
- "modules"
- ]
- }
- },
- "response": []
- }
- ],
- "auth": {
- "type": "basic",
- "basic": [
- {
- "key": "password",
- "value": "cpsr0cks!",
- "type": "string"
- },
- {
- "key": "username",
- "value": "cpsuser",
- "type": "string"
- }
- ]
- },
- "event": [
- {
- "listen": "prerequest",
- "script": {
- "type": "text/javascript",
- "exec": [
- ""
- ]
- }
- },
- {
- "listen": "test",
- "script": {
- "type": "text/javascript",
- "exec": [
- ""
- ]
- }
- }
- ]
-} \ No newline at end of file
diff --git a/releases/3.5.1-container.yaml b/releases/3.5.1-container.yaml
new file mode 100644
index 000000000..ddd96ba36
--- /dev/null
+++ b/releases/3.5.1-container.yaml
@@ -0,0 +1,8 @@
+distribution_type: container
+container_release_tag: 3.5.1
+project: cps
+log_dir: cps-maven-docker-stage-master/943/
+ref: 7afd73d95b2de559e728b08abb7f003e70664c44
+containers:
+ - name: 'cps-and-ncmp'
+ version: '3.5.1-20240715T100945Z' \ No newline at end of file
diff --git a/releases/3.5.1.yaml b/releases/3.5.1.yaml
new file mode 100644
index 000000000..f265e331d
--- /dev/null
+++ b/releases/3.5.1.yaml
@@ -0,0 +1,4 @@
+distribution_type: maven
+log_dir: cps-maven-stage-master/951/
+project: cps
+version: 3.5.1 \ No newline at end of file
diff --git a/spotbugs/pom.xml b/spotbugs/pom.xml
index 7edfaac7c..38dea06eb 100644
--- a/spotbugs/pom.xml
+++ b/spotbugs/pom.xml
@@ -25,7 +25,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.onap.cps</groupId>
<artifactId>spotbugs</artifactId>
- <version>3.5.1-SNAPSHOT</version>
+ <version>3.5.2-SNAPSHOT</version>
<properties>
<nexusproxy>https://nexus.onap.org</nexusproxy>
diff --git a/version.properties b/version.properties
index 6345596e1..3c626cf77 100644
--- a/version.properties
+++ b/version.properties
@@ -22,7 +22,7 @@
major=3
minor=5
-patch=1
+patch=2
base_version=${major}.${minor}.${patch}