aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.gitignore2
-rw-r--r--cps-ncmp-events/src/main/resources/schemas/trustlevel/device-trust-level-event-schema-1.0.0.json30
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml31
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java23
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/SampleCpsNcmpClientSpec.groovy82
-rw-r--r--cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/TestApplication.groovy28
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java31
-rwxr-xr-xcps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java20
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapper.java5
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java8
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java15
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java30
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java12
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilter.java58
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java5
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy13
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy50
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapperSpec.groovy29
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy83
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilterSpec.groovy (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceTrustLevel.java)26
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDogSpec.groovy3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy5
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy26
-rw-r--r--docs/cps-path.rst4
-rw-r--r--docs/cps-stubs.rst120
-rw-r--r--docs/deployment.rst4
-rwxr-xr-xdocs/design.rst23
-rwxr-xr-xdocs/index.rst1
-rwxr-xr-xdocs/release-notes.rst8
-rw-r--r--docs/spelling_wordlist.txt67
-rw-r--r--docs/tox.ini10
35 files changed, 694 insertions, 172 deletions
diff --git a/.gitignore b/.gitignore
index b4abc48bc..c59fc4731 100755
--- a/.gitignore
+++ b/.gitignore
@@ -27,10 +27,10 @@ tmp/
.checkstyle
/.tox
-/_build/*
/__pycache__/*
/docs/docs/
/docs/.vscode/
+/docs/_build/*
/test-tools/metrics-reports/
diff --git a/cps-ncmp-events/src/main/resources/schemas/trustlevel/device-trust-level-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/trustlevel/device-trust-level-event-schema-1.0.0.json
new file mode 100644
index 000000000..e1796fbc7
--- /dev/null
+++ b/cps-ncmp-events/src/main/resources/schemas/trustlevel/device-trust-level-event-schema-1.0.0.json
@@ -0,0 +1,30 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "$id": "urn:cps:org.onap.cps.ncmp.events:device-trust-level-event-schema:1.0.0",
+ "$ref": "#/definitions/DeviceTrustLevel",
+ "definitions": {
+ "DeviceTrustLevel" : {
+ "description": "The payload for device trust level event.",
+ "type": "object",
+ "javaType": "org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel",
+ "properties": {
+ "data": {
+ "type": "object",
+ "properties": {
+ "trustLevel": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "trustLevel"
+ ],
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false,
+ "required": [
+ "data"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
index 83699b934..d2cce8797 100644
--- a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
@@ -46,11 +46,42 @@
<groupId>org.onap.cps</groupId>
<artifactId>cps-ncmp-rest</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.servlet</groupId>
+ <artifactId>jakarta.servlet-api</artifactId>
+ </dependency>
<!-- T E S T - D E P E N D E N C I E S -->
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.junit.vintage</groupId>
+ <artifactId>junit-vintage-engine</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.spockframework</groupId>
+ <artifactId>spock-spring</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.spockframework</groupId>
+ <artifactId>spock-core</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+
</project> \ No newline at end of file
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
index 198b14fc3..e33af45f9 100644
--- a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
@@ -141,13 +141,13 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
}
@Override
- public ResponseEntity<Void> createResourceDataRunningForCmHandle(@NotNull @Valid final String resourceIdentifier,
- final String datastoreName, final String cmHandle,
- @Valid final Object body,
+ public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String datastoreName, final String cmHandle,
+ @NotNull @Valid final String resourceIdentifier,
+ @Valid final Object body,
final String contentType) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
-
+
@Override
public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName, final String cmHandle,
@NotNull @Valid final String resourceIdentifier,
@@ -183,13 +183,13 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
}
@Override
- public ResponseEntity<Object> patchResourceDataRunningForCmHandle(@NotNull @Valid final String resourceIdentifier,
- final String datastoreName, final String cmHandle,
- @Valid final Object body,
+ public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String datastoreName, final String cmHandle,
+ @NotNull @Valid final String resourceIdentifier,
+ @Valid final Object body,
final String contentType) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
-
+
@Override
public ResponseEntity<Object> queryResourceDataForCmHandle(final String datastoreName, final String cmHandle,
@Valid final String cpsPath, @Valid final String options,
@@ -218,9 +218,10 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
}
@Override
- public ResponseEntity<Object> updateResourceDataRunningForCmHandle(@NotNull @Valid final String resourceIdentifier,
- final String datastoreName,
- final String cmHandle, @Valid final Object body,
+ public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String datastoreName,
+ final String cmHandle,
+ @NotNull @Valid final String resourceIdentifier,
+ @Valid final Object body,
final String contentType) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/SampleCpsNcmpClientSpec.groovy b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/SampleCpsNcmpClientSpec.groovy
new file mode 100644
index 000000000..b36e25ada
--- /dev/null
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/SampleCpsNcmpClientSpec.groovy
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.cps.ncmp.rest.stub
+
+import org.onap.cps.ncmp.api.impl.operations.DatastoreType
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration
+import org.springframework.boot.test.context.SpringBootContextLoader
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.boot.test.web.client.TestRestTemplate
+import org.springframework.boot.test.web.server.LocalServerPort
+import org.springframework.http.HttpStatus
+import org.springframework.test.context.ActiveProfiles
+import org.springframework.test.context.ContextConfiguration
+
+import com.fasterxml.jackson.core.JsonProcessingException
+import com.fasterxml.jackson.core.type.TypeReference
+import com.fasterxml.jackson.databind.JsonMappingException
+import com.fasterxml.jackson.databind.ObjectMapper
+
+import spock.lang.Shared
+import spock.lang.Specification
+
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+class SampleCpsNcmpClientSpec extends Specification {
+
+ static final String CM_HANDLE = "anything"
+
+ static final String DATA_STORE_NAME = DatastoreType.PASSTHROUGH_OPERATIONAL.getDatastoreName()
+
+ @LocalServerPort
+ def port
+
+ final def testRestTemplate = new TestRestTemplate()
+
+ @Value('${rest.api.ncmp-stub-base-path}')
+ def stubBasePath
+
+ @Autowired
+ ObjectMapper objectMapper
+
+ def 'Test the invocation of the stub API' () throws JsonMappingException, JsonProcessingException {
+
+ when: 'Get resource data for cm handle URL is invoked'
+ def url = "${getBaseUrl()}/v1/ch/${CM_HANDLE}/data/ds/${DATA_STORE_NAME}?resourceIdentifier=parent&options=(a=1,b=2)"
+ def response = testRestTemplate.getForEntity(url, String.class)
+ then: 'Response is OK'
+ response.getStatusCode() == HttpStatus.OK
+
+ and: 'Response body contains customized stub response that contains correct bookstore category code'
+ def typeRef = new TypeReference<HashMap<String, Object>>() {}
+ def map = objectMapper.readValue(response.getBody(), typeRef)
+ def obj1 = (Map<String, Object>) map.get("stores:bookstore")
+ def obj2 = (List<Object>) obj1.get("categories")
+ def obj3 = (Map<String, Object>) obj2.iterator().next()
+
+ assert obj3.get("code") == "02"
+ }
+
+ def String getBaseUrl() {
+ return "http://localhost:" + port + stubBasePath
+ }
+}
diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/TestApplication.groovy b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/TestApplication.groovy
new file mode 100644
index 000000000..79384239a
--- /dev/null
+++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/TestApplication.groovy
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.cps.ncmp.rest.stub
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.context.annotation.ComponentScan
+
+@SpringBootApplication
+@ComponentScan(basePackages = ["org.onap.cps.ncmp.rest.stub", "org.onap.cps.ncmp.rest.stub.controller", "org.onap.cps.ncmp.rest.api"])
+class TestApplication {
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java
index 7475cdd4a..1f6c94869 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceImpl.java
@@ -24,6 +24,7 @@ import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DM
import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_MODULES;
import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.HAS_ALL_PROPERTIES;
import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_CPS_PATH;
+import static org.onap.cps.ncmp.api.impl.utils.CmHandleQueryConditions.WITH_TRUST_LEVEL;
import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateCpsPathConditionProperties;
import static org.onap.cps.ncmp.api.impl.utils.RestQueryParametersValidator.validateModuleNameConditionProperties;
import static org.onap.cps.ncmp.api.impl.utils.YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle;
@@ -70,7 +71,8 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
return executeQueries(cmHandleQueryServiceParameters,
this::executeCpsPathQuery,
this::queryCmHandlesByPublicProperties,
- this::executeModuleNameQuery);
+ this::executeModuleNameQuery,
+ this::queryCmHandlesByTrustLevel);
}
@Override
@@ -117,9 +119,10 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
InventoryQueryConditions.HAS_ALL_ADDITIONAL_PROPERTIES.getName());
- return privatePropertyQueryPairs.isEmpty()
- ? NO_QUERY_TO_EXECUTE
- : cmHandleQueries.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
+ if (privatePropertyQueryPairs.isEmpty()) {
+ return NO_QUERY_TO_EXECUTE;
+ }
+ return cmHandleQueries.queryCmHandleAdditionalProperties(privatePropertyQueryPairs);
}
private Collection<String> queryCmHandlesByPublicProperties(
@@ -129,9 +132,23 @@ public class NetworkCmProxyCmHandleQueryServiceImpl implements NetworkCmProxyCmH
getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
HAS_ALL_PROPERTIES.getConditionName());
- return publicPropertyQueryPairs.isEmpty()
- ? NO_QUERY_TO_EXECUTE
- : cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
+ if (publicPropertyQueryPairs.isEmpty()) {
+ return NO_QUERY_TO_EXECUTE;
+ }
+ return cmHandleQueries.queryCmHandlePublicProperties(publicPropertyQueryPairs);
+ }
+
+ private Collection<String> queryCmHandlesByTrustLevel(final CmHandleQueryServiceParameters
+ cmHandleQueryServiceParameters) {
+
+ final Map<String, String> trustLevelPropertyQueryPairs =
+ getPropertyPairs(cmHandleQueryServiceParameters.getCmHandleQueryParameters(),
+ WITH_TRUST_LEVEL.getConditionName());
+
+ if (trustLevelPropertyQueryPairs.isEmpty()) {
+ return NO_QUERY_TO_EXECUTE;
+ }
+ return cmHandleQueries.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs);
}
private Collection<String> executeModuleNameQuery(
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
index 692a9f2a9..a37b27199 100755
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
@@ -99,7 +99,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler;
private final CpsDataService cpsDataService;
private final IMap<String, Object> moduleSyncStartedOnCmHandles;
- private final IMap<String, TrustLevel> trustLevelPerDmiPlugin;
+ private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
@Override
public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
index 6a8310c20..e8ce050b2 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
@@ -75,10 +75,8 @@ public class DmiRestClient {
final HttpEntity<Object> httpHeaders = new HttpEntity<>(configureHttpHeaders(new HttpHeaders()));
final JsonNode dmiPluginHealthStatus = restTemplate.getForObject(dmiPluginBaseUrl + "/manage/health",
JsonNode.class, httpHeaders);
- if (dmiPluginHealthStatus != null) {
- if (dmiPluginHealthStatus.get("status").asText().equals("UP")) {
- return DmiPluginStatus.UP;
- }
+ if (dmiPluginHealthStatus != null && dmiPluginHealthStatus.get("status").asText().equals("UP")) {
+ return DmiPluginStatus.UP;
}
} catch (final Exception exception) {
log.warn("Could not send request for health check since {}", exception.getMessage());
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java
index ebe99057d..171db5299 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java
@@ -20,10 +20,8 @@
package org.onap.cps.ncmp.api.impl.config.embeddedcache;
-import com.hazelcast.collection.ISet;
import com.hazelcast.config.MapConfig;
-import com.hazelcast.config.SetConfig;
-import com.hazelcast.map.IMap;
+import java.util.Map;
import org.onap.cps.cache.HazelcastCacheConfig;
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
import org.springframework.context.annotation.Bean;
@@ -32,21 +30,21 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class TrustLevelCacheConfig extends HazelcastCacheConfig {
- private static final SetConfig untrustworthyCmHandlesSetConfig =
- createSetConfig("untrustworthyCmHandlesSetConfig");
+ private static final MapConfig trustLevelPerCmHandleCacheConfig =
+ createMapConfig("trustLevelPerCmHandleCacheConfig");
private static final MapConfig trustLevelPerDmiPluginCacheConfig =
createMapConfig("trustLevelPerDmiPluginCacheConfig");
/**
- * Distributed collection of untrustworthy cm handles.
+ * Distributed instance of trust level cache containing the trust level per cm handle.
*
- * @return instance of distributed set of untrustworthy cm handles.
+ * @return configured map of cm handle name as keys to trust-level for values.
*/
@Bean
- public ISet<String> untrustworthyCmHandlesSet() {
- return createHazelcastInstance("untrustworthyCmHandlesSet",
- untrustworthyCmHandlesSetConfig).getSet("untrustworthyCmHandlesSet");
+ public Map<String, TrustLevel> trustLevelPerCmHandle() {
+ return createHazelcastInstance("hazelcastInstanceTrustLevelPerCmHandleMap",
+ trustLevelPerCmHandleCacheConfig).getMap("trustLevelPerCmHandle");
}
/**
@@ -55,7 +53,7 @@ public class TrustLevelCacheConfig extends HazelcastCacheConfig {
* @return configured map of dmi-plugin name as keys to trust-level for values.
*/
@Bean
- public IMap<String, TrustLevel> trustLevelPerDmiPlugin() {
+ public Map<String, TrustLevel> trustLevelPerDmiPlugin() {
return createHazelcastInstance("hazelcastInstanceTrustLevelPerDmiPluginMap",
trustLevelPerDmiPluginCacheConfig).getMap("trustLevelPerDmiPlugin");
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapper.java
index 98ba95386..4120970e5 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapper.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapper.java
@@ -25,7 +25,6 @@ import io.cloudevents.CloudEvent;
import io.cloudevents.core.CloudEventUtils;
import io.cloudevents.core.data.PojoCloudEventData;
import io.cloudevents.jackson.PojoCloudEventDataMapper;
-import io.cloudevents.rw.CloudEventRWException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -51,9 +50,9 @@ public class CloudEventMapper {
mappedCloudEvent =
CloudEventUtils.mapData(cloudEvent, PojoCloudEventDataMapper.from(objectMapper, targetEventClass));
- } catch (final CloudEventRWException cloudEventRwException) {
+ } catch (final RuntimeException runtimeException) {
log.error("Unable to map cloud event to target event class type : {} with cause : {}", targetEventClass,
- cloudEventRwException.getMessage());
+ runtimeException.getMessage());
}
return mappedCloudEvent == null ? null : mappedCloudEvent.getValue();
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java
index a5892afc3..81467dbb3 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueries.java
@@ -45,6 +45,14 @@ public interface CmHandleQueries {
Collection<String> queryCmHandlePublicProperties(Map<String, String> publicPropertyQueryPairs);
/**
+ * Query CmHandles based on Trust Level.
+ *
+ * @param trustLevelPropertyQueryPairs trust level properties for query
+ * @return CmHandles which have desired trust level
+ */
+ Collection<String> queryCmHandlesByTrustLevel(Map<String, String> trustLevelPropertyQueryPairs);
+
+ /**
* Method which returns cm handles by the cm handles state.
*
* @param cmHandleState cm handle state
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java
index c4e3fd098..e5cf8edd6 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java
@@ -35,6 +35,8 @@ import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType;
+import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
+import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelFilter;
import org.onap.cps.spi.CpsDataPersistenceService;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.model.DataNode;
@@ -45,9 +47,9 @@ import org.springframework.stereotype.Component;
public class CmHandleQueriesImpl implements CmHandleQueries {
private static final String DESCENDANT_PATH = "//";
-
- private final CpsDataPersistenceService cpsDataPersistenceService;
private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles";
+ private final CpsDataPersistenceService cpsDataPersistenceService;
+ private final Map<String, TrustLevel> trustLevelPerCmHandle;
@Override
public Collection<String> queryCmHandleAdditionalProperties(final Map<String, String> privatePropertyQueryPairs) {
@@ -60,6 +62,15 @@ public class CmHandleQueriesImpl implements CmHandleQueries {
}
@Override
+ public Collection<String> queryCmHandlesByTrustLevel(final Map<String, String> trustLevelPropertyQueryPairs) {
+ final String trustLevelProperty = trustLevelPropertyQueryPairs.values().iterator().next();
+ final TrustLevel targetTrustLevel = TrustLevel.valueOf(trustLevelProperty);
+
+ final TrustLevelFilter trustLevelFilter = new TrustLevelFilter(targetTrustLevel, trustLevelPerCmHandle);
+ return trustLevelFilter.getAllCmHandleIdsByTargetTrustLevel();
+ }
+
+ @Override
public List<DataNode> queryCmHandlesByState(final CmHandleState cmHandleState) {
return queryCmHandleAncestorsByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]",
INCLUDE_ALL_DESCENDANTS);
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java
index 458c1b851..b6d74d980 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumer.java
@@ -20,14 +20,14 @@
package org.onap.cps.ncmp.api.impl.trustlevel;
-import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent;
-
-import com.hazelcast.collection.ISet;
import io.cloudevents.CloudEvent;
import io.cloudevents.kafka.impl.KafkaHeaders;
+import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper;
+import org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@@ -36,7 +36,8 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor
public class DeviceHeartbeatConsumer {
- private final ISet<String> untrustworthyCmHandlesSet;
+ private static final String CLOUD_EVENT_ID_HEADER_NAME = "ce_id";
+ private final Map<String, TrustLevel> trustLevelPerCmHandle;
/**
* Listening the device heartbeats.
@@ -47,23 +48,16 @@ public class DeviceHeartbeatConsumer {
containerFactory = "cloudEventConcurrentKafkaListenerContainerFactory")
public void heartbeatListener(final ConsumerRecord<String, CloudEvent> deviceHeartbeatConsumerRecord) {
- final String cmHandleId = KafkaHeaders.getParsedKafkaHeader(deviceHeartbeatConsumerRecord.headers(), "ce_id");
+ final String cmHandleId = KafkaHeaders.getParsedKafkaHeader(deviceHeartbeatConsumerRecord.headers(),
+ CLOUD_EVENT_ID_HEADER_NAME);
final DeviceTrustLevel deviceTrustLevel =
- toTargetEvent(deviceHeartbeatConsumerRecord.value(), DeviceTrustLevel.class);
-
- if (deviceTrustLevel == null || deviceTrustLevel.getTrustLevel() == null) {
- log.warn("No or Invalid trust level defined");
- return;
- }
+ CloudEventMapper.toTargetEvent(deviceHeartbeatConsumerRecord.value(), DeviceTrustLevel.class);
- if (deviceTrustLevel.getTrustLevel().equals(TrustLevel.NONE)) {
- untrustworthyCmHandlesSet.add(cmHandleId);
- log.debug("Added cmHandleId to untrustworthy set : {}", cmHandleId);
- } else if (deviceTrustLevel.getTrustLevel().equals(TrustLevel.COMPLETE) && untrustworthyCmHandlesSet.contains(
- cmHandleId)) {
- untrustworthyCmHandlesSet.remove(cmHandleId);
- log.debug("Removed cmHandleId from untrustworthy set : {}", cmHandleId);
+ if (cmHandleId != null && deviceTrustLevel != null) {
+ final String trustLevel = deviceTrustLevel.getData().getTrustLevel();
+ trustLevelPerCmHandle.put(cmHandleId, TrustLevel.valueOf(trustLevel));
+ log.debug("Added cmHandleId to trustLevelPerCmHandle map as {}:{}", cmHandleId, trustLevel);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java
index f4254bb47..8d1f8e90f 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevel.java
@@ -20,6 +20,16 @@
package org.onap.cps.ncmp.api.impl.trustlevel;
+import lombok.Getter;
+
+@Getter
public enum TrustLevel {
- NONE, COMPLETE;
+ NONE(0), COMPLETE(99);
+
+ private final int value;
+
+ TrustLevel(final int value) {
+ this.value = value;
+ }
+
} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilter.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilter.java
new file mode 100644
index 000000000..3b704ae4f
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilter.java
@@ -0,0 +1,58 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl.trustlevel;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+public class TrustLevelFilter implements Comparable<TrustLevel> {
+
+ @EqualsAndHashCode.Include
+ private final TrustLevel targetTrustLevel;
+ private final Map<String, TrustLevel> trustLevelPerCmHandle;
+
+ @Override
+ public int compareTo(@NonNull final TrustLevel other) {
+ return Integer.compare(this.targetTrustLevel.getValue(), other.getValue());
+ }
+
+ /**
+ * This method return cm handles that matches with given trust level.
+ *
+ * @return cm handle ids.
+ */
+ public Collection<String> getAllCmHandleIdsByTargetTrustLevel() {
+ final Collection<String> resultCmHandleIds = new HashSet<>();
+ trustLevelPerCmHandle.entrySet().forEach(cmHandleTrustLevelEntrySet -> {
+ if (compareTo(cmHandleTrustLevelEntrySet.getValue()) == 0) {
+ resultCmHandleIds.add(cmHandleTrustLevelEntrySet.getKey());
+ }
+ });
+ return resultCmHandleIds;
+ }
+
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java
index d3b95eacb..39f880257 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDog.java
@@ -20,7 +20,7 @@
package org.onap.cps.ncmp.api.impl.trustlevel.dmiavailability;
-import com.hazelcast.map.IMap;
+import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
@@ -33,7 +33,7 @@ import org.springframework.stereotype.Service;
@Service
public class DMiPluginWatchDog {
- private final IMap<String, TrustLevel> trustLevelPerDmiPlugin;
+ private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
private final DmiRestClient dmiRestClient;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java
index b1bb7f767..a59776036 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditions.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * Copyright (C) 2022-2023 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,8 @@ import lombok.Getter;
public enum CmHandleQueryConditions {
HAS_ALL_PROPERTIES("hasAllProperties"),
HAS_ALL_MODULES("hasAllModules"),
- WITH_CPS_PATH("cmHandleWithCpsPath");
+ WITH_CPS_PATH("cmHandleWithCpsPath"),
+ WITH_TRUST_LEVEL("cmHandleWithTrustLevel");
public static final Collection<String> ALL_CONDITION_NAMES = Arrays.stream(CmHandleQueryConditions.values())
.map(CmHandleQueryConditions::getConditionName).collect(Collectors.toList());
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy
index ce6d85658..7c410cc58 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandleQueryServiceSpec.groovy
@@ -39,7 +39,7 @@ import spock.lang.Specification
class NetworkCmProxyCmHandleQueryServiceSpec extends Specification {
def cmHandleQueries = Mock(CmHandleQueries)
- def partiallyMockedCmHandleQueries = Spy(CmHandleQueriesImpl)
+ def partiallyMockedCmHandleQueries = Spy(CmHandleQueries)
def mockInventoryPersistence = Mock(InventoryPersistence)
def dmiRegistry = new DataNode(xpath: NCMP_DMI_REGISTRY_PARENT, childDataNodes: createDataNodeList(['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4']))
@@ -106,6 +106,17 @@ class NetworkCmProxyCmHandleQueryServiceSpec extends Specification {
'No anchors are returned' | []
}
+ def 'Query cm handles with some trust level query parameters'() {
+ given: 'a trust level condition property'
+ def trustLevelQueryParameters = new CmHandleQueryServiceParameters()
+ def trustLevelConditionProperties = createConditionProperties('cmHandleWithTrustLevel', [['trustLevel': 'COMPLETE'] as Map])
+ trustLevelQueryParameters.setCmHandleQueryParameters([trustLevelConditionProperties])
+ when: 'the query is being executed'
+ objectUnderTest.queryCmHandleIds(trustLevelQueryParameters)
+ then: 'the query is being delegated to the cm handle query service with correct parameter'
+ 1 * cmHandleQueries.queryCmHandlesByTrustLevel(['trustLevel': 'COMPLETE'] as Map)
+ }
+
def 'Query cm handle details with module names when #scenario from query.'() {
given: 'a modules condition property'
def cmHandleQueryParameters = new CmHandleQueryServiceParameters()
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
index 0d9aa6124..af65cfc1a 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
@@ -76,7 +76,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
def mockCpsCmHandlerQueryService = Mock(NetworkCmProxyCmHandleQueryService)
def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler)
def stubModuleSyncStartedOnCmHandles = Stub(IMap<String, Object>)
- def stubTrustLevelPerDmiPlugin = Stub(IMap<String, TrustLevel>)
+ def stubTrustLevelPerDmiPlugin = Stub(Map<String, TrustLevel>)
def NO_TOPIC = null
def NO_REQUEST_ID = null
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy
index 6184a9722..3eff96d79 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfigSpec.groovy
@@ -22,7 +22,6 @@ package org.onap.cps.ncmp.api.impl.config.embeddedcache
import com.hazelcast.config.Config
import com.hazelcast.core.Hazelcast
-import com.hazelcast.map.IMap
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
@@ -32,7 +31,10 @@ import spock.lang.Specification
class TrustLevelCacheConfigSpec extends Specification {
@Autowired
- private IMap<String, TrustLevel> trustLevelPerDmiPlugin
+ private Map<String, TrustLevel> trustLevelPerDmiPlugin
+
+ @Autowired
+ private Map<String, TrustLevel> trustLevelPerCmHandle
def 'Hazelcast cache for trust level per dmi plugin'() {
expect: 'system is able to create an instance of the trust level per dmi plugin cache'
@@ -43,23 +45,29 @@ class TrustLevelCacheConfigSpec extends Specification {
assert Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceTrustLevelPerDmiPluginMap')
}
- def 'Verify Trust Level Per Dmi Plugin Cache for basic hazelcast map operations'() {
- when: 'the key inserted into Trust Level Per Dmi Plugin Cache'
- trustLevelPerDmiPlugin.put('dmi1', TrustLevel.COMPLETE)
- trustLevelPerDmiPlugin.put('dmi2', TrustLevel.NONE)
- then: 'the value for each dmi can be retrieved'
- assert trustLevelPerDmiPlugin.get('dmi1') == TrustLevel.COMPLETE
- assert trustLevelPerDmiPlugin.get('dmi2') == TrustLevel.NONE
+ def 'Hazelcast cache for trust level per cm handle'() {
+ expect: 'system is able to create an instance of the trust level per cm handle cache'
+ assert null != trustLevelPerCmHandle
+ and: 'there is at least 1 instance'
+ assert Hazelcast.allHazelcastInstances.size() > 0
+ and: 'Hazelcast cache instance for trust level is present'
+ assert Hazelcast.allHazelcastInstances.name.contains('hazelcastInstanceTrustLevelPerCmHandleMap')
}
- def 'Verify configs for Distributed Caches'(){
- given: 'the Trust Level Per Dmi Plugin Cache config'
- def trustLevelDmiPerPluginCacheConfig = Hazelcast.getHazelcastInstanceByName('hazelcastInstanceTrustLevelPerDmiPluginMap').config
- def trustLevelDmiPerPluginCacheMapConfig = trustLevelDmiPerPluginCacheConfig.mapConfigs.get('trustLevelPerDmiPluginCacheConfig')
- expect: 'system created instance with correct config'
- assert trustLevelDmiPerPluginCacheConfig.clusterName == 'cps-and-ncmp-test-caches'
- assert trustLevelDmiPerPluginCacheMapConfig.backupCount == 3
- assert trustLevelDmiPerPluginCacheMapConfig.asyncBackupCount == 3
+ def 'Trust level cache configurations: #scenario'() {
+ when: 'retrieving the cache config for trustLevel'
+ def cacheConfig = Hazelcast.getHazelcastInstanceByName(hazelcastInstanceName).config
+ then: 'the cache config has the right cluster'
+ assert cacheConfig.clusterName == 'cps-and-ncmp-test-caches'
+ when: 'retrieving the map config for trustLevel'
+ def mapConfig = cacheConfig.mapConfigs.get(hazelcastMapConfigName)
+ then: 'the map config has the correct backup counts'
+ assert mapConfig.backupCount == 3
+ assert mapConfig.asyncBackupCount == 3
+ where: 'the following caches are used'
+ scenario | hazelcastInstanceName | hazelcastMapConfigName
+ 'cmhandle map' | 'hazelcastInstanceTrustLevelPerCmHandleMap' | 'trustLevelPerCmHandleCacheConfig'
+ 'dmi plugin map' | 'hazelcastInstanceTrustLevelPerDmiPluginMap' | 'trustLevelPerDmiPluginCacheConfig'
}
def 'Verify deployment network configs for Distributed Caches'() {
@@ -70,6 +78,14 @@ class TrustLevelCacheConfigSpec extends Specification {
assert !trustLevelDmiPerPluginCacheConfig.join.kubernetesConfig.enabled
}
+ def 'Verify deployment network configs for Cm Handle Distributed Caches'() {
+ given: 'the Trust Level Per Cm Handle Cache config'
+ def trustLevelPerCmHandlePluginCacheConfig = Hazelcast.getHazelcastInstanceByName('hazelcastInstanceTrustLevelPerCmHandleMap').config.networkConfig
+ expect: 'system created instance with correct config'
+ assert trustLevelPerCmHandlePluginCacheConfig.join.autoDetectionConfig.enabled
+ assert !trustLevelPerCmHandlePluginCacheConfig.join.kubernetesConfig.enabled
+ }
+
def 'Verify network config'() {
given: 'Synchronization config object and test configuration'
def objectUnderTest = new TrustLevelCacheConfig()
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapperSpec.groovy
index 380aea405..e6d383128 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapperSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/mapper/CloudEventMapperSpec.groovy
@@ -34,17 +34,30 @@ class CloudEventMapperSpec extends Specification {
@Autowired
JsonObjectMapper jsonObjectMapper
- def 'Cloud event to Target event type when it is #scenario'() {
- expect: 'Events mapped correctly'
- assert mappedCloudEvent == (CloudEventMapper.toTargetEvent(testCloudEvent(), targetClass) != null)
+ def 'Cloud event to target event type'() {
+ given: 'a cloud event with valid payload'
+ def cloudEvent = testCloudEvent(new CmSubscriptionNcmpInEvent())
+ when: 'the cloud event mapped to target event'
+ def result = CloudEventMapper.toTargetEvent((cloudEvent), CmSubscriptionNcmpInEvent.class)
+ then: 'the cloud event is mapped'
+ assert result instanceof CmSubscriptionNcmpInEvent
+ }
+
+ def 'Cloud event to target event type when it is #scenario'() {
+ given: 'a cloud event with invalid payload'
+ def cloudEvent = testCloudEvent(payload)
+ when: 'the cloud event mapped to target event'
+ def result = CloudEventMapper.toTargetEvent(cloudEvent, CmSubscriptionNcmpInEvent.class)
+ then: 'result is null'
+ assert result == null
where: 'below are the scenarios'
- scenario | targetClass || mappedCloudEvent
- 'valid concrete type' | CmSubscriptionNcmpInEvent.class || true
- 'invalid concrete type' | ArrayList.class || false
+ scenario | payload
+ 'invalid payload type' | ArrayList.class
+ 'without payload' | null
}
- def testCloudEvent() {
- return CloudEventBuilder.v1().withData(jsonObjectMapper.asJsonBytes(new CmSubscriptionNcmpInEvent()))
+ def testCloudEvent(payload) {
+ return CloudEventBuilder.v1().withData(jsonObjectMapper.asJsonBytes(payload))
.withId("cmhandle1")
.withSource(URI.create('test-source'))
.withDataSchema(URI.create('test'))
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy
index 48de23dca..80778b9c7 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/DeviceHeartbeatConsumerSpec.groovy
@@ -21,81 +21,70 @@
package org.onap.cps.ncmp.api.impl.trustlevel
import com.fasterxml.jackson.databind.ObjectMapper
-import com.hazelcast.collection.ISet
+import com.hazelcast.map.IMap
import io.cloudevents.CloudEvent
import io.cloudevents.core.builder.CloudEventBuilder
import org.apache.kafka.clients.consumer.ConsumerRecord
+import org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel
import org.onap.cps.utils.JsonObjectMapper
+import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import spock.lang.Specification
@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper])
class DeviceHeartbeatConsumerSpec extends Specification {
- def mockUntrustworthyCmHandlesSet = Mock(ISet<String>)
+ def mockTrustLevelPerCmHandle = Mock(Map<String, TrustLevel>)
+
+ def objectUnderTest = new DeviceHeartbeatConsumer(mockTrustLevelPerCmHandle)
def objectMapper = new ObjectMapper()
- def objectUnderTest = new DeviceHeartbeatConsumer(mockUntrustworthyCmHandlesSet)
+ @Autowired
+ JsonObjectMapper jsonObjectMapper
+
+ def static trustLevelString = '{"data":{"trustLevel": "COMPLETE"}}'
- def 'Operations to be done in an empty untrustworthy set for #scenario'() {
- given: 'an event with trustlevel as #trustLevel'
- def incomingEvent = testCloudEvent(trustLevel)
- and: 'transformed as a kafka record'
- def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', incomingEvent)
+ def 'Consume a trustlevel event'() {
+ given: 'an event from dmi with trust level complete'
+ def payload = jsonObjectMapper.convertJsonString(trustLevelString, DeviceTrustLevel.class)
+ def eventFromDmi = createTrustLevelEvent(payload)
+ and: 'transformed to a consumer record with a cloud event id (ce_id)'
+ def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'sample-message-key', eventFromDmi)
consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('cmhandle1'))
when: 'the event is consumed'
objectUnderTest.heartbeatListener(consumerRecord)
- then: 'untrustworthy cmhandles are stored'
- untrustworthyCmHandlesSetInvocationForAdd * mockUntrustworthyCmHandlesSet.add(_)
- and: 'trustworthy cmHandles will be removed from untrustworthy set'
- untrustworthyCmHandlesSetInvocationForContains * mockUntrustworthyCmHandlesSet.contains(_)
-
- where: 'below scenarios are applicable'
- scenario | trustLevel || untrustworthyCmHandlesSetInvocationForAdd | untrustworthyCmHandlesSetInvocationForContains
- 'None trust' | TrustLevel.NONE || 1 | 0
- 'Complete trust' | TrustLevel.COMPLETE || 0 | 1
+ then: 'cm handles are stored with correct trust level'
+ 1 * mockTrustLevelPerCmHandle.put('"cmhandle1"', TrustLevel.COMPLETE)
}
- def 'Invalid trust'() {
- when: 'we provide an invalid trust in the event'
- def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', testCloudEvent(null))
- consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('cmhandle1'))
+ def 'Consume trustlevel event without cloud event id'() {
+ given: 'an event from dmi'
+ def payload = jsonObjectMapper.convertJsonString(trustLevelString, DeviceTrustLevel.class)
+ def eventFromDmi = createTrustLevelEvent(payload)
+ and: 'transformed to a consumer record WITHOUT Cloud event ID (ce_id)'
+ def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'sample-message-key', eventFromDmi)
+ when: 'the event is consumed'
objectUnderTest.heartbeatListener(consumerRecord)
- then: 'no interaction with the untrustworthy cmhandles set'
- 0 * mockUntrustworthyCmHandlesSet.add(_)
- 0 * mockUntrustworthyCmHandlesSet.contains(_)
- 0 * mockUntrustworthyCmHandlesSet.remove(_)
- and: 'control flow returns without any exception'
- noExceptionThrown()
-
+ then: 'no cm handle has been stored in the map'
+ 0 * mockTrustLevelPerCmHandle.put(*_)
}
- def 'Remove trustworthy cmhandles from untrustworthy cmhandles set'() {
- given: 'an event with COMPLETE trustlevel'
- def incomingEvent = testCloudEvent(TrustLevel.COMPLETE)
- and: 'transformed as a kafka record'
- def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', incomingEvent)
- consumerRecord.headers().add('ce_id', objectMapper.writeValueAsBytes('cmhandle1'))
- and: 'untrustworthy cmhandles set contains cmhandle1'
- 1 * mockUntrustworthyCmHandlesSet.contains(_) >> true
+ def 'Consume a trust level event without payload'() {
+ given: 'a consumer record with ce_id header but without payload'
+ def consumerRecord = new ConsumerRecord<String, CloudEvent>('test-device-heartbeat', 0, 0, 'cmhandle1', createTrustLevelEvent(null))
+ consumerRecord.headers().add('some_other_header_value', objectMapper.writeValueAsBytes('cmhandle1'))
when: 'the event is consumed'
objectUnderTest.heartbeatListener(consumerRecord)
- then: 'cmhandle removed from untrustworthy cmhandles set'
- 1 * mockUntrustworthyCmHandlesSet.remove(_) >> {
- args ->
- {
- args[0].equals('cmhandle1')
- }
- }
-
+ then: 'no cm handle has been stored in the map'
+ 0 * mockTrustLevelPerCmHandle.put(*_)
}
- def testCloudEvent(trustLevel) {
- return CloudEventBuilder.v1().withData(objectMapper.writeValueAsBytes(new DeviceTrustLevel(trustLevel)))
+ def createTrustLevelEvent(eventPayload) {
+ return CloudEventBuilder.v1().withData(objectMapper.writeValueAsBytes(eventPayload))
.withId("cmhandle1")
.withSource(URI.create('DMI'))
.withDataSchema(URI.create('test'))
- .withType('org.onap.cm.events.trustlevel-notification')
+ .withType('org.onap.cps.ncmp.events.trustlevel.DeviceTrustLevel')
.build()
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceTrustLevel.java b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilterSpec.groovy
index 2ed4e4522..8f6621d24 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/DeviceTrustLevel.java
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelFilterSpec.groovy
@@ -18,20 +18,24 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.trustlevel;
+package org.onap.cps.ncmp.api.impl.trustlevel
-import java.io.Serializable;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-@AllArgsConstructor
-@Data
-@NoArgsConstructor
-class DeviceTrustLevel implements Serializable {
+import spock.lang.Specification
- private static final long serialVersionUID = -1705715024067165212L;
+class TrustLevelFilterSpec extends Specification {
- private TrustLevel trustLevel;
+ def targetTrustLevel = TrustLevel.COMPLETE
+ def trustLevelPerCmHandle = [ 'my completed cm handle': TrustLevel.COMPLETE, 'my untrusted cm handle': TrustLevel.NONE ]
+
+ def objectUnderTest = new TrustLevelFilter(targetTrustLevel, trustLevelPerCmHandle)
+
+ def 'Obtain cm handle ids by a given trust level value'() {
+ when: 'cm handles are retrieved'
+ def result = objectUnderTest.getAllCmHandleIdsByTargetTrustLevel()
+ then: 'the result only contains the completed cm handle'
+ assert result.size() == 1
+ assert result[0] == 'my completed cm handle'
+ }
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDogSpec.groovy
index af546b7f5..b6259bdf3 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDogSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DMiPluginWatchDogSpec.groovy
@@ -20,7 +20,6 @@
package org.onap.cps.ncmp.api.impl.trustlevel.dmiavailability
-import com.hazelcast.map.IMap
import org.onap.cps.ncmp.api.impl.client.DmiRestClient
import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
import spock.lang.Specification
@@ -28,7 +27,7 @@ import spock.lang.Specification
class DMiPluginWatchDogSpec extends Specification {
- def mockTrustLevelPerDmiPlugin = Mock(IMap<String, TrustLevel>)
+ def mockTrustLevelPerDmiPlugin = Mock(Map<String, TrustLevel>)
def mockDmiRestClient = Mock(DmiRestClient)
def objectUnderTest = new DMiPluginWatchDog(mockTrustLevelPerDmiPlugin, mockDmiRestClient)
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy
index f0e2d9f0b..100705ff5 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/CmHandleQueryConditionsSpec.groovy
@@ -26,10 +26,11 @@ class CmHandleQueryConditionsSpec extends Specification {
def 'CmHandle query condition names.'() {
expect: '3 conditions with the correct names'
- assert CmHandleQueryConditions.ALL_CONDITION_NAMES.size() == 3
+ assert CmHandleQueryConditions.ALL_CONDITION_NAMES.size() == 4
assert CmHandleQueryConditions.ALL_CONDITION_NAMES.containsAll('hasAllProperties',
'hasAllModules',
- 'cmHandleWithCpsPath')
+ 'cmHandleWithCpsPath',
+ 'cmHandleWithTrustLevel')
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy
index e7c337cc2..a3a5efc74 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesImplSpec.groovy
@@ -21,12 +21,15 @@
package org.onap.cps.ncmp.api.inventory
+import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel
+
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
+import com.hazelcast.map.IMap
import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueriesImpl
import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
import org.onap.cps.ncmp.api.impl.inventory.DataStoreSyncState
@@ -37,8 +40,9 @@ import spock.lang.Specification
class CmHandleQueriesImplSpec extends Specification {
def cpsDataPersistenceService = Mock(CpsDataPersistenceService)
+ def trustLevelPerCmHandle = [ 'my completed cm handle': TrustLevel.COMPLETE, 'my untrusted cm handle': TrustLevel.NONE ]
- def objectUnderTest = new CmHandleQueriesImpl(cpsDataPersistenceService)
+ def objectUnderTest = new CmHandleQueriesImpl(cpsDataPersistenceService, trustLevelPerCmHandle)
@Shared
def static sampleDataNodes = [new DataNode()]
@@ -60,11 +64,21 @@ class CmHandleQueriesImplSpec extends Specification {
result.containsAll(expectedCmHandleIds)
result.size() == expectedCmHandleIds.size()
where: 'the following data is used'
- scenario | publicPropertyPairs || expectedCmHandleIds
- 'single property matches' | ['Contact' : 'newemailforstore@bookstore.com'] || ['PNFDemo', 'PNFDemo2', 'PNFDemo4']
- 'public property does not match' | ['wont_match' : 'wont_match'] || []
- '2 properties, only one match' | ['Contact' : 'newemailforstore@bookstore.com', 'Contact2': 'newemailforstore2@bookstore.com'] || ['PNFDemo4']
- '2 properties, no matches' | ['Contact' : 'newemailforstore@bookstore.com', 'Contact2': ''] || []
+ scenario | publicPropertyPairs || expectedCmHandleIds
+ 'single property matches' | [Contact: 'newemailforstore@bookstore.com'] || ['PNFDemo', 'PNFDemo2', 'PNFDemo4']
+ 'public property does not match' | [wont_match: 'wont_match'] || []
+ '2 properties, only one match' | [Contact: 'newemailforstore@bookstore.com', Contact2: 'newemailforstore2@bookstore.com'] || ['PNFDemo4']
+ '2 properties, no matches' | [Contact: 'newemailforstore@bookstore.com', Contact2: ''] || []
+ }
+
+ def 'Query cm handles on trust level'() {
+ given: 'query properties for trustlevel COMPLETE'
+ def trustLevelPropertyQueryPairs = ['trustLevel' : TrustLevel.COMPLETE.toString()]
+ when: 'the query is executed'
+ def result = objectUnderTest.queryCmHandlesByTrustLevel(trustLevelPropertyQueryPairs)
+ then: 'the result only contains the completed cm handle'
+ assert result.size() == 1
+ assert result[0] == 'my completed cm handle'
}
def 'Query CmHandles using empty public properties query pair.'() {
diff --git a/docs/cps-path.rst b/docs/cps-path.rst
index 661178954..eb203d891 100644
--- a/docs/cps-path.rst
+++ b/docs/cps-path.rst
@@ -247,7 +247,7 @@ leaf-conditions
- Using comparative operators with string values will lead to an error at runtime. This error can't be validated earlier as the datatype is unknown until the execution phase.
- The key should be supplied with correct data type for it to be queried from DB. In the last example above the attribute code is of type
Integer so the cps query will not work if the value is passed as string.
- eg: ``//categories[@code="1"]`` or ``//categories[@code='1']`` will not work because the key attribute code is treated a string.
+ e.g.: ``//categories[@code="1"]`` or ``//categories[@code='1']`` will not work because the key attribute code is treated a string.
**Notes**
- For performance reasons it does not make sense to query using key leaf as attribute. If the key value is known it is better to execute a get request with the complete xpath.
@@ -260,7 +260,7 @@ The text()-condition can be added to any CPS path query.
**Syntax**: ``<cps-path> ( '/' <leaf-name> '[text()=' <string-value> ']' )?``
- ``cps-path``: Any CPS path query.
- ``leaf-name``: The name of the leaf or leaf-list which value needs to be compared.
- - ``string-value``: The required value of the leaf or leaf-list element as a string wrapped in quotation marks (U+0022) or apostrophes (U+0027). This wil still match integer values.
+ - ``string-value``: The required value of the leaf or leaf-list element as a string wrapped in quotation marks (U+0022) or apostrophes (U+0027). This will still match integer values.
**Examples**
- ``//book/label[text()="classic"]``
diff --git a/docs/cps-stubs.rst b/docs/cps-stubs.rst
new file mode 100644
index 000000000..00577eb0d
--- /dev/null
+++ b/docs/cps-stubs.rst
@@ -0,0 +1,120 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. http://creativecommons.org/licenses/by/4.0
+.. Copyright (C) 2023 Nordix Foundation
+
+.. DO NOT CHANGE THIS LABEL FOR RELEASE NOTES - EVEN THOUGH IT GIVES A WARNING
+
+.. _cpsStubs:
+
+
+CPS Stubs
+#########
+
+.. toctree::
+ :maxdepth: 1
+
+NCMP Stubs
+==========
+
+The CPS NCMP stub module provides the capability to create dynamic and customizable stubs, offering control over the responses generated for each endpoint. This capability ensures that client interactions adhere to a specified NCMP interface, enabling comprehensive testing and validation of your applications.
+
+The NCMP stub RestController is an extended implementation of the actual NCMP interface. It can be deployed as part of the application JAR or within a SpringBootTest JUnit environment, allowing you to define dynamic responses for each endpoint and allowing testing against real stub interfaces.
+
+Prerequisites
+=============
+
+Ensure you meet the following prerequisites:
+
+1. **Required Java Installation:**
+
+ Ensure that you have the required Java installed on your system.
+
+2. **Access to Gerrit and Maven Installation (for building CPS project locally):**
+
+ - Ensure you have access to the ONAP Gerrit repository.
+
+ - If you plan to build the CPS project locally, make sure you have Maven installed.
+
+Method 1: Running Stubs as an Application
+=========================================
+
+Follow these steps to run the CPS-NCMP stub application:
+
+1. **Download Application Jar:**
+
+ You can obtain the CPS-NCMP stub application jar in one of the following ways:
+
+ - **Option 1: Download from Nexus Repository:**
+
+ Download the application jar from the Nexus repository at `https://nexus.onap.org/content/repositories/releases/org/onap/cps/cps-ncmp-rest-stub-app/`_.
+
+ - **Option 2: Build Locally:**
+
+ To build the CPS project locally, navigate to the project's root directory. Once there, you can build the project using :code:`mvn clean install`, and the application CPS-NCMP stub application jar can be found in the following location:
+
+ ::
+
+ cps/cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/target/
+
+2. **Run the Application:**
+
+ After obtaining the application jar, use the following command to run it:
+
+ .. code-block:: bash
+
+ java -jar ./cps-ncmp-rest-stub-app-<VERSION>.jar
+
+ Replace ``<VERSION>`` with the actual version number of the application jar.
+
+This will start the CPS-NCMP stub application, and you can interact with it as needed.
+
+.. _`https://nexus.onap.org/content/repositories/releases/org/onap/cps/cps-ncmp-rest-stub-app/`: https://nexus.onap.org/content/repositories/releases/org/onap/cps/cps-ncmp-rest-stub-app/
+
+Method 2: Using Stubs in Unit Tests
+===================================
+1. **Add Dependency to pom.xml:**
+
+ To include the required module in your project, add the following dependency to your `pom.xml` file:
+
+ .. code-block:: xml
+
+ <dependency>
+ <groupId>org.onap.cps</groupId>
+ <artifactId>cps-ncmp-rest-stub-service</artifactId>
+ <version>VERSION</version>
+ </dependency>
+
+ Replace ``VERSION`` with the actual version number.
+
+2. **Using Custom Response Objects:**
+
+ If you prefer to use custom response objects instead of the built-in ones, follow these steps:
+
+ Modify the `application.yaml` file located in your project's test resources directory (`src/test/resources`).
+
+ Add the following property to the `application.yaml` file, specifying the directory that contains your custom response objects:
+
+ .. code-block:: yaml
+
+ stub:
+ path: "/my_custom_stubs/"
+
+ **Note:** Custom response objects can be placed in the `src/test/resources` directory of your project under the directory defined in above property. Refer to the `examples <https://github.com/onap/cps/tree/master/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/resources/stubs>`_ included in the CPS source repository for reference.
+
+3. **Simple Test Code:**
+
+ You may refer to the sample test code 'SampleCpsNcmpClientSpec.groovy' in the local CPS project under the following directory:
+
+ ::
+
+ /cps/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub/
+
+ Alternatively, you can refer to the `example <https://github.com/onap/cps/tree/master/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/test/groovy/org/onap/cps/ncmp/rest/stub>`_ included in the CPS source repository.
+
+**Custom Responses for Supported Endpoints**
+
+ Only the following endpoints are supported for the first draft. To use your custom response objects for these endpoints, create the corresponding JSON files:
+
+ - For RequestMethod.GET /v1/ch/{cm-handle}/data/ds/{datastore-name}, create "passthrough-operational-example.json".
+
+ - For RequestMethod.POST /v1/ch/searches, create "cmHandlesSearch.json".
diff --git a/docs/deployment.rst b/docs/deployment.rst
index 0642e6a8e..0fee55969 100644
--- a/docs/deployment.rst
+++ b/docs/deployment.rst
@@ -197,8 +197,8 @@ Any spring supported property can be configured by providing in ``config.additio
| logging.level | Logging level set in cps-core | info |
| | | |
+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
-| config.useStrimziKafka | If targeting a custom kafka cluster, ie useStrimziKafka: false, the config.eventPublisher.spring.kafka | true |
-| | values below must be set. | |
+| config.useStrimziKafka | If targeting a custom kafka cluster, i.e. useStrimziKafka: false, the | true |
+| | config.eventPublisher.spring.kafka values below must be set. | |
+---------------------------------------+---------------------------------------------------------------------------------------------------------+-------------------------------+
| config.eventPublisher. | Kafka hostname and port | ``<kafka-bootstrap>:9092`` |
| spring.kafka.bootstrap-servers | | |
diff --git a/docs/design.rst b/docs/design.rst
index 5ad86a3ae..80eb5f152 100755
--- a/docs/design.rst
+++ b/docs/design.rst
@@ -1,6 +1,6 @@
.. This work is licensed under a Creative Commons Attribution 4.0 International License.
.. http://creativecommons.org/licenses/by/4.0
-.. Copyright (C) 2021-2022 Nordix Foundation
+.. Copyright (C) 2021-2023 Nordix Foundation
.. DO NOT CHANGE THIS LABEL FOR RELEASE NOTES - EVEN THOUGH IT GIVES A WARNING
.. _design:
@@ -93,3 +93,24 @@ NCMP uses common responses codes in REST responses and events. Also the DMI plug
:maxdepth: 1
cps-ncmp-message-status-codes.rst
+
+Contract Testing (stubs)
+========================
+
+The CPS team is committed to supporting consumers of our APIs through contract testing.
+Obviously we test our own contracts on a continuous basis as part of the build and delivery process.
+CPS uses a contract-first approach. That means we write our OpenAPi contracts first and then generate the interface code from that.
+This means our interface implementation simply cannot deviate from the OpenApi contracts we deliver.
+
+Another advantage is that we can also generate 'stubs'. Stubs are a basic implementation of the same interface for testing purposes.
+These stubs can be used by clients for unit testing but also for more higher level integration-like testing where the real service is replaced by a stub.
+This can be useful for faster feedback loops where deployment of a full stack is difficult and not strictly needed for the purpose of the tests.
+
+Stubs for contract testing typically always return the same response which is sufficient for the strict definition of a contract test.
+However it is often useful to allow more variation in the responses so different clients or the same client can test different scenarios without having to mock the service.
+CPS has implemented what we call 'extended stubs' that allow clients to provide alternate responses.implementation
+
+The available stubs and how to use them are described in :doc:'cps-stubs'.
+
+
+
diff --git a/docs/index.rst b/docs/index.rst
index c1427ad38..573bd5412 100755
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -25,6 +25,7 @@ CPS
cps-events.rst
deployment.rst
release-notes.rst
+ cps-stubs.rst
DMI-Plugin
==========
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
index d891162c3..e6b81fcba 100755
--- a/docs/release-notes.rst
+++ b/docs/release-notes.rst
@@ -515,7 +515,7 @@ Bug Fixes
- `CPS-1289 <https://jira.onap.org/browse/CPS-1289>`_ Getting wrong error code for create node api
- `CPS-1326 <https://jira.onap.org/browse/CPS-1326>`_ Creation of DataNodeBuilder with module name prefix is very slow
- `CPS-1344 <https://jira.onap.org/browse/CPS-1344>`_ Top level container (prefix) is not always the first module
- - `CPS-1350 <https://jira.onap.org/browse/CPS-1350>`_ Add Basic Auth to CPS/NCMP OpenAPI Definitions.
+ - `CPS-1350 <https://jira.onap.org/browse/CPS-1350>`_ Add Basic Authentication to CPS/NCMP OpenAPI Definitions.
- `CPS-1352 <https://jira.onap.org/browse/CPS-1352>`_ Handle YangChoiceNode in right format.
- `CPS-1409 <https://jira.onap.org/browse/CPS-1409>`_ Fix Delete uses case with '/' in path.
- `CPS-1433 <https://jira.onap.org/browse/CPS-1433>`_ Fix to allow posting data with '/' key fields.
@@ -701,7 +701,7 @@ Bug Fixes
- `CPS-957 <https://jira.onap.org/browse/CPS-957>`_ NCMP: fix getResourceDataForPassthroughOperational endpoint
- `CPS-1020 <https://jira.onap.org/browse/CPS-1020>`_ DuplicatedYangResourceException error at parallel cmHandle registration
- `CPS-1056 <https://jira.onap.org/browse/CPS-1056>`_ Wrong error response format in case of Dmi plugin error
- - `CPS-1067 <https://jira.onap.org/browse/CPS-1067>`_ NCMP returns 500 error on searches endpoint when No DMi Handles registered
+ - `CPS-1067 <https://jira.onap.org/browse/CPS-1067>`_ NCMP returns 500 error on searches endpoint when No DMI Handles registered
- `CPS-1085 <https://jira.onap.org/browse/CPS-1085>`_ Performance degradation on ncmp/v1/ch/searches endpoint
- `CPS-1088 <https://jira.onap.org/browse/CPS-1088>`_ Kafka consumer can not be turned off
- `CPS-1097 <https://jira.onap.org/browse/CPS-1097>`_ Unable to change state from LOCKED to ADVISED
@@ -813,7 +813,7 @@ Bug Fixes
- `CPS-886 <https://jira.onap.org/browse/CPS-886>`_ Fragment handling decreasing performance for large number of cmHandles
- `CPS-887 <https://jira.onap.org/browse/CPS-887>`_ Increase performance of cmHandle registration for large number of schema sets in DB
- `CPS-892 <https://jira.onap.org/browse/CPS-892>`_ Fixed the response code during CM-Handle Registration from 201 CREATED to 204 NO_CONTENT
- - `CPS-893 <https://jira.onap.org/browse/CPS-893>`_ NCMP Java API depends on NCM-Rest-API (cyclic) through json properties on Java API
+ - `CPS-893 <https://jira.onap.org/browse/CPS-893>`_ NCMP Java API depends on NCMP-Rest-API (cyclic) through json properties on Java API
Known Limitations, Issues and Workarounds
-----------------------------------------
@@ -1268,7 +1268,7 @@ Security Notes
*Known Security Issues*
- * Weak Crytography using md5
+ * Weak Cryptography using md5
* Risk seen in Zip file expansion
*Known Vulnerabilities in Used Modules*
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
new file mode 100644
index 000000000..3bfa9a0a3
--- /dev/null
+++ b/docs/spelling_wordlist.txt
@@ -0,0 +1,67 @@
+api
+async
+authorization
+boolean
+behavior
+camelCasing
+cmHandle
+cmHandles
+config
+color
+cps
+cpsPath
+cpsPaths
+csit
+customizations
+dataschema
+dataspace
+dataspaces
+datasource
+datastore
+datastores
+deliverables
+dmi
+dmiPlugin
+dmiPlugins
+rnv
+hazelcast
+hostname
+jira
+json
+kafka
+kibana
+kubernetes
+kohn
+lifecycle
+liquibase
+logback
+modeled
+modeling
+normalized
+ncmp
+onap
+openapi
+optimized
+passthrough
+performant
+postgres
+queryable
+repo
+runtime
+schemas
+sql
+ssl
+standardized
+synchronize
+synchronization
+undeploying
+utilizes
+xml
+xNF
+xNFs
+xpath
+xpaths
+xPath
+XPath
+XPaths
+yaml \ No newline at end of file
diff --git a/docs/tox.ini b/docs/tox.ini
index 8684276f9..7020752c8 100644
--- a/docs/tox.ini
+++ b/docs/tox.ini
@@ -21,23 +21,23 @@ minversion = 1.6
envlist = docs,docs-linkcheck,docs-spellcheck
skipsdist = true
[testenv:docs]
-basepython = python3.8
+basepython = python3.10
deps =
-r{toxinidir}/requirements-docs.txt
-chttps://raw.githubusercontent.com/openstack/requirements/stable/yoga/upper-constraints.txt
-chttps://git.onap.org/doc/plain/etc/upper-constraints.onap.txt?h=master
commands =
- sphinx-build -W -q -b html -n -d {envtmpdir}/doctrees {toxinidir} {toxinidir}/_build/html
+ sphinx-build -q -b html -n -d {envtmpdir}/doctrees {toxinidir} {toxinidir}/_build/html
[testenv:docs-linkcheck]
-basepython = python3.8
+basepython = python3.10
deps =
-r{toxinidir}/requirements-docs.txt
-chttps://raw.githubusercontent.com/openstack/requirements/stable/yoga/upper-constraints.txt
-chttps://git.onap.org/doc/plain/etc/upper-constraints.onap.txt?h=master
commands =
- sphinx-build -W -q -b linkcheck -d {envtmpdir}/doctrees {toxinidir} {toxinidir}/_build/linkcheck
+ sphinx-build -q -b linkcheck -d {envtmpdir}/doctrees {toxinidir} {toxinidir}/_build/linkcheck
[testenv:docs-spellcheck]
-basepython = python3.8
+basepython = python3.10
deps =
-r{toxinidir}/requirements-docs.txt
-chttps://raw.githubusercontent.com/openstack/requirements/stable/yoga/upper-constraints.txt