aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cps-application/src/test/java/org/onap/cps/architecture/ArchitectureTestBase.java47
-rw-r--r--cps-application/src/test/java/org/onap/cps/architecture/CpsArchitectureTest.java69
-rw-r--r--cps-application/src/test/java/org/onap/cps/architecture/NcmpArchitectureTest.java81
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java3
-rw-r--r--cps-ncmp-rest/docs/openapi/components.yaml8
-rwxr-xr-xcps-ncmp-rest/docs/openapi/ncmp-inventory.yml6
-rwxr-xr-xcps-ncmp-rest/docs/openapi/ncmp.yml4
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java14
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java17
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy2
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy12
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy3
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java26
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java20
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java82
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java3
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java7
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java18
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java16
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java90
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java48
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/Sleeper.java35
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacadeSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy45
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy28
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy17
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy16
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy59
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy65
-rw-r--r--cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java25
-rw-r--r--docs/deployment.rst6
-rw-r--r--docs/release-notes.rst8
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy37
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy52
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpdateSpec.groovy4
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy17
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy99
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy21
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy20
-rw-r--r--integration-test/src/test/resources/application-module-sync-delayed.yml23
-rw-r--r--integration-test/src/test/resources/application.yml2
-rw-r--r--integration-test/src/test/resources/data/inventory/cmHandleTemplate.json (renamed from integration-test/src/test/resources/data/ncmp-registry/innerNode.json)6
-rw-r--r--integration-test/src/test/resources/data/inventory/cmHandleWithAlternateIdTemplate.json (renamed from integration-test/src/test/resources/data/ncmp-registry/innerCmHandleNode.json)0
-rw-r--r--integration-test/src/test/resources/data/inventory/dmi-registry@2024-02-23.yang (renamed from integration-test/src/test/resources/data/ncmp-registry/dmi-registry@2024-02-23.yang)0
-rw-r--r--k6-tests/ncmp/common/search-base.js2
-rw-r--r--k6-tests/ncmp/common/utils.js4
-rw-r--r--k6-tests/ncmp/ncmp-kpi.js4
-rw-r--r--policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/Sleeper.java4
49 files changed, 843 insertions, 340 deletions
diff --git a/cps-application/src/test/java/org/onap/cps/architecture/ArchitectureTestBase.java b/cps-application/src/test/java/org/onap/cps/architecture/ArchitectureTestBase.java
new file mode 100644
index 0000000000..1d39060024
--- /dev/null
+++ b/cps-application/src/test/java/org/onap/cps/architecture/ArchitectureTestBase.java
@@ -0,0 +1,47 @@
+/*
+ * ============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.architecture;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+public class ArchitectureTestBase {
+
+ private static final String[] ACCEPTED_3PP_PACKAGES = { "com.fasterxml..",
+ "com.google..",
+ "com.hazelcast..",
+ "edu..",
+ "io.cloudevents..",
+ "io.micrometer..",
+ "io.netty..",
+ "io.swagger..",
+ "jakarta..",
+ "java..",
+ "lombok..",
+ "org.apache..",
+ "org.mapstruct..",
+ "org.slf4j..",
+ "org.springframework..",
+ "reactor.."
+ };
+
+ static String[] commonAndListedPackages(final String... packageIdentifiers) {
+ return ArrayUtils.addAll(ACCEPTED_3PP_PACKAGES, packageIdentifiers);
+ }
+}
diff --git a/cps-application/src/test/java/org/onap/cps/architecture/CpsArchitectureTest.java b/cps-application/src/test/java/org/onap/cps/architecture/CpsArchitectureTest.java
new file mode 100644
index 0000000000..7e96447252
--- /dev/null
+++ b/cps-application/src/test/java/org/onap/cps/architecture/CpsArchitectureTest.java
@@ -0,0 +1,69 @@
+/*
+ * ============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.architecture;
+
+import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
+
+import com.tngtech.archunit.core.importer.ImportOption;
+import com.tngtech.archunit.junit.AnalyzeClasses;
+import com.tngtech.archunit.junit.ArchTest;
+import com.tngtech.archunit.lang.ArchRule;
+
+@AnalyzeClasses(packages = "org.onap.cps", importOptions = {ImportOption.DoNotIncludeTests.class})
+public class CpsArchitectureTest extends ArchitectureTestBase {
+
+ @ArchTest
+ static final ArchRule cpsRestControllerShouldOnlyDependOnCpsService =
+ classes().that().resideInAPackage("org.onap.cps.rest..").should().onlyDependOnClassesThat()
+ .resideInAnyPackage(commonAndListedPackages("org.onap.cps.rest..",
+ "org.onap.cps.api..",
+ "org.onap.cps.utils..",
+ // Breaks arch rules
+ "org.onap.cps.spi.."));
+
+ @ArchTest
+ static final ArchRule cpsServiceApiShouldNotDependOnAnything =
+ classes().that().resideInAPackage("org.onap.cps.api.").should().onlyDependOnClassesThat()
+ .resideInAnyPackage(commonAndListedPackages()).allowEmptyShould(true);
+
+ @ArchTest
+ static final ArchRule cpsServiceImplShouldDependOnServiceAndEventsAndPathParserPackages =
+ // I think impl package should be moved from the api package.
+ // So in a way this whole rule is breaking our architecture goals
+ classes().that().resideInAPackage("org.onap.cps.api.impl..").should().onlyDependOnClassesThat()
+ .resideInAnyPackage(commonAndListedPackages("org.onap.cps.api..",
+ "org.onap.cps.api.impl..",
+ "org.onap.cps.events..",
+ "org.onap.cps.impl.utils..",
+ "org.onap.cps.spi..",
+ "org.onap.cps.utils..",
+ "org.onap.cps.cpspath.parser..",
+ "org.onap.cps.yang.."));
+
+ @ArchTest
+ static final ArchRule cpsReferenceImplShouldHaveNoDependants =
+ classes().that().resideInAPackage("org.onap.cps.ri..").should().onlyHaveDependentClassesThat()
+ .resideInAnyPackage("org.onap.cps.ri..");
+
+ @ArchTest
+ static final ArchRule referenceImplShouldOnlyHaveDependantsInReferenceImpl =
+ classes().that().resideInAPackage("org.onap.cps.ri.repository..").should().onlyHaveDependentClassesThat()
+ .resideInAnyPackage("org.onap.cps.ri..");
+}
diff --git a/cps-application/src/test/java/org/onap/cps/architecture/NcmpArchitectureTest.java b/cps-application/src/test/java/org/onap/cps/architecture/NcmpArchitectureTest.java
index 4c0b82fec8..5d8c534e35 100644
--- a/cps-application/src/test/java/org/onap/cps/architecture/NcmpArchitectureTest.java
+++ b/cps-application/src/test/java/org/onap/cps/architecture/NcmpArchitectureTest.java
@@ -25,31 +25,9 @@ import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
-import org.apache.commons.lang3.ArrayUtils;
-/**
- * These test verify the correct use of dependencies in all CPS modules.
- */
@AnalyzeClasses(packages = "org.onap.cps", importOptions = {ImportOption.DoNotIncludeTests.class})
-public class NcmpArchitectureTest {
-
- private static final String[] ACCEPTED_3PP_PACKAGES = { "com.fasterxml..",
- "com.google..",
- "com.hazelcast..",
- "edu..",
- "io.cloudevents..",
- "io.micrometer..",
- "io.netty..",
- "io.swagger..",
- "jakarta..",
- "java..",
- "lombok..",
- "org.apache..",
- "org.mapstruct..",
- "org.slf4j..",
- "org.springframework..",
- "reactor.."
- };
+public class NcmpArchitectureTest extends ArchitectureTestBase {
@ArchTest
static final ArchRule nothingDependsOnCpsNcmpRest =
@@ -61,38 +39,45 @@ public class NcmpArchitectureTest {
classes().that().resideInAPackage("org.onap.cps.ncmp.rest..")
.should()
.onlyDependOnClassesThat()
- .resideInAnyPackage(commonAndListedPackages("org.onap.cps.ncmp.rest..", "org.onap.cps.ncmp.api..",
- // Below packages are breaking the agreed dependencies
- // and need to be removed from this rule.
- // This will be handled in a separate user story
- "org.onap.cps.spi..", "org.onap.cps.utils..", "org.onap.cps.ncmp.impl.."));
+ .resideInAnyPackage(commonAndListedPackages("org.onap.cps.ncmp.api..",
+ "org.onap.cps.ncmp.rest..",
+ // Below packages are breaking the agreed dependencies
+ // and need to be removed from this rule.
+ // This will be handled in a separate user story
+ "org.onap.cps.spi..",
+ "org.onap.cps.utils..",
+ "org.onap.cps.ncmp.impl.."));
@ArchTest
static final ArchRule ncmpServiceApiShouldOnlyDependOnThirdPartyPackages =
classes().that().resideInAPackage("org.onap.cps.ncmp.api..").should().onlyDependOnClassesThat()
- .resideInAnyPackage(commonAndListedPackages(
- // Below packages are breaking the agreed dependencies
- // and need to be removed from this rule.
- // This will be handled in a separate user story
- "org.onap.cps.spi..", "org.onap.cps.ncmp.api..", "org.onap.cps.ncmp.impl..",
- "org.onap.cps.ncmp.config", "org.onap.cps.utils.."));
+ .resideInAnyPackage(commonAndListedPackages(// Below packages are breaking the agreed dependencies
+ // and need to be removed from this rule.
+ // This will be handled in a separate user story
+ "org.onap.cps.ncmp.api..",
+ "org.onap.cps.ncmp.impl..",
+ "org.onap.cps.ncmp.config",
+ "org.onap.cps.spi..",
+ "org.onap.cps.utils.."));
@ArchTest
static final ArchRule ncmpServiceImplShouldOnlyDependOnCpsServiceAndNcmpEvents =
classes().that().resideInAPackage("org.onap.cps.ncmp.impl..").should().onlyDependOnClassesThat()
- .resideInAnyPackage(commonAndListedPackages(
- "org.onap.cps.ncmp.api..", "org.onap.cps.ncmp.impl..",
- "org.onap.cps.ncmp.event..", "org.onap.cps.ncmp.events..", "org.onap.cps.ncmp.utils..",
- "org.onap.cps.ncmp.config..", "org.onap.cps.api..", "org.onap.cps.ncmp.exceptions..",
- // Below packages are breaking the agreed dependencies
- // and need to be removed from this rule.
- // This will be handled in a separate user story
- "org.onap.cps.spi..", "org.onap.cps.events..", "org.onap.cps.cpspath..",
- "org.onap.cps.impl..", "org.onap.cps.utils.."));
-
- static String[] commonAndListedPackages(final String... packageIdentifiers) {
- return ArrayUtils.addAll(ACCEPTED_3PP_PACKAGES, packageIdentifiers);
- }
-
+ .resideInAnyPackage(commonAndListedPackages("org.onap.cps.api..",
+ "org.onap.cps.ncmp.api..",
+ "org.onap.cps.ncmp.impl..",
+ "org.onap.cps.ncmp.event..",
+ "org.onap.cps.ncmp.events..",
+ "org.onap.cps.ncmp.utils..",
+ "org.onap.cps.ncmp.config..",
+ "org.onap.cps.ncmp.exceptions..",
+ // Below packages are breaking the agreed dependencies
+ // and need to be removed from this rule.
+ // This will be handled in a separate user story
+ "org.onap.cps.cpspath..",
+ "org.onap.cps.events..",
+ "org.onap.cps.impl..",
+ "org.onap.cps.spi..",
+ "org.onap.cps.utils.."));
}
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
index 183698c4f5..166488793d 100644
--- a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
@@ -213,7 +213,8 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
}
@Override
- public ResponseEntity<List<String>> searchCmHandleIds(@Valid final CmHandleQueryParameters body) {
+ public ResponseEntity<List<String>> searchCmHandleIds(@Valid final CmHandleQueryParameters body,
+ @Valid final Boolean outputAlternateId) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml
index 112dddf61c..99072c43e5 100644
--- a/cps-ncmp-rest/docs/openapi/components.yaml
+++ b/cps-ncmp-rest/docs/openapi/components.yaml
@@ -513,6 +513,14 @@ components:
schema:
type: string
example: my-cm-handle-reference
+ outputAlternateIdOptionInQuery:
+ name: outputAlternateId
+ in: query
+ description: Boolean parameter to determine if returned value(s) will be cmHandle Ids or Alternate Ids for a given query
+ required: false
+ schema:
+ type: boolean
+ default: false
moduleNameInQuery:
name: module-name
in: query
diff --git a/cps-ncmp-rest/docs/openapi/ncmp-inventory.yml b/cps-ncmp-rest/docs/openapi/ncmp-inventory.yml
index ea020f9e81..24b83cf368 100755
--- a/cps-ncmp-rest/docs/openapi/ncmp-inventory.yml
+++ b/cps-ncmp-rest/docs/openapi/ncmp-inventory.yml
@@ -1,6 +1,6 @@
# ============LICENSE_START=======================================================
# Copyright (C) 2021 Bell Canada
-# Modifications Copyright (C) 2021-2022 Nordix Foundation
+# Modifications 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.
@@ -121,11 +121,13 @@ getAllCmHandleIdsForRegisteredDmi:
searchCmHandleIds:
post:
- description: Query and get CMHandleIds for additional properties, public properties and registered DMI plugin (DMI plugin, DMI data plugin, DMI model plugin).
+ description: Query and get CMHandle references for additional properties, public properties and registered DMI plugin (DMI plugin, DMI data plugin, DMI model plugin).
tags:
- network-cm-proxy-inventory
summary: Query for CM Handle IDs
operationId: searchCmHandleIds
+ parameters:
+ - $ref: 'components.yaml#/components/parameters/outputAlternateIdOptionInQuery'
requestBody:
required: true
content:
diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml
index adb2419c8a..a3ddc3fb3b 100755
--- a/cps-ncmp-rest/docs/openapi/ncmp.yml
+++ b/cps-ncmp-rest/docs/openapi/ncmp.yml
@@ -417,11 +417,13 @@ getCmHandleStateById:
searchCmHandleIds:
post:
- description: Execute cm handle query search and return a list of cm handle ids. Any number of conditions can be applied. To be included in the result a cm-handle must fulfill ALL the conditions. An empty collection will be returned in the case that the cm handle does not match a condition. For more on cm handle query search please refer to <a href="https://docs.onap.org/projects/onap-cps/en/latest/ncmp-cmhandle-querying.html">cm handle query search Read the Docs</a>.<br/>By supplying a CPS Path it is possible to query on any data related to the cm handle. For more on CPS Path please refer to <a href="https://docs.onap.org/projects/onap-cps/en/latest/cps-path.html">CPS Path Read the Docs</a>. The cm handle ancestor is automatically returned for this query.
+ description: Execute cm handle query search and return a list of cm handle references. Any number of conditions can be applied. To be included in the result a cm-handle must fulfill ALL the conditions. An empty collection will be returned in the case that the cm handle does not match a condition. For more on cm handle query search please refer to <a href="https://docs.onap.org/projects/onap-cps/en/latest/ncmp-cmhandle-querying.html">cm handle query search Read the Docs</a>.<br/>By supplying a CPS Path it is possible to query on any data related to the cm handle. For more on CPS Path please refer to <a href="https://docs.onap.org/projects/onap-cps/en/latest/cps-path.html">CPS Path Read the Docs</a>. The cm handle ancestor is automatically returned for this query.
tags:
- network-cm-proxy
summary: Execute cm handle query upon a given set of query parameters
operationId: searchCmHandleIds
+ parameters:
+ - $ref: 'components.yaml#/components/parameters/outputAlternateIdOptionInQuery'
requestBody:
required: true
content:
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
index 42f709dcf5..3676bb1393 100755
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
@@ -268,18 +268,20 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
}
/**
- * Query and return cm handle ids that match the given query parameters.
+ * Query and return cm handle ids or alternate ids that match the given query parameters.
*
- * @param cmHandleQueryParameters the cm handle query parameters
- * @return collection of cm handle ids
+ * @param cmHandleQueryParameters the cm handle query parameters
+ * @param outputAlternateId Boolean for cm handle reference type either
+ * cm handle id (false or null) or alternate id (true)
+ * @return collection of cm handle ids
*/
@Override
- public ResponseEntity<List<String>> searchCmHandleIds(
- final CmHandleQueryParameters cmHandleQueryParameters) {
+ public ResponseEntity<List<String>> searchCmHandleIds(final CmHandleQueryParameters cmHandleQueryParameters,
+ final Boolean outputAlternateId) {
final CmHandleQueryApiParameters cmHandleQueryApiParameters =
jsonObjectMapper.convertToValueType(cmHandleQueryParameters, CmHandleQueryApiParameters.class);
final Collection<String> cmHandleIds
- = networkCmProxyInventoryFacade.executeCmHandleIdSearch(cmHandleQueryApiParameters);
+ = networkCmProxyInventoryFacade.executeCmHandleIdSearch(cmHandleQueryApiParameters, outputAlternateId);
return ResponseEntity.ok(List.copyOf(cmHandleIds));
}
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java
index 8aa86ade36..f76376991a 100755
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java
@@ -1,7 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021-2022 Bell Canada
- * Modifications Copyright (C) 2022-2023 Nordix Foundation
+ * Modifications Copyright (C) 2022-2024 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,13 +51,22 @@ public class NetworkCmProxyInventoryController implements NetworkCmProxyInventor
private final NetworkCmProxyInventoryFacade networkCmProxyInventoryFacade;
private final NcmpRestInputMapper ncmpRestInputMapper;
+ /**
+ * Get all cm handle references under a registered DMI plugin.
+ *
+ * @param cmHandleQueryParameters DMI plugin identifier
+ * @param outputAlternateId Boolean for cm handle reference type either
+ * cm handle id (False) or alternate id (True)
+ * @return list of cm handle IDs
+ */
@Override
- public ResponseEntity<List<String>> searchCmHandleIds(final CmHandleQueryParameters cmHandleQueryParameters) {
+ public ResponseEntity<List<String>> searchCmHandleIds(final CmHandleQueryParameters cmHandleQueryParameters,
+ final Boolean outputAlternateId) {
final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = ncmpRestInputMapper
.toCmHandleQueryServiceParameters(cmHandleQueryParameters);
final Collection<String> cmHandleIds = networkCmProxyInventoryFacade
- .executeParameterizedCmHandleIdSearch(cmHandleQueryServiceParameters);
+ .executeParameterizedCmHandleIdSearch(cmHandleQueryServiceParameters, outputAlternateId);
return ResponseEntity.ok(List.copyOf(cmHandleIds));
}
@@ -85,7 +94,7 @@ public class NetworkCmProxyInventoryController implements NetworkCmProxyInventor
public ResponseEntity updateDmiPluginRegistration(
final @Valid RestDmiPluginRegistration restDmiPluginRegistration) {
final DmiPluginRegistrationResponse dmiPluginRegistrationResponse =
- networkCmProxyInventoryFacade.updateDmiRegistrationAndSyncModule(
+ networkCmProxyInventoryFacade.updateDmiRegistration(
ncmpRestInputMapper.toDmiPluginRegistration(restDmiPluginRegistration));
final DmiPluginRegistrationErrorResponse failedRegistrationErrorResponse =
getFailureRegistrationResponse(dmiPluginRegistrationResponse);
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
index 43403fa890..5340c6d93f 100644
--- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
@@ -363,7 +363,7 @@ class NetworkCmProxyControllerSpec extends Specification {
given: 'an endpoint and json data'
def searchesEndpoint = "$ncmpBasePathV1/ch/id-searches"
and: 'the service method is invoked with module names and returns cm handle ids'
- 1 * mockNetworkCmProxyInventoryFacade.executeCmHandleIdSearch(_) >> ['ch-1', 'ch-2']
+ 1 * mockNetworkCmProxyInventoryFacade.executeCmHandleIdSearch(_, _) >> ['ch-1', 'ch-2']
when: 'the searches api is invoked'
def response = mvc.perform(post(searchesEndpoint).contentType(MediaType.APPLICATION_JSON).content('{}')).andReturn().response
then: 'cm handle ids are returned'
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy
index 97c68f08f3..74e6759f72 100644
--- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy
@@ -1,7 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021-2022 Bell Canada
- * Modifications Copyright (C) 2021-2023 Nordix Foundation
+ * Modifications 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.
@@ -84,7 +84,7 @@ class NetworkCmProxyInventoryControllerSpec extends Specification {
.content(jsonData)
).andReturn().response
then: 'the converted object is forwarded to the registration service'
- 1 * mockNetworkCmProxyInventoryFacade.updateDmiRegistrationAndSyncModule(mockDmiPluginRegistration) >> new DmiPluginRegistrationResponse()
+ 1 * mockNetworkCmProxyInventoryFacade.updateDmiRegistration(mockDmiPluginRegistration) >> new DmiPluginRegistrationResponse()
and: 'response status is no content'
response.status == HttpStatus.OK.value()
where: 'the following registration json is used'
@@ -113,7 +113,7 @@ class NetworkCmProxyInventoryControllerSpec extends Specification {
and: 'the mapper service returns a converted object'
ncmpRestInputMapper.toCmHandleQueryServiceParameters(_) >> cmHandleQueryServiceParameters
and: 'the service returns the desired results'
- mockNetworkCmProxyInventoryFacade.executeParameterizedCmHandleIdSearch(cmHandleQueryServiceParameters) >> serviceMockResponse
+ mockNetworkCmProxyInventoryFacade.executeParameterizedCmHandleIdSearch(cmHandleQueryServiceParameters, _) >> serviceMockResponse
when: 'post request is performed & search is called with the given request parameters'
def response = mvc.perform(
post("$ncmpBasePathV1/ch/searches")
@@ -136,7 +136,7 @@ class NetworkCmProxyInventoryControllerSpec extends Specification {
and: 'the mapper service returns a converted object'
ncmpRestInputMapper.toCmHandleQueryServiceParameters(_) >> cmHandleQueryServiceParameters
and: 'the service returns the desired results'
- mockNetworkCmProxyInventoryFacade.executeParameterizedCmHandleIdSearch(cmHandleQueryServiceParameters) >> serviceMockResponse
+ mockNetworkCmProxyInventoryFacade.executeParameterizedCmHandleIdSearch(cmHandleQueryServiceParameters, _) >> serviceMockResponse
when: 'post request is performed & search is called with the given request parameters'
def response = mvc.perform(
post("$ncmpBasePathV1/ch/searches")
@@ -181,7 +181,7 @@ class NetworkCmProxyInventoryControllerSpec extends Specification {
updatedCmHandles: [CmHandleRegistrationResponse.createSuccessResponse('cm-handle-2')],
removedCmHandles: [CmHandleRegistrationResponse.createSuccessResponse('cm-handle-3')]
)
- mockNetworkCmProxyInventoryFacade.updateDmiRegistrationAndSyncModule(*_) >> dmiRegistrationResponse
+ mockNetworkCmProxyInventoryFacade.updateDmiRegistration(*_) >> dmiRegistrationResponse
when: 'registration endpoint is invoked'
def response = mvc.perform(
post("$ncmpBasePathV1/ch")
@@ -205,7 +205,7 @@ class NetworkCmProxyInventoryControllerSpec extends Specification {
removedCmHandles: [removeCmHandleResponse],
upgradedCmHandles: [upgradeCmHandleResponse]
)
- mockNetworkCmProxyInventoryFacade.updateDmiRegistrationAndSyncModule(*_) >> dmiRegistrationResponse
+ mockNetworkCmProxyInventoryFacade.updateDmiRegistration(*_) >> dmiRegistrationResponse
when: 'registration endpoint is invoked'
def response = mvc.perform(
post("$ncmpBasePathV1/ch")
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy
index e87acacc74..c75058bfd6 100644
--- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy
@@ -35,7 +35,6 @@ import org.onap.cps.ncmp.api.inventory.NetworkCmProxyInventoryFacade
import org.onap.cps.ncmp.impl.data.NcmpCachedResourceRequestHandler
import org.onap.cps.ncmp.impl.data.NcmpPassthroughResourceRequestHandler
import org.onap.cps.ncmp.impl.data.NetworkCmProxyFacade
-import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
import org.onap.cps.ncmp.rest.util.CmHandleStateMapper
import org.onap.cps.ncmp.rest.util.DataOperationRequestMapper
@@ -170,7 +169,7 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
if (NCMP == apiType) {
mockNetworkCmProxyInventoryFacade.getYangResourcesModuleReferences(*_) >> { throw exception }
}
- mockNetworkCmProxyInventoryFacade.updateDmiRegistrationAndSyncModule(*_) >> { throw exception }
+ mockNetworkCmProxyInventoryFacade.updateDmiRegistration(*_) >> { throw exception }
}
def performTestRequest(apiType) {
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
index 1fa801c3c5..e9e5f5499f 100644
--- 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
@@ -29,7 +29,6 @@ import static org.onap.cps.ncmp.impl.inventory.CmHandleQueryParametersValidator.
import java.util.Collection;
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;
@@ -51,7 +50,6 @@ import org.onap.cps.spi.model.ModuleReference;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.stereotype.Service;
-@Slf4j
@Service
@RequiredArgsConstructor
public class NetworkCmProxyInventoryFacade {
@@ -64,15 +62,16 @@ public class NetworkCmProxyInventoryFacade {
private final TrustLevelManager trustLevelManager;
private final AlternateIdMatcher alternateIdMatcher;
+
+
/**
* 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);
+ public DmiPluginRegistrationResponse updateDmiRegistration(final DmiPluginRegistration dmiPluginRegistration) {
+ return cmHandleRegistrationService.updateDmiRegistration(dmiPluginRegistration);
}
/**
@@ -89,12 +88,16 @@ public class NetworkCmProxyInventoryFacade {
* Get all cm handle IDs by various properties.
*
* @param cmHandleQueryServiceParameters cm handle query parameters
- * @return collection of cm handle IDs
+ * @param outputAlternateId Boolean for cm handle reference type either
+ * cm handle id (false) or alternate id (true)
+ * @return collection of cm handle IDs
*/
public Collection<String> executeParameterizedCmHandleIdSearch(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final Boolean outputAlternateId) {
validateCmHandleQueryParameters(cmHandleQueryServiceParameters, InventoryQueryConditions.ALL_CONDITION_NAMES);
- return parameterizedCmHandleQueryService.queryCmHandleIdsForInventory(cmHandleQueryServiceParameters);
+
+ return parameterizedCmHandleQueryService.queryCmHandleIdsForInventory(cmHandleQueryServiceParameters,
+ outputAlternateId);
}
@@ -156,13 +159,16 @@ public class NetworkCmProxyInventoryFacade {
* Retrieve cm handle ids for the given query parameters.
*
* @param cmHandleQueryApiParameters cm handle query parameters
+ * @param outputAlternateId boolean for cm handle reference type either cmHandleId (false) or AlternateId (true)
* @return cm handle ids
*/
- public Collection<String> executeCmHandleIdSearch(final CmHandleQueryApiParameters cmHandleQueryApiParameters) {
+ public Collection<String> executeCmHandleIdSearch(final CmHandleQueryApiParameters cmHandleQueryApiParameters,
+ final Boolean outputAlternateId) {
final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType(
cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class);
validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES);
- return parameterizedCmHandleQueryService.queryCmHandleIds(cmHandleQueryServiceParameters);
+ return parameterizedCmHandleQueryService.queryCmHandleReferenceIds(cmHandleQueryServiceParameters,
+ outputAlternateId);
}
/**
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java
index 5343a2e131..b9b295a8a0 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java
@@ -28,16 +28,13 @@ import static org.onap.cps.ncmp.api.data.models.DatastoreType.OPERATIONAL;
import java.util.Collection;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.data.models.CmResourceAddress;
import org.onap.cps.ncmp.api.data.models.DataOperationRequest;
import org.onap.cps.ncmp.api.data.models.DatastoreType;
import org.onap.cps.ncmp.api.data.models.OperationType;
-import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher;
import org.onap.cps.spi.model.DataNode;
import org.springframework.stereotype.Service;
-@Slf4j
@Service
@RequiredArgsConstructor
public class NetworkCmProxyFacade {
@@ -45,7 +42,6 @@ public class NetworkCmProxyFacade {
private final NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler;
private final NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler;
private final DmiDataOperations dmiDataOperations;
- private final AlternateIdMatcher alternateIdMatcher;
/**
* Fetches resource data for a given data store using DMI (Data Management Interface).
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java
index 95c3c77b71..86e9c934ce 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java
@@ -32,25 +32,31 @@ public interface CmHandleQueryService {
* Query Cm Handles based on additional (private) properties.
*
* @param additionalPropertyQueryPairs private properties for query
+ * @param outputAlternateId boolean for cm handle reference type either cmHandleId (false) or AlternateId (true)
* @return Ids of Cm Handles which have these private properties
*/
- Collection<String> queryCmHandleAdditionalProperties(Map<String, String> additionalPropertyQueryPairs);
+ Collection<String> queryCmHandleAdditionalProperties(Map<String, String> additionalPropertyQueryPairs,
+ Boolean outputAlternateId);
/**
* Query Cm Handles based on public properties.
*
* @param publicPropertyQueryPairs public properties for query
+ * @param outputAlternateId boolean for cm handle reference type either cmHandleId (false) or AlternateId (true)
* @return CmHandles which have these public properties
*/
- Collection<String> queryCmHandlePublicProperties(Map<String, String> publicPropertyQueryPairs);
+ Collection<String> queryCmHandlePublicProperties(Map<String, String> publicPropertyQueryPairs,
+ Boolean outputAlternateId);
/**
* Query Cm Handles based on Trust Level.
*
* @param trustLevelPropertyQueryPairs trust level properties for query
+ * @param outputAlternateId boolean for cm handle reference type either cmHandleId (false) or AlternateId (true)
* @return Ids of Cm Handles which have desired trust level
*/
- Collection<String> queryCmHandlesByTrustLevel(Map<String, String> trustLevelPropertyQueryPairs);
+ Collection<String> queryCmHandlesByTrustLevel(Map<String, String> trustLevelPropertyQueryPairs,
+ Boolean outputAlternateId);
/**
* Method which returns cm handles by the cm handles state.
@@ -101,4 +107,12 @@ public interface CmHandleQueryService {
*/
Collection<String> getCmHandleIdsByDmiPluginIdentifier(String dmiPluginIdentifier);
+ /**
+ * Get map of cmHandle ids and alternate ids by DMI plugin identifier.
+ *
+ * @param dmiPluginIdentifier DMI plugin identifier
+ * @return map of cmHandle references key:CmHandleId Value:AlternateId
+ */
+ Map<String, String> getCmHandleReferencesByDmiPluginIdentifier(String dmiPluginIdentifier);
+
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java
index 71e7384208..4249b452c3 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java
@@ -29,6 +29,7 @@ import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.stream.Collectors;
@@ -53,6 +54,7 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService {
private static final String DESCENDANT_PATH = "//";
private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles";
+ private static final String ALTERNATE_ID = "alternate-id";
private final CpsDataService cpsDataService;
private final CpsQueryService cpsQueryService;
@@ -65,21 +67,23 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService {
private final CpsValidator cpsValidator;
@Override
- public Collection<String> queryCmHandleAdditionalProperties(final Map<String, String> privatePropertyQueryPairs) {
- return queryCmHandleAnyProperties(privatePropertyQueryPairs, PropertyType.ADDITIONAL);
+ public Collection<String> queryCmHandleAdditionalProperties(final Map<String, String> privatePropertyQueryPairs,
+ final Boolean outputAlternateId) {
+ return queryCmHandleAnyProperties(privatePropertyQueryPairs, PropertyType.ADDITIONAL, outputAlternateId);
}
@Override
- public Collection<String> queryCmHandlePublicProperties(final Map<String, String> publicPropertyQueryPairs) {
- return queryCmHandleAnyProperties(publicPropertyQueryPairs, PropertyType.PUBLIC);
+ public Collection<String> queryCmHandlePublicProperties(final Map<String, String> publicPropertyQueryPairs,
+ final Boolean outputAlternateId) {
+ return queryCmHandleAnyProperties(publicPropertyQueryPairs, PropertyType.PUBLIC, outputAlternateId);
}
@Override
- public Collection<String> queryCmHandlesByTrustLevel(final Map<String, String> trustLevelPropertyQueryPairs) {
+ public Collection<String> queryCmHandlesByTrustLevel(final Map<String, String> trustLevelPropertyQueryPairs,
+ final Boolean outputAlternateId) {
final String trustLevelProperty = trustLevelPropertyQueryPairs.values().iterator().next();
final TrustLevel targetTrustLevel = TrustLevel.valueOf(trustLevelProperty);
-
- return getCmHandleIdsByTrustLevel(targetTrustLevel);
+ return getCmHandleReferencesByTrustLevel(targetTrustLevel, outputAlternateId);
}
@Override
@@ -130,37 +134,64 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService {
return cmHandleIds;
}
- private Collection<String> getCmHandleIdsByTrustLevel(final TrustLevel targetTrustLevel) {
- final Collection<String> selectedCmHandleIds = new HashSet<>();
+ @Override
+ public Map<String, String> getCmHandleReferencesByDmiPluginIdentifier(final String dmiPluginIdentifier) {
+ final Map<String, String> cmHandleReferencesMap = new HashMap<>();
+ for (final ModelledDmiServiceLeaves modelledDmiServiceLeaf : ModelledDmiServiceLeaves.values()) {
+ for (final DataNode cmHandleAsDataNode: getCmHandlesByDmiPluginIdentifierAndDmiProperty(
+ dmiPluginIdentifier,
+ modelledDmiServiceLeaf.getLeafName())) {
+ cmHandleReferencesMap.put(cmHandleAsDataNode.getLeaves().get("id").toString(),
+ cmHandleAsDataNode.getLeaves().get(ALTERNATE_ID).toString());
+ }
+ }
+ return cmHandleReferencesMap;
+ }
+
+ private Collection<String> getCmHandleReferencesByTrustLevel(final TrustLevel targetTrustLevel,
+ final Boolean outputAlternateId) {
+ final Collection<String> selectedCmHandleReferences = new HashSet<>();
for (final Map.Entry<String, TrustLevel> mapEntry : trustLevelPerDmiPlugin.entrySet()) {
final String dmiPluginIdentifier = mapEntry.getKey();
final TrustLevel dmiTrustLevel = mapEntry.getValue();
- final Collection<String> candidateCmHandleIds = getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifier);
- for (final String candidateCmHandleId : candidateCmHandleIds) {
- final TrustLevel candidateCmHandleTrustLevel = trustLevelPerCmHandle.get(candidateCmHandleId);
+ final Map<String, String> candidateCmHandleReferences =
+ getCmHandleReferencesByDmiPluginIdentifier(dmiPluginIdentifier);
+ for (final Map.Entry<String, String> candidateCmHandleReference : candidateCmHandleReferences.entrySet()) {
+ final TrustLevel candidateCmHandleTrustLevel =
+ trustLevelPerCmHandle.get(candidateCmHandleReference.getKey());
final TrustLevel effectiveTrustlevel =
candidateCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel);
if (targetTrustLevel.equals(effectiveTrustlevel)) {
- selectedCmHandleIds.add(candidateCmHandleId);
+ if (Boolean.TRUE.equals(outputAlternateId)) {
+ selectedCmHandleReferences.add(candidateCmHandleReference.getValue());
+ } else {
+ selectedCmHandleReferences.add(candidateCmHandleReference.getKey());
+ }
}
}
}
-
- return selectedCmHandleIds;
+ return selectedCmHandleReferences;
}
- private Collection<String> collectCmHandleIdsFromDataNodes(final Collection<DataNode> dataNodes) {
- return dataNodes.stream().map(dataNode -> (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet());
+ private Collection<String> collectCmHandleReferencesFromDataNodes(final Collection<DataNode> dataNodes,
+ final Boolean outputAlternateId) {
+ if (Boolean.TRUE.equals(outputAlternateId)) {
+ return dataNodes.stream().map(dataNode ->
+ (String) dataNode.getLeaves().get(ALTERNATE_ID)).collect(Collectors.toSet());
+ } else {
+ return dataNodes.stream().map(dataNode ->
+ (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet());
+ }
}
private Collection<String> queryCmHandleAnyProperties(
final Map<String, String> propertyQueryPairs,
- final PropertyType propertyType) {
+ final PropertyType propertyType, final Boolean outputAlternateId) {
if (propertyQueryPairs.isEmpty()) {
return Collections.emptySet();
}
- Collection<String> cmHandleIds = null;
+ Collection<String> cmHandleReferences = null;
for (final Map.Entry<String, String> publicPropertyQueryPair : propertyQueryPairs.entrySet()) {
final String cpsPath = DESCENDANT_PATH + propertyType.getYangContainerName() + "[@name=\""
+ publicPropertyQueryPair.getKey()
@@ -168,17 +199,18 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService {
final Collection<DataNode> dataNodes = queryCmHandleAncestorsByCpsPath(cpsPath,
OMIT_DESCENDANTS);
- if (cmHandleIds == null) {
- cmHandleIds = collectCmHandleIdsFromDataNodes(dataNodes);
+ if (cmHandleReferences == null) {
+ cmHandleReferences = collectCmHandleReferencesFromDataNodes(dataNodes, outputAlternateId);
} else {
- final Collection<String> cmHandleIdsToRetain = collectCmHandleIdsFromDataNodes(dataNodes);
- cmHandleIds.retainAll(cmHandleIdsToRetain);
+ final Collection<String> cmHandleReferencesToRetain;
+ cmHandleReferencesToRetain = collectCmHandleReferencesFromDataNodes(dataNodes, outputAlternateId);
+ cmHandleReferences.retainAll(cmHandleReferencesToRetain);
}
- if (cmHandleIds.isEmpty()) {
+ if (cmHandleReferences.isEmpty()) {
break;
}
}
- return cmHandleIds;
+ return cmHandleReferences;
}
private Collection<DataNode> getCmHandlesByDmiPluginIdentifierAndDmiProperty(final String dmiPluginIdentifier,
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java
index d9f7e38993..cb55b09d41 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java
@@ -87,8 +87,7 @@ public class CmHandleRegistrationService {
* @param dmiPluginRegistration Dmi Plugin Registration details
* @return dmiPluginRegistrationResponse
*/
- public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(
- final DmiPluginRegistration dmiPluginRegistration) {
+ public DmiPluginRegistrationResponse updateDmiRegistration(final DmiPluginRegistration dmiPluginRegistration) {
dmiPluginRegistration.validateDmiPluginRegistration();
final DmiPluginRegistrationResponse dmiPluginRegistrationResponse = new DmiPluginRegistrationResponse();
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java
index a0d3a3eaee..850edf7d57 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistence.java
@@ -149,9 +149,12 @@ public interface InventoryPersistence extends NcmpPersistence {
* get CM handles that has given module names.
*
* @param moduleNamesForQuery module names
+ * @param outputAlternateIds Boolean for cm handle reference type either
+ * cm handle id (false or null) or alternate id (true)
* @return Collection of CM handle Ids
*/
- Collection<String> getCmHandleIdsWithGivenModules(Collection<String> moduleNamesForQuery);
+ Collection<String> getCmHandleReferencesWithGivenModules(Collection<String> moduleNamesForQuery,
+ Boolean outputAlternateIds);
/**
* Check database if cm handle id exists if not return false.
@@ -159,5 +162,5 @@ public interface InventoryPersistence extends NcmpPersistence {
* @param cmHandleId cmHandle Id
* @return Boolean
*/
- boolean isExistingCmHandleId(String cmHandleId);
+ Boolean isExistingCmHandleId(String cmHandleId);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
index 06c3f8d2f4..655d8437b1 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImpl.java
@@ -201,12 +201,19 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
}
@Override
- public Collection<String> getCmHandleIdsWithGivenModules(final Collection<String> moduleNamesForQuery) {
- return cpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery);
+ public Collection<String> getCmHandleReferencesWithGivenModules(final Collection<String> moduleNamesForQuery,
+ final Boolean outputAlternateIds) {
+ if (Boolean.TRUE.equals(outputAlternateIds)) {
+ final Collection<String> cmHandleIds =
+ cpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery);
+ return getAlternateIdsFromDataNodes(getCmHandleDataNodes(cmHandleIds));
+ } else {
+ return cpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, moduleNamesForQuery);
+ }
}
@Override
- public boolean isExistingCmHandleId(final String cmHandleId) {
+ public Boolean isExistingCmHandleId(final String cmHandleId) {
try {
return !getCmHandleDataNodeByCmHandleId(cmHandleId).isEmpty();
} catch (final DataNodeNotFoundException exception) {
@@ -234,4 +241,9 @@ public class InventoryPersistenceImpl extends NcmpPersistenceImpl implements Inv
private String createCmHandlesJsonData(final List<YangModelCmHandle> yangModelCmHandles) {
return "{\"cm-handles\":" + jsonObjectMapper.asJsonString(yangModelCmHandles) + "}";
}
+
+ private Collection<String> getAlternateIdsFromDataNodes(final Collection<DataNode> dataNodes) {
+ return dataNodes.stream().map(dataNode ->
+ (String) dataNode.getLeaves().get("alternate-id")).collect(Collectors.toSet());
+ }
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java
index e5848c0dfa..8301579b42 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryService.java
@@ -26,19 +26,22 @@ import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
public interface ParameterizedCmHandleQueryService {
/**
- * Query and return cm handle ids that match the given query parameters.
+ * Query and return cm handle ids or alternate ids that match the given query parameters.
* Supported query types:
* public properties
* modules
* cps-path
*
* @param cmHandleQueryServiceParameters the cm handle query parameters
- * @return collection of cm handle ids
+ * @param outputAlternateId Boolean for cm handle reference type either
+ * cm handle id (false or null) or alternate id (true)
+ * @return collection of cm handle ids or alternate ids
*/
- Collection<String> queryCmHandleIds(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
+ Collection<String> queryCmHandleReferenceIds(CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
+ Boolean outputAlternateId);
/**
- * Query and return cm handle ids that match the given query parameters.
+ * Query and return cm handle ids or alternate ids that match the given query parameters.
* Supported query types:
* public properties
* private (additional) properties
@@ -46,9 +49,12 @@ public interface ParameterizedCmHandleQueryService {
* The inventory interface also allows conditions on private (additional) properties and dmi names
*
* @param cmHandleQueryServiceParameters the cm handle query parameters
+ * @param outputAlternateId Boolean for cm handle reference type either
+ * cm handle id (false or null) or alternate id (true)
* @return collection of cm handle ids
*/
- Collection<String> queryCmHandleIdsForInventory(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
+ Collection<String> queryCmHandleIdsForInventory(CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
+ Boolean outputAlternateId);
/**
* Query and return cm handle objects that match the given query parameters.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java
index 34eeaccf8f..bacbbe0c95 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceImpl.java
@@ -37,10 +37,9 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.function.Function;
+import java.util.function.BiFunction;
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.inventory.models.CmHandleQueryServiceParameters;
import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
@@ -54,7 +53,6 @@ import org.onap.cps.spi.model.DataNode;
import org.springframework.stereotype.Service;
@Service
-@Slf4j
@RequiredArgsConstructor
public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHandleQueryService {
@@ -63,19 +61,21 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
private final InventoryPersistence inventoryPersistence;
@Override
- public Collection<String> queryCmHandleIds(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
- return executeQueries(cmHandleQueryServiceParameters,
- this::executeCpsPathQuery,
- this::queryCmHandlesByPublicProperties,
- this::executeModuleNameQuery,
- this::queryCmHandlesByTrustLevel);
+ public Collection<String> queryCmHandleReferenceIds(
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
+ final Boolean outputAlternateId) {
+ return executeQueries(cmHandleQueryServiceParameters, outputAlternateId,
+ this::executeCpsPathQuery,
+ this::queryCmHandlesByPublicProperties,
+ this::executeModuleNameQuery,
+ this::queryCmHandlesByTrustLevel);
}
@Override
public Collection<String> queryCmHandleIdsForInventory(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
- return executeQueries(cmHandleQueryServiceParameters,
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
+ final Boolean outputAlternateId) {
+ return executeQueries(cmHandleQueryServiceParameters, outputAlternateId,
this::executeCpsPathQuery,
this::queryCmHandlesByPublicProperties,
this::queryCmHandlesByPrivateProperties,
@@ -90,7 +90,7 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
return getAllCmHandles();
}
- final Collection<String> cmHandleIds = queryCmHandleIds(cmHandleQueryServiceParameters);
+ final Collection<String> cmHandleIds = queryCmHandleReferenceIds(cmHandleQueryServiceParameters, false);
return getNcmpServiceCmHandles(cmHandleIds);
}
@@ -102,7 +102,7 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
}
private Collection<String> queryCmHandlesByDmiPlugin(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final Boolean outputAlternateId) {
final Map<String, String> dmiPropertyQueryPairs =
getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
InventoryQueryConditions.CM_HANDLE_WITH_DMI_PLUGIN.getName());
@@ -113,11 +113,15 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
final String dmiPluginIdentifierValue = dmiPropertyQueryPairs
.get(PropertyType.DMI_PLUGIN.getYangContainerName());
- return cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifierValue);
+ if (Boolean.TRUE.equals(outputAlternateId)) {
+ return cmHandleQueryService.getCmHandleReferencesByDmiPluginIdentifier(dmiPluginIdentifierValue).values();
+ } else {
+ return cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiPluginIdentifierValue);
+ }
}
private Collection<String> queryCmHandlesByPrivateProperties(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final Boolean outputAlternateId) {
final Map<String, String> privatePropertyQueryPairs =
getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
@@ -126,11 +130,11 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
if (privatePropertyQueryPairs.isEmpty()) {
return NO_QUERY_TO_EXECUTE;
}
- return cmHandleQueryService.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
+ return cmHandleQueryService.queryCmHandleAdditionalProperties(privatePropertyQueryPairs, outputAlternateId);
}
private Collection<String> queryCmHandlesByPublicProperties(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final Boolean outputAlternateId) {
final Map<String, String> publicPropertyQueryPairs =
getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
@@ -139,11 +143,12 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
if (publicPropertyQueryPairs.isEmpty()) {
return NO_QUERY_TO_EXECUTE;
}
- return cmHandleQueryService.queryCmHandlePublicProperties(publicPropertyQueryPairs);
+ return cmHandleQueryService.queryCmHandlePublicProperties(publicPropertyQueryPairs, outputAlternateId);
}
private Collection<String> queryCmHandlesByTrustLevel(final CmHandleQueryServiceParameters
- cmHandleQueryServiceParameters) {
+ cmHandleQueryServiceParameters,
+ final Boolean outputAlternateId) {
final Map<String, String> trustLevelPropertyQueryPairs =
getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
@@ -152,21 +157,21 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
if (trustLevelPropertyQueryPairs.isEmpty()) {
return NO_QUERY_TO_EXECUTE;
}
- return cmHandleQueryService.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs);
+ return cmHandleQueryService.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs, outputAlternateId);
}
private Collection<String> executeModuleNameQuery(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final Boolean outputAlternateId) {
final Collection<String> moduleNamesForQuery =
getModuleNamesForQuery(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
if (moduleNamesForQuery.isEmpty()) {
return NO_QUERY_TO_EXECUTE;
}
- return inventoryPersistence.getCmHandleIdsWithGivenModules(moduleNamesForQuery);
+ return inventoryPersistence.getCmHandleReferencesWithGivenModules(moduleNamesForQuery, outputAlternateId);
}
private Collection<String> executeCpsPathQuery(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters, final Boolean outputAlternateId) {
final Map<String, String> cpsPathCondition
= getCpsPathCondition(cmHandleQueryServiceParameters.getCmHandleQueryParameters());
if (!validateCpsPathConditionProperties(cpsPathCondition)) {
@@ -177,9 +182,9 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
return NO_QUERY_TO_EXECUTE;
}
try {
- cpsPathQueryResult = collectCmHandleIdsFromDataNodes(
- cmHandleQueryService.queryCmHandleAncestorsByCpsPath(
- cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS));
+ cpsPathQueryResult = collectCmHandleReferencesFromDataNodes(
+ cmHandleQueryService.queryCmHandleAncestorsByCpsPath(cpsPathCondition.get("cpsPath"), OMIT_DESCENDANTS),
+ outputAlternateId);
} catch (final PathParsingException pathParsingException) {
throw new DataValidationException(pathParsingException.getMessage(), pathParsingException.getDetails(),
pathParsingException);
@@ -220,10 +225,10 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
return Collections.emptyList();
}
- private Collection<String> getAllCmHandleIds() {
+ private Collection<String> getAllCmHandleReferences(final Boolean outputAlternateId) {
final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, DIRECT_CHILDREN_ONLY)
- .iterator().next();
- return collectCmHandleIdsFromDataNodes(dataNode.getChildDataNodes());
+ .iterator().next();
+ return collectCmHandleReferencesFromDataNodes(dataNode.getChildDataNodes(), outputAlternateId);
}
private Collection<NcmpServiceCmHandle> getNcmpServiceCmHandles(final Collection<String> cmHandleIds) {
@@ -243,14 +248,17 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
}
private Collection<String> executeQueries(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
- final Function<CmHandleQueryServiceParameters, Collection<String>>...
- queryFunctions) {
+ final Boolean outputAlternateId,
+ final BiFunction<CmHandleQueryServiceParameters, Boolean,
+ Collection<String>>... queryFunctions) {
if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
- return getAllCmHandleIds();
+ return getAllCmHandleReferences(outputAlternateId);
}
Collection<String> combinedQueryResult = NO_QUERY_TO_EXECUTE;
- for (final Function<CmHandleQueryServiceParameters, Collection<String>> queryFunction : queryFunctions) {
- final Collection<String> queryResult = queryFunction.apply(cmHandleQueryServiceParameters);
+ for (final BiFunction<CmHandleQueryServiceParameters, Boolean,
+ Collection<String>> queryFunction : queryFunctions) {
+ final Collection<String> queryResult = queryFunction.apply(cmHandleQueryServiceParameters,
+ outputAlternateId);
if (noEntriesFoundCanStopQuerying(queryResult)) {
return Collections.emptySet();
}
@@ -277,8 +285,14 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
}
}
- private Collection<String> collectCmHandleIdsFromDataNodes(final Collection<DataNode> dataNodes) {
- return dataNodes.stream().map(dataNode -> (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet());
+ private Collection<String> collectCmHandleReferencesFromDataNodes(final Collection<DataNode> dataNodes,
+ final Boolean outputAlternateId) {
+ if (Boolean.TRUE.equals(outputAlternateId)) {
+ return dataNodes.stream().map(dataNode ->
+ (String) dataNode.getLeaves().get("alternate-id")).collect(Collectors.toSet());
+ } else {
+ return dataNodes.stream().map(dataNode ->
+ (String) dataNode.getLeaves().get("id")).collect(Collectors.toSet());
+ }
}
-
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java
index 4061298cd0..898b8d5bf4 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java
@@ -32,6 +32,7 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.Sleeper;
import org.onap.cps.spi.model.DataNode;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@@ -47,6 +48,7 @@ public class ModuleSyncWatchdog {
private final ModuleSyncTasks moduleSyncTasks;
private final AsyncTaskExecutor asyncTaskExecutor;
private final Lock workQueueLock;
+ private final Sleeper sleeper;
private static final int MODULE_SYNC_BATCH_SIZE = 100;
private static final long PREVENT_CPU_BURN_WAIT_TIME_MILLIS = 10;
@@ -59,9 +61,10 @@ public class ModuleSyncWatchdog {
* Check DB for any cm handles in 'ADVISED' state.
* Queue and create batches to process them asynchronously.
* This method will only finish when there are no more 'ADVISED' cm handles in the DB.
- * This method wil be triggered on a configurable interval
+ * This method is triggered on a configurable interval (ncmp.timers.advised-modules-sync.sleep-time-ms)
*/
- @Scheduled(fixedDelayString = "${ncmp.timers.advised-modules-sync.sleep-time-ms:5000}")
+ @Scheduled(initialDelayString = "${test.ncmp.timers.advised-modules-sync.initial-delay-ms:0}",
+ fixedDelayString = "${ncmp.timers.advised-modules-sync.sleep-time-ms:5000}")
public void moduleSyncAdvisedCmHandles() {
log.debug("Processing module sync watchdog waking up.");
populateWorkQueueIfNeeded();
@@ -82,26 +85,20 @@ public class ModuleSyncWatchdog {
}
}
- private void preventBusyWait() {
- try {
- log.debug("Busy waiting now");
- TimeUnit.MILLISECONDS.sleep(PREVENT_CPU_BURN_WAIT_TIME_MILLIS);
- } catch (final InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
-
- private void populateWorkQueueIfNeeded() {
- if (moduleSyncWorkQueue.isEmpty()) {
- if (workQueueLock.tryLock()) {
- try {
- populateWorkQueue();
- if (moduleSyncWorkQueue.isEmpty()) {
- setPreviouslyLockedCmHandlesToAdvised();
- }
- } finally {
- workQueueLock.unlock();
+ /**
+ * Populate work queue with advised cm handles from db.
+ * This method is made public for (integration) testing purposes.
+ * So it can be tested without the queue being emptied immediately as the main public method does.
+ */
+ public void populateWorkQueueIfNeeded() {
+ if (moduleSyncWorkQueue.isEmpty() && workQueueLock.tryLock()) {
+ try {
+ populateWorkQueue();
+ if (moduleSyncWorkQueue.isEmpty()) {
+ setPreviouslyLockedCmHandlesToAdvised();
}
+ } finally {
+ workQueueLock.unlock();
}
}
}
@@ -156,4 +153,13 @@ public class ModuleSyncWatchdog {
log.info("nextBatch size : {}", nextBatch.size());
return nextBatch;
}
+
+ private void preventBusyWait() {
+ try {
+ log.debug("Busy waiting now");
+ sleeper.haveALittleRest(PREVENT_CPU_BURN_WAIT_TIME_MILLIS);
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/Sleeper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/Sleeper.java
new file mode 100644
index 0000000000..7a02fa06e0
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/Sleeper.java
@@ -0,0 +1,35 @@
+/*
+ * ============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 java.util.concurrent.TimeUnit;
+import org.springframework.stereotype.Service;
+
+/**
+ * This class is to extract out sleep functionality so the interrupted exception handling can
+ * be covered with a test (e.g. using spy on Sleeper) and help to get to 100% code coverage.
+ */
+@Service
+public class Sleeper {
+ public void haveALittleRest(final long timeInMillis) throws InterruptedException {
+ TimeUnit.MILLISECONDS.sleep(timeInMillis);
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacadeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacadeSpec.groovy
index 5f83ad5f83..c62e93c214 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacadeSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacadeSpec.groovy
@@ -42,9 +42,8 @@ class NetworkCmProxyFacadeSpec extends Specification {
def mockDmiDataOperations = Mock(DmiDataOperations)
def mockNcmpCachedResourceRequestHandler = Mock(NcmpCachedResourceRequestHandler)
def mockNcmpPassthroughResourceRequestHandler = Mock(NcmpPassthroughResourceRequestHandler)
- def mockAlternateIdMatcher = Mock(AlternateIdMatcher)
- def objectUnderTest = new NetworkCmProxyFacade(mockNcmpCachedResourceRequestHandler, mockNcmpPassthroughResourceRequestHandler, mockDmiDataOperations, mockAlternateIdMatcher)
+ def objectUnderTest = new NetworkCmProxyFacade(mockNcmpCachedResourceRequestHandler, mockNcmpPassthroughResourceRequestHandler, mockDmiDataOperations)
def NO_TOPIC = null
@@ -89,7 +88,6 @@ class NetworkCmProxyFacadeSpec extends Specification {
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'
- mockAlternateIdMatcher.getCmHandleId('some CM Handle') >> 'some CM Handle'
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'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy
index 7e34fe2822..0c50e3d4ee 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy
@@ -64,16 +64,16 @@ class CmHandleQueryServiceImplSpec extends Specification {
given: 'the DataNodes queried for a given cpsPath are returned from the persistence service.'
mockResponses()
when: 'a query on cmhandle public properties is performed with a public property pair'
- def result = objectUnderTest.queryCmHandlePublicProperties(publicPropertyPairs)
+ def result = objectUnderTest.queryCmHandlePublicProperties(publicPropertyPairs, outputAlternateId)
then: 'the correct cm handle data objects are returned'
- result.containsAll(expectedCmHandleIds)
- result.size() == expectedCmHandleIds.size()
+ result.containsAll(expectedCmHandleReferences)
+ result.size() == expectedCmHandleReferences.size()
where: 'the following data is used'
- scenario | publicPropertyPairs || expectedCmHandleIds
- 'single property matches' | [Contact: 'newemailforstore@bookstore.com'] || ['PNFDemo', 'PNFDemo2', 'PNFDemo4']
- 'public property does not match' | [wont_match: 'wont_match'] || []
- '2 properties, only one match' | [Contact: 'newemailforstore@bookstore.com', Contact2: 'newemailforstore2@bookstore.com'] || ['PNFDemo4']
- '2 properties, no matches' | [Contact: 'newemailforstore@bookstore.com', Contact2: ''] || []
+ scenario | publicPropertyPairs | outputAlternateId || expectedCmHandleReferences
+ 'single property matches' | [Contact: 'newemailforstore@bookstore.com'] | false || ['PNFDemo', 'PNFDemo2', 'PNFDemo4']
+ 'public property does not match' | [wont_match: 'wont_match'] | false || []
+ '2 properties, only one match' | [Contact: 'newemailforstore@bookstore.com', Contact2: 'newemailforstore2@bookstore.com'] | true || ['alt-PNFDemo4']
+ '2 properties, no matches' | [Contact: 'newemailforstore@bookstore.com', Contact2: ''] | false || []
}
def 'Query cm handles on trust level'() {
@@ -84,22 +84,26 @@ class CmHandleQueryServiceImplSpec extends Specification {
and: 'the DataNodes queried for a given cpsPath are returned from the persistence service'
mockResponses()
when: 'the query is run'
- def result = objectUnderTest.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs)
- then: 'the result contain trusted PNFDemo'
+ def result = objectUnderTest.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs, outputAlternateId)
+ then: 'the result contain trusted cmHandle reference'
assert result.size() == 1
- assert result[0] == 'PNFDemo'
+ assert result[0] == expectedCmHandleReference
+ where: 'the following data is used'
+ senario | outputAlternateId | expectedCmHandleReference
+ 'output cmHandleId' | false | 'PNFDemo'
+ 'output AlternateId' | true | 'alt-PNFDemo'
}
def 'Query CmHandles using empty public properties query pair.'() {
when: 'a query on CmHandle public properties is executed using an empty map'
- def result = objectUnderTest.queryCmHandlePublicProperties([:])
+ def result = objectUnderTest.queryCmHandlePublicProperties([:], false)
then: 'no cm handles are returned'
result.size() == 0
}
def 'Query CmHandles using empty private properties query pair.'() {
when: 'a query on CmHandle private properties is executed using an empty map'
- def result = objectUnderTest.queryCmHandleAdditionalProperties([:])
+ def result = objectUnderTest.queryCmHandleAdditionalProperties([:], false)
then: 'no cm handles are returned'
result.size() == 0
}
@@ -108,7 +112,7 @@ class CmHandleQueryServiceImplSpec extends Specification {
given: 'a data node exists with a certain additional-property'
mockCpsQueryService.queryDataNodes(_, _, dataNodeWithPrivateField, _) >> [pnfDemo5]
when: 'a query on CmHandle private properties is executed using a map'
- def result = objectUnderTest.queryCmHandleAdditionalProperties(['Contact3': 'newemailforstore3@bookstore.com'])
+ def result = objectUnderTest.queryCmHandleAdditionalProperties(['Contact3': 'newemailforstore3@bookstore.com'], false)
then: 'one cm handle is returned'
result.size() == 1
}
@@ -206,6 +210,17 @@ class CmHandleQueryServiceImplSpec extends Specification {
assert result.containsAll('PNFDemo', 'PNFDemo2', 'PNFDemo4')
}
+ def 'Get all alternateIds by dmi plugin identifier'() {
+ given: 'the DataNodes queried for a given cpsPath are returned from the persistence service.'
+ mockResponses()
+ when: 'cm Handles are fetched for a given dmi plugin identifier'
+ def result = objectUnderTest.getCmHandleReferencesByDmiPluginIdentifier('my-dmi-plugin-identifier').values()
+ then: 'result is the correct size'
+ assert result.size() == 3
+ and: 'result contains the correct alternate Ids'
+ assert result.containsAll('alt-PNFDemo', 'alt-PNFDemo2', 'alt-PNFDemo4')
+ }
+
void mockResponses() {
mockCpsQueryService.queryDataNodes(_, _, '//public-properties[@name=\"Contact\" and @value=\"newemailforstore@bookstore.com\"]/ancestor::cm-handles', _) >> [pnfDemo, pnfDemo2, pnfDemo4]
mockCpsQueryService.queryDataNodes(_, _, '//public-properties[@name=\"wont_match\" and @value=\"wont_match\"]/ancestor::cm-handles', _) >> []
@@ -219,6 +234,6 @@ class CmHandleQueryServiceImplSpec extends Specification {
}
def static createDataNode(dataNodeId) {
- return new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'' + dataNodeId + '\']', leaves: ['id':dataNodeId])
+ return new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'' + dataNodeId + '\']', leaves: ['id':dataNodeId, 'alternate-id':'alt-' + dataNodeId])
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy
index dcff2e9b89..70e26d993c 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy
@@ -87,7 +87,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
and: 'cm handle is in READY state'
mockCmHandleQueries.cmHandleHasState('cmhandle-3', CmHandleState.READY) >> true
when: 'registration is processed'
- objectUnderTest.updateDmiRegistrationAndSyncModule(dmiRegistration)
+ objectUnderTest.updateDmiRegistration(dmiRegistration)
then: 'cm-handles are removed first'
1 * objectUnderTest.processRemovedCmHandles(*_)
and: 'de-registered cm handle entry is removed from in progress map'
@@ -108,7 +108,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
and: 'exception while checking cm handle state'
mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> new YangModelCmHandle(id: 'cmhandle-3', moduleSetTag: '', compositeState: new CompositeState(cmHandleState: cmHandleState))
when: 'registration is processed'
- def result = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiRegistration)
+ def result = objectUnderTest.updateDmiRegistration(dmiRegistration)
then: 'upgrade operation contains expected error code'
assert result.upgradedCmHandles[0].status == expectedResponseStatus
where: 'the following parameters are used'
@@ -124,7 +124,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
and: 'exception while checking cm handle state'
mockInventoryPersistence.getYangModelCmHandle('cmhandle-3') >> { throw exception }
when: 'registration is processed'
- def result = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiRegistration)
+ def result = objectUnderTest.updateDmiRegistration(dmiRegistration)
then: 'upgrade operation contains expected error code'
assert result.upgradedCmHandles.ncmpResponseStatus.code[0] == expectedErrorCode
where: 'the following parameters are used'
@@ -139,7 +139,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
dmiDataPlugin: dmiDataPlugin)
dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle]
when: 'update registration and sync module is called with correct DMI plugin information'
- objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'create cm handles registration and sync modules is called with the correct plugin information'
1 * objectUnderTest.processCreatedCmHandles(dmiPluginRegistration, _)
where:
@@ -155,7 +155,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
dmiDataPlugin: dmiDataPlugin)
dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle]
when: 'registration is called with incorrect DMI plugin information'
- objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'a DMI Request Exception is thrown with correct message details'
def exceptionThrown = thrown(DmiRequestException.class)
assert exceptionThrown.getMessage().contains(expectedMessageDetails)
@@ -178,7 +178,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
dmiPluginRegistration.createdCmHandles = [new NcmpServiceCmHandle(cmHandleId: 'cmhandle', dmiProperties: dmiProperties, publicProperties: publicProperties)]
when: 'registration is updated'
- def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'a successful response is received'
response.createdCmHandles.size() == 1
with(response.createdCmHandles[0]) {
@@ -206,7 +206,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server',
createdCmHandles:[new NcmpServiceCmHandle(cmHandleId: 'ch-1', registrationTrustLevel: registrationTrustLevel)])
when: 'registration is updated'
- objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'trustLevel is set for the created cm-handle'
1 * mockTrustLevelManager.registerCmHandles(expectedMapping)
where:
@@ -225,7 +225,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
def xpath = "somePathWithId[@id='cmhandle2']"
mockLcmEventsCmHandleStateHandler.initiateStateAdvised(*_) >> { throw AlreadyDefinedException.forDataNodes([xpath], 'some-context') }
when: 'registration is updated to create cm-handles'
- def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'a response is received for all cm-handles'
response.createdCmHandles.size() == 1
and: 'all cm-handles creation fails'
@@ -244,7 +244,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
and: 'cm-handler registration fails: #scenario'
mockLcmEventsCmHandleStateHandler.initiateStateAdvised(*_) >> { throw exception }
when: 'registration is updated'
- def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'a failure response is received'
response.createdCmHandles.size() == 1
with(response.createdCmHandles[0]) {
@@ -269,7 +269,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
CmHandleRegistrationResponse.createFailureResponse('cm handle 4', CM_HANDLE_INVALID_ID)]
mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(_) >> updateOperationResponse
when: 'registration is updated'
- def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'the response contains updateOperationResponse'
assert response.updatedCmHandles.size() == 4
assert response.updatedCmHandles.containsAll(updateOperationResponse)
@@ -281,7 +281,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
and: '#scenario'
mockCpsModuleService.deleteSchemaSetsWithCascade(_, ['cmhandle']) >> { if (!schemaSetExist) { throw new SchemaSetNotFoundException('', '') } }
when: 'registration is updated to delete cmhandle'
- def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'the cmHandle state is updated to "DELETING"'
1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch(_) >>
{ args -> args[0].values()[0] == CmHandleState.DELETING }
@@ -315,7 +315,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
and: 'cm-handle deletion is successful for 1st and 3rd; failed for 2nd'
mockInventoryPersistence.deleteDataNode("/dmi-registry/cm-handles[@id='cmhandle2']") >> { throw new RuntimeException("Failed") }
when: 'registration is updated to delete cmhandles'
- def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'the cmHandle states are all updated to "DELETING"'
1 * mockLcmEventsCmHandleStateHandler.updateCmHandleStateBatch({ assert it.every { entry -> entry.value == CmHandleState.DELETING } })
and: 'a response is received for all cm-handles'
@@ -361,7 +361,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
and: 'schema set single deletion failed with unknown error'
mockInventoryPersistence.deleteSchemaSetWithCascade(_) >> { throw new RuntimeException('Failed') }
when: 'registration is updated to delete cmhandle'
- def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'no exception is thrown'
noExceptionThrown()
and: 'cm-handle is not deleted'
@@ -387,7 +387,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
and: 'cm-handle deletion fails on individual delete'
mockInventoryPersistence.deleteDataNode(_) >> { throw deleteListElementException }
when: 'registration is updated to delete cmhandle'
- def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ def response = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'a failure response is received'
assert response.removedCmHandles.size() == 1
with(response.removedCmHandles[0]) {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
index 1830f1331d..e2261f4b7c 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/InventoryPersistenceImplSpec.groovy
@@ -38,6 +38,7 @@ import org.onap.cps.spi.model.ModuleDefinition
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.utils.ContentType
import org.onap.cps.utils.JsonObjectMapper
+import org.testcontainers.shaded.com.fasterxml.jackson.databind.introspect.BasicClassIntrospector
import spock.lang.Shared
import spock.lang.Specification
@@ -332,13 +333,25 @@ class InventoryPersistenceImplSpec extends Specification {
0 * mockCmHandleQueries.queryNcmpRegistryByCpsPath(_, _)
}
- def 'Get CM handles that has given module names'() {
+ def 'Get CM handle ids for CM Handles that has given module names'() {
when: 'the method to get cm handles is called'
- objectUnderTest.getCmHandleIdsWithGivenModules(['sample-module-name'])
+ objectUnderTest.getCmHandleReferencesWithGivenModules(['sample-module-name'], false)
then: 'the admin persistence service method to query anchors is invoked once with the same parameter'
1 * mockCpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, ['sample-module-name'])
}
+ def 'Get Alternate Ids for CM Handles that has given module names'() {
+ given: 'A Collection of data nodes'
+ def dataNodes = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='ch-1']", leaves: ['id': 'ch-1', 'alternate-id': 'alt-1'])]
+ when: 'the methods to get dataNodes is called and returns correct values'
+ mockCpsAnchorService.queryAnchorNames(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, ['sample-module-name']) >> ['ch-1']
+ mockCpsDataService.getDataNodesForMultipleXpaths(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, ["/dmi-registry/cm-handles[@id='ch-1']"], INCLUDE_ALL_DESCENDANTS) >> dataNodes
+ and: 'the method returns a result'
+ def result = objectUnderTest.getCmHandleReferencesWithGivenModules(['sample-module-name'], true)
+ then: 'the result contains the correct alternate Id'
+ assert result == ['alt-1'] as HashSet
+ }
+
def 'Replace list content'() {
when: 'replace list content method is called with xpath and data nodes collection'
objectUnderTest.replaceListContent('sample xpath', [new DataNode()])
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
index fec07556eb..4c554c6af5 100644
--- 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
@@ -56,12 +56,12 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
given: 'an (updated) dmi plugin registration'
def dmiPluginRegistration = Mock(DmiPluginRegistration)
when: 'the registration is submitted '
- objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'the call is delegated to the cm handle registration service'
- 1 * mockCmHandleRegistrationService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ 1 * mockCmHandleRegistrationService.updateDmiRegistration(dmiPluginRegistration)
}
- def 'Execute cm handle id search for inventory'() {
+ def 'Execute cm handle reference search for inventory'() {
given: 'a ConditionApiProperties object'
def conditionProperties = new ConditionProperties()
conditionProperties.conditionName = 'hasAllProperties'
@@ -71,7 +71,7 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
and: 'the system returns an set of cmHandle ids'
mockParameterizedCmHandleQueryService.queryCmHandleIdsForInventory(*_) >> [ 'cmHandle1', 'cmHandle2' ]
when: 'executing the search'
- def result = objectUnderTest.executeParameterizedCmHandleIdSearch(cmHandleQueryServiceParameters)
+ def result = objectUnderTest.executeParameterizedCmHandleIdSearch(cmHandleQueryServiceParameters, false)
then: 'the result returns the correct 2 elements'
assert result.size() == 2
assert result.contains('cmHandle1')
@@ -191,7 +191,7 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
'Cm Handle Reference as alternate-id' | 'some-alternate-id'
}
- def 'Execute cm handle id search'() {
+ def 'Execute cm handle reference search'() {
given: 'valid CmHandleQueryApiParameters input'
def cmHandleQueryApiParameters = new CmHandleQueryApiParameters()
def conditionApiProperties = new ConditionApiProperties()
@@ -199,11 +199,11 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
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))
+ mockParameterizedCmHandleQueryService.queryCmHandleReferenceIds(
+ spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class), false)
>> ['cm-handle-id-1']
when: 'execute cm handle search is called'
- def result = objectUnderTest.executeCmHandleIdSearch(cmHandleQueryApiParameters)
+ def result = objectUnderTest.executeCmHandleIdSearch(cmHandleQueryApiParameters, false)
then: 'result is the same collection as returned by the CPS Data Service'
assert result == ['cm-handle-id-1']
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy
index 013bace04d..9a81807ef9 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 Nordix Foundation
+ * Copyright (C) 2022-2024 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,11 +50,15 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']])
cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
and: 'the query get the cm handle datanodes excluding all descendants returns a datanode'
- cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])]
+ cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id', 'alternate-id':'some-alternate-id'])]
when: 'the query is executed for cm handle ids'
- def result = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
+ def result = objectUnderTest.queryCmHandleReferenceIds(cmHandleQueryParameters, outputAlternateId)
then: 'the correct expected cm handles ids are returned'
- assert result == ['some-cmhandle-id'] as Set
+ assert result == expectedCmhandleReference
+ where: 'the following data is used'
+ senario | outputAlternateId || expectedCmhandleReference
+ 'output CmHandle Ids' | false || ['some-cmhandle-id'] as Set
+ 'output Alternate Ids' | true || ['some-alternate-id'] as Set
}
def 'Query cm handle where cps path itself is ancestor axis.'() {
@@ -63,11 +67,15 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']])
cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
and: 'the query get the cm handle data nodes excluding all descendants returns a datanode'
- cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])]
+ cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id', 'alternate-id':'some-alternate-id'])]
when: 'the query is executed for cm handle ids'
- def result = objectUnderTest.queryCmHandleIdsForInventory(cmHandleQueryParameters)
+ def result = objectUnderTest.queryCmHandleIdsForInventory(cmHandleQueryParameters, outputAlternateId)
then: 'the correct expected cm handles ids are returned'
- assert result == ['some-cmhandle-id'] as Set
+ assert result == expectedCmhandleReference
+ where: 'the following data is used'
+ senario | outputAlternateId || expectedCmhandleReference
+ 'outputAlternate is false' | false || ['some-cmhandle-id'] as Set
+ 'outputAlternate is true' | true || ['some-alternate-id'] as Set
}
def 'Cm handle ids query with error: #scenario.'() {
@@ -78,7 +86,7 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
and: 'cmHandleQueries throws a path parsing exception'
cmHandleQueries.queryCmHandleAncestorsByCpsPath('/some/cps/path', FetchDescendantsOption.OMIT_DESCENDANTS) >> { throw thrownException }
when: 'the query is executed for cm handle ids'
- objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
+ objectUnderTest.queryCmHandleReferenceIds(cmHandleQueryParameters, false)
then: 'a data validation exception is thrown'
thrown(expectedException)
where: 'the following data is used'
@@ -93,7 +101,7 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/additional-properties']])
cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
when: 'the query is executed for cm handle ids'
- def result = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
+ def result = objectUnderTest.queryCmHandleReferenceIds(cmHandleQueryParameters, false)
then: 'empty result is returned'
assert result.isEmpty()
}
@@ -104,9 +112,9 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
def conditionProperties = createConditionProperties('hasAllModules', [['moduleName': 'some-module-name']])
cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
when: 'the query is executed for cm handle ids'
- def result = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
+ def result = objectUnderTest.queryCmHandleReferenceIds(cmHandleQueryParameters, false)
then: 'the inventory service is called with the correct module names'
- 1 * mockInventoryPersistence.getCmHandleIdsWithGivenModules(['some-module-name']) >> cmHandleIdsFromService
+ 1 * mockInventoryPersistence.getCmHandleReferencesWithGivenModules(['some-module-name'], false) >> cmHandleIdsFromService
and: 'the correct expected cm handles ids are returned'
assert result.size() == cmHandleIdsFromService.size()
assert result.containsAll(cmHandleIdsFromService)
@@ -122,9 +130,9 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
def trustLevelConditionProperties = createConditionProperties('cmHandleWithTrustLevel', [['trustLevel': 'COMPLETE'] as Map])
trustLevelQueryParameters.setCmHandleQueryParameters([trustLevelConditionProperties])
when: 'the query is being executed'
- objectUnderTest.queryCmHandleIds(trustLevelQueryParameters)
+ objectUnderTest.queryCmHandleReferenceIds(trustLevelQueryParameters, false)
then: 'the query is being delegated to the cm handle query service with correct parameter'
- 1 * cmHandleQueries.queryCmHandlesByTrustLevel(['trustLevel': 'COMPLETE'] as Map)
+ 1 * cmHandleQueries.queryCmHandlesByTrustLevel(['trustLevel': 'COMPLETE'] as Map, false)
}
def 'Query cm handle details with module names when #scenario from query.'() {
@@ -135,7 +143,7 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
when: 'the query is executed for cm handle ids'
def result = objectUnderTest.queryCmHandles(cmHandleQueryParameters)
then: 'the inventory service is called with the correct module names'
- 1 * mockInventoryPersistence.getCmHandleIdsWithGivenModules(['some-module-name']) >> ['ch1']
+ 1 * mockInventoryPersistence.getCmHandleReferencesWithGivenModules(['some-module-name'], false) >> ['ch1']
and: 'the inventory service is called with teh correct if and returns a yang model cm handle'
1 * mockInventoryPersistence.getYangModelCmHandles(['ch1']) >>
[new YangModelCmHandle(id: 'abc', dmiProperties: [new YangModelCmHandle.Property('name','value')], publicProperties: [])]
@@ -145,15 +153,19 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
assert result[0].dmiProperties == [name:'value']
}
- def 'Query cm handle ids when the query is empty.'() {
+ def 'Query cm handle references when the query is empty.'() {
given: 'We use an empty query'
def cmHandleQueryParameters = new CmHandleQueryServiceParameters()
and: 'the inventory persistence returns the dmi registry datanode with just ids'
mockInventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT, FetchDescendantsOption.DIRECT_CHILDREN_ONLY) >> [dmiRegistry]
when: 'the query is executed for both cm handle ids'
- def result = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters)
+ def result = objectUnderTest.queryCmHandleReferenceIds(cmHandleQueryParameters, outputAlternateId)
then: 'the correct expected cm handles are returned'
- assert result.containsAll('PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4')
+ assert result.containsAll(expectedCmhandleReferences)
+ where: 'the following data is used'
+ senario | outputAlternateId || expectedCmhandleReferences
+ 'outputAlternate is false' | false || ['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4']
+ 'outputAlternate is true' | true || ['alt-PNFDemo1', 'alt-PNFDemo2', 'alt-PNFDemo3', 'alt-PNFDemo4']
}
def 'Query cm handle details when the query is empty.'() {
@@ -177,7 +189,7 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
partiallyMockedCmHandleQueries.queryCmHandlePublicProperties(*_) >> cmHandlesWithMatchingPublicProperties
partiallyMockedCmHandleQueries.queryCmHandleAdditionalProperties(*_) >> cmHandlesWithMatchingPrivateProperties
when: 'the query executed'
- def result = objectUnderTestWithPartiallyMockedQueries.queryCmHandleIdsForInventory(cmHandleQueryParameters)
+ def result = objectUnderTestWithPartiallyMockedQueries.queryCmHandleIdsForInventory(cmHandleQueryParameters, false)
then: 'the expected number of results are returned.'
assert result.size() == expectedCmHandleIdsSize
where: 'the following data is used'
@@ -195,14 +207,15 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties])
and: 'the inventoryPersistence returns different CmHandleIds'
partiallyMockedCmHandleQueries.getCmHandleIdsByDmiPluginIdentifier(*_) >> cmHandleQueryResult
+ partiallyMockedCmHandleQueries.getCmHandleReferencesByDmiPluginIdentifier(*_) >> cmHandleQueryResult
when: 'the query executed'
- def result = objectUnderTestWithPartiallyMockedQueries.queryCmHandleIdsForInventory(cmHandleQueryParameters)
+ def result = objectUnderTestWithPartiallyMockedQueries.queryCmHandleIdsForInventory(cmHandleQueryParameters, outputAlternateId)
then: 'the expected number of results are returned.'
assert result.size() == expectedCmHandleIdsSize
where: 'the following data is used'
- scenario | cmHandleQueryResult || expectedCmHandleIdsSize
- 'some matches' | ['h1','h2'] || 2
- 'no matches' | [] || 0
+ scenario | cmHandleQueryResult | outputAlternateId || expectedCmHandleIdsSize
+ 'some matches' | ['h1','h2'] | false || 2
+ 'no matches' | [:] | true || 0
}
def 'Combine two query results where #scenario.'() {
@@ -227,7 +240,7 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
def static createDataNodeList(dataNodeIds) {
def dataNodes =[]
- dataNodeIds.each{ dataNodes << new DataNode(xpath: "/dmi-registry/cm-handles[@id='${it}']", leaves: ['id':it]) }
+ dataNodeIds.each{ dataNodes << new DataNode(xpath: "/dmi-registry/cm-handles[@id='${it}']", leaves: ['id':it, 'alternate-id':'alt-' + it]) }
return dataNodes
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy
index 3064a78ff9..f2c88a511e 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy
@@ -23,6 +23,7 @@ package org.onap.cps.ncmp.impl.inventory.sync
import com.hazelcast.map.IMap
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
+import org.onap.cps.ncmp.impl.utils.Sleeper
import org.onap.cps.spi.model.DataNode
import spock.lang.Specification
@@ -31,7 +32,7 @@ import java.util.concurrent.locks.Lock
class ModuleSyncWatchdogSpec extends Specification {
- def mockSyncUtils = Mock(ModuleOperationsUtils)
+ def mockModuleOperationsUtils = Mock(ModuleOperationsUtils)
def static testQueueCapacity = 50 + 2 * ModuleSyncWatchdog.MODULE_SYNC_BATCH_SIZE
@@ -45,16 +46,21 @@ class ModuleSyncWatchdogSpec extends Specification {
def mockWorkQueueLock = Mock(Lock)
- def objectUnderTest = new ModuleSyncWatchdog(mockSyncUtils, moduleSyncWorkQueue , mockModuleSyncStartedOnCmHandles, mockModuleSyncTasks, spiedAsyncTaskExecutor, mockWorkQueueLock)
+ def spiedSleeper = Spy(Sleeper)
+
+ def objectUnderTest = new ModuleSyncWatchdog(mockModuleOperationsUtils, moduleSyncWorkQueue , mockModuleSyncStartedOnCmHandles, mockModuleSyncTasks, spiedAsyncTaskExecutor, mockWorkQueueLock, spiedSleeper)
void setup() {
spiedAsyncTaskExecutor.setupThreadPool()
- mockWorkQueueLock.tryLock() >> true
}
def 'Module sync advised cm handles with #scenario.'() {
- given: 'sync utilities returns #numberOfAdvisedCmHandles advised cm handles'
- mockSyncUtils.getAdvisedCmHandles() >> createDataNodes(numberOfAdvisedCmHandles)
+ given: 'module sync utilities returns #numberOfAdvisedCmHandles advised cm handles'
+ mockModuleOperationsUtils.getAdvisedCmHandles() >> createDataNodes(numberOfAdvisedCmHandles)
+ and: 'module sync utilities returns no failed (locked) cm handles'
+ mockModuleOperationsUtils.getCmHandlesThatFailedModelSyncOrUpgrade() >> []
+ and: 'the work queue is not locked'
+ mockWorkQueueLock.tryLock() >> true
and: 'the executor has enough available threads'
spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >> 3
when: ' module sync is started'
@@ -63,6 +69,7 @@ class ModuleSyncWatchdogSpec extends Specification {
expectedNumberOfTaskExecutions * spiedAsyncTaskExecutor.executeTask(*_)
where: 'the following parameter are used'
scenario | numberOfAdvisedCmHandles || expectedNumberOfTaskExecutions
+ 'none at all' | 0 || 0
'less then 1 batch' | 1 || 1
'exactly 1 batch' | ModuleSyncWatchdog.MODULE_SYNC_BATCH_SIZE || 1
'2 batches' | 2 * ModuleSyncWatchdog.MODULE_SYNC_BATCH_SIZE || 2
@@ -70,9 +77,11 @@ class ModuleSyncWatchdogSpec extends Specification {
'over queue capacity' | testQueueCapacity + 2 * ModuleSyncWatchdog.MODULE_SYNC_BATCH_SIZE || 3
}
- def 'Module sync advised cm handles starts with no available threads.'() {
- given: 'sync utilities returns a advise cm handles'
- mockSyncUtils.getAdvisedCmHandles() >> createDataNodes(1)
+ def 'Module sync cm handles starts with no available threads.'() {
+ given: 'module sync utilities returns a advise cm handles'
+ mockModuleOperationsUtils.getAdvisedCmHandles() >> createDataNodes(1)
+ and: 'the work queue is not locked'
+ mockWorkQueueLock.tryLock() >> true
and: 'the executor first has no threads but has one thread on the second attempt'
spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >>> [ 0, 1 ]
when: ' module sync is started'
@@ -81,9 +90,11 @@ class ModuleSyncWatchdogSpec extends Specification {
1 * spiedAsyncTaskExecutor.executeTask(*_)
}
- def 'Module sync advised cm handles already handled.'() {
- given: 'sync utilities returns a advise cm handles'
- mockSyncUtils.getAdvisedCmHandles() >> createDataNodes(1)
+ def 'Module sync advised cm handle already handled by other thread.'() {
+ given: 'module sync utilities returns an advised cm handle'
+ mockModuleOperationsUtils.getAdvisedCmHandles() >> createDataNodes(1)
+ and: 'the work queue is not locked'
+ mockWorkQueueLock.tryLock() >> true
and: 'the executor has a thread available'
spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >> 1
and: 'the semaphore cache indicates the cm handle is already being processed'
@@ -98,7 +109,7 @@ class ModuleSyncWatchdogSpec extends Specification {
given: 'there is still a cm handle in the queue'
moduleSyncWorkQueue.offer(new DataNode())
and: 'sync utilities returns many advise cm handles'
- mockSyncUtils.getAdvisedCmHandles() >> createDataNodes(500)
+ mockModuleOperationsUtils.getAdvisedCmHandles() >> createDataNodes(500)
and: 'the executor has plenty threads available'
spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >> 10
when: ' module sync is started'
@@ -108,18 +119,42 @@ class ModuleSyncWatchdogSpec extends Specification {
}
def 'Reset failed cm handles.'() {
- given: 'sync utilities returns failed cm handles'
+ given: 'module sync utilities returns failed cm handles'
def failedCmHandles = [new YangModelCmHandle()]
- mockSyncUtils.getCmHandlesThatFailedModelSyncOrUpgrade() >> failedCmHandles
+ mockModuleOperationsUtils.getCmHandlesThatFailedModelSyncOrUpgrade() >> failedCmHandles
when: 'reset failed cm handles is started'
objectUnderTest.setPreviouslyLockedCmHandlesToAdvised()
then: 'it is delegated to the module sync task (service)'
1 * mockModuleSyncTasks.setCmHandlesToAdvised(failedCmHandles)
}
+ def 'Module Sync Locking.'() {
+ given: 'module sync utilities returns an advised cm handle'
+ mockModuleOperationsUtils.getAdvisedCmHandles() >> createDataNodes(1)
+ and: 'can lock is : #canLock'
+ mockWorkQueueLock.tryLock() >> canLock
+ when: 'attempt to populate the work queue'
+ objectUnderTest.populateWorkQueueIfNeeded()
+ then: 'the queue remains empty is #expectQueueRemainsEmpty'
+ assert moduleSyncWorkQueue.isEmpty() == expectQueueRemainsEmpty
+ where: 'the following lock states are applied'
+ canLock | expectQueueRemainsEmpty
+ false | true
+ true | false
+ }
+
+ def 'Sleeper gets interrupted.'() {
+ given: 'sleeper gets interrupted'
+ spiedSleeper.haveALittleRest(_) >> { throw new InterruptedException() }
+ when: 'the watchdog attempts to sleep to save cpu cycles'
+ objectUnderTest.preventBusyWait()
+ then: 'no exception is thrown'
+ noExceptionThrown()
+ }
+
def createDataNodes(numberOfDataNodes) {
def dataNodes = []
- (1..numberOfDataNodes).each {dataNodes.add(new DataNode())}
+ numberOfDataNodes.times { dataNodes.add(new DataNode()) }
return dataNodes
}
}
diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java b/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java
index 9859acdf0e..de57914527 100644
--- a/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java
+++ b/cps-service/src/main/java/org/onap/cps/spi/model/DataNodeBuilder.java
@@ -204,18 +204,17 @@ public class DataNodeBuilder {
private static void addDataNodeFromNormalizedNode(final DataNode currentDataNode,
final NormalizedNode normalizedNode) {
- if (normalizedNode instanceof ChoiceNode) {
- addChoiceNode(currentDataNode, (ChoiceNode) normalizedNode);
- } else if (normalizedNode instanceof DataContainerNode) {
- addYangContainer(currentDataNode, (DataContainerNode) normalizedNode);
- } else if (normalizedNode instanceof MapNode) {
- addDataNodeForEachListElement(currentDataNode, (MapNode) normalizedNode);
- } else if (normalizedNode instanceof ValueNode) {
- final ValueNode<NormalizedNode> valuesNode = (ValueNode) normalizedNode;
- addYangLeaf(currentDataNode, valuesNode.getIdentifier().getNodeType().getLocalName(),
- (Serializable) valuesNode.body());
- } else if (normalizedNode instanceof LeafSetNode) {
- addYangLeafList(currentDataNode, (LeafSetNode<?>) normalizedNode);
+ if (normalizedNode instanceof ChoiceNode choiceNode) {
+ addChoiceNode(currentDataNode, choiceNode);
+ } else if (normalizedNode instanceof DataContainerNode dataContainerNode) {
+ addYangContainer(currentDataNode, dataContainerNode);
+ } else if (normalizedNode instanceof MapNode mapNode) {
+ addDataNodeForEachListElement(currentDataNode, mapNode);
+ } else if (normalizedNode instanceof ValueNode<?> valueNode) {
+ addYangLeaf(currentDataNode, valueNode.getIdentifier().getNodeType().getLocalName(),
+ (Serializable) valueNode.body());
+ } else if (normalizedNode instanceof LeafSetNode<?> leafSetNode) {
+ addYangLeafList(currentDataNode, leafSetNode);
} else {
log.warn("Unsupported NormalizedNode type detected: {}", normalizedNode.getClass());
}
@@ -243,7 +242,7 @@ public class DataNodeBuilder {
private static void addYangLeafList(final DataNode currentDataNode, final LeafSetNode<?> leafSetNode) {
final String leafListName = leafSetNode.getIdentifier().getNodeType().getLocalName();
- List<?> leafListValues = ((Collection<? extends NormalizedNode>) leafSetNode.body())
+ List<?> leafListValues = (leafSetNode.body())
.stream()
.map(NormalizedNode::body)
.collect(Collectors.toList());
diff --git a/docs/deployment.rst b/docs/deployment.rst
index b49bc71985..3f0c1eddc5 100644
--- a/docs/deployment.rst
+++ b/docs/deployment.rst
@@ -31,6 +31,12 @@ This helps the JVM make the best use of the allocated resources while leaving en
JAVA_TOOL_OPTIONS: "-XX:InitialRAMPercentage=75.0 -XX:MaxRAMPercentage=75.0"
+Load balancer configuration
+===========================
+
+For optimal performance in CPS/NCMP, load balancers should be configured to use a least-requests policy, also known as
+least-connected. Use of round-robin load balancing can lead to instability.
+
CPS OOM Charts
==============
The CPS kubernetes chart is located in the `OOM repository <https://github.com/onap/oom/tree/master/kubernetes/cps>`_.
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
index 24ba54fe43..c5b00d6888 100644
--- a/docs/release-notes.rst
+++ b/docs/release-notes.rst
@@ -1618,10 +1618,6 @@ Following CPS components are available with default ONAP/CPS installation.
- Postgres Database
-Below service components (mS) are available to be deployed on-demand.
- - CPS-TBDMT
-
-
Under OOM (Kubernetes) all CPS component containers are deployed as Kubernetes Pods/Deployments/Services into Kubernetes cluster.
Known Limitations, Issues and Workarounds
@@ -1731,10 +1727,6 @@ Following CPS components are available with default ONAP/CPS installation.
- Postgres Database
-Below service components (mS) are available to be deployed on-demand.
- - CPS-TBDMT
-
-
Under OOM (Kubernetes) all CPS component containers are deployed as Kubernetes Pods/Deployments/Services into Kubernetes cluster.
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
index 587cbae619..759eccd966 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
@@ -53,6 +53,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.context.annotation.ComponentScan
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
+import org.springframework.test.context.ActiveProfiles
import org.springframework.test.web.servlet.MockMvc
import org.testcontainers.spock.Testcontainers
import spock.lang.Shared
@@ -61,6 +62,7 @@ import spock.util.concurrent.PollingConditions
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter
+import java.util.concurrent.BlockingQueue
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
@@ -73,6 +75,7 @@ import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY
@EnableJpaRepositories(basePackageClasses = [DataspaceRepository])
@ComponentScan(basePackages = ['org.onap.cps'])
@EntityScan('org.onap.cps.ri.models')
+@ActiveProfiles('module-sync-delayed')
abstract class CpsIntegrationSpecBase extends Specification {
@Shared
@@ -118,6 +121,9 @@ abstract class CpsIntegrationSpecBase extends Specification {
ModuleSyncWatchdog moduleSyncWatchdog
@Autowired
+ BlockingQueue<DataNode> moduleSyncWorkQueue
+
+ @Autowired
JsonObjectMapper jsonObjectMapper
@Autowired
@@ -244,26 +250,39 @@ abstract class CpsIntegrationSpecBase extends Specification {
}
def registerCmHandle(dmiPlugin, cmHandleId, moduleSetTag, alternateId) {
- def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: cmHandleId, moduleSetTag: moduleSetTag, alternateId: alternateId)
- networkCmProxyInventoryFacade.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: dmiPlugin, createdCmHandles: [cmHandleToCreate]))
+ registerCmHandleWithoutWaitForReady(dmiPlugin, cmHandleId, moduleSetTag, alternateId)
+ moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
CmHandleState.READY == networkCmProxyInventoryFacade.getCmHandleCompositeState(cmHandleId).cmHandleState
})
}
+ def registerCmHandleWithoutWaitForReady(dmiPlugin, cmHandleId, moduleSetTag, alternateId) {
+ def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: cmHandleId, moduleSetTag: moduleSetTag, alternateId: alternateId)
+ networkCmProxyInventoryFacade.updateDmiRegistration(new DmiPluginRegistration(dmiPlugin: dmiPlugin, createdCmHandles: [cmHandleToCreate]))
+ }
+
+ def registerSequenceOfCmHandlesWithoutWaitForReady(dmiPlugin, moduleSetTag, numberOfCmHandles) {
+ def cmHandles = []
+ (1..numberOfCmHandles).each {
+ def cmHandle = new NcmpServiceCmHandle(cmHandleId: 'ch-'+it, moduleSetTag: moduleSetTag, alternateId: NO_ALTERNATE_ID)
+ cmHandles.add(cmHandle)
+ }
+ networkCmProxyInventoryFacade.updateDmiRegistration(new DmiPluginRegistration(dmiPlugin: dmiPlugin, createdCmHandles: cmHandles))
+ }
+
def deregisterCmHandle(dmiPlugin, cmHandleId) {
deregisterCmHandles(dmiPlugin, [cmHandleId])
}
def deregisterCmHandles(dmiPlugin, cmHandleIds) {
- networkCmProxyInventoryFacade.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: dmiPlugin, removedCmHandles: cmHandleIds))
+ networkCmProxyInventoryFacade.updateDmiRegistration(new DmiPluginRegistration(dmiPlugin: dmiPlugin, removedCmHandles: cmHandleIds))
}
- def overrideCmHandleLastUpdateTime(cmHandleId, newUpdateTime) {
- String ISO_TIMESTAMP_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
- DateTimeFormatter ISO_TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern(ISO_TIMESTAMP_PATTERN);
- def jsonForUpdate = '{ "state": { "last-update-time": "%s" } }'.formatted(ISO_TIMESTAMP_FORMATTER.format(newUpdateTime))
- cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='${cmHandleId}']", jsonForUpdate, now, ContentType.JSON)
+ def deregisterSequenceOfCmHandles(dmiPlugin, numberOfCmHandles) {
+ def cmHandleIds = []
+ (1..numberOfCmHandles).each { cmHandleIds.add('ch-'+it) }
+ networkCmProxyInventoryFacade.updateDmiRegistration(new DmiPluginRegistration(dmiPlugin: dmiPlugin, removedCmHandles: cmHandleIds))
}
+
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy
index 10a9f15e21..19b10a3c79 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleCreateSpec.groovy
@@ -32,42 +32,48 @@ import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
import org.onap.cps.ncmp.events.lcm.v1.LcmEvent
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory
+import spock.lang.Ignore
import spock.util.concurrent.PollingConditions
import java.time.Duration
-import java.time.OffsetDateTime
class CmHandleCreateSpec extends CpsIntegrationSpecBase {
NetworkCmProxyInventoryFacade objectUnderTest
+ def uniqueId = 'ch-unique-id-for-create-test'
- def kafkaConsumer = KafkaTestContainer.getConsumer('ncmp-group', StringDeserializer.class)
+ def kafkaConsumer = KafkaTestContainer.getConsumer('test-group', StringDeserializer.class)
def setup() {
objectUnderTest = networkCmProxyInventoryFacade
}
+ @Ignore
def 'CM Handle registration is successful.'() {
given: 'DMI will return modules when requested'
dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
+ dmiDispatcher1.moduleNamesPerCmHandleId[uniqueId] = ['M1', 'M2']
and: 'consumer subscribed to topic'
kafkaConsumer.subscribe(['ncmp-events'])
when: 'a CM-handle is registered for creation'
- def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: 'ch-1')
+ def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: uniqueId)
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: [cmHandleToCreate])
- def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'registration gives successful response'
- assert dmiPluginRegistrationResponse.createdCmHandles == [CmHandleRegistrationResponse.createSuccessResponse('ch-1')]
+ assert dmiPluginRegistrationResponse.createdCmHandles == [CmHandleRegistrationResponse.createSuccessResponse(uniqueId)]
and: 'CM-handle is initially in ADVISED state'
- assert CmHandleState.ADVISED == objectUnderTest.getCmHandleCompositeState('ch-1').cmHandleState
+ assert CmHandleState.ADVISED == objectUnderTest.getCmHandleCompositeState(uniqueId).cmHandleState
+
+ and: 'the module sync watchdog is triggered'
+ moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
and: 'CM-handle goes to READY state after module sync'
new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
- assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState('ch-1').cmHandleState
+ assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(uniqueId).cmHandleState
})
and: 'the messages is polled'
@@ -76,13 +82,20 @@ class CmHandleCreateSpec extends CpsIntegrationSpecBase {
and: 'the newest lcm event notification is received with READY state'
def notificationMessage = jsonObjectMapper.convertJsonString(records.last().value().toString(), LcmEvent)
+ /*TODO (Toine) This test was failing intermittently (when running as part of suite).
+ I suspect that it often gave false positives as the message being assert here was any random message created by previous tests
+ By checking the cm-handle and using an unique cm-handle in this test this flaw became obvious.
+ I have now ignored this test as it is out of scope of this commit to fix it.
+ Created: https://lf-onap.atlassian.net/browse/CPS-2468 to fix this instead
+ */
+ assert notificationMessage.event.cmHandleId == uniqueId
assert notificationMessage.event.newValues.cmHandleState.value() == 'READY'
and: 'the CM-handle has expected modules'
- assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences('ch-1').moduleName.sort()
+ assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences(uniqueId).moduleName.sort()
cleanup: 'deregister CM handle'
- deregisterCmHandle(DMI1_URL, 'ch-1')
+ deregisterCmHandle(DMI1_URL, uniqueId)
}
def 'CM Handle goes to LOCKED state when DMI gives error during module sync.'() {
@@ -92,7 +105,10 @@ class CmHandleCreateSpec extends CpsIntegrationSpecBase {
when: 'a CM-handle is registered for creation'
def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: 'ch-1')
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: [cmHandleToCreate])
- objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
+
+ and: 'the module sync watchdog is triggered'
+ moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
then: 'CM-handle goes to LOCKED state with reason MODULE_SYNC_FAILED'
new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
@@ -117,7 +133,10 @@ class CmHandleCreateSpec extends CpsIntegrationSpecBase {
when: 'a CM-handle is registered for creation with moduleSetTag "B"'
def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: 'ch-3', moduleSetTag: 'B')
- objectUnderTest.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: [cmHandleToCreate]))
+ objectUnderTest.updateDmiRegistration(new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: [cmHandleToCreate]))
+
+ and: 'the module sync watchdog is triggered'
+ moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
then: 'the CM-handle goes to READY state'
new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
@@ -151,7 +170,7 @@ class CmHandleCreateSpec extends CpsIntegrationSpecBase {
new NcmpServiceCmHandle(cmHandleId: 'ch-7', alternateId: 'duplicate-alt-id'),
]
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: cmHandlesToCreate)
- def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
then: 'registration gives expected responses'
assert dmiPluginRegistrationResponse.createdCmHandles.sort { it.cmHandle } == [
@@ -173,7 +192,11 @@ class CmHandleCreateSpec extends CpsIntegrationSpecBase {
when: 'CM-handles are registered for creation'
def cmHandlesToCreate = [new NcmpServiceCmHandle(cmHandleId: 'ch-1'), new NcmpServiceCmHandle(cmHandleId: 'ch-2')]
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI1_URL, createdCmHandles: cmHandlesToCreate)
- objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
+ objectUnderTest.updateDmiRegistration(dmiPluginRegistration)
+
+ and: 'the module sync watchdog is triggered'
+ moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
+
then: 'CM-handles go to LOCKED state'
new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
assert objectUnderTest.getCmHandleCompositeState('ch-1').cmHandleState == CmHandleState.LOCKED
@@ -183,6 +206,9 @@ class CmHandleCreateSpec extends CpsIntegrationSpecBase {
dmiDispatcher1.moduleNamesPerCmHandleId = ['ch-1': ['M1', 'M2'], 'ch-2': ['M1', 'M2']]
dmiDispatcher1.isAvailable = true
+ and: 'the module sync watchdog is triggered TWICE'
+ 2.times { moduleSyncWatchdog.moduleSyncAdvisedCmHandles() }
+
then: 'Both CM-handles go to READY state'
new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
['ch-1', 'ch-2'].each { cmHandleId ->
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpdateSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpdateSpec.groovy
index 2d1588ecf9..67011f811b 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpdateSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpdateSpec.groovy
@@ -44,7 +44,7 @@ class CmHandleUpdateSpec extends CpsIntegrationSpecBase {
when: "CM-handle is registered for update with new alternate ID: $newAlternateId"
def cmHandleToUpdate = new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: newAlternateId)
def dmiPluginRegistrationResponse =
- objectUnderTest.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: DMI1_URL, updatedCmHandles: [cmHandleToUpdate]))
+ objectUnderTest.updateDmiRegistration(new DmiPluginRegistration(dmiPlugin: DMI1_URL, updatedCmHandles: [cmHandleToUpdate]))
then: 'registration gives successful response'
assert dmiPluginRegistrationResponse.updatedCmHandles == [CmHandleRegistrationResponse.createSuccessResponse('ch-1')]
@@ -74,7 +74,7 @@ class CmHandleUpdateSpec extends CpsIntegrationSpecBase {
when: 'a CM-handle is registered for update with new alternate ID'
def cmHandleToUpdate = new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: 'new')
def dmiPluginRegistrationResponse =
- objectUnderTest.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: DMI1_URL, updatedCmHandles: [cmHandleToUpdate]))
+ objectUnderTest.updateDmiRegistration(new DmiPluginRegistration(dmiPlugin: DMI1_URL, updatedCmHandles: [cmHandleToUpdate]))
then: 'registration gives failure response, due to alternate ID being already associated'
assert dmiPluginRegistrationResponse.updatedCmHandles == [CmHandleRegistrationResponse.createFailureResponse('ch-1', NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED)]
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy
index f93f58ce20..64449371fe 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/CmHandleUpgradeSpec.groovy
@@ -48,7 +48,7 @@ class CmHandleUpgradeSpec extends CpsIntegrationSpecBase {
when: "the CM-handle is upgraded with given moduleSetTag '${updatedModuleSetTag}'"
def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: updatedModuleSetTag)
- def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistrationAndSyncModule(
+ def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistration(
new DmiPluginRegistration(dmiPlugin: DMI1_URL, upgradedCmHandles: cmHandlesToUpgrade))
then: 'registration gives successful response'
@@ -63,6 +63,9 @@ class CmHandleUpgradeSpec extends CpsIntegrationSpecBase {
when: 'DMI will return different modules for upgrade: M1 and M3'
dmiDispatcher1.moduleNamesPerCmHandleId[CM_HANDLE_ID] = ['M1', 'M3']
+ and: 'the module sync watchdog is triggered twice'
+ 2.times { moduleSyncWatchdog.moduleSyncAdvisedCmHandles() }
+
then: 'CM-handle goes to READY state'
new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
@@ -98,12 +101,15 @@ class CmHandleUpgradeSpec extends CpsIntegrationSpecBase {
when: "CM-handle is upgraded to moduleSetTag '${updatedModuleSetTag}'"
def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: updatedModuleSetTag)
- def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistrationAndSyncModule(
+ def dmiPluginRegistrationResponse = objectUnderTest.updateDmiRegistration(
new DmiPluginRegistration(dmiPlugin: DMI1_URL, upgradedCmHandles: cmHandlesToUpgrade))
then: 'registration gives successful response'
assert dmiPluginRegistrationResponse.upgradedCmHandles == [CmHandleRegistrationResponse.createSuccessResponse(CM_HANDLE_ID)]
+ and: 'the module sync watchdog is triggered twice'
+ 2.times { moduleSyncWatchdog.moduleSyncAdvisedCmHandles() }
+
and: 'CM-handle goes to READY state'
new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID).cmHandleState
@@ -132,7 +138,7 @@ class CmHandleUpgradeSpec extends CpsIntegrationSpecBase {
when: 'CM-handle is upgraded with the same moduleSetTag'
def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: 'same')
- objectUnderTest.updateDmiRegistrationAndSyncModule(
+ objectUnderTest.updateDmiRegistration(
new DmiPluginRegistration(dmiPlugin: DMI1_URL, upgradedCmHandles: cmHandlesToUpgrade))
then: 'CM-handle remains in READY state'
@@ -157,9 +163,12 @@ class CmHandleUpgradeSpec extends CpsIntegrationSpecBase {
when: 'the CM-handle is upgraded'
def cmHandlesToUpgrade = new UpgradedCmHandles(cmHandles: [CM_HANDLE_ID], moduleSetTag: 'newTag')
- objectUnderTest.updateDmiRegistrationAndSyncModule(
+ objectUnderTest.updateDmiRegistration(
new DmiPluginRegistration(dmiPlugin: DMI1_URL, upgradedCmHandles: cmHandlesToUpgrade))
+ and: 'the module sync watchdog is triggered twice'
+ 2.times { moduleSyncWatchdog.moduleSyncAdvisedCmHandles() }
+
then: 'CM-handle goes to LOCKED state with reason MODULE_UPGRADE_FAILED'
new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
def cmHandleCompositeState = objectUnderTest.getCmHandleCompositeState(CM_HANDLE_ID)
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy
new file mode 100644
index 0000000000..e0bb437a7c
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/ModuleSyncWatchdogIntegrationSpec.groovy
@@ -0,0 +1,99 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.integration.functional.ncmp
+
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.onap.cps.ncmp.impl.inventory.sync.ModuleSyncWatchdog
+
+import java.util.concurrent.Executors
+
+class ModuleSyncWatchdogIntegrationSpec extends CpsIntegrationSpecBase {
+
+ ModuleSyncWatchdog objectUnderTest
+
+ def executorService = Executors.newFixedThreadPool(2)
+ def SYNC_SAMPLE_SIZE = 100
+
+ def setup() {
+ objectUnderTest = moduleSyncWatchdog
+ registerSequenceOfCmHandlesWithoutWaitForReady(DMI1_URL, NO_MODULE_SET_TAG, SYNC_SAMPLE_SIZE)
+ }
+
+ def cleanup() {
+ try {
+ deregisterSequenceOfCmHandles(DMI1_URL, SYNC_SAMPLE_SIZE)
+ moduleSyncWorkQueue.clear()
+ } finally {
+ executorService.shutdownNow()
+ }
+ }
+
+ def 'Watchdog is disabled for test.'() {
+ when: 'wait a while but less then the initial delay of 10 minutes'
+ Thread.sleep(3000)
+ then: 'the work queue remains empty'
+ assert moduleSyncWorkQueue.isEmpty()
+ }
+
+ def 'Populate module sync work queue simultaneously on two parallel threads (CPS-2403).'() {
+ // This test failed before bug https://lf-onap.atlassian.net/browse/CPS-2403 was fixed
+ given: 'the queue is empty at the start'
+ assert moduleSyncWorkQueue.isEmpty()
+ when: 'attempt to populate the queue on the main (test) and another parallel thread at the same time'
+ objectUnderTest.populateWorkQueueIfNeeded()
+ executorService.execute(populateQueueWithoutDelay)
+ and: 'wait a little (to give all threads time to complete their task)'
+ Thread.sleep(50)
+ then: 'the queue size is exactly the sample size'
+ assert moduleSyncWorkQueue.size() == SYNC_SAMPLE_SIZE
+ }
+
+ def 'Populate module sync work queue on two parallel threads with a slight difference in start time.'() {
+ // This test proved that the issue in CPS-2403 did not arise if the the queue was populated and given time to be distributed
+ given: 'the queue is empty at the start'
+ assert moduleSyncWorkQueue.isEmpty()
+ when: 'attempt to populate the queue on the main (test) and another parallel thread a little later'
+ objectUnderTest.populateWorkQueueIfNeeded()
+ executorService.execute(populateQueueWithDelay)
+ and: 'wait a little (to give all threads time to complete their task)'
+ Thread.sleep(50)
+ then: 'the queue size is exactly the sample size'
+ assert moduleSyncWorkQueue.size() == SYNC_SAMPLE_SIZE
+ }
+
+ def populateQueueWithoutDelay = () -> {
+ try {
+ objectUnderTest.populateWorkQueueIfNeeded()
+ } catch (InterruptedException e) {
+ e.printStackTrace()
+ }
+ }
+
+ def populateQueueWithDelay = () -> {
+ try {
+ Thread.sleep(10)
+ objectUnderTest.populateWorkQueueIfNeeded()
+ } catch (InterruptedException e) {
+ e.printStackTrace()
+ }
+ }
+
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy
index 1e1af556f1..7ce3cf5e17 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy
@@ -44,6 +44,8 @@ class RestApiSpec extends CpsIntegrationSpecBase {
def requestBody = '{"dmiPlugin":"'+DMI1_URL+'","createdCmHandles":[{"cmHandle":"ch-1","alternateId":"alt-1"},{"cmHandle":"ch-2","alternateId":"alt-2"},{"cmHandle":"ch-3","alternateId":"alt-3"}]}'
mvc.perform(post('/ncmpInventory/v1/ch').contentType(MediaType.APPLICATION_JSON).content(requestBody))
.andExpect(status().is2xxSuccessful())
+ and: 'the module sync watchdog is triggered'
+ moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
then: 'CM-handles go to READY state'
new PollingConditions().within(MODULE_SYNC_WAIT_TIME_IN_SECONDS, () -> {
(1..3).each {
@@ -65,15 +67,20 @@ class RestApiSpec extends CpsIntegrationSpecBase {
]
}""".formatted(moduleName)
expect: "a search for module ${moduleName} returns expected CM handles"
- mvc.perform(post('/ncmp/v1/ch/id-searches').contentType(MediaType.APPLICATION_JSON).content(requestBodyWithModuleCondition))
+ mvc.perform(post('/ncmp/v1/ch/id-searches'+outputAlternateId).contentType(MediaType.APPLICATION_JSON).content(requestBodyWithModuleCondition))
.andExpect(status().is2xxSuccessful())
- .andExpect(jsonPath('$[*]', containsInAnyOrder(expectedCmHandles.toArray())))
- .andExpect(jsonPath('$', hasSize(expectedCmHandles.size())));
+ .andExpect(jsonPath('$[*]', containsInAnyOrder(expectedCmHandleReferences.toArray())))
+ .andExpect(jsonPath('$', hasSize(expectedCmHandleReferences.size())));
where:
- moduleName || expectedCmHandles
- 'M1' || ['ch-1', 'ch-2', 'ch-3']
- 'M2' || ['ch-1', 'ch-2']
- 'M3' || ['ch-3']
+ moduleName | outputAlternateId || expectedCmHandleReferences
+ 'M1' | '?outputAlternateId=false' || ['ch-1', 'ch-2', 'ch-3']
+ 'M2' | '?outputAlternateId=false' || ['ch-1', 'ch-2']
+ 'M3' | '?outputAlternateId=false' || ['ch-3']
+ 'M1' | '?outputAlternateId=true' || ['alt-1', 'alt-2', 'alt-3']
+ 'M2' | '?outputAlternateId=true' || ['alt-1', 'alt-2']
+ 'M3' | '?outputAlternateId=true' || ['alt-3']
+ 'M1' | '' || ['ch-1', 'ch-2', 'ch-3']
+
}
def 'Search for CM Handles using Cps Path Query.'() {
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy
index f6ae27d129..fb5a0c3eb1 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy
@@ -27,11 +27,13 @@ import org.onap.cps.utils.ContentType
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DATASPACE_NAME
import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
+import static org.onap.cps.ncmp.impl.inventory.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
class NcmpPerfTestBase extends PerfTestBase {
def static NCMP_PERFORMANCE_TEST_DATASPACE = 'ncmpPerformance'
- def static REGISTRY_ANCHOR = 'ncmp-registry'
+ def static REGISTRY_ANCHOR = NCMP_DMI_REGISTRY_ANCHOR
+ def static REGISTRY_PARENT = NCMP_DMI_REGISTRY_PARENT
def static REGISTRY_SCHEMA_SET = 'registrySchemaSet'
def static TOTAL_CM_HANDLES = 20_000
def static CM_DATA_SUBSCRIPTIONS_ANCHOR = 'cm-data-subscriptions'
@@ -70,30 +72,30 @@ class NcmpPerfTestBase extends PerfTestBase {
}
def createRegistrySchemaSet() {
- def modelAsString = readResourceDataFile('ncmp-registry/dmi-registry@2024-02-23.yang')
+ def modelAsString = readResourceDataFile('inventory/dmi-registry@2024-02-23.yang')
cpsModuleService.createSchemaSet(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_SCHEMA_SET, [registry: modelAsString])
}
def addRegistryData() {
cpsAnchorService.createAnchor(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_SCHEMA_SET, REGISTRY_ANCHOR)
cpsDataService.saveData(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR, '{"dmi-registry": []}', now)
- def innerNodeJsonTemplate = readResourceDataFile('ncmp-registry/innerNode.json')
+ def cmHandleJsonTemplate = readResourceDataFile('inventory/cmHandleTemplate.json')
def batchSize = 100
for (def i = 0; i < TOTAL_CM_HANDLES; i += batchSize) {
- def data = '{ "cm-handles": [' + (1..batchSize).collect { innerNodeJsonTemplate.replace('CMHANDLE_ID_HERE', (it + i).toString()) }.join(',') + ']}'
- cpsDataService.saveListElements(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR, '/dmi-registry', data, now, ContentType.JSON)
+ def data = '{ "cm-handles": [' + (1..batchSize).collect { cmHandleJsonTemplate.replace('CM_HANDLE_ID_HERE', (it + i).toString()) }.join(',') + ']}'
+ cpsDataService.saveListElements(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR, REGISTRY_PARENT, data, now, ContentType.JSON)
}
}
def addRegistryDataWithAlternateIdAsPath() {
- def innerNodeJsonTemplate = readResourceDataFile('ncmp-registry/innerCmHandleNode.json')
+ def cmHandleWithAlternateIdTemplate = readResourceDataFile('inventory/cmHandleWithAlternateIdTemplate.json')
def batchSize = 10
for (def i = 0; i < TOTAL_CM_HANDLES; i += batchSize) {
def data = '{ "cm-handles": [' + (1..batchSize).collect {
- innerNodeJsonTemplate.replace('CM_HANDLE_ID_HERE', (it + i).toString())
+ cmHandleWithAlternateIdTemplate.replace('CM_HANDLE_ID_HERE', (it + i).toString())
.replace('ALTERNATE_ID_AS_PATH', (it + i).toString())
}.join(',') + ']}'
- cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry', data, now, ContentType.JSON)
+ cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, REGISTRY_PARENT, data, now, ContentType.JSON)
}
}
@@ -117,7 +119,7 @@ class NcmpPerfTestBase extends PerfTestBase {
def result = cpsDataService.getDataNodes(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR, '/', FetchDescendantsOption.OMIT_DESCENDANTS)
resourceMeter.stop()
then: 'expected data exists'
- assert result.xpath == ['/dmi-registry']
+ assert result.xpath == [REGISTRY_PARENT]
and: 'operation completes within expected time'
recordAndAssertResourceUsage('NCMP pre-load test data',
15, resourceMeter.totalTimeInSeconds,
diff --git a/integration-test/src/test/resources/application-module-sync-delayed.yml b/integration-test/src/test/resources/application-module-sync-delayed.yml
new file mode 100644
index 0000000000..7b9c6aea4f
--- /dev/null
+++ b/integration-test/src/test/resources/application-module-sync-delayed.yml
@@ -0,0 +1,23 @@
+# ============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=========================================================
+
+test:
+ ncmp:
+ timers:
+ advised-modules-sync:
+ initial-delay-ms: 600000
+
diff --git a/integration-test/src/test/resources/application.yml b/integration-test/src/test/resources/application.yml
index 853797aac5..b786a3d4c5 100644
--- a/integration-test/src/test/resources/application.yml
+++ b/integration-test/src/test/resources/application.yml
@@ -179,7 +179,7 @@ ncmp:
timers:
advised-modules-sync:
- sleep-time-ms: 1000
+ sleep-time-ms: 1000000
cm-handle-data-sync:
sleep-time-ms: 30000
subscription-forwarding:
diff --git a/integration-test/src/test/resources/data/ncmp-registry/innerNode.json b/integration-test/src/test/resources/data/inventory/cmHandleTemplate.json
index b6c65f3763..6577f4e560 100644
--- a/integration-test/src/test/resources/data/ncmp-registry/innerNode.json
+++ b/integration-test/src/test/resources/data/inventory/cmHandleTemplate.json
@@ -1,6 +1,6 @@
{
- "id": "cm-CMHANDLE_ID_HERE",
- "alternate-id": "alt-CMHANDLE_ID_HERE",
+ "id": "cm-CM_HANDLE_ID_HERE",
+ "alternate-id": "alt-CM_HANDLE_ID_HERE",
"module-set-tag": "my-module-set-tag",
"dmi-service-name": "http://ncmp-dmi-plugin-stub:8080",
"dmi-data-service-name": "",
@@ -21,4 +21,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/integration-test/src/test/resources/data/ncmp-registry/innerCmHandleNode.json b/integration-test/src/test/resources/data/inventory/cmHandleWithAlternateIdTemplate.json
index 88446c4a0f..88446c4a0f 100644
--- a/integration-test/src/test/resources/data/ncmp-registry/innerCmHandleNode.json
+++ b/integration-test/src/test/resources/data/inventory/cmHandleWithAlternateIdTemplate.json
diff --git a/integration-test/src/test/resources/data/ncmp-registry/dmi-registry@2024-02-23.yang b/integration-test/src/test/resources/data/inventory/dmi-registry@2024-02-23.yang
index d7b4ff7550..d7b4ff7550 100644
--- a/integration-test/src/test/resources/data/ncmp-registry/dmi-registry@2024-02-23.yang
+++ b/integration-test/src/test/resources/data/inventory/dmi-registry@2024-02-23.yang
diff --git a/k6-tests/ncmp/common/search-base.js b/k6-tests/ncmp/common/search-base.js
index 1e98e9b07b..af2caf71ec 100644
--- a/k6-tests/ncmp/common/search-base.js
+++ b/k6-tests/ncmp/common/search-base.js
@@ -43,7 +43,7 @@ const SEARCH_PARAMETERS_PER_SCENARIO = {
"cmHandleQueryParameters": [
{
"conditionName": "hasAllModules",
- "conditionParameters": [{"moduleName": "ietf-yang-types"}]
+ "conditionParameters": [{"moduleName": "module100"}]
}
]
},
diff --git a/k6-tests/ncmp/common/utils.js b/k6-tests/ncmp/common/utils.js
index 7873732361..6ddcca5fbf 100644
--- a/k6-tests/ncmp/common/utils.js
+++ b/k6-tests/ncmp/common/utils.js
@@ -30,7 +30,7 @@ export const LEGACY_BATCH_THROUGHPUT_TEST_BATCH_SIZE = 200;
export const LEGACY_BATCH_THROUGHPUT_TEST_NUMBER_OF_REQUESTS = 1000;
export const LEGACY_BATCH_TOPIC_NAME = 'legacy_batch_topic';
export const KAFKA_BOOTSTRAP_SERVERS = ['localhost:9092'];
-export const MODULE_SET_TAGS = ['tagA','tagB','tagC',' tagD']
+export const MODULE_SET_TAGS = ['tagA', 'tagB', 'tagC', 'tagD', 'tagE'];
/**
@@ -85,7 +85,7 @@ export function makeCustomSummaryReport(testResults, scenarioConfig) {
const summaryCsvLines = [
'#,Test Name,Unit,Fs Requirement,Current Expectation,Actual',
makeSummaryCsvLine('0', 'HTTP request failures for all tests', 'rate of failed requests', 'http_req_failed', 0, testResults, scenarioConfig),
- makeSummaryCsvLine('1', 'Registration of CM-handles', 'CM-handles/second', 'cmhandles_created_per_second', 110, testResults, scenarioConfig),
+ makeSummaryCsvLine('1', 'Registration of CM-handles', 'CM-handles/second', 'cmhandles_created_per_second', 70, testResults, scenarioConfig),
makeSummaryCsvLine('2', 'De-registration of CM-handles', 'CM-handles/second', 'cmhandles_deleted_per_second', 90, testResults, scenarioConfig),
makeSummaryCsvLine('3a', 'CM-handle ID search with No filter', 'milliseconds', 'id_search_nofilter_duration', 400, testResults, scenarioConfig),
makeSummaryCsvLine('3b', 'CM-handle ID search with Module filter', 'milliseconds', 'id_search_module_duration', 200, testResults, scenarioConfig),
diff --git a/k6-tests/ncmp/ncmp-kpi.js b/k6-tests/ncmp/ncmp-kpi.js
index 8815511bdd..53f7629cac 100644
--- a/k6-tests/ncmp/ncmp-kpi.js
+++ b/k6-tests/ncmp/ncmp-kpi.js
@@ -58,8 +58,8 @@ const DURATION = '15m';
const LEGACY_BATCH_THROUGHPUT_TEST_START_TIME = '15m30s';
export const options = {
- setupTimeout: '8m',
- teardownTimeout: '6m',
+ setupTimeout: '20m',
+ teardownTimeout: '20m',
scenarios: {
passthrough_read_scenario: {
executor: 'constant-vus',
diff --git a/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/Sleeper.java b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/Sleeper.java
index 8f904cc5f2..789201ffce 100644
--- a/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/Sleeper.java
+++ b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/Sleeper.java
@@ -24,8 +24,8 @@ import java.util.concurrent.TimeUnit;
import org.springframework.stereotype.Service;
/**
- * This class is a successfull experiment to extract out sleep functionality so the interrupted exception handling can
- * be covered with a test (e.g. using spy ion Sleeper) and help to get too 100% code coverage.
+ * This class is to extract out sleep functionality so the interrupted exception handling can
+ * be covered with a test (e.g. using spy on Sleeper) and help to get too 100% code coverage.
*/
@Service
public class Sleeper {