aboutsummaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service
diff options
context:
space:
mode:
Diffstat (limited to 'cps-ncmp-service')
-rw-r--r--cps-ncmp-service/pom.xml34
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpResponseStatus.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java204
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java27
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobService.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/DataJobService.java)14
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DataJobMetadata.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/DataJobMetadata.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DataJobReadRequest.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/DataJobReadRequest.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DataJobWriteRequest.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/DataJobWriteRequest.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DmiWriteOperation.java43
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/ProducerKey.java36
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/ReadOperation.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/ReadOperation.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteRequest.java41
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteResponse.java30
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/WriteOperation.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/WriteOperation.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpCachedResourceRequestHandler.java76
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandler.java96
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpPassthroughResourceRequestHandler.java103
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacade.java129
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java10
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java164
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiProperties.java55
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java145
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java59
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java114
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java111
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java35
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDelta.java13
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandler.java36
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionDmiOutEventConsumer.java54
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionNcmpInEventConsumer.java20
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java12
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/producer/CmNotificationSubscriptionDmiInEventProducer.java11
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/producer/CmNotificationSubscriptionNcmpOutEventProducer.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerService.java21
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImpl.java68
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImpl.java44
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java22
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreator.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiClientRequestException.java54
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidDmiResourceUrlException.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/HttpClientRequestException.java)22
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperation.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java240
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java39
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperationCmHandle.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/CmHandle.java)15
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java49
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java17
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManager.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDog.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceNameOrganizer.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java179
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java76
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java208
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryApiParameters.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryServiceParameters.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryServiceParameters.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponse.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java)4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java)5
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java)11
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/ConditionApiProperties.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/ConditionApiProperties.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistrationResponse.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java)4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java)3
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/UpgradedCmHandles.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/YangResource.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/YangResource.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/InvalidTopicException.java40
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NoAlternateIdParentFoundException.java)9
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/OperationNotSupportedException.java32
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/PayloadTooLargeException.java31
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImpl.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/DataJobServiceImpl.java)31
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java85
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java109
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryParametersValidator.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/RestQueryParametersValidator.java)8
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java)22
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java)14
-rw-r--r--[-rwxr-xr-x]cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java)331
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java)31
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java)4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/DataStoreSyncState.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java)16
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java)37
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java)3
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyCmHandleQueryService.java)11
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java)49
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleQueryConditions.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleState.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/InventoryQueryConditions.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/LockReasonCategory.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/ModelledDmiServiceLeaves.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/PropertyType.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java)6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java)11
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtils.java)37
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java)26
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java)14
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java)6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/WatchdogSchedulingConfigurer.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java)4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java63
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java)10
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/AbstractModelLoader.java6
-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/init/InventoryModelLoader.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/ModelLoader.java8
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/TopicValidator.java47
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/DataJobServiceImplSpec.groovy57
-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/NcmpCachedResourceRequestHandlerSpec.groovy64
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandlerSpec.groovy133
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy411
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacadeSpec.groovy108
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/WriteRequestExaminerSpec.groovy63
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumerSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy146
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiPropertiesSpec.groovy37
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfigurationSpec.groovy68
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy48
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy70
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfigSpec.groovy81
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfigSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDeltaSpec.groovy11
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDmiInEventProducerSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDmiOutEventConsumerSpec.groovy7
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionNcmpInEventConsumerSpec.groovy29
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandlerSpec.groovy37
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapperSpec.groovy10
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImplSpec.groovy60
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImplSpec.groovy45
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy22
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorSpec.groovy16
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DatastoreTypeSpec.groovy46
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy139
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy30
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy22
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/OperationTypeSpec.groovy48
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManagerSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDogSpec.groovy9
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/AlternateIdCheckerSpec.groovy6
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeBaseSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DataNodeHelperSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy109
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatterSpec.groovy45
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/YangDataConverterSpec.groovy3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/context/CpsApplicationContextSpec.groovy20
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy78
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy)11
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilderSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilderSpec.groovy)11
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/CompositeStateSpec.groovy)14
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/YangResourceTest.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangResourceTest.groovy)3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryParametersValidatorSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/RestQueryParametersValidatorSpec.groovy)27
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImplSpec.groovy)20
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandlerSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy)41
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy)98
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImplSpec.groovy)61
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy223
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyQueryServiceImplSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImplSpec.groovy)9
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy)25
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/CmHandleQueryConditionsSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy)3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditionsSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/InventoryQueryConditionsSpec.groovy)3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandleSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy)12
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutorSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutorSpec.groovy)5
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdogSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdogSpec.groovy)16
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy)32
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncServiceSpec.groovy)25
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasksSpec.groovy)21
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy)8
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy)3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/WatchdogSchedulingConfigurerSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurerSpec.groovy)3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy66
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/AbstractModelLoaderSpec.groovy14
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/CmDataSubscriptionModelLoaderSpec.groovy8
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy17
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/TopicValidatorSpec.groovy47
-rw-r--r--cps-ncmp-service/src/test/resources/application.yml15
-rw-r--r--cps-ncmp-service/src/test/resources/cmSubscription/cmNotificationSubscriptionNcmpInEvent.json4
180 files changed, 4467 insertions, 2473 deletions
diff --git a/cps-ncmp-service/pom.xml b/cps-ncmp-service/pom.xml
index fc41da3ae..1f94b34ea 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.0-SNAPSHOT</version>
+ <version>3.5.1-SNAPSHOT</version>
<relativePath>../cps-parent/pom.xml</relativePath>
</parent>
@@ -38,6 +38,22 @@
</properties>
<dependencies>
<dependency>
+ <groupId>io.opentelemetry</groupId>
+ <artifactId>opentelemetry-exporter-otlp</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.opentelemetry</groupId>
+ <artifactId>opentelemetry-sdk-extension-jaeger-remote-sampler</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.opentelemetry</groupId>
+ <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.opentelemetry.instrumentation</groupId>
+ <artifactId>opentelemetry-kafka-clients-2.6</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
@@ -58,6 +74,10 @@
<artifactId>cps-path-parser</artifactId>
</dependency>
<dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>annotations</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-spring</artifactId>
</dependency>
@@ -70,8 +90,8 @@
<artifactId>mapstruct-processor</artifactId>
</dependency>
<dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-web</artifactId>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- T E S T - D E P E N D E N C I E S -->
<dependency>
@@ -104,5 +124,13 @@
<artifactId>spock</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-actuator-autoconfigure</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.servlet</groupId>
+ <artifactId>jakarta.servlet-api</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpResponseStatus.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpResponseStatus.java
index bdc3dee77..8cfad7dbf 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpResponseStatus.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NcmpResponseStatus.java
@@ -26,14 +26,12 @@ import lombok.Getter;
public enum NcmpResponseStatus {
SUCCESS("0", "Successfully applied changes"),
- SUCCESSFULLY_APPLIED_SUBSCRIPTION("1", "successfully applied subscription"),
+ CM_DATA_SUBSCRIPTION_ACCEPTED("1", "ACCEPTED"),
CM_HANDLES_NOT_FOUND("100", "cm handle id(s) not found"),
CM_HANDLES_NOT_READY("101", "cm handle(s) not ready"),
DMI_SERVICE_NOT_RESPONDING("102", "dmi plugin service is not responding"),
UNABLE_TO_READ_RESOURCE_DATA("103", "dmi plugin service is not able to read resource data"),
- PARTIALLY_APPLIED_SUBSCRIPTION("104", "partially applied subscription"),
- SUBSCRIPTION_NOT_APPLICABLE("105", "subscription not applicable for all cm handles"),
- SUBSCRIPTION_PENDING("106", "subscription pending for all cm handles"),
+ CM_DATA_SUBSCRIPTION_REJECTED("104", "REJECTED"),
UNKNOWN_ERROR("108", "Unknown error"),
CM_HANDLE_ALREADY_EXIST("109", "cm-handle already exists"),
CM_HANDLE_INVALID_ID("110", "cm-handle has an invalid character(s) in id"),
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java
deleted file mode 100644
index 20545d711..000000000
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2021 highstreet technologies GmbH
- * Modifications Copyright (C) 2021-2024 Nordix Foundation
- * Modifications Copyright (C) 2021 Pantheon.tech
- * Modifications Copyright (C) 2022 Bell Canada
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.api;
-
-import java.util.Collection;
-import java.util.Map;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
-import org.onap.cps.ncmp.api.impl.operations.OperationType;
-import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters;
-import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters;
-import org.onap.cps.ncmp.api.models.CmResourceAddress;
-import org.onap.cps.ncmp.api.models.DataOperationRequest;
-import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
-import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
-import org.onap.cps.spi.FetchDescendantsOption;
-import org.onap.cps.spi.model.ModuleDefinition;
-import org.onap.cps.spi.model.ModuleReference;
-
-/*
- * Datastore interface for handling CPS data.
- */
-public interface NetworkCmProxyDataService {
-
- /**
- * Registration of New CM Handles.
- *
- * @param dmiPluginRegistration Dmi Plugin Registration
- * @return dmiPluginRegistrationResponse
- */
- DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(DmiPluginRegistration dmiPluginRegistration);
-
- /**
- * Get resource data for given data store using dmi.
- *
- * @param cmResourceAddress target datastore, cm handle and resource identifier
- * @param optionsParamInQuery options query
- * @param topicParamInQuery topic name for (triggering) async responses
- * @param requestId unique requestId for async request
- * @param authorization contents of Authorization header, or null if not present
- * @return {@code Object} resource data
- */
- Object getResourceDataForCmHandle(CmResourceAddress cmResourceAddress,
- String optionsParamInQuery,
- String topicParamInQuery,
- String requestId,
- String authorization);
-
- /**
- * Get resource data for operational.
- *
- * @param cmResourceAddress target datastore, cm handle and resource identifier
- * @Link FetchDescendantsOption fetch descendants option
- * @return {@code Object} resource data
- */
- Object getResourceDataForCmHandle(CmResourceAddress cmResourceAddress,
- FetchDescendantsOption fetchDescendantsOption);
-
- /**
- * Execute (async) data operation for group of cm handles using dmi.
- *
- * @param topicParamInQuery topic name for (triggering) async responses
- * @param dataOperationRequest contains a list of operation definitions(multiple operations)
- * @param requestId request ID
- * @param authorization contents of Authorization header, or null if not present
- */
- void executeDataOperationForCmHandles(String topicParamInQuery,
- DataOperationRequest dataOperationRequest,
- String requestId,
- String authorization);
-
-
- /**
- * Write resource data for data store pass-through running using dmi for given cm-handle.
- *
- * @param cmHandleId cm handle identifier
- * @param resourceIdentifier resource identifier
- * @param operationType required operation type
- * @param requestBody request body to create resource
- * @param contentType content type in body
- * @param authorization contents of Authorization header, or null if not present
- * @return {@code Object} return data
- */
- Object writeResourceDataPassThroughRunningForCmHandle(String cmHandleId,
- String resourceIdentifier,
- OperationType operationType,
- String requestBody,
- String contentType,
- String authorization);
-
- /**
- * Retrieve module references for the given cm handle.
- *
- * @param cmHandleId cm handle identifier
- * @return a collection of modules names and revisions
- */
- Collection<ModuleReference> getYangResourcesModuleReferences(String cmHandleId);
-
- /**
- * Retrieve module definitions for the given cm handle.
- *
- * @param cmHandleId cm handle identifier
- * @return a collection of module definition (moduleName, revision and yang resource content)
- */
- Collection<ModuleDefinition> getModuleDefinitionsByCmHandleId(String cmHandleId);
-
- /**
- * Get module definitions for the given parameters.
- *
- * @param cmHandleId cm-handle identifier
- * @param moduleName module name
- * @param moduleRevision the revision of the module
- * @return list of module definitions (module name, revision, yang resource content)
- */
- Collection<ModuleDefinition> getModuleDefinitionsByCmHandleAndModule(String cmHandleId,
- String moduleName,
- String moduleRevision);
-
- /**
- * Query cm handle details by cm handle's name.
- *
- * @param cmHandleId cm handle identifier
- * @return a collection of cm handle details.
- */
- NcmpServiceCmHandle getNcmpServiceCmHandle(String cmHandleId);
-
- /**
- * Get cm handle public properties by cm handle id.
- *
- * @param cmHandleId cm handle identifier
- * @return a collection of cm handle public properties.
- */
- Map<String, String> getCmHandlePublicProperties(String cmHandleId);
-
- /**
- * Get cm handle composite state by cm handle id.
- *
- * @param cmHandleId cm handle identifier
- * @return a cm handle composite state
- */
- CompositeState getCmHandleCompositeState(String cmHandleId);
-
- /**
- * Query and return cm handles that match the given query parameters.
- *
- * @param cmHandleQueryApiParameters the cm handle query parameters
- * @return collection of cm handles
- */
- Collection<NcmpServiceCmHandle> executeCmHandleSearch(CmHandleQueryApiParameters cmHandleQueryApiParameters);
-
- /**
- * Query and return cm handle ids that match the given query parameters.
- *
- * @param cmHandleQueryApiParameters the cm handle query parameters
- * @return collection of cm handle ids
- */
- Collection<String> executeCmHandleIdSearch(CmHandleQueryApiParameters cmHandleQueryApiParameters);
-
- /**
- * Set the data sync enabled flag, along with the data sync state to true or false based on the cm handle id.
- *
- * @param cmHandleId cm handle id
- * @param dataSyncEnabled data sync enabled flag
- */
- void setDataSyncEnabled(String cmHandleId, Boolean dataSyncEnabled);
-
- /**
- * Get all cm handle IDs by DMI plugin identifier.
- *
- * @param dmiPluginIdentifier DMI plugin identifier
- * @return collection of cm handle IDs
- */
- Collection<String> getAllCmHandleIdsByDmiPluginIdentifier(String dmiPluginIdentifier);
-
- /**
- * Get all cm handle IDs by various search criteria.
- *
- * @param cmHandleQueryServiceParameters cm handle query parameters
- * @return collection of cm handle IDs
- */
- Collection<String> executeCmHandleIdSearchForInventory(CmHandleQueryServiceParameters
- cmHandleQueryServiceParameters);
-}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java
index 340806b89..39d497217 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyQueryService.java
@@ -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,7 +20,9 @@
package org.onap.cps.ncmp.api;
+import java.util.Collection;
import org.onap.cps.spi.FetchDescendantsOption;
+import org.onap.cps.spi.model.DataNode;
/*
* Datastore interface for handling cached CPS data query requests.
@@ -28,14 +30,21 @@ import org.onap.cps.spi.FetchDescendantsOption;
public interface NetworkCmProxyQueryService {
/**
- * Get resource data for operational.
+ * Fetches operational resource data based on the provided CM handle identifier and CPS path.
+ * This method retrieves data nodes from the specified path within the context of a given CM handle.
+ * It supports options for fetching descendant nodes.
*
- * @param cmHandleId cm handle identifier
- * @param cpsPath cps path
- * @Link FetchDescendantsOption fetch descendants option
- * @return {@code Object} resource data
+ * @param cmHandleId The CM handle identifier, which uniquely identifies the CM handle.
+ * This parameter must not be null.
+ * @param cpsPath The CPS (Control Plane Service) path specifying the location of the
+ * resource data within the CM handle. This parameter must not be null.
+ * @param fetchDescendantsOption The option specifying whether to fetch descendant nodes along with the specified
+ * resource data.
+ * @return {@code Collection<DataNode>} A collection of DataNode objects representing the resource data
+ * retrieved from the specified path. The collection may include descendant nodes based on the
+ * fetchDescendantsOption.
*/
- Object queryResourceDataOperational(String cmHandleId,
- String cpsPath,
- FetchDescendantsOption fetchDescendantsOption);
+ Collection<DataNode> queryResourceDataOperational(String cmHandleId,
+ String cpsPath,
+ FetchDescendantsOption fetchDescendantsOption);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/DataJobService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobService.java
index 6122afc80..6ff79a934 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/DataJobService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/DataJobService.java
@@ -18,11 +18,13 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api;
+package org.onap.cps.ncmp.api.datajobs;
-import org.onap.cps.ncmp.api.models.datajob.DataJobMetadata;
-import org.onap.cps.ncmp.api.models.datajob.DataJobReadRequest;
-import org.onap.cps.ncmp.api.models.datajob.DataJobWriteRequest;
+import java.util.List;
+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.SubJobWriteResponse;
public interface DataJobService {
@@ -41,6 +43,8 @@ public interface DataJobService {
* @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
*/
- void writeDataJob(String dataJobId, DataJobMetadata dataJobMetadata, DataJobWriteRequest dataJobWriteRequest);
+ List<SubJobWriteResponse> writeDataJob(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/models/datajob/DataJobMetadata.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DataJobMetadata.java
index dc8037b86..564352d8d 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/DataJobMetadata.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DataJobMetadata.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models.datajob;
+package org.onap.cps.ncmp.api.datajobs.models;
/**
* Metadata of read/write data job request.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/DataJobReadRequest.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DataJobReadRequest.java
index f861c3d49..19408b1da 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/DataJobReadRequest.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DataJobReadRequest.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models.datajob;
+package org.onap.cps.ncmp.api.datajobs.models;
import java.util.List;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/DataJobWriteRequest.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DataJobWriteRequest.java
index 254e198b8..d8961b17c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/DataJobWriteRequest.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DataJobWriteRequest.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models.datajob;
+package org.onap.cps.ncmp.api.datajobs.models;
import java.util.List;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DmiWriteOperation.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DmiWriteOperation.java
new file mode 100644
index 000000000..7e9ca7988
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/DmiWriteOperation.java
@@ -0,0 +1,43 @@
+/*
+ * ============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.models;
+
+import java.util.Map;
+
+/**
+ * Describes the write data job operation to be forwarded to dmi.
+ *
+ * @param path Identifier of a managed object (MO) on a network element. Defines the resource on which
+ * operation is executed. Typically, is Fully Distinguished Name (FDN).
+ * @param op Describes the operation to execute. The value can be as below:
+ * e.g. "add", "replace", "remove", "action" etc.
+ * @param moduleSetTag The module set tag of the CM Handle.
+ * @param value The value to be written depends on the type of operation.
+ * @param operationId Unique identifier of the operation within the request.
+ * @param privateProperties Contains the private properties of a Cm Handle.
+ */
+public record DmiWriteOperation(
+ String path,
+ String op,
+ String moduleSetTag,
+ Object value,
+ String operationId,
+ Map<String, String> privateProperties) {}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/ProducerKey.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/ProducerKey.java
new file mode 100644
index 000000000..ac6b7f862
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/ProducerKey.java
@@ -0,0 +1,36 @@
+/*
+ * ============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.models;
+
+/**
+ * Composite key created from the DMI Service name and a data producer identifier.
+ * Helps to group of the sub job request for a given DMI Plugin.
+ *
+ * @param dmiServiceName Describes the name of the relevant DMI service.
+ * @param dataProducerIdentifier The name of a data producer identifier from a Cm Handle.
+ */
+public record ProducerKey(String dmiServiceName, String dataProducerIdentifier) {
+
+ @Override
+ public String toString() {
+ return dmiServiceName + "#" + dataProducerIdentifier;
+ }
+} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/ReadOperation.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/ReadOperation.java
index d2b073896..2459e4cc2 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/ReadOperation.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/ReadOperation.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models.datajob;
+package org.onap.cps.ncmp.api.datajobs.models;
import java.util.List;
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
new file mode 100644
index 000000000..432b21b8c
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteRequest.java
@@ -0,0 +1,41 @@
+/*
+ * ============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.models;
+
+import java.util.Collection;
+
+/**
+ * Response 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",
+ * "application/vnd.3gpp.object-tree-flat+json" etc.
+ * @param dataContentType Define the data request content type.
+ * e.g. "application/3gpp-json-patch+json" etc.
+ * @param dataProducerId Identifier of the data producer.
+ *
+ * @param data A collection of outgoing write operations.
+ */
+public record SubJobWriteRequest (
+ String dataAcceptType,
+ String dataContentType,
+ String dataProducerId,
+ Collection<DmiWriteOperation> data) {} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteResponse.java
new file mode 100644
index 000000000..9cdd8e059
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/SubJobWriteResponse.java
@@ -0,0 +1,30 @@
+/*
+ * ============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.models;
+
+/**
+ * Request data for a write operation towards DMI Plugin.
+ *
+ * @param subJobId Identifier of the sub-job from DMI.
+ * @param dmiServiceName The provided name of the DMI service from the request.
+ * @param dataProducerId Identifier of the data producer.
+ */
+public record SubJobWriteResponse(String subJobId, String dmiServiceName, String dataProducerId) {} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/WriteOperation.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/WriteOperation.java
index c2f6504ce..807e03f06 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/datajob/WriteOperation.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/datajobs/models/WriteOperation.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models.datajob;
+package org.onap.cps.ncmp.api.datajobs.models;
/**
* Holds information of write data job operation.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpCachedResourceRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpCachedResourceRequestHandler.java
new file mode 100644
index 000000000..da230cf73
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpCachedResourceRequestHandler.java
@@ -0,0 +1,76 @@
+/*
+ * ============LICENSE_START=======================================================
+ * 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.
+ * 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;
+
+import java.util.Collection;
+import lombok.RequiredArgsConstructor;
+import org.onap.cps.api.CpsDataService;
+import org.onap.cps.ncmp.api.NetworkCmProxyQueryService;
+import org.onap.cps.ncmp.api.models.CmResourceAddress;
+import org.onap.cps.spi.FetchDescendantsOption;
+import org.onap.cps.spi.model.DataNode;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Mono;
+
+@Service
+@RequiredArgsConstructor
+public class NcmpCachedResourceRequestHandler extends NcmpDatastoreRequestHandler {
+
+ private final CpsDataService cpsDataService;
+ private final NetworkCmProxyQueryService networkCmProxyQueryService;
+
+ /**
+ * Executes a synchronous query request for given cm handle.
+ * Note. Currently only ncmp-datastore:operational supports query operations.
+ *
+ * @param cmHandleId the cm handle
+ * @param resourceIdentifier the resource identifier
+ * @param includeDescendants whether include descendants
+ * @return a collection of data nodes
+ */
+ public Collection<DataNode> executeRequest(final String cmHandleId, final String resourceIdentifier,
+ final boolean includeDescendants) {
+ final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendants);
+ return networkCmProxyQueryService.queryResourceDataOperational(cmHandleId, resourceIdentifier,
+ fetchDescendantsOption);
+ }
+
+ @Override
+ protected Mono<Object> getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress,
+ final String optionsParamInQuery,
+ final String topicParamInQuery,
+ final String requestId,
+ final boolean includeDescendants,
+ final String authorization) {
+ final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendants);
+
+ final DataNode dataNode = cpsDataService.getDataNodes(cmResourceAddress.datastoreName(),
+ cmResourceAddress.cmHandleId(),
+ cmResourceAddress.resourceIdentifier(),
+ fetchDescendantsOption).iterator().next();
+ return Mono.justOrEmpty(dataNode);
+ }
+
+ private static FetchDescendantsOption getFetchDescendantsOption(final boolean includeDescendants) {
+ return includeDescendants ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
+ : FetchDescendantsOption.OMIT_DESCENDANTS;
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandler.java
new file mode 100644
index 000000000..302ba449c
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandler.java
@@ -0,0 +1,96 @@
+/*
+ * ============LICENSE_START=======================================================
+ * 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.
+ * 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;
+
+import java.util.Map;
+import java.util.UUID;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.models.CmResourceAddress;
+import org.onap.cps.ncmp.utils.TopicValidator;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Mono;
+
+@Slf4j
+@Service
+public abstract class NcmpDatastoreRequestHandler {
+
+ private static final String NO_REQUEST_ID = null;
+ private static final String NO_TOPIC = null;
+
+ @Value("${notification.async.executor.time-out-value-in-ms:60000}")
+ protected int timeOutInMilliSeconds;
+ @Value("${notification.enabled:true}")
+ protected boolean notificationFeatureEnabled;
+
+ /**
+ * Executes synchronous/asynchronous get request for given cm handle.
+ *
+ * @param cmResourceAddress the name of the datastore, cm handle and resource identifier
+ * @param options options to pass through to dmi client
+ * @param topic topic (optional) for asynchronous responses
+ * @param includeDescendants whether include descendants
+ * @param authorization contents of Authorization header, or null if not present
+ * @return the result object, depends on use op topic. With topic a map object with request id is returned
+ * otherwise the result of the request.
+ */
+ public Object executeRequest(final CmResourceAddress cmResourceAddress,
+ final String options,
+ final String topic,
+ final boolean includeDescendants,
+ final String authorization) {
+
+ final boolean asyncResponseRequested = topic != null;
+ if (asyncResponseRequested && notificationFeatureEnabled) {
+ return getResourceDataAsynchronously(cmResourceAddress, options, topic, includeDescendants, authorization);
+ }
+
+ if (asyncResponseRequested) {
+ log.warn("Asynchronous request is unavailable as notification feature is currently disabled, "
+ + "will use synchronous operation.");
+ }
+ final Mono<Object> resourceDataMono = getResourceDataForCmHandle(cmResourceAddress, options,
+ NO_TOPIC, NO_REQUEST_ID, includeDescendants, authorization);
+ return resourceDataMono.block();
+ }
+
+ private Map<String, String> getResourceDataAsynchronously(final CmResourceAddress cmResourceAddress,
+ final String options,
+ final String topic,
+ final boolean includeDescendants,
+ final String authorization) {
+ TopicValidator.validateTopicName(topic);
+ final String requestId = UUID.randomUUID().toString();
+ getResourceDataForCmHandle(cmResourceAddress, options, topic, requestId, includeDescendants, authorization)
+ .doOnSuccess(result ->
+ log.debug("Async operation succeeded for request id {}: {}", requestId, result))
+ .subscribe();
+ log.debug("Received Async request with id {}", requestId);
+ return Map.of("requestId", requestId);
+ }
+
+ protected abstract Mono<Object> getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress,
+ final String optionsParamInQuery,
+ final String topicParamInQuery,
+ final String requestId,
+ final boolean includeDescendant,
+ final String authorization);
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpPassthroughResourceRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpPassthroughResourceRequestHandler.java
new file mode 100644
index 000000000..0fd32501c
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NcmpPassthroughResourceRequestHandler.java
@@ -0,0 +1,103 @@
+/*
+ * ============LICENSE_START=======================================================
+ * 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.
+ * 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;
+
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL;
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ;
+
+import java.util.Map;
+import java.util.UUID;
+import lombok.RequiredArgsConstructor;
+import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException;
+import org.onap.cps.ncmp.api.impl.operations.DatastoreType;
+import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
+import org.onap.cps.ncmp.api.impl.operations.OperationType;
+import org.onap.cps.ncmp.api.models.CmResourceAddress;
+import org.onap.cps.ncmp.api.models.DataOperationRequest;
+import org.onap.cps.ncmp.exceptions.OperationNotSupportedException;
+import org.onap.cps.ncmp.exceptions.PayloadTooLargeException;
+import org.onap.cps.ncmp.utils.TopicValidator;
+import org.springframework.stereotype.Service;
+import reactor.core.publisher.Mono;
+
+@Service
+@RequiredArgsConstructor
+public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestHandler {
+
+ private final DmiDataOperations dmiDataOperations;
+
+ private static final int MAXIMUM_CM_HANDLES_PER_OPERATION = 200;
+ private static final String PAYLOAD_TOO_LARGE_TEMPLATE = "Operation '%s' affects too many (%d) cm handles";
+
+ /**
+ * Executes asynchronous request for group of cm handles to resource data.
+ *
+ * @param topic the topic param in query
+ * @param dataOperationRequest data operation request details for resource data
+ * @param authorization contents of Authorization header, or null if not present
+ * @return a map with one entry of request Id for success or status and error when async feature is disabled
+ */
+ public Map<String, String> executeAsynchronousRequest(final String topic,
+ final DataOperationRequest dataOperationRequest,
+ final String authorization) {
+ validateDataOperationRequest(topic, dataOperationRequest);
+ if (!notificationFeatureEnabled) {
+ return Map.of("status",
+ "Asynchronous request is unavailable as notification feature is currently disabled.");
+ }
+ final String requestId = UUID.randomUUID().toString();
+ dmiDataOperations.requestResourceDataFromDmi(topic, dataOperationRequest, requestId, authorization);
+ return Map.of("requestId", requestId);
+ }
+
+ @Override
+ protected Mono<Object> getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress,
+ final String options,
+ final String topic,
+ final String requestId,
+ final boolean includeDescendants,
+ final String authorization) {
+
+ return dmiDataOperations.getResourceDataFromDmi(cmResourceAddress, options, topic, requestId, authorization)
+ .flatMap(responseEntity -> Mono.justOrEmpty(responseEntity.getBody()));
+ }
+
+ private void validateDataOperationRequest(final String topicParamInQuery,
+ final DataOperationRequest dataOperationRequest) {
+ TopicValidator.validateTopicName(topicParamInQuery);
+ dataOperationRequest.getDataOperationDefinitions().forEach(dataOperationDefinition -> {
+ if (OperationType.fromOperationName(dataOperationDefinition.getOperation()) != READ) {
+ throw new OperationNotSupportedException(
+ dataOperationDefinition.getOperation() + " operation not yet supported");
+ }
+ if (DatastoreType.fromDatastoreName(dataOperationDefinition.getDatastore()) == OPERATIONAL) {
+ throw new InvalidDatastoreException(dataOperationDefinition.getDatastore()
+ + " datastore is not supported");
+ }
+ if (dataOperationDefinition.getCmHandleIds().size() > MAXIMUM_CM_HANDLES_PER_OPERATION) {
+ final String errorMessage = String.format(PAYLOAD_TOO_LARGE_TEMPLATE,
+ dataOperationDefinition.getOperationId(),
+ dataOperationDefinition.getCmHandleIds().size());
+ throw new PayloadTooLargeException(errorMessage);
+ }
+ });
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacade.java
new file mode 100644
index 000000000..a24b18446
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacade.java
@@ -0,0 +1,129 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 highstreet technologies GmbH
+ * Modifications Copyright (C) 2021-2024 Nordix Foundation
+ * Modifications Copyright (C) 2021 Pantheon.tech
+ * Modifications Copyright (C) 2021-2022 Bell Canada
+ * Modifications Copyright (C) 2023 TechMahindra Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl;
+
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL;
+
+import java.util.Collection;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.impl.operations.DatastoreType;
+import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
+import org.onap.cps.ncmp.api.impl.operations.OperationType;
+import org.onap.cps.ncmp.api.models.CmResourceAddress;
+import org.onap.cps.ncmp.api.models.DataOperationRequest;
+import org.onap.cps.spi.model.DataNode;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class NetworkCmProxyFacade {
+
+ private final NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler;
+ private final NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler;
+ private final DmiDataOperations dmiDataOperations;
+
+ /**
+ * Fetches resource data for a given data store using DMI (Data Management Interface).
+ * This method retrieves data based on the provided CmResourceAddress and additional query parameters.
+ * It supports asynchronous processing and handles authorization if required.
+ *
+ * @param cmResourceAddress The target data store, including the CM handle and resource identifier.
+ * This parameter must not be null.
+ * @param options Additional query parameters that may influence the data retrieval process,
+ * such as filters or limits. This parameter can be null.
+ * @param topic The topic name for triggering asynchronous responses. If specified,
+ * the response will be sent to this topic. This parameter can be null.
+ * @param includeDescendants include (all) descendants or not
+ * @param authorization The contents of the Authorization header. This parameter can be null
+ * if authorization is not required.
+ * @return the result object, depends on use op topic. With topic a map object with request id is returned
+ * otherwise the result of the request.
+ */
+ public Object getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress,
+ final String options,
+ final String topic,
+ final Boolean includeDescendants,
+ final String authorization) {
+ final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler
+ = getNcmpDatastoreRequestHandler(cmResourceAddress.datastoreName());
+
+ return ncmpDatastoreRequestHandler.executeRequest(cmResourceAddress, options, topic, includeDescendants,
+ authorization);
+ }
+
+ /**
+ * Executes asynchronous request for group of cm handles to resource data.
+ *
+ * @param topic the topic param in query
+ * @param dataOperationRequest data operation request details for resource data
+ * @param authorization contents of Authorization header, or null if not present
+ * @return a map with one entry of request Id for success or status and error when async feature is disabled
+ */
+ public Object executeDataOperationForCmHandles(final String topic,
+ final DataOperationRequest dataOperationRequest,
+ final String authorization) {
+ return ncmpPassthroughResourceRequestHandler.executeAsynchronousRequest(topic,
+ dataOperationRequest,
+ authorization);
+ }
+
+ public Collection<DataNode> queryResourceDataForCmHandle(final String cmHandle,
+ final String cpsPath,
+ final Boolean includeDescendants) {
+ return ncmpCachedResourceRequestHandler.executeRequest(cmHandle, cpsPath, includeDescendants);
+ }
+
+ /**
+ * Write resource data for data store pass-through running using dmi for given cm-handle.
+ *
+ * @param cmHandleId cm handle identifier
+ * @param resourceIdentifier resource identifier
+ * @param operationType required operation type
+ * @param requestData request body to create resource
+ * @param dataType content type in body
+ * @param authorization contents of Authorization header, or null if not present
+ * @return {@code Object} return data
+ */
+ public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandleId,
+ final String resourceIdentifier,
+ final OperationType operationType,
+ final String requestData,
+ final String dataType,
+ final String authorization) {
+ return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleId, resourceIdentifier,
+ operationType, requestData, dataType, authorization);
+ }
+
+
+ private NcmpDatastoreRequestHandler getNcmpDatastoreRequestHandler(final String datastoreName) {
+ if (OPERATIONAL.equals(DatastoreType.fromDatastoreName(datastoreName))) {
+ return ncmpCachedResourceRequestHandler;
+ }
+ return ncmpPassthroughResourceRequestHandler;
+ }
+
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java
index d8353f302..8507fb773 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImpl.java
@@ -20,13 +20,15 @@
package org.onap.cps.ncmp.api.impl;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
+import java.util.Collection;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.api.CpsQueryService;
import org.onap.cps.ncmp.api.NetworkCmProxyQueryService;
import org.onap.cps.spi.FetchDescendantsOption;
+import org.onap.cps.spi.model.DataNode;
import org.springframework.stereotype.Service;
@Slf4j
@@ -37,9 +39,9 @@ public class NetworkCmProxyQueryServiceImpl implements NetworkCmProxyQueryServic
private final CpsQueryService cpsQueryService;
@Override
- public Object queryResourceDataOperational(final String cmHandleId,
- final String cpsPath,
- final FetchDescendantsOption fetchDescendantsOption) {
+ public Collection<DataNode> queryResourceDataOperational(final String cmHandleId,
+ final String cpsPath,
+ final FetchDescendantsOption fetchDescendantsOption) {
return cpsQueryService.queryDataNodes(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId, cpsPath,
fetchDescendantsOption);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
index 798a280c8..d4c5d16a4 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation
+ * Copyright (C) 2021-2024 Nordix Foundation
* Modifications Copyright (C) 2022 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,20 +21,36 @@
package org.onap.cps.ncmp.api.impl.client;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR;
+import static org.springframework.http.HttpStatus.BAD_REQUEST;
+import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
+import static org.springframework.http.HttpStatus.REQUEST_TIMEOUT;
+
import com.fasterxml.jackson.databind.JsonNode;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.Locale;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration.DmiProperties;
-import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException;
+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.exception.InvalidDmiResourceUrlException;
import org.onap.cps.ncmp.api.impl.operations.OperationType;
-import org.springframework.http.HttpEntity;
+import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService;
+import org.onap.cps.utils.JsonObjectMapper;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
+import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
-import org.springframework.web.client.HttpStatusCodeException;
-import org.springframework.web.client.RestTemplate;
+import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.client.WebClientRequestException;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+import reactor.core.publisher.Mono;
@Component
@RequiredArgsConstructor
@@ -43,60 +59,136 @@ public class DmiRestClient {
private static final String HEALTH_CHECK_URL_EXTENSION = "/actuator/health";
private static final String NOT_SPECIFIED = "";
- private final RestTemplate restTemplate;
+ private static final String NO_AUTHORIZATION = null;
+
private final DmiProperties dmiProperties;
+ private final JsonObjectMapper jsonObjectMapper;
+ @Qualifier("dataServicesWebClient")
+ private final WebClient dataServicesWebClient;
+ @Qualifier("modelServicesWebClient")
+ private final WebClient modelServicesWebClient;
+ @Qualifier("healthChecksWebClient")
+ private final WebClient healthChecksWebClient;
/**
- * Sends POST operation to DMI with json body containing module references.
+ * Sends a synchronous (blocking) POST operation to the DMI with a JSON body containing module references.
*
- * @param dmiResourceUrl dmi resource url
- * @param requestBodyAsJsonString json data body
- * @param operationType the type of operation being executed (for error reporting only)
- * @param authorization contents of Authorization header, or null if not present
- * @return response entity of type String
+ * @param requiredDmiService Determines if the required service is for a data or model operation.
+ * @param dmiUrl The DMI resource URL.
+ * @param requestBodyAsJsonString JSON data body.
+ * @param operationType The type of operation being executed (for error reporting only).
+ * @param authorization Contents of the Authorization header, or null if not present.
+ * @return ResponseEntity containing the response from the DMI.
+ * @throws DmiClientRequestException If there is an error during the DMI request.
*/
- public ResponseEntity<Object> postOperationWithJsonData(final String dmiResourceUrl,
+ public ResponseEntity<Object> synchronousPostOperationWithJsonData(final RequiredDmiService requiredDmiService,
+ final String dmiUrl,
+ final String requestBodyAsJsonString,
+ final OperationType operationType,
+ final String authorization) {
+ final Mono<ResponseEntity<Object>> responseEntityMono =
+ asynchronousPostOperationWithJsonData(requiredDmiService,
+ dmiUrl,
+ requestBodyAsJsonString,
+ operationType,
+ authorization);
+ return responseEntityMono.block();
+ }
+
+ /**
+ * Asynchronously performs an HTTP POST operation with the given JSON data.
+ *
+ * @param requiredDmiService The service object required for retrieving or configuring the WebClient.
+ * @param dmiUrl The URL to which the POST request is sent.
+ * @param requestBodyAsJsonString The JSON string that will be sent as the request body.
+ * @param operationType An enumeration or object that holds information about the type of operation
+ * being performed.
+ * @param authorization The authorization token to be added to the request headers.
+ * @return A Mono emitting the response entity containing the server's response.
+ */
+ public Mono<ResponseEntity<Object>> asynchronousPostOperationWithJsonData(
+ final RequiredDmiService requiredDmiService,
+ final String dmiUrl,
final String requestBodyAsJsonString,
final OperationType operationType,
final String authorization) {
- final var httpEntity = new HttpEntity<>(requestBodyAsJsonString, configureHttpHeaders(new HttpHeaders(),
- authorization));
- try {
- return restTemplate.postForEntity(dmiResourceUrl, httpEntity, Object.class);
- } catch (final HttpStatusCodeException httpStatusCodeException) {
- final String exceptionMessage = "Unable to " + operationType.toString() + " resource data.";
- throw new HttpClientRequestException(exceptionMessage, httpStatusCodeException.getResponseBodyAsString(),
- httpStatusCodeException.getStatusCode().value());
- }
+ final WebClient webClient = getWebClient(requiredDmiService);
+ return webClient.post()
+ .uri(toUri(dmiUrl))
+ .headers(httpHeaders -> configureHttpHeaders(httpHeaders, authorization))
+ .body(BodyInserters.fromValue(requestBodyAsJsonString))
+ .retrieve()
+ .toEntity(Object.class)
+ .onErrorMap(throwable -> handleDmiClientException(throwable, operationType.getOperationName()));
}
/**
* Get DMI plugin health status.
*
- * @param dmiPluginBaseUrl the base URL of the dmi-plugin
- * @return plugin health status ("UP" is all OK, "" (not-specified) in case of any exception)
+ * @param dmiUrl the base URL of the dmi-plugin
+ * @return plugin health status ("UP" is all OK, "" (not-specified) in case of any exception)
*/
- public String getDmiHealthStatus(final String dmiPluginBaseUrl) {
- final HttpEntity<Object> httpHeaders = new HttpEntity<>(configureHttpHeaders(new HttpHeaders(), null));
+ public String getDmiHealthStatus(final String dmiUrl) {
try {
- final JsonNode responseHealthStatus =
- restTemplate.getForObject(dmiPluginBaseUrl + HEALTH_CHECK_URL_EXTENSION,
- JsonNode.class, httpHeaders);
+ final URI dmiHealthCheckUri = toUri(dmiUrl + HEALTH_CHECK_URL_EXTENSION);
+ final JsonNode responseHealthStatus = healthChecksWebClient.get()
+ .uri(dmiHealthCheckUri)
+ .headers(httpHeaders -> configureHttpHeaders(httpHeaders, NO_AUTHORIZATION))
+ .retrieve()
+ .bodyToMono(JsonNode.class).block();
return responseHealthStatus == null ? NOT_SPECIFIED :
- responseHealthStatus.get("status").asText();
+ responseHealthStatus.path("status").asText();
} catch (final Exception e) {
- log.warn("Failed to retrieve health status from {}. Error Message: {}", dmiPluginBaseUrl, e.getMessage());
+ log.warn("Failed to retrieve health status from {}. Error Message: {}", dmiUrl, e.getMessage());
return NOT_SPECIFIED;
}
}
- private HttpHeaders configureHttpHeaders(final HttpHeaders httpHeaders, final String authorization) {
+ private WebClient getWebClient(final RequiredDmiService requiredDmiService) {
+ return requiredDmiService.equals(RequiredDmiService.DATA) ? dataServicesWebClient : modelServicesWebClient;
+ }
+
+ private void configureHttpHeaders(final HttpHeaders httpHeaders, final String authorization) {
if (dmiProperties.isDmiBasicAuthEnabled()) {
httpHeaders.setBasicAuth(dmiProperties.getAuthUsername(), dmiProperties.getAuthPassword());
} else if (authorization != null && authorization.toLowerCase(Locale.getDefault()).startsWith("bearer ")) {
httpHeaders.add(HttpHeaders.AUTHORIZATION, authorization);
}
- httpHeaders.setContentType(MediaType.APPLICATION_JSON);
- return httpHeaders;
+ }
+
+ private static URI toUri(final String dmiResourceUrl) {
+ try {
+ return new URI(dmiResourceUrl);
+ } catch (final URISyntaxException e) {
+ throw new InvalidDmiResourceUrlException(dmiResourceUrl, BAD_REQUEST.value());
+ }
+ }
+
+ private DmiClientRequestException handleDmiClientException(final Throwable throwable, final String operationType) {
+ if (throwable instanceof WebClientResponseException webClientResponseException) {
+ if (webClientResponseException.getStatusCode().isSameCodeAs(REQUEST_TIMEOUT)) {
+ throw new DmiClientRequestException(webClientResponseException.getStatusCode().value(),
+ webClientResponseException.getMessage(),
+ jsonObjectMapper.asJsonString(webClientResponseException.getResponseBodyAsString()),
+ DMI_SERVICE_NOT_RESPONDING);
+ }
+ throw new DmiClientRequestException(webClientResponseException.getStatusCode().value(),
+ webClientResponseException.getMessage(),
+ jsonObjectMapper.asJsonString(webClientResponseException.getResponseBodyAsString()),
+ UNABLE_TO_READ_RESOURCE_DATA);
+
+ }
+ final String exceptionMessage = "Unable to " + operationType + " resource data.";
+ if (throwable instanceof WebClientRequestException webClientRequestException) {
+ throw new DmiClientRequestException(HttpStatus.SERVICE_UNAVAILABLE.value(),
+ webClientRequestException.getMessage(),
+ exceptionMessage, DMI_SERVICE_NOT_RESPONDING);
+ }
+ if (throwable instanceof HttpServerErrorException httpServerErrorException) {
+ throw new DmiClientRequestException(httpServerErrorException.getStatusCode().value(), exceptionMessage,
+ httpServerErrorException.getResponseBodyAsString(), DMI_SERVICE_NOT_RESPONDING);
+ }
+ throw new DmiClientRequestException(INTERNAL_SERVER_ERROR.value(), exceptionMessage, throwable.getMessage(),
+ UNKNOWN_ERROR);
}
}
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/api/impl/config/DmiProperties.java
new file mode 100644
index 000000000..5453efecd
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiProperties.java
@@ -0,0 +1,55 @@
+/*
+ * ============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 lombok.AccessLevel;
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Getter
+@Component
+public class DmiProperties {
+ @Value("${ncmp.dmi.auth.username}")
+ private String authUsername;
+ @Value("${ncmp.dmi.auth.password}")
+ private String authPassword;
+ @Getter(AccessLevel.NONE)
+ @Value("${ncmp.dmi.api.base-path}")
+ private String dmiBasePath;
+ @Value("${ncmp.dmi.auth.enabled}")
+ private boolean dmiBasicAuthEnabled;
+
+ /**
+ * Removes both leading and trailing slashes if they are present.
+ *
+ * @return dmi base path without any slashes ("/")
+ */
+ public String getDmiBasePath() {
+ if (dmiBasePath.startsWith("/")) {
+ dmiBasePath = dmiBasePath.substring(1);
+ }
+ if (dmiBasePath.endsWith("/")) {
+ dmiBasePath = dmiBasePath.substring(0, dmiBasePath.length() - 1);
+ }
+ return dmiBasePath;
+ }
+}
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/api/impl/config/DmiWebClientConfiguration.java
new file mode 100644
index 000000000..3a861a68b
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfiguration.java
@@ -0,0 +1,145 @@
+/*
+ * ============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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import io.netty.channel.ChannelOption;
+import io.netty.handler.timeout.ReadTimeoutHandler;
+import io.netty.handler.timeout.WriteTimeoutHandler;
+import io.netty.resolver.DefaultAddressResolverGroup;
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.netty.http.client.HttpClient;
+import reactor.netty.resources.ConnectionProvider;
+
+/**
+ * Configures and creates WebClient beans for various DMI services including data, model, and health check services.
+ * The configuration utilizes Netty-based HttpClient with custom connection settings, read and write timeouts,
+ * and initializes WebClient with these settings to ensure optimal performance and resource management.
+ */
+@Configuration
+@RequiredArgsConstructor
+public class DmiWebClientConfiguration {
+
+ private final HttpClientConfiguration httpClientConfiguration;
+
+ private static final Duration DEFAULT_RESPONSE_TIMEOUT = Duration.ofSeconds(30);
+
+ /**
+ * Configures and creates a WebClient bean for DMI data services.
+ *
+ * @return a WebClient instance configured for data services.
+ */
+ @Bean
+ public WebClient dataServicesWebClient() {
+ final HttpClientConfiguration.DataServices dataServiceConfig = httpClientConfiguration.getDataServices();
+ final ConnectionProvider dataServicesConnectionProvider
+ = getConnectionProvider(dataServiceConfig.getConnectionProviderName(),
+ dataServiceConfig.getMaximumConnectionsTotal(), dataServiceConfig.getPendingAcquireMaxCount());
+ final HttpClient dataServicesHttpClient = createHttpClient(dataServiceConfig, dataServicesConnectionProvider);
+ return buildAndGetWebClient(dataServicesHttpClient, dataServiceConfig.getMaximumInMemorySizeInMegabytes());
+ }
+
+ /**
+ * Configures and creates a WebClient bean for DMI model services.
+ *
+ * @return a WebClient instance configured for model services.
+ */
+ @Bean
+ public WebClient modelServicesWebClient() {
+ final HttpClientConfiguration.ModelServices modelServiceConfig = httpClientConfiguration.getModelServices();
+ final ConnectionProvider modelServicesConnectionProvider
+ = getConnectionProvider(modelServiceConfig.getConnectionProviderName(),
+ modelServiceConfig.getMaximumConnectionsTotal(),
+ modelServiceConfig.getPendingAcquireMaxCount());
+ final HttpClient modelServicesHttpClient
+ = createHttpClient(modelServiceConfig, modelServicesConnectionProvider);
+ return buildAndGetWebClient(modelServicesHttpClient, modelServiceConfig.getMaximumInMemorySizeInMegabytes());
+ }
+
+ /**
+ * Configures and creates a WebClient bean for DMI health check services.
+ *
+ * @return a WebClient instance configured for health check services.
+ */
+ @Bean
+ public WebClient healthChecksWebClient() {
+ final HttpClientConfiguration.HealthCheckServices healthCheckServiceConfig
+ = httpClientConfiguration.getHealthCheckServices();
+ final ConnectionProvider healthChecksConnectionProvider
+ = getConnectionProvider(healthCheckServiceConfig.getConnectionProviderName(),
+ healthCheckServiceConfig.getMaximumConnectionsTotal(),
+ healthCheckServiceConfig.getPendingAcquireMaxCount());
+ final HttpClient healthChecksHttpClient
+ = createHttpClient(healthCheckServiceConfig, healthChecksConnectionProvider);
+ return buildAndGetWebClient(healthChecksHttpClient,
+ healthCheckServiceConfig.getMaximumInMemorySizeInMegabytes());
+ }
+
+ /**
+ * Provides a WebClient.Builder bean for creating WebClient instances.
+ *
+ * @return a WebClient.Builder instance.
+ */
+ @Bean
+ public WebClient.Builder webClientBuilder() {
+ return WebClient.builder();
+ }
+
+ private static HttpClient createHttpClient(final HttpClientConfiguration.ServiceConfig serviceConfig,
+ final ConnectionProvider connectionProvider) {
+ return HttpClient.create(connectionProvider)
+ .responseTimeout(DEFAULT_RESPONSE_TIMEOUT)
+ .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, serviceConfig.getConnectionTimeoutInSeconds() * 1000)
+ .doOnConnected(connection -> connection.addHandlerLast(new ReadTimeoutHandler(
+ serviceConfig.getReadTimeoutInSeconds(), TimeUnit.SECONDS)).addHandlerLast(
+ new WriteTimeoutHandler(serviceConfig.getWriteTimeoutInSeconds(), TimeUnit.SECONDS)))
+ .resolver(DefaultAddressResolverGroup.INSTANCE)
+ .compress(true);
+ }
+
+ @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE")
+ private static ConnectionProvider getConnectionProvider(final String connectionProviderName,
+ final int maximumConnectionsTotal,
+ final int pendingAcquireMaxCount) {
+ return ConnectionProvider.builder(connectionProviderName)
+ .maxConnections(maximumConnectionsTotal)
+ .pendingAcquireMaxCount(pendingAcquireMaxCount)
+ .build();
+ }
+
+ private WebClient buildAndGetWebClient(final HttpClient httpClient,
+ final int maximumInMemorySizeInMegabytes) {
+ return webClientBuilder()
+ .defaultHeaders(header -> header.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
+ .defaultHeaders(header -> header.set(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE))
+ .clientConnector(new ReactorClientHttpConnector(httpClient))
+ .codecs(configurer -> configurer.defaultCodecs()
+ .maxInMemorySize(maximumInMemorySizeInMegabytes * 1024 * 1024)).build();
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java
index d547e31c6..0acbabbba 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/api/impl/config/HttpClientConfiguration.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation.
+ * 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.
@@ -20,38 +20,53 @@
package org.onap.cps.ncmp.api.impl.config;
-import java.time.Duration;
-import java.time.temporal.ChronoUnit;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.convert.DurationUnit;
+import org.springframework.context.annotation.Configuration;
@Getter
@Setter
-@ConfigurationProperties(prefix = "ncmp.dmi.httpclient", ignoreUnknownFields = true)
+@Configuration
+@ConfigurationProperties(prefix = "ncmp.dmi.httpclient")
public class HttpClientConfiguration {
- /**
- * The maximum time to establish a connection.
- */
- @DurationUnit(ChronoUnit.SECONDS)
- private Duration connectionTimeoutInSeconds = Duration.ofSeconds(180);
+ private final DataServices dataServices = new DataServices();
+ private final ModelServices modelServices = new ModelServices();
+ private final HealthCheckServices healthCheckServices = new HealthCheckServices();
- /**
- * The maximum number of open connections per route.
- */
- private int maximumConnectionsPerRoute = 50;
+ @Getter
+ @Setter
+ public static class DataServices extends ServiceConfig {
+ private String connectionProviderName = "dataConnectionPool";
+ }
- /**
- * The maximum total number of open connections.
- */
- private int maximumConnectionsTotal = maximumConnectionsPerRoute * 2;
+ @Getter
+ @Setter
+ public static class ModelServices extends ServiceConfig {
+ private String connectionProviderName = "modelConnectionPool";
+ }
+
+ @Getter
+ @Setter
+ public static class HealthCheckServices extends ServiceConfig {
+ private String connectionProviderName = "healthConnectionPool";
+ private int maximumConnectionsTotal = 10;
+ private int pendingAcquireMaxCount = 5;
+ }
/**
- * The duration after which idle connections are evicted.
+ * Base configuration properties for all services.
*/
- @DurationUnit(ChronoUnit.SECONDS)
- private Duration idleConnectionEvictionThresholdInSeconds = Duration.ofSeconds(5);
-
+ @Getter
+ @Setter
+ public static class ServiceConfig {
+ private String connectionProviderName = "cpsConnectionPool";
+ private int maximumConnectionsTotal = 100;
+ private int pendingAcquireMaxCount = 50;
+ private Integer connectionTimeoutInSeconds = 30;
+ private long readTimeoutInSeconds = 30;
+ private long writeTimeoutInSeconds = 30;
+ private int maximumInMemorySizeInMegabytes = 1;
+ }
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java
deleted file mode 100644
index c6ff116a7..000000000
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.api.impl.config;
-
-import java.util.Arrays;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.apache.hc.client5.http.config.ConnectionConfig;
-import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
-import org.apache.hc.client5.http.impl.classic.HttpClients;
-import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
-import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
-import org.apache.hc.core5.util.TimeValue;
-import org.apache.hc.core5.util.Timeout;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.beans.factory.config.ConfigurableBeanFactory;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.boot.web.client.RestTemplateBuilder;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Scope;
-import org.springframework.http.MediaType;
-import org.springframework.http.client.ClientHttpRequestFactory;
-import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
-import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestTemplate;
-
-@Configuration
-@EnableConfigurationProperties(HttpClientConfiguration.class)
-@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
-public class NcmpConfiguration {
-
- @Getter
- @Component
- public static class DmiProperties {
- @Value("${ncmp.dmi.auth.username}")
- private String authUsername;
- @Value("${ncmp.dmi.auth.password}")
- private String authPassword;
- @Value("${ncmp.dmi.api.base-path}")
- private String dmiBasePath;
- @Value("${ncmp.dmi.auth.enabled}")
- private boolean dmiBasicAuthEnabled;
- }
-
- /**
- * Rest template bean.
- *
- * @param restTemplateBuilder the rest template builder
- * @param httpClientConfiguration the http client configuration
- * @return rest template instance
- */
- @Bean
- @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
- public static RestTemplate restTemplate(final RestTemplateBuilder restTemplateBuilder,
- final HttpClientConfiguration httpClientConfiguration) {
-
- final ConnectionConfig connectionConfig = ConnectionConfig.copy(ConnectionConfig.DEFAULT)
- .setConnectTimeout(Timeout.of(httpClientConfiguration.getConnectionTimeoutInSeconds()))
- .build();
-
- final PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
- .setDefaultConnectionConfig(connectionConfig)
- .setMaxConnTotal(httpClientConfiguration.getMaximumConnectionsTotal())
- .setMaxConnPerRoute(httpClientConfiguration.getMaximumConnectionsPerRoute())
- .build();
-
- final CloseableHttpClient httpClient = HttpClients.custom()
- .setConnectionManager(connectionManager)
- .evictExpiredConnections()
- .evictIdleConnections(
- TimeValue.of(httpClientConfiguration.getIdleConnectionEvictionThresholdInSeconds()))
- .build();
-
- final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
-
- final RestTemplate restTemplate = restTemplateBuilder
- .requestFactory(() -> requestFactory)
- .setConnectTimeout(httpClientConfiguration.getConnectionTimeoutInSeconds())
- .build();
-
- setRestTemplateMessageConverters(restTemplate);
- return restTemplate;
- }
-
- private static void setRestTemplateMessageConverters(final RestTemplate restTemplate) {
- final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
- new MappingJackson2HttpMessageConverter();
- mappingJackson2HttpMessageConverter.setSupportedMediaTypes(
- Arrays.asList(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN));
- restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
- }
-
-}
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/api/impl/config/OpenTelemetryConfig.java
new file mode 100644
index 000000000..bcbacbd42
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java
@@ -0,0 +1,111 @@
+/*
+ * ============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.micrometer.observation.ObservationPredicate;
+import io.micrometer.observation.ObservationRegistry;
+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 java.time.Duration;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryCustomizer;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.server.observation.ServerRequestObservationContext;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.util.PathMatcher;
+
+@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;
+
+ @Value("${cps.tracing.exporter.endpoint:http://onap-otel-collector:4317}")
+ private String tracingExporterEndpointUrl;
+
+ @Value("${cps.tracing.sampler.jaeger_remote.endpoint:http://onap-otel-collector:14250}")
+ private String jaegerRemoteSamplerUrl;
+
+ /**
+ * OTLP Exporter with Grpc exporter protocol.
+ */
+ @Bean
+ @ConditionalOnExpression(
+ "${cps.tracing.enabled} && 'grpc'.equals('${cps.tracing.exporter.protocol}')")
+ public OtlpGrpcSpanExporter createOtlpExporterGrpc() {
+ return OtlpGrpcSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build();
+ }
+
+ /**
+ * OTLP Exporter with HTTP exporter protocol.
+ */
+ @Bean
+ @ConditionalOnExpression(
+ "${cps.tracing.enabled} && 'http'.equals('${cps.tracing.exporter.protocol}')")
+ public OtlpHttpSpanExporter createOtlpExporterHttp() {
+ return OtlpHttpSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build();
+ }
+
+ /**
+ * Jaeger Remote Sampler.
+ */
+ @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();
+ }
+
+ /**
+ * Excluding /actuator/** endpoints.
+ */
+ @Bean
+ @ConditionalOnProperty("cps.tracing.enabled")
+ ObservationRegistryCustomizer<ObservationRegistry> skipActuatorEndpointsFromObservation() {
+ final PathMatcher pathMatcher = new AntPathMatcher("/");
+ return registry ->
+ registry.observationConfig().observationPredicate(observationPredicate(pathMatcher));
+ }
+
+ /**
+ * Excluding /actuator/** endpoints.
+ */
+ static ObservationPredicate observationPredicate(final PathMatcher pathMatcher) {
+ return (name, context) -> {
+ if (context instanceof ServerRequestObservationContext observationContext) {
+ return !pathMatcher.match("/actuator/**", observationContext.getCarrier().getRequestURI());
+ } else {
+ return true;
+ }
+ };
+ }
+} \ No newline at end of file
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/api/impl/config/kafka/KafkaConfig.java
index 167df5a98..cf6f1c5b1 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/api/impl/config/kafka/KafkaConfig.java
@@ -21,10 +21,14 @@
package org.onap.cps.ncmp.api.impl.config.kafka;
import io.cloudevents.CloudEvent;
+import io.opentelemetry.instrumentation.kafkaclients.v2_6.TracingConsumerInterceptor;
+import io.opentelemetry.instrumentation.kafkaclients.v2_6.TracingProducerInterceptor;
import java.time.Duration;
import java.util.Map;
import lombok.RequiredArgsConstructor;
+import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.kafka.KafkaProperties;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.context.annotation.Bean;
@@ -52,6 +56,9 @@ public class KafkaConfig<T> {
private final KafkaProperties kafkaProperties;
+ @Value("${cps.tracing.enabled:false}")
+ private boolean tracingEnabled;
+
private static final SslBundles NO_SSL = null;
/**
@@ -64,6 +71,10 @@ public class KafkaConfig<T> {
public ProducerFactory<String, T> legacyEventProducerFactory() {
final Map<String, Object> producerConfigProperties = kafkaProperties.buildProducerProperties(NO_SSL);
producerConfigProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
+ if (tracingEnabled) {
+ producerConfigProperties.put(
+ ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingProducerInterceptor.class.getName());
+ }
return new DefaultKafkaProducerFactory<>(producerConfigProperties);
}
@@ -77,6 +88,10 @@ public class KafkaConfig<T> {
public ConsumerFactory<String, T> legacyEventConsumerFactory() {
final Map<String, Object> consumerConfigProperties = kafkaProperties.buildConsumerProperties(NO_SSL);
consumerConfigProperties.put("spring.deserializer.value.delegate.class", JsonDeserializer.class);
+ if (tracingEnabled) {
+ consumerConfigProperties.put(
+ ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingConsumerInterceptor.class.getName());
+ }
return new DefaultKafkaConsumerFactory<>(consumerConfigProperties);
}
@@ -90,6 +105,9 @@ public class KafkaConfig<T> {
public KafkaTemplate<String, T> legacyEventKafkaTemplate() {
final KafkaTemplate<String, T> kafkaTemplate = new KafkaTemplate<>(legacyEventProducerFactory());
kafkaTemplate.setConsumerFactory(legacyEventConsumerFactory());
+ if (tracingEnabled) {
+ kafkaTemplate.setObservationEnabled(true);
+ }
return kafkaTemplate;
}
@@ -104,6 +122,9 @@ public class KafkaConfig<T> {
new ConcurrentKafkaListenerContainerFactory<>();
containerFactory.setConsumerFactory(legacyEventConsumerFactory());
containerFactory.getContainerProperties().setAuthExceptionRetryInterval(Duration.ofSeconds(10));
+ if (tracingEnabled) {
+ containerFactory.getContainerProperties().setObservationEnabled(true);
+ }
return containerFactory;
}
@@ -116,6 +137,10 @@ public class KafkaConfig<T> {
@Bean
public ProducerFactory<String, CloudEvent> cloudEventProducerFactory() {
final Map<String, Object> producerConfigProperties = kafkaProperties.buildProducerProperties(NO_SSL);
+ if (tracingEnabled) {
+ producerConfigProperties.put(
+ ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingProducerInterceptor.class.getName());
+ }
return new DefaultKafkaProducerFactory<>(producerConfigProperties);
}
@@ -128,6 +153,10 @@ public class KafkaConfig<T> {
@Bean
public ConsumerFactory<String, CloudEvent> cloudEventConsumerFactory() {
final Map<String, Object> consumerConfigProperties = kafkaProperties.buildConsumerProperties(NO_SSL);
+ if (tracingEnabled) {
+ consumerConfigProperties.put(
+ ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingConsumerInterceptor.class.getName());
+ }
return new DefaultKafkaConsumerFactory<>(consumerConfigProperties);
}
@@ -142,6 +171,9 @@ public class KafkaConfig<T> {
final KafkaTemplate<String, CloudEvent> kafkaTemplate =
new KafkaTemplate<>(cloudEventProducerFactory());
kafkaTemplate.setConsumerFactory(cloudEventConsumerFactory());
+ if (tracingEnabled) {
+ kafkaTemplate.setObservationEnabled(true);
+ }
return kafkaTemplate;
}
@@ -157,6 +189,9 @@ public class KafkaConfig<T> {
new ConcurrentKafkaListenerContainerFactory<>();
containerFactory.setConsumerFactory(cloudEventConsumerFactory());
containerFactory.getContainerProperties().setAuthExceptionRetryInterval(Duration.ofSeconds(10));
+ if (tracingEnabled) {
+ containerFactory.getContainerProperties().setObservationEnabled(true);
+ }
return containerFactory;
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDelta.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDelta.java
index 8a4beb956..4e2062fed 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDelta.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDelta.java
@@ -64,12 +64,19 @@ public class CmNotificationSubscriptionDelta {
}
}
- final DmiCmNotificationSubscriptionPredicate predicateDelta =
- new DmiCmNotificationSubscriptionPredicate(targetCmHandleIds, datastoreType, xpaths);
+ populateValidDmiCmNotificationSubscriptionPredicateDelta(targetCmHandleIds, xpaths, datastoreType, delta);
+ }
+ return delta;
+ }
+ private void populateValidDmiCmNotificationSubscriptionPredicateDelta(final Set<String> targetCmHandleIds,
+ final Set<String> xpaths, final DatastoreType datastoreType,
+ final List<DmiCmNotificationSubscriptionPredicate> delta) {
+ if (!(targetCmHandleIds.isEmpty() || xpaths.isEmpty())) {
+ final DmiCmNotificationSubscriptionPredicate predicateDelta =
+ new DmiCmNotificationSubscriptionPredicate(targetCmHandleIds, datastoreType, xpaths);
delta.add(predicateDelta);
}
- return delta;
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandler.java
index b5370bf1e..21c26228b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandler.java
@@ -35,10 +35,10 @@ import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.CmNotificationSubs
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionDetails;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionPredicate;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.service.CmNotificationSubscriptionPersistenceService;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
import org.onap.cps.ncmp.api.impl.operations.DatastoreType;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.Predicate;
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.springframework.stereotype.Component;
@Component
@@ -123,12 +123,12 @@ public class DmiCmNotificationSubscriptionCacheHandler {
*
*/
public void updateDmiCmNotificationSubscriptionStatusPerDmi(final String subscriptionId,
- final String dmiServiceName, final CmNotificationSubscriptionStatus status) {
+ final String dmiServiceName,
+ final CmNotificationSubscriptionStatus status) {
final Map<String, DmiCmNotificationSubscriptionDetails> dmiCmNotificationSubscriptionDetailsPerDmi =
cmNotificationSubscriptionCache.get(subscriptionId);
dmiCmNotificationSubscriptionDetailsPerDmi.get(dmiServiceName).setCmNotificationSubscriptionStatus(status);
cmNotificationSubscriptionCache.put(subscriptionId, dmiCmNotificationSubscriptionDetailsPerDmi);
-
}
/**
@@ -157,6 +157,32 @@ public class DmiCmNotificationSubscriptionCacheHandler {
}
}
+ /**
+ * Remove subscription from database per DMI service name.
+ *
+ * @param subscriptionId String of subscription id
+ * @param dmiServiceName String of dmiServiceName
+ *
+ */
+ public void removeFromDatabasePerDmi(final String subscriptionId, final String dmiServiceName) {
+ final List<DmiCmNotificationSubscriptionPredicate> dmiCmNotificationSubscriptionPredicateList =
+ cmNotificationSubscriptionCache.get(subscriptionId).get(dmiServiceName)
+ .getDmiCmNotificationSubscriptionPredicates();
+ for (final DmiCmNotificationSubscriptionPredicate dmiCmNotificationSubscriptionPredicate:
+ dmiCmNotificationSubscriptionPredicateList) {
+ final DatastoreType datastoreType = dmiCmNotificationSubscriptionPredicate.getDatastoreType();
+ final Set<String> cmHandles = dmiCmNotificationSubscriptionPredicate.getTargetCmHandleIds();
+ final Set<String> xpaths = dmiCmNotificationSubscriptionPredicate.getXpaths();
+
+ for (final String cmHandle: cmHandles) {
+ for (final String xpath: xpaths) {
+ cmNotificationSubscriptionPersistenceService.removeCmNotificationSubscription(datastoreType,
+ cmHandle, xpath, subscriptionId);
+ }
+ }
+ }
+ }
+
private void updateDmiCmNotificationSubscriptionDetailsPerDmi(
final String dmiServiceName,
final DmiCmNotificationSubscriptionPredicate dmiCmNotificationSubscriptionPredicate,
@@ -190,4 +216,4 @@ public class DmiCmNotificationSubscriptionCacheHandler {
return dmiCmNotificationSubscription.getCmNotificationSubscriptionStatus().toString().equals("ACCEPTED")
|| dmiCmNotificationSubscription.getCmNotificationSubscriptionStatus().toString().equals("REJECTED");
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionDmiOutEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionDmiOutEventConsumer.java
index fb89aae3f..051949c5e 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionDmiOutEventConsumer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionDmiOutEventConsumer.java
@@ -20,6 +20,8 @@
package org.onap.cps.ncmp.api.impl.events.cmsubscription.consumer;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_DATA_SUBSCRIPTION_ACCEPTED;
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_DATA_SUBSCRIPTION_REJECTED;
import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent;
import io.cloudevents.CloudEvent;
@@ -27,12 +29,14 @@ import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.CmNotificationSubscriptionEventsHandler;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.CmNotificationSubscriptionMappersHandler;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.DmiCmNotificationSubscriptionCacheHandler;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.CmNotificationSubscriptionStatus;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionDetails;
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.dmi_to_ncmp.CmNotificationSubscriptionDmiOutEvent;
+import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.dmi_to_ncmp.Data;
import org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.ncmp_to_client.CmNotificationSubscriptionNcmpOutEvent;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@@ -46,12 +50,14 @@ public class CmNotificationSubscriptionDmiOutEventConsumer {
private final CmNotificationSubscriptionEventsHandler cmNotificationSubscriptionEventsHandler;
private final CmNotificationSubscriptionMappersHandler cmNotificationSubscriptionMappersHandler;
+ private static final String CM_DATA_SUBSCRIPTION_CORRELATION_ID_SEPARATOR = "#";
+
/**
* Consume the Cm Notification Subscription event from the dmi-plugin.
*
* @param cmNotificationSubscriptionDmiOutEventConsumerRecord the event to be consumed
*/
- @KafkaListener(topics = "${app.ncmp.avc.subscription-response-topic}",
+ @KafkaListener(topics = "${app.ncmp.avc.cm-subscription-dmi-out}",
containerFactory = "cloudEventConcurrentKafkaListenerContainerFactory")
public void consumeCmNotificationSubscriptionDmiOutEvent(
final ConsumerRecord<String, CloudEvent> cmNotificationSubscriptionDmiOutEventConsumerRecord) {
@@ -59,26 +65,33 @@ public class CmNotificationSubscriptionDmiOutEventConsumer {
final CmNotificationSubscriptionDmiOutEvent cmNotificationSubscriptionDmiOutEvent =
toTargetEvent(cloudEvent, CmNotificationSubscriptionDmiOutEvent.class);
final String correlationId = String.valueOf(cloudEvent.getExtension("correlationid"));
- if ("subscriptionCreateResponse".equals(cloudEvent.getType()) && cmNotificationSubscriptionDmiOutEvent != null
- && correlationId != null) {
- handleCmSubscriptionCreate(correlationId, cmNotificationSubscriptionDmiOutEvent);
+ if (cmNotificationSubscriptionDmiOutEvent != null && correlationId != null) {
+ final String eventType = cloudEvent.getType();
+ handleCmSubscriptionDmiOutEvent(correlationId, eventType, cmNotificationSubscriptionDmiOutEvent);
}
}
- private void handleCmSubscriptionCreate(final String correlationId,
- final CmNotificationSubscriptionDmiOutEvent cmNotificationSubscriptionDmiOutEvent) {
- final String subscriptionId = correlationId.split("#")[0];
- final String dmiPluginName = correlationId.split("#")[1];
+ private void handleCmSubscriptionDmiOutEvent(final String correlationId,
+ final String eventType,
+ final CmNotificationSubscriptionDmiOutEvent
+ cmNotificationSubscriptionDmiOutEvent) {
+ final String subscriptionId = correlationId.split(CM_DATA_SUBSCRIPTION_CORRELATION_ID_SEPARATOR)[0];
+ final String dmiPluginName = correlationId.split(CM_DATA_SUBSCRIPTION_CORRELATION_ID_SEPARATOR)[1];
- if ("ACCEPTED".equals(cmNotificationSubscriptionDmiOutEvent.getData().getStatusMessage())) {
+ if (checkStatusCodeAndMessage(CM_DATA_SUBSCRIPTION_ACCEPTED, cmNotificationSubscriptionDmiOutEvent.getData())) {
handleCacheStatusPerDmi(subscriptionId, dmiPluginName, CmNotificationSubscriptionStatus.ACCEPTED);
- dmiCmNotificationSubscriptionCacheHandler.persistIntoDatabasePerDmi(subscriptionId, dmiPluginName);
- handleEventsStatusPerDmi(subscriptionId);
+ if (eventType.equals("subscriptionCreateResponse")) {
+ dmiCmNotificationSubscriptionCacheHandler.persistIntoDatabasePerDmi(subscriptionId, dmiPluginName);
+ }
+ if (eventType.equals("subscriptionDeleteResponse")) {
+ dmiCmNotificationSubscriptionCacheHandler.removeFromDatabasePerDmi(subscriptionId, dmiPluginName);
+ }
+ handleEventsStatusPerDmi(subscriptionId, eventType);
}
- if ("REJECTED".equals(cmNotificationSubscriptionDmiOutEvent.getData().getStatusMessage())) {
+ if (checkStatusCodeAndMessage(CM_DATA_SUBSCRIPTION_REJECTED, cmNotificationSubscriptionDmiOutEvent.getData())) {
handleCacheStatusPerDmi(subscriptionId, dmiPluginName, CmNotificationSubscriptionStatus.REJECTED);
- handleEventsStatusPerDmi(subscriptionId);
+ handleEventsStatusPerDmi(subscriptionId, eventType);
}
log.info("Cm Subscription with id : {} handled by the dmi-plugin : {} has the status : {}", subscriptionId,
@@ -86,18 +99,25 @@ public class CmNotificationSubscriptionDmiOutEventConsumer {
}
private void handleCacheStatusPerDmi(final String subscriptionId, final String dmiPluginName,
- final CmNotificationSubscriptionStatus cmNotificationSubscriptionStatus) {
+ final CmNotificationSubscriptionStatus cmNotificationSubscriptionStatus) {
dmiCmNotificationSubscriptionCacheHandler.updateDmiCmNotificationSubscriptionStatusPerDmi(subscriptionId,
dmiPluginName, cmNotificationSubscriptionStatus);
}
- private void handleEventsStatusPerDmi(final String subscriptionId) {
+ private void handleEventsStatusPerDmi(final String subscriptionId, final String eventType) {
final Map<String, DmiCmNotificationSubscriptionDetails> dmiCmNotificationSubscriptionDetailsPerDmi =
dmiCmNotificationSubscriptionCacheHandler.get(subscriptionId);
final CmNotificationSubscriptionNcmpOutEvent cmNotificationSubscriptionNcmpOutEvent =
cmNotificationSubscriptionMappersHandler.toCmNotificationSubscriptionNcmpOutEvent(subscriptionId,
dmiCmNotificationSubscriptionDetailsPerDmi);
cmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionNcmpOutEvent(subscriptionId,
- "subscriptionCreateResponse", cmNotificationSubscriptionNcmpOutEvent, false);
+ eventType, cmNotificationSubscriptionNcmpOutEvent, false);
+ }
+
+ private boolean checkStatusCodeAndMessage(final NcmpResponseStatus ncmpResponseStatus,
+ final Data cmNotificationSubscriptionDmiOutData) {
+ return ncmpResponseStatus.getCode().equals(cmNotificationSubscriptionDmiOutData.getStatusCode())
+ && ncmpResponseStatus.getMessage()
+ .equals(cmNotificationSubscriptionDmiOutData.getStatusMessage());
}
-}
+} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionNcmpInEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionNcmpInEventConsumer.java
index 70135b307..fb3388c11 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionNcmpInEventConsumer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionNcmpInEventConsumer.java
@@ -23,12 +23,13 @@ package org.onap.cps.ncmp.api.impl.events.cmsubscription.consumer;
import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent;
import io.cloudevents.CloudEvent;
+import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.service.CmNotificationSubscriptionHandlerService;
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.CmNotificationSubscriptionNcmpInEvent;
-import org.springframework.beans.factory.annotation.Value;
+import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.Predicate;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@@ -39,15 +40,12 @@ public class CmNotificationSubscriptionNcmpInEventConsumer {
private final CmNotificationSubscriptionHandlerService cmNotificationSubscriptionHandlerService;
- @Value("${notification.enabled:true}")
- private boolean notificationFeatureEnabled;
-
/**
* Consume the specified event.
*
* @param subscriptionEventConsumerRecord the event to be consumed
*/
- @KafkaListener(topics = "${app.ncmp.avc.subscription-topic}",
+ @KafkaListener(topics = "${app.ncmp.avc.cm-subscription-ncmp-in}",
containerFactory = "cloudEventConcurrentKafkaListenerContainerFactory")
public void consumeSubscriptionEvent(final ConsumerRecord<String, CloudEvent> subscriptionEventConsumerRecord) {
final CloudEvent cloudEvent = subscriptionEventConsumerRecord.value();
@@ -57,10 +55,16 @@ public class CmNotificationSubscriptionNcmpInEventConsumer {
cmNotificationSubscriptionNcmpInEvent.getData().getSubscriptionId());
final String subscriptionId = cmNotificationSubscriptionNcmpInEvent.getData().getSubscriptionId();
+ final List<Predicate> predicates = cmNotificationSubscriptionNcmpInEvent.getData().getPredicates();
if ("subscriptionCreateRequest".equals(cloudEvent.getType())) {
- log.info("Subscription for source {} with subscription id {} ...", cloudEvent.getSource(), subscriptionId);
- cmNotificationSubscriptionHandlerService.processSubscriptionCreateRequest(
- cmNotificationSubscriptionNcmpInEvent);
+ log.info("Subscription create request for source {} with subscription id {} ...",
+ cloudEvent.getSource(), subscriptionId);
+ cmNotificationSubscriptionHandlerService.processSubscriptionCreateRequest(subscriptionId, predicates);
+ }
+ if ("subscriptionDeleteRequest".equals(cloudEvent.getType())) {
+ log.info("Subscription delete request for source {} with subscription id {} ...",
+ cloudEvent.getSource(), subscriptionId);
+ cmNotificationSubscriptionHandlerService.processSubscriptionDeleteRequest(subscriptionId, predicates);
}
}
} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java
index 489401f26..7263891a2 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java
@@ -28,12 +28,12 @@ import java.util.Map;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionPredicate;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
+import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmHandle;
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmNotificationSubscriptionDmiInEvent;
-import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.Cmhandle;
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.Data;
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.Predicate;
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.ScopeFilter;
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
import org.springframework.stereotype.Component;
@Component
@@ -54,7 +54,7 @@ public class CmNotificationSubscriptionDmiInEventMapper {
new CmNotificationSubscriptionDmiInEvent();
final Data cmSubscriptionData = new Data();
cmSubscriptionData.setPredicates(mapToDmiInEventPredicates(dmiCmNotificationSubscriptionPredicates));
- cmSubscriptionData.setCmhandles(mapToCmSubscriptionCmhandleWithPrivateProperties(
+ cmSubscriptionData.setCmHandles(mapToCmSubscriptionCmhandleWithPrivateProperties(
extractUniqueCmHandleIds(dmiCmNotificationSubscriptionPredicates)));
cmNotificationSubscriptionDmiInEvent.setData(cmSubscriptionData);
return cmNotificationSubscriptionDmiInEvent;
@@ -81,12 +81,12 @@ public class CmNotificationSubscriptionDmiInEventMapper {
}
- private List<Cmhandle> mapToCmSubscriptionCmhandleWithPrivateProperties(final Set<String> cmHandleIds) {
+ private List<CmHandle> mapToCmSubscriptionCmhandleWithPrivateProperties(final Set<String> cmHandleIds) {
- final List<Cmhandle> cmSubscriptionCmHandles = new ArrayList<>();
+ final List<CmHandle> cmSubscriptionCmHandles = new ArrayList<>();
inventoryPersistence.getYangModelCmHandles(cmHandleIds).forEach(yangModelCmHandle -> {
- final Cmhandle cmhandle = new Cmhandle();
+ final CmHandle cmhandle = new CmHandle();
final Map<String, String> cmhandleDmiProperties = new LinkedHashMap<>();
yangModelCmHandle.getDmiProperties()
.forEach(dmiProperty -> cmhandleDmiProperties.put(dmiProperty.getName(), dmiProperty.getValue()));
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/producer/CmNotificationSubscriptionDmiInEventProducer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/producer/CmNotificationSubscriptionDmiInEventProducer.java
index 9fbe26848..3273c556c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/producer/CmNotificationSubscriptionDmiInEventProducer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/producer/CmNotificationSubscriptionDmiInEventProducer.java
@@ -25,7 +25,6 @@ import io.cloudevents.core.builder.CloudEventBuilder;
import java.net.URI;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.onap.cps.events.EventsPublisher;
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmNotificationSubscriptionDmiInEvent;
import org.onap.cps.utils.JsonObjectMapper;
@@ -34,7 +33,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
@Component
-@Slf4j
@RequiredArgsConstructor
@ConditionalOnProperty(name = "notification.enabled", havingValue = "true", matchIfMissing = true)
public class CmNotificationSubscriptionDmiInEventProducer {
@@ -42,7 +40,7 @@ public class CmNotificationSubscriptionDmiInEventProducer {
private final EventsPublisher<CloudEvent> eventsPublisher;
private final JsonObjectMapper jsonObjectMapper;
- @Value("${app.ncmp.avc.subscription-forward-topic-prefix}")
+ @Value("${app.ncmp.avc.cm-subscription-dmi-in}")
private String cmNotificationSubscriptionDmiInEventTopic;
/**
@@ -65,9 +63,10 @@ public class CmNotificationSubscriptionDmiInEventProducer {
final String dmiPluginName, final String eventType,
final CmNotificationSubscriptionDmiInEvent cmNotificationSubscriptionDmiInEvent) {
return CloudEventBuilder.v1().withId(UUID.randomUUID().toString()).withType(eventType)
- .withSource(URI.create("NCMP")).withDataSchema(URI.create("org.onap.ncmp.dmi.cm.subscription:1.0.0"))
- .withExtension("correlationid", subscriptionId.concat("#").concat(dmiPluginName))
- .withData(jsonObjectMapper.asJsonBytes(cmNotificationSubscriptionDmiInEvent)).build();
+ .withSource(URI.create("NCMP"))
+ .withDataSchema(URI.create("org.onap.ncmp.dmi.cm.subscription:1.0.0"))
+ .withExtension("correlationid", subscriptionId.concat("#").concat(dmiPluginName))
+ .withData(jsonObjectMapper.asJsonBytes(cmNotificationSubscriptionDmiInEvent)).build();
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/producer/CmNotificationSubscriptionNcmpOutEventProducer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/producer/CmNotificationSubscriptionNcmpOutEventProducer.java
index ac5de07f0..ed7ed2a0b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/producer/CmNotificationSubscriptionNcmpOutEventProducer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/producer/CmNotificationSubscriptionNcmpOutEventProducer.java
@@ -48,7 +48,7 @@ import org.springframework.stereotype.Component;
@ConditionalOnProperty(name = "notification.enabled", havingValue = "true", matchIfMissing = true)
public class CmNotificationSubscriptionNcmpOutEventProducer {
- @Value("${app.ncmp.avc.subscription-outcome-topic}")
+ @Value("${app.ncmp.avc.cm-subscription-ncmp-out}")
private String cmNotificationSubscriptionNcmpOutEventTopic;
@Value("${ncmp.timers.subscription-forwarding.dmi-response-timeout-ms}")
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerService.java
index 536693ee4..1c52ffa79 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerService.java
@@ -20,16 +20,25 @@
package org.onap.cps.ncmp.api.impl.events.cmsubscription.service;
-import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.CmNotificationSubscriptionNcmpInEvent;
+import java.util.List;
+import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.Predicate;
public interface CmNotificationSubscriptionHandlerService {
/**
- * Process cm notification subscription request.
+ * Process cm notification subscription create request.
*
- * @param cmNotificationSubscriptionNcmpInEvent CM Notification Subscription event
+ * @param subscriptionId subscription id
+ * @param predicates subscription predicates
*/
- void processSubscriptionCreateRequest(
- final CmNotificationSubscriptionNcmpInEvent cmNotificationSubscriptionNcmpInEvent);
+ void processSubscriptionCreateRequest(final String subscriptionId, final List<Predicate> predicates);
-}
+ /**
+ * Process cm notification subscription delete request.
+ *
+ * @param subscriptionId subscription id
+ * @param predicates subscription predicates
+ */
+ void processSubscriptionDeleteRequest(final String subscriptionId, final List<Predicate> predicates);
+
+} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImpl.java
index 7872ba0a3..08e3c9552 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImpl.java
@@ -30,9 +30,9 @@ import org.onap.cps.ncmp.api.impl.events.cmsubscription.CmNotificationSubscripti
import org.onap.cps.ncmp.api.impl.events.cmsubscription.CmNotificationSubscriptionEventsHandler;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.CmNotificationSubscriptionMappersHandler;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.DmiCmNotificationSubscriptionCacheHandler;
+import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.CmNotificationSubscriptionStatus;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionDetails;
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionPredicate;
-import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.CmNotificationSubscriptionNcmpInEvent;
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.Predicate;
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmNotificationSubscriptionDmiInEvent;
import org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.ncmp_to_client.CmNotificationSubscriptionNcmpOutEvent;
@@ -49,28 +49,32 @@ public class CmNotificationSubscriptionHandlerServiceImpl implements CmNotificat
private final DmiCmNotificationSubscriptionCacheHandler dmiCmNotificationSubscriptionCacheHandler;
@Override
- public void processSubscriptionCreateRequest(
- final CmNotificationSubscriptionNcmpInEvent cmNotificationSubscriptionNcmpInEvent) {
- final String subscriptionId = cmNotificationSubscriptionNcmpInEvent.getData().getSubscriptionId();
- final List<Predicate> predicates = cmNotificationSubscriptionNcmpInEvent.getData().getPredicates();
-
+ public void processSubscriptionCreateRequest(final String subscriptionId, final List<Predicate> predicates) {
if (cmNotificationSubscriptionPersistenceService.isUniqueSubscriptionId(subscriptionId)) {
dmiCmNotificationSubscriptionCacheHandler.add(subscriptionId, predicates);
- sendSubscriptionCreateRequestToDmi(subscriptionId);
- scheduleCmNotificationSubscriptionNcmpOutEventResponse(subscriptionId);
+ handleCmNotificationSubscriptionDelta(subscriptionId);
+ scheduleCmNotificationSubscriptionNcmpOutEventResponse(subscriptionId,
+ "subscriptionCreateResponse");
} else {
- rejectAndPublishCmNotificationSubscriptionCreateRequest(subscriptionId,
- predicates);
+ rejectAndPublishCmNotificationSubscriptionCreateRequest(subscriptionId, predicates);
}
}
- private void scheduleCmNotificationSubscriptionNcmpOutEventResponse(final String subscriptionId) {
+ @Override
+ public void processSubscriptionDeleteRequest(final String subscriptionId, final List<Predicate> predicates) {
+ dmiCmNotificationSubscriptionCacheHandler.add(subscriptionId, predicates);
+ sendSubscriptionDeleteRequestToDmi(subscriptionId);
+ scheduleCmNotificationSubscriptionNcmpOutEventResponse(subscriptionId, "subscriptionDeleteResponse");
+ }
+
+ private void scheduleCmNotificationSubscriptionNcmpOutEventResponse(final String subscriptionId,
+ final String eventType) {
cmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionNcmpOutEvent(subscriptionId,
- "subscriptionCreateResponse", null, true);
+ eventType, null, true);
}
private void rejectAndPublishCmNotificationSubscriptionCreateRequest(final String subscriptionId,
- final List<Predicate> predicates) {
+ final List<Predicate> predicates) {
final Set<String> subscriptionTargetFilters =
predicates.stream().flatMap(predicate -> predicate.getTargetFilter().stream())
.collect(Collectors.toSet());
@@ -81,18 +85,50 @@ public class CmNotificationSubscriptionHandlerServiceImpl implements CmNotificat
"subscriptionCreateResponse", cmNotificationSubscriptionNcmpOutEvent, false);
}
- private void sendSubscriptionCreateRequestToDmi(final String subscriptionId) {
+ private void handleCmNotificationSubscriptionDelta(final String subscriptionId) {
final Map<String, DmiCmNotificationSubscriptionDetails> dmiCmNotificationSubscriptionDetailsMap =
dmiCmNotificationSubscriptionCacheHandler.get(subscriptionId);
dmiCmNotificationSubscriptionDetailsMap.forEach((dmiPluginName, dmiCmNotificationSubscriptionDetails) -> {
final List<DmiCmNotificationSubscriptionPredicate> dmiCmNotificationSubscriptionPredicates =
cmNotificationSubscriptionDelta.getDelta(
dmiCmNotificationSubscriptionDetails.getDmiCmNotificationSubscriptionPredicates());
+
+ if (dmiCmNotificationSubscriptionPredicates.isEmpty()) {
+ acceptAndPublishCmNotificationSubscriptionNcmpOutEventPerDmi(subscriptionId, dmiPluginName);
+ } else {
+ publishCmNotificationSubscriptionDmiInEventPerDmi(subscriptionId, dmiPluginName,
+ dmiCmNotificationSubscriptionPredicates);
+ }
+ });
+ }
+
+ private void publishCmNotificationSubscriptionDmiInEventPerDmi(final String subscriptionId,
+ final String dmiPluginName,
+ final List<DmiCmNotificationSubscriptionPredicate>
+ dmiCmNotificationSubscriptionPredicates) {
+ final CmNotificationSubscriptionDmiInEvent cmNotificationSubscriptionDmiInEvent =
+ cmNotificationSubscriptionMappersHandler.toCmNotificationSubscriptionDmiInEvent(
+ dmiCmNotificationSubscriptionPredicates);
+ cmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionDmiInEvent(subscriptionId,
+ dmiPluginName, "subscriptionCreateRequest", cmNotificationSubscriptionDmiInEvent);
+ }
+
+ private void acceptAndPublishCmNotificationSubscriptionNcmpOutEventPerDmi(final String subscriptionId,
+ final String dmiPluginName) {
+ dmiCmNotificationSubscriptionCacheHandler.updateDmiCmNotificationSubscriptionStatusPerDmi(subscriptionId,
+ dmiPluginName, CmNotificationSubscriptionStatus.ACCEPTED);
+ dmiCmNotificationSubscriptionCacheHandler.persistIntoDatabasePerDmi(subscriptionId, dmiPluginName);
+ }
+
+ private void sendSubscriptionDeleteRequestToDmi(final String subscriptionId) {
+ final Map<String, DmiCmNotificationSubscriptionDetails> dmiCmNotificationSubscriptionDetailsMap =
+ dmiCmNotificationSubscriptionCacheHandler.get(subscriptionId);
+ dmiCmNotificationSubscriptionDetailsMap.forEach((dmiPluginName, dmiCmNotificationSubscriptionDetails) -> {
final CmNotificationSubscriptionDmiInEvent cmNotificationSubscriptionDmiInEvent =
cmNotificationSubscriptionMappersHandler.toCmNotificationSubscriptionDmiInEvent(
- dmiCmNotificationSubscriptionPredicates);
+ dmiCmNotificationSubscriptionDetails.getDmiCmNotificationSubscriptionPredicates());
cmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionDmiInEvent(subscriptionId,
- dmiPluginName, "subscriptionCreateRequest", cmNotificationSubscriptionDmiInEvent);
+ dmiPluginName, "subscriptionDeleteRequest", cmNotificationSubscriptionDmiInEvent);
});
}
} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImpl.java
index 0adf225fe..a9b1e26f5 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImpl.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.
@@ -20,6 +21,7 @@
package org.onap.cps.ncmp.api.impl.events.cmsubscription.service;
+import static org.onap.cps.spi.FetchDescendantsOption.DIRECT_CHILDREN_ONLY;
import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
import java.io.Serializable;
@@ -45,10 +47,14 @@ public class CmNotificationSubscriptionPersistenceServiceImpl implements CmNotif
private static final String SUBSCRIPTION_ANCHOR_NAME = "cm-data-subscriptions";
private static final String CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_AND_CMHANDLE = """
- /datastores/datastore[@name='%s']/cm-handles/cm-handle[@id='%s']/filters
+ /datastores/datastore[@name='%s']/cm-handles/cm-handle[@id='%s']
""".trim();
+ private static final String CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE =
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_AND_CMHANDLE + "/filters";
+
private static final String CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH =
- CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_AND_CMHANDLE + "/filter[@xpath='%s']";
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE + "/filter[@xpath='%s']";
+
private static final String CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_ID = """
//filter/subscriptionIds[text()='%s']
@@ -106,12 +112,11 @@ public class CmNotificationSubscriptionPersistenceServiceImpl implements CmNotif
final Collection<String> subscriptionIds = getOngoingCmNotificationSubscriptionIds(datastoreType,
cmHandleId, xpath);
if (subscriptionIds.remove(subscriptionId)) {
- if (isOngoingCmNotificationSubscription(datastoreType, cmHandleId, xpath)) {
- saveSubscriptionDetails(datastoreType, cmHandleId, xpath, subscriptionIds);
- log.info("There are subscribers left for the following cps path {} :",
- CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH.formatted(
- datastoreType.getDatastoreName(), cmHandleId, escapeQuotesByDoublingThem(xpath)));
- } else {
+ saveSubscriptionDetails(datastoreType, cmHandleId, xpath, subscriptionIds);
+ log.info("There are subscribers left for the following cps path {} :",
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH.formatted(
+ datastoreType.getDatastoreName(), cmHandleId, escapeQuotesByDoublingThem(xpath)));
+ if (subscriptionIds.isEmpty()) {
log.info("No subscribers left for the following cps path {} :",
CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH.formatted(
datastoreType.getDatastoreName(), cmHandleId, escapeQuotesByDoublingThem(xpath)));
@@ -126,11 +131,25 @@ public class CmNotificationSubscriptionPersistenceServiceImpl implements CmNotif
CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH.formatted(
datastoreType.getDatastoreName(), cmHandleId, escapeQuotesByDoublingThem(xpath)),
OffsetDateTime.now());
+ final Collection<DataNode> existingFiltersForCmHandle =
+ cpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, CM_SUBSCRIPTIONS_ANCHOR_NAME,
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE.formatted(
+ datastoreType.getDatastoreName(), cmHandleId),
+ DIRECT_CHILDREN_ONLY).iterator().next().getChildDataNodes();
+ if (existingFiltersForCmHandle.isEmpty()) {
+ removeCmHandleFromDatastore(datastoreType.getDatastoreName(), cmHandleId);
+ }
+ }
+
+ private void removeCmHandleFromDatastore(final String datastoreName, final String cmHandleId) {
+ cpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, SUBSCRIPTION_ANCHOR_NAME,
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_AND_CMHANDLE.formatted(
+ datastoreName, cmHandleId), OffsetDateTime.now());
}
private boolean isFirstSubscriptionForCmHandle(final DatastoreType datastoreType, final String cmHandleId) {
return cpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, CM_SUBSCRIPTIONS_ANCHOR_NAME,
- CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_AND_CMHANDLE.formatted(
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE.formatted(
datastoreType.getDatastoreName(), cmHandleId),
OMIT_DESCENDANTS).isEmpty();
}
@@ -150,7 +169,7 @@ public class CmNotificationSubscriptionPersistenceServiceImpl implements CmNotif
OffsetDateTime.now(), ContentType.JSON);
} else {
cpsDataService.saveListElements(NCMP_DATASPACE_NAME, CM_SUBSCRIPTIONS_ANCHOR_NAME,
- CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_AND_CMHANDLE.formatted(
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE.formatted(
datastoreType.getDatastoreName(), cmHandleId),
subscriptionDetailsAsJson, OffsetDateTime.now());
}
@@ -161,8 +180,9 @@ public class CmNotificationSubscriptionPersistenceServiceImpl implements CmNotif
final Collection<String> subscriptionIds) {
final String subscriptionDetailsAsJson = getSubscriptionDetailsAsJson(xpath, subscriptionIds);
cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, CM_SUBSCRIPTIONS_ANCHOR_NAME,
- CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_AND_CMHANDLE.formatted(
- datastoreType.getDatastoreName(), cmHandleId), subscriptionDetailsAsJson, OffsetDateTime.now());
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE.formatted(
+ datastoreType.getDatastoreName(), cmHandleId), subscriptionDetailsAsJson,
+ OffsetDateTime.now(), ContentType.JSON);
}
private String getSubscriptionDetailsAsJson(final String xpath, final Collection<String> subscriptionIds) {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java
index 8274772d2..3a4995786 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandler.java
@@ -22,8 +22,8 @@ package org.onap.cps.ncmp.api.impl.events.lcm;
import java.util.Collection;
import java.util.Map;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
/**
* The implementation of it should handle the persisting of composite state and delegate the request to publish the
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java
index 3742719e2..b7e6a7457 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerAsyncHelper.java
@@ -22,11 +22,11 @@ package org.onap.cps.ncmp.api.impl.events.lcm;
import java.util.Collection;
import lombok.RequiredArgsConstructor;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
import org.onap.cps.ncmp.events.lcm.v1.LcmEvent;
import org.onap.cps.ncmp.events.lcm.v1.LcmEventHeader;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java
index 0ed95adff..97e519351 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImpl.java
@@ -20,10 +20,10 @@
package org.onap.cps.ncmp.api.impl.events.lcm;
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.ADVISED;
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED;
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.LOCKED;
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.READY;
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED;
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETED;
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.LOCKED;
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY;
import io.micrometer.core.annotation.Timed;
import java.util.ArrayList;
@@ -37,13 +37,13 @@ import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.impl.inventory.CompositeStateUtils;
+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;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.springframework.stereotype.Service;
@Slf4j
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreator.java
index fa27be158..4231c9967 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreator.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreator.java
@@ -27,7 +27,7 @@ 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.models.NcmpServiceCmHandle;
+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;
@@ -128,4 +128,4 @@ public class LcmEventsCreator {
private Values newValues;
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java
index 19d9ba5c0..7c7a9722c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorHelper.java
@@ -23,7 +23,7 @@ package org.onap.cps.ncmp.api.impl.events.lcm;
import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.CREATE;
import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.DELETE;
import static org.onap.cps.ncmp.api.impl.events.lcm.LcmEventType.UPDATE;
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED;
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETED;
import com.google.common.collect.MapDifference;
import com.google.common.collect.Maps;
@@ -33,7 +33,7 @@ import java.util.Map;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
import org.onap.cps.ncmp.events.lcm.v1.Values;
/**
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/impl/exception/DmiClientRequestException.java
new file mode 100644
index 000000000..ab0fa6893
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/DmiClientRequestException.java
@@ -0,0 +1,54 @@
+/*
+ * ============LICENSE_START=======================================================
+ * 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.
+ * 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.exception;
+
+import lombok.Getter;
+import org.onap.cps.ncmp.api.NcmpResponseStatus;
+
+/**
+ * Http Client Request exception from dmi service.
+ */
+@Getter
+public class DmiClientRequestException extends NcmpException {
+
+ private static final long serialVersionUID = 6659897770659834797L;
+ final NcmpResponseStatus ncmpResponseStatus;
+ final String message;
+ final String responseBodyAsString;
+ final int httpStatusCode;
+
+ /**
+ * Constructor to form exception for dmi service response.
+ *
+ * @param httpStatusCode http response code from the client
+ * @param message response message from the client
+ * @param responseBodyAsString response body from the client
+ * @param ncmpResponseStatus ncmp status message and code
+ */
+ public DmiClientRequestException(final int httpStatusCode, final String message, final String responseBodyAsString,
+ final NcmpResponseStatus ncmpResponseStatus) {
+ super(message, responseBodyAsString);
+ this.httpStatusCode = httpStatusCode;
+ this.message = message;
+ this.responseBodyAsString = responseBodyAsString;
+ this.ncmpResponseStatus = ncmpResponseStatus;
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/HttpClientRequestException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidDmiResourceUrlException.java
index 9d307e5d2..270988b63 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/HttpClientRequestException.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/InvalidDmiResourceUrlException.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * 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.
@@ -22,24 +22,16 @@ package org.onap.cps.ncmp.api.impl.exception;
import lombok.Getter;
-/**
- * Http Client Request exception for passthrough scenarios.
- */
@Getter
-public class HttpClientRequestException extends NcmpException {
+public class InvalidDmiResourceUrlException extends RuntimeException {
+
+ private static final long serialVersionUID = 2928476384584894968L;
- private static final long serialVersionUID = 6659897770659834797L;
+ private static final String INVALID_DMI_URL = "Invalid dmi resource url";
final Integer httpStatus;
- /**
- * Constructor to form exception for passthrough scenarios.
- *
- * @param message message details from NCMP
- * @param details response body from the client available as details
- * @param httpStatus http status code from the client
- */
- public HttpClientRequestException(final String message, final String details, final Integer httpStatus) {
- super(message, details);
+ public InvalidDmiResourceUrlException(final String details, final Integer httpStatus) {
+ super(String.format(INVALID_DMI_URL + ": %s", details));
this.httpStatus = httpStatus;
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperation.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperation.java
index 2e66ac0bf..7baac34b1 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperation.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperation.java
@@ -40,7 +40,7 @@ public class DmiDataOperation {
private String options;
private String resourceIdentifier;
- private final List<CmHandle> cmHandles = new ArrayList<>();
+ private final List<DmiOperationCmHandle> cmHandles = new ArrayList<>();
/**
* Create and initialise a (outgoing) DMI data operation.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
index a9ec1241b..32fc8a5db 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
@@ -21,10 +21,10 @@
package org.onap.cps.ncmp.api.impl.operations;
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING;
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA;
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL;
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING;
import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ;
+import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA;
import io.micrometer.core.annotation.Timed;
import java.util.Collection;
@@ -32,91 +32,86 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
-import lombok.extern.slf4j.Slf4j;
+import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
-import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
-import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
+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.DmiServiceUrlBuilder;
import org.onap.cps.ncmp.api.impl.utils.data.operation.ResourceDataOperationRequestUtils;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
import org.onap.cps.ncmp.api.models.CmResourceAddress;
import org.onap.cps.ncmp.api.models.DataOperationRequest;
+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;
import org.onap.cps.spi.exceptions.CpsException;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponentsBuilder;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
/**
* Operations class for DMI data.
*/
-@Component
-@Slf4j
-public class DmiDataOperations extends DmiOperations {
+@RequiredArgsConstructor
+@Service
+public class DmiDataOperations {
- public DmiDataOperations(final InventoryPersistence inventoryPersistence,
- final JsonObjectMapper jsonObjectMapper,
- final NcmpConfiguration.DmiProperties dmiProperties,
- final DmiRestClient dmiRestClient,
- final DmiServiceUrlBuilder dmiServiceUrlBuilder) {
- super(inventoryPersistence, jsonObjectMapper, dmiProperties, dmiRestClient, dmiServiceUrlBuilder);
- }
+ private final InventoryPersistence inventoryPersistence;
+ private final JsonObjectMapper jsonObjectMapper;
+ private final DmiProperties dmiProperties;
+ private final DmiRestClient dmiRestClient;
/**
- * This method fetches the resource data from operational data store for given cm handle
- * identifier on given resource using dmi client.
+ * This method fetches the resource data from the operational data store for a given CM handle
+ * identifier on the specified resource using the DMI client.
*
- * @param cmResourceAddress target datastore, cm handle and resource identifier
- * @param optionsParamInQuery options query
- * @param topicParamInQuery topic name for (triggering) async responses
- * @param requestId requestId for async responses
- * @param authorization contents of Authorization header, or null if not present
- * @return {@code ResponseEntity} response entity
+ * @param cmResourceAddress Target datastore, CM handle, and resource identifier.
+ * @param options Options query string.
+ * @param topic Topic name for triggering asynchronous responses.
+ * @param requestId Request ID for asynchronous responses.
+ * @param authorization Contents of the Authorization header, or null if not present.
+ * @return {@code Mono<ResponseEntity<Object>>} A reactive type representing the response entity.
*/
@Timed(value = "cps.ncmp.dmi.get",
description = "Time taken to fetch the resource data from operational data store for given cm handle "
+ "identifier on given resource using dmi client")
- public ResponseEntity<Object> getResourceDataFromDmi(final CmResourceAddress cmResourceAddress,
- final String optionsParamInQuery,
- final String topicParamInQuery,
- final String requestId,
- final String authorization) {
+ public Mono<ResponseEntity<Object>> getResourceDataFromDmi(final CmResourceAddress cmResourceAddress,
+ final String options,
+ final String topic,
+ final String requestId,
+ final String authorization) {
final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmResourceAddress.cmHandleId());
final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle);
- final String dmiResourceDataUrl = getDmiRequestUrl(cmResourceAddress.datastoreName(),
- cmResourceAddress.cmHandleId(), cmResourceAddress.resourceIdentifier(), optionsParamInQuery,
- topicParamInQuery, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
- return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ, authorization);
+ final String dmiUrl = getDmiResourceDataUrl(cmResourceAddress.datastoreName(), yangModelCmHandle,
+ cmResourceAddress.resourceIdentifier(), options, topic);
+ return dmiRestClient.asynchronousPostOperationWithJsonData(DATA, dmiUrl, jsonRequestBody, READ, authorization);
}
/**
* This method fetches all the resource data from operational data store for given cm handle
* identifier using dmi client.
+ * Note: this method is only used for DataSync
*
- * @param dataStoreName data store name
* @param cmHandleId network resource identifier
* @param requestId requestId for async responses
* @return {@code ResponseEntity} response entity
*/
- public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName,
- final String cmHandleId,
- final String requestId) {
+ public ResponseEntity<Object> getAllResourceDataFromDmi(final String cmHandleId, final String requestId) {
final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
- final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null,
- yangModelCmHandle);
- final String dmiResourceDataUrl = getDmiRequestUrl(dataStoreName, cmHandleId, "/",
- null, null,
- yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
- return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ, null);
+
+ final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle);
+ final String dmiUrl =
+ getDmiResourceDataUrl(PASSTHROUGH_OPERATIONAL.getDatastoreName(), yangModelCmHandle, "/", null, null);
+ return dmiRestClient.synchronousPostOperationWithJsonData(DATA, dmiUrl, jsonRequestBody, READ, null);
}
/**
@@ -137,13 +132,13 @@ public class DmiDataOperations extends DmiOperations {
= getDistinctCmHandleIdsFromDataOperationRequest(dataOperationRequest);
final Collection<YangModelCmHandle> yangModelCmHandles
- = inventoryPersistence.getYangModelCmHandles(cmHandlesIds);
+ = inventoryPersistence.getYangModelCmHandles(cmHandlesIds);
final Map<String, List<DmiDataOperation>> operationsOutPerDmiServiceName
= ResourceDataOperationRequestUtils.processPerDefinitionInDataOperationsRequest(topicParamInQuery,
requestId, dataOperationRequest, yangModelCmHandles);
- buildDataOperationRequestUrlAndSendToDmiService(topicParamInQuery, requestId, operationsOutPerDmiServiceName,
+ buildDataOperationRequestUrlAndSendToDmiService(requestId, topicParamInQuery, operationsOutPerDmiServiceName,
authorization);
}
@@ -166,14 +161,15 @@ public class DmiDataOperations extends DmiOperations {
final String dataType,
final String authorization) {
final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
- final String jsonRequestBody = getDmiRequestBody(operationType, null, requestData, dataType,
- yangModelCmHandle);
- final String dmiUrl = getDmiRequestUrl(PASSTHROUGH_RUNNING.getDatastoreName(), cmHandleId, resourceId,
- null, null,
- yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
- return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, operationType, authorization);
+
+ final String jsonRequestBody = getDmiRequestBody(operationType, null, requestData, dataType,
+ yangModelCmHandle);
+ final String dmiUrl = getDmiResourceDataUrl(PASSTHROUGH_RUNNING.getDatastoreName(),
+ yangModelCmHandle, resourceId, null, null);
+ return dmiRestClient.synchronousPostOperationWithJsonData(DATA, dmiUrl, jsonRequestBody,
+ operationType, authorization);
}
private YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
@@ -190,30 +186,28 @@ public class DmiDataOperations extends DmiOperations {
.requestId(requestId)
.data(requestData)
.dataType(dataType)
+ .moduleSetTag(yangModelCmHandle.getModuleSetTag())
.build();
dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties());
return jsonObjectMapper.asJsonString(dmiRequestBody);
}
- private String getDmiRequestUrl(final String dataStoreName,
- final String cmHandleId,
- final String resourceId,
- final String optionsParamInQuery,
- final String topicParamInQuery,
- final String dmiServiceName) {
- return dmiServiceUrlBuilder.getDmiDatastoreUrl(
- dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery,
- topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables(dataStoreName, dmiServiceName,
- cmHandleId));
- }
-
- private String getDmiServiceDataOperationRequestUrl(final String dmiServiceName,
- final String topicParamInQuery,
- final String requestId) {
- final MultiValueMap<String, String> dataOperationRequestQueryParams = dmiServiceUrlBuilder
- .getDataOperationRequestQueryParams(topicParamInQuery, requestId);
- return dmiServiceUrlBuilder.getDataOperationRequestUrl(dataOperationRequestQueryParams,
- dmiServiceUrlBuilder.populateDataOperationRequestUriVariables(dmiServiceName));
+ private String getDmiResourceDataUrl(final String datastoreName,
+ final YangModelCmHandle yangModelCmHandle,
+ final String resourceIdentifier,
+ final String optionsParamInQuery,
+ final String topicParamInQuery) {
+ final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA);
+ return DmiServiceUrlBuilder.newInstance()
+ .pathSegment("ch")
+ .variablePathSegment("cmHandleId", yangModelCmHandle.getId())
+ .pathSegment("data")
+ .pathSegment("ds")
+ .variablePathSegment("datastore", datastoreName)
+ .queryParameter("resourceIdentifier", resourceIdentifier)
+ .queryParameter("options", optionsParamInQuery)
+ .queryParameter("topic", topicParamInQuery)
+ .build(dmiServiceName, dmiProperties.getDmiBasePath());
}
private void validateIfCmHandleStateReady(final YangModelCmHandle yangModelCmHandle,
@@ -226,66 +220,78 @@ public class DmiDataOperations extends DmiOperations {
}
private static Set<String> getDistinctCmHandleIdsFromDataOperationRequest(final DataOperationRequest
- dataOperationRequest) {
+ dataOperationRequest) {
return dataOperationRequest.getDataOperationDefinitions().stream()
.flatMap(dataOperationDefinition ->
dataOperationDefinition.getCmHandleIds().stream()).collect(Collectors.toSet());
}
- private void buildDataOperationRequestUrlAndSendToDmiService(final String topicParamInQuery,
- final String requestId,
+ private void buildDataOperationRequestUrlAndSendToDmiService(final String requestId,
+ final String topicParamInQuery,
final Map<String, List<DmiDataOperation>>
- groupsOutPerDmiServiceName,
+ groupsOutPerDmiServiceName,
final String authorization) {
- groupsOutPerDmiServiceName.forEach((dmiServiceName, dmiDataOperationRequestBodies) -> {
- final String dmiDataOperationResourceUrl =
- getDmiServiceDataOperationRequestUrl(dmiServiceName, topicParamInQuery, requestId);
- sendDataOperationRequestToDmiService(dmiDataOperationResourceUrl, dmiDataOperationRequestBodies,
- authorization);
- });
+ Flux.fromIterable(groupsOutPerDmiServiceName.entrySet())
+ .flatMap(dmiDataOperationsByDmiServiceName -> {
+ final String dmiServiceName = dmiDataOperationsByDmiServiceName.getKey();
+ final String dmiUrl = buildDmiServiceUrl(dmiServiceName, requestId, topicParamInQuery);
+ final List<DmiDataOperation> dmiDataOperationRequestBodies
+ = dmiDataOperationsByDmiServiceName.getValue();
+ return sendDataOperationRequestToDmiService(dmiUrl, dmiDataOperationRequestBodies, authorization);
+ })
+ .subscribe();
}
- private void sendDataOperationRequestToDmiService(final String dataOperationResourceUrl,
- final List<DmiDataOperation> dmiDataOperationRequestBodies,
- final String authorization) {
+ private String buildDmiServiceUrl(final String dmiServiceName, final String requestId,
+ final String topicParamInQuery) {
+ return DmiServiceUrlBuilder.newInstance()
+ .pathSegment("data")
+ .queryParameter("requestId", requestId)
+ .queryParameter("topic", topicParamInQuery)
+ .build(dmiServiceName, dmiProperties.getDmiBasePath());
+ }
+
+ private Mono<Void> sendDataOperationRequestToDmiService(final String dmiUrl,
+ final List<DmiDataOperation> dmiDataOperationRequestBodies,
+ final String authorization) {
+ final String dmiDataOperationRequestAsJsonString
+ = createDmiDataOperationRequestAsJsonString(dmiDataOperationRequestBodies);
+ return dmiRestClient.asynchronousPostOperationWithJsonData(DATA, dmiUrl, dmiDataOperationRequestAsJsonString,
+ READ, authorization)
+ .then()
+ .onErrorResume(DmiClientRequestException.class, dmiClientRequestException -> {
+ handleTaskCompletionException(dmiClientRequestException, dmiUrl, dmiDataOperationRequestBodies);
+ return Mono.empty();
+ });
+ }
+
+ private String createDmiDataOperationRequestAsJsonString(
+ final List<DmiDataOperation> dmiDataOperationRequestBodies) {
final DmiDataOperationRequest dmiDataOperationRequest = DmiDataOperationRequest.builder()
- .operations(dmiDataOperationRequestBodies).build();
- final String dmiDataOperationRequestAsJsonString =
- jsonObjectMapper.asJsonString(dmiDataOperationRequest);
- try {
- dmiRestClient.postOperationWithJsonData(dataOperationResourceUrl, dmiDataOperationRequestAsJsonString, READ,
- authorization);
- } catch (final Exception exception) {
- handleTaskCompletionException(exception, dataOperationResourceUrl, dmiDataOperationRequestBodies);
- }
+ .operations(dmiDataOperationRequestBodies)
+ .build();
+ return jsonObjectMapper.asJsonString(dmiDataOperationRequest);
}
- private void handleTaskCompletionException(final Throwable throwable,
+ private void handleTaskCompletionException(final DmiClientRequestException dmiClientRequestException,
final String dataOperationResourceUrl,
final List<DmiDataOperation> dmiDataOperationRequestBodies) {
- if (throwable != null) {
- final MultiValueMap<String, String> dataOperationResourceUrlParameters =
- UriComponentsBuilder.fromUriString(dataOperationResourceUrl).build().getQueryParams();
- final String topicName = dataOperationResourceUrlParameters.get("topic").get(0);
- final String requestId = dataOperationResourceUrlParameters.get("requestId").get(0);
+ final MultiValueMap<String, String> dataOperationResourceUrlParameters =
+ UriComponentsBuilder.fromUriString(dataOperationResourceUrl).build().getQueryParams();
+ final String topicName = dataOperationResourceUrlParameters.get("topic").get(0);
+ final String requestId = dataOperationResourceUrlParameters.get("requestId").get(0);
- final MultiValueMap<DmiDataOperation, Map<NcmpResponseStatus, List<String>>>
- cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>();
+ final MultiValueMap<DmiDataOperation, Map<NcmpResponseStatus, List<String>>>
+ cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>();
- dmiDataOperationRequestBodies.forEach(dmiDataOperationRequestBody -> {
- final List<String> cmHandleIds = dmiDataOperationRequestBody.getCmHandles().stream()
- .map(CmHandle::getId).toList();
- if (throwable.getCause() instanceof HttpClientRequestException) {
- cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
- Map.of(UNABLE_TO_READ_RESOURCE_DATA, cmHandleIds));
- } else {
- cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
- Map.of(DMI_SERVICE_NOT_RESPONDING, cmHandleIds));
- }
- });
- ResourceDataOperationRequestUtils.publishErrorMessageToClientTopic(topicName, requestId,
- cmHandleIdsPerResponseCodesPerOperation);
- }
+ dmiDataOperationRequestBodies.forEach(dmiDataOperationRequestBody -> {
+ final List<String> cmHandleIds = dmiDataOperationRequestBody.getCmHandles().stream()
+ .map(DmiOperationCmHandle::getId).toList();
+ cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperationRequestBody,
+ Map.of(dmiClientRequestException.getNcmpResponseStatus(), cmHandleIds));
+ });
+ ResourceDataOperationRequestUtils.publishErrorMessageToClientTopic(topicName, requestId,
+ cmHandleIdsPerResponseCodesPerOperation);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
index 798f6de81..f1fdbea7f 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
@@ -21,6 +21,7 @@
package org.onap.cps.ncmp.api.impl.operations;
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ;
import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.MODEL;
import com.google.gson.JsonArray;
@@ -33,34 +34,27 @@ import java.util.Collections;
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.NcmpConfiguration;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
+import org.onap.cps.ncmp.api.impl.config.DmiProperties;
import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.onap.cps.ncmp.api.models.YangResource;
+import org.onap.cps.ncmp.api.inventory.models.YangResource;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.spi.model.ModuleReference;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
/**
* Operations class for DMI Model.
*/
-@Component
-public class DmiModelOperations extends DmiOperations {
+@RequiredArgsConstructor
+@Service
+public class DmiModelOperations {
- /**
- * Constructor for {@code DmiOperations}. This method also manipulates url properties.
- *
- * @param dmiRestClient {@code DmiRestClient}
- */
- public DmiModelOperations(final InventoryPersistence inventoryPersistence,
- final JsonObjectMapper jsonObjectMapper,
- final NcmpConfiguration.DmiProperties dmiProperties,
- final DmiRestClient dmiRestClient, final DmiServiceUrlBuilder dmiServiceUrlBuilder) {
- super(inventoryPersistence, jsonObjectMapper, dmiProperties, dmiRestClient, dmiServiceUrlBuilder);
- }
+ private final JsonObjectMapper jsonObjectMapper;
+ private final DmiProperties dmiProperties;
+ private final DmiRestClient dmiRestClient;
/**
* Retrieves module references.
@@ -113,9 +107,12 @@ public class DmiModelOperations extends DmiOperations {
final String jsonRequestBody,
final String cmHandle,
final String resourceName) {
- final String dmiResourceDataUrl = getDmiResourceUrl(dmiServiceName, cmHandle, resourceName);
- return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody,
- OperationType.READ, null);
+ final String dmiUrl = DmiServiceUrlBuilder.newInstance()
+ .pathSegment("ch")
+ .variablePathSegment("cmHandleId", cmHandle)
+ .variablePathSegment("resourceName", resourceName)
+ .build(dmiServiceName, dmiProperties.getDmiBasePath());
+ return dmiRestClient.synchronousPostOperationWithJsonData(MODEL, dmiUrl, jsonRequestBody, READ, null);
}
private static String getRequestBodyToFetchYangResources(final Collection<ModuleReference> newModuleReferences,
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/CmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperationCmHandle.java
index 618da7454..1bf2b77dc 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/CmHandle.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperationCmHandle.java
@@ -29,14 +29,21 @@ import lombok.Getter;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Getter
@Builder
-public class CmHandle {
+public class DmiOperationCmHandle {
private String id;
@JsonProperty("cmHandleProperties")
private Map<String, String> dmiProperties;
+ private String moduleSetTag;
- public static CmHandle buildCmHandleWithProperties(final String cmHandleId,
- final Map<String, String> dmiProperties) {
- return CmHandle.builder().id(cmHandleId).dmiProperties(dmiProperties).build();
+ /**
+ * Builds Dmi Operation Cm Handle object with all its associated properties.
+ */
+ public static DmiOperationCmHandle buildDmiOperationCmHandle(final String cmHandleId,
+ final Map<String, String> dmiProperties,
+ final String moduleSetTag) {
+ return DmiOperationCmHandle.builder().id(cmHandleId)
+ .dmiProperties(dmiProperties).moduleSetTag(moduleSetTag)
+ .build();
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java
deleted file mode 100644
index c8d73eac6..000000000
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation
- * Modifications Copyright (C) 2022 Bell Canada
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.api.impl.operations;
-
-import lombok.RequiredArgsConstructor;
-import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
-import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
-import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder;
-import org.onap.cps.utils.JsonObjectMapper;
-import org.springframework.stereotype.Service;
-
-@RequiredArgsConstructor
-@Service
-public class DmiOperations {
-
- protected final InventoryPersistence inventoryPersistence;
- protected final JsonObjectMapper jsonObjectMapper;
- protected final NcmpConfiguration.DmiProperties dmiProperties;
- protected final DmiRestClient dmiRestClient;
- protected final DmiServiceUrlBuilder dmiServiceUrlBuilder;
-
- String getDmiResourceUrl(final String dmiServiceName, final String cmHandle, final String resourceName) {
- return dmiServiceUrlBuilder.getResourceDataBasePathUriBuilder()
- .pathSegment("{resourceName}")
- .buildAndExpand(dmiServiceName, dmiProperties.getDmiBasePath(), cmHandle, resourceName).toUriString();
- }
-
-
-}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java
index f1032f818..f10b4f920 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java
@@ -28,7 +28,7 @@ import java.util.List;
import java.util.Map;
import lombok.Builder;
import lombok.Getter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
@JsonInclude(JsonInclude.Include.NON_NULL)
@Getter
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java
index fa00d1a15..e863228ed 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java
@@ -21,9 +21,7 @@
package org.onap.cps.ncmp.api.impl.operations;
import com.fasterxml.jackson.annotation.JsonValue;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.Locale;
import lombok.Getter;
import org.onap.cps.ncmp.api.impl.exception.InvalidOperationException;
@@ -48,13 +46,6 @@ public enum OperationType {
return String.valueOf(operationName);
}
- private static final Map<String, OperationType> operationNameToOperationEnum = new HashMap<>();
-
- static {
- Arrays.stream(OperationType.values()).forEach(
- operationType -> operationNameToOperationEnum.put(operationType.getOperationName(), operationType));
- }
-
/**
* From operation name get operation enum type.
*
@@ -62,10 +53,10 @@ public enum OperationType {
* @return the operation enum type
*/
public static OperationType fromOperationName(final String operationName) {
- final OperationType operationType = operationNameToOperationEnum.get(operationName);
- if (null == operationType) {
+ try {
+ return OperationType.valueOf(operationName.toUpperCase(Locale.ENGLISH));
+ } catch (final IllegalArgumentException e) {
throw new InvalidOperationException(operationName + " is an invalid operation name");
}
- return operationType;
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManager.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManager.java
index 9d65a66d8..d01acb8a3 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManager.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManager.java
@@ -26,9 +26,9 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig;
import org.onap.cps.ncmp.api.impl.events.avc.ncmptoclient.AvcEventPublisher;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDog.java
index d6d6fd6bc..c5098936c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDog.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDog.java
@@ -24,11 +24,11 @@ import java.util.Collection;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig;
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager;
+import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@@ -39,7 +39,7 @@ import org.springframework.stereotype.Service;
public class DmiPluginWatchDog {
private final DmiRestClient dmiRestClient;
- private final NetworkCmProxyDataService networkCmProxyDataService;
+ private final CmHandleQueryService cmHandleQueryService;
private final TrustLevelManager trustLevelManager;
@Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN)
@@ -68,7 +68,7 @@ public class DmiPluginWatchDog {
log.debug("The Dmi Plugin: {} has already the same trust level: {}", dmiServiceName, newDmiTrustLevel);
} else {
final Collection<String> cmHandleIds =
- networkCmProxyDataService.getAllCmHandleIdsByDmiPluginIdentifier(dmiServiceName);
+ cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiServiceName);
trustLevelManager.handleUpdateOfDmiTrustLevel(dmiServiceName, cmHandleIds, newDmiTrustLevel);
}
});
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java
index 60f39fcea..7ddde643a 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java
@@ -27,9 +27,9 @@ import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.springframework.stereotype.Service;
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/api/impl/utils/DmiServiceNameOrganizer.java
index 26e94866a..533e15b91 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/api/impl/utils/DmiServiceNameOrganizer.java
@@ -28,7 +28,7 @@ import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DmiServiceNameOrganizer {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java
index 04acaa5e9..aeeeb6430 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java
@@ -21,166 +21,91 @@
package org.onap.cps.ncmp.api.impl.utils;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
-import lombok.RequiredArgsConstructor;
+import lombok.NoArgsConstructor;
import org.apache.logging.log4j.util.Strings;
-import org.apache.logging.log4j.util.TriConsumer;
-import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
-import org.onap.cps.spi.utils.CpsValidator;
-import org.springframework.stereotype.Component;
-import org.springframework.util.LinkedMultiValueMap;
-import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponentsBuilder;
-@Component
-@RequiredArgsConstructor
+@NoArgsConstructor
public class DmiServiceUrlBuilder {
- private final NcmpConfiguration.DmiProperties dmiProperties;
- private final CpsValidator cpsValidator;
+ private static final String FIXED_PATH_SEGMENT = null;
- /**
- * This method creates the dmi service url.
- *
- * @param queryParams query param map as key,value pair
- * @param uriVariables uri param map as key (placeholder),value pair
- * @return {@code String} dmi service url as string
- */
- public String getDmiDatastoreUrl(final MultiValueMap<String, String> queryParams,
- final Map<String, Object> uriVariables) {
- return getUriComponentsBuilder(getResourceDataBasePathUriBuilder(), queryParams, uriVariables)
- .buildAndExpand().toUriString();
- }
+ final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance();
+ final Map<String, Object> pathSegments = new LinkedHashMap<>();
- /**
- * This method builds data operation request url.
- *
- * @param dataoperationRequestQueryParams query param map as key, value pair
- * @param dataoperationRequestUriVariables uri param map as key (placeholder), value pair
- * @return {@code String} data operation request url as string
- */
- public String getDataOperationRequestUrl(final MultiValueMap<String, String> dataoperationRequestQueryParams,
- final Map<String, Object> dataoperationRequestUriVariables) {
- return getDataOperationResourceDataBasePathUriBuilder()
- .queryParams(dataoperationRequestQueryParams)
- .uriVariables(dataoperationRequestUriVariables)
- .buildAndExpand().toUriString();
+ public static DmiServiceUrlBuilder newInstance() {
+ return new DmiServiceUrlBuilder();
}
/**
- * This method creates the dmi service url builder object with path variables.
+ * Add a fixed pathSegment to the URI.
*
- * @return {@code UriComponentsBuilder} dmi service url builder object
+ * @param pathSegment the path segment
+ * @return this builder
*/
- public UriComponentsBuilder getResourceDataBasePathUriBuilder() {
- return UriComponentsBuilder.newInstance()
- .path("{dmiServiceName}")
- .pathSegment("{dmiBasePath}")
- .pathSegment("v1")
- .pathSegment("ch")
- .pathSegment("{cmHandleId}");
+ public DmiServiceUrlBuilder pathSegment(final String pathSegment) {
+ pathSegments.put(pathSegment, FIXED_PATH_SEGMENT);
+ return this;
}
/**
- * This method creates the dmi service url builder object with path variables for data operation request.
+ * Add a variable pathSegment to the URI.
+ * Do NOT add { } braces. the builder will take care of that
*
- * @return {@code UriComponentsBuilder} dmi service url builder object
+ * @param pathSegment the name of the variable path segment (with { and }
+ * @param value the value to be insert in teh URI for the given variable path segment
+ * @return this builder
*/
- public UriComponentsBuilder getDataOperationResourceDataBasePathUriBuilder() {
- return UriComponentsBuilder.newInstance()
- .path("{dmiServiceName}")
- .pathSegment("{dmiBasePath}")
- .pathSegment("v1")
- .pathSegment("data");
+ public DmiServiceUrlBuilder variablePathSegment(final String pathSegment, final Object value) {
+ pathSegments.put(pathSegment, value);
+ return this;
}
/**
- * This method populates uri variables.
+ * Add a query parameter to the URI.
+ * Do NOT encode as the builder wil take care of encoding
*
- * @param dataStoreName data store name
- * @param dmiServiceName dmi service name
- * @param cmHandleId cm handle id for dmi registration
- * @return {@code String} dmi service url as string
+ * @param name the name of the variable
+ * @param value the value of the variable (only Strings are supported).
+ *
+ * @return this builder
*/
- public Map<String, Object> populateUriVariables(final String dataStoreName,
- final String dmiServiceName,
- final String cmHandleId) {
- cpsValidator.validateNameCharacters(cmHandleId);
- final Map<String, Object> uriVariables = new HashMap<>();
- final String dmiBasePath = dmiProperties.getDmiBasePath();
- uriVariables.put("dmiServiceName", dmiServiceName);
- uriVariables.put("dmiBasePath", dmiBasePath);
- uriVariables.put("cmHandleId", cmHandleId);
- uriVariables.put("dataStore", dataStoreName);
- return uriVariables;
+ public DmiServiceUrlBuilder queryParameter(final String name, final String value) {
+ if (Strings.isNotBlank(value)) {
+ uriComponentsBuilder.queryParam(name, value);
+ }
+ return this;
}
/**
- * This method populates uri variables for data operation request.
+ * Build the URI as a correctly percentage-encoded String.
+ *
+ * @param dmiServiceName the name of the dmi service
+ * @param dmiBasePath the base path of the dmi service
*
- * @param dmiServiceName dmi service name
- * @return {@code Map<String, Object>} uri variables as map
+ * @return URI as a string
*/
- public Map<String, Object> populateDataOperationRequestUriVariables(final String dmiServiceName) {
+ public String build(final String dmiServiceName, final String dmiBasePath) {
+ uriComponentsBuilder
+ .path("{dmiServiceName}")
+ .pathSegment("{dmiBasePath}")
+ .pathSegment("v1");
+
final Map<String, Object> uriVariables = new HashMap<>();
- final String dmiBasePath = dmiProperties.getDmiBasePath();
uriVariables.put("dmiServiceName", dmiServiceName);
uriVariables.put("dmiBasePath", dmiBasePath);
- return uriVariables;
- }
-
- /**
- * This method is used to populate map from query params.
- *
- * @param resourceId unique id of response for valid topic
- * @param optionsParamInQuery options into url param
- * @param topicParamInQuery topic into url param
- * @return all valid query params as map
- */
- public MultiValueMap<String, String> populateQueryParams(final String resourceId,
- final String optionsParamInQuery,
- final String topicParamInQuery) {
- final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
- getQueryParamConsumer().accept("resourceIdentifier",
- resourceId, queryParams);
- getQueryParamConsumer().accept("options", optionsParamInQuery, queryParams);
- if (Strings.isNotEmpty(topicParamInQuery)) {
- getQueryParamConsumer().accept("topic", topicParamInQuery, queryParams);
- }
- return queryParams;
- }
- /**
- * This method is used to populate map from query params for data operation request.
- *
- * @param topicParamInQuery topic into url param
- * @param requestId unique id of response for valid topic
- * @return all valid query params as map
- */
- public MultiValueMap<String, String> getDataOperationRequestQueryParams(final String topicParamInQuery,
- final String requestId) {
- final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
- getQueryParamConsumer().accept("topic", topicParamInQuery, queryParams);
- getQueryParamConsumer().accept("requestId", requestId, queryParams);
- return queryParams;
- }
-
- private TriConsumer<String, String, MultiValueMap<String, String>> getQueryParamConsumer() {
- return (paramName, paramValue, paramMap) -> {
- if (Strings.isNotEmpty(paramValue)) {
- paramMap.add(paramName, paramValue);
+ pathSegments.forEach((pathSegment, variablePathValue) -> {
+ if (variablePathValue == FIXED_PATH_SEGMENT) {
+ uriComponentsBuilder.pathSegment(pathSegment);
+ } else {
+ uriComponentsBuilder.pathSegment("{" + pathSegment + "}");
+ uriVariables.put(pathSegment, variablePathValue);
}
- };
+ });
+ return uriComponentsBuilder.buildAndExpand(uriVariables).encode().toUriString();
}
- private UriComponentsBuilder getUriComponentsBuilder(final UriComponentsBuilder uriComponentsBuilder,
- final MultiValueMap<String, String> queryParams,
- final Map<String, Object> uriVariables) {
- return uriComponentsBuilder
- .pathSegment("data")
- .pathSegment("ds")
- .pathSegment("{dataStore}")
- .queryParams(queryParams)
- .uriVariables(uriVariables);
- }
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java
index 4b016b37d..bb0c9a315 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtils.java
@@ -31,26 +31,25 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.events.EventsPublisher;
import org.onap.cps.ncmp.api.NcmpResponseStatus;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
-import org.onap.cps.ncmp.api.impl.operations.CmHandle;
import org.onap.cps.ncmp.api.impl.operations.DmiDataOperation;
+import org.onap.cps.ncmp.api.impl.operations.DmiOperationCmHandle;
import org.onap.cps.ncmp.api.impl.utils.DmiServiceNameOrganizer;
import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
import org.onap.cps.ncmp.api.models.DataOperationDefinition;
import org.onap.cps.ncmp.api.models.DataOperationRequest;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
-@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
+@Slf4j
public class ResourceDataOperationRequestUtils {
private static final String UNKNOWN_SERVICE_NAME = null;
@@ -81,6 +80,8 @@ public class ResourceDataOperationRequestUtils {
final Map<String, String> dmiServiceNamesPerCmHandleId =
getDmiServiceNamesPerCmHandleId(dmiPropertiesPerCmHandleIdPerServiceName);
+ final Map<String, String> moduleSetTagPerCmHandle = getModuleSetTagPerCmHandleId(yangModelCmHandles);
+
for (final DataOperationDefinition dataOperationDefinitionIn :
dataOperationRequestIn.getDataOperationDefinitions()) {
final List<String> nonExistingCmHandleIds = new ArrayList<>();
@@ -97,9 +98,10 @@ public class ResourceDataOperationRequestUtils {
} else {
final DmiDataOperation dmiBatchOperationOut = getOrAddDmiBatchOperation(dmiServiceName,
dataOperationDefinitionIn, dmiDataOperationsOutPerDmiServiceName);
- final CmHandle cmHandle = CmHandle.buildCmHandleWithProperties(cmHandleId,
- cmHandleIdProperties);
- dmiBatchOperationOut.getCmHandles().add(cmHandle);
+ final DmiOperationCmHandle dmiOperationCmHandle = DmiOperationCmHandle
+ .buildDmiOperationCmHandle(cmHandleId, cmHandleIdProperties,
+ moduleSetTagPerCmHandle.get(cmHandleId));
+ dmiBatchOperationOut.getCmHandles().add(dmiOperationCmHandle);
}
}
}
@@ -114,56 +116,12 @@ public class ResourceDataOperationRequestUtils {
return dmiDataOperationsOutPerDmiServiceName;
}
- /**
- * Handles the async task completion for an entire data, publishing errors to client topic on task failure.
- *
- * @param topicParamInQuery client given topic
- * @param requestId unique identifier per request
- * @param dataOperationRequest incoming data operation request details
- * @param throwable error cause, or null if task completed with no exception
- */
- public static void handleAsyncTaskCompletionForDataOperationsRequest(
- final String topicParamInQuery,
- final String requestId,
- final DataOperationRequest dataOperationRequest,
- final Throwable throwable) {
- if (throwable == null) {
- log.info("Data operations request {} completed.", requestId);
- } else if (throwable instanceof TimeoutException) {
- log.error("Data operations request {} timed out.", requestId);
- ResourceDataOperationRequestUtils.publishErrorMessageToClientTopicForEntireOperation(topicParamInQuery,
- requestId, dataOperationRequest, NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING);
- } else {
- log.error("Data operations request {} failed.", requestId, throwable);
- ResourceDataOperationRequestUtils.publishErrorMessageToClientTopicForEntireOperation(topicParamInQuery,
- requestId, dataOperationRequest, NcmpResponseStatus.UNKNOWN_ERROR);
- }
- }
-
- /**
- * Creates data operation cloud event for when the entire data operation fails and publishes it to client topic.
- *
- * @param topicParamInQuery client given topic
- * @param requestId unique identifier per request
- * @param dataOperationRequestIn incoming data operation request details
- * @param ncmpResponseStatus response code to be sent for all cm handle ids in all operations
- */
- private static void publishErrorMessageToClientTopicForEntireOperation(
- final String topicParamInQuery,
- final String requestId,
- final DataOperationRequest dataOperationRequestIn,
- final NcmpResponseStatus ncmpResponseStatus) {
-
- final MultiValueMap<DmiDataOperation, Map<NcmpResponseStatus, List<String>>>
- cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>();
-
- for (final DataOperationDefinition dataOperationDefinitionIn :
- dataOperationRequestIn.getDataOperationDefinitions()) {
- cmHandleIdsPerResponseCodesPerOperation.add(
- DmiDataOperation.buildDmiDataOperationRequestBodyWithoutCmHandles(dataOperationDefinitionIn),
- Map.of(ncmpResponseStatus, dataOperationDefinitionIn.getCmHandleIds()));
- }
- publishErrorMessageToClientTopic(topicParamInQuery, requestId, cmHandleIdsPerResponseCodesPerOperation);
+ private static Map<String, String> getModuleSetTagPerCmHandleId(
+ final Collection<YangModelCmHandle> yangModelCmHandles) {
+ final Map<String, String> moduleSetTagPerCmHandle = new HashMap<>(yangModelCmHandles.size());
+ yangModelCmHandles.forEach(yangModelCmHandle ->
+ moduleSetTagPerCmHandle.put(yangModelCmHandle.getId(), yangModelCmHandle.getModuleSetTag()));
+ return moduleSetTagPerCmHandle;
}
/**
@@ -182,6 +140,8 @@ public class ResourceDataOperationRequestUtils {
final CloudEvent dataOperationCloudEvent = DataOperationEventCreator.createDataOperationEvent(clientTopic,
requestId, cmHandleIdsPerResponseCodesPerOperation);
final EventsPublisher<CloudEvent> eventsPublisher = CpsApplicationContext.getCpsBean(EventsPublisher.class);
+ log.warn("publishing error message to client topic: {} ,requestId: {}, data operation cloud event id: {}",
+ clientTopic, requestId, dataOperationCloudEvent.getId());
eventsPublisher.publishCloudEvent(clientTopic, requestId, dataOperationCloudEvent);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java
new file mode 100644
index 000000000..0ff59c131
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java
@@ -0,0 +1,208 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 highstreet technologies GmbH
+ * Modifications Copyright (C) 2021-2024 Nordix Foundation
+ * Modifications Copyright (C) 2021 Pantheon.tech
+ * Modifications Copyright (C) 2021-2022 Bell Canada
+ * Modifications Copyright (C) 2023 TechMahindra Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.inventory;
+
+import static org.onap.cps.ncmp.impl.inventory.CmHandleQueryParametersValidator.validateCmHandleQueryParameters;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryApiParameters;
+import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration;
+import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistrationResponse;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService;
+import org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationService;
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
+import org.onap.cps.ncmp.impl.inventory.ParameterizedCmHandleQueryService;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions;
+import org.onap.cps.ncmp.impl.inventory.models.InventoryQueryConditions;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
+import org.onap.cps.spi.model.ModuleDefinition;
+import org.onap.cps.spi.model.ModuleReference;
+import org.onap.cps.utils.JsonObjectMapper;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class NetworkCmProxyInventoryFacade {
+
+ private final CmHandleRegistrationService cmHandleRegistrationService;
+ private final CmHandleQueryService cmHandleQueryService;
+ private final ParameterizedCmHandleQueryService parameterizedCmHandleQueryService;
+ private final InventoryPersistence inventoryPersistence;
+ private final JsonObjectMapper jsonObjectMapper;
+
+ /**
+ * Registration of Created, Removed, Updated or Upgraded CM Handles.
+ *
+ * @param dmiPluginRegistration Dmi Plugin Registration details
+ * @return dmiPluginRegistrationResponse
+ */
+
+ public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(
+ final DmiPluginRegistration dmiPluginRegistration) {
+ return cmHandleRegistrationService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration);
+ }
+
+ /**
+ * Get all cm handle IDs by DMI plugin identifier.
+ *
+ * @param dmiPluginIdentifier DMI plugin identifier
+ * @return collection of cm handle IDs
+ */
+ public Collection<String> getAllCmHandleIdsByDmiPluginIdentifier(final String dmiPluginIdentifier) {
+ return cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifier);
+ }
+
+ /**
+ * Get all cm handle IDs by various properties.
+ *
+ * @param cmHandleQueryServiceParameters cm handle query parameters
+ * @return collection of cm handle IDs
+ */
+ public Collection<String> executeParameterizedCmHandleIdSearch(
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+ validateCmHandleQueryParameters(cmHandleQueryServiceParameters, InventoryQueryConditions.ALL_CONDITION_NAMES);
+ return parameterizedCmHandleQueryService.queryCmHandleIdsForInventory(cmHandleQueryServiceParameters);
+ }
+
+
+ /**
+ * Retrieve module references for the given cm handle.
+ *
+ * @param cmHandleId cm handle identifier
+ * @return a collection of modules names and revisions
+ */
+ public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleId) {
+ return inventoryPersistence.getYangResourcesModuleReferences(cmHandleId);
+ }
+
+ /**
+ * Retrieve module definitions for the given cm handle.
+ *
+ * @param cmHandleId cm handle identifier
+ * @return a collection of module definition (moduleName, revision and yang resource content)
+ */
+ public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleId(final String cmHandleId) {
+ return inventoryPersistence.getModuleDefinitionsByCmHandleId(cmHandleId);
+ }
+
+ /**
+ * Get module definitions for the given parameters.
+ *
+ * @param cmHandleId cm-handle identifier
+ * @param moduleName module name
+ * @param moduleRevision the revision of the module
+ * @return list of module definitions (module name, revision, yang resource content)
+ */
+ public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleAndModule(final String cmHandleId,
+ final String moduleName,
+ final String moduleRevision) {
+ return inventoryPersistence.getModuleDefinitionsByCmHandleAndModule(cmHandleId, moduleName, moduleRevision);
+ }
+
+ /**
+ * Retrieve cm handles with details for the given query parameters.
+ *
+ * @param cmHandleQueryApiParameters cm handle query parameters
+ * @return cm handles with details
+ */
+ public Collection<NcmpServiceCmHandle> executeCmHandleSearch(
+ final CmHandleQueryApiParameters cmHandleQueryApiParameters) {
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType(
+ cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class);
+ validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES);
+ return parameterizedCmHandleQueryService.queryCmHandles(cmHandleQueryServiceParameters);
+ }
+
+ /**
+ * Retrieve cm handle ids for the given query parameters.
+ *
+ * @param cmHandleQueryApiParameters cm handle query parameters
+ * @return cm handle ids
+ */
+ public Collection<String> executeCmHandleIdSearch(final CmHandleQueryApiParameters cmHandleQueryApiParameters) {
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType(
+ cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class);
+ validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES);
+ return parameterizedCmHandleQueryService.queryCmHandleIds(cmHandleQueryServiceParameters);
+ }
+
+ /**
+ * Set the data sync enabled flag, along with the data sync state
+ * based on the data sync enabled boolean for the cm handle id provided.
+ *
+ * @param cmHandleId cm handle id
+ * @param dataSyncEnabledTargetValue data sync enabled flag
+ */
+ public void setDataSyncEnabled(final String cmHandleId, final Boolean dataSyncEnabledTargetValue) {
+ cmHandleRegistrationService.setDataSyncEnabled(cmHandleId, dataSyncEnabledTargetValue);
+ }
+
+ /**
+ * Retrieve cm handle details for a given cm handle.
+ *
+ * @param cmHandleId cm handle identifier
+ * @return cm handle details
+ */
+ public NcmpServiceCmHandle getNcmpServiceCmHandle(final String cmHandleId) {
+ return YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(
+ inventoryPersistence.getYangModelCmHandle(cmHandleId));
+ }
+
+ /**
+ * Get cm handle public properties for a given cm handle id.
+ *
+ * @param cmHandleId cm handle identifier
+ * @return cm handle public properties
+ */
+ public Map<String, String> getCmHandlePublicProperties(final String cmHandleId) {
+ final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
+ final List<YangModelCmHandle.Property> yangModelPublicProperties = yangModelCmHandle.getPublicProperties();
+ final Map<String, String> cmHandlePublicProperties = new HashMap<>();
+ YangDataConverter.asPropertiesMap(yangModelPublicProperties, cmHandlePublicProperties);
+ return cmHandlePublicProperties;
+ }
+
+ /**
+ * Get cm handle composite state for a given cm handle id.
+ *
+ * @param cmHandleId cm handle identifier
+ * @return cm handle state
+ */
+ public CompositeState getCmHandleCompositeState(final String cmHandleId) {
+ return inventoryPersistence.getYangModelCmHandle(cmHandleId).getCompositeState();
+ }
+
+
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryApiParameters.java
index dd8dcd60a..596fb94a3 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryApiParameters.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryApiParameters.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models;
+package org.onap.cps.ncmp.api.inventory.models;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryServiceParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryServiceParameters.java
index 5eeafaca3..13915918e 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleQueryServiceParameters.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleQueryServiceParameters.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models;
+package org.onap.cps.ncmp.api.inventory.models;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponse.java
index 52b8d6926..7523f77af 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponse.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponse.java
@@ -19,7 +19,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models;
+package org.onap.cps.ncmp.api.inventory.models;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR;
@@ -31,7 +31,7 @@ import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.NcmpResponseStatus;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
@Data
@Builder
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java
index 5b88f560e..ca4fde2b6 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeState.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeState.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.api.inventory.models;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -29,6 +29,9 @@ import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
+import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory;
/**
* State Model to store state corresponding to the Yang resource dmi-registry model.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java
index 2fbe2b2f7..59d7aa2b4 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilder.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilder.java
@@ -19,11 +19,14 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.api.inventory.models;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState.DataStores;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState.LockReason;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState.Operational;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState.DataStores;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState.LockReason;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState.Operational;
+import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
+import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory;
import org.onap.cps.spi.model.DataNode;
public class CompositeStateBuilder {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/ConditionApiProperties.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/ConditionApiProperties.java
index 5cb2ed376..61d9f4a25 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/ConditionApiProperties.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/ConditionApiProperties.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models;
+package org.onap.cps.ncmp.api.inventory.models;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java
index 7d6a8e140..a5002e790 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistration.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistration.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models;
+package org.onap.cps.ncmp.api.inventory.models;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistrationResponse.java
index ee034176e..736ca620d 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/DmiPluginRegistrationResponse.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/DmiPluginRegistrationResponse.java
@@ -19,7 +19,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models;
+package org.onap.cps.ncmp.api.inventory.models;
import java.util.Collections;
import java.util.List;
@@ -33,4 +33,4 @@ public class DmiPluginRegistrationResponse {
private List<CmHandleRegistrationResponse> updatedCmHandles = Collections.emptyList();
private List<CmHandleRegistrationResponse> removedCmHandles = Collections.emptyList();
private List<CmHandleRegistrationResponse> upgradedCmHandles = Collections.emptyList();
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java
index 676eebc4d..69b33a16f 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/NcmpServiceCmHandle.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models;
+package org.onap.cps.ncmp.api.inventory.models;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.Nulls;
@@ -27,7 +27,6 @@ import java.util.Map;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
import org.springframework.validation.annotation.Validated;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/UpgradedCmHandles.java
index 61cd99ac8..9f48ae968 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/UpgradedCmHandles.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/UpgradedCmHandles.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models;
+package org.onap.cps.ncmp.api.inventory.models;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.util.Collections;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/YangResource.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/YangResource.java
index 7975777aa..1c0ca5d8c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/YangResource.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/models/YangResource.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models;
+package org.onap.cps.ncmp.api.inventory.models;
import lombok.Data;
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/exceptions/InvalidTopicException.java
new file mode 100644
index 000000000..fcf2a28cc
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/InvalidTopicException.java
@@ -0,0 +1,40 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.exceptions;
+
+import lombok.Getter;
+
+public class InvalidTopicException extends RuntimeException {
+
+ @Getter
+ final String details;
+
+ /**
+ * Constructor.
+ *
+ * @param message the error message
+ * @param details the error details
+ */
+ public InvalidTopicException(final String message, final String details) {
+ super(message);
+ this.details = details;
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NoAlternateIdParentFoundException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java
index 2e6cd3308..510a6f51a 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NoAlternateIdParentFoundException.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/NoAlternateIdMatchFoundException.java
@@ -18,22 +18,23 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.exception;
+package org.onap.cps.ncmp.exceptions;
import java.io.Serial;
+import org.onap.cps.ncmp.api.impl.exception.NcmpException;
-public class NoAlternateIdParentFoundException extends NcmpException {
+public class NoAlternateIdMatchFoundException extends NcmpException {
@Serial
private static final long serialVersionUID = -2412915490233422945L;
- private static final String ALTERNATE_ID_NOT_FOUND = "No matching (parent) cm handle found using alternate ids";
+ private static final String ALTERNATE_ID_NOT_FOUND = "No matching cm handle found using alternate ids";
/**
* Constructor.
*
* @param cpsPath datanode cpsPath
*/
- public NoAlternateIdParentFoundException(final String cpsPath) {
+ public NoAlternateIdMatchFoundException(final String cpsPath) {
super(ALTERNATE_ID_NOT_FOUND, String.format("cannot find a datanode with alternate id %s", cpsPath));
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/OperationNotSupportedException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/OperationNotSupportedException.java
new file mode 100644
index 000000000..d75c0bd47
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/OperationNotSupportedException.java
@@ -0,0 +1,32 @@
+/*
+ * ============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.exceptions;
+
+public class OperationNotSupportedException extends RuntimeException {
+ /**
+ * Instantiates a new not implemented operation exception.
+ *
+ * @param message the message
+ */
+ public OperationNotSupportedException(final String message) {
+ super(message);
+ }
+}
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/exceptions/PayloadTooLargeException.java
new file mode 100644
index 000000000..dc7057af7
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/exceptions/PayloadTooLargeException.java
@@ -0,0 +1,31 @@
+/*
+ * ============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.exceptions;
+
+public class PayloadTooLargeException extends RuntimeException {
+
+ /**
+ * Instantiates a new payload too large exception.
+ */
+ public PayloadTooLargeException(final String message) {
+ super(message);
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/DataJobServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImpl.java
index b4377b84f..56ed6e30d 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/DataJobServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobServiceImpl.java
@@ -18,17 +18,29 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl;
+package org.onap.cps.ncmp.impl.datajobs;
+import java.util.List;
+import java.util.Map;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.DataJobService;
-import org.onap.cps.ncmp.api.models.datajob.DataJobMetadata;
-import org.onap.cps.ncmp.api.models.datajob.DataJobReadRequest;
-import org.onap.cps.ncmp.api.models.datajob.DataJobWriteRequest;
+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.DataJobReadRequest;
+import org.onap.cps.ncmp.api.datajobs.models.DataJobWriteRequest;
+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.springframework.stereotype.Service;
@Slf4j
+@Service
+@RequiredArgsConstructor
public class DataJobServiceImpl implements DataJobService {
+ private final DmiSubJobRequestHandler dmiSubJobClient;
+ private final WriteRequestExaminer writeRequestExaminer;
+
@Override
public void readDataJob(final String dataJobId, final DataJobMetadata dataJobMetadata,
final DataJobReadRequest dataJobReadRequest) {
@@ -36,8 +48,13 @@ public class DataJobServiceImpl implements DataJobService {
}
@Override
- public void writeDataJob(final String dataJobId, final DataJobMetadata dataJobMetadata,
- final DataJobWriteRequest dataJobWriteRequest) {
+ public List<SubJobWriteResponse> writeDataJob(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);
}
}
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
new file mode 100644
index 000000000..8027e69d5
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java
@@ -0,0 +1,85 @@
+/*
+ * ============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 java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+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.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.operations.OperationType;
+import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService;
+import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder;
+import org.onap.cps.utils.JsonObjectMapper;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+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 dataJobMetadata the data job's metadata
+ * @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,
+ 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);
+
+ final String dmiResourceUrl = getDmiResourceUrl(dataJobId, producerKey);
+ final ResponseEntity<Object> responseEntity = dmiRestClient.synchronousPostOperationWithJsonData(
+ RequiredDmiService.DATA,
+ dmiResourceUrl,
+ jsonObjectMapper.asJsonString(subJobWriteRequest),
+ OperationType.CREATE,
+ NO_AUTH_HEADER);
+ final SubJobWriteResponse subJobWriteResponse = (SubJobWriteResponse) responseEntity.getBody();
+ log.debug("Sub job write response: {}", subJobWriteResponse);
+ subJobWriteResponses.add(subJobWriteResponse);
+ });
+ return subJobWriteResponses;
+ }
+
+ private String getDmiResourceUrl(final String dataJobId, final ProducerKey producerKey) {
+ return DmiServiceUrlBuilder.newInstance().pathSegment("writeJob").variablePathSegment("requestId", dataJobId)
+ .build(producerKey.dmiServiceName(), dmiProperties.getDmiBasePath());
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java
new file mode 100644
index 000000000..0e51f0c44
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java
@@ -0,0 +1,109 @@
+/*
+ * ============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 java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.datajobs.models.DataJobWriteRequest;
+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.WriteOperation;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
+import org.onap.cps.spi.model.DataNode;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class WriteRequestExaminer {
+
+ private final AlternateIdMatcher alternateIdMatcher;
+ private static final String PATH_SEPARATOR = "/";
+
+ /**
+ * Splitting incoming data job write request into Dmi Write Operations by ProducerKey.
+ *
+ * @param dataJobId data job identifier
+ * @param dataJobWriteRequest incoming data job write request
+ * @return {@code Map} map of Dmi Write Operations per Producer Key
+ */
+ public Map<ProducerKey, List<DmiWriteOperation>> splitDmiWriteOperationsFromRequest(
+ final String dataJobId,
+ final DataJobWriteRequest dataJobWriteRequest) {
+ final Map<ProducerKey, List<DmiWriteOperation>> dmiWriteOperationsPerProducerKey = new HashMap<>();
+ for (final WriteOperation writeOperation : dataJobWriteRequest.data()) {
+ examineWriteOperation(dataJobId, dmiWriteOperationsPerProducerKey, writeOperation);
+ }
+ return dmiWriteOperationsPerProducerKey;
+ }
+
+ private void examineWriteOperation(final String dataJobId,
+ final Map<ProducerKey, List<DmiWriteOperation>> dmiWriteOperationsPerProducerKey,
+ final WriteOperation writeOperation) {
+ log.debug("data job id for write operation is: {}", dataJobId);
+ final DataNode dataNode = alternateIdMatcher
+ .getCmHandleDataNodeByLongestMatchingAlternateId(writeOperation.path(), PATH_SEPARATOR);
+
+ final DmiWriteOperation dmiWriteOperation = createDmiWriteOperation(writeOperation, dataNode);
+
+ final ProducerKey producerKey = createProducerKey(dataNode);
+ final List<DmiWriteOperation> dmiWriteOperations;
+ if (dmiWriteOperationsPerProducerKey.containsKey(producerKey)) {
+ dmiWriteOperations = dmiWriteOperationsPerProducerKey.get(producerKey);
+ } else {
+ dmiWriteOperations = new ArrayList<>();
+ dmiWriteOperationsPerProducerKey.put(producerKey, dmiWriteOperations);
+ }
+ dmiWriteOperations.add(dmiWriteOperation);
+ }
+
+ private ProducerKey createProducerKey(final DataNode dataNode) {
+ return new ProducerKey((String) dataNode.getLeaves().get("dmi-service-name"),
+ (String) dataNode.getLeaves().get("data-producer-identifier"));
+ }
+
+ private DmiWriteOperation createDmiWriteOperation(final WriteOperation writeOperation,
+ final DataNode dataNode) {
+ return new DmiWriteOperation(
+ writeOperation.path(),
+ writeOperation.op(),
+ (String) dataNode.getLeaves().get("module-set-tag"),
+ writeOperation.value(),
+ writeOperation.operationId(),
+ getPrivatePropertiesFromDataNode(dataNode));
+ }
+
+ private Map<String, String> getPrivatePropertiesFromDataNode(final DataNode dataNode) {
+ final YangModelCmHandle yangModelCmHandle = YangDataConverter.convertCmHandleToYangModel(dataNode);
+ final Map<String, String> cmHandleDmiProperties = new LinkedHashMap<>();
+ yangModelCmHandle.getDmiProperties()
+ .forEach(dmiProperty -> cmHandleDmiProperties.put(dmiProperty.getName(), dmiProperty.getValue()));
+ return cmHandleDmiProperties;
+ }
+
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/RestQueryParametersValidator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryParametersValidator.java
index 2ef97cab5..08954024b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/RestQueryParametersValidator.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryParametersValidator.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils;
+package org.onap.cps.ncmp.impl.inventory;
import com.google.common.base.Strings;
import java.util.Collection;
@@ -26,12 +26,12 @@ import java.util.Map;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters;
+import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters;
import org.onap.cps.spi.exceptions.DataValidationException;
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class RestQueryParametersValidator {
+public class CmHandleQueryParametersValidator {
/**
* Validate query parameters.
@@ -55,7 +55,7 @@ public class RestQueryParametersValidator {
"Empty 'conditionsParameters' - please supply a valid condition parameter.");
}
cmHandleQueryParameter.getConditionParameters().forEach(
- RestQueryParametersValidator::validateConditionParameter
+ CmHandleQueryParametersValidator::validateConditionParameter
);
}
);
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java
index 81467dbb3..795d7c9c4 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java
@@ -18,26 +18,27 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.impl.inventory;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.model.DataNode;
-public interface CmHandleQueries {
+public interface CmHandleQueryService {
/**
- * Query CmHandles based on additional (private) properties.
+ * Query Cm Handles based on additional (private) properties.
*
* @param additionalPropertyQueryPairs private properties for query
- * @return Ids of CmHandles which have these private properties
+ * @return Ids of Cm Handles which have these private properties
*/
Collection<String> queryCmHandleAdditionalProperties(Map<String, String> additionalPropertyQueryPairs);
/**
- * Query CmHandles based on public properties.
+ * Query Cm Handles based on public properties.
*
* @param publicPropertyQueryPairs public properties for query
* @return CmHandles which have these public properties
@@ -45,10 +46,10 @@ public interface CmHandleQueries {
Collection<String> queryCmHandlePublicProperties(Map<String, String> publicPropertyQueryPairs);
/**
- * Query CmHandles based on Trust Level.
+ * Query Cm Handles based on Trust Level.
*
* @param trustLevelPropertyQueryPairs trust level properties for query
- * @return CmHandles which have desired trust level
+ * @return Ids of Cm Handles which have desired trust level
*/
Collection<String> queryCmHandlesByTrustLevel(Map<String, String> trustLevelPropertyQueryPairs);
@@ -56,7 +57,7 @@ public interface CmHandleQueries {
* Method which returns cm handles by the cm handles state.
*
* @param cmHandleState cm handle state
- * @return a list of cm handles
+ * @return a list of data nodes representing the cm handles.
*/
List<DataNode> queryCmHandlesByState(CmHandleState cmHandleState);
@@ -90,7 +91,7 @@ public interface CmHandleQueries {
* Method which returns cm handles by the operational sync state of cm handle.
*
* @param dataStoreSyncState sync state
- * @return a list of cm handles
+ * @return a list of data nodes representing the cm handles.
*/
List<DataNode> queryCmHandlesByOperationalSyncState(DataStoreSyncState dataStoreSyncState);
@@ -98,7 +99,8 @@ public interface CmHandleQueries {
* Get all cm handles ids by DMI plugin identifier.
*
* @param dmiPluginIdentifier DMI plugin identifier
- * @return collection of cm handles
+ * @return collection of cm handle ids
*/
Collection<String> getCmHandleIdsByDmiPluginIdentifier(String dmiPluginIdentifier);
+
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java
index 6cffb4d27..4c2f93a95 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java
@@ -19,11 +19,11 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.impl.inventory;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
@@ -35,8 +35,10 @@ import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig;
-import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType;
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
+import org.onap.cps.ncmp.impl.inventory.models.ModelledDmiServiceLeaves;
+import org.onap.cps.ncmp.impl.inventory.models.PropertyType;
import org.onap.cps.spi.CpsDataPersistenceService;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.model.DataNode;
@@ -46,7 +48,7 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor
@Component
-public class CmHandleQueriesImpl implements CmHandleQueries {
+public class CmHandleQueryServiceImpl implements CmHandleQueryService {
private static final String DESCENDANT_PATH = "//";
private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles";
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java
index 6aa09767b..f10ccd4ae 100755..100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java
@@ -1,7 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021 highstreet technologies GmbH
- * Modifications Copyright (C) 2021-2024 Nordix Foundation
+ * Copyright (C) 2021-2024 Nordix Foundation
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2021-2022 Bell Canada
* Modifications Copyright (C) 2023 TechMahindra Ltd.
@@ -22,17 +21,16 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl;
+package org.onap.cps.ncmp.impl.inventory;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_READY;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID;
-import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
-import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCmHandleQueryParameters;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
+import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE;
import com.google.common.collect.Lists;
import com.hazelcast.map.IMap;
@@ -49,70 +47,52 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.onap.cps.api.CpsDataService;
-import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService;
-import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig;
import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeStateUtils;
-import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
-import org.onap.cps.ncmp.api.impl.inventory.sync.ModuleOperationsUtils;
-import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
-import org.onap.cps.ncmp.api.impl.operations.OperationType;
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager;
import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker;
-import org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions;
-import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters;
-import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters;
-import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse;
-import org.onap.cps.ncmp.api.models.CmResourceAddress;
-import org.onap.cps.ncmp.api.models.DataOperationRequest;
-import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
-import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
-import org.onap.cps.spi.FetchDescendantsOption;
+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.CompositeStateBuilder;
+import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration;
+import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistrationResponse;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.inventory.sync.ModuleOperationsUtils;
import org.onap.cps.spi.exceptions.AlreadyDefinedException;
import org.onap.cps.spi.exceptions.CpsException;
import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.onap.cps.spi.exceptions.DataValidationException;
-import org.onap.cps.spi.model.ModuleDefinition;
-import org.onap.cps.spi.model.ModuleReference;
-import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@RequiredArgsConstructor
-public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService {
+public class CmHandleRegistrationService {
private static final int DELETE_BATCH_SIZE = 100;
- private final JsonObjectMapper jsonObjectMapper;
- private final DmiDataOperations dmiDataOperations;
- private final NetworkCmProxyDataServicePropertyHandler networkCmProxyDataServicePropertyHandler;
+
+ private final CmHandleRegistrationServicePropertyHandler cmHandleRegistrationServicePropertyHandler;
private final InventoryPersistence inventoryPersistence;
- private final CmHandleQueries cmHandleQueries;
- private final NetworkCmProxyCmHandleQueryService networkCmProxyCmHandleQueryService;
- private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler;
private final CpsDataService cpsDataService;
+ private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler;
private final IMap<String, Object> moduleSyncStartedOnCmHandles;
@Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN)
private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
-
private final TrustLevelManager trustLevelManager;
+
private final AlternateIdChecker alternateIdChecker;
- @Override
+ /**
+ * Registration of Created, Removed, Updated or Upgraded CM Handles.
+ *
+ * @param dmiPluginRegistration Dmi Plugin Registration details
+ * @return dmiPluginRegistrationResponse
+ */
public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(
final DmiPluginRegistration dmiPluginRegistration) {
@@ -132,95 +112,6 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
return dmiPluginRegistrationResponse;
}
- @Override
- public Object getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress,
- final String optionsParamInQuery,
- final String topicParamInQuery,
- final String requestId,
- final String authorization) {
- final ResponseEntity<?> responseEntity = dmiDataOperations.getResourceDataFromDmi(cmResourceAddress,
- optionsParamInQuery,
- topicParamInQuery,
- requestId,
- authorization);
- return responseEntity.getBody();
- }
-
- @Override
- public Object getResourceDataForCmHandle(final CmResourceAddress cmResourceAddress,
- final FetchDescendantsOption fetchDescendantsOption) {
- return cpsDataService.getDataNodes(cmResourceAddress.datastoreName(),
- cmResourceAddress.cmHandleId(),
- cmResourceAddress.resourceIdentifier(),
- fetchDescendantsOption).iterator().next();
- }
-
- @Override
- public void executeDataOperationForCmHandles(final String topicParamInQuery,
- final DataOperationRequest dataOperationRequest,
- final String requestId,
- final String authorization) {
- dmiDataOperations.requestResourceDataFromDmi(topicParamInQuery, dataOperationRequest, requestId,
- authorization);
- }
-
- @Override
- public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandleId,
- final String resourceIdentifier,
- final OperationType operationType,
- final String requestData,
- final String dataType,
- final String authorization) {
- return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleId, resourceIdentifier,
- operationType, requestData, dataType, authorization);
- }
-
- @Override
- public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleId) {
- return inventoryPersistence.getYangResourcesModuleReferences(cmHandleId);
- }
-
- @Override
- public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleId(final String cmHandleId) {
- return inventoryPersistence.getModuleDefinitionsByCmHandleId(cmHandleId);
- }
-
- @Override
- public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleAndModule(final String cmHandleId,
- final String moduleName,
- final String moduleRevision) {
- return inventoryPersistence.getModuleDefinitionsByCmHandleAndModule(cmHandleId, moduleName, moduleRevision);
- }
-
- /**
- * Retrieve cm handles with details for the given query parameters.
- *
- * @param cmHandleQueryApiParameters cm handle query parameters
- * @return cm handles with details
- */
- @Override
- public Collection<NcmpServiceCmHandle> executeCmHandleSearch(
- final CmHandleQueryApiParameters cmHandleQueryApiParameters) {
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType(
- cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class);
- validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES);
- return networkCmProxyCmHandleQueryService.queryCmHandles(cmHandleQueryServiceParameters);
- }
-
- /**
- * Retrieve cm handle ids for the given query parameters.
- *
- * @param cmHandleQueryApiParameters cm handle query parameters
- * @return cm handle ids
- */
- @Override
- public Collection<String> executeCmHandleIdSearch(final CmHandleQueryApiParameters cmHandleQueryApiParameters) {
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType(
- cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class);
- validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES);
- return networkCmProxyCmHandleQueryService.queryCmHandleIds(cmHandleQueryServiceParameters);
- }
-
/**
* Set the data sync enabled flag, along with the data sync state
* based on the data sync enabled boolean for the cm handle id provided.
@@ -228,7 +119,6 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
* @param cmHandleId cm handle id
* @param dataSyncEnabledTargetValue data sync enabled flag
*/
- @Override
public void setDataSyncEnabled(final String cmHandleId, final Boolean dataSyncEnabledTargetValue) {
final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId);
if (dataSyncEnabledTargetValue.equals(compositeState.getDataSyncEnabled())) {
@@ -252,70 +142,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
}
}
- /**
- * Get all cm handle IDs by DMI plugin identifier.
- *
- * @param dmiPluginIdentifier DMI plugin identifier
- * @return set of cm handle IDs
- */
- @Override
- public Collection<String> getAllCmHandleIdsByDmiPluginIdentifier(final String dmiPluginIdentifier) {
- return cmHandleQueries.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifier);
- }
-
- /**
- * Get all cm handle IDs by various properties.
- *
- * @param cmHandleQueryServiceParameters cm handle query parameters
- * @return set of cm handle IDs
- */
- @Override
- public Collection<String> executeCmHandleIdSearchForInventory(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
- validateCmHandleQueryParameters(cmHandleQueryServiceParameters, InventoryQueryConditions.ALL_CONDITION_NAMES);
- return networkCmProxyCmHandleQueryService.queryCmHandleIdsForInventory(cmHandleQueryServiceParameters);
- }
-
- /**
- * Retrieve cm handle details for a given cm handle.
- *
- * @param cmHandleId cm handle identifier
- * @return cm handle details
- */
- @Override
- public NcmpServiceCmHandle getNcmpServiceCmHandle(final String cmHandleId) {
- return YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(
- inventoryPersistence.getYangModelCmHandle(cmHandleId));
- }
-
- /**
- * Get cm handle public properties for a given cm handle id.
- *
- * @param cmHandleId cm handle identifier
- * @return cm handle public properties
- */
- @Override
- public Map<String, String> getCmHandlePublicProperties(final String cmHandleId) {
- final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
- final List<YangModelCmHandle.Property> yangModelPublicProperties = yangModelCmHandle.getPublicProperties();
- final Map<String, String> cmHandlePublicProperties = new HashMap<>();
- YangDataConverter.asPropertiesMap(yangModelPublicProperties, cmHandlePublicProperties);
- return cmHandlePublicProperties;
- }
-
- /**
- * Get cm handle composite state for a given cm handle id.
- *
- * @param cmHandleId cm handle identifier
- * @return cm handle state
- */
- @Override
- public CompositeState getCmHandleCompositeState(final String cmHandleId) {
- return inventoryPersistence.getYangModelCmHandle(cmHandleId).getCompositeState();
- }
-
protected void processRemovedCmHandles(final DmiPluginRegistration dmiPluginRegistration,
- final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
+ final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
final List<String> tobeRemovedCmHandleIds = dmiPluginRegistration.getRemovedCmHandles();
final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses =
new ArrayList<>(tobeRemovedCmHandleIds.size());
@@ -348,7 +176,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
}
protected void processCreatedCmHandles(final DmiPluginRegistration dmiPluginRegistration,
- final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
+ final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
final List<NcmpServiceCmHandle> ncmpServiceCmHandles = dmiPluginRegistration.getCreatedCmHandles();
final List<CmHandleRegistrationResponse> failedCmHandleRegistrationResponses = new ArrayList<>();
@@ -378,8 +206,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
}
protected void processUpdatedCmHandles(final DmiPluginRegistration dmiPluginRegistration,
- final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
- dmiPluginRegistrationResponse.setUpdatedCmHandles(networkCmProxyDataServicePropertyHandler
+ final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
+ dmiPluginRegistrationResponse.setUpdatedCmHandles(cmHandleRegistrationServicePropertyHandler
.updateCmHandleProperties(dmiPluginRegistration.getUpdatedCmHandles()));
}
@@ -405,67 +233,24 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
}
} else {
cmHandleUpgradeResponses.add(
- CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_READY));
+ CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_READY));
}
} catch (final DataNodeNotFoundException dataNodeNotFoundException) {
log.error("Unable to find data node for cm handle id : {} , caused by : {}",
- cmHandleId, dataNodeNotFoundException.getMessage());
+ cmHandleId, dataNodeNotFoundException.getMessage());
cmHandleUpgradeResponses.add(
- CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND));
+ CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND));
} catch (final DataValidationException dataValidationException) {
log.error("Unable to upgrade cm handle id: {}, caused by : {}",
- cmHandleId, dataValidationException.getMessage());
+ cmHandleId, dataValidationException.getMessage());
cmHandleUpgradeResponses.add(
- CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID));
+ CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID));
}
}
cmHandleUpgradeResponses.addAll(upgradeCmHandles(acceptedCmHandleStatePerCmHandle));
dmiPluginRegistrationResponse.setUpgradedCmHandles(cmHandleUpgradeResponses);
}
- private Collection<String> checkAlternateIds(
- final List<NcmpServiceCmHandle> cmHandlesToBeCreated,
- final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses) {
- final Collection<String> rejectedCmHandleIds = alternateIdChecker
- .getIdsOfCmHandlesWithRejectedAlternateId(cmHandlesToBeCreated, AlternateIdChecker.Operation.CREATE);
- cmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponses(
- rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED));
- return rejectedCmHandleIds;
- }
-
- private List<String> persistCmHandlesWithState(final DmiPluginRegistration dmiPluginRegistration,
- final DmiPluginRegistrationResponse dmiPluginRegistrationResponse,
- final List<NcmpServiceCmHandle> cmHandlesToBeCreated,
- final Collection<String> rejectedCmHandleIds) {
- final List<String> succeededCmHandleIds = new ArrayList<>(cmHandlesToBeCreated.size());
- final List<YangModelCmHandle> yangModelCmHandlesToRegister = new ArrayList<>(cmHandlesToBeCreated.size());
- final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses =
- new ArrayList<>(cmHandlesToBeCreated.size());
- for (final NcmpServiceCmHandle ncmpServiceCmHandle: cmHandlesToBeCreated) {
- if (!rejectedCmHandleIds.contains(ncmpServiceCmHandle.getCmHandleId())) {
- yangModelCmHandlesToRegister.add(getYangModelCmHandle(dmiPluginRegistration, ncmpServiceCmHandle));
- cmHandleRegistrationResponses.add(
- CmHandleRegistrationResponse.createSuccessResponse(ncmpServiceCmHandle.getCmHandleId()));
- succeededCmHandleIds.add(ncmpServiceCmHandle.getCmHandleId());
- }
- }
- lcmEventsCmHandleStateHandler.initiateStateAdvised(yangModelCmHandlesToRegister);
- dmiPluginRegistrationResponse.setCreatedCmHandles(cmHandleRegistrationResponses);
- return succeededCmHandleIds;
- }
-
- private YangModelCmHandle getYangModelCmHandle(final DmiPluginRegistration dmiPluginRegistration,
- final NcmpServiceCmHandle ncmpServiceCmHandle) {
- return YangModelCmHandle.toYangModelCmHandle(
- dmiPluginRegistration.getDmiPlugin(),
- dmiPluginRegistration.getDmiDataPlugin(),
- dmiPluginRegistration.getDmiModelPlugin(),
- ncmpServiceCmHandle,
- ncmpServiceCmHandle.getModuleSetTag(),
- ncmpServiceCmHandle.getAlternateId(),
- ncmpServiceCmHandle.getDataProducerIdentifier());
- }
-
private void processTrustLevels(final Collection<NcmpServiceCmHandle> cmHandlesToBeCreated,
final Collection<String> succeededCmHandleIds) {
final Map<String, TrustLevel> initialTrustLevelPerCmHandleId = new HashMap<>(cmHandlesToBeCreated.size());
@@ -489,9 +274,9 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
private static void updateYangModelCmHandleForUpgrade(final YangModelCmHandle yangModelCmHandle,
final String upgradedModuleSetTag) {
final String lockReasonWithModuleSetTag = String.format(ModuleOperationsUtils.MODULE_SET_TAG_MESSAGE_FORMAT,
- upgradedModuleSetTag);
+ upgradedModuleSetTag);
yangModelCmHandle.setCompositeState(new CompositeStateBuilder().withCmHandleState(CmHandleState.READY)
- .withLockReason(MODULE_UPGRADE, lockReasonWithModuleSetTag).build());
+ .withLockReason(MODULE_UPGRADE, lockReasonWithModuleSetTag).build());
}
private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) {
@@ -569,4 +354,48 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
}
}
+ private Collection<String> checkAlternateIds(
+ final List<NcmpServiceCmHandle> cmHandlesToBeCreated,
+ final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses) {
+ final Collection<String> rejectedCmHandleIds = alternateIdChecker
+ .getIdsOfCmHandlesWithRejectedAlternateId(cmHandlesToBeCreated, AlternateIdChecker.Operation.CREATE);
+ cmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponses(
+ rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED));
+ return rejectedCmHandleIds;
+ }
+
+ private List<String> persistCmHandlesWithState(final DmiPluginRegistration dmiPluginRegistration,
+ final DmiPluginRegistrationResponse dmiPluginRegistrationResponse,
+ final List<NcmpServiceCmHandle> cmHandlesToBeCreated,
+ final Collection<String> rejectedCmHandleIds) {
+ final List<String> succeededCmHandleIds = new ArrayList<>(cmHandlesToBeCreated.size());
+ final List<YangModelCmHandle> yangModelCmHandlesToRegister = new ArrayList<>(cmHandlesToBeCreated.size());
+ final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses =
+ new ArrayList<>(cmHandlesToBeCreated.size());
+ for (final NcmpServiceCmHandle ncmpServiceCmHandle: cmHandlesToBeCreated) {
+ if (!rejectedCmHandleIds.contains(ncmpServiceCmHandle.getCmHandleId())) {
+ yangModelCmHandlesToRegister.add(getYangModelCmHandle(dmiPluginRegistration, ncmpServiceCmHandle));
+ cmHandleRegistrationResponses.add(
+ CmHandleRegistrationResponse.createSuccessResponse(ncmpServiceCmHandle.getCmHandleId()));
+ succeededCmHandleIds.add(ncmpServiceCmHandle.getCmHandleId());
+ }
+ }
+ lcmEventsCmHandleStateHandler.initiateStateAdvised(yangModelCmHandlesToRegister);
+ dmiPluginRegistrationResponse.setCreatedCmHandles(cmHandleRegistrationResponses);
+ return succeededCmHandleIds;
+ }
+
+ private YangModelCmHandle getYangModelCmHandle(final DmiPluginRegistration dmiPluginRegistration,
+ final NcmpServiceCmHandle ncmpServiceCmHandle) {
+ return YangModelCmHandle.toYangModelCmHandle(
+ dmiPluginRegistration.getDmiPlugin(),
+ dmiPluginRegistration.getDmiDataPlugin(),
+ dmiPluginRegistration.getDmiModelPlugin(),
+ ncmpServiceCmHandle,
+ ncmpServiceCmHandle.getModuleSetTag(),
+ ncmpServiceCmHandle.getAlternateId(),
+ ncmpServiceCmHandle.getDataProducerIdentifier());
+ }
+
+
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.java
index f86191002..164d91725 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandler.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.
@@ -20,16 +20,16 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl;
+package org.onap.cps.ncmp.impl.inventory;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID;
-import static org.onap.cps.ncmp.api.impl.NetworkCmProxyDataServicePropertyHandler.PropertyType.DMI_PROPERTY;
-import static org.onap.cps.ncmp.api.impl.NetworkCmProxyDataServicePropertyHandler.PropertyType.PUBLIC_PROPERTY;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
+import static org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationServicePropertyHandler.PropertyType.DMI_PROPERTY;
+import static org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationServicePropertyHandler.PropertyType.PUBLIC_PROPERTY;
+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;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
import com.google.common.collect.ImmutableMap;
import java.time.OffsetDateTime;
@@ -45,16 +45,16 @@ import java.util.regex.Pattern;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.api.CpsDataService;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.onap.cps.spi.exceptions.DataValidationException;
import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.model.DataNodeBuilder;
+import org.onap.cps.utils.ContentType;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@@ -64,7 +64,7 @@ import org.springframework.util.StringUtils;
@RequiredArgsConstructor
//Accepting the security hotspot as the string checked is generated from inside code and not user input.
@SuppressWarnings("squid:S5852")
-public class NetworkCmProxyDataServicePropertyHandler {
+public class CmHandleRegistrationServicePropertyHandler {
private final InventoryPersistence inventoryPersistence;
private final CpsDataService cpsDataService;
@@ -137,6 +137,9 @@ public class NetworkCmProxyDataServicePropertyHandler {
log.warn("Unable to update dataProducerIdentifier for cmHandle {}. "
+ "Value for dataProducerIdentifier has been set previously.",
ncmpServiceCmHandle.getCmHandleId());
+ } else {
+ log.debug("dataProducerIdentifier for cmHandle {} is already set to {}.",
+ ncmpServiceCmHandle.getCmHandleId(), newDataProducerIdentifier);
}
} else {
setAndUpdateCmHandleField(
@@ -222,7 +225,7 @@ public class NetworkCmProxyDataServicePropertyHandler {
cmHandleData.put(fieldName, newFieldValue);
dmiRegistryData.put("cm-handles", cmHandleData);
cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT,
- jsonObjectMapper.asJsonString(dmiRegistryData), OffsetDateTime.now());
+ jsonObjectMapper.asJsonString(dmiRegistryData), OffsetDateTime.now(), ContentType.JSON);
log.debug("Updating {} for cmHandle {} with value : {})", fieldName, cmHandleIdToUpdate, newFieldValue);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java
index 35ad54fde..685d20463 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CompositeStateUtils.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CompositeStateUtils.java
@@ -18,11 +18,13 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.impl.inventory;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
/**
* It will have all the utility method responsible for handling the composite state.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/DataStoreSyncState.java
index b92d152bf..a260ce9cb 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/DataStoreSyncState.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/DataStoreSyncState.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.impl.inventory;
public enum DataStoreSyncState {
SYNCHRONIZED, UNSYNCHRONIZED, NONE_REQUESTED
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java
index 184b12570..cb4b04e4a 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistence.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java
@@ -19,13 +19,13 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.impl.inventory;
import java.util.Collection;
import java.util.List;
import java.util.Map;
-import org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.model.ModuleDefinition;
import org.onap.cps.spi.model.ModuleReference;
@@ -130,16 +130,6 @@ public interface InventoryPersistence extends NcmpPersistence {
DataNode getCmHandleDataNodeByAlternateId(String alternateId);
/**
- * Get data node that matches longest alternate id by removing elements (as defined by the separator string)
- * from right to left.
- *
- * @param alternateId alternate ID
- * @param separator a string that separates each element from the next.
- * @return data node
- */
- DataNode getCmHandleDataNodeByLongestMatchAlternateId(final String alternateId, final String separator);
-
- /**
* Get collection of data nodes of given cm handles.
*
* @param cmHandleIds collection of cmHandle IDs
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
index bf54fe5d9..40aefed2a 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
@@ -20,7 +20,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.impl.inventory;
import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
@@ -33,13 +33,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
import org.onap.cps.api.CpsAnchorService;
import org.onap.cps.api.CpsDataService;
import org.onap.cps.api.CpsModuleService;
-import org.onap.cps.ncmp.api.impl.exception.NoAlternateIdParentFoundException;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.onap.cps.spi.exceptions.DataValidationException;
@@ -59,7 +59,7 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
private final CpsModuleService cpsModuleService;
private final CpsAnchorService cpsAnchorService;
private final CpsValidator cpsValidator;
- private final CmHandleQueries cmHandleQueries;
+ private final CmHandleQueryService cmHandleQueryService;
/**
* initialize an inventory persistence object.
@@ -72,12 +72,13 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
*/
public InventoryPersistenceImpl(final JsonObjectMapper jsonObjectMapper, final CpsDataService cpsDataService,
final CpsModuleService cpsModuleService, final CpsValidator cpsValidator,
- final CpsAnchorService cpsAnchorService, final CmHandleQueries cmHandleQueries) {
+ final CpsAnchorService cpsAnchorService,
+ final CmHandleQueryService cmHandleQueryService) {
super(jsonObjectMapper, cpsDataService, cpsModuleService, cpsValidator);
this.cpsModuleService = cpsModuleService;
this.cpsAnchorService = cpsAnchorService;
this.cpsValidator = cpsValidator;
- this.cmHandleQueries = cmHandleQueries;
+ this.cmHandleQueryService = cmHandleQueryService;
}
@@ -172,7 +173,7 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
@Override
public DataNode getCmHandleDataNodeByAlternateId(final String alternateId) {
final String cpsPathForCmHandleByAlternateId = getCpsPathForCmHandleByAlternateId(alternateId);
- final Collection<DataNode> dataNodes = cmHandleQueries
+ final Collection<DataNode> dataNodes = cmHandleQueryService
.queryNcmpRegistryByCpsPath(cpsPathForCmHandleByAlternateId, OMIT_DESCENDANTS);
if (dataNodes.isEmpty()) {
throw new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
@@ -182,19 +183,6 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
}
@Override
- public DataNode getCmHandleDataNodeByLongestMatchAlternateId(final String alternateId, final String separator) {
- String bestMatch = alternateId;
- while (StringUtils.isNotEmpty(bestMatch)) {
- try {
- return getCmHandleDataNodeByAlternateId(bestMatch);
- } catch (final DataNodeNotFoundException ignored) {
- bestMatch = getParentPath(bestMatch, separator);
- }
- }
- throw new NoAlternateIdParentFoundException(alternateId);
- }
-
- @Override
public Collection<DataNode> getCmHandleDataNodes(final Collection<String> cmHandleIds) {
final Collection<String> xpaths = new ArrayList<>(cmHandleIds.size());
cmHandleIds.forEach(cmHandleId -> xpaths.add(getXPathForCmHandleById(cmHandleId)));
@@ -221,9 +209,4 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
private String createCmHandlesJsonData(final List<YangModelCmHandle> yangModelCmHandles) {
return "{\"cm-handles\":" + jsonObjectMapper.asJsonString(yangModelCmHandles) + "}";
}
-
- private static String getParentPath(final String path, final String separator) {
- final int lastSeparatorIndex = path.lastIndexOf(separator);
- return lastSeparatorIndex < 0 ? "" : path.substring(0, lastSeparatorIndex);
- }
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java
index d72b5d58f..5271485e3 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/ncmppersistence/NcmpPersistence.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistence.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.ncmppersistence;
+package org.onap.cps.ncmp.impl.inventory;
import java.time.OffsetDateTime;
import java.util.Collection;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java
index 6a2d6d810..e44b6ba34 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/NcmpPersistenceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/NcmpPersistenceImpl.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.impl.inventory;
import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED;
import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
@@ -29,7 +29,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.api.CpsDataService;
import org.onap.cps.api.CpsModuleService;
-import org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.exceptions.SchemaSetNotFoundException;
import org.onap.cps.spi.model.DataNode;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyCmHandleQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java
index 06522f80c..e5848c0df 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyCmHandleQueryService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java
@@ -18,13 +18,13 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api;
+package org.onap.cps.ncmp.impl.inventory;
import java.util.Collection;
-import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
-public interface NetworkCmProxyCmHandleQueryService {
+public interface ParameterizedCmHandleQueryService {
/**
* Query and return cm handle ids that match the given query parameters.
* Supported query types:
@@ -63,7 +63,8 @@ public interface NetworkCmProxyCmHandleQueryService {
Collection<NcmpServiceCmHandle> queryCmHandles(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
/**
- * Query and return all cm handle objects.
+ * Get all cm handle objects.
+ * Note: it is similar to all the queries above but simply no conditions and hence not 'parameterized'
*
* @return collection of cm handles
*/
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java
index 8890d14ae..51e403fd6 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java
@@ -18,16 +18,16 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl;
-
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
-import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_MODULES;
-import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_PROPERTIES;
-import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_CPS_PATH;
-import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_TRUST_LEVEL;
-import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCpsPathConditionProperties;
-import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateModuleNameConditionProperties;
-import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
+package org.onap.cps.ncmp.impl.inventory;
+
+import static org.onap.cps.ncmp.impl.inventory.CmHandleQueryParametersValidator.validateCpsPathConditionProperties;
+import static org.onap.cps.ncmp.impl.inventory.CmHandleQueryParametersValidator.validateModuleNameConditionProperties;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.HAS_ALL_MODULES;
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.HAS_ALL_PROPERTIES;
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.WITH_CPS_PATH;
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.WITH_TRUST_LEVEL;
+import static org.onap.cps.ncmp.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
import static org.onap.cps.spi.FetchDescendantsOption.DIRECT_CHILDREN_ONLY;
import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
@@ -42,15 +42,12 @@ import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.cpspath.parser.PathParsingException;
-import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
-import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType;
-import org.onap.cps.ncmp.api.impl.utils.InventoryQueryConditions;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.impl.inventory.models.InventoryQueryConditions;
+import org.onap.cps.ncmp.impl.inventory.models.PropertyType;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.onap.cps.spi.exceptions.DataValidationException;
import org.onap.cps.spi.model.ConditionProperties;
import org.onap.cps.spi.model.DataNode;
@@ -59,10 +56,10 @@ import org.springframework.stereotype.Service;
@Service
@Slf4j
@RequiredArgsConstructor
-public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmHandleQueryService {
+public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHandleQueryService {
private static final Collection<String> NO_QUERY_TO_EXECUTE = null;
- private final CmHandleQueries cmHandleQueries;
+ private final CmHandleQueryService cmHandleQueryService;
private final InventoryPersistence inventoryPersistence;
@Override
@@ -115,7 +112,7 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
final String dmiPluginIdentifierValue = dmiPropertyQueryPairs
.get(PropertyType.DMI_PLUGIN.getYangContainerName());
- return cmHandleQueries.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifierValue);
+ return cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifierValue);
}
private Collection<String> queryCmHandlesByPrivateProperties(
@@ -128,7 +125,7 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
if (privatePropertyQueryPairs.isEmpty()) {
return NO_QUERY_TO_EXECUTE;
}
- return cmHandleQueries.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
+ return cmHandleQueryService.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
}
private Collection<String> queryCmHandlesByPublicProperties(
@@ -141,7 +138,7 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
if (publicPropertyQueryPairs.isEmpty()) {
return NO_QUERY_TO_EXECUTE;
}
- return cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
+ return cmHandleQueryService.queryCmHandlePublicProperties(publicPropertyQueryPairs);
}
private Collection<String> queryCmHandlesByTrustLevel(final CmHandleQueryServiceParameters
@@ -154,7 +151,7 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
if (trustLevelPropertyQueryPairs.isEmpty()) {
return NO_QUERY_TO_EXECUTE;
}
- return cmHandleQueries.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs);
+ return cmHandleQueryService.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs);
}
private Collection<String> executeModuleNameQuery(
@@ -180,7 +177,7 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
}
try {
cpsPathQueryResult = collectCmHandleIdsFromDataNodes(
- cmHandleQueries.queryCmHandleAncestorsByCpsPath(
+ cmHandleQueryService.queryCmHandleAncestorsByCpsPath(
cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS));
} catch (final PathParsingException pathParsingException) {
throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(),
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleQueryConditions.java
index a59776036..6be5c8ba1 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleQueryConditions.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils;
+package org.onap.cps.ncmp.impl.inventory.models;
import java.util.Arrays;
import java.util.Collection;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleState.java
index 5485ee7e8..9a4b3e2a8 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleState.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/CmHandleState.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.impl.inventory.models;
public enum CmHandleState {
ADVISED, READY, LOCKED, DELETING, DELETED
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/InventoryQueryConditions.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java
index 9437cf0ba..fce285b41 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/InventoryQueryConditions.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditions.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils;
+package org.onap.cps.ncmp.impl.inventory.models;
import java.util.Arrays;
import java.util.List;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/LockReasonCategory.java
index e2b2c6b4a..1003aeca2 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/LockReasonCategory.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/LockReasonCategory.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.impl.inventory.models;
public enum LockReasonCategory {
MODULE_SYNC_FAILED,
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/ModelledDmiServiceLeaves.java
index b8a1ba02d..e9c4957d0 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/ModelledDmiServiceLeaves.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/ModelledDmiServiceLeaves.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory;
+package org.onap.cps.ncmp.impl.inventory.models;
public enum ModelledDmiServiceLeaves {
DMI_SERVICE_NAME("dmi-service-name"),
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/PropertyType.java
index 08bfe98e5..cc8b094b4 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/enums/PropertyType.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/PropertyType.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.enums;
+package org.onap.cps.ncmp.impl.inventory.models;
import lombok.AllArgsConstructor;
import lombok.Getter;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java
index 2ca2b2eb0..d96c9c720 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandle.java
@@ -19,7 +19,7 @@
*/
-package org.onap.cps.ncmp.api.impl.yangmodels;
+package org.onap.cps.ncmp.impl.inventory.models;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@@ -34,9 +34,9 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
/**
* Cm Handle which follows the Yang resource dmi registry model when persisting data to DMI or the DB.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java
index 2d5e7a1ab..b8bb64f53 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutor.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutor.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync.executor;
+package org.onap.cps.ncmp.impl.inventory.sync;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java
index 6f089a57f..45f636784 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdog.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdog.java
@@ -18,9 +18,9 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync;
+package org.onap.cps.ncmp.impl.inventory.sync;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
import com.hazelcast.map.IMap;
import java.time.OffsetDateTime;
@@ -29,10 +29,9 @@ import java.util.function.Consumer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.api.CpsDataService;
-import org.onap.cps.ncmp.api.impl.config.embeddedcache.SynchronizationCacheConfig;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
-import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState;
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java
index 794ca5b1b..15e4653c9 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtils.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java
@@ -19,9 +19,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync;
-
-import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL;
+package org.onap.cps.ncmp.impl.inventory.sync;
import com.fasterxml.jackson.databind.JsonNode;
import java.time.Duration;
@@ -38,14 +36,14 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
-import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState;
-import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory;
import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService;
+import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
+import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.model.DataNode;
import org.onap.cps.utils.JsonObjectMapper;
@@ -57,7 +55,7 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor
public class ModuleOperationsUtils {
- private final CmHandleQueries cmHandleQueries;
+ private final CmHandleQueryService cmHandleQueryService;
private final DmiDataOperations dmiDataOperations;
private final JsonObjectMapper jsonObjectMapper;
private static final String RETRY_ATTEMPT_KEY = "attempt";
@@ -78,7 +76,8 @@ public class ModuleOperationsUtils {
* @return cm handles (data nodes) in ADVISED state (empty list if none found)
*/
public List<DataNode> getAdvisedCmHandles() {
- final List<DataNode> advisedCmHandlesAsDataNodes = cmHandleQueries.queryCmHandlesByState(CmHandleState.ADVISED);
+ final List<DataNode> advisedCmHandlesAsDataNodes =
+ cmHandleQueryService.queryCmHandlesByState(CmHandleState.ADVISED);
log.debug("Total number of fetched advised cm handle(s) is (are) {}", advisedCmHandlesAsDataNodes.size());
return advisedCmHandlesAsDataNodes;
}
@@ -91,13 +90,13 @@ public class ModuleOperationsUtils {
* return empty list if not found
*/
public List<YangModelCmHandle> getUnsynchronizedReadyCmHandles() {
- final List<DataNode> unsynchronizedCmHandles = cmHandleQueries
+ final List<DataNode> unsynchronizedCmHandles = cmHandleQueryService
.queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED);
final List<YangModelCmHandle> yangModelCmHandles = new ArrayList<>();
for (final DataNode unsynchronizedCmHandle : unsynchronizedCmHandles) {
final String cmHandleId = unsynchronizedCmHandle.getLeaves().get("id").toString();
- if (cmHandleQueries.cmHandleHasState(cmHandleId, CmHandleState.READY)) {
+ if (cmHandleQueryService.cmHandleHasState(cmHandleId, CmHandleState.READY)) {
yangModelCmHandles.addAll(convertCmHandlesDataNodesToYangModelCmHandles(
Collections.singletonList(unsynchronizedCmHandle)));
}
@@ -113,7 +112,7 @@ public class ModuleOperationsUtils {
*/
public List<YangModelCmHandle> getCmHandlesThatFailedModelSyncOrUpgrade() {
final List<DataNode> lockedCmHandlesAsDataNodeList
- = cmHandleQueries.queryCmHandleAncestorsByCpsPath(CPS_PATH_CM_HANDLES_MODEL_SYNC_FAILED_OR_UPGRADE,
+ = cmHandleQueryService.queryCmHandleAncestorsByCpsPath(CPS_PATH_CM_HANDLES_MODEL_SYNC_FAILED_OR_UPGRADE,
FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
return convertCmHandlesDataNodesToYangModelCmHandles(lockedCmHandlesAsDataNodeList);
}
@@ -198,16 +197,14 @@ public class ModuleOperationsUtils {
}
/**
- * Get the Resourece Data from Node through DMI Passthrough service.
+ * Get the Resource Data from Node through DMI Passthrough service.
*
* @param cmHandleId cm handle id
* @return optional string containing the resource data
*/
public String getResourceData(final String cmHandleId) {
- final ResponseEntity<Object> resourceDataResponseEntity = dmiDataOperations.getResourceDataFromDmi(
- PASSTHROUGH_OPERATIONAL.getDatastoreName(),
- cmHandleId,
- UUID.randomUUID().toString());
+ final ResponseEntity<Object> resourceDataResponseEntity = dmiDataOperations.getAllResourceDataFromDmi(
+ cmHandleId, UUID.randomUUID().toString());
if (resourceDataResponseEntity.getStatusCode().is2xxSuccessful()) {
return getFirstResource(resourceDataResponseEntity.getBody());
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java
index e257112fc..2c8639a4d 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncService.java
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2022-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.
@@ -18,12 +19,12 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync;
+package org.onap.cps.ncmp.impl.inventory.sync;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
import java.time.OffsetDateTime;
import java.util.Collection;
@@ -37,16 +38,17 @@ import org.apache.commons.lang3.StringUtils;
import org.onap.cps.api.CpsAnchorService;
import org.onap.cps.api.CpsDataService;
import org.onap.cps.api.CpsModuleService;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.onap.cps.spi.CascadeDeleteAllowed;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.exceptions.SchemaSetNotFoundException;
import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.model.ModuleReference;
+import org.onap.cps.utils.ContentType;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.stereotype.Service;
@@ -57,7 +59,7 @@ public class ModuleSyncService {
private final DmiModelOperations dmiModelOperations;
private final CpsModuleService cpsModuleService;
- private final CmHandleQueries cmHandleQueries;
+ private final CmHandleQueryService cmHandleQueryService;
private final CpsDataService cpsDataService;
private final CpsAnchorService cpsAnchorService;
private final JsonObjectMapper jsonObjectMapper;
@@ -134,7 +136,7 @@ public class ModuleSyncService {
return null;
}
final String escapedModuleSetTag = moduleSetTag.replace("'", "''");
- final List<DataNode> dataNodes = cmHandleQueries.queryNcmpRegistryByCpsPath(
+ final List<DataNode> dataNodes = cmHandleQueryService.queryNcmpRegistryByCpsPath(
NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@module-set-tag='" + escapedModuleSetTag + "']",
FetchDescendantsOption.DIRECT_CHILDREN_ONLY);
return dataNodes.stream().map(YangDataConverter::convertCmHandleToYangModel)
@@ -146,6 +148,6 @@ public class ModuleSyncService {
final String jsonForUpdate = jsonObjectMapper.asJsonString(Map.of(
"cm-handles", Map.of("id", yangModelCmHandle.getId(), "module-set-tag", newModuleSetTag)));
cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT,
- jsonForUpdate, OffsetDateTime.now());
+ jsonForUpdate, OffsetDateTime.now(), ContentType.JSON);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java
index 590cb56c4..80c290cb5 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasks.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync;
+package org.onap.cps.ncmp.impl.inventory.sync;
import com.hazelcast.map.IMap;
import java.util.Collection;
@@ -30,12 +30,12 @@ import java.util.concurrent.atomic.AtomicInteger;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler;
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
-import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+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;
+import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.onap.cps.spi.model.DataNode;
import org.springframework.stereotype.Component;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java
index 249232d23..b4dde18da 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdog.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java
@@ -19,7 +19,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync;
+package org.onap.cps.ncmp.impl.inventory.sync;
import com.hazelcast.map.IMap;
import java.util.Collection;
@@ -31,9 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.impl.config.embeddedcache.SynchronizationCacheConfig;
-import org.onap.cps.ncmp.api.impl.inventory.sync.executor.AsyncTaskExecutor;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.spi.model.DataNode;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java
index 62a380ca5..76b33cc8d 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfig.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfig.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config.embeddedcache;
+package org.onap.cps.ncmp.impl.inventory.sync;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.QueueConfig;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/WatchdogSchedulingConfigurer.java
index 1aaee2708..203c5a1a2 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/WatchdogSchedulingConfigurer.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync.config;
+package org.onap.cps.ncmp.impl.inventory.sync;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
@@ -53,4 +53,4 @@ public class WatchdogSchedulingConfigurer implements SchedulingConfigurer {
taskScheduler.initialize();
return taskScheduler;
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java
new file mode 100644
index 000000000..832e576d5
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java
@@ -0,0 +1,63 @@
+/*
+ * ============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.utils;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.cps.ncmp.exceptions.NoAlternateIdMatchFoundException;
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
+import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
+import org.onap.cps.spi.model.DataNode;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class AlternateIdMatcher {
+
+ private final InventoryPersistence inventoryPersistence;
+
+ /**
+ * Get data node that matches longest alternate id by removing elements (as defined by the separator string)
+ * from right to left.
+ *
+ * @param alternateId alternate ID
+ * @param separator a string that separates each element from the next.
+ * @return data node
+ */
+ public DataNode getCmHandleDataNodeByLongestMatchingAlternateId(final String alternateId, final String separator) {
+ String bestMatch = alternateId;
+ while (StringUtils.isNotEmpty(bestMatch)) {
+ try {
+ return inventoryPersistence.getCmHandleDataNodeByAlternateId(bestMatch);
+ } catch (final DataNodeNotFoundException ignored) {
+ bestMatch = getParentPath(bestMatch, separator);
+ }
+ }
+ throw new NoAlternateIdMatchFoundException(alternateId);
+ }
+
+ private String getParentPath(final String path, final String separator) {
+ final int lastSeparatorIndex = path.lastIndexOf(separator);
+ return lastSeparatorIndex < 0 ? "" : path.substring(0, lastSeparatorIndex);
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java
index 07b92892a..bde13684a 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/YangDataConverter.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/YangDataConverter.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils;
+package org.onap.cps.ncmp.impl.utils;
import java.util.Collection;
import java.util.LinkedHashMap;
@@ -30,10 +30,10 @@ import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
-import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder;
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.spi.model.DataNode;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
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 4cc8cdaa6..554501127 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
@@ -39,7 +39,7 @@ import org.onap.cps.spi.exceptions.AlreadyDefinedException;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
-import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
@Slf4j
@RequiredArgsConstructor
@@ -61,12 +61,12 @@ abstract class AbstractModelLoader implements ModelLoader {
long retryTimeMs;
@Override
- public void onApplicationEvent(@NonNull final ApplicationReadyEvent applicationReadyEvent) {
+ public void onApplicationEvent(@NonNull final ApplicationStartedEvent applicationStartedEvent) {
try {
onboardOrUpgradeModel();
} catch (final NcmpStartUpException ncmpStartUpException) {
log.error("Onboarding model for NCMP failed: {} ", ncmpStartUpException.getMessage());
- SpringApplication.exit(applicationReadyEvent.getApplicationContext(), () -> EXIT_CODE_ON_ERROR);
+ SpringApplication.exit(applicationStartedEvent.getApplicationContext(), () -> EXIT_CODE_ON_ERROR);
}
}
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 a0b7bd582..130defb30 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
@@ -20,7 +20,7 @@
package org.onap.cps.ncmp.init;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME;
import static org.onap.cps.utils.ContentType.JSON;
import java.time.OffsetDateTime;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
index 7c25953f0..76d12f290 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
@@ -20,9 +20,9 @@
package org.onap.cps.ncmp.init;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR;
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
+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;
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.api.CpsAnchorService;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/ModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/ModelLoader.java
index c61bf1c9b..9832ba3f9 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/ModelLoader.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/ModelLoader.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation
+ * 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.
@@ -21,13 +21,13 @@
package org.onap.cps.ncmp.init;
import lombok.NonNull;
-import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
-public interface ModelLoader extends ApplicationListener<ApplicationReadyEvent> {
+public interface ModelLoader extends ApplicationListener<ApplicationStartedEvent> {
@Override
- void onApplicationEvent(@NonNull ApplicationReadyEvent applicationReadyEvent);
+ void onApplicationEvent(@NonNull ApplicationStartedEvent applicationStartedEvent);
void onboardOrUpgradeModel();
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/TopicValidator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/TopicValidator.java
new file mode 100644
index 000000000..f9fed8d43
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/TopicValidator.java
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.utils;
+
+import java.util.regex.Pattern;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.onap.cps.ncmp.exceptions.InvalidTopicException;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class TopicValidator {
+
+ private static final Pattern TOPIC_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9]([._-](?![._-])|"
+ + "[a-zA-Z0-9]){0,120}[a-zA-Z0-9]$");
+
+ /**
+ * Validate kafka topic name pattern.
+ *
+ * @param topicName name of the topic to be validated
+ *
+ * @throws InvalidTopicException if the topic is not valid
+ */
+ public static void validateTopicName(final String topicName) {
+ if (!TOPIC_NAME_PATTERN.matcher(topicName).matches()) {
+ throw new InvalidTopicException("Topic name " + topicName + " is invalid", "invalid topic");
+ }
+ }
+
+}
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/api/impl/DataJobServiceImplSpec.groovy
index 43787640a..9cee2bdba 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/api/impl/DataJobServiceImplSpec.groovy
@@ -24,17 +24,25 @@ 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.models.datajob.DataJobReadRequest
-import org.onap.cps.ncmp.api.models.datajob.DataJobWriteRequest
-import org.onap.cps.ncmp.api.models.datajob.DataJobMetadata
-import org.onap.cps.ncmp.api.models.datajob.ReadOperation
-import org.onap.cps.ncmp.api.models.datajob.WriteOperation
+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 spock.lang.Specification
-class DataJobServiceImplSpec extends Specification{
+class DataJobServiceImplSpec extends Specification {
- def objectUnderTest = new DataJobServiceImpl()
+ def mockWriteRequestExaminer = Mock(WriteRequestExaminer)
+ def mockDmiSubJobRequestHandler = Mock(DmiSubJobRequestHandler)
+
+ def objectUnderTest = new DataJobServiceImpl(mockDmiSubJobRequestHandler, mockWriteRequestExaminer)
+
+ def myDataJobMetadata = new DataJobMetadata('', '', '')
def logger = Spy(ListAppender<ILoggingEvent>)
@@ -46,28 +54,27 @@ class DataJobServiceImplSpec extends Specification{
((Logger) LoggerFactory.getLogger(DataJobServiceImpl.class)).detachAndStopAllAppenders()
}
- def '#operation data job request.'() {
- given: 'data job metadata'
- def dataJobMetadata = new DataJobMetadata('client-topic', 'application/vnd.3gpp.object-tree-hierarchical+json', 'application/3gpp-json-patch+json')
- when: 'read/write data job request is processed'
- if (operation == 'read') {
- objectUnderTest.readDataJob('some-job-id', dataJobMetadata, new DataJobReadRequest([getWriteOrReadOperationRequest(operation)]))
- } else {
- objectUnderTest.writeDataJob('some-job-id', dataJobMetadata, new DataJobWriteRequest([getWriteOrReadOperationRequest(operation)]))
- }
+ 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]))
then: 'the data job id is correctly logged'
def loggingEvent = logger.list[0]
assert loggingEvent.level == Level.INFO
- assert loggingEvent.formattedMessage.contains('data job id for ' + operation + ' operation is: some-job-id')
- where: 'the following data job operations are used'
- operation << ['read', 'write']
+ assert loggingEvent.formattedMessage.contains('data job id for read operation is: my-job-id')
}
- def getWriteOrReadOperationRequest(operation) {
- if (operation == 'write') {
- return new WriteOperation('some/write/path', 'add', 'some-operation-id', 'some-value')
- }
- return new ReadOperation('some/read/path', 'read', 'some-operation-id', ['some-attrib-1'], ['some-field-1'], 'some-filter', 'some-scope-type', 1)
+ def 'Write data-job request.'() {
+ given: 'data job metadata and write request'
+ def dataJobWriteRequest = new DataJobWriteRequest([new WriteOperation('', '', '', null)])
+ 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)
+ 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)
}
def setupLogger() {
@@ -76,4 +83,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/api/impl/DmiSubJobRequestHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/DmiSubJobRequestHandlerSpec.groovy
new file mode 100644
index 000000000..8dc3d223b
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/DmiSubJobRequestHandlerSpec.groovy
@@ -0,0 +1,41 @@
+package org.onap.cps.ncmp.api.impl
+
+import com.fasterxml.jackson.databind.ObjectMapper
+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.api.impl.operations.OperationType
+import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService
+import org.onap.cps.ncmp.impl.datajobs.DmiSubJobRequestHandler
+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/NcmpCachedResourceRequestHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NcmpCachedResourceRequestHandlerSpec.groovy
new file mode 100644
index 000000000..781b6204a
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NcmpCachedResourceRequestHandlerSpec.groovy
@@ -0,0 +1,64 @@
+/*
+ * ============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
+
+import org.onap.cps.api.CpsDataService
+import org.onap.cps.ncmp.api.NetworkCmProxyQueryService
+import org.onap.cps.ncmp.api.models.CmResourceAddress
+import org.onap.cps.spi.model.DataNode
+import reactor.core.publisher.Mono
+import spock.lang.Specification
+
+import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
+import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
+
+class NcmpCachedResourceRequestHandlerSpec extends Specification {
+
+ def cpsDataService = Mock(CpsDataService)
+ def networkCmProxyQueryService= Mock(NetworkCmProxyQueryService)
+
+ def objectUnderTest = new NcmpCachedResourceRequestHandler(cpsDataService, networkCmProxyQueryService)
+
+ def 'Execute a request with include descendants = #includeDescendants.'() {
+ when: 'executing a request'
+ objectUnderTest.executeRequest('ch-1', 'resource', includeDescendants)
+ then: 'it is delegated to the ncmp query service with the correct option'
+ 1 * networkCmProxyQueryService.queryResourceDataOperational('ch-1','resource', expectedFetchDescendantsOption)
+ where: 'the following options are used'
+ includeDescendants || expectedFetchDescendantsOption
+ true || INCLUDE_ALL_DESCENDANTS
+ false || OMIT_DESCENDANTS
+ }
+
+ def 'Get resource data.'() {
+ given: 'the data service returns 2 nodes for the given resource address'
+ def cmResourceAddress = new CmResourceAddress('datastore','ch-1','resource')
+ def dataNode1 = new DataNode(xpath:'p1')
+ def dataNode2 = new DataNode(xpath:'p2')
+ cpsDataService.getDataNodes('datastore','ch-1','resource',OMIT_DESCENDANTS) >> [dataNode1, dataNode2]
+ when: 'getting the resource data'
+ def result = objectUnderTest.getResourceDataForCmHandle(cmResourceAddress, 'options', 'topic', 'request id', false, 'authorization')
+ then: 'the result is a "Mono" holding just the first data node'
+ assert result instanceof Mono
+ assert result.block() == dataNode1
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandlerSpec.groovy
new file mode 100644
index 000000000..9a845c0ba
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NcmpDatastoreRequestHandlerSpec.groovy
@@ -0,0 +1,133 @@
+/*
+ * ============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.api.impl
+
+import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException
+import org.onap.cps.ncmp.api.impl.exception.InvalidOperationException
+import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
+import org.onap.cps.ncmp.api.models.CmResourceAddress
+import org.onap.cps.ncmp.api.models.DataOperationDefinition
+import org.onap.cps.ncmp.api.models.DataOperationRequest
+import org.onap.cps.ncmp.exceptions.OperationNotSupportedException
+import org.onap.cps.ncmp.exceptions.PayloadTooLargeException
+import org.springframework.http.ResponseEntity
+import reactor.core.publisher.Mono
+import spock.lang.Specification
+
+import static org.springframework.http.HttpStatus.I_AM_A_TEAPOT
+
+class NcmpDatastoreRequestHandlerSpec extends Specification {
+
+ def dmiDataOperations = Mock(DmiDataOperations)
+
+ def objectUnderTest = new NcmpPassthroughResourceRequestHandler(dmiDataOperations)
+
+ def NO_TOPIC = null
+ def NO_AUTH_HEADER = null
+
+ def 'Attempt to execute async get request with #scenario.'() {
+ given: 'notification feature is turned on/off'
+ objectUnderTest.notificationFeatureEnabled = notificationFeatureEnabled
+ and: 'a CM resource address'
+ def cmResourceAddress = new CmResourceAddress('ds', 'ch1', 'resource1')
+ and: 'the (mocked) service when called with the correct parameters (with or without topic) returns a response from dmi'
+ def dmiResponse = Mono.justOrEmpty(new ResponseEntity('dmi response',I_AM_A_TEAPOT))
+ dmiDataOperations.getResourceDataFromDmi(cmResourceAddress, 'options', NO_TOPIC, _, NO_AUTH_HEADER) >> dmiResponse
+ dmiDataOperations.getResourceDataFromDmi(cmResourceAddress, 'options', topic, _, NO_AUTH_HEADER) >> dmiResponse
+ when: 'get request is executed with topic = #topic'
+ def response = objectUnderTest.executeRequest(cmResourceAddress, 'options', topic, false, NO_AUTH_HEADER)
+ then: 'a successful result with/without request id is returned'
+ if (expectSynchronousResponse) {
+ assert response == 'dmi response'
+ } else { // expect request id in a map
+ assert response.keySet()[0] == 'requestId'
+ }
+ where: 'the following parameters are used'
+ scenario | notificationFeatureEnabled | topic || expectSynchronousResponse
+ 'feature on, valid topic' | true | 'valid' || false
+ 'feature on, no topic' | true | null || true
+ 'feature off, valid topic' | false | 'valid' || true
+ 'feature off, no topic' | false | null || true
+ }
+
+ def 'Attempt to execute async data operation request with feature #scenario.'() {
+ given: 'a extended request handler that supports bulk requests'
+ def objectUnderTest = new NcmpPassthroughResourceRequestHandler(dmiDataOperations)
+ and: 'notification feature is turned on/off'
+ objectUnderTest.notificationFeatureEnabled = notificationFeatureEnabled
+ when: 'data operation request is executed'
+ def dataOperationDefinition = new DataOperationDefinition(operation: 'read', datastore: 'ncmp-datastore:passthrough-running', cmHandleIds: ['ch'])
+ def result = objectUnderTest.executeAsynchronousRequest('someTopic', new DataOperationRequest(dataOperationDefinitions:[dataOperationDefinition]), NO_AUTH_HEADER)
+ then: 'the task is executed in an async fashion or not'
+ expectedCalls * dmiDataOperations.requestResourceDataFromDmi('someTopic', _, _, NO_AUTH_HEADER)
+ and:
+ result.keySet()[0] == expectedKeyInMap
+ where: 'the following parameters are used'
+ scenario | notificationFeatureEnabled || expectedCalls || expectedKeyInMap
+ 'on' | true || 1 || 'requestId'
+ 'off' | false || 0 || 'status'
+ }
+
+ def 'Attempt to execute async data operation request with error #scenario'() {
+ given: 'a data operation definition with datastore: #datastore'
+ def dataOperationDefinition = new DataOperationDefinition(operation: 'read', datastore: datastore)
+ when: 'data operation request is executed'
+ def dataOperationRequest = new DataOperationRequest(dataOperationDefinitions: [dataOperationDefinition])
+ objectUnderTest.executeAsynchronousRequest('myTopic', dataOperationRequest, NO_AUTH_HEADER)
+ then: 'the correct error is thrown'
+ def thrown = thrown(InvalidDatastoreException)
+ assert thrown.message.contains(expectedErrorMessage)
+ where: 'the following datastore names are used'
+ scenario | datastore || expectedErrorMessage
+ 'unsupported datastore' | 'ncmp-datastore:operational' || 'not supported'
+ 'invalid datastore' | 'invalid' || 'invalid datastore name'
+ }
+
+ def 'Attempt to execute async data operation request with #scenario operation: #operation.'() {
+ given: 'a data operation definition with operation: #operation'
+ def dataOperationDefinition = new DataOperationDefinition(operation: operation, datastore: 'ncmp-datastore:passthrough-running')
+ when: 'data operation request is executed'
+ objectUnderTest.executeAsynchronousRequest('someTopic', new DataOperationRequest(dataOperationDefinitions:[dataOperationDefinition]), NO_AUTH_HEADER)
+ then: 'the expected type of exception is thrown'
+ thrown(expectedException)
+ where: 'the following operations are used'
+ scenario | operation || expectedException
+ 'invalid' | 'invalid' || InvalidOperationException
+ 'unsupported' | 'create' || OperationNotSupportedException
+ 'unsupported' | 'update' || OperationNotSupportedException
+ 'unsupported' | 'patch' || OperationNotSupportedException
+ 'unsupported' | 'delete' || OperationNotSupportedException
+ }
+
+ def 'Attempt to execute async data operation request with too many cm handles.'() {
+ given: 'a data operation definition with too many cm handles'
+ def tooMany = objectUnderTest.MAXIMUM_CM_HANDLES_PER_OPERATION + 1
+ def cmHandleIds = new String[tooMany]
+ def dataOperationDefinition = new DataOperationDefinition(operationId: 'abc', operation: 'read', datastore: 'ncmp-datastore:passthrough-running', cmHandleIds: cmHandleIds)
+ when: 'data operation request is executed'
+ objectUnderTest.executeAsynchronousRequest('someTopic', new DataOperationRequest(dataOperationDefinitions:[dataOperationDefinition]), NO_AUTH_HEADER)
+ then: 'a payload too large exception is thrown'
+ def exceptionThrown = thrown(PayloadTooLargeException)
+ and: 'the error message contains the offending number of cm handles'
+ assert exceptionThrown.message == "Operation 'abc' affects too many (${tooMany}) cm handles"
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
deleted file mode 100644
index 4d0af6f49..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2021-2024 Nordix Foundation
- * Modifications Copyright (C) 2021 Pantheon.tech
- * Modifications Copyright (C) 2021-2022 Bell Canada
- * Modifications Copyright (C) 2023 TechMahindra Ltd.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.api.impl
-
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
-import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL
-import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL
-import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE
-
-import org.onap.cps.ncmp.api.models.DmiPluginRegistrationResponse
-import org.onap.cps.ncmp.api.models.CmResourceAddress
-import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker
-import com.hazelcast.map.IMap
-import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService
-import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler
-import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
-import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory
-import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState
-import org.onap.cps.ncmp.api.models.DataOperationDefinition
-import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters
-import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters
-import org.onap.cps.ncmp.api.models.ConditionApiProperties
-import org.onap.cps.ncmp.api.models.DmiPluginRegistration
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
-import org.onap.cps.ncmp.api.models.DataOperationRequest
-import org.onap.cps.spi.exceptions.CpsException
-import org.onap.cps.spi.model.ConditionProperties
-import java.util.stream.Collectors
-import org.onap.cps.utils.JsonObjectMapper
-import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.api.CpsDataService
-import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
-import org.onap.cps.spi.FetchDescendantsOption
-import org.onap.cps.spi.model.DataNode
-import org.springframework.http.HttpStatus
-import org.springframework.http.ResponseEntity
-import spock.lang.Specification
-
-class NetworkCmProxyDataServiceImplSpec extends Specification {
-
- def mockCpsDataService = Mock(CpsDataService)
- def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
- def mockDmiDataOperations = Mock(DmiDataOperations)
- def nullNetworkCmProxyDataServicePropertyHandler = null
- def mockInventoryPersistence = Mock(InventoryPersistence)
- def mockCmHandleQueries = Mock(CmHandleQueries)
- def mockDmiPluginRegistration = Mock(DmiPluginRegistration)
- def mockCpsCmHandlerQueryService = Mock(NetworkCmProxyCmHandleQueryService)
- def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler)
- def stubModuleSyncStartedOnCmHandles = Stub(IMap<String, Object>)
- def stubTrustLevelPerDmiPlugin = Stub(Map<String, TrustLevel>)
- def mockTrustLevelManager = Mock(TrustLevelManager)
- def mockAlternateIdChecker = Mock(AlternateIdChecker)
-
- def NO_TOPIC = null
- def NO_REQUEST_ID = null
- def NO_AUTH_HEADER = null
- def OPTIONS_PARAM = '(a=1,b=2)'
- def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'test-cm-handle-id')
-
- def objectUnderTest = new NetworkCmProxyDataServiceImpl(
- spiedJsonObjectMapper,
- mockDmiDataOperations,
- nullNetworkCmProxyDataServicePropertyHandler,
- mockInventoryPersistence,
- mockCmHandleQueries,
- mockCpsCmHandlerQueryService,
- mockLcmEventsCmHandleStateHandler,
- mockCpsDataService,
- stubModuleSyncStartedOnCmHandles,
- stubTrustLevelPerDmiPlugin,
- mockTrustLevelManager,
- mockAlternateIdChecker)
-
- def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']"
-
- def dataNode = [new DataNode(leaves: ['id': 'some-cm-handle', 'dmi-service-name': 'testDmiService'])]
-
- def 'Write resource data for pass-through running from DMI using POST.'() {
- given: 'cpsDataService returns valid datanode'
- mockDataNode()
- when: 'write resource data is called'
- objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
- 'testResourceId', CREATE,
- '{some-json}', 'application/json', null)
- then: 'DMI called with correct data'
- 1 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId',
- CREATE, '{some-json}', 'application/json', null)
- >> { new ResponseEntity<>(HttpStatus.CREATED) }
- }
-
- def 'Get resource data for from DMI.'() {
- given: 'cpsDataService returns valid data node'
- mockDataNode()
- and: 'some cm resource address'
- def cmResourceAddress = new CmResourceAddress('some datastore','some CM Handle', 'some resource Id')
- and: 'get resource data from DMI is called'
- mockDmiDataOperations.getResourceDataFromDmi(cmResourceAddress, OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER) >>
- new ResponseEntity<>('dmi-response', HttpStatus.OK)
- when: 'get resource data operational for the given cm resource address is called'
- def response = objectUnderTest.getResourceDataForCmHandle(cmResourceAddress, OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER)
- then: 'DMI returns a json response'
- assert response == 'dmi-response'
- }
-
- def 'Get resource data for operational (cached) data.'() {
- given: 'CPS Data service returns some object(s)'
- mockCpsDataService.getDataNodes(OPERATIONAL.datastoreName, 'testCmHandle', 'testResourceId', FetchDescendantsOption.OMIT_DESCENDANTS) >> ['First Object', 'other Object']
- and: 'a cm resource address for the same datastore, cm handle and resource id'
- def cmResourceAddress = new CmResourceAddress(OPERATIONAL.datastoreName, 'testCmHandle', 'testResourceId')
- when: 'get resource data is called'
- def response = objectUnderTest.getResourceDataForCmHandle(cmResourceAddress, FetchDescendantsOption.OMIT_DESCENDANTS)
- then: 'get resource data returns teh first object from the data service'
- assert response == 'First Object'
- }
-
- def 'Execute (async) data operation for #datastoreName from DMI.'() {
- given: 'cpsDataService returns valid data node'
- def dataOperationRequest = getDataOperationRequest(datastoreName)
- when: 'request resource data for data operation is called'
- objectUnderTest.executeDataOperationForCmHandles('some topic', dataOperationRequest, 'requestId', NO_AUTH_HEADER)
- then: 'request resource data for data operation returns expected response'
- 1 * mockDmiDataOperations.requestResourceDataFromDmi('some topic', dataOperationRequest, 'requestId', NO_AUTH_HEADER)
- where: 'the following data stores are used'
- datastoreName << [PASSTHROUGH_RUNNING.datastoreName, PASSTHROUGH_OPERATIONAL.datastoreName]
- }
-
- def 'Getting Yang Resources.'() {
- when: 'yang resources is called'
- objectUnderTest.getYangResourcesModuleReferences('some-cm-handle')
- then: 'CPS module services is invoked for the correct dataspace and cm handle'
- 1 * mockInventoryPersistence.getYangResourcesModuleReferences('some-cm-handle')
- }
-
- def 'Get a cm handle.'() {
- given: 'the system returns a yang modelled cm handle'
- def dmiServiceName = 'some service name'
- def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED,
- lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(),
- lastUpdateTime: 'some-timestamp',
- dataSyncEnabled: false,
- dataStores: dataStores())
- def dmiProperties = [new YangModelCmHandle.Property('Book', 'Romance Novel')]
- def publicProperties = [new YangModelCmHandle.Property('Public Book', 'Public Romance Novel')]
- def moduleSetTag = 'some-module-set-tag'
- def alternateId = 'some-alternate-id'
- def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', dmiServiceName: dmiServiceName,
- dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState,
- moduleSetTag: moduleSetTag, alternateId: alternateId)
- 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
- when: 'getting cm handle details for a given cm handle id from ncmp service'
- def result = objectUnderTest.getNcmpServiceCmHandle('some-cm-handle')
- then: 'the result is a ncmpServiceCmHandle'
- result.class == NcmpServiceCmHandle.class
- and: 'the cm handle contains the cm handle id'
- result.cmHandleId == 'some-cm-handle'
- and: 'the cm handle contains the alternate id'
- result.alternateId == 'some-alternate-id'
- and: 'the cm handle contains the module-set-tag'
- result.moduleSetTag == 'some-module-set-tag'
- and: 'the cm handle contains the DMI Properties'
- result.dmiProperties ==[ Book:'Romance Novel' ]
- and: 'the cm handle contains the public Properties'
- result.publicProperties == [ "Public Book":'Public Romance Novel' ]
- and: 'the cm handle contains the cm handle composite state'
- result.compositeState == compositeState
- }
-
- def 'Get cm handle public properties'() {
- given: 'a yang modelled cm handle'
- def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
- def publicProperties = [new YangModelCmHandle.Property('public prop', 'some public prop')]
- def yangModelCmHandle = new YangModelCmHandle(id:'some-cm-handle', dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties)
- and: 'the system returns this yang modelled cm handle'
- 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
- when: 'getting cm handle public properties for a given cm handle id from ncmp service'
- def result = objectUnderTest.getCmHandlePublicProperties('some-cm-handle')
- then: 'the result returns the correct data'
- result == [ 'public prop' : 'some public prop' ]
- }
-
- def 'Execute cm handle id search for inventory'() {
- given: 'a ConditionApiProperties object'
- def conditionProperties = new ConditionProperties()
- conditionProperties.conditionName = 'hasAllProperties'
- conditionProperties.conditionParameters = [ [ 'some-key' : 'some-value' ] ]
- def conditionServiceProps = new CmHandleQueryServiceParameters()
- conditionServiceProps.cmHandleQueryParameters = [conditionProperties] as List<ConditionProperties>
- and: 'the system returns an set of cmHandle ids'
- mockCpsCmHandlerQueryService.queryCmHandleIdsForInventory(*_) >> [ 'cmHandle1', 'cmHandle2' ]
- when: 'getting cm handle id set for a given dmi property'
- def result = objectUnderTest.executeCmHandleIdSearchForInventory(conditionServiceProps)
- then: 'the result returns the correct 2 elements'
- assert result.size() == 2
- assert result.contains('cmHandle1')
- assert result.contains('cmHandle2')
- }
-
- def 'Get cm handle composite state'() {
- given: 'a yang modelled cm handle'
- def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED,
- lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(),
- lastUpdateTime: 'some-timestamp',
- dataSyncEnabled: false,
- dataStores: dataStores())
- def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
- def publicProperties = [new YangModelCmHandle.Property('public prop', 'some public prop')]
- def yangModelCmHandle = new YangModelCmHandle(id:'some-cm-handle', dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState)
- and: 'the system returns this yang modelled cm handle'
- 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
- when: 'getting cm handle composite state for a given cm handle id from ncmp service'
- def result = objectUnderTest.getCmHandleCompositeState('some-cm-handle')
- then: 'the result returns the correct data'
- result == compositeState
- }
-
- def 'Update resource data for pass-through running from dmi using POST #scenario DMI properties.'() {
- given: 'cpsDataService returns valid datanode'
- mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
- when: 'get resource data is called'
- objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
- 'testResourceId', UPDATE,
- '{some-json}', 'application/json', NO_AUTH_HEADER)
- then: 'DMI called with correct data'
- 1 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId',
- UPDATE, '{some-json}', 'application/json', NO_AUTH_HEADER)
- >> { new ResponseEntity<>(HttpStatus.OK) }
- }
-
- def 'Verify modules and create anchor params.'() {
- given: 'dmi plugin registration return created cm handles'
- def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'service1', dmiModelPlugin: 'service1',
- dmiDataPlugin: 'service2')
- dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle]
- mockDmiPluginRegistration.getCreatedCmHandles() >> [ncmpServiceCmHandle]
- and: 'no rejected cm handles because of alternate ids'
- mockAlternateIdChecker.getIdsOfCmHandlesWithRejectedAlternateId(*_) >> []
- when: 'parse and create cm handle in dmi registration then sync module'
- mockDmiPluginRegistration.createdCmHandles = ['test-cm-handle-id']
- objectUnderTest.processCreatedCmHandles(mockDmiPluginRegistration, new DmiPluginRegistrationResponse())
- then: 'system persists the cm handle state'
- 1 * mockLcmEventsCmHandleStateHandler.initiateStateAdvised(_) >> {
- args -> {
- def cmHandleStatePerCmHandle = (args[0] as Collection)
- cmHandleStatePerCmHandle.each {
- assert it.id == 'test-cm-handle-id'
- }
- }
- }
- }
-
- def 'Execute cm handle id search'() {
- given: 'valid CmHandleQueryApiParameters input'
- def cmHandleQueryApiParameters = new CmHandleQueryApiParameters()
- def conditionApiProperties = new ConditionApiProperties()
- conditionApiProperties.conditionName = 'hasAllModules'
- conditionApiProperties.conditionParameters = [[moduleName: 'module-name-1']]
- cmHandleQueryApiParameters.cmHandleQueryParameters = [conditionApiProperties]
- and: 'query cm handle method return with a data node list'
- mockCpsCmHandlerQueryService.queryCmHandleIds(
- spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class))
- >> ['cm-handle-id-1']
- when: 'execute cm handle search is called'
- def result = objectUnderTest.executeCmHandleIdSearch(cmHandleQueryApiParameters)
- then: 'result is the same collection as returned by the CPS Data Service'
- assert result == ['cm-handle-id-1']
- }
-
- def 'Getting module definitions by module'() {
- when: 'get module definitions is performed with module name'
- objectUnderTest.getModuleDefinitionsByCmHandleAndModule('some-cm-handle', 'some-module', '2021-08-04')
- then: 'ncmp inventory persistence service is invoked once with correct parameters'
- 1 * mockInventoryPersistence.getModuleDefinitionsByCmHandleAndModule('some-cm-handle', 'some-module', '2021-08-04')
- }
-
- def 'Getting module definitions by cm handle id'() {
- when: 'get module definitions is performed with cm handle id'
- objectUnderTest.getModuleDefinitionsByCmHandleId('some-cm-handle')
- then: 'ncmp inventory persistence service is invoked once with correct parameter'
- 1 * mockInventoryPersistence.getModuleDefinitionsByCmHandleId('some-cm-handle')
- }
-
- def 'Execute cm handle search'() {
- given: 'valid CmHandleQueryApiParameters input'
- def cmHandleQueryApiParameters = new CmHandleQueryApiParameters()
- def conditionApiProperties = new ConditionApiProperties()
- conditionApiProperties.conditionName = 'hasAllModules'
- conditionApiProperties.conditionParameters = [[moduleName: 'module-name-1']]
- cmHandleQueryApiParameters.cmHandleQueryParameters = [conditionApiProperties]
- and: 'query cm handle method return with a data node list'
- mockCpsCmHandlerQueryService.queryCmHandles(
- spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class))
- >> [new NcmpServiceCmHandle(cmHandleId: 'cm-handle-id-1')]
- when: 'execute cm handle search is called'
- def result = objectUnderTest.executeCmHandleSearch(cmHandleQueryApiParameters)
- then: 'result is the same collection as returned by the CPS Data Service'
- assert result.stream().map(d -> d.cmHandleId).collect(Collectors.toSet()) == ['cm-handle-id-1'] as Set
- }
-
- def 'Set Cm Handle Data Sync Enabled Flag where data sync flag is #scenario'() {
- given: 'an existing cm handle composite state'
- def compositeState = new CompositeState(cmHandleState: CmHandleState.READY, dataSyncEnabled: initialDataSyncEnabledFlag,
- dataStores: CompositeState.DataStores.builder()
- .operationalDataStore(CompositeState.Operational.builder()
- .dataStoreSyncState(initialDataSyncState)
- .build()).build())
- and: 'get cm handle state returns the composite state for the given cm handle id'
- mockInventoryPersistence.getCmHandleState('some-cm-handle-id') >> compositeState
- when: 'set data sync enabled is called with the data sync enabled flag set to #dataSyncEnabledFlag'
- objectUnderTest.setDataSyncEnabled('some-cm-handle-id', dataSyncEnabledFlag)
- then: 'the data sync enabled flag is set to #dataSyncEnabled'
- compositeState.dataSyncEnabled == dataSyncEnabledFlag
- and: 'the data store sync state is set to #expectedDataStoreSyncState'
- compositeState.dataStores.operationalDataStore.dataStoreSyncState == expectedDataStoreSyncState
- and: 'the cps data service to delete data nodes is invoked the expected number of times'
- deleteDataNodeExpectedNumberOfInvocation * mockCpsDataService.deleteDataNode(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'some-cm-handle-id', '/netconf-state', _)
- and: 'the inventory persistence service to update node leaves is called with the correct values'
- saveCmHandleStateExpectedNumberOfInvocations * mockInventoryPersistence.saveCmHandleState('some-cm-handle-id', compositeState)
- where: 'the following data sync enabled flag is used'
- scenario | dataSyncEnabledFlag | initialDataSyncEnabledFlag | initialDataSyncState || expectedDataStoreSyncState | deleteDataNodeExpectedNumberOfInvocation | saveCmHandleStateExpectedNumberOfInvocations
- 'enabled' | true | false | DataStoreSyncState.NONE_REQUESTED || DataStoreSyncState.UNSYNCHRONIZED | 0 | 1
- 'disabled' | false | true | DataStoreSyncState.UNSYNCHRONIZED || DataStoreSyncState.NONE_REQUESTED | 0 | 1
- 'disabled where sync-state is currently SYNCHRONIZED' | false | true | DataStoreSyncState.SYNCHRONIZED || DataStoreSyncState.NONE_REQUESTED | 1 | 1
- 'is set to existing flag state' | true | true | DataStoreSyncState.UNSYNCHRONIZED || DataStoreSyncState.UNSYNCHRONIZED | 0 | 0
- }
-
- def 'Set cm Handle Data Sync Enabled flag with following cm handle not in ready state exception' () {
- given: 'a cm handle composite state'
- def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, dataSyncEnabled: false)
- and: 'get cm handle state returns the composite state for the given cm handle id'
- mockInventoryPersistence.getCmHandleState('some-cm-handle-id') >> compositeState
- when: 'set data sync enabled is called with the data sync enabled flag set to true'
- objectUnderTest.setDataSyncEnabled('some-cm-handle-id', true)
- then: 'the expected exception is thrown'
- thrown(CpsException)
- and: 'the inventory persistence service to update node leaves is not invoked'
- 0 * mockInventoryPersistence.saveCmHandleState(_, _)
- }
-
- def 'Get all cm handle IDs by DMI plugin identifier.' () {
- given: 'cm handle queries service returns cm handles'
- 1 * mockCmHandleQueries.getCmHandleIdsByDmiPluginIdentifier('some-dmi-plugin-identifier') >> ['cm-handle-1','cm-handle-2']
- when: 'cm handle Ids are requested with dmi plugin identifier'
- def result = objectUnderTest.getAllCmHandleIdsByDmiPluginIdentifier('some-dmi-plugin-identifier')
- then: 'the result size is correct'
- assert result.size() == 2
- and: 'the result returns the correct details'
- assert result.containsAll('cm-handle-1','cm-handle-2')
- }
-
- def dataStores() {
- CompositeState.DataStores.builder()
- .operationalDataStore(CompositeState.Operational.builder()
- .dataStoreSyncState(DataStoreSyncState.NONE_REQUESTED)
- .lastSyncTime('some-timestamp').build()).build()
- }
-
- def mockDataNode() {
- mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
- }
-
- def getDataOperationRequest(datastore) {
- def dataOperationRequest = new DataOperationRequest()
- def dataOperationDefinitions = new ArrayList()
- dataOperationDefinitions.add(getDataOperationDefinition(datastore))
- dataOperationRequest.setDataOperationDefinitions(dataOperationDefinitions)
- return dataOperationRequest
- }
-
- def getDataOperationDefinition(datastore) {
- def dataOperationDefinition = new DataOperationDefinition()
- dataOperationDefinition.setOperation("read")
- dataOperationDefinition.setOperationId("operational-12")
- dataOperationDefinition.setDatastore(datastore)
- def targetIds = new ArrayList()
- targetIds.add("some-cm-handle")
- dataOperationDefinition.setCmHandleIds(targetIds)
- return dataOperationDefinition
- }
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacadeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacadeSpec.groovy
new file mode 100644
index 000000000..f79e0ee2e
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyFacadeSpec.groovy
@@ -0,0 +1,108 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021-2024 Nordix Foundation
+ * Modifications Copyright (C) 2021 Pantheon.tech
+ * Modifications Copyright (C) 2021-2022 Bell Canada
+ * Modifications Copyright (C) 2023 TechMahindra Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl
+
+import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
+import org.onap.cps.ncmp.api.models.CmResourceAddress
+import org.onap.cps.ncmp.api.models.DataOperationRequest
+import org.onap.cps.spi.model.DataNode
+import reactor.core.publisher.Mono
+import spock.lang.Specification
+
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.OPERATIONAL
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL
+import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE
+
+class NetworkCmProxyFacadeSpec extends Specification {
+
+ def mockDmiDataOperations = Mock(DmiDataOperations)
+ def mockNcmpCachedResourceRequestHandler = Mock(NcmpCachedResourceRequestHandler)
+ def mockNcmpPassthroughResourceRequestHandler = Mock(NcmpPassthroughResourceRequestHandler)
+
+ def objectUnderTest = new NetworkCmProxyFacade(mockNcmpCachedResourceRequestHandler, mockNcmpPassthroughResourceRequestHandler, mockDmiDataOperations)
+
+ def NO_TOPIC = null
+
+ def 'Execute Data Operation for CM Handles (delegation).'() {
+ given: 'a data operation request'
+ def dataOperationRequest = Mock(DataOperationRequest)
+ and: ' a response from the (mocked) pass-through request handler for the given parameters'
+ def responseFromHandler = [attr:'value']
+ mockNcmpPassthroughResourceRequestHandler.executeAsynchronousRequest('topic', dataOperationRequest, 'authorization') >> responseFromHandler
+ expect: 'the response form the handler'
+ assert objectUnderTest.executeDataOperationForCmHandles('topic', dataOperationRequest, 'authorization') == responseFromHandler
+ }
+
+ def 'Query Resource Data for cm handle (delegation).'() {
+ given: 'a response from the (mocked) cached data handler for the given parameters'
+ def responseFromHandler = [Mock(DataNode)]
+ mockNcmpCachedResourceRequestHandler.executeRequest('ch-1', 'some cps path', true) >> responseFromHandler
+ expect: 'the response form the handler'
+ assert objectUnderTest.queryResourceDataForCmHandle('ch-1','some cps path',true) == responseFromHandler
+ }
+
+ def 'Choosing Data Request Handler.'() {
+ expect: '(a mock of) #expectedHandler'
+ assert objectUnderTest.getNcmpDatastoreRequestHandler(datastore.datastoreName).class.name.startsWith(expectedHandler.name)
+ where:
+ datastore || expectedHandler
+ OPERATIONAL || NcmpCachedResourceRequestHandler.class
+ PASSTHROUGH_RUNNING || NcmpPassthroughResourceRequestHandler.class
+ PASSTHROUGH_OPERATIONAL || NcmpPassthroughResourceRequestHandler.class
+ }
+
+ def 'Write resource data for pass-through running from DMI using POST (delegation).'() {
+ when: 'write resource data is called'
+ objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
+ 'testResourceId', CREATE,
+ '{some-json}', 'application/json', null)
+ then: 'DMI called with correct data'
+ 1 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId', CREATE, '{some-json}', 'application/json', null)
+ }
+
+ def 'Get resource data from DMI (delegation).'() {
+ given: 'a cm resource address for datastore operational'
+ def cmResourceAddress = new CmResourceAddress('ncmp-datastore:operational', 'some CM Handle', 'some resource Id')
+ and: 'get resource data from DMI is called'
+ mockNcmpCachedResourceRequestHandler.executeRequest(cmResourceAddress, 'options', NO_TOPIC, false, 'authorization') >>
+ Mono.just('dmi response')
+ when: 'get resource data operational for the given cm resource address is called'
+ def response = objectUnderTest.getResourceDataForCmHandle(cmResourceAddress, 'options', NO_TOPIC, false, 'authorization').block()
+ then: 'DMI returns a json response'
+ assert response == 'dmi response'
+ }
+
+ def 'Update resource data for pass-through running from dmi (delegation).'() {
+ when: 'get resource data is called'
+ objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
+ 'testResourceId', UPDATE,
+ '{some-json}', 'application/json', 'authorization')
+ then: 'DMI called with correct data'
+ 1 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId', UPDATE, '{some-json}', 'application/json', 'authorization')
+ }
+
+
+}
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/api/impl/WriteRequestExaminerSpec.groovy
new file mode 100644
index 000000000..84eb78b75
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/WriteRequestExaminerSpec.groovy
@@ -0,0 +1,63 @@
+
+package org.onap.cps.ncmp.impl.datajobs
+
+import org.onap.cps.ncmp.api.datajobs.models.DataJobWriteRequest
+import org.onap.cps.ncmp.api.datajobs.models.WriteOperation
+import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher
+import org.onap.cps.spi.model.DataNode
+import spock.lang.Specification
+
+class WriteRequestExaminerSpec extends Specification {
+
+ def mockAlternateIdMatcher = Mock(AlternateIdMatcher)
+ def objectUnderTest = new WriteRequestExaminer(mockAlternateIdMatcher)
+
+ def setup() {
+ def ch1 = new DataNode(leaves: [id: 'ch1', 'dmi-service-name': 'dmiA', 'data-producer-identifier': 'p1'])
+ def ch2 = new DataNode(leaves: [id: 'ch2', 'dmi-service-name': 'dmiA', 'data-producer-identifier': 'p1'])
+ def ch3 = new DataNode(leaves: [id: 'ch3', 'dmi-service-name': 'dmiA', 'data-producer-identifier': 'p2'])
+ def ch4 = new DataNode(leaves: [id: 'ch4', 'dmi-service-name': 'dmiB', 'data-producer-identifier': 'p1'])
+ mockAlternateIdMatcher.getCmHandleDataNodeByLongestMatchingAlternateId('fdn1', '/') >> ch1
+ mockAlternateIdMatcher.getCmHandleDataNodeByLongestMatchingAlternateId('fdn2', '/') >> ch2
+ mockAlternateIdMatcher.getCmHandleDataNodeByLongestMatchingAlternateId('fdn3', '/') >> ch3
+ mockAlternateIdMatcher.getCmHandleDataNodeByLongestMatchingAlternateId('fdn4', '/') >> ch4
+ }
+
+ def 'Create a map of dmi write requests per producer key with #scenario.'() {
+ given: 'a write request with some write operations'
+ def writeOperations = writeOperationFdns.collect {
+ new WriteOperation(it, '', '', null)
+ }
+ and: 'operations are wrapped in a write request'
+ def dataJobWriteRequest = new DataJobWriteRequest(writeOperations)
+ when: 'the DMI write operations are split from the request'
+ def dmiWriteOperationsPerProducerKey = objectUnderTest.splitDmiWriteOperationsFromRequest('some id', dataJobWriteRequest)
+ then: 'we get the expected number of keys and values.'
+ def producerKeysAsStrings = dmiWriteOperationsPerProducerKey.keySet().collect {
+ it.toString()
+ }
+ assert producerKeysAsStrings.size() == expectedKeys.size()
+ assert expectedKeys.containsAll(producerKeysAsStrings)
+ where:
+ scenario | writeOperationFdns || expectedKeys
+ 'one fdn' | ['fdn1'] || ['dmiA#p1']
+ 'a duplicated target' | ['fdn1','fdn1'] || ['dmiA#p1']
+ 'two different targets' | ['fdn1','fdn2'] || ['dmiA#p1']
+ 'two different targets and different producer keys' | ['fdn1','fdn3'] || ['dmiA#p1', 'dmiA#p2']
+ 'two different targets and different DMI services' | ['fdn1','fdn4'] || ['dmiA#p1', 'dmiB#p1']
+ 'many targets with different dmi service names and producer keys' | ['fdn1', 'fdn2', 'fdn3', 'fdn4'] || ['dmiA#p1', 'dmiA#p2', 'dmiB#p1']
+ }
+
+ def 'Validate the ordering of the created sub jobs.'() {
+ given: 'a few write operations for the same producer'
+ def writeOperations = (1..3).collect {
+ new WriteOperation('fdn1', '', it.toString(), null)
+ }
+ and: 'operation is wrapped in a write request'
+ def dataJobWriteRequest = new DataJobWriteRequest(writeOperations)
+ when: 'the DMI write operations are split from the request'
+ def dmiWriteOperations = objectUnderTest.splitDmiWriteOperationsFromRequest('some id', dataJobWriteRequest).values().iterator().next()
+ then: 'we get the operation ids in the expected order.'
+ assert dmiWriteOperations.operationId == ['1', '2', '3']
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumerSpec.groovy
index 369b496ca..b095f904a 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/DataOperationEventConsumerSpec.groovy
@@ -20,6 +20,8 @@
package org.onap.cps.ncmp.api.impl.async
+import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent
+
import com.fasterxml.jackson.databind.ObjectMapper
import io.cloudevents.CloudEvent
import io.cloudevents.kafka.CloudEventDeserializer
@@ -42,8 +44,6 @@ import org.springframework.test.annotation.DirtiesContext
import org.testcontainers.spock.Testcontainers
import java.time.Duration
-import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent
-
@SpringBootTest(classes = [EventsPublisher, DataOperationEventConsumer, RecordFilterStrategies, JsonObjectMapper, ObjectMapper])
@Testcontainers
@DirtiesContext
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/api/impl/client/DmiRestClientSpec.groovy
index c8e34b1a5..bb73c6879 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/api/impl/client/DmiRestClientSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation
+ * Copyright (C) 2021-2024 Nordix Foundation
* Modifications Copyright (C) 2022 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,89 +24,125 @@ package org.onap.cps.ncmp.api.impl.client
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.NcmpConfiguration
-import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration.DmiProperties;
-import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException
+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.exception.InvalidDmiResourceUrlException
import org.onap.cps.ncmp.utils.TestUtils
-import org.spockframework.spring.SpringBean
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.test.context.SpringBootTest
-import org.springframework.http.HttpEntity
+import org.onap.cps.utils.JsonObjectMapper
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
-import org.springframework.test.context.ContextConfiguration
-import org.springframework.web.client.HttpServerErrorException
-import org.springframework.web.client.RestTemplate
+import org.springframework.web.reactive.function.client.WebClient
+import org.springframework.web.reactive.function.client.WebClientRequestException
+import org.springframework.web.reactive.function.client.WebClientResponseException
+import reactor.core.publisher.Mono
import spock.lang.Specification
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.PATCH
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.PATCH
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
+import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA
+import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.MODEL
-@SpringBootTest
-@ContextConfiguration(classes = [DmiProperties, DmiRestClient, ObjectMapper])
class DmiRestClientSpec extends Specification {
static final NO_AUTH_HEADER = null
- static final BASIC_AUTH_HEADER = 'Basic c29tZS11c2VyOnNvbWUtcGFzc3dvcmQ='
+ static final BASIC_AUTH_HEADER = 'Basic c29tZSB1c2VyOnNvbWUgcGFzc3dvcmQ='
static final BEARER_AUTH_HEADER = 'Bearer my-bearer-token'
- @SpringBean
- RestTemplate mockRestTemplate = Mock(RestTemplate)
+ def mockDataServicesWebClient = Mock(WebClient)
+ def mockModelServicesWebClient = Mock(WebClient)
+ def mockHealthChecksWebClient = Mock(WebClient)
- @Autowired
- NcmpConfiguration.DmiProperties dmiProperties
+ def mockRequestBody = Mock(WebClient.RequestBodyUriSpec)
+ def mockResponse = Mock(WebClient.ResponseSpec)
- @Autowired
- DmiRestClient objectUnderTest
+ def mockDmiProperties = Mock(DmiProperties)
- @Autowired
- ObjectMapper objectMapper
+ JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
- def responseFromRestTemplate = Mock(ResponseEntity)
+ DmiRestClient objectUnderTest = new DmiRestClient(mockDmiProperties, jsonObjectMapper, mockDataServicesWebClient, mockModelServicesWebClient, mockHealthChecksWebClient)
- def 'DMI POST operation with JSON.'() {
- given: 'the rest template returns a valid response entity for the expected parameters'
- mockRestTemplate.postForEntity('my url', _ as HttpEntity, Object.class) >> responseFromRestTemplate
- when: 'POST operation is invoked'
- def result = objectUnderTest.postOperationWithJsonData('my url', 'some json', READ, null)
+ def setup() {
+ mockRequestBody.uri(_) >> mockRequestBody
+ mockRequestBody.headers(_) >> mockRequestBody
+ mockRequestBody.body(_) >> mockRequestBody
+ mockRequestBody.retrieve() >> mockResponse
+ }
+
+ def 'DMI POST Operation with JSON for DMI Data Service '() {
+ given: 'the Data web client returns a valid response entity for the expected parameters'
+ mockDataServicesWebClient.post() >> mockRequestBody
+ mockResponse.toEntity(Object.class) >> Mono.just(new ResponseEntity<>('from Data service', HttpStatus.I_AM_A_TEAPOT))
+ when: 'POST operation is invoked fro Data Service'
+ def response = objectUnderTest.synchronousPostOperationWithJsonData(DATA, '/my/url', 'some json', READ, NO_AUTH_HEADER)
then: 'the output of the method is equal to the output from the test template'
- result == responseFromRestTemplate
+ assert response.statusCode == HttpStatus.I_AM_A_TEAPOT
+ assert response.body == 'from Data service'
}
- def 'Failing DMI POST operation.'() {
- given: 'the rest template returns a valid response entity'
- def serverResponse = 'server response'.getBytes()
- def httpServerErrorException = new HttpServerErrorException(HttpStatus.FORBIDDEN, 'status text', serverResponse, null)
- mockRestTemplate.postForEntity(*_) >> { throw httpServerErrorException }
- when: 'POST operation is invoked'
- def result = objectUnderTest.postOperationWithJsonData('some url', 'some json', operation, null)
- then: 'a Http Client Exception is thrown'
- def thrown = thrown(HttpClientRequestException)
+ def 'DMI POST Operation with JSON for DMI Model Service '() {
+ given: 'the Model web client returns a valid response entity for the expected parameters'
+ mockModelServicesWebClient.post() >> mockRequestBody
+ mockResponse.toEntity(Object.class) >> Mono.just(new ResponseEntity<>('from Model service', HttpStatus.I_AM_A_TEAPOT))
+ when: 'POST operation is invoked for Model Service'
+ def response = objectUnderTest.synchronousPostOperationWithJsonData(MODEL, '/my/url', 'some json', READ, NO_AUTH_HEADER)
+ then: 'the output of the method is equal to the output from the test template'
+ assert response.statusCode == HttpStatus.I_AM_A_TEAPOT
+ assert response.body == 'from Model service'
+ }
+
+ def 'Failing DMI POST operation due to invalid dmi resource url.'() {
+ when: 'POST operation is invoked with invalid dmi resource url'
+ objectUnderTest.synchronousPostOperationWithJsonData(DATA, '/invalid dmi url', null, null, NO_AUTH_HEADER)
+ then: 'invalid dmi resource url exception is thrown'
+ def thrown = thrown(InvalidDmiResourceUrlException)
and: 'the exception has the relevant details from the error response'
- assert thrown.httpStatus == 403
- assert thrown.message == "Unable to ${operation} resource data."
- assert thrown.details == 'server response'
- where: 'the following operation is executed'
+ thrown.httpStatus == 400
+ thrown.message == 'Invalid dmi resource url: /invalid dmi url'
+ where: 'the following operations are executed'
operation << [CREATE, READ, PATCH]
}
+ def 'Dmi service sends client error response when #scenario'() {
+ given: 'the web client unable to return response entity but error'
+ mockDataServicesWebClient.post() >> mockRequestBody
+ mockResponse.toEntity(Object.class) >> Mono.error(exceptionType)
+ when: 'POST operation is invoked'
+ objectUnderTest.synchronousPostOperationWithJsonData(DATA, '/my/url', 'some json', READ, NO_AUTH_HEADER)
+ then: 'a http client exception is thrown'
+ def thrown = thrown(DmiClientRequestException)
+ and: 'the exception has the relevant details from the error response'
+ assert thrown.ncmpResponseStatus == expectedNcmpResponseStatusCode
+ assert thrown.httpStatusCode == httpStatusCode
+ where: 'the following errors occur'
+ scenario | httpStatusCode | exceptionType || expectedNcmpResponseStatusCode
+ 'dmi service unavailable' | 503 | new WebClientRequestException(new RuntimeException('some-error'), null, null, new HttpHeaders()) || DMI_SERVICE_NOT_RESPONDING
+ 'dmi request timeout' | 408 | new WebClientResponseException('message', httpStatusCode, 'statusText', null, null, null) || DMI_SERVICE_NOT_RESPONDING
+ 'dmi server error' | 500 | new WebClientResponseException('message', httpStatusCode, 'statusText', null, null, null) || UNABLE_TO_READ_RESOURCE_DATA
+ 'unknown error' | 500 | new Throwable('message') || UNKNOWN_ERROR
+ }
+
def 'Dmi trust level is determined by spring boot health status'() {
given: 'a health check response'
def dmiPluginHealthCheckResponseJsonData = TestUtils.getResourceFileContent('dmiPluginHealthCheckResponse.json')
- def jsonNode = objectMapper.readValue(dmiPluginHealthCheckResponseJsonData, JsonNode.class)
+ def jsonNode = jsonObjectMapper.convertJsonString(dmiPluginHealthCheckResponseJsonData, JsonNode.class)
((ObjectNode) jsonNode).put('status', 'my status')
- mockRestTemplate.getForObject(*_) >> {jsonNode}
+ mockHealthChecksWebClient.get() >> mockRequestBody
+ mockResponse.bodyToMono(JsonNode.class) >> Mono.just(jsonNode)
when: 'get trust level of the dmi plugin'
- def result = objectUnderTest.getDmiHealthStatus('some url')
- then: 'the status value from the json is return'
+ def result = objectUnderTest.getDmiHealthStatus('some/url')
+ then: 'the status value from the json is returned'
assert result == 'my status'
}
def 'Failing to get dmi plugin health status #scenario'() {
given: 'rest template with #scenario'
- mockRestTemplate.getForObject(*_) >> healthStatusResponse
+ mockHealthChecksWebClient.get() >> mockRequestBody
+ mockResponse.bodyToMono(_) >> healthStatusResponse
when: 'attempt to get health status of the dmi plugin'
def result = objectUnderTest.getDmiHealthStatus('some url')
then: 'result will be empty'
@@ -114,15 +150,18 @@ class DmiRestClientSpec extends Specification {
where: 'the following responses are used'
scenario | healthStatusResponse
'null' | null
- 'exception' | {throw new Exception()}
+ 'exception' | { throw new Exception() }
}
def 'DMI auth header #scenario'() {
when: 'Specific dmi properties are provided'
- dmiProperties.dmiBasicAuthEnabled = authEnabled
+ mockDmiProperties.dmiBasicAuthEnabled >> authEnabled
+ mockDmiProperties.authUsername >> 'some user'
+ mockDmiProperties.authPassword >> 'some password'
then: 'http headers to conditionally have Authorization header'
- def authHeaderValues = objectUnderTest.configureHttpHeaders(new HttpHeaders(), ncmpAuthHeader).getOrEmpty('Authorization')
- def outputAuthHeader = (authHeaderValues == null ? null : authHeaderValues[0])
+ def httpHeaders = new HttpHeaders()
+ objectUnderTest.configureHttpHeaders(httpHeaders, ncmpAuthHeader)
+ def outputAuthHeader = (httpHeaders.Authorization == null ? null : httpHeaders.Authorization[0])
assert outputAuthHeader == expectedAuthHeader
where: 'the following configurations are used'
scenario | authEnabled | ncmpAuthHeader || expectedAuthHeader
@@ -132,5 +171,4 @@ 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
}
-
}
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/api/impl/config/DmiPropertiesSpec.groovy
new file mode 100644
index 000000000..c763c522c
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiPropertiesSpec.groovy
@@ -0,0 +1,37 @@
+/*-
+ * ============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 spock.lang.Specification
+
+class DmiPropertiesSpec extends Specification {
+
+ def objectUnderTest = new DmiProperties()
+
+ def 'Geting dmi base path.'() {
+ given: 'base path of #dmiBasePath'
+ objectUnderTest.dmiBasePath = dmiBasePath
+ expect: 'Preceding and trailing slash wil be removed'
+ assert objectUnderTest.getDmiBasePath() == 'test'
+ where: 'the following dmi base paths are used'
+ dmiBasePath << [ 'test' , '/test', 'test/', '/test/' ]
+ }
+}
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/api/impl/config/DmiWebClientConfigurationSpec.groovy
new file mode 100644
index 000000000..05ecaa11b
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/DmiWebClientConfigurationSpec.groovy
@@ -0,0 +1,68 @@
+/*-
+ * ============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 org.springframework.boot.context.properties.EnableConfigurationProperties
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.TestPropertySource
+import org.springframework.web.reactive.function.client.WebClient
+import spock.lang.Specification
+
+@SpringBootTest
+@ContextConfiguration(classes = [HttpClientConfiguration])
+@TestPropertySource(properties = ['ncmp.dmi.httpclient.data-services.connectionTimeoutInSeconds=1', 'ncmp.dmi.httpclient.model-services.maximumInMemorySizeInMegabytes=1'])
+@EnableConfigurationProperties
+class DmiWebClientConfigurationSpec extends Specification {
+
+ def httpClientConfiguration = Spy(HttpClientConfiguration.class)
+
+ def objectUnderTest = new DmiWebClientConfiguration(httpClientConfiguration)
+
+ def 'Web Client Configuration construction.'() {
+ expect: 'the system can create an instance'
+ new DmiWebClientConfiguration(httpClientConfiguration) != null
+ }
+
+ def 'Creating a web client instance data service.'() {
+ given: 'Web client configuration is invoked'
+ def dataServicesWebClient = objectUnderTest.dataServicesWebClient()
+ expect: 'the system can create an instance for data service'
+ assert dataServicesWebClient != null
+ assert dataServicesWebClient instanceof WebClient
+ }
+
+ def 'Creating a web client instance model service.'() {
+ given: 'Web client configuration invoked'
+ def modelServicesWebClient = objectUnderTest.modelServicesWebClient()
+ expect: 'the system can create an instance for model service'
+ assert modelServicesWebClient != null
+ assert modelServicesWebClient instanceof WebClient
+ }
+
+ def 'Creating a web client instance health service.'() {
+ given: 'Web client configuration invoked'
+ def healthChecksWebClient = objectUnderTest.healthChecksWebClient()
+ expect: 'the system can create an instance for health service'
+ assert healthChecksWebClient != null
+ assert healthChecksWebClient instanceof WebClient
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy
index 2c76b5bb4..228f41277 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/api/impl/config/HttpClientConfigurationSpec.groovy
@@ -1,6 +1,6 @@
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation.
+ * 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.
@@ -17,32 +17,58 @@
* SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
+
package org.onap.cps.ncmp.api.impl.config
-import java.time.Duration
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.TestPropertySource
-import org.springframework.test.context.support.AnnotationConfigContextLoader
import spock.lang.Specification
@SpringBootTest
@ContextConfiguration(classes = [HttpClientConfiguration])
@EnableConfigurationProperties(HttpClientConfiguration.class)
-@TestPropertySource(properties = ["ncmp.dmi.httpclient.connectionTimeoutInSeconds=1", "ncmp.dmi.httpclient.maximumConnectionsTotal=200"])
+@TestPropertySource(properties = ["ncmp.dmi.httpclient.data-services.readTimeoutInSeconds=789", "ncmp.dmi.httpclient.model-services.maximumConnectionsTotal=111"])
class HttpClientConfigurationSpec extends Specification {
@Autowired
private HttpClientConfiguration httpClientConfiguration
- def 'Test HttpClientConfiguration properties with custom and default values'() {
- expect: 'custom property values'
- assert httpClientConfiguration.getConnectionTimeoutInSeconds() == Duration.ofSeconds(1)
- assert httpClientConfiguration.getMaximumConnectionsTotal() == 200
- and: 'default property values'
- assert httpClientConfiguration.getMaximumConnectionsPerRoute() == 50
- assert httpClientConfiguration.getIdleConnectionEvictionThresholdInSeconds() == Duration.ofSeconds(5)
+ 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 writeTimeoutInSeconds == 30
+ assert maximumConnectionsTotal == 100
+ assert pendingAcquireMaxCount == 22
+ assert maximumInMemorySizeInMegabytes == 7
+ }
+ }
+
+ def 'Test http client configuration properties of model with custom and default values'() {
+ expect: 'properties are populated correctly for model'
+ with(httpClientConfiguration.modelServices) {
+ assert connectionTimeoutInSeconds == 456
+ assert readTimeoutInSeconds == 30
+ assert writeTimeoutInSeconds == 30
+ assert maximumConnectionsTotal == 111
+ assert pendingAcquireMaxCount == 44
+ assert maximumInMemorySizeInMegabytes == 8
+ }
+ }
+
+ def 'Test http client configuration properties of health with default values'() {
+ expect: 'properties are populated correctly for health'
+ with(httpClientConfiguration.healthCheckServices) {
+ assert connectionTimeoutInSeconds == 30
+ assert readTimeoutInSeconds == 30
+ assert writeTimeoutInSeconds == 30
+ assert maximumConnectionsTotal == 10
+ assert pendingAcquireMaxCount == 5
+ assert maximumInMemorySizeInMegabytes == 1
+ }
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy
deleted file mode 100644
index 74e342405..000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * 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 org.apache.hc.client5.http.impl.classic.CloseableHttpClient
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.test.context.SpringBootTest
-import org.springframework.boot.web.client.RestTemplateBuilder
-import org.springframework.http.MediaType
-import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
-import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
-import org.springframework.test.context.ContextConfiguration
-import org.springframework.web.client.RestTemplate
-import spock.lang.Specification
-
-@SpringBootTest
-@ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, HttpClientConfiguration])
-class NcmpConfigurationSpec extends Specification{
-
- @Autowired
- NcmpConfiguration.DmiProperties dmiProperties
-
- @Autowired
- HttpClientConfiguration httpClientConfiguration
-
- def mockRestTemplateBuilder = new RestTemplateBuilder()
-
- def 'NcmpConfiguration Construction.'() {
- expect: 'the system can create an instance'
- new NcmpConfiguration() != null
- }
-
- def 'DMI Properties.'() {
- expect: 'properties are set to values in test configuration yaml file'
- dmiProperties.authUsername == 'some-user'
- dmiProperties.authPassword == 'some-password'
- }
-
- def 'Rest Template creation with CloseableHttpClient and MappingJackson2HttpMessageConverter.'() {
- when: 'a rest template is created'
- def result = NcmpConfiguration.restTemplate(mockRestTemplateBuilder, httpClientConfiguration)
- then: 'the rest template is returned'
- assert result instanceof RestTemplate
- and: 'the rest template is created with httpclient5'
- assert result.getRequestFactory() instanceof HttpComponentsClientHttpRequestFactory
- assert ((HttpComponentsClientHttpRequestFactory) result.getRequestFactory()).getHttpClient() instanceof CloseableHttpClient;
- and: 'a jackson media converter has been added'
- def lastMessageConverter = result.getMessageConverters().get(result.getMessageConverters().size()-1)
- lastMessageConverter instanceof MappingJackson2HttpMessageConverter
- and: 'the jackson media converters supports the expected media types'
- lastMessageConverter.getSupportedMediaTypes() == [MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN];
- }
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfigSpec.groovy
new file mode 100644
index 000000000..07395cf5b
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfigSpec.groovy
@@ -0,0 +1,81 @@
+/*
+ * ============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/config/kafka/KafkaConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfigSpec.groovy
index 16f27d081..4d3fd6616 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/api/impl/config/kafka/KafkaConfigSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config.kafka;
+package org.onap.cps.ncmp.api.impl.config.kafka
import io.cloudevents.CloudEvent
import io.cloudevents.kafka.CloudEventDeserializer
@@ -31,12 +31,14 @@ import org.springframework.boot.test.context.SpringBootTest
import org.springframework.kafka.core.KafkaTemplate
import org.springframework.kafka.support.serializer.JsonDeserializer
import org.springframework.kafka.support.serializer.JsonSerializer
+import org.springframework.test.context.TestPropertySource
import spock.lang.Shared
import spock.lang.Specification
@SpringBootTest(classes = [KafkaProperties, KafkaConfig])
@EnableSharedInjection
@EnableConfigurationProperties
+@TestPropertySource(properties = ["cps.tracing.enabled=true"])
class KafkaConfigSpec extends Specification {
@Shared
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDeltaSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDeltaSpec.groovy
index e50652689..75db0bfe5 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDeltaSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDeltaSpec.groovy
@@ -46,4 +46,15 @@ class CmNotificationSubscriptionDeltaSpec extends Specification {
}
+ def 'Find Delta of given list of predicates when it is an ongoing Cm Subscription'() {
+ given: 'A list of predicates'
+ def predicateList = [new DmiCmNotificationSubscriptionPredicate(['ch-1'].toSet(), DatastoreType.PASSTHROUGH_OPERATIONAL, ['a/1/'].toSet())]
+ and: 'its already present'
+ mockCmNotificationSubscriptionPersistenceService.isOngoingCmNotificationSubscription(DatastoreType.PASSTHROUGH_OPERATIONAL, 'ch-1', 'a/1/') >>> true
+ when: 'getDelta is called'
+ def result = objectUnderTest.getDelta(predicateList)
+ then: 'verify correct delta is returned'
+ assert result.size() == 0
+ }
+
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDmiInEventProducerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDmiInEventProducerSpec.groovy
index cfb28a0ad..039a18949 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDmiInEventProducerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDmiInEventProducerSpec.groovy
@@ -25,8 +25,8 @@ import io.cloudevents.CloudEvent
import org.onap.cps.events.EventsPublisher
import org.onap.cps.ncmp.api.impl.events.cmsubscription.producer.CmNotificationSubscriptionDmiInEventProducer
import org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper
+import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmHandle
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmNotificationSubscriptionDmiInEvent
-import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.Cmhandle
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.Data
import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Specification
@@ -43,7 +43,7 @@ class CmNotificationSubscriptionDmiInEventProducerSpec extends Specification {
def subscriptionId = 'test-subscription-id'
def dmiPluginName = 'test-dmiplugin'
def eventType = 'subscriptionCreateRequest'
- def cmNotificationSubscriptionDmiInEvent = new CmNotificationSubscriptionDmiInEvent(data: new Data(cmhandles: [new Cmhandle(cmhandleId: 'test-1', privateProperties: [:])]))
+ def cmNotificationSubscriptionDmiInEvent = new CmNotificationSubscriptionDmiInEvent(data: new Data(cmHandles: [new CmHandle(cmhandleId: 'test-1', privateProperties: [:])]))
and: 'also we have target topic for dmiPlugin'
objectUnderTest.cmNotificationSubscriptionDmiInEventTopic = 'dmiplugin-test-topic'
when: 'the event is published'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDmiOutEventConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDmiOutEventConsumerSpec.groovy
index 488879db7..9b0a48d93 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDmiOutEventConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionDmiOutEventConsumerSpec.groovy
@@ -36,7 +36,6 @@ import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.dmi_to_ncm
import org.onap.cps.ncmp.utils.TestUtils
import org.onap.cps.utils.JsonObjectMapper
import org.slf4j.LoggerFactory
-import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
@@ -108,9 +107,9 @@ class CmNotificationSubscriptionDmiOutEventConsumerSpec extends MessagingBaseSpe
and: 'correct number of calls to publish the ncmp out event to client'
1 * mockCmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionNcmpOutEvent('sub-1', 'subscriptionCreateResponse', _, false)
where: 'the following parameters are used'
- scenario | subscriptionStatus | statusCode || expectedCacheCalls | expectedPersistenceCalls
- 'Accepted Status' | CmNotificationSubscriptionStatus.ACCEPTED | '1' || 1 | 1
- 'Rejected Status' | CmNotificationSubscriptionStatus.REJECTED | '2' || 1 | 0
+ scenario | subscriptionStatus | statusCode || expectedCacheCalls | expectedPersistenceCalls
+ 'Accepted Status' | CmNotificationSubscriptionStatus.ACCEPTED | '1' || 1 | 1
+ 'Rejected Status' | CmNotificationSubscriptionStatus.REJECTED | '104' || 1 | 0
}
def getLoggingEvent() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionNcmpInEventConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionNcmpInEventConsumerSpec.groovy
index 9c84c51b2..01a92c02f 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionNcmpInEventConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/CmNotificationSubscriptionNcmpInEventConsumerSpec.groovy
@@ -72,19 +72,40 @@ class CmNotificationSubscriptionNcmpInEventConsumerSpec extends MessagingBaseSpe
.withSource(URI.create('some-resource'))
.withExtension('correlationid', 'test-cmhandle1').build()
def consumerRecord = new ConsumerRecord<String, CloudEvent>('topic-name', 0, 0, 'event-key', testCloudEventSent)
- and: 'notifications are enabled'
- objectUnderTest.notificationFeatureEnabled = true
when: 'the valid event is consumed'
objectUnderTest.consumeSubscriptionEvent(consumerRecord)
then: 'an event is logged with level INFO'
def loggingEvent = getLoggingEvent()
assert loggingEvent.level == Level.INFO
and: 'the log indicates the task completed successfully'
- assert loggingEvent.formattedMessage == 'Subscription for source some-resource with subscription id test-id ...'
+ assert loggingEvent.formattedMessage == 'Subscription create request for source some-resource with subscription id test-id ...'
and: 'the subscription handler service is called once'
- 1 * mockCmNotificationSubscriptionHandlerService.processSubscriptionCreateRequest(_)
+ 1 * mockCmNotificationSubscriptionHandlerService.processSubscriptionCreateRequest('test-id',_)
}
+ def 'Consume valid CmNotificationSubscriptionNcmpInEvent delete message'() {
+ given: 'a cmNotificationSubscription event'
+ def jsonData = TestUtils.getResourceFileContent('cmSubscription/cmNotificationSubscriptionNcmpInEvent.json')
+ def testEventSent = jsonObjectMapper.convertJsonString(jsonData, CmNotificationSubscriptionNcmpInEvent.class)
+ def testCloudEventSent = CloudEventBuilder.v1()
+ .withData(objectMapper.writeValueAsBytes(testEventSent))
+ .withId('sub-id')
+ .withType('subscriptionDeleteRequest')
+ .withSource(URI.create('some-resource'))
+ .withExtension('correlationid', 'test-cmhandle1').build()
+ def consumerRecord = new ConsumerRecord<String, CloudEvent>('topic-name', 0, 0, 'event-key', testCloudEventSent)
+ when: 'the valid event is consumed'
+ objectUnderTest.consumeSubscriptionEvent(consumerRecord)
+ then: 'an event is logged with level INFO'
+ def loggingEvent = getLoggingEvent()
+ assert loggingEvent.level == Level.INFO
+ 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 * mockCmNotificationSubscriptionHandlerService.processSubscriptionDeleteRequest('test-id',_)
+ }
+
+
def getLoggingEvent() {
return logger.list[1]
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandlerSpec.groovy
index 43568be50..393432fc5 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandlerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/DmiCmNotificationSubscriptionCacheHandlerSpec.groovy
@@ -27,10 +27,10 @@ import org.apache.kafka.clients.consumer.ConsumerRecord
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.CmNotificationSubscriptionStatus
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionDetails
import org.onap.cps.ncmp.api.impl.events.cmsubscription.service.CmNotificationSubscriptionPersistenceService
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.CmNotificationSubscriptionNcmpInEvent
+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.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
@@ -133,10 +133,10 @@ class DmiCmNotificationSubscriptionCacheHandlerSpec extends MessagingBaseSpec {
assert resultMapForDmi2.dmiCmNotificationSubscriptionPredicates[1].targetCmHandleIds == ['ch4'].toSet()
and: 'the list of xpath for each is correct'
assert resultMapForDmi1.dmiCmNotificationSubscriptionPredicates[0].xpaths
- && resultMapForDmi2.dmiCmNotificationSubscriptionPredicates[0].xpaths == ['/x1/y1','x2/y2'].toSet()
+ && resultMapForDmi2.dmiCmNotificationSubscriptionPredicates[0].xpaths == ['/x1/y1','x2/y2'].toSet()
assert resultMapForDmi1.dmiCmNotificationSubscriptionPredicates[1].xpaths
- && resultMapForDmi2.dmiCmNotificationSubscriptionPredicates[1].xpaths == ['/x3/y3','x4/y4'].toSet()
+ && resultMapForDmi2.dmiCmNotificationSubscriptionPredicates[1].xpaths == ['/x3/y3','x4/y4'].toSet()
}
def 'Get map for cm handle IDs by DMI service name'() {
@@ -164,7 +164,7 @@ class DmiCmNotificationSubscriptionCacheHandlerSpec extends MessagingBaseSpec {
}
def 'Persist Cache into database per dmi'() {
- given: 'populate cache'
+ given: 'populated cache'
def predicates = cmNotificationSubscriptionNcmpInEvent.getData().getPredicates()
def subscriptionId = cmNotificationSubscriptionNcmpInEvent.getData().getSubscriptionId()
objectUnderTest.add(subscriptionId, predicates)
@@ -174,15 +174,26 @@ class DmiCmNotificationSubscriptionCacheHandlerSpec extends MessagingBaseSpec {
4 * mockCmNotificationSubscriptionPersistenceService.addCmNotificationSubscription(_,_,_,subscriptionId)
}
+ def 'Remove subscription from database per dmi'() {
+ given: 'populated cache'
+ def predicates = cmNotificationSubscriptionNcmpInEvent.getData().getPredicates()
+ def subscriptionId = cmNotificationSubscriptionNcmpInEvent.getData().getSubscriptionId()
+ objectUnderTest.add(subscriptionId, predicates)
+ when: 'subscription is persisted in database'
+ objectUnderTest.removeFromDatabasePerDmi(subscriptionId,'dmi-1')
+ then: 'persistence service is called the correct number of times per dmi'
+ 4 * mockCmNotificationSubscriptionPersistenceService.removeCmNotificationSubscription(_,_,_,subscriptionId)
+ }
+
def setUpTestEvent(){
def jsonData = TestUtils.getResourceFileContent('cmSubscription/cmNotificationSubscriptionNcmpInEvent.json')
def testEventSent = jsonObjectMapper.convertJsonString(jsonData, CmNotificationSubscriptionNcmpInEvent.class)
def testCloudEventSent = CloudEventBuilder.v1()
- .withData(objectMapper.writeValueAsBytes(testEventSent))
- .withId('subscriptionCreated')
- .withType('subscriptionCreated')
- .withSource(URI.create('some-resource'))
- .withExtension('correlationid', 'test-cmhandle1').build()
+ .withData(objectMapper.writeValueAsBytes(testEventSent))
+ .withId('subscriptionCreated')
+ .withType('subscriptionCreated')
+ .withSource(URI.create('some-resource'))
+ .withExtension('correlationid', 'test-cmhandle1').build()
def consumerRecord = new ConsumerRecord<String, CloudEvent>('topic-name', 0, 0, 'event-key', testCloudEventSent)
def cloudEvent = consumerRecord.value()
@@ -191,10 +202,10 @@ class DmiCmNotificationSubscriptionCacheHandlerSpec extends MessagingBaseSpec {
def initialiseMockInventoryPersistenceResponses(){
mockInventoryPersistence.getYangModelCmHandles(['ch1','ch2'])
- >> [yangModelCmHandle1, yangModelCmHandle2]
+ >> [yangModelCmHandle1, yangModelCmHandle2]
mockInventoryPersistence.getYangModelCmHandles(['ch3','ch4'])
- >> [yangModelCmHandle3, yangModelCmHandle4]
+ >> [yangModelCmHandle3, yangModelCmHandle4]
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapperSpec.groovy
index 763aedaa0..0c9e3b691 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapperSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapperSpec.groovy
@@ -22,8 +22,8 @@ package org.onap.cps.ncmp.api.impl.events.cmsubscription.mapper
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionPredicate
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import spock.lang.Specification
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL
@@ -48,10 +48,10 @@ class CmNotificationSubscriptionDmiInEventMapperSpec extends Specification {
when: 'we try to map the values'
def result = objectUnderTest.toCmNotificationSubscriptionDmiInEvent(dmiCmNotificationSubscriptionPredicates)
then: 'it contains correct cm notification subscription cmhandle object'
- assert result.data.cmhandles.cmhandleId.containsAll(['ch-1', 'ch-2'])
- assert result.data.cmhandles.privateProperties.containsAll([['k1': 'v1'], ['k2': 'v2']])
+ assert result.data.cmHandles.cmhandleId.containsAll(['ch-1', 'ch-2'])
+ assert result.data.cmHandles.privateProperties.containsAll([['k1': 'v1'], ['k2': 'v2']])
and: 'also has the correct dmi cm notification subscription predicates'
assert result.data.predicates.targetFilter.containsAll([['ch-1'], ['ch-2']])
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImplSpec.groovy
index 98b4ee267..982150ec0 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImplSpec.groovy
@@ -25,10 +25,10 @@ import org.onap.cps.ncmp.api.impl.events.cmsubscription.CmNotificationSubscripti
import org.onap.cps.ncmp.api.impl.events.cmsubscription.CmNotificationSubscriptionEventsHandler
import org.onap.cps.ncmp.api.impl.events.cmsubscription.CmNotificationSubscriptionMappersHandler
import org.onap.cps.ncmp.api.impl.events.cmsubscription.DmiCmNotificationSubscriptionCacheHandler
-import org.onap.cps.ncmp.api.impl.events.cmsubscription.mapper.CmNotificationSubscriptionDmiInEventMapper
-import org.onap.cps.ncmp.api.impl.events.cmsubscription.mapper.CmNotificationSubscriptionNcmpOutEventMapper
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.CmNotificationSubscriptionStatus
import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionDetails
+import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionPredicate
+import org.onap.cps.ncmp.api.impl.operations.DatastoreType
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.CmNotificationSubscriptionNcmpInEvent
import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmNotificationSubscriptionDmiInEvent
import org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.ncmp_to_client.CmNotificationSubscriptionNcmpOutEvent
@@ -50,13 +50,16 @@ class CmNotificationSubscriptionHandlerServiceImplSpec extends Specification{
mockCmNotificationSubscriptionEventsHandler, mockDmiCmNotificationSubscriptionCacheHandler)
def testSubscriptionDetailsMap = ["dmi-1":new DmiCmNotificationSubscriptionDetails([], CmNotificationSubscriptionStatus.PENDING)]
- def testListOfDeltaPredicates = []
def 'Consume valid and unique CmNotificationSubscriptionNcmpInEvent create message'() {
given: 'a cmNotificationSubscriptionNcmp in event with unique subscription id'
def jsonData = TestUtils.getResourceFileContent('cmSubscription/cmNotificationSubscriptionNcmpInEvent.json')
def testEventConsumed = jsonObjectMapper.convertJsonString(jsonData, CmNotificationSubscriptionNcmpInEvent.class)
+ def testListOfDeltaPredicates = [new DmiCmNotificationSubscriptionPredicate(['ch1'].toSet(), DatastoreType.PASSTHROUGH_OPERATIONAL, ['/a/b'].toSet())]
mockCmNotificationSubscriptionPersistenceService.isUniqueSubscriptionId("test-id") >> true
+ 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 * mockDmiCmNotificationSubscriptionCacheHandler.get("test-id") >> testSubscriptionDetailsMap
and: 'the delta predicates is returned'
@@ -66,7 +69,7 @@ class CmNotificationSubscriptionHandlerServiceImplSpec extends Specification{
1 * mockCmNotificationSubscriptionMappersHandler
.toCmNotificationSubscriptionDmiInEvent(testListOfDeltaPredicates) >> testDmiInEvent
when: 'the valid and unique event is consumed'
- objectUnderTest.processSubscriptionCreateRequest(testEventConsumed)
+ objectUnderTest.processSubscriptionCreateRequest(subscriptionId, predicates)
then: 'the subscription cache handler is called once'
1 * mockDmiCmNotificationSubscriptionCacheHandler.add('test-id',_)
and: 'the events handler method to publish DMI event is called correct number of times with the correct parameters'
@@ -77,21 +80,68 @@ class CmNotificationSubscriptionHandlerServiceImplSpec extends Specification{
"test-id", "subscriptionCreateResponse", null, true)
}
+ def 'Consume valid and Overlapping Cm Notification Subscription NcmpIn Event'() {
+ given: 'a cmNotificationSubscriptionNcmp in event with unique subscription id'
+ def jsonData = TestUtils.getResourceFileContent('cmSubscription/cmNotificationSubscriptionNcmpInEvent.json')
+ def testEventConsumed = jsonObjectMapper.convertJsonString(jsonData, CmNotificationSubscriptionNcmpInEvent.class)
+ def noDeltaPredicates = []
+ mockCmNotificationSubscriptionPersistenceService.isUniqueSubscriptionId("test-id") >> true
+ and: 'the cache handler returns for relevant subscription id'
+ 1 * mockDmiCmNotificationSubscriptionCacheHandler.get("test-id") >> testSubscriptionDetailsMap
+ and: 'the delta predicates is returned'
+ 1 * mockCmNotificationSubscriptionDelta.getDelta(_) >> noDeltaPredicates
+ when: 'the valid and unique event is consumed'
+ objectUnderTest.processSubscriptionCreateRequest('test-id', noDeltaPredicates)
+ then: 'the subscription cache handler is called once'
+ 1 * mockDmiCmNotificationSubscriptionCacheHandler.add('test-id', _)
+ and: 'the subscription details are updated in the cache'
+ 1 * mockDmiCmNotificationSubscriptionCacheHandler.updateDmiCmNotificationSubscriptionStatusPerDmi('test-id', _, CmNotificationSubscriptionStatus.ACCEPTED)
+ and: 'we schedule to send the response after configured time from the cache'
+ 1 * mockCmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionNcmpOutEvent(
+ "test-id", "subscriptionCreateResponse", null, true)
+ }
+
def 'Consume valid and but non-unique CmNotificationSubscription create message'() {
given: 'a cmNotificationSubscriptionNcmp in event'
def jsonData = TestUtils.getResourceFileContent('cmSubscription/cmNotificationSubscriptionNcmpInEvent.json')
def testEventConsumed = jsonObjectMapper.convertJsonString(jsonData, CmNotificationSubscriptionNcmpInEvent.class)
mockCmNotificationSubscriptionPersistenceService.isUniqueSubscriptionId('test-id') >> false
+ and: 'relevant details is extracted from the event'
+ def subscriptionId = testEventConsumed.getData().getSubscriptionId()
+ def predicates = testEventConsumed.getData().getPredicates()
and: 'the NCMP out in event mapper returns an event for rejected request'
def testNcmpOutEvent = new CmNotificationSubscriptionNcmpOutEvent()
1 * mockCmNotificationSubscriptionMappersHandler.toCmNotificationSubscriptionNcmpOutEventForRejectedRequest(
"test-id",_) >> testNcmpOutEvent
when: 'the valid but non-unique event is consumed'
- objectUnderTest.processSubscriptionCreateRequest(testEventConsumed)
+ objectUnderTest.processSubscriptionCreateRequest(subscriptionId, predicates)
then: 'the events handler method to publish DMI event is never called'
0 * mockCmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionDmiInEvent(_,_,_,_)
and: 'the events handler method to publish NCMP out event is called once'
1 * mockCmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionNcmpOutEvent(
'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, CmNotificationSubscriptionNcmpInEvent.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 * mockDmiCmNotificationSubscriptionCacheHandler.get('test-id') >> testSubscriptionDetailsMap
+ when: 'the valid and unique event is consumed'
+ objectUnderTest.processSubscriptionDeleteRequest(subscriptionId, predicates)
+ then: 'the subscription cache handler is called once'
+ 1 * mockDmiCmNotificationSubscriptionCacheHandler.add('test-id', predicates)
+ and: 'the mapper handler to get DMI in event is called once'
+ 1 * mockCmNotificationSubscriptionMappersHandler.toCmNotificationSubscriptionDmiInEvent(_)
+ and: 'the events handler method to publish DMI event is called correct number of times with the correct parameters'
+ testSubscriptionDetailsMap.size() * mockCmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionDmiInEvent(
+ 'test-id', 'dmi-1', 'subscriptionDeleteRequest', _)
+ and: 'we schedule to send the response after configured time from the cache'
+ 1 * mockCmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionNcmpOutEvent(
+ 'test-id', 'subscriptionDeleteResponse', null, true)
+ }
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImplSpec.groovy
index b51ecb0cf..281ec4f7e 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionPersistenceServiceImplSpec.groovy
@@ -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.
@@ -23,9 +24,8 @@ package org.onap.cps.ncmp.api.impl.events.cmsubscription.service
import org.onap.cps.utils.ContentType
import static org.onap.cps.ncmp.api.impl.events.cmsubscription.service.CmNotificationSubscriptionPersistenceServiceImpl.CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_ID;
-import static org.onap.cps.ncmp.api.impl.events.cmsubscription.service.CmNotificationSubscriptionPersistenceServiceImpl.CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_AND_CMHANDLE;
+import static org.onap.cps.ncmp.api.impl.events.cmsubscription.service.CmNotificationSubscriptionPersistenceServiceImpl.CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE;
import static org.onap.cps.ncmp.api.impl.events.cmsubscription.service.CmNotificationSubscriptionPersistenceServiceImpl.CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH;
-
import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsQueryService
import org.onap.cps.ncmp.api.impl.operations.DatastoreType
@@ -48,7 +48,7 @@ class CmNotificationSubscriptionPersistenceServiceImplSpec extends Specification
def cpsPathQuery = "/datastores/datastore[@name='ncmp-datastore:passthrough-running']/cm-handles/cm-handle[@id='ch-1']/filters/filter[@xpath='/cps/path']";
and: 'datanodes optionally returned'
1 * mockCpsQueryService.queryDataNodes('NCMP-Admin', 'cm-data-subscriptions',
- cpsPathQuery, FetchDescendantsOption.OMIT_DESCENDANTS) >> dataNode
+ cpsPathQuery, FetchDescendantsOption.OMIT_DESCENDANTS) >> dataNode
when: 'we check for an ongoing cm subscription'
def response = objectUnderTest.isOngoingCmNotificationSubscription(DatastoreType.PASSTHROUGH_RUNNING, 'ch-1', '/cps/path')
then: 'we get expected response'
@@ -64,7 +64,7 @@ class CmNotificationSubscriptionPersistenceServiceImplSpec extends Specification
def cpsPathQuery = CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_ID.formatted('some-sub')
and: 'relevant datanodes are returned'
1 * mockCpsQueryService.queryDataNodes('NCMP-Admin', 'cm-data-subscriptions', cpsPathQuery, FetchDescendantsOption.OMIT_DESCENDANTS) >>
- dataNodes
+ dataNodes
when: 'a subscription ID is tested for uniqueness'
def result = objectUnderTest.isUniqueSubscriptionId('some-sub')
then: 'result is as expected'
@@ -79,7 +79,7 @@ class CmNotificationSubscriptionPersistenceServiceImplSpec extends Specification
given: 'a valid cm subscription path query'
def cpsPathQuery =CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH.formatted('ncmp-datastore:passthrough-running', 'ch-1', '/x/y')
and: 'a dataNode exists for the given cps path query'
- mockCpsQueryService.queryDataNodes('NCMP-Admin', 'cm-data-subscriptions',
+ mockCpsQueryService.queryDataNodes('NCMP-Admin', 'cm-data-subscriptions',
cpsPathQuery, FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(xpath: cpsPathQuery, leaves: ['xpath': '/x/y','subscriptionIds': ['sub-1']])]
when: 'the method to add/update cm notification subscription is called'
objectUnderTest.addCmNotificationSubscription(DatastoreType.PASSTHROUGH_RUNNING, 'ch-1','/x/y', 'newSubId')
@@ -88,18 +88,18 @@ class CmNotificationSubscriptionPersistenceServiceImplSpec extends Specification
'NCMP-Admin',
'cm-data-subscriptions',
'/datastores/datastore[@name=\'ncmp-datastore:passthrough-running\']/cm-handles/cm-handle[@id=\'ch-1\']/filters',
- objectUnderTest.getSubscriptionDetailsAsJson('/x/y', ['sub-1','newSubId']), _)
+ objectUnderTest.getSubscriptionDetailsAsJson('/x/y', ['sub-1','newSubId']), _,ContentType.JSON)
}
def 'Add new cm notification subscription for #datastoreType'() {
given: 'a valid cm subscription path query'
def cmSubscriptionCpsPathQuery = CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH.formatted(datastoreName, 'ch-1', '/x/y')
- def cmHandleForSubscriptionPathQuery = CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_AND_CMHANDLE.formatted(datastoreName, 'ch-1')
+ def cmHandleForSubscriptionPathQuery = CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE.formatted(datastoreName, 'ch-1')
and: 'a parent node xpath for the cm subscription path above'
def parentNodeXpath = '/datastores/datastore[@name=\'%s\']/cm-handles'
and: 'a datanode does not exist for cm subscription path query'
mockCpsQueryService.queryDataNodes('NCMP-Admin', 'cm-data-subscriptions',
- cmSubscriptionCpsPathQuery,
+ cmSubscriptionCpsPathQuery,
FetchDescendantsOption.OMIT_DESCENDANTS) >> []
and: 'a datanode does not exist for the given cm handle subscription path query'
mockCpsQueryService.queryDataNodes('NCMP-Admin', 'cm-data-subscriptions',
@@ -124,7 +124,7 @@ class CmNotificationSubscriptionPersistenceServiceImplSpec extends Specification
def 'Add new cm notification subscription when xpath does not exist for existing subscription cm handle'() {
given: 'a valid cm subscription path query'
def cmSubscriptionCpsPathQuery = CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH.formatted(datastoreName, 'ch-1', '/x/y')
- def cmHandleForSubscriptionPathQuery = CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_AND_CMHANDLE.formatted(datastoreName, 'ch-1')
+ def cmHandleForSubscriptionPathQuery = CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE.formatted(datastoreName, 'ch-1')
and: 'a parent node xpath for given cm handle for subscription path above'
def parentNodeXpath = '/datastores/datastore[@name=\'%s\']/cm-handles/cm-handle[@id=\'%s\']/filters'
and: 'a datanode does not exist for cm subscription path query'
@@ -157,19 +157,36 @@ class CmNotificationSubscriptionPersistenceServiceImplSpec extends Specification
then: 'the list of subscribers is updated'
1 * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'cm-data-subscriptions',
'/datastores/datastore[@name=\'ncmp-datastore:passthrough-running\']/cm-handles/cm-handle[@id=\'ch-1\']/filters',
- objectUnderTest.getSubscriptionDetailsAsJson('/x/y', ['sub-2']), _)
+ objectUnderTest.getSubscriptionDetailsAsJson('/x/y', ['sub-2']), _, ContentType.JSON)
}
- def 'Removing last ongoing subscription for datastore, cmhandle and xpath'(){
+ def 'Removing last ongoing subscription for datastore and cmhandle and xpath'(){
given: 'a subscription exists when queried but has only 1 subscriber'
- def cpsPathQuery = CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH.formatted('ncmp-datastore:passthrough-running', 'ch-1', '/x/y')
- mockCpsQueryService.queryDataNodes('NCMP-Admin', 'cm-data-subscriptions',
- cpsPathQuery, FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(xpath: cpsPathQuery, leaves: ['xpath': '/x/y','subscriptionIds': ['sub-1']])]
+ mockCpsQueryService.queryDataNodes(
+ 'NCMP-Admin',
+ 'cm-data-subscriptions',
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_WITH_DATASTORE_CMHANDLE_AND_XPATH.formatted('ncmp-datastore:passthrough-running', 'ch-1', '/x/y'),
+ FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['xpath': '/x/y','subscriptionIds': ['sub-1']])]
+ and: 'the #scenario'
+ mockCpsQueryService.queryDataNodes(
+ 'NCMP-Admin',
+ 'cm-data-subscriptions',
+ CPS_PATH_QUERY_FOR_CM_SUBSCRIPTION_FILTERS_WITH_DATASTORE_AND_CMHANDLE.formatted('ncmp-datastore:passthrough-running', 'ch-1'),
+ FetchDescendantsOption.DIRECT_CHILDREN_ONLY) >> [new DataNode(childDataNodes: listOfChildNodes)]
when: 'that last ongoing subscription is removed'
objectUnderTest.removeCmNotificationSubscription(DatastoreType.PASSTHROUGH_RUNNING, 'ch-1', '/x/y', 'sub-1')
then: 'the subscription with empty subscriber list is removed'
1 * mockCpsDataService.deleteDataNode('NCMP-Admin', 'cm-data-subscriptions',
'/datastores/datastore[@name=\'ncmp-datastore:passthrough-running\']/cm-handles/cm-handle[@id=\'ch-1\']/filters/filter[@xpath=\'/x/y\']',
_)
+ and: 'method call to delete the cm handle is called the correct number of times'
+ numberOfCallsToDeleteCmHandle * mockCpsDataService.deleteDataNode('NCMP-Admin', 'cm-data-subscriptions',
+ '/datastores/datastore[@name=\'ncmp-datastore:passthrough-running\']/cm-handles/cm-handle[@id=\'ch-1\']',
+ _)
+ where:
+ scenario | listOfChildNodes || numberOfCallsToDeleteCmHandle
+ 'cm handle in same datastore is used for other subscriptions' | [new DataNode()] || 0
+ 'cm handle in same datastore is NOT used for other subscriptions' | [] || 1
}
+
} \ No newline at end of file
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy
index 3ae95209f..1adf01c55 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy
@@ -20,19 +20,19 @@
package org.onap.cps.ncmp.api.impl.events.lcm
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.ADVISED
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETED
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETING
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.LOCKED
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.READY
-import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_SYNC_FAILED
-
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
+import org.onap.cps.ncmp.api.inventory.models.CompositeState
+import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import spock.lang.Specification
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETED
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETING
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.LOCKED
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY
+import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_SYNC_FAILED
+
class LcmEventsCmHandleStateHandlerImplSpec extends Specification {
def mockInventoryPersistence = Mock(InventoryPersistence)
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorSpec.groovy
index bef2963cf..36024b74e 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/lcm/LcmEventsCreatorSpec.groovy
@@ -20,17 +20,17 @@
package org.onap.cps.ncmp.api.impl.events.lcm
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.ADVISED
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.DELETING
-import static org.onap.cps.ncmp.api.impl.inventory.CmHandleState.READY
-
import org.mapstruct.factory.Mappers
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.api.inventory.models.CompositeState
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
import org.onap.cps.ncmp.events.lcm.v1.Values
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
import spock.lang.Specification
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.DELETING
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY
+
class LcmEventsCreatorSpec extends Specification {
LcmEventHeaderMapper lcmEventsHeaderMapper = Mappers.getMapper(LcmEventHeaderMapper)
@@ -190,4 +190,4 @@ class LcmEventsCreatorSpec extends Specification {
'blank target and existing values' | '' | '' | '' | '' | '' | ''
'new target value and blank existing values' | '' | 'someAlternateId' | '' | 'someAlternateId' | '' | 'someDataProducerIdentifier'
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DatastoreTypeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DatastoreTypeSpec.groovy
new file mode 100644
index 000000000..7e364c97c
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DatastoreTypeSpec.groovy
@@ -0,0 +1,46 @@
+/*
+ * ============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.operations
+
+import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException
+import spock.lang.Specification
+
+class DatastoreTypeSpec extends Specification {
+
+ def 'Converting string to enum.'() {
+ expect: 'converting string to enum results in the correct enum value'
+ DatastoreType.fromDatastoreName(datastoreName) == expectedEnum
+ where: 'the following datastore names are used'
+ datastoreName || expectedEnum
+ 'ncmp-datastore:operational' || DatastoreType.OPERATIONAL
+ 'ncmp-datastore:passthrough-running' || DatastoreType.PASSTHROUGH_RUNNING
+ 'ncmp-datastore:passthrough-operational' || DatastoreType.PASSTHROUGH_OPERATIONAL
+ }
+
+ def 'Converting unknown name string to enum.'() {
+ when: 'attempt converting unknown datastore name'
+ DatastoreType.fromDatastoreName('unknown')
+ then: 'an invalid datastore exception is thrown'
+ def thrown = thrown(InvalidDatastoreException)
+ assert thrown.message.contains('unknown is an invalid datastore')
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
index eb6c7a0f4..1e877f4a8 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
@@ -23,13 +23,13 @@ package org.onap.cps.ncmp.api.impl.operations
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
-import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException
-import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder
+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.models.DataOperationRequest
import org.onap.cps.ncmp.api.models.CmResourceAddress
+import org.onap.cps.ncmp.api.models.DataOperationRequest
import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent
+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
@@ -38,29 +38,27 @@ import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.test.context.ContextConfiguration
+import reactor.core.publisher.Mono
import spock.lang.Shared
-import java.util.concurrent.TimeoutException
-
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL
import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING
import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
import static org.onap.cps.ncmp.api.impl.operations.OperationType.UPDATE
+import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA
@SpringBootTest
-@ContextConfiguration(classes = [EventsPublisher, CpsApplicationContext, NcmpConfiguration.DmiProperties, DmiDataOperations])
+@ContextConfiguration(classes = [EventsPublisher, CpsApplicationContext, DmiProperties, DmiDataOperations])
class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
- @SpringBean
- DmiServiceUrlBuilder dmiServiceUrlBuilder = Mock()
def dmiServiceBaseUrl = "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/data/ds/ncmp-datastore:"
def NO_TOPIC = null
def NO_REQUEST_ID = null
def NO_AUTH_HEADER = null
+
@Shared
def OPTIONS_PARAM = '(a=1,b=2)'
@@ -77,23 +75,24 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
given: 'a cm handle for #cmHandleId'
mockYangModelCmHandleRetrieval(dmiProperties)
and: 'a positive response from DMI service when it is called with the expected parameters'
- def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
- def expectedUrl = dmiServiceBaseUrl + "${expectedDatastoreInUrl}?resourceIdentifier=${resourceIdentifier}${expectedOptionsInUrl}"
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, READ, NO_AUTH_HEADER) >> responseFromDmi
- dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
+ def responseFromDmi = Mono.just(new ResponseEntity<Object>('{some-key:some-value}', HttpStatus.OK))
+ def expectedUrl = "${dmiServiceBaseUrl}${expectedDatastoreInUrl}?resourceIdentifier=${resourceIdentifier}${expectedOptionsInUrl}"
+ def expectedJson = '{"operation":"read","cmHandleProperties":' + expectedProperties + ',"moduleSetTag":""}'
+ mockDmiRestClient.asynchronousPostOperationWithJsonData(DATA, expectedUrl, expectedJson, READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get resource data is invoked'
def cmResourceAddress = new CmResourceAddress(dataStore.datastoreName, cmHandleId, resourceIdentifier)
- def result = objectUnderTest.getResourceDataFromDmi(cmResourceAddress, options, NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER)
+ def result = objectUnderTest.getResourceDataFromDmi(cmResourceAddress, options, NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER).block()
then: 'the result is the response from the DMI service'
- assert result == responseFromDmi
+ assert result.body == '{some-key:some-value}'
+ assert result.statusCode.'2xxSuccessful'
where: 'the following parameters are used'
- scenario | dmiProperties | dataStore | options || expectedJson | expectedDatastoreInUrl | expectedOptionsInUrl
- 'without properties' | [] | PASSTHROUGH_OPERATIONAL | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-operational' | '&options=(a=1,b=2)'
- 'with properties' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '&options=(a=1,b=2)'
- 'null options' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | null || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | ''
- 'empty options' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | '' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | ''
- 'datastore running without properties' | [] | PASSTHROUGH_RUNNING | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-running' | '&options=(a=1,b=2)'
- 'datastore running with properties' | [yangModelCmHandleProperty] | PASSTHROUGH_RUNNING | OPTIONS_PARAM || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-running' | '&options=(a=1,b=2)'
+ scenario | dmiProperties | dataStore | options || expectedProperties | expectedDatastoreInUrl | expectedOptionsInUrl
+ 'without properties' | [] | PASSTHROUGH_OPERATIONAL | OPTIONS_PARAM || '{}' | 'passthrough-operational' | '&options=(a%3D1,b%3D2)'
+ 'with properties' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | OPTIONS_PARAM || '{"prop1":"val1"}' | 'passthrough-operational' | '&options=(a%3D1,b%3D2)'
+ 'null options' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | null || '{"prop1":"val1"}' | 'passthrough-operational' | ''
+ 'empty options' | [yangModelCmHandleProperty] | PASSTHROUGH_OPERATIONAL | '' || '{"prop1":"val1"}' | 'passthrough-operational' | ''
+ 'datastore running without properties' | [] | PASSTHROUGH_RUNNING | OPTIONS_PARAM || '{}' | 'passthrough-running' | '&options=(a%3D1,b%3D2)'
+ 'datastore running with properties' | [yangModelCmHandleProperty] | PASSTHROUGH_RUNNING | OPTIONS_PARAM || '{"prop1":"val1"}' | 'passthrough-running' | '&options=(a%3D1,b%3D2)'
}
def 'Execute (async) data operation from DMI service.'() {
@@ -103,49 +102,48 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def dataOperationRequest = spiedJsonObjectMapper.convertJsonString(dataOperationBatchRequestJsonData, DataOperationRequest.class)
dataOperationRequest.dataOperationDefinitions[0].cmHandleIds = [cmHandleId]
and: 'a positive response from DMI service when it is called with valid request parameters'
- def responseFromDmi = new ResponseEntity<Object>(HttpStatus.ACCEPTED)
- def expectedDmiBatchResourceDataUrl = "ncmp/v1/data/topic=my-topic-name"
- def expectedBatchRequestAsJson = '{"operations":[{"operation":"read","operationId":"operational-14","datastore":"ncmp-datastore:passthrough-operational","options":"some option","resourceIdentifier":"some resource identifier","cmHandles":[{"id":"some-cm-handle","cmHandleProperties":{"prop1":"val1"}}]}]}'
- mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, _, READ.operationName, NO_AUTH_HEADER) >> responseFromDmi
- dmiServiceUrlBuilder.getDataOperationRequestUrl(_, _) >> expectedDmiBatchResourceDataUrl
- when: 'get resource data for group of cm handles are invoked'
+ def responseFromDmi = Mono.just(new ResponseEntity<Object>(HttpStatus.ACCEPTED))
+ def expectedDmiBatchResourceDataUrl = "someServiceName/dmi/v1/data?requestId=requestId&topic=my-topic-name"
+ def expectedBatchRequestAsJson = '{"operations":[{"operation":"read","operationId":"operational-14","datastore":"ncmp-datastore:passthrough-operational","options":"some option","resourceIdentifier":"some resource identifier","cmHandles":[{"id":"some-cm-handle","moduleSetTag":"","cmHandleProperties":{"prop1":"val1"}}]}]}'
+ mockDmiRestClient.asynchronousPostOperationWithJsonData(DATA, expectedDmiBatchResourceDataUrl, _, READ, NO_AUTH_HEADER) >> responseFromDmi
+ when: 'get resource data for group of cm handles is invoked'
objectUnderTest.requestResourceDataFromDmi('my-topic-name', dataOperationRequest, 'requestId', NO_AUTH_HEADER)
- then: 'the post operation was called and ncmp generated dmi request body json args'
- 1 * mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, expectedBatchRequestAsJson, READ, NO_AUTH_HEADER)
+ then: 'the post operation was called with the expected URL and JSON request body'
+ 1 * mockDmiRestClient.asynchronousPostOperationWithJsonData(DATA, expectedDmiBatchResourceDataUrl, expectedBatchRequestAsJson, READ, NO_AUTH_HEADER)
}
- def 'Execute (async) data operation from DMI service for #scenario.'() {
- given: 'data operation request body and dmi resource url'
- def dmiDataOperation = DmiDataOperation.builder().operationId('some-operation-id').build()
- dmiDataOperation.getCmHandles().add(CmHandle.builder().id('some-cm-handle-id').build())
- def dmiDataOperationResourceDataUrl = "http://dmi-service-name:dmi-port/dmi/v1/data?topic=my-topic-name&requestId=some-request-id"
+ def 'Execute (async) data operation from DMI service with Exception.'() {
+ given: 'collection of yang model cm Handles and data operation request'
+ mockYangModelCmHandleCollectionRetrieval([yangModelCmHandleProperty])
+ def dataOperationBatchRequestJsonData = TestUtils.getResourceFileContent('dataOperationRequest.json')
+ def dataOperationRequest = spiedJsonObjectMapper.convertJsonString(dataOperationBatchRequestJsonData, DataOperationRequest.class)
+ dataOperationRequest.dataOperationDefinitions[0].cmHandleIds = [cmHandleId]
+ and: 'the published cloud event will be captured'
def actualDataOperationCloudEvent = null
- when: 'exception occurs after sending request to dmi service'
- objectUnderTest.handleTaskCompletionException(new Throwable(exception), dmiDataOperationResourceDataUrl, List.of(dmiDataOperation))
- then: 'a cloud event is published'
- eventsPublisher.publishCloudEvent('my-topic-name', 'some-request-id', _) >> { args -> actualDataOperationCloudEvent = args[2] }
- and: 'the event contains the expected error details'
+ eventsPublisher.publishCloudEvent('my-topic-name', 'my-request-id', _) >> { args -> actualDataOperationCloudEvent = args[2] }
+ and: 'a DMI client request exception is thrown when DMI service is called'
+ mockDmiRestClient.asynchronousPostOperationWithJsonData(*_) >> { Mono.error(new DmiClientRequestException(123, '', '', UNKNOWN_ERROR)) }
+ when: 'attempt to get resource data for group of cm handles is invoked'
+ objectUnderTest.requestResourceDataFromDmi('my-topic-name', dataOperationRequest, 'my-request-id', NO_AUTH_HEADER)
+ then: 'the event contains the expected error details'
def eventDataValue = extractDataValue(actualDataOperationCloudEvent)
- assert eventDataValue.operationId == dmiDataOperation.operationId
- assert eventDataValue.ids == dmiDataOperation.cmHandles.id
- assert eventDataValue.statusCode == responseCode.code
- assert eventDataValue.statusMessage == responseCode.message
- where: 'the following exceptions are occurred'
- scenario | exception || responseCode
- 'http client request exception' | new HttpClientRequestException('error-message', 'error-details', HttpStatus.SERVICE_UNAVAILABLE.value()) || UNABLE_TO_READ_RESOURCE_DATA
- 'timeout exception' | new TimeoutException() || DMI_SERVICE_NOT_RESPONDING
+ assert eventDataValue.statusCode == '108'
+ assert eventDataValue.statusMessage == UNKNOWN_ERROR.message
+ and: 'the event contains the correct operation details'
+ assert eventDataValue.operationId == dataOperationRequest.dataOperationDefinitions[0].operationId
+ assert eventDataValue.ids == dataOperationRequest.dataOperationDefinitions[0].cmHandleIds
}
def 'call get all resource data.'() {
- given: 'the system returns a cm handle with a sample property'
- mockYangModelCmHandleRetrieval([yangModelCmHandleProperty])
+ given: 'the system returns a cm handle with a sample property and sample module set tag'
+ mockYangModelCmHandleRetrieval([yangModelCmHandleProperty], 'my-module-set-tag')
and: 'a positive response from DMI service when it is called with the expected parameters'
def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
def expectedUrl = dmiServiceBaseUrl + "passthrough-operational?resourceIdentifier=/"
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}', READ, null) >> responseFromDmi
- dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
+ def expectedJson = '{"operation":"read","cmHandleProperties":{"prop1":"val1"},"moduleSetTag":"my-module-set-tag"}'
+ mockDmiRestClient.synchronousPostOperationWithJsonData(DATA, expectedUrl, expectedJson, READ, null) >> responseFromDmi
when: 'get resource data is invoked'
- def result = objectUnderTest.getResourceDataFromDmi( PASSTHROUGH_OPERATIONAL.datastoreName, cmHandleId, NO_REQUEST_ID)
+ def result = objectUnderTest.getAllResourceDataFromDmi(cmHandleId, NO_REQUEST_ID)
then: 'the result is the response from the DMI service'
assert result == responseFromDmi
}
@@ -154,11 +152,10 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
given: 'a cm handle for #cmHandleId'
mockYangModelCmHandleRetrieval([yangModelCmHandleProperty])
and: 'a positive response from DMI service when it is called with the expected parameters'
- def expectedUrl = dmiServiceBaseUrl + "passthrough-running?resourceIdentifier=${resourceIdentifier}"
- def expectedJson = '{"operation":"' + expectedOperationInUrl + '","dataType":"some data type","data":"requestData","cmHandleProperties":{"prop1":"val1"}}'
+ def expectedUrl = "${dmiServiceBaseUrl}passthrough-running?resourceIdentifier=${resourceIdentifier}"
+ def expectedJson = '{"operation":"' + expectedOperationInUrl + '","dataType":"some data type","data":"requestData","cmHandleProperties":{"prop1":"val1"},"moduleSetTag":""}'
def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
- dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, operation, NO_AUTH_HEADER) >> responseFromDmi
+ mockDmiRestClient.synchronousPostOperationWithJsonData(DATA, expectedUrl, expectedJson, operation, NO_AUTH_HEADER) >> responseFromDmi
when: 'write resource method is invoked'
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'
@@ -169,7 +166,29 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
UPDATE || 'update'
}
+ def 'State Ready validation'() {
+ given: ' a yang model cm handle'
+ populateYangModelCmHandle([] ,'')
+ when: 'Validating State of #cmHandleState'
+ def caughtException = null
+ try {
+ objectUnderTest.validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState)
+ } catch (Exception e) {
+ caughtException = e
+ }
+ then: 'only when not ready a exception is thrown'
+ if (expecteException) {
+ assert caughtException.details.contains('not in READY state')
+ } else {
+ assert caughtException == null
+ }
+ where: ' the following states are used'
+ cmHandleState || expecteException
+ CmHandleState.READY || false
+ CmHandleState.ADVISED || true
+ }
+
def extractDataValue(actualDataOperationCloudEvent) {
- return toTargetEvent(actualDataOperationCloudEvent, DataOperationEvent.class).data.responses[0]
+ return toTargetEvent(actualDataOperationCloudEvent, DataOperationEvent).data.responses[0]
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
index 9aab46747..9ab52b946 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
@@ -21,9 +21,12 @@
package org.onap.cps.ncmp.api.impl.operations
+import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
+import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.MODEL
+
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
+import org.onap.cps.ncmp.api.impl.config.DmiProperties
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
@@ -34,10 +37,8 @@ import org.springframework.http.ResponseEntity
import org.springframework.test.context.ContextConfiguration
import spock.lang.Shared
-import static org.onap.cps.ncmp.api.impl.operations.OperationType.READ
-
@SpringBootTest
-@ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, DmiModelOperations])
+@ContextConfiguration(classes = [DmiProperties, DmiModelOperations])
class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
@Shared
@@ -58,8 +59,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
def moduleReferencesAsLisOfMaps = [[moduleName: 'mod1', revision: 'A'], [moduleName: 'mod2', revision: 'X']]
def expectedUrl = "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules"
def responseFromDmi = new ResponseEntity([schemas: moduleReferencesAsLisOfMaps], HttpStatus.OK)
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"cmHandleProperties":{},"moduleSetTag":""}', READ, NO_AUTH_HEADER)
- >> responseFromDmi
+ mockDmiRestClient.synchronousPostOperationWithJsonData(MODEL, expectedUrl, '{"cmHandleProperties":{},"moduleSetTag":""}', READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get module references is called'
def result = objectUnderTest.getModuleReferences(yangModelCmHandle)
then: 'the result consists of expected module references'
@@ -72,7 +72,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
and: 'any response from DMI service when it is called with the expected parameters'
// TODO (toine): production code ignores any error code from DMI, this should be improved in future
def responseFromDmi = new ResponseEntity(bodyAsMap, HttpStatus.NO_CONTENT)
- mockDmiRestClient.postOperationWithJsonData(*_) >> responseFromDmi
+ mockDmiRestClient.synchronousPostOperationWithJsonData(*_) >> responseFromDmi
when: 'get module references is called'
def result = objectUnderTest.getModuleReferences(yangModelCmHandle)
then: 'the result is empty'
@@ -90,7 +90,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
mockYangModelCmHandleRetrieval(dmiProperties)
and: 'a positive response from DMI service when it is called with tha expected parameters'
def responseFromDmi = new ResponseEntity<String>(HttpStatus.OK)
- mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules",
+ mockDmiRestClient.synchronousPostOperationWithJsonData(MODEL, "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules",
'{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + ',"moduleSetTag":""}', READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'a get module references is called'
def result = objectUnderTest.getModuleReferences(yangModelCmHandle)
@@ -109,7 +109,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
def responseFromDmi = new ResponseEntity([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source'],
[moduleName: 'mod2', revision: 'C', yangSource: 'other yang source']], HttpStatus.OK)
def expectedModuleReferencesInRequest = '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}'
- mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
+ mockDmiRestClient.synchronousPostOperationWithJsonData(MODEL, "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
'{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}', READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get new yang resources from DMI service'
def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences)
@@ -125,7 +125,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
and: 'a positive response from DMI service when it is called with tha expected parameters'
// TODO (toine): production code ignores any error code from DMI, this should be improved in future
def responseFromDmi = new ResponseEntity(responseFromDmiBody, HttpStatus.NO_CONTENT)
- mockDmiRestClient.postOperationWithJsonData(*_) >> responseFromDmi
+ mockDmiRestClient.synchronousPostOperationWithJsonData(*_) >> responseFromDmi
when: 'get new yang resources from DMI service'
def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences)
then: 'the result is empty'
@@ -141,7 +141,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
mockYangModelCmHandleRetrieval(dmiProperties)
and: 'a positive response from DMI service when it is called with the expected moduleSetTag, modules and properties'
def responseFromDmi = new ResponseEntity<>([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source']], HttpStatus.OK)
- mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
+ mockDmiRestClient.synchronousPostOperationWithJsonData(MODEL, "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
'{"data":{"modules":[{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}]},"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}',
READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get new yang resources from DMI service'
@@ -159,9 +159,9 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
mockYangModelCmHandleRetrieval([], moduleSetTag)
and: 'a positive response from DMI service when it is called with the expected moduleSetTag'
def responseFromDmi = new ResponseEntity<>([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source']], HttpStatus.OK)
- mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
- '{' + expectedModuleSetTagInRequest + '"data":{"modules":[{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}]},"cmHandleProperties":{}}',
- READ, NO_AUTH_HEADER) >> responseFromDmi
+ mockDmiRestClient.synchronousPostOperationWithJsonData(MODEL, "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
+ '{' + expectedModuleSetTagInRequest + '"data":{"modules":[{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}]},"cmHandleProperties":{}}',
+ READ, NO_AUTH_HEADER) >> responseFromDmi
when: 'get new yang resources from DMI service'
def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences)
then: 'the result is the response from DMI service'
@@ -180,7 +180,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
then: 'no resources are returned'
assert result == [:]
and: 'no request is sent to DMI'
- 0 * mockDmiRestClient.postOperationWithJsonData(*_)
+ 0 * mockDmiRestClient.synchronousPostOperationWithJsonData(*_)
}
def 'Retrieving yang resources from DMI with null DMI properties.'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy
index 72a0f2f11..f224a5cc0 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation
+ * Copyright (C) 2021-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.
@@ -22,13 +22,10 @@ package org.onap.cps.ncmp.api.impl.operations
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.ncmp.api.impl.client.DmiRestClient
-import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.spi.utils.CpsValidator
+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
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.spockframework.spring.SpringBean
import spock.lang.Shared
import spock.lang.Specification
@@ -44,16 +41,11 @@ abstract class DmiOperationsBaseSpec extends Specification {
@SpringBean
InventoryPersistence mockInventoryPersistence = Mock()
- def mockCpsValidator = Mock(CpsValidator)
-
@SpringBean
ObjectMapper spyObjectMapper = Spy()
- @SpringBean
- DmiServiceUrlBuilder dmiServiceUrlBuilder = new DmiServiceUrlBuilder(new NcmpConfiguration.DmiProperties(), mockCpsValidator)
-
def yangModelCmHandle = new YangModelCmHandle()
- def static dmiServiceName = 'some service name'
+ def static dmiServiceName = 'someServiceName'
def static cmHandleId = 'some-cm-handle'
def static resourceIdentifier = 'parent/child'
@@ -68,7 +60,7 @@ abstract class DmiOperationsBaseSpec extends Specification {
}
def mockYangModelCmHandleCollectionRetrieval(dmiProperties) {
- populateYangModelCmHandle(dmiProperties, "")
+ populateYangModelCmHandle(dmiProperties, '')
mockInventoryPersistence.getYangModelCmHandles(_) >> [yangModelCmHandle]
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/OperationTypeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/OperationTypeSpec.groovy
new file mode 100644
index 000000000..d31b8d4fd
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/OperationTypeSpec.groovy
@@ -0,0 +1,48 @@
+/*
+ * ============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.operations
+
+import org.onap.cps.ncmp.api.impl.exception.InvalidOperationException
+import spock.lang.Specification
+
+class OperationTypeSpec extends Specification {
+
+ def 'Converting string to enum.'() {
+ expect: 'converting string to enum results in the correct enum value'
+ OperationType.fromOperationName(operationName) == expectedEnum
+ where: 'the following datastore names are used'
+ operationName || expectedEnum
+ 'read' || OperationType.READ
+ 'create' || OperationType.CREATE
+ 'update' || OperationType.UPDATE
+ 'patch' || OperationType.PATCH
+ 'delete' || OperationType.DELETE
+ }
+
+ def 'Converting unknown name string to enum.'() {
+ when: 'attempt converting unknown datastore name'
+ OperationType.fromOperationName('unknown')
+ then: 'an invalid operation exception is thrown'
+ def thrown = thrown(InvalidOperationException)
+ assert thrown.message.contains('unknown is an invalid operation')
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManagerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManagerSpec.groovy
index 886648a7e..65ab7a7fd 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManagerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManagerSpec.groovy
@@ -21,8 +21,8 @@
package org.onap.cps.ncmp.api.impl.trustlevel
import org.onap.cps.ncmp.api.impl.events.avc.ncmptoclient.AvcEventPublisher
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import spock.lang.Specification
class TrustLevelManagerSpec extends Specification {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDogSpec.groovy
index 446126be9..f5835ff85 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDogSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDogSpec.groovy
@@ -20,24 +20,21 @@
package org.onap.cps.ncmp.api.impl.trustlevel.dmiavailability
-import org.onap.cps.ncmp.api.NetworkCmProxyDataService
import org.onap.cps.ncmp.api.impl.client.DmiRestClient
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager
+import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService
import spock.lang.Specification
class DmiPluginWatchDogSpec extends Specification {
def mockDmiRestClient = Mock(DmiRestClient)
- def mockNetworkCmProxyDataService = Mock(NetworkCmProxyDataService)
+ def mockCmHandleQueryService = Mock(CmHandleQueryService)
def mockTrustLevelManager = Mock(TrustLevelManager)
def trustLevelPerDmiPlugin = [:]
- def objectUnderTest = new DmiPluginWatchDog(mockDmiRestClient,
- mockNetworkCmProxyDataService,
- mockTrustLevelManager,
- trustLevelPerDmiPlugin)
+ def objectUnderTest = new DmiPluginWatchDog(mockDmiRestClient, mockCmHandleQueryService, mockTrustLevelManager, trustLevelPerDmiPlugin)
def 'watch dmi plugin health status for #dmiHealhStatus'() {
given: 'the cache has been initialised and "knows" about dmi-1'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/AlternateIdCheckerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/AlternateIdCheckerSpec.groovy
index 1e843676b..5be966b0f 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/AlternateIdCheckerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/AlternateIdCheckerSpec.groovy
@@ -20,9 +20,9 @@
package org.onap.cps.ncmp.api.impl.utils
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.spi.exceptions.DataNodeNotFoundException
import org.onap.cps.spi.model.DataNode
import org.onap.cps.spi.model.DataNodeBuilder
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
index 9f84fb073..2e0469430 100644
--- 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
@@ -20,11 +20,11 @@
package org.onap.cps.ncmp.api.impl.utils
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
-
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
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
index 05e5f5898..9481613d4 100644
--- 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
@@ -20,10 +20,10 @@
package org.onap.cps.ncmp.api.impl.utils
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
-
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.'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy
index fbf2c3d78..69d08e3de 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilderSpec.groovy
@@ -20,76 +20,67 @@
package org.onap.cps.ncmp.api.impl.utils
-import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_RUNNING
-
-import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService
-import org.onap.cps.spi.utils.CpsValidator
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
import spock.lang.Specification
class DmiServiceUrlBuilderSpec extends Specification {
- static YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('dmiServiceName',
- 'dmiDataServiceName', 'dmiModuleServiceName', new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id'),'my-module-set-tag', 'my-alternate-id', 'my-data-producer-identifier')
-
- NcmpConfiguration.DmiProperties dmiProperties = new NcmpConfiguration.DmiProperties()
-
- def mockCpsValidator = Mock(CpsValidator)
+ def objectUnderTest = new DmiServiceUrlBuilder()
- def objectUnderTest = new DmiServiceUrlBuilder(dmiProperties, mockCpsValidator)
-
- def setup() {
- dmiProperties.dmiBasePath = 'dmi'
+ def 'Build URI with (variable) path segments and parameters.'() {
+ given: 'the URI details are given to the builder'
+ objectUnderTest.pathSegment(segment1)
+ objectUnderTest.variablePathSegment('myVariableSegment','someValue')
+ objectUnderTest.pathSegment(segment2)
+ objectUnderTest.queryParameter('param1', paramValue1)
+ objectUnderTest.queryParameter('param2', paramValue2)
+ objectUnderTest.queryParameter('param3', null)
+ objectUnderTest.queryParameter('param4', '')
+ when: 'the URI (string) is build'
+ def result = objectUnderTest.build('myDmiServer', 'myBasePath')
+ then: 'the URI is correct (segments are in correct order) '
+ assert result == expectedUri
+ where: 'following URI details are used'
+ segment1 | segment2 | paramValue1 | paramValue2 || expectedUri
+ 'segment1' | 'segment2' | '123' | 'abc' || 'myDmiServer/myBasePath/v1/segment1/someValue/segment2?param1=123&param2=abc'
+ 'segment2' | 'segment1' | 'abc' | '123' || 'myDmiServer/myBasePath/v1/segment2/someValue/segment1?param1=abc&param2=123'
}
- def 'Create the dmi service url with #scenario.'() {
- given: 'uri variables'
- def uriVars = objectUnderTest.populateUriVariables(PASSTHROUGH_RUNNING.datastoreName, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA), 'cmHandle')
- and: 'query params'
- def uriQueries = objectUnderTest.populateQueryParams(resourceId, 'optionsParamInQuery', topic)
- when: 'a dmi datastore service url is generated'
- def dmiServiceUrl = objectUnderTest.getDmiDatastoreUrl(uriQueries, uriVars)
- then: 'service url is generated as expected'
- assert dmiServiceUrl == expectedDmiServiceUrl
- where: 'the following parameters are used'
- scenario | topic | resourceId || expectedDmiServiceUrl
- 'With valid resourceId' | 'topicParamInQuery' | 'resourceId' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=resourceId&options=optionsParamInQuery&topic=topicParamInQuery'
- 'With Empty resourceId' | 'topicParamInQuery' | '' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?options=optionsParamInQuery&topic=topicParamInQuery'
- 'With Empty dmi base path' | 'topicParamInQuery' | 'resourceId' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=resourceId&options=optionsParamInQuery&topic=topicParamInQuery'
- 'With Empty topicParamInQuery' | '' | 'resourceId' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=resourceId&options=optionsParamInQuery'
+ def 'Build URI with special characters in path segments.'() {
+ given: 'the path segments are given to the builder'
+ objectUnderTest.pathSegment(segment)
+ objectUnderTest.variablePathSegment('myVariableSegment', variableSegmentValue)
+ when: 'the URI (string) is build'
+ def result = objectUnderTest.build('myDmiServer', 'myBasePath')
+ then: 'Only teh characters that cause issues in path segments issues are encoded'
+ assert result == expectedUri
+ where: 'following variable path segments are used'
+ segment | variableSegmentValue || expectedUri
+ 'some/special?characters=are\\encoded' | 'my/variable/segment' || 'myDmiServer/myBasePath/v1/some%2Fspecial%3Fcharacters=are%5Cencoded/my%2Fvariable%2Fsegment'
+ 'but=some&are:not-!' | 'my&variable:segment' || 'myDmiServer/myBasePath/v1/but=some&are:not-!/my&variable:segment'
}
- def 'Populate dmi data store url #scenario.'() {
- given: 'uri variables are created'
- dmiProperties.dmiBasePath = dmiBasePath
- def uriVars = objectUnderTest.populateUriVariables(PASSTHROUGH_RUNNING.datastoreName, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA), 'cmHandle')
- and: 'null query params'
- def uriQueries = objectUnderTest.populateQueryParams(null, null, null)
- when: 'a dmi datastore service url is generated'
- def dmiServiceUrl = objectUnderTest.getDmiDatastoreUrl(uriQueries, uriVars)
- then: 'the created dmi service url matches the expected'
- assert dmiServiceUrl == expectedDmiServiceUrl
- where: 'the following parameters are used'
- scenario | decription | dmiBasePath || expectedDmiServiceUrl
- 'with base path / ' | 'Invalid base path as it starts with /' | '/dmi' || 'dmiServiceName//dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running'
- 'without base path / ' | 'Valid path as it does not starts with /' | 'dmi' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running'
+ def 'Build URI with special characters in query parameters.'() {
+ given: 'the query parameter is given to the builder'
+ objectUnderTest.queryParameter(paramName, value)
+ when: 'the URI (string) is build'
+ def result = objectUnderTest.build('myDmiServer', 'myBasePath')
+ then: 'Only the characters (in the name and value) that cause issues in query parameters are encoded'
+ assert result == expectedUri
+ where: 'the following query parameters are used'
+ paramName | value || expectedUri
+ 'my&param' | 'some?special&characters=are\\encoded' || 'myDmiServer/myBasePath/v1?my%26param=some?special%26characters%3Dare%5Cencoded'
+ 'my-param' | 'but/some:are-not-!' || 'myDmiServer/myBasePath/v1?my-param=but/some:are-not-!'
}
- def 'Bath request Url creation.'() {
- given: 'the required path parameters'
- def batchRequestUriVariables = [dmiServiceName: 'some-service', dmiBasePath: 'testBase', cmHandleId: '123']
- and: 'the relevant query parameters'
- def batchRequestQueryParams = objectUnderTest.getDataOperationRequestQueryParams('some topic', 'some id')
- when: 'a URL is created'
- def result = objectUnderTest.getDataOperationRequestUrl(batchRequestQueryParams, batchRequestUriVariables)
- then: 'it is formed correctly'
- assert result.toString() == 'some-service/testBase/v1/data?topic=some topic&requestId=some id'
+ def 'Build URI with empty query parameters.'() {
+ when: 'the query parameter is given to the builder'
+ objectUnderTest.queryParameter('param', value)
+ and: 'the URI (string) is build'
+ def result = objectUnderTest.build('myDmiServer', 'myBasePath')
+ then: 'no parameter gets added'
+ assert result == 'myDmiServer/myBasePath/v1'
+ where: 'the following parameter values are used'
+ value << [ null, '', ' ' ]
}
- def 'Populate batch uri variables.'() {
- expect: 'Populate batch uri variables returns a map with given service name and base path from setup'
- assert objectUnderTest.populateDataOperationRequestUriVariables('some service') == [dmiServiceName: 'some service', dmiBasePath: 'dmi' ]
- }
}
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/api/impl/utils/EventDateTimeFormatterSpec.groovy
new file mode 100644
index 000000000..c72eb9e4c
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/EventDateTimeFormatterSpec.groovy
@@ -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.impl.utils
+
+import spock.lang.Specification
+import java.time.Year
+
+class EventDateTimeFormatterSpec extends Specification {
+
+ def 'Get ISO formatted date and time.' () {
+ expect: 'iso formatted date and time starts with current year'
+ assert EventDateTimeFormatter.getCurrentIsoFormattedDateTime().startsWith(String.valueOf(Year.now()))
+ }
+
+ def 'Convert date time from string to OffsetDateTime type.'() {
+ when: 'date time as a string is converted to OffsetDateTime type'
+ def result = EventDateTimeFormatter.toIsoOffsetDateTime('2024-05-28T18:28:02.869+0100')
+ then: 'the result convert back back to a string is the same as the original timestamp (except the format of timezone offset)'
+ assert result.toString() == '2024-05-28T18:28:02.869+01:00'
+ }
+
+ def 'Convert blank string.' () {
+ expect: 'converting a blank string result in null'
+ assert EventDateTimeFormatter.toIsoOffsetDateTime(' ') == null
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/YangDataConverterSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/YangDataConverterSpec.groovy
index 0ae348c07..3f0d98934 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/YangDataConverterSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/YangDataConverterSpec.groovy
@@ -20,6 +20,7 @@
package org.onap.cps.ncmp.api.impl.utils
+import org.onap.cps.ncmp.impl.utils.YangDataConverter
import org.onap.cps.spi.model.DataNode
import spock.lang.Specification
@@ -34,7 +35,7 @@ class YangDataConverterSpec extends Specification{
def dataNodeCmHandle = new DataNode(leaves:['id':'sample-id'], childDataNodes:[dataNodeAdditionalProperties, dataNodePublicProperties])
when: 'the dataNode is converted'
def yangModelCmHandle =
- YangDataConverter.convertCmHandleToYangModel(dataNodeCmHandle)
+ YangDataConverter.convertCmHandleToYangModel(dataNodeCmHandle)
then: 'the converted object has the correct id'
assert yangModelCmHandle.id == 'sample-id'
and: 'the additional (dmi, private) properties are included'
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/api/impl/utils/context/CpsApplicationContextSpec.groovy
index b7fa44925..ee117160c 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/api/impl/utils/context/CpsApplicationContextSpec.groovy
@@ -1,3 +1,23 @@
+/*
+ * ============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.api.impl.utils.context
import com.fasterxml.jackson.databind.ObjectMapper
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy
index 8df27bb62..d8d04d44a 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/data/operation/ResourceDataOperationRequestUtilsSpec.groovy
@@ -26,26 +26,27 @@ import io.cloudevents.kafka.CloudEventDeserializer
import io.cloudevents.kafka.impl.KafkaHeaders
import org.apache.kafka.clients.consumer.KafkaConsumer
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.api.NcmpResponseStatus
+import org.onap.cps.ncmp.api.impl.operations.DmiDataOperation
+import org.onap.cps.ncmp.api.impl.operations.OperationType
import org.onap.cps.ncmp.api.impl.utils.context.CpsApplicationContext
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder
+import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder
import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
import org.onap.cps.ncmp.api.models.DataOperationRequest
import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
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.test.context.ContextConfiguration
+import org.springframework.util.LinkedMultiValueMap
import java.time.Duration
-import java.util.concurrent.TimeoutException
import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY
-@ContextConfiguration(classes = [EventsPublisher, CpsApplicationContext, ObjectMapper])
+@ContextConfiguration(classes = [EventsPublisher, CpsApplicationContext])
class ResourceDataOperationRequestUtilsSpec extends MessagingBaseSpec {
def static clientTopic = 'my-topic-name'
@@ -57,9 +58,6 @@ class ResourceDataOperationRequestUtilsSpec extends MessagingBaseSpec {
@SpringBean
EventsPublisher eventPublisher = new EventsPublisher<CloudEvent>(legacyEventKafkaTemplate, cloudEventKafkaTemplate)
- @Autowired
- ObjectMapper objectMapper
-
def 'Process per data operation request with #serviceName.'() {
given: 'data operation request with 3 operations'
def dataOperationRequestJsonData = TestUtils.getResourceFileContent('dataOperationRequest.json')
@@ -90,6 +88,23 @@ class ResourceDataOperationRequestUtilsSpec extends MessagingBaseSpec {
'dmi2' | 2 || 'operational-15' | 'ncmp-datastore:passthrough-operational' | ['ch4-dmi2']
}
+ def 'Process one data operation request with #serviceName and Module Set Tag set.'() {
+ given: 'data operation request'
+ def dataOperationRequestJsonData = TestUtils.getResourceFileContent('dataOperationRequest.json')
+ def dataOperationRequest = jsonObjectMapper.convertJsonString(dataOperationRequestJsonData, DataOperationRequest.class)
+ and: '1 known cm handles: ch1-dmi1'
+ def yangModelCmHandles = getYangModelCmHandlesForOneCmHandle()
+ when: 'data operation request is processed'
+ def operationsOutPerDmiServiceName = ResourceDataOperationRequestUtils.processPerDefinitionInDataOperationsRequest(clientTopic,'request-id', dataOperationRequest, yangModelCmHandles)
+ and: 'converted to a json node'
+ def dmiDataOperationRequestBody = operationsOutPerDmiServiceName['dmi1']
+ def cmHandlesInRequestBody = dmiDataOperationRequestBody[0].cmHandles
+ then: 'it contains the correct operation details'
+ assert cmHandlesInRequestBody.size() == 1
+ assert cmHandlesInRequestBody[0].id == 'ch1-dmi1'
+ assert cmHandlesInRequestBody[0].moduleSetTag == 'module-set-tag1'
+ }
+
def 'Process per data operation request with non-ready, non-existing cm handle and publish event to client specified topic'() {
given: 'consumer subscribing to client topic'
def cloudEventKafkaConsumer = new KafkaConsumer<>(eventConsumerConfigProperties('test-1', CloudEventDeserializer))
@@ -118,34 +133,10 @@ class ResourceDataOperationRequestUtilsSpec extends MessagingBaseSpec {
jsonObjectMapper.asJsonString(dataOperationResponseEvent.data.responses) == dataOperationResponseEventJson
}
- def 'Publish error response for entire data operations request when async task fails'() {
- given: 'consumer subscribing to client topic'
- def cloudEventKafkaConsumer = new KafkaConsumer<>(eventConsumerConfigProperties(consumerGroupId, CloudEventDeserializer))
- cloudEventKafkaConsumer.subscribe([clientTopic])
- and: 'data operation request having non-ready and non-existing cm handle ids'
- def dataOperationRequestJsonData = TestUtils.getResourceFileContent('dataOperationRequest.json')
- def dataOperationRequest = jsonObjectMapper.convertJsonString(dataOperationRequestJsonData, DataOperationRequest.class)
- when: 'an error occurs for the entire data operations request'
- ResourceDataOperationRequestUtils.handleAsyncTaskCompletionForDataOperationsRequest(clientTopic, 'request-id', dataOperationRequest, exceptionThrown)
- and: 'subscribed client specified topic is polled and first record is selected'
- def consumerRecordOut = cloudEventKafkaConsumer.poll(Duration.ofMillis(1500)).last()
- def dataOperationResponseEvent = toTargetEvent(consumerRecordOut.value(), DataOperationEvent.class)
- then: 'data operation response event response size is 3'
- dataOperationResponseEvent.data.responses.size() == 3
- and: 'all 3 have the expected error code'
- dataOperationResponseEvent.data.responses.each {
- assert it.statusCode == errorReportedToClientTopic.code
- }
- where:
- scenario | exceptionThrown | consumerGroupId || errorReportedToClientTopic
- 'task timed out' | new TimeoutException() | 'test-2' || NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING
- 'unspecified error' | new RuntimeException() | 'test-3' || NcmpResponseStatus.UNKNOWN_ERROR
- }
-
static def getYangModelCmHandles() {
def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
- def readyState = new CompositeStateBuilder().withCmHandleState(CmHandleState.READY).withLastUpdatedTimeNow().build()
- def advisedState = new CompositeStateBuilder().withCmHandleState(CmHandleState.ADVISED).withLastUpdatedTimeNow().build()
+ def readyState = new CompositeStateBuilder().withCmHandleState(READY).withLastUpdatedTimeNow().build()
+ def advisedState = new CompositeStateBuilder().withCmHandleState(ADVISED).withLastUpdatedTimeNow().build()
return [new YangModelCmHandle(id: 'ch1-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
new YangModelCmHandle(id: 'ch2-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
new YangModelCmHandle(id: 'ch6-dmi1', dmiServiceName: 'dmi1', dmiProperties: dmiProperties, compositeState: readyState),
@@ -156,4 +147,19 @@ class ResourceDataOperationRequestUtilsSpec extends MessagingBaseSpec {
new YangModelCmHandle(id: 'non-ready-cm-handle', dmiServiceName: 'dmi2', dmiProperties: dmiProperties, compositeState: advisedState)
]
}
+
+ static def getYangModelCmHandlesForOneCmHandle() {
+ def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
+ def readyState = new CompositeStateBuilder().withCmHandleState(READY).withLastUpdatedTimeNow().build()
+ return [new YangModelCmHandle(id: 'ch1-dmi1', dmiServiceName: 'dmi1', moduleSetTag: 'module-set-tag1', dmiProperties: dmiProperties, compositeState: readyState)]
+ }
+
+ def mockAndPopulateErrorMap(errorReportedToClientTopic) {
+ def dmiDataOperation = DmiDataOperation.builder().operation(OperationType.fromOperationName('read'))
+ .operationId('some-op-id').datastore('ncmp-datastore:passthrough-operational')
+ .options('some-option').resourceIdentifier('some-resource-identifier').build()
+ def cmHandleIdsPerResponseCodesPerOperation = new LinkedMultiValueMap<>()
+ cmHandleIdsPerResponseCodesPerOperation.add(dmiDataOperation, Map.of(errorReportedToClientTopic, ['some-cm-handle-id']))
+ return cmHandleIdsPerResponseCodesPerOperation
+ }
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy
index 7803ae319..055a6e744 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/CmHandleRegistrationResponseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CmHandleRegistrationResponseSpec.groovy
@@ -19,16 +19,17 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.models
+package org.onap.cps.ncmp.api.inventory.models
+
+import org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse.Status
+import spock.lang.Specification
+
+import java.util.stream.Collectors
import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST
import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
-import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
-import spock.lang.Specification
-import java.util.stream.Collectors
-
class CmHandleRegistrationResponseSpec extends Specification {
def 'Successful cm-handle Registration Response'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilderSpec.groovy
index 777b505b4..dfed3c787 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/CompositeStateBuilderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateBuilderSpec.groovy
@@ -19,13 +19,12 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory
+package org.onap.cps.ncmp.api.inventory.models
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder
-import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState
-import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory
+
+import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
+import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory
import org.onap.cps.spi.model.DataNode
import org.onap.cps.spi.model.DataNodeBuilder
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/CompositeStateSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateSpec.groovy
index d8beba8de..f6e4c8870 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/CompositeStateSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/CompositeStateSpec.groovy
@@ -18,20 +18,20 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory
+package org.onap.cps.ncmp.api.inventory.models
import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState
-import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory
+import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
+import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory
import spock.lang.Specification
+
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
-import static org.onap.cps.ncmp.api.impl.inventory.CompositeState.DataStores
-import static org.onap.cps.ncmp.api.impl.inventory.CompositeState.Operational
+import static org.onap.cps.ncmp.api.inventory.models.CompositeState.DataStores
+import static org.onap.cps.ncmp.api.inventory.models.CompositeState.Operational
import static org.onap.cps.ncmp.utils.TestUtils.getResourceFileContent
import static org.springframework.util.StringUtils.trimAllWhitespace
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangResourceTest.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/YangResourceTest.groovy
index 0a0c84e25..068997591 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangResourceTest.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/models/YangResourceTest.groovy
@@ -1,4 +1,5 @@
-package org.onap.cps.ncmp.api.models
+package org.onap.cps.ncmp.api.inventory.models
+
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/RestQueryParametersValidatorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryParametersValidatorSpec.groovy
index dc471e64f..15526a0c8 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/RestQueryParametersValidatorSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryParametersValidatorSpec.groovy
@@ -18,21 +18,20 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils
+package org.onap.cps.ncmp.impl.inventory
-import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters
+import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters
import org.onap.cps.spi.exceptions.DataValidationException
import org.onap.cps.spi.model.ConditionProperties
import spock.lang.Specification
-class RestQueryParametersValidatorSpec extends Specification {
-
+class CmHandleQueryParametersValidatorSpec extends Specification {
def 'CM Handle Query validation: empty query.'() {
given: 'a cm handle query'
def cmHandleQueryParameters = new CmHandleQueryServiceParameters()
when: 'validator is invoked'
- RestQueryParametersValidator.validateCmHandleQueryParameters(cmHandleQueryParameters, [])
+ CmHandleQueryParametersValidator.validateCmHandleQueryParameters(cmHandleQueryParameters, [])
then: 'data validation exception is not thrown'
noExceptionThrown()
}
@@ -45,7 +44,7 @@ class RestQueryParametersValidatorSpec extends Specification {
condition.conditionParameters = [['key':'value']]
cmHandleQueryParameters.cmHandleQueryParameters = [condition]
when: 'validator is invoked'
- RestQueryParametersValidator.validateCmHandleQueryParameters(cmHandleQueryParameters, ['validConditionName'])
+ CmHandleQueryParametersValidator.validateCmHandleQueryParameters(cmHandleQueryParameters, ['validConditionName'])
then: 'data validation exception is not thrown'
noExceptionThrown()
}
@@ -58,17 +57,17 @@ class RestQueryParametersValidatorSpec extends Specification {
condition.conditionParameters = conditionParameters
cmHandleQueryParameters.cmHandleQueryParameters = [condition]
when: 'validator is invoked'
- RestQueryParametersValidator.validateCmHandleQueryParameters(cmHandleQueryParameters, ['validConditionName'])
+ CmHandleQueryParametersValidator.validateCmHandleQueryParameters(cmHandleQueryParameters, ['validConditionName'])
then: 'a data validation exception is thrown'
def thrown = thrown(DataValidationException)
and: 'the exception details contain the correct significant term '
- thrown.details.contains(expectedWordInDetails)
+ assert thrown.details.contains(expectedWordInDetails)
where:
scenario | conditionName | conditionParameters || expectedWordInDetails
'unknown condition name' | 'unknownCondition' | [['key': 'value']] || 'conditionName'
'no condition name' | '' | [['key': 'value']] || 'conditionName'
+ 'empty conditions' | 'validConditionName' | [] || 'conditionsParameters'
'empty properties' | 'validConditionName' | [[:]] || 'conditionsParameter'
- 'empty conditions' | 'validConditionName' | [[:]] || 'conditionsParameter'
'too many properties' | 'validConditionName' | [[key1: 'value1', key2: 'value2']] || 'conditionsParameter'
'empty key' | 'validConditionName' | [['': 'wrong']] || 'conditionsParameter'
}
@@ -77,14 +76,14 @@ class RestQueryParametersValidatorSpec extends Specification {
given: 'a condition property'
def conditionProperty = [moduleName: 'value']
when: 'validator is invoked'
- RestQueryParametersValidator.validateModuleNameConditionProperties(conditionProperty)
+ CmHandleQueryParametersValidator.validateModuleNameConditionProperties(conditionProperty)
then: 'data validation exception is not thrown'
noExceptionThrown()
}
def 'CM Handle Query validation: validate module name condition properties - #scenario.'() {
when: 'validator is invoked'
- RestQueryParametersValidator.validateModuleNameConditionProperties(conditionProperty)
+ CmHandleQueryParametersValidator.validateModuleNameConditionProperties(conditionProperty)
then: 'a data validation exception is thrown'
thrown(DataValidationException)
where:
@@ -95,7 +94,7 @@ class RestQueryParametersValidatorSpec extends Specification {
def 'Validate CmHandle where an exception is thrown due to #scenario.'() {
when: 'the validator is called on a cps path condition property'
- RestQueryParametersValidator.validateCpsPathConditionProperties(conditionProperty)
+ CmHandleQueryParametersValidator.validateCpsPathConditionProperties(conditionProperty)
then: 'a data validation exception is thrown'
def e = thrown(DataValidationException)
and: 'exception message matches the expected message'
@@ -109,12 +108,12 @@ class RestQueryParametersValidatorSpec extends Specification {
def 'No conditions.'() {
expect: 'no conditions always returns true'
- RestQueryParametersValidator.validateCpsPathConditionProperties([:]) == true
+ CmHandleQueryParametersValidator.validateCpsPathConditionProperties([:]) == true
}
def 'Validate CmHandle where #scenario.'() {
when: 'the validator is called on a cps path condition property'
- def result = RestQueryParametersValidator.validateCpsPathConditionProperties(['cpsPath':cpsPath])
+ def result = CmHandleQueryParametersValidator.validateCpsPathConditionProperties(['cpsPath':cpsPath])
then: 'the expected boolean value is returned'
result == expectedBoolean
where:
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy
index 2f9d26494..52ddcfb6c 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy
@@ -19,21 +19,23 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory
+package org.onap.cps.ncmp.impl.inventory
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
-import org.onap.cps.spi.utils.CpsValidator
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
-import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
-import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.model.DataNode
+import org.onap.cps.spi.utils.CpsValidator
import spock.lang.Shared
import spock.lang.Specification
-class CmHandleQueriesImplSpec extends Specification {
+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
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
+import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
+import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
+
+class CmHandleQueryServiceImplSpec extends Specification {
def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
@@ -43,7 +45,7 @@ class CmHandleQueriesImplSpec extends Specification {
def mockCpsValidator = Mock(CpsValidator)
- def objectUnderTest = new CmHandleQueriesImpl(mockCpsDataPersistenceService, trustLevelPerDmiPlugin, trustLevelPerCmHandle, mockCpsValidator)
+ def objectUnderTest = new CmHandleQueryServiceImpl(mockCpsDataPersistenceService, trustLevelPerDmiPlugin, trustLevelPerCmHandle, mockCpsValidator)
@Shared
def static sampleDataNodes = [new DataNode()]
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandlerSpec.groovy
index 260772714..0a5b4f4ec 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServicePropertyHandlerSpec.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.
@@ -20,7 +20,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl
+package org.onap.cps.ncmp.impl.inventory
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
@@ -28,13 +28,13 @@ import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.core.read.ListAppender
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.api.CpsDataService
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
import org.onap.cps.spi.exceptions.DataNodeNotFoundException
import org.onap.cps.spi.exceptions.DataValidationException
import org.onap.cps.spi.model.DataNode
import org.onap.cps.spi.model.DataNodeBuilder
+import org.onap.cps.utils.ContentType
import org.onap.cps.utils.JsonObjectMapper
import org.slf4j.LoggerFactory
import spock.lang.Specification
@@ -42,22 +42,22 @@ import spock.lang.Specification
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND
import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID
import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
+import static org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse.Status
+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
-class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
+class CmHandleRegistrationServicePropertyHandlerSpec extends Specification {
def mockInventoryPersistence = Mock(InventoryPersistence)
def mockCpsDataService = Mock(CpsDataService)
def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
def mockAlternateIdChecker = Mock(AlternateIdChecker)
- def objectUnderTest = new NetworkCmProxyDataServicePropertyHandler(mockInventoryPersistence, mockCpsDataService, jsonObjectMapper, mockAlternateIdChecker)
+ def objectUnderTest = new CmHandleRegistrationServicePropertyHandler(mockInventoryPersistence, mockCpsDataService, jsonObjectMapper, mockAlternateIdChecker)
def logger = Spy(ListAppender<ILoggingEvent>)
void setup() {
- def setupLogger = ((Logger) LoggerFactory.getLogger(NetworkCmProxyDataServicePropertyHandler.class))
+ def setupLogger = ((Logger) LoggerFactory.getLogger(CmHandleRegistrationServicePropertyHandler.class))
setupLogger.addAppender(logger)
setupLogger.setLevel(Level.DEBUG)
logger.start()
@@ -66,7 +66,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
}
void cleanup() {
- ((Logger) LoggerFactory.getLogger(NetworkCmProxyDataServicePropertyHandler.class)).detachAndStopAllAppenders()
+ ((Logger) LoggerFactory.getLogger(CmHandleRegistrationServicePropertyHandler.class)).detachAndStopAllAppenders()
}
def static cmHandleId = 'myHandle1'
@@ -209,7 +209,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
when: 'cm handle properties is updated'
def response = objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest)
then: 'the update is delegated to cps data service with correct parameters'
- 1 * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', _, _) >>
+ 1 * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', _, _, ContentType.JSON) >>
{ args ->
assert args[3].contains('alt-1')
}
@@ -241,12 +241,12 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
given: 'an existing cm handle with no data producer identifier'
DataNode existingCmHandleDataNode = new DataNode(xpath: cmHandleXpath, leaves: ['id': 'cmHandleId','data-producer-identifier': oldDataProducerIdentifier])
and: 'an update request with a new data producer identifier'
- def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, dataProducerIdentifier: 'someDataProducerIdentifier')
+ def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, dataProducerIdentifier: 'New Data Producer Identifier')
when: 'data producer identifier updated'
objectUnderTest.updateDataProducerIdentifier(existingCmHandleDataNode, ncmpServiceCmHandle)
then: 'the update node leaves method is invoked once'
- 1 * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', _, _) >> { args ->
- assert args[3].contains('someDataProducerIdentifier')
+ 1 * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', _, _, ContentType.JSON) >> { args ->
+ assert args[3].contains('New Data Producer Identifier')
}
and: 'correct information is logged'
def lastLoggingEvent = logger.list[0]
@@ -258,6 +258,17 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
'blank to something' | ''
}
+ def 'Update CM Handle data producer identifier with same value'() {
+ given: 'an existing cm handle with no data producer identifier'
+ DataNode existingCmHandleDataNode = new DataNode(xpath: cmHandleXpath, leaves: ['id': 'cmHandleId','data-producer-identifier': 'same id'])
+ and: 'an update request with a new data producer identifier'
+ def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, dataProducerIdentifier: 'same id')
+ when: 'data producer identifier updated'
+ objectUnderTest.updateDataProducerIdentifier(existingCmHandleDataNode, ncmpServiceCmHandle)
+ then: 'the update node leaves method is not invoked'
+ 0 * mockCpsDataService.updateNodeLeaves(*_)
+ }
+
def 'Update CM Handle data producer identifier from some data producer identifier to another data producer identifier'() {
given: 'an existing cm handle with a data producer identifier'
DataNode existingCmHandleDataNode = new DataNode(xpath: cmHandleXpath, leaves: ['id': 'cmHandleId', 'data-producer-identifier': 'someDataProducerIdentifier'])
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy
index fbfbac59e..da3116283 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy
@@ -19,51 +19,44 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl
+package org.onap.cps.ncmp.impl.inventory
-import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
-
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager
-import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker
-import org.onap.cps.ncmp.api.models.UpgradedCmHandles
-import com.fasterxml.jackson.databind.ObjectMapper
import com.hazelcast.map.IMap
import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
-import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService
import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler
import org.onap.cps.ncmp.api.impl.exception.DmiRequestException
-import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse
-import org.onap.cps.ncmp.api.models.DmiPluginRegistration
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager
+import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker
+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
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.api.inventory.models.UpgradedCmHandles
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.spi.exceptions.AlreadyDefinedException
+import org.onap.cps.spi.exceptions.CpsException
import org.onap.cps.spi.exceptions.DataNodeNotFoundException
import org.onap.cps.spi.exceptions.DataValidationException
import org.onap.cps.spi.exceptions.SchemaSetNotFoundException
-import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Specification
-class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_ALREADY_EXIST
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
+import static org.onap.cps.ncmp.api.inventory.models.CmHandleRegistrationResponse.Status
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
+
+class CmHandleRegistrationServiceSpec extends Specification {
def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id')
def mockCpsModuleService = Mock(CpsModuleService)
- def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
- def mockDmiDataOperations = Mock(DmiDataOperations)
- def mockNetworkCmProxyDataServicePropertyHandler = Mock(NetworkCmProxyDataServicePropertyHandler)
+ def mockNetworkCmProxyDataServicePropertyHandler = Mock(CmHandleRegistrationServicePropertyHandler)
def mockInventoryPersistence = Mock(InventoryPersistence)
- def mockCmHandleQueries = Mock(CmHandleQueries)
- def stubbedNetworkCmProxyCmHandlerQueryService = Stub(NetworkCmProxyCmHandleQueryService)
+ def mockCmHandleQueries = Mock(CmHandleQueryService)
def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler)
def mockCpsDataService = Mock(CpsDataService)
def mockModuleSyncStartedOnCmHandles = Mock(IMap<String, Object>)
@@ -71,10 +64,9 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def mockTrustLevelManager = Mock(TrustLevelManager)
def mockAlternateIdChecker = Mock(AlternateIdChecker)
- def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(spiedJsonObjectMapper, mockDmiDataOperations,
- mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCmHandleQueries,
- stubbedNetworkCmProxyCmHandlerQueryService, mockLcmEventsCmHandleStateHandler, mockCpsDataService,
- mockModuleSyncStartedOnCmHandles, trustLevelPerDmiPlugin, mockTrustLevelManager, mockAlternateIdChecker))
+ def objectUnderTest = Spy(new CmHandleRegistrationService(
+ mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCpsDataService, mockLcmEventsCmHandleStateHandler,
+ mockModuleSyncStartedOnCmHandles, trustLevelPerDmiPlugin , mockTrustLevelManager, mockAlternateIdChecker))
def setup() {
// always accept all cm handles
@@ -418,4 +410,46 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
'an unexpected exception' | 'cmhandle' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed'
}
+ def 'Set Cm Handle Data Sync Enabled Flag where data sync flag is #scenario'() {
+ given: 'an existing cm handle composite state'
+ def compositeState = new CompositeState(cmHandleState: CmHandleState.READY, dataSyncEnabled: initialDataSyncEnabledFlag,
+ dataStores: CompositeState.DataStores.builder()
+ .operationalDataStore(CompositeState.Operational.builder()
+ .dataStoreSyncState(initialDataSyncState)
+ .build()).build())
+ and: 'get cm handle state returns the composite state for the given cm handle id'
+ mockInventoryPersistence.getCmHandleState('some-cm-handle-id') >> compositeState
+ when: 'set data sync enabled is called with the data sync enabled flag set to #dataSyncEnabledFlag'
+ objectUnderTest.setDataSyncEnabled('some-cm-handle-id', dataSyncEnabledFlag)
+ then: 'the data sync enabled flag is set to #dataSyncEnabled'
+ compositeState.dataSyncEnabled == dataSyncEnabledFlag
+ and: 'the data store sync state is set to #expectedDataStoreSyncState'
+ compositeState.dataStores.operationalDataStore.dataStoreSyncState == expectedDataStoreSyncState
+ and: 'the cps data service to delete data nodes is invoked the expected number of times'
+ deleteDataNodeExpectedNumberOfInvocation * mockCpsDataService.deleteDataNode(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, 'some-cm-handle-id', '/netconf-state', _)
+ and: 'the inventory persistence service to update node leaves is called with the correct values'
+ saveCmHandleStateExpectedNumberOfInvocations * mockInventoryPersistence.saveCmHandleState('some-cm-handle-id', compositeState)
+ where: 'the following data sync enabled flag is used'
+ scenario | dataSyncEnabledFlag | initialDataSyncEnabledFlag | initialDataSyncState || expectedDataStoreSyncState | deleteDataNodeExpectedNumberOfInvocation | saveCmHandleStateExpectedNumberOfInvocations
+ 'enabled' | true | false | DataStoreSyncState.NONE_REQUESTED || DataStoreSyncState.UNSYNCHRONIZED | 0 | 1
+ 'disabled' | false | true | DataStoreSyncState.UNSYNCHRONIZED || DataStoreSyncState.NONE_REQUESTED | 0 | 1
+ 'disabled where sync-state is currently SYNCHRONIZED' | false | true | DataStoreSyncState.SYNCHRONIZED || DataStoreSyncState.NONE_REQUESTED | 1 | 1
+ 'is set to existing flag state' | true | true | DataStoreSyncState.UNSYNCHRONIZED || DataStoreSyncState.UNSYNCHRONIZED | 0 | 0
+ }
+
+ def 'Set cm Handle Data Sync Enabled flag with following cm handle not in ready state exception' () {
+ given: 'a cm handle composite state'
+ def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, dataSyncEnabled: false)
+ and: 'get cm handle state returns the composite state for the given cm handle id'
+ mockInventoryPersistence.getCmHandleState('some-cm-handle-id') >> compositeState
+ when: 'set data sync enabled is called with the data sync enabled flag set to true'
+ objectUnderTest.setDataSyncEnabled('some-cm-handle-id', true)
+ then: 'the expected exception is thrown'
+ thrown(CpsException)
+ and: 'the inventory persistence service to update node leaves is not invoked'
+ 0 * mockInventoryPersistence.saveCmHandleState(_, _)
+ }
+
+
+
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
index 9907e9ab2..d58a1dfa0 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/InventoryPersistenceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
@@ -20,24 +20,17 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory
-
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NO_TIMESTAMP
-import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
-import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
+package org.onap.cps.ncmp.impl.inventory
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.api.CpsAnchorService
import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.ncmp.api.inventory.models.CompositeState
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.spi.CascadeDeleteAllowed
import org.onap.cps.spi.FetchDescendantsOption
-import org.onap.cps.ncmp.api.impl.exception.NoAlternateIdParentFoundException
import org.onap.cps.spi.exceptions.DataNodeNotFoundException
import org.onap.cps.spi.model.DataNode
import org.onap.cps.spi.model.ModuleDefinition
@@ -46,10 +39,19 @@ import org.onap.cps.spi.utils.CpsValidator
import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Shared
import spock.lang.Specification
+
import java.time.OffsetDateTime
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
+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
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NO_TIMESTAMP
+import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
+import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
+
class InventoryPersistenceImplSpec extends Specification {
def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
@@ -62,7 +64,7 @@ class InventoryPersistenceImplSpec extends Specification {
def mockCpsValidator = Mock(CpsValidator)
- def mockCmHandleQueries = Mock(CmHandleQueries)
+ def mockCmHandleQueries = Mock(CmHandleQueryService)
def objectUnderTest = new InventoryPersistenceImpl(spiedJsonObjectMapper, mockCpsDataService, mockCpsModuleService,
mockCpsValidator, mockCpsAnchorService, mockCmHandleQueries)
@@ -303,41 +305,6 @@ class InventoryPersistenceImplSpec extends Specification {
assert objectUnderTest.getCmHandleDataNodeByAlternateId('alternate id') == new DataNode()
}
- def 'Find cm handle parent data node using alternate ids'() {
- given: 'cm handle in the registry with alternateId /a/b'
- def matchingCpsPath = "/dmi-registry/cm-handles[@alternate-id='/a/b']"
- mockCmHandleQueries.queryNcmpRegistryByCpsPath(matchingCpsPath, OMIT_DESCENDANTS) >> [new DataNode()]
- and: 'no other cm handle'
- mockCmHandleQueries.queryNcmpRegistryByCpsPath(*_) >> []
- expect: 'querying for alternate id a matching result found'
- assert objectUnderTest.getCmHandleDataNodeByLongestMatchAlternateId(alternateId, '/') != null
- where: 'the following parameters are used'
- scenario | alternateId
- 'exact match' | '/a/b'
- 'exact match with trailing separator' | '/a/b/'
- 'child match' | '/a/b/c'
- }
-
- def 'Find cm handle parent data node using alternate ids mismatches'() {
- given: 'cm handle in the registry with alternateId'
- def matchingCpsPath = "/dmi-registry/cm-handles[@alternate-id='${cpsPath}]"
- mockCmHandleQueries.queryNcmpRegistryByCpsPath(matchingCpsPath, OMIT_DESCENDANTS) >> [new DataNode()]
- and: 'no other cm handle'
- mockCmHandleQueries.queryNcmpRegistryByCpsPath(*_) >> []
- when: 'attempt to find alternateId'
- objectUnderTest.getCmHandleDataNodeByLongestMatchAlternateId(alternateId, '/')
- then: 'no alternate id found exception thrown'
- def thrown = thrown(NoAlternateIdParentFoundException)
- and: 'the exception has the relevant details from the error response'
- assert thrown.message == 'No matching (parent) cm handle found using alternate ids'
- assert thrown.details == 'cannot find a datanode with alternate id ' + alternateId
- where: 'the following parameters are used'
- scenario | alternateId | cpsPath
- 'no match for parent only' | '/a' | '/a/b'
- 'no match at all' | '/x/y/z' | '/a/b'
- 'no match with trailing separator' | '/c/d/' | '/c/d'
- }
-
def 'Attempt to get non existing cm handle data node by alternate id'() {
given: 'query service is invoked and returns empty collection of data nodes'
mockCmHandleQueries.queryNcmpRegistryByCpsPath(*_) >> []
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy
new file mode 100644
index 000000000..49d4c39a1
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy
@@ -0,0 +1,223 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021-2024 Nordix Foundation
+ * Modifications Copyright (C) 2021 Pantheon.tech
+ * Modifications Copyright (C) 2021-2022 Bell Canada
+ * Modifications Copyright (C) 2023 TechMahindra Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.impl.inventory
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.ncmp.api.inventory.NetworkCmProxyInventoryFacade
+import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryApiParameters
+import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters
+import org.onap.cps.ncmp.api.inventory.models.CompositeState
+import org.onap.cps.ncmp.api.inventory.models.ConditionApiProperties
+import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
+import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
+import org.onap.cps.spi.model.ConditionProperties
+import org.onap.cps.utils.JsonObjectMapper
+import spock.lang.Specification
+
+import java.util.stream.Collectors
+
+class NetworkCmProxyInventoryFacadeSpec extends Specification {
+
+ def mockCmHandleRegistrationService = Mock(CmHandleRegistrationService)
+ def mockCmHandleQueryService = Mock(CmHandleQueryService)
+ def mockParameterizedCmHandleQueryService = Mock(ParameterizedCmHandleQueryService)
+ def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
+ def mockInventoryPersistence = Mock(InventoryPersistence)
+
+ def objectUnderTest = new NetworkCmProxyInventoryFacade(mockCmHandleRegistrationService, mockCmHandleQueryService, mockParameterizedCmHandleQueryService, mockInventoryPersistence, spiedJsonObjectMapper)
+
+ def 'Update DMI Registration'() {
+ given: 'an (updated) dmi plugin registration'
+ def dmiPluginRegistration = Mock(DmiPluginRegistration)
+ when: 'the registration is submitted '
+ objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ then: 'the call is delegated to the cm handle registration service'
+ 1 * mockCmHandleRegistrationService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ }
+
+ def 'Execute cm handle id search for inventory'() {
+ given: 'a ConditionApiProperties object'
+ def conditionProperties = new ConditionProperties()
+ conditionProperties.conditionName = 'hasAllProperties'
+ conditionProperties.conditionParameters = [ [ 'some-key' : 'some-value' ] ]
+ def cmHandleQueryServiceParameters = new CmHandleQueryServiceParameters()
+ cmHandleQueryServiceParameters.cmHandleQueryParameters = [conditionProperties] as List<ConditionProperties>
+ and: 'the system returns an set of cmHandle ids'
+ mockParameterizedCmHandleQueryService.queryCmHandleIdsForInventory(*_) >> [ 'cmHandle1', 'cmHandle2' ]
+ when: 'executing the search'
+ def result = objectUnderTest.executeParameterizedCmHandleIdSearch(cmHandleQueryServiceParameters)
+ then: 'the result returns the correct 2 elements'
+ assert result.size() == 2
+ assert result.contains('cmHandle1')
+ assert result.contains('cmHandle2')
+ }
+
+ def 'Get all cm handle IDs by DMI plugin identifier.' () {
+ given: 'cm handle queries service returns cm handles'
+ 1 * mockCmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier('some-dmi-plugin-identifier') >> ['cm-handle-1','cm-handle-2']
+ when: 'cm handle Ids are requested with dmi plugin identifier'
+ def result = objectUnderTest.getAllCmHandleIdsByDmiPluginIdentifier('some-dmi-plugin-identifier')
+ then: 'the result size is correct'
+ assert result.size() == 2
+ and: 'the result returns the correct details'
+ assert result.containsAll('cm-handle-1','cm-handle-2')
+ }
+
+ def 'Getting Yang Resources.'() {
+ when: 'yang resources is called'
+ objectUnderTest.getYangResourcesModuleReferences('some-cm-handle')
+ then: 'CPS module services is invoked for the correct dataspace and cm handle'
+ 1 * mockInventoryPersistence.getYangResourcesModuleReferences('some-cm-handle')
+ }
+
+ def 'Get a cm handle.'() {
+ given: 'the system returns a yang modelled cm handle'
+ def dmiServiceName = 'some service name'
+ def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED,
+ lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(),
+ lastUpdateTime: 'some-timestamp',
+ dataSyncEnabled: false,
+ dataStores: dataStores())
+ def dmiProperties = [new YangModelCmHandle.Property('Book', 'Romance Novel')]
+ def publicProperties = [new YangModelCmHandle.Property('Public Book', 'Public Romance Novel')]
+ def moduleSetTag = 'some-module-set-tag'
+ def alternateId = 'some-alternate-id'
+ def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', dmiServiceName: dmiServiceName,
+ dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState,
+ moduleSetTag: moduleSetTag, alternateId: alternateId)
+ 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
+ when: 'getting cm handle details for a given cm handle id from ncmp service'
+ def result = objectUnderTest.getNcmpServiceCmHandle('some-cm-handle')
+ then: 'the result is a ncmpServiceCmHandle'
+ result.class == NcmpServiceCmHandle.class
+ and: 'the cm handle contains the cm handle id'
+ result.cmHandleId == 'some-cm-handle'
+ and: 'the cm handle contains the alternate id'
+ result.alternateId == 'some-alternate-id'
+ and: 'the cm handle contains the module-set-tag'
+ result.moduleSetTag == 'some-module-set-tag'
+ and: 'the cm handle contains the DMI Properties'
+ result.dmiProperties ==[ Book:'Romance Novel' ]
+ and: 'the cm handle contains the public Properties'
+ result.publicProperties == [ "Public Book":'Public Romance Novel' ]
+ and: 'the cm handle contains the cm handle composite state'
+ result.compositeState == compositeState
+ }
+
+ def 'Get cm handle public properties'() {
+ given: 'a yang modelled cm handle'
+ def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
+ def publicProperties = [new YangModelCmHandle.Property('public prop', 'some public prop')]
+ def yangModelCmHandle = new YangModelCmHandle(id:'some-cm-handle', dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties)
+ and: 'the system returns this yang modelled cm handle'
+ 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
+ when: 'getting cm handle public properties for a given cm handle id from ncmp service'
+ def result = objectUnderTest.getCmHandlePublicProperties('some-cm-handle')
+ then: 'the result returns the correct data'
+ result == [ 'public prop' : 'some public prop' ]
+ }
+
+ def 'Get cm handle composite state'() {
+ given: 'a yang modelled cm handle'
+ def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED,
+ lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(),
+ lastUpdateTime: 'some-timestamp',
+ dataSyncEnabled: false,
+ dataStores: dataStores())
+ def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
+ def publicProperties = [new YangModelCmHandle.Property('public prop', 'some public prop')]
+ def yangModelCmHandle = new YangModelCmHandle(id:'some-cm-handle', dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState)
+ and: 'the system returns this yang modelled cm handle'
+ 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
+ when: 'getting cm handle composite state for a given cm handle id from ncmp service'
+ def result = objectUnderTest.getCmHandleCompositeState('some-cm-handle')
+ then: 'the result returns the correct data'
+ result == compositeState
+ }
+
+ def 'Execute cm handle id search'() {
+ given: 'valid CmHandleQueryApiParameters input'
+ def cmHandleQueryApiParameters = new CmHandleQueryApiParameters()
+ def conditionApiProperties = new ConditionApiProperties()
+ conditionApiProperties.conditionName = 'hasAllModules'
+ conditionApiProperties.conditionParameters = [[moduleName: 'module-name-1']]
+ cmHandleQueryApiParameters.cmHandleQueryParameters = [conditionApiProperties]
+ and: 'query cm handle method return with a data node list'
+ mockParameterizedCmHandleQueryService.queryCmHandleIds(
+ spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class))
+ >> ['cm-handle-id-1']
+ when: 'execute cm handle search is called'
+ def result = objectUnderTest.executeCmHandleIdSearch(cmHandleQueryApiParameters)
+ then: 'result is the same collection as returned by the CPS Data Service'
+ assert result == ['cm-handle-id-1']
+ }
+
+ def 'Getting module definitions by module'() {
+ when: 'get module definitions is performed with module name'
+ objectUnderTest.getModuleDefinitionsByCmHandleAndModule('some-cm-handle', 'some-module', '2021-08-04')
+ then: 'ncmp inventory persistence service is invoked once with correct parameters'
+ 1 * mockInventoryPersistence.getModuleDefinitionsByCmHandleAndModule('some-cm-handle', 'some-module', '2021-08-04')
+ }
+
+ def 'Getting module definitions by cm handle id'() {
+ when: 'get module definitions is performed with cm handle id'
+ objectUnderTest.getModuleDefinitionsByCmHandleId('some-cm-handle')
+ then: 'ncmp inventory persistence service is invoked once with correct parameter'
+ 1 * mockInventoryPersistence.getModuleDefinitionsByCmHandleId('some-cm-handle')
+ }
+
+ def 'Execute cm handle search'() {
+ given: 'valid CmHandleQueryApiParameters input'
+ def cmHandleQueryApiParameters = new CmHandleQueryApiParameters()
+ def conditionApiProperties = new ConditionApiProperties()
+ conditionApiProperties.conditionName = 'hasAllModules'
+ conditionApiProperties.conditionParameters = [[moduleName: 'module-name-1']]
+ cmHandleQueryApiParameters.cmHandleQueryParameters = [conditionApiProperties]
+ and: 'query cm handle method return with a data node list'
+ mockParameterizedCmHandleQueryService.queryCmHandles(
+ spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class))
+ >> [new NcmpServiceCmHandle(cmHandleId: 'cm-handle-id-1')]
+ when: 'execute cm handle search is called'
+ def result = objectUnderTest.executeCmHandleSearch(cmHandleQueryApiParameters)
+ then: 'result is the same collection as returned by the CPS Data Service'
+ assert result.stream().map(cmHandle -> cmHandle.cmHandleId).collect(Collectors.toSet()) == ['cm-handle-id-1'] as Set
+ }
+
+ def 'Set Cm Handle Data Sync flag.'() {
+ when: 'setting data sync enabled flag'
+ objectUnderTest.setDataSyncEnabled('ch-1',true)
+ then: 'call is delegated to the cm handle registration service'
+ mockCmHandleRegistrationService.setDataSyncEnabled('ch-1', true)
+ }
+
+ def dataStores() {
+ CompositeState.DataStores.builder()
+ .operationalDataStore(CompositeState.Operational.builder()
+ .dataStoreSyncState(DataStoreSyncState.NONE_REQUESTED)
+ .lastSyncTime('some-timestamp').build()).build()
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyQueryServiceImplSpec.groovy
index 5f4f248c6..d8bb559bf 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyQueryServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyQueryServiceImplSpec.groovy
@@ -18,16 +18,17 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl
-
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
+package org.onap.cps.ncmp.impl.inventory
import org.onap.cps.api.CpsQueryService
+import org.onap.cps.ncmp.api.impl.NetworkCmProxyQueryServiceImpl
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.model.DataNode
import spock.lang.Specification
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
+
class NetworkCmProxyQueryServiceImplSpec extends Specification {
def mockCpsQueryService = Mock(CpsQueryService)
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy
index 7c410cc58..dfd549e63 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy
@@ -18,17 +18,12 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl
-
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
+package org.onap.cps.ncmp.impl.inventory
import org.onap.cps.cpspath.parser.PathParsingException
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueriesImpl
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.ncmp.api.models.CmHandleQueryServiceParameters
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.exceptions.DataInUseException
import org.onap.cps.spi.exceptions.DataValidationException
@@ -36,16 +31,18 @@ import org.onap.cps.spi.model.ConditionProperties
import org.onap.cps.spi.model.DataNode
import spock.lang.Specification
-class NetworkCmProxyCmHandleQueryServiceSpec extends Specification {
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
+
+class ParameterizedCmHandleQueryServiceSpec extends Specification {
- def cmHandleQueries = Mock(CmHandleQueries)
- def partiallyMockedCmHandleQueries = Spy(CmHandleQueries)
+ def cmHandleQueries = Mock(CmHandleQueryService)
+ def partiallyMockedCmHandleQueries = Spy(CmHandleQueryService)
def mockInventoryPersistence = Mock(InventoryPersistence)
def dmiRegistry = new DataNode(xpath: NCMP_DMI_REGISTRY_PARENT, childDataNodes: createDataNodeList(['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4']))
- def objectUnderTest = new NetworkCmProxyCmHandleQueryServiceImpl(cmHandleQueries, mockInventoryPersistence)
- def objectUnderTestWithPartiallyMockedQueries = new NetworkCmProxyCmHandleQueryServiceImpl(partiallyMockedCmHandleQueries, mockInventoryPersistence)
+ def objectUnderTest = new ParameterizedCmHandleQueryServiceImpl(cmHandleQueries, mockInventoryPersistence)
+ def objectUnderTestWithPartiallyMockedQueries = new ParameterizedCmHandleQueryServiceImpl(partiallyMockedCmHandleQueries, mockInventoryPersistence)
def 'Query cm handle ids with cpsPath.'() {
given: 'a cmHandleWithCpsPath condition property'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/CmHandleQueryConditionsSpec.groovy
index 100705ff5..26541de64 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/CmHandleQueryConditionsSpec.groovy
@@ -18,7 +18,8 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils
+package org.onap.cps.ncmp.impl.inventory.models
+
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/InventoryQueryConditionsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditionsSpec.groovy
index 00edb8d0d..51c1f4bb1 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/InventoryQueryConditionsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/InventoryQueryConditionsSpec.groovy
@@ -18,7 +18,8 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.utils
+package org.onap.cps.ncmp.impl.inventory.models
+
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandleSpec.groovy
index cfc6ffda1..3f379b0b8 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandleSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/models/YangModelCmHandleSpec.groovy
@@ -18,14 +18,12 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.yangmodels
+package org.onap.cps.ncmp.impl.inventory.models
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder
-import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory
-import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.api.inventory.models.CompositeState
+import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState
import spock.lang.Specification
import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.DATA
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutorSpec.groovy
index 64ecafefc..751c97a4d 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/executor/AsyncTaskExecutorSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/AsyncTaskExecutorSpec.groovy
@@ -18,12 +18,13 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync.executor
+package org.onap.cps.ncmp.impl.inventory.sync
+
-import org.onap.cps.ncmp.api.impl.inventory.sync.executor.AsyncTaskExecutor
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import spock.lang.Specification
+
import java.util.concurrent.TimeoutException
import java.util.function.Supplier
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdogSpec.groovy
index 0ffb56791..2ee5226dc 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/DataSyncWatchdogSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DataSyncWatchdogSpec.groovy
@@ -18,19 +18,19 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync
-
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
+package org.onap.cps.ncmp.impl.inventory.sync
import com.hazelcast.map.IMap
import org.onap.cps.api.CpsDataService
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState
+import org.onap.cps.ncmp.api.inventory.models.CompositeState
+import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState
+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
import spock.lang.Specification
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
+
class DataSyncWatchdogSpec extends Specification {
def mockInventoryPersistence = Mock(InventoryPersistence)
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy
index 44bc18200..52b48a366 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtilsSpec.groovy
@@ -19,40 +19,40 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync
-
-import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.LOCKED_MISBEHAVING
-import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE
-import static org.onap.cps.ncmp.api.impl.operations.DatastoreType.PASSTHROUGH_OPERATIONAL
-import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_SYNC_FAILED
-import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE_FAILED
+package org.onap.cps.ncmp.impl.inventory.sync
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import ch.qos.logback.core.read.ListAppender
-import org.slf4j.LoggerFactory
-import org.springframework.context.annotation.AnnotationConfigApplicationContext
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder
-import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState
+import org.onap.cps.ncmp.api.inventory.models.CompositeState
+import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder
+import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService
+import org.onap.cps.ncmp.impl.inventory.DataStoreSyncState
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.model.DataNode
import org.onap.cps.utils.JsonObjectMapper
+import org.slf4j.LoggerFactory
+import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import spock.lang.Specification
+
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
import java.util.stream.Collectors
+import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.LOCKED_MISBEHAVING
+import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_SYNC_FAILED
+import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE
+import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE_FAILED
+
class ModuleOperationsUtilsSpec extends Specification{
- def mockCmHandleQueries = Mock(CmHandleQueries)
+ def mockCmHandleQueries = Mock(CmHandleQueryService)
def mockDmiDataOperations = Mock(DmiDataOperations)
@@ -202,7 +202,7 @@ class ModuleOperationsUtilsSpec extends Specification{
def jsonString = '{"stores:bookstore":{"categories":[{"code":"01"}]}}'
JsonNode jsonNode = jsonObjectMapper.convertToJsonNode(jsonString);
def responseEntity = new ResponseEntity<>(jsonNode, HttpStatus.OK)
- mockDmiDataOperations.getResourceDataFromDmi(PASSTHROUGH_OPERATIONAL.datastoreName, 'cm-handle-123', _) >> responseEntity
+ mockDmiDataOperations.getAllResourceDataFromDmi('cm-handle-123', _) >> responseEntity
when: 'get resource data is called'
def result = objectUnderTest.getResourceData('cm-handle-123')
then: 'the returned data is correct'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy
index cb933fafb..685a65b15 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncServiceSpec.groovy
@@ -18,35 +18,34 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync
+package org.onap.cps.ncmp.impl.inventory.sync
import org.onap.cps.api.CpsAnchorService
-
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
-import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE
-
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.spi.model.DataNode
import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
-import org.onap.cps.spi.model.DataNodeBuilder
import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries
-import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder
-import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.spi.CascadeDeleteAllowed
import org.onap.cps.spi.exceptions.SchemaSetNotFoundException
+import org.onap.cps.spi.model.DataNode
+import org.onap.cps.spi.model.DataNodeBuilder
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Specification
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME
+import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE
+
class ModuleSyncServiceSpec extends Specification {
def mockCpsModuleService = Mock(CpsModuleService)
def mockDmiModelOperations = Mock(DmiModelOperations)
def mockCpsAnchorService = Mock(CpsAnchorService)
- def mockCmHandleQueries = Mock(CmHandleQueries)
+ def mockCmHandleQueries = Mock(CmHandleQueryService)
def mockCpsDataService = Mock(CpsDataService)
def mockJsonObjectMapper = Mock(JsonObjectMapper)
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasksSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy
index 6c0d6dfb8..a9dbf07e2 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncTasksSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasksSpec.groovy
@@ -19,10 +19,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync
-
-import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_SYNC_FAILED
-import static org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory.MODULE_UPGRADE_FAILED
+package org.onap.cps.ncmp.impl.inventory.sync
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
@@ -32,17 +29,21 @@ import com.hazelcast.config.Config
import com.hazelcast.instance.impl.HazelcastInstanceFactory
import com.hazelcast.map.IMap
import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeState
-import org.onap.cps.ncmp.api.impl.inventory.CompositeStateBuilder
-import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
-import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory
+import org.onap.cps.ncmp.api.inventory.models.CompositeState
+import org.onap.cps.ncmp.api.inventory.models.CompositeStateBuilder
+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.LockReasonCategory
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.spi.model.DataNode
import org.slf4j.LoggerFactory
import spock.lang.Specification
+
import java.util.concurrent.atomic.AtomicInteger
+import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_SYNC_FAILED
+import static org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory.MODULE_UPGRADE_FAILED
+
class ModuleSyncTasksSpec extends Specification {
def logger = Spy(ListAppender<ILoggingEvent>)
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy
index 1752a17a1..155edc8bc 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy
@@ -19,15 +19,15 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync
+package org.onap.cps.ncmp.impl.inventory.sync
import com.hazelcast.map.IMap
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
-import org.onap.cps.ncmp.api.impl.inventory.sync.executor.AsyncTaskExecutor
-import java.util.concurrent.ArrayBlockingQueue
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.spi.model.DataNode
import spock.lang.Specification
+import java.util.concurrent.ArrayBlockingQueue
+
class ModuleSyncWatchdogSpec extends Specification {
def mockSyncUtils = Mock(ModuleOperationsUtils)
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy
index 6d09df0d4..8e59922c4 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/SynchronizationCacheConfigSpec.groovy
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.config.embeddedcache
+package org.onap.cps.ncmp.impl.inventory.sync
import com.hazelcast.config.Config
import com.hazelcast.core.Hazelcast
@@ -29,6 +29,7 @@ import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
import spock.util.concurrent.PollingConditions
+
import java.util.concurrent.BlockingQueue
import java.util.concurrent.TimeUnit
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/WatchdogSchedulingConfigurerSpec.groovy
index f37d5a41e..a943962e9 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/inventory/sync/config/WatchdogSchedulingConfigurerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/WatchdogSchedulingConfigurerSpec.groovy
@@ -18,7 +18,8 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.inventory.sync.config
+package org.onap.cps.ncmp.impl.inventory.sync
+
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/impl/utils/AlternateIdMatcherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy
new file mode 100644
index 000000000..ad8449582
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy
@@ -0,0 +1,66 @@
+/*
+ * ============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.utils
+
+import org.onap.cps.ncmp.exceptions.NoAlternateIdMatchFoundException
+import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
+import org.onap.cps.spi.exceptions.DataNodeNotFoundException
+import org.onap.cps.spi.model.DataNode
+import spock.lang.Specification
+
+class AlternateIdMatcherSpec extends Specification {
+
+ def mockInventoryPersistence = Mock(InventoryPersistence)
+ def objectUnderTest = new AlternateIdMatcher(mockInventoryPersistence)
+
+ def setup() {
+ given: 'cm handle in the registry with alternate id /a/b'
+ mockInventoryPersistence.getCmHandleDataNodeByAlternateId('/a/b') >> new DataNode()
+ and: 'no other cm handle'
+ mockInventoryPersistence.getCmHandleDataNodeByAlternateId(_) >> { throw new DataNodeNotFoundException('', '') }
+ }
+
+ def 'Finding longest alternate id matches.'() {
+ expect: 'querying for alternate id a matching result found'
+ assert objectUnderTest.getCmHandleDataNodeByLongestMatchingAlternateId(targetAlternateId, '/') != null
+ where: 'the following parameters are used'
+ scenario | targetAlternateId
+ 'exact match' | '/a/b'
+ 'parent match' | '/a/b/c'
+ 'grand parent match' | '/a/b/c/d'
+ 'trailing separator match' | '/a/b/'
+ }
+
+ def 'Attempt to find longest alternate id match without any matches.'() {
+ when: 'attempt to find alternateId'
+ objectUnderTest.getCmHandleDataNodeByLongestMatchingAlternateId(targetAlternateId, '/')
+ then: 'no alternate id match found exception thrown'
+ def thrown = thrown(NoAlternateIdMatchFoundException)
+ and: 'the exception has the relevant details from the error response'
+ assert thrown.message == 'No matching cm handle found using alternate ids'
+ assert thrown.details == 'cannot find a datanode with alternate id ' + targetAlternateId
+ where: 'the following parameters are used'
+ scenario | targetAlternateId
+ 'no match for parent only' | '/a'
+ 'no match for other child' | '/a/c'
+ 'no match at all' | '/x/y'
+ }
+}
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 b0be29d93..162a9831c 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
@@ -32,7 +32,7 @@ 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.context.event.ApplicationReadyEvent
+import org.springframework.boot.context.event.ApplicationStartedEvent
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import spock.lang.Specification
@@ -64,18 +64,18 @@ class AbstractModelLoaderSpec extends Specification {
applicationContext.close()
}
- def 'Application ready event'() {
- when: 'Application (ready) event is triggered'
- objectUnderTest.onApplicationEvent(Mock(ApplicationReadyEvent))
+ def 'Application started event'() {
+ when: 'Application (started) event is triggered'
+ objectUnderTest.onApplicationEvent(Mock(ApplicationStartedEvent))
then: 'the onboard/upgrade method is executed'
1 * objectUnderTest.onboardOrUpgradeModel()
}
- def 'Application ready event with start up exception'() {
+ def 'Application started event with start up exception'() {
given: 'a start up exception is thrown doing model onboarding'
objectUnderTest.onboardOrUpgradeModel() >> { throw new NcmpStartUpException('test message','details are not logged') }
- when: 'Application (ready) event is triggered'
- objectUnderTest.onApplicationEvent(new ApplicationReadyEvent(new SpringApplication(), null, applicationContext, null))
+ when: 'Application (started) event is triggered'
+ objectUnderTest.onApplicationEvent(new ApplicationStartedEvent(new SpringApplication(), null, applicationContext, null))
then: 'the exception message is logged'
def logs = loggingListAppender.list.toString()
assert logs.contains('test message')
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 f3b405b11..dd1fd0b46 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
@@ -31,11 +31,11 @@ import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException
import org.onap.cps.spi.exceptions.AlreadyDefinedException
import org.onap.cps.spi.model.Dataspace
import org.slf4j.LoggerFactory
-import org.springframework.boot.context.event.ApplicationReadyEvent
+import org.springframework.boot.context.event.ApplicationStartedEvent
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import spock.lang.Specification
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME
class CmDataSubscriptionModelLoaderSpec extends Specification {
@@ -65,11 +65,11 @@ class CmDataSubscriptionModelLoaderSpec extends Specification {
applicationContext.close()
}
- def 'Onboard subscription model via application ready event.'() {
+ def 'Onboard subscription model via application started event.'() {
given: 'dataspace is ready for use'
mockCpsDataspaceService.getDataspace(NCMP_DATASPACE_NAME) >> new Dataspace('')
when: 'the application is ready'
- objectUnderTest.onApplicationEvent(Mock(ApplicationReadyEvent))
+ objectUnderTest.onApplicationEvent(Mock(ApplicationStartedEvent))
then: 'the module service to create schema set is called once'
1 * mockCpsModuleService.createSchemaSet(NCMP_DATASPACE_NAME, 'cm-data-subscriptions', expectedYangResourcesToContentMap)
and: 'the admin service to create an anchor set is called once'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
index cd659bb52..76c1589be 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
@@ -20,23 +20,22 @@
package org.onap.cps.ncmp.init
-import org.onap.cps.api.CpsAnchorService
-
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
-import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
-
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import ch.qos.logback.core.read.ListAppender
-import org.onap.cps.api.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.spi.model.Dataspace
import org.slf4j.LoggerFactory
-import org.springframework.boot.context.event.ApplicationReadyEvent
+import org.springframework.boot.context.event.ApplicationStartedEvent
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import spock.lang.Specification
+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
+
class InventoryModelLoaderSpec extends Specification {
def mockCpsAdminService = Mock(CpsDataspaceService)
@@ -68,8 +67,8 @@ class InventoryModelLoaderSpec extends Specification {
def 'Onboard subscription model via application ready event.'() {
given: 'dataspace is ready for use'
mockCpsAdminService.getDataspace(NCMP_DATASPACE_NAME) >> new Dataspace('')
- when: 'the application is ready'
- objectUnderTest.onApplicationEvent(Mock(ApplicationReadyEvent))
+ when: 'the application is started'
+ objectUnderTest.onApplicationEvent(Mock(ApplicationStartedEvent))
then: 'the module service is used to create the new schema set from the correct resource'
1 * mockCpsModuleService.createSchemaSet(NCMP_DATASPACE_NAME, 'dmi-registry-2024-02-23', expectedYangResourceToContentMap)
and: 'the admin service is used to update the anchor'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/TopicValidatorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/TopicValidatorSpec.groovy
new file mode 100644
index 000000000..f96502984
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/utils/TopicValidatorSpec.groovy
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.utils
+
+import org.onap.cps.ncmp.exceptions.InvalidTopicException
+import org.onap.cps.ncmp.utils.TopicValidator
+import spock.lang.Specification
+
+class TopicValidatorSpec extends Specification {
+
+ def 'Valid topic name validation.'() {
+ when: 'a valid topic name is validated'
+ TopicValidator.validateTopicName('my-valid-topic')
+ then: 'no exception is thrown'
+ noExceptionThrown()
+ }
+
+ def 'Validating invalid topic names.'() {
+ when: 'the invalid topic name is validated'
+ TopicValidator.validateTopicName(topicName)
+ then: 'boolean response will be returned for #scenario'
+ thrown(InvalidTopicException)
+ where: 'the following names are used'
+ scenario | topicName
+ 'empty topic' | ''
+ 'blank topic' | ' '
+ 'invalid non empty topic' | '1_5_*_#'
+ }
+}
diff --git a/cps-ncmp-service/src/test/resources/application.yml b/cps-ncmp-service/src/test/resources/application.yml
index 574b49982..5b10e7376 100644
--- a/cps-ncmp-service/src/test/resources/application.yml
+++ b/cps-ncmp-service/src/test/resources/application.yml
@@ -1,5 +1,5 @@
# ============LICENSE_START=======================================================
-# Copyright (C) 2021-2023 Nordix Foundation
+# Copyright (C) 2021-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.
@@ -30,14 +30,21 @@ app:
async-m2m:
topic: ncmp-async-m2m
avc:
- subscription-topic: subscription
+ cm-subscription-ncmp-in: subscription
cm-events-topic: cm-events
- subscription-forward-topic-prefix: ${NCMP_FORWARD_CM_AVC_SUBSCRIPTION:ncmp-dmi-cm-avc-subscription-}
+ cm-subscription-dmi-in: ${CM_SUBSCRIPTION_DMI_IN_TOPIC:ncmp-dmi-cm-avc-subscription}
ncmp:
dmi:
httpclient:
- connectionTimeoutInSeconds: 180
+ data-services:
+ pendingAcquireMaxCount: 22
+ connectionTimeoutInSeconds: 123
+ maximumInMemorySizeInMegabytes: 7
+ model-services:
+ pendingAcquireMaxCount: 44
+ connectionTimeoutInSeconds: 456
+ maximumInMemorySizeInMegabytes: 8
auth:
username: some-user
password: some-password
diff --git a/cps-ncmp-service/src/test/resources/cmSubscription/cmNotificationSubscriptionNcmpInEvent.json b/cps-ncmp-service/src/test/resources/cmSubscription/cmNotificationSubscriptionNcmpInEvent.json
index 6b665495c..04d37b8bb 100644
--- a/cps-ncmp-service/src/test/resources/cmSubscription/cmNotificationSubscriptionNcmpInEvent.json
+++ b/cps-ncmp-service/src/test/resources/cmSubscription/cmNotificationSubscriptionNcmpInEvent.json
@@ -6,14 +6,14 @@
"targetFilter": ["ch1","ch2"],
"scopeFilter": {
"datastore": "ncmp-datastore:passthrough-operational",
- "xpath-filter": ["/x1/y1","x2/y2"]
+ "xpathFilter": ["/x1/y1","x2/y2"]
}
},
{
"targetFilter": ["ch3","ch4"],
"scopeFilter": {
"datastore": "ncmp-datastore:passthrough-operational",
- "xpath-filter": ["/x3/y3","x4/y4"]
+ "xpathFilter": ["/x3/y3","x4/y4"]
}
}
]