summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cps-application/pom.xml6
-rw-r--r--cps-application/src/main/resources/application.yml6
-rw-r--r--cps-dependencies/pom.xml2
-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.yml20
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java64
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandler.java7
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy36
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandlerSpec.groovy29
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PolicyExecutorException.java42
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java76
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java16
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java133
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImpl.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java1
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfiguration.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryService.java12
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImpl.java31
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java32
-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.java34
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java15
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java3
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdog.java7
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java8
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java77
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfiguration.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilder.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java)39
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/UrlTemplateParameters.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java)2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java (renamed from cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/WebClientConfiguration.java)2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy7
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy74
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutorConfigurationSpec.groovy45
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutorSpec.groovy154
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImplSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy1
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleQueryServiceImplSpec.groovy60
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy8
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy108
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/ParameterizedCmHandleQueryServiceSpec.groovy11
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy62
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilderSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilderSpec.groovy)15
-rw-r--r--cps-ncmp-service/src/test/java/org/onap/cps/ncmp/utils/WebClientBuilderTestConfig.java40
-rw-r--r--cps-ncmp-service/src/test/resources/application.yml4
-rw-r--r--cps-parent/pom.xml24
-rw-r--r--cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g48
-rw-r--r--cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java48
-rw-r--r--cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java18
-rw-r--r--cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy39
-rw-r--r--cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java170
-rw-r--r--cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md23
-rw-r--r--cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang63
-rw-r--r--cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-02-10.yang81
-rw-r--r--cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-05-10.yang123
-rw-r--r--cps-ri/src/main/resources/yangResourceCsvGenerator.py66
-rw-r--r--cps-service/pom.xml12
-rwxr-xr-xcsit/install-deps.sh36
-rwxr-xr-xcsit/plans/cps/setup.sh9
-rwxr-xr-xcsit/run-project-csit.sh3
-rw-r--r--csit/tests/cps-trust-level/cps-trust-level.robot4
-rw-r--r--docker-compose/config/grafana/jvm-micrometer-dashboard.json3613
-rw-r--r--docker-compose/config/grafana/provisioning/dashboards/dashboard.yml9
-rw-r--r--docker-compose/config/grafana/provisioning/datasources/datasource.yml8
-rw-r--r--docker-compose/config/nginx/nginx.conf (renamed from docker-compose/nginx.conf)0
-rw-r--r--docker-compose/config/nginx/proxy_params (renamed from docker-compose/proxy_params)0
-rw-r--r--docker-compose/config/postgres-init.sql (renamed from docker-compose/postgres-init.sql)0
-rw-r--r--docker-compose/config/prometheus.yml (renamed from docker-compose/prometheus.yml)6
-rw-r--r--docker-compose/docker-compose.yml15
-rw-r--r--docs/schemas/policy-executor/ncmp-create-schema-1.0.0.json2
-rw-r--r--docs/schemas/policy-executor/ncmp-delete-schema-1.0.0.json2
-rw-r--r--docs/schemas/policy-executor/ncmp-patch-schema-1.0.0.json2
-rw-r--r--docs/schemas/policy-executor/ncmp-update-schema-1.0.0.json2
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy13
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy18
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy74
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy1
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy63
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/RestApiSpec.groovy23
-rw-r--r--integration-test/src/test/resources/application.yml14
-rwxr-xr-xk6-tests/install-deps.sh47
-rw-r--r--k6-tests/ncmp/common/cmhandle-crud.js67
-rw-r--r--k6-tests/ncmp/common/passthrough-crud.js59
-rw-r--r--k6-tests/ncmp/common/search-base.js48
-rw-r--r--k6-tests/ncmp/common/utils.js62
-rw-r--r--k6-tests/ncmp/ncmp-kpi.js172
-rwxr-xr-xk6-tests/ncmp/run-all-tests.sh4
-rwxr-xr-xk6-tests/run-k6-tests.sh4
-rwxr-xr-xk6-tests/teardown.sh8
-rw-r--r--spotbugs/src/main/resources/spotbugs-exclude.xml1
103 files changed, 5200 insertions, 1236 deletions
diff --git a/cps-application/pom.xml b/cps-application/pom.xml
index 4ff3111f73..19710be80b 100644
--- a/cps-application/pom.xml
+++ b/cps-application/pom.xml
@@ -84,11 +84,6 @@
<!-- T E S T D E P E N D E N C I E S -->
<dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<scope>test</scope>
@@ -111,6 +106,7 @@
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit5</artifactId>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
diff --git a/cps-application/src/main/resources/application.yml b/cps-application/src/main/resources/application.yml
index dd4576ec02..8ca6b0fe02 100644
--- a/cps-application/src/main/resources/application.yml
+++ b/cps-application/src/main/resources/application.yml
@@ -189,10 +189,10 @@ logging:
cps: INFO
ncmp:
policy-executor:
- enabled: true
+ enabled: false
server:
- address: "http://localhost"
- port: "8785"
+ address: http://localhost
+ port: 8785
httpclient:
all-services:
maximumInMemorySizeInMegabytes: 16
diff --git a/cps-dependencies/pom.xml b/cps-dependencies/pom.xml
index 6ed4db9b96..adef9031ab 100644
--- a/cps-dependencies/pom.xml
+++ b/cps-dependencies/pom.xml
@@ -249,7 +249,7 @@
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
- <version>4.28.0</version>
+ <version>4.29.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
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 11adc84a1f..183698c4f5 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
@@ -165,7 +165,8 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
}
@Override
- public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId(final String cmHandle) {
+ public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId(
+ final String cmHandleReference) {
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 a9311d0861..112dddf61c 100644
--- a/cps-ncmp-rest/docs/openapi/components.yaml
+++ b/cps-ncmp-rest/docs/openapi/components.yaml
@@ -505,6 +505,14 @@ components:
schema:
type: string
example: my-cm-handle
+ cmHandleReferenceInPath:
+ name: cm-handle
+ in: path
+ description: The identifier (cmHandle or alternate) for a network function, network element, subnetwork or any other cm object by managed Network CM Proxy
+ required: true
+ schema:
+ type: string
+ example: my-cm-handle-reference
moduleNameInQuery:
name: module-name
in: query
diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml
index 6972463e3c..adb2419c8a 100755
--- a/cps-ncmp-rest/docs/openapi/ncmp.yml
+++ b/cps-ncmp-rest/docs/openapi/ncmp.yml
@@ -27,7 +27,7 @@ resourceDataForCmHandle:
operationId: getResourceDataForCmHandle
parameters:
- $ref: 'components.yaml#/components/parameters/datastoreName'
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
+ - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath'
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
- $ref: 'components.yaml#/components/parameters/topicParamInQuery'
@@ -60,7 +60,7 @@ resourceDataForCmHandle:
operationId: createResourceDataRunningForCmHandle
parameters:
- $ref: 'components.yaml#/components/parameters/datastoreName'
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
+ - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath'
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/contentParamInHeader'
- $ref: 'components.yaml#/components/parameters/authorizationParamInHeader'
@@ -99,7 +99,7 @@ resourceDataForCmHandle:
operationId: updateResourceDataRunningForCmHandle
parameters:
- $ref: 'components.yaml#/components/parameters/datastoreName'
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
+ - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath'
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/contentParamInHeader'
- $ref: 'components.yaml#/components/parameters/authorizationParamInHeader'
@@ -138,7 +138,7 @@ resourceDataForCmHandle:
operationId: patchResourceDataRunningForCmHandle
parameters:
- $ref: 'components.yaml#/components/parameters/datastoreName'
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
+ - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath'
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/contentParamInHeader'
- $ref: 'components.yaml#/components/parameters/authorizationParamInHeader'
@@ -171,7 +171,7 @@ resourceDataForCmHandle:
operationId: deleteResourceDataRunningForCmHandle
parameters:
- $ref: 'components.yaml#/components/parameters/datastoreName'
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
+ - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath'
- $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
- $ref: 'components.yaml#/components/parameters/contentParamInHeader'
- $ref: 'components.yaml#/components/parameters/authorizationParamInHeader'
@@ -264,7 +264,7 @@ fetchModuleReferencesByCmHandle:
summary: Fetch all module references (name and revision) for a given cm handle
operationId: getModuleReferencesByCmHandle
parameters:
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
+ - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath'
responses:
200:
description: OK
@@ -289,7 +289,7 @@ getModuleDefinitions:
description: Get module definitions (module name, revision, yang resource) with options to filter on module name and revision
operationId: getModuleDefinitions
parameters:
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
+ - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath'
- $ref: 'components.yaml#/components/parameters/moduleNameInQuery'
- $ref: 'components.yaml#/components/parameters/revisionInQuery'
responses:
@@ -354,7 +354,7 @@ retrieveCmHandleDetailsById:
summary: Retrieve CM handle details
operationId: retrieveCmHandleDetailsById
parameters:
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
+ - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath'
responses:
200:
description: OK
@@ -377,7 +377,7 @@ getCmHandlePropertiesById:
summary: Get CM handle properties
operationId: getCmHandlePublicPropertiesByCmHandleId
parameters:
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
+ - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath'
responses:
200:
description: OK
@@ -400,7 +400,7 @@ getCmHandleStateById:
summary: Get CM handle state
operationId: getCmHandleStateByCmHandleId
parameters:
- - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
+ - $ref: 'components.yaml#/components/parameters/cmHandleReferenceInPath'
responses:
200:
description: OK
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 af5f226a4f..42f709dcf5 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
@@ -148,7 +148,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
* Patch resource data.
*
* @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
- * @param cmHandle cm handle identifier
+ * @param cmHandleReference cm handle or alternate identifier
* @param resourceIdentifier resource identifier
* @param requestBody the request body
* @param contentType content type of body
@@ -158,7 +158,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
@Override
public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String datastoreName,
- final String cmHandle,
+ final String cmHandleReference,
final String resourceIdentifier,
final Object requestBody,
final String contentType,
@@ -168,7 +168,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
final Object responseObject = networkCmProxyFacade
.writeResourceDataPassThroughRunningForCmHandle(
- cmHandle, resourceIdentifier, PATCH,
+ cmHandleReference, resourceIdentifier, PATCH,
jsonObjectMapper.asJsonString(requestBody), contentType, authorization);
return ResponseEntity.ok(responseObject);
}
@@ -177,7 +177,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
* Create resource data for given cm-handle.
*
* @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
- * @param cmHandle cm handle identifier
+ * @param cmHandleReference cm handle or alternate identifier
* @param resourceIdentifier resource identifier
* @param requestBody the request body
* @param contentType content type of body
@@ -186,14 +186,14 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
*/
@Override
public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String datastoreName,
- final String cmHandle,
+ final String cmHandleReference,
final String resourceIdentifier,
final Object requestBody,
final String contentType,
final String authorization) {
validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
- networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
+ networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandleReference,
resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType, authorization);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@@ -202,7 +202,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
* Update resource data for given cm-handle.
*
* @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
- * @param cmHandle cm handle identifier
+ * @param cmHandleReference cm handle or alternate identifier
* @param resourceIdentifier resource identifier
* @param requestBody the request body
* @param contentType content type of the body
@@ -212,14 +212,14 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
@Override
public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String datastoreName,
- final String cmHandle,
+ final String cmHandleReference,
final String resourceIdentifier,
final Object requestBody,
final String contentType,
final String authorization) {
validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
- networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
+ networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandleReference,
resourceIdentifier, UPDATE, jsonObjectMapper.asJsonString(requestBody), contentType, authorization);
return new ResponseEntity<>(HttpStatus.OK);
}
@@ -228,7 +228,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
* Delete resource data for a given cm-handle.
*
* @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running")
- * @param cmHandle cm handle identifier
+ * @param cmHandleReference cm handle or alternate identifier
* @param resourceIdentifier resource identifier
* @param contentType content type of the body
* @param authorization contents of Authorization header, or null if not present
@@ -236,14 +236,14 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
*/
@Override
public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName,
- final String cmHandle,
+ final String cmHandleReference,
final String resourceIdentifier,
final String contentType,
final String authorization) {
validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
- networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
+ networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandleReference,
resourceIdentifier, DELETE, NO_BODY, contentType, authorization);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@@ -286,28 +286,28 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
/**
* Search for Cm Handle and Properties by Name.
*
- * @param cmHandleId cm-handle identifier
+ * @param cmHandleReference cm-handle or alternate identifier
* @return cm handle and its properties
*/
@Override
- public ResponseEntity<RestOutputCmHandle> retrieveCmHandleDetailsById(final String cmHandleId) {
+ public ResponseEntity<RestOutputCmHandle> retrieveCmHandleDetailsById(final String cmHandleReference) {
final NcmpServiceCmHandle ncmpServiceCmHandle
- = networkCmProxyInventoryFacade.getNcmpServiceCmHandle(cmHandleId);
+ = networkCmProxyInventoryFacade.getNcmpServiceCmHandle(cmHandleReference);
final RestOutputCmHandle restOutputCmHandle = toRestOutputCmHandle(ncmpServiceCmHandle);
return ResponseEntity.ok(restOutputCmHandle);
}
/**
- * Get Cm Handle Properties by Cm Handle Id.
+ * Get Cm Handle Properties by Cm Handle or alternate Identifier.
*
- * @param cmHandleId cm-handle identifier
+ * @param cmHandleReference cm-handle or alternate identifier
* @return cm handle properties
*/
@Override
public ResponseEntity<RestOutputCmHandlePublicProperties> getCmHandlePublicPropertiesByCmHandleId(
- final String cmHandleId) {
+ final String cmHandleReference) {
final CmHandlePublicProperties cmHandlePublicProperties = new CmHandlePublicProperties();
- cmHandlePublicProperties.add(networkCmProxyInventoryFacade.getCmHandlePublicProperties(cmHandleId));
+ cmHandlePublicProperties.add(networkCmProxyInventoryFacade.getCmHandlePublicProperties(cmHandleReference));
final RestOutputCmHandlePublicProperties restOutputCmHandlePublicProperties =
new RestOutputCmHandlePublicProperties();
restOutputCmHandlePublicProperties.setPublicCmHandleProperties(cmHandlePublicProperties);
@@ -317,13 +317,13 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
/**
* Get Cm Handle State by Cm Handle Id.
*
- * @param cmHandleId cm-handle identifier
+ * @param cmHandleReference cm-handle or alternate identifier
* @return cm handle state
*/
@Override
public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId(
- final String cmHandleId) {
- final CompositeState cmHandleState = networkCmProxyInventoryFacade.getCmHandleCompositeState(cmHandleId);
+ final String cmHandleReference) {
+ final CompositeState cmHandleState = networkCmProxyInventoryFacade.getCmHandleCompositeState(cmHandleReference);
final RestOutputCmHandleCompositeState restOutputCmHandleCompositeState =
new RestOutputCmHandleCompositeState();
restOutputCmHandleCompositeState.setState(
@@ -334,21 +334,23 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
/**
* Return module definitions.
*
- * @param cmHandleId cm-handle identifier
- * @param moduleName module name
- * @param revision the revision of the module
+ * @param cmHandleReference cm handle or alternate id identifier
+ * @param moduleName module name
+ * @param revision the revision of the module
* @return list of module definitions (module name, revision, yang resource content)
*/
@Override
- public ResponseEntity<List<RestModuleDefinition>> getModuleDefinitions(final String cmHandleId,
+ public ResponseEntity<List<RestModuleDefinition>> getModuleDefinitions(final String cmHandleReference,
final String moduleName,
final String revision) {
final Collection<ModuleDefinition> moduleDefinitions;
if (StringUtils.hasText(moduleName)) {
moduleDefinitions =
- networkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleAndModule(cmHandleId, moduleName, revision);
+ networkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleAndModule(cmHandleReference,
+ moduleName, revision);
} else {
- moduleDefinitions = networkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleId(cmHandleId);
+ moduleDefinitions =
+ networkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleReference(cmHandleReference);
if (StringUtils.hasText(revision)) {
log.warn("Ignoring revision filter as no module name is provided");
}
@@ -363,12 +365,12 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
/**
* Return module references for a cm handle.
*
- * @param cmHandle the cm handle
+ * @param cmHandleReference cm handle or alternate id identifier
* @return module references for cm handle. Namespace will be always blank because restConf does not include this.
*/
- public ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandle) {
+ public ResponseEntity<List<RestModuleReference>> getModuleReferencesByCmHandle(final String cmHandleReference) {
final List<RestModuleReference> restModuleReferences =
- networkCmProxyInventoryFacade.getYangResourcesModuleReferences(cmHandle).stream()
+ networkCmProxyInventoryFacade.getYangResourcesModuleReferences(cmHandleReference).stream()
.map(ncmpRestInputMapper::toRestModuleReference)
.collect(Collectors.toList());
return new ResponseEntity<>(restModuleReferences, HttpStatus.OK);
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandler.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandler.java
index d61d30dc2b..6910003c54 100644
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandler.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyRestExceptionHandler.java
@@ -31,6 +31,7 @@ import org.onap.cps.ncmp.api.exceptions.DmiRequestException;
import org.onap.cps.ncmp.api.exceptions.InvalidTopicException;
import org.onap.cps.ncmp.api.exceptions.NcmpException;
import org.onap.cps.ncmp.api.exceptions.PayloadTooLargeException;
+import org.onap.cps.ncmp.api.exceptions.PolicyExecutorException;
import org.onap.cps.ncmp.api.exceptions.ServerNcmpException;
import org.onap.cps.ncmp.rest.model.DmiErrorMessage;
import org.onap.cps.ncmp.rest.model.DmiErrorMessageDmiResponse;
@@ -84,8 +85,8 @@ public class NetworkCmProxyRestExceptionHandler {
return buildErrorResponse(HttpStatus.BAD_REQUEST, exception);
}
- @ExceptionHandler({AlreadyDefinedException.class})
- public static ResponseEntity<Object> handleAlreadyDefinedExceptions(final Exception exception) {
+ @ExceptionHandler({AlreadyDefinedException.class, PolicyExecutorException.class})
+ public static ResponseEntity<Object> handleConflictExceptions(final Exception exception) {
return buildErrorResponse(HttpStatus.CONFLICT, exception);
}
@@ -113,8 +114,6 @@ public class NetworkCmProxyRestExceptionHandler {
} else {
errorMessage.setDetails(CHECK_LOGS_FOR_DETAILS);
}
- errorMessage.setDetails(
- exception instanceof CpsException ? ((CpsException) exception).getDetails() : CHECK_LOGS_FOR_DETAILS);
return new ResponseEntity<>(errorMessage, status);
}
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 9f5331dbc3..43403fa890 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
@@ -32,7 +32,6 @@ import groovy.json.JsonSlurper
import org.mapstruct.factory.Mappers
import org.onap.cps.TestUtils
import org.onap.cps.events.EventsPublisher
-import org.onap.cps.ncmp.api.data.models.CmResourceAddress
import org.onap.cps.ncmp.api.inventory.NetworkCmProxyInventoryFacade
import org.onap.cps.ncmp.api.inventory.models.CompositeState
import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
@@ -95,7 +94,7 @@ class NetworkCmProxyControllerSpec extends Specification {
NetworkCmProxyInventoryFacade mockNetworkCmProxyInventoryFacade = Mock()
@SpringBean
- AlternateIdMatcher mockalternateIdMatcher = Mock()
+ AlternateIdMatcher mockAlternateIdMatcher = Mock()
@SpringBean
ObjectMapper objectMapper = new ObjectMapper()
@@ -285,17 +284,18 @@ class NetworkCmProxyControllerSpec extends Specification {
assert response.contentAsString == '[{"cmHandle":"ch-1","publicCmHandleProperties":[{"color":"yellow"}],"state":null,"trustLevel":"NONE","moduleSetTag":null,"alternateId":null,"dataProducerIdentifier":null},{"cmHandle":"ch-2","publicCmHandleProperties":[{"color":"green"}],"state":null,"trustLevel":null,"moduleSetTag":"someModuleSetTag","alternateId":"someAlternateId","dataProducerIdentifier":"someDataProducerIdentifier"}]'
}
- def 'Get complete Cm Handle details by Cm Handle id.'() {
- given: 'an endpoint and a cm handle'
- def cmHandleDetailsEndpoint = "$ncmpBasePathV1/ch/some-cm-handle"
+ def 'Get complete Cm Handle details by Cm Handle Reference.'() {
+ given: 'an endpoint and a cm handle reference'
+ def cmHandleDetailsEndpoint = "$ncmpBasePathV1/ch/some-cm-handle-reference"
and: 'an existing ncmp service cm handle'
def cmHandleId = 'some-cm-handle'
+ def alternateId = 'some-alternate-id'
def dmiProperties = [prop: 'some DMI property']
def publicProperties = ["public prop": 'some public property']
def compositeState = compositeStateTestObject()
- def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState, currentTrustLevel: TrustLevel.COMPLETE)
- and: 'the service method is invoked with the cm handle id'
- 1 * mockNetworkCmProxyInventoryFacade.getNcmpServiceCmHandle('some-cm-handle') >> ncmpServiceCmHandle
+ def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, alternateId: alternateId, dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState, currentTrustLevel: TrustLevel.COMPLETE)
+ and: 'the service method is invoked with the cm handle reference'
+ 1 * mockNetworkCmProxyInventoryFacade.getNcmpServiceCmHandle('some-cm-handle-reference') >> ncmpServiceCmHandle
when: 'the cm handle details api is invoked'
def response = mvc.perform(
get(cmHandleDetailsEndpoint)).andReturn().response
@@ -309,13 +309,13 @@ class NetworkCmProxyControllerSpec extends Specification {
assert !response.contentAsString.contains("some DMI property")
}
- def 'Get Cm Handle public properties by Cm Handle id.'() {
+ def 'Get Cm Handle public properties by Cm Handle Reference.'() {
given: 'a cm handle properties endpoint'
- def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle/properties"
+ def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle-reference/properties"
and: 'some cm handle public properties'
def publicProperties = ['public prop': 'some public property']
and: 'the service method is invoked with the cm handle id returning the cm handle public properties'
- 1 * mockNetworkCmProxyInventoryFacade.getCmHandlePublicProperties('some-cm-handle') >> publicProperties
+ 1 * mockNetworkCmProxyInventoryFacade.getCmHandlePublicProperties('some-cm-handle-reference') >> publicProperties
when: 'the cm handle properties api is invoked'
def response = mvc.perform(get(cmHandlePropertiesEndpoint)).andReturn().response
then: 'the correct response is returned'
@@ -324,13 +324,13 @@ class NetworkCmProxyControllerSpec extends Specification {
assertContainsPublicProperties(response)
}
- def 'Get Cm Handle composite state by Cm Handle id.'() {
+ def 'Get Cm Handle composite state by Cm Handle Reference.'() {
given: 'a cm handle state endpoint'
- def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle/state"
+ def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle-reference/state"
and: 'some cm handle composite state'
def compositeState = compositeStateTestObject()
and: 'the service method is invoked with the cm handle id returning the cm handle composite state'
- 1 * mockNetworkCmProxyInventoryFacade.getCmHandleCompositeState('some-cm-handle') >> compositeState
+ 1 * mockNetworkCmProxyInventoryFacade.getCmHandleCompositeState('some-cm-handle-reference') >> compositeState
when: 'the cm handle state api is invoked'
def response = mvc.perform(get(cmHandlePropertiesEndpoint)).andReturn().response
then: 'the correct response is returned'
@@ -416,12 +416,12 @@ class NetworkCmProxyControllerSpec extends Specification {
def 'Getting module definitions filtering on #scenario'() {
when: 'get module definition request is performed'
def response = mvc.perform(
- get("$ncmpBasePathV1/ch/some-cmhandle/modules/definitions?module-name=" + moduleName + "&revision=" + revision))
+ get("$ncmpBasePathV1/ch/some-cmhandle-reference/modules/definitions?module-name=" + moduleName + "&revision=" + revision))
.andReturn().response
- then: 'ncmp service method to get definitions by cm handle is invoked when needed'
- numberOfCallsToByCmHandleId * mockNetworkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleId('some-cmhandle') >> []
+ then: 'ncmp service method to get definitions by cm handle reference is invoked when needed'
+ numberOfCallsToByCmHandleId * mockNetworkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleReference('some-cmhandle-reference') >> []
and: 'ncmp service method to get definitions by module is invoked when needed'
- numberOfCallsToByModule * mockNetworkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleAndModule('some-cmhandle', moduleName, revision) >> []
+ numberOfCallsToByModule * mockNetworkCmProxyInventoryFacade.getModuleDefinitionsByCmHandleAndModule('some-cmhandle-reference', moduleName, revision) >> []
and: 'response returns an OK http code'
response.status == HttpStatus.OK.value()
and: 'the correct message is logged when needed'
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 e6288ffbec..9d36d106c7 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
@@ -29,11 +29,13 @@ import org.onap.cps.ncmp.api.data.exceptions.OperationNotSupportedException
import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException
import org.onap.cps.ncmp.api.exceptions.DmiRequestException
import org.onap.cps.ncmp.api.exceptions.PayloadTooLargeException
+import org.onap.cps.ncmp.api.exceptions.PolicyExecutorException
import org.onap.cps.ncmp.api.exceptions.ServerNcmpException
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
@@ -120,25 +122,26 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification {
dataNodeBaseEndpointNcmpInventory = "$basePathNcmpInventory/v1"
}
- def 'Get request with #scenario exception returns correct HTTP Status with #scenario'() {
+ def 'Get request with #scenario exception returns correct HTTP Status with #scenario exception'() {
when: 'an exception is thrown by the service'
setupTestException(exception, NCMP)
def response = performTestRequest(NCMP)
then: 'an HTTP response is returned with correct message and details'
assertTestResponse(response, expectedErrorCode, expectedErrorMessage, expectedErrorDetails)
where:
- scenario | exception || expectedErrorCode | expectedErrorMessage | expectedErrorDetails
- 'CPS' | new CpsException(sampleErrorMessage, sampleErrorDetails) || INTERNAL_SERVER_ERROR | sampleErrorMessage | sampleErrorDetails
- 'NCMP-server' | new ServerNcmpException(sampleErrorMessage, sampleErrorDetails) || INTERNAL_SERVER_ERROR | sampleErrorMessage | null
- 'DMI Request' | new DmiRequestException(sampleErrorMessage, sampleErrorDetails) || BAD_REQUEST | sampleErrorMessage | null
- 'Invalid Operation' | new InvalidOperationException('some reason') || BAD_REQUEST | 'some reason' | null
- 'Unsupported Operation' | new OperationNotSupportedException('not yet') || BAD_REQUEST | 'not yet' | null
- 'DataNode Validation' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || NOT_FOUND | 'DataNode not found' | null
- 'other' | new IllegalStateException(sampleErrorMessage) || INTERNAL_SERVER_ERROR | sampleErrorMessage | null
- 'Data Node Not Found' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || NOT_FOUND | 'DataNode not found' | 'DataNode not found'
- 'Existing entry' | new AlreadyDefinedException('name',null) || CONFLICT | 'Already defined exception' | 'name already exists'
- 'Existing entries' | AlreadyDefinedException.forDataNodes(['A', 'B'], 'myAnchorName') || CONFLICT | 'Already defined exception' | '2 data node(s) already exist'
- 'Operation too large' | new PayloadTooLargeException(sampleErrorMessage) || PAYLOAD_TOO_LARGE | sampleErrorMessage | 'Check logs'
+ scenario | exception || expectedErrorCode | expectedErrorMessage | expectedErrorDetails
+ 'CPS' | new CpsException(sampleErrorMessage, sampleErrorDetails) || INTERNAL_SERVER_ERROR | sampleErrorMessage | sampleErrorDetails
+ 'NCMP-server' | new ServerNcmpException(sampleErrorMessage, sampleErrorDetails) || INTERNAL_SERVER_ERROR | sampleErrorMessage | null
+ 'DMI Request' | new DmiRequestException(sampleErrorMessage, sampleErrorDetails) || BAD_REQUEST | sampleErrorMessage | null
+ 'Invalid Operation' | new InvalidOperationException('some reason') || BAD_REQUEST | 'some reason' | null
+ 'Unsupported Operation' | new OperationNotSupportedException('not yet') || BAD_REQUEST | 'not yet' | null
+ 'DataNode Validation' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || NOT_FOUND | 'DataNode not found' | null
+ 'other' | new IllegalStateException(sampleErrorMessage) || INTERNAL_SERVER_ERROR | sampleErrorMessage | null
+ 'Data Node Not Found' | new DataNodeNotFoundException('myDataspaceName', 'myAnchorName') || NOT_FOUND | 'DataNode not found' | 'DataNode not found'
+ 'Existing entry' | new AlreadyDefinedException('name',null) || CONFLICT | 'Already defined exception' | 'name already exists'
+ 'Existing entries' | AlreadyDefinedException.forDataNodes(['A', 'B'], 'myAnchorName') || CONFLICT | 'Already defined exception' | '2 data node(s) already exist'
+ 'Operation too large' | new PayloadTooLargeException(sampleErrorMessage) || PAYLOAD_TOO_LARGE | sampleErrorMessage | 'Check logs'
+ 'Policy Executor' | new PolicyExecutorException(sampleErrorMessage, sampleErrorDetails) || CONFLICT | sampleErrorMessage | sampleErrorDetails
}
def 'Post request with exception returns correct HTTP Status.'() {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PolicyExecutorException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PolicyExecutorException.java
new file mode 100644
index 0000000000..333c12271b
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/exceptions/PolicyExecutorException.java
@@ -0,0 +1,42 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.exceptions;
+
+import lombok.Getter;
+
+/**
+ * Exception to be used when policy execution fails or does not allow to proceed.
+ */
+@Getter
+public class PolicyExecutorException extends NcmpException {
+
+ private static final long serialVersionUID = 6659897770659834798L;
+
+ /**
+ * Constructor to form exception for policy executor responses.
+ *
+ * @param message response message
+ * @param details response details
+ */
+ public PolicyExecutorException(final String message, final String details) {
+ super(message, details);
+ }
+}
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 794bc238f4..cde4eacbf2 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
@@ -26,6 +26,7 @@ package org.onap.cps.ncmp.api.inventory;
import static org.onap.cps.ncmp.impl.inventory.CmHandleQueryParametersValidator.validateCmHandleQueryParameters;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import lombok.RequiredArgsConstructor;
@@ -36,7 +37,6 @@ import org.onap.cps.ncmp.api.inventory.models.CompositeState;
import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration;
import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistrationResponse;
import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
-import org.onap.cps.ncmp.api.inventory.models.TrustLevel;
import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService;
import org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationService;
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
@@ -44,12 +44,13 @@ import org.onap.cps.ncmp.impl.inventory.ParameterizedCmHandleQueryService;
import org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions;
import org.onap.cps.ncmp.impl.inventory.models.InventoryQueryConditions;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
-import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelCacheConfig;
+import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager;
+import org.onap.cps.ncmp.impl.models.RequiredDmiService;
+import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher;
import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.onap.cps.spi.model.ModuleDefinition;
import org.onap.cps.spi.model.ModuleReference;
import org.onap.cps.utils.JsonObjectMapper;
-import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Slf4j
@@ -62,9 +63,8 @@ public class NetworkCmProxyInventoryFacade {
private final ParameterizedCmHandleQueryService parameterizedCmHandleQueryService;
private final InventoryPersistence inventoryPersistence;
private final JsonObjectMapper jsonObjectMapper;
-
- @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE)
- private final Map<String, TrustLevel> trustLevelPerCmHandle;
+ private final TrustLevelManager trustLevelManager;
+ private final AlternateIdMatcher alternateIdMatcher;
/**
* Registration of Created, Removed, Updated or Upgraded CM Handles.
@@ -72,7 +72,6 @@ public class NetworkCmProxyInventoryFacade {
* @param dmiPluginRegistration Dmi Plugin Registration details
* @return dmiPluginRegistrationResponse
*/
-
public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule(
final DmiPluginRegistration dmiPluginRegistration) {
return cmHandleRegistrationService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration);
@@ -102,36 +101,39 @@ public class NetworkCmProxyInventoryFacade {
/**
- * Retrieve module references for the given cm handle.
+ * Retrieve module references for the given cm handle reference.
*
- * @param cmHandleId cm handle identifier
+ * @param cmHandleReference cm handle or alternate id identifier
* @return a collection of modules names and revisions
*/
- public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleId) {
+ public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleReference) {
+ final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference);
return inventoryPersistence.getYangResourcesModuleReferences(cmHandleId);
}
/**
* Retrieve module definitions for the given cm handle.
*
- * @param cmHandleId cm handle identifier
+ * @param cmHandleReference cm handle or alternate id identifier
* @return a collection of module definition (moduleName, revision and yang resource content)
*/
- public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleId(final String cmHandleId) {
+ public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleReference(final String cmHandleReference) {
+ final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference);
return inventoryPersistence.getModuleDefinitionsByCmHandleId(cmHandleId);
}
/**
* Get module definitions for the given parameters.
*
- * @param cmHandleId cm-handle identifier
- * @param moduleName module name
- * @param moduleRevision the revision of the module
+ * @param cmHandleReference cm handle or alternate id identifier
+ * @param moduleName module name
+ * @param moduleRevision the revision of the module
* @return list of module definitions (module name, revision, yang resource content)
*/
- public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleAndModule(final String cmHandleId,
+ public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleAndModule(final String cmHandleReference,
final String moduleName,
final String moduleRevision) {
+ final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference);
return inventoryPersistence.getModuleDefinitionsByCmHandleAndModule(cmHandleId, moduleName, moduleRevision);
}
@@ -146,9 +148,13 @@ public class NetworkCmProxyInventoryFacade {
final CmHandleQueryServiceParameters cmHandleQueryServiceParameters = jsonObjectMapper.convertToValueType(
cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class);
validateCmHandleQueryParameters(cmHandleQueryServiceParameters, CmHandleQueryConditions.ALL_CONDITION_NAMES);
- final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles =
+ final Collection<YangModelCmHandle> yangModelCmHandles =
parameterizedCmHandleQueryService.queryCmHandles(cmHandleQueryServiceParameters);
- ncmpServiceCmHandles.forEach(this::applyCurrentTrustLevel);
+ final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles = new ArrayList<>(yangModelCmHandles.size());
+ for (final YangModelCmHandle yangModelCmHandle : yangModelCmHandles) {
+ final NcmpServiceCmHandle ncmpServiceCmHandle = toNcmpServiceCmHandleWithTrustLevel(yangModelCmHandle);
+ ncmpServiceCmHandles.add(ncmpServiceCmHandle);
+ }
return ncmpServiceCmHandles;
}
@@ -177,25 +183,25 @@ public class NetworkCmProxyInventoryFacade {
}
/**
- * Retrieve cm handle details for a given cm handle.
+ * Retrieve cm handle details for a given cm handle reference.
*
- * @param cmHandleId cm handle identifier
+ * @param cmHandleReference cm handle or alternate identifier
* @return cm handle details
*/
- public NcmpServiceCmHandle getNcmpServiceCmHandle(final String cmHandleId) {
- final NcmpServiceCmHandle ncmpServiceCmHandle = YangDataConverter.toNcmpServiceCmHandle(
- inventoryPersistence.getYangModelCmHandle(cmHandleId));
- applyCurrentTrustLevel(ncmpServiceCmHandle);
- return ncmpServiceCmHandle;
+ public NcmpServiceCmHandle getNcmpServiceCmHandle(final String cmHandleReference) {
+ final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference);
+ final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
+ return toNcmpServiceCmHandleWithTrustLevel(yangModelCmHandle);
}
/**
- * Get cm handle public properties for a given cm handle id.
+ * Get cm handle public properties for a given cm handle or alternate id.
*
- * @param cmHandleId cm handle identifier
+ * @param cmHandleReference cm handle or alternate identifier
* @return cm handle public properties
*/
- public Map<String, String> getCmHandlePublicProperties(final String cmHandleId) {
+ public Map<String, String> getCmHandlePublicProperties(final String cmHandleReference) {
+ final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference);
final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
return YangDataConverter.toPropertiesMap(yangModelCmHandle.getPublicProperties());
}
@@ -203,16 +209,20 @@ public class NetworkCmProxyInventoryFacade {
/**
* Get cm handle composite state for a given cm handle id.
*
- * @param cmHandleId cm handle identifier
+ * @param cmHandleReference cm handle or alternate identifier
* @return cm handle state
*/
- public CompositeState getCmHandleCompositeState(final String cmHandleId) {
+ public CompositeState getCmHandleCompositeState(final String cmHandleReference) {
+ final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference);
return inventoryPersistence.getYangModelCmHandle(cmHandleId).getCompositeState();
}
- private void applyCurrentTrustLevel(final NcmpServiceCmHandle ncmpServiceCmHandle) {
- ncmpServiceCmHandle.setCurrentTrustLevel(trustLevelPerCmHandle.get(ncmpServiceCmHandle.getCmHandleId()));
+ private NcmpServiceCmHandle toNcmpServiceCmHandleWithTrustLevel(final YangModelCmHandle yangModelCmHandle) {
+ final NcmpServiceCmHandle ncmpServiceCmHandle = YangDataConverter.toNcmpServiceCmHandle(yangModelCmHandle);
+ final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA);
+ ncmpServiceCmHandle.setCurrentTrustLevel(
+ trustLevelManager.getEffectiveTrustLevel(dmiServiceName, ncmpServiceCmHandle.getCmHandleId()));
+ return ncmpServiceCmHandle;
}
-
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
index 8be57fed3d..301b8195e4 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
@@ -45,12 +45,12 @@ import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor;
import org.onap.cps.ncmp.impl.data.utils.DmiDataOperationsHelper;
import org.onap.cps.ncmp.impl.dmi.DmiProperties;
import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
-import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.ncmp.impl.models.DmiRequestBody;
+import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters;
import org.onap.cps.spi.exceptions.CpsException;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.ResponseEntity;
@@ -139,8 +139,7 @@ public class DmiDataOperations {
final String requestId,
final String authorization) {
- final Set<String> cmHandlesIds
- = getDistinctCmHandleIds(dataOperationRequest);
+ final Set<String> cmHandlesIds = getDistinctCmHandleIds(dataOperationRequest);
final Collection<YangModelCmHandle> yangModelCmHandles
= inventoryPersistence.getYangModelCmHandles(cmHandlesIds);
@@ -171,7 +170,10 @@ public class DmiDataOperations {
final String requestData,
final String dataType,
final String authorization) {
- final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
+ final CmResourceAddress cmResourceAddress =
+ new CmResourceAddress(PASSTHROUGH_RUNNING.getDatastoreName(), cmHandleId, resourceId);
+
+ final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmResourceAddress.getResolvedCmHandleId());
policyExecutor.checkPermission(yangModelCmHandle, operationType, authorization, resourceId, requestData);
@@ -213,7 +215,7 @@ public class DmiDataOperations {
final String optionsParamInQuery,
final String topicParamInQuery) {
final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(DATA);
- return DmiServiceUrlTemplateBuilder.newInstance()
+ return RestServiceUrlTemplateBuilder.newInstance()
.fixedPathSegment("ch")
.variablePathSegment("cmHandleId", yangModelCmHandle.getId())
.fixedPathSegment("data")
@@ -228,7 +230,7 @@ public class DmiDataOperations {
private UrlTemplateParameters getUrlTemplateParameters(final String dmiServiceName,
final String requestId,
final String topicParamInQuery) {
- return DmiServiceUrlTemplateBuilder.newInstance()
+ return RestServiceUrlTemplateBuilder.newInstance()
.fixedPathSegment("data")
.queryParameter("requestId", requestId)
.queryParameter("topic", topicParamInQuery)
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 b97088a5e0..5343a2e131 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
@@ -101,7 +101,7 @@ public class NetworkCmProxyFacade {
/**
* Write resource data for data store pass-through running using dmi for given cm-handle.
*
- * @param cmHandleId cm handle identifier
+ * @param cmHandleReference cm handle or alternate identifier
* @param resourceIdentifier resource identifier
* @param operationType required operation type
* @param requestData request body to create resource
@@ -109,13 +109,13 @@ public class NetworkCmProxyFacade {
* @param authorization contents of Authorization header, or null if not present
* @return {@code Object} return data
*/
- public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandleId,
+ public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandleReference,
final String resourceIdentifier,
final OperationType operationType,
final String requestData,
final String dataType,
final String authorization) {
- return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleId, resourceIdentifier,
+ return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleReference, resourceIdentifier,
operationType, requestData, dataType, authorization);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java
index 8e7620ccea..b3aa848394 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java
@@ -20,12 +20,29 @@
package org.onap.cps.ncmp.impl.data.policyexecutor;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.data.models.OperationType;
+import org.onap.cps.ncmp.api.exceptions.NcmpException;
+import org.onap.cps.ncmp.api.exceptions.PolicyExecutorException;
+import org.onap.cps.ncmp.api.exceptions.ServerNcmpException;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.WebClient;
@Slf4j
@Service
@@ -41,7 +58,10 @@ public class PolicyExecutor {
@Value("${ncmp.policy-executor.server.port:8080}")
private String serverPort;
- private static final String PAYLOAD_TYPE_PREFIX = "cm_";
+ @Qualifier("policyExecutorWebClient")
+ private final WebClient policyExecutorWebClient;
+
+ private final ObjectMapper objectMapper;
/**
* Use the Policy Executor to check permission for a cm write operation.
@@ -58,17 +78,108 @@ public class PolicyExecutor {
final String authorization,
final String resourceIdentifier,
final String changeRequestAsJson) {
+ log.trace("Policy Executor Enabled: {}", enabled);
if (enabled) {
- final String payloadType = PAYLOAD_TYPE_PREFIX + operationType.getOperationName();
- log.info("Policy Executor Enabled");
- log.info("Address : {}", serverAddress);
- log.info("Port : {}", serverPort);
- log.info("Authorization : {}", authorization);
- log.info("Payload Type : {}", payloadType);
- log.info("Target FDN : {}", yangModelCmHandle.getAlternateId());
- log.info("CM Handle Id : {}", yangModelCmHandle.getId());
- log.info("Resource Identifier : {}", resourceIdentifier);
- log.info("Change Request (json) : {}", changeRequestAsJson);
+ final ResponseEntity<JsonNode> responseEntity =
+ getPolicyExecutorResponse(yangModelCmHandle, operationType, authorization, resourceIdentifier,
+ changeRequestAsJson);
+
+ if (responseEntity == null) {
+ log.warn("No valid response from policy, ignored");
+ return;
+ }
+
+ if (responseEntity.getStatusCode().is2xxSuccessful()) {
+ if (responseEntity.getBody() == null) {
+ log.warn("No valid response body from policy, ignored");
+ return;
+ }
+ processResponse(responseEntity.getBody());
+ } else {
+ log.warn("Policy Executor invocation failed with status {}",
+ responseEntity.getStatusCode().value());
+ throw new ServerNcmpException("Policy Executor invocation failed", "HTTP status code: "
+ + responseEntity.getStatusCode().value());
+ }
+ }
+ }
+
+ private Map<String, Object> getSingleRequestAsMap(final YangModelCmHandle yangModelCmHandle,
+ final OperationType operationType,
+ final String resourceIdentifier,
+ final String changeRequestAsJson) {
+ final Map<String, Object> data = new HashMap<>(4);
+ data.put("cmHandleId", yangModelCmHandle.getId());
+ data.put("resourceIdentifier", resourceIdentifier);
+ data.put("targetIdentifier", yangModelCmHandle.getAlternateId());
+ if (!OperationType.DELETE.equals(operationType)) {
+ try {
+ final Object changeRequestAsObject = objectMapper.readValue(changeRequestAsJson, Object.class);
+ data.put("cmChangeRequest", changeRequestAsObject);
+ } catch (final JsonProcessingException e) {
+ throw new NcmpException("Cannot convert Change Request data to Object",
+ "Invalid Json: " + changeRequestAsJson);
+ }
}
+
+ final Map<String, Object> request = new HashMap<>(2);
+ request.put("schema", getAssociatedPolicyDataSchemaName(operationType));
+ request.put("data", data);
+ return request;
+ }
+
+ private static String getAssociatedPolicyDataSchemaName(final OperationType operationType) {
+ return "urn:cps:org.onap.cps.ncmp.policy-executor.ncmp-" + operationType.getOperationName() + "-schema:1.0.0";
+ }
+
+ private Object createBodyAsObject(final List<Object> requests) {
+ final Map<String, Object> bodyAsMap = new HashMap<>(2);
+ bodyAsMap.put("decisionType", "allow");
+ bodyAsMap.put("requests", requests);
+ return bodyAsMap;
}
+
+ private ResponseEntity<JsonNode> getPolicyExecutorResponse(final YangModelCmHandle yangModelCmHandle,
+ final OperationType operationType,
+ final String authorization,
+ final String resourceIdentifier,
+ final String changeRequestAsJson) {
+ final String serviceBaseUrl = serverAddress + ":" + serverPort;
+
+ final Map<String, Object> requestAsMap = getSingleRequestAsMap(yangModelCmHandle,
+ operationType,
+ resourceIdentifier,
+ changeRequestAsJson);
+
+ final Object bodyAsObject = createBodyAsObject(Collections.singletonList(requestAsMap));
+
+ final UrlTemplateParameters urlTemplateParameters = RestServiceUrlTemplateBuilder.newInstance()
+ .fixedPathSegment("execute")
+ .createUrlTemplateParameters(serviceBaseUrl, "");
+
+ return policyExecutorWebClient.post()
+ .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables())
+ .header(HttpHeaders.AUTHORIZATION, authorization)
+ .body(BodyInserters.fromValue(bodyAsObject))
+ .retrieve()
+ .toEntity(JsonNode.class)
+ .block();
+ }
+
+ private static void processResponse(final JsonNode responseBody) {
+ final String decisionId = responseBody.path("decisionId").asText("unknown id");
+ log.trace("Policy Executor Decision ID: {} ", decisionId);
+ final String decision = responseBody.path("decision").asText("unknown");
+ if ("allow".equals(decision)) {
+ log.trace("Policy Executor allows the operation");
+ } else {
+ log.warn("Policy Executor decision: {}", decision);
+ final String details = responseBody.path("message").asText();
+ log.warn("Policy Executor message: {}", details);
+ final String message = "Policy Executor did not allow request. Decision #"
+ + decisionId + " : " + decision;
+ throw new PolicyExecutorException(message, details);
+ }
+ }
+
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImpl.java
index 031cedc78b..8934c088a1 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImpl.java
@@ -24,8 +24,8 @@ import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.api.datajobs.DataJobResultService;
import org.onap.cps.ncmp.impl.dmi.DmiProperties;
import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
-import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
+import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters;
import org.springframework.stereotype.Service;
@Service
@@ -41,7 +41,7 @@ public class DataJobResultServiceImpl implements DataJobResultService {
final String dataProducerId,
final String dataProducerJobId,
final String destination) {
- final UrlTemplateParameters urlTemplateParameters = DmiServiceUrlTemplateBuilder.newInstance()
+ final UrlTemplateParameters urlTemplateParameters = RestServiceUrlTemplateBuilder.newInstance()
.fixedPathSegment("cmwriteJob")
.fixedPathSegment("dataProducer")
.variablePathSegment("dataProducerId", dataProducerId)
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java
index fb17f066ce..1cfb8a9dff 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java
@@ -24,8 +24,8 @@ import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.api.datajobs.DataJobStatusService;
import org.onap.cps.ncmp.impl.dmi.DmiProperties;
import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
-import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
+import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters;
import org.springframework.stereotype.Service;
/**
@@ -54,7 +54,7 @@ public class DataJobStatusServiceImpl implements DataJobStatusService {
private UrlTemplateParameters buildUrlParameters(final String dmiServiceName,
final String dataProducerId,
final String dataProducerJobId) {
- return DmiServiceUrlTemplateBuilder.newInstance()
+ return RestServiceUrlTemplateBuilder.newInstance()
.fixedPathSegment("cmwriteJob")
.fixedPathSegment("dataProducer")
.variablePathSegment("dataProducerId", dataProducerId)
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java
index 0d14dace5e..a118d53e7e 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java
@@ -33,9 +33,9 @@ import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteRequest;
import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteResponse;
import org.onap.cps.ncmp.impl.dmi.DmiProperties;
import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
-import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
import org.onap.cps.ncmp.impl.models.RequiredDmiService;
+import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
@@ -88,7 +88,7 @@ public class DmiSubJobRequestHandler {
}
private UrlTemplateParameters getUrlTemplateParameters(final String destination, final ProducerKey producerKey) {
- return DmiServiceUrlTemplateBuilder.newInstance()
+ return RestServiceUrlTemplateBuilder.newInstance()
.fixedPathSegment("cmwriteJob")
.queryParameter("destination", destination)
.createUrlTemplateParameters(producerKey.dmiServiceName(), dmiProperties.getDmiBasePath());
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java
index c10132060d..a177272dff 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java
@@ -34,6 +34,7 @@ import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.data.models.OperationType;
import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException;
import org.onap.cps.ncmp.impl.models.RequiredDmiService;
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpHeaders;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfiguration.java
index 265d284239..4134a56ead 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfiguration.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfiguration.java
@@ -22,7 +22,7 @@ package org.onap.cps.ncmp.impl.dmi;
import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.config.DmiHttpClientConfig;
-import org.onap.cps.ncmp.impl.utils.WebClientConfiguration;
+import org.onap.cps.ncmp.impl.utils.http.WebClientConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
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 795d7c9c4c..95c3c77b71 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
@@ -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.
@@ -21,7 +21,6 @@
package org.onap.cps.ncmp.impl.inventory;
import java.util.Collection;
-import java.util.List;
import java.util.Map;
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
import org.onap.cps.spi.FetchDescendantsOption;
@@ -59,7 +58,7 @@ public interface CmHandleQueryService {
* @param cmHandleState cm handle state
* @return a list of data nodes representing the cm handles.
*/
- List<DataNode> queryCmHandlesByState(CmHandleState cmHandleState);
+ Collection<DataNode> queryCmHandlesByState(CmHandleState cmHandleState);
/**
* Method to return data nodes with ancestor representing the cm handles.
@@ -67,8 +66,7 @@ public interface CmHandleQueryService {
* @param cpsPath cps path for which the cmHandle is requested
* @return a list of data nodes representing the cm handles.
*/
- List<DataNode> queryCmHandleAncestorsByCpsPath(String cpsPath,
- FetchDescendantsOption fetchDescendantsOption);
+ Collection<DataNode> queryCmHandleAncestorsByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption);
/**
* Method to return data nodes representing the cm handles.
@@ -76,7 +74,7 @@ public interface CmHandleQueryService {
* @param cpsPath cps path for which the cmHandle is requested
* @return a list of data nodes representing the cm handles.
*/
- List<DataNode> queryNcmpRegistryByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption);
+ Collection<DataNode> queryNcmpRegistryByCpsPath(String cpsPath, FetchDescendantsOption fetchDescendantsOption);
/**
* Method to check the state of a cm handle with given id.
@@ -93,7 +91,7 @@ public interface CmHandleQueryService {
* @param dataStoreSyncState sync state
* @return a list of data nodes representing the cm handles.
*/
- List<DataNode> queryCmHandlesByOperationalSyncState(DataStoreSyncState dataStoreSyncState);
+ Collection<DataNode> queryCmHandlesByOperationalSyncState(DataStoreSyncState dataStoreSyncState);
/**
* Get all cm handles ids by DMI plugin identifier.
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 e36477f8c8..f32008d482 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
@@ -30,16 +30,17 @@ import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
-import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
+import org.onap.cps.api.CpsDataService;
+import org.onap.cps.api.CpsQueryService;
+import org.onap.cps.cpspath.parser.CpsPathUtil;
import org.onap.cps.ncmp.api.inventory.models.TrustLevel;
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
import org.onap.cps.ncmp.impl.inventory.models.ModelledDmiServiceLeaves;
import org.onap.cps.ncmp.impl.inventory.models.PropertyType;
import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelCacheConfig;
-import org.onap.cps.spi.CpsDataPersistenceService;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.utils.CpsValidator;
@@ -52,7 +53,8 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService {
private static final String DESCENDANT_PATH = "//";
private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles";
- private final CpsDataPersistenceService cpsDataPersistenceService;
+ private final CpsDataService cpsDataService;
+ private final CpsQueryService cpsQueryService;
@Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN)
private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
@@ -81,21 +83,24 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService {
}
@Override
- public List<DataNode> queryCmHandlesByState(final CmHandleState cmHandleState) {
+ public Collection<DataNode> queryCmHandlesByState(final CmHandleState cmHandleState) {
return queryCmHandleAncestorsByCpsPath("//state[@cm-handle-state=\"" + cmHandleState + "\"]",
INCLUDE_ALL_DESCENDANTS);
}
@Override
- public List<DataNode> queryNcmpRegistryByCpsPath(final String cpsPath,
+ public Collection<DataNode> queryNcmpRegistryByCpsPath(final String cpsPath,
final FetchDescendantsOption fetchDescendantsOption) {
- return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- cpsPath, fetchDescendantsOption);
+ return cpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, cpsPath,
+ fetchDescendantsOption);
}
@Override
- public List<DataNode> queryCmHandleAncestorsByCpsPath(final String cpsPath,
+ public Collection<DataNode> queryCmHandleAncestorsByCpsPath(final String cpsPath,
final FetchDescendantsOption fetchDescendantsOption) {
+ if (CpsPathUtil.getCpsPathQuery(cpsPath).getXpathPrefix().endsWith("/cm-handles")) {
+ return queryNcmpRegistryByCpsPath(cpsPath, fetchDescendantsOption);
+ }
return queryNcmpRegistryByCpsPath(cpsPath + ANCESTOR_CM_HANDLES, fetchDescendantsOption);
}
@@ -107,7 +112,7 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService {
}
@Override
- public List<DataNode> queryCmHandlesByOperationalSyncState(final DataStoreSyncState dataStoreSyncState) {
+ public Collection<DataNode> queryCmHandlesByOperationalSyncState(final DataStoreSyncState dataStoreSyncState) {
return queryCmHandleAncestorsByCpsPath("//state/datastores" + "/operational[@sync-state=\""
+ dataStoreSyncState + "\"]", FetchDescendantsOption.OMIT_DESCENDANTS);
}
@@ -176,9 +181,9 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService {
return cmHandleIds;
}
- private List<DataNode> getCmHandlesByDmiPluginIdentifierAndDmiProperty(final String dmiPluginIdentifier,
- final String dmiProperty) {
- return cpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+ private Collection<DataNode> getCmHandlesByDmiPluginIdentifierAndDmiProperty(final String dmiPluginIdentifier,
+ final String dmiProperty) {
+ return cpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@" + dmiProperty + "='" + dmiPluginIdentifier + "']",
OMIT_DESCENDANTS);
}
@@ -186,7 +191,7 @@ public class CmHandleQueryServiceImpl implements CmHandleQueryService {
private DataNode getCmHandleState(final String cmHandleId) {
cpsValidator.validateNameCharacters(cmHandleId);
final String xpath = NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']/state";
- return cpsDataPersistenceService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+ return cpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
xpath, OMIT_DESCENDANTS).iterator().next();
}
}
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 d6bda3beee..d9f7e38993 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
@@ -37,6 +37,7 @@ import com.hazelcast.map.IMap;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -58,13 +59,11 @@ import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.ncmp.impl.inventory.sync.ModuleOperationsUtils;
import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandler;
-import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelCacheConfig;
import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager;
import org.onap.cps.spi.exceptions.AlreadyDefinedException;
import org.onap.cps.spi.exceptions.CpsException;
import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.onap.cps.spi.exceptions.DataValidationException;
-import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Slf4j
@@ -79,11 +78,7 @@ public class CmHandleRegistrationService {
private final CpsDataService cpsDataService;
private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler;
private final IMap<String, Object> moduleSyncStartedOnCmHandles;
-
- @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN)
- private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
private final TrustLevelManager trustLevelManager;
-
private final AlternateIdChecker alternateIdChecker;
/**
@@ -98,7 +93,7 @@ public class CmHandleRegistrationService {
dmiPluginRegistration.validateDmiPluginRegistration();
final DmiPluginRegistrationResponse dmiPluginRegistrationResponse = new DmiPluginRegistrationResponse();
- setTrustLevelPerDmiPlugin(dmiPluginRegistration);
+ trustLevelManager.registerDmiPlugin(dmiPluginRegistration);
processRemovedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse);
@@ -153,7 +148,7 @@ public class CmHandleRegistrationService {
final Set<String> notDeletedCmHandles = new HashSet<>();
for (final List<String> tobeRemovedCmHandleBatch : Lists.partition(tobeRemovedCmHandleIds, DELETE_BATCH_SIZE)) {
try {
- batchDeleteCmHandlesFromDbAndModuleSyncMap(tobeRemovedCmHandleBatch);
+ batchDeleteCmHandlesFromDbAndCaches(tobeRemovedCmHandleBatch);
tobeRemovedCmHandleBatch.forEach(cmHandleId ->
cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId)));
@@ -215,8 +210,7 @@ public class CmHandleRegistrationService {
final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) {
final List<String> cmHandleIds = dmiPluginRegistration.getUpgradedCmHandles().getCmHandles();
- final String upgradedModuleSetTag =
- StringUtils.trimToEmpty(dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag());
+ final String upgradedModuleSetTag = dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag();
final Map<YangModelCmHandle, CmHandleState> acceptedCmHandleStatePerCmHandle
= new HashMap<>(cmHandleIds.size());
final List<CmHandleRegistrationResponse> cmHandleUpgradeResponses = new ArrayList<>(cmHandleIds.size());
@@ -260,7 +254,7 @@ public class CmHandleRegistrationService {
ncmpServiceCmHandle.getRegistrationTrustLevel());
}
}
- trustLevelManager.handleInitialRegistrationOfTrustLevels(initialTrustLevelPerCmHandleId);
+ trustLevelManager.registerCmHandles(initialTrustLevelPerCmHandleId);
}
private static boolean moduleUpgradeCanBeSkipped(final YangModelCmHandle yangModelCmHandle,
@@ -281,7 +275,7 @@ public class CmHandleRegistrationService {
private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) {
try {
- deleteCmHandleFromDbAndModuleSyncMap(cmHandleId);
+ deleteCmHandleFromDbAndCaches(cmHandleId);
return CmHandleRegistrationResponse.createSuccessResponse(cmHandleId);
} catch (final DataNodeNotFoundException dataNodeNotFoundException) {
log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}",
@@ -304,15 +298,17 @@ public class CmHandleRegistrationService {
lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle);
}
- private void deleteCmHandleFromDbAndModuleSyncMap(final String cmHandleId) {
+ private void deleteCmHandleFromDbAndCaches(final String cmHandleId) {
inventoryPersistence.deleteSchemaSetWithCascade(cmHandleId);
inventoryPersistence.deleteDataNode(NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']");
+ trustLevelManager.removeCmHandles(Collections.singleton(cmHandleId));
removeDeletedCmHandleFromModuleSyncMap(cmHandleId);
}
- private void batchDeleteCmHandlesFromDbAndModuleSyncMap(final Collection<String> cmHandleIds) {
+ private void batchDeleteCmHandlesFromDbAndCaches(final Collection<String> cmHandleIds) {
inventoryPersistence.deleteSchemaSetsWithCascade(cmHandleIds);
inventoryPersistence.deleteDataNodes(mapCmHandleIdsToXpaths(cmHandleIds));
+ trustLevelManager.removeCmHandles(cmHandleIds);
cmHandleIds.forEach(this::removeDeletedCmHandleFromModuleSyncMap);
}
@@ -346,14 +342,6 @@ public class CmHandleRegistrationService {
return cmHandleStatePerCmHandle.keySet().stream().map(YangModelCmHandle::getId).toList();
}
- private void setTrustLevelPerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) {
- if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) {
- trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiPlugin(), TrustLevel.COMPLETE);
- } else {
- trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiDataPlugin(), TrustLevel.COMPLETE);
- }
- }
-
private Collection<String> checkAlternateIds(
final List<NcmpServiceCmHandle> cmHandlesToBeCreated,
final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses) {
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..03ec30b73b 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
@@ -22,7 +22,7 @@ package org.onap.cps.ncmp.impl.inventory;
import java.util.Collection;
import org.onap.cps.ncmp.api.inventory.models.CmHandleQueryServiceParameters;
-import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle;
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
public interface ParameterizedCmHandleQueryService {
/**
@@ -51,22 +51,14 @@ public interface ParameterizedCmHandleQueryService {
Collection<String> queryCmHandleIdsForInventory(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
/**
- * Query and return cm handle objects that match the given query parameters.
+ * Query and return yang model cm handle objects 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 handles
+ * @return collection of yang model cm handles
*/
- Collection<NcmpServiceCmHandle> queryCmHandles(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
-
- /**
- * Get all cm handle objects.
- * Note: it is similar to all the queries above but simply no conditions and hence not 'parameterized'
- *
- * @return collection of cm handles
- */
- Collection<NcmpServiceCmHandle> getAllCmHandles();
+ Collection<YangModelCmHandle> queryCmHandles(CmHandleQueryServiceParameters cmHandleQueryServiceParameters);
}
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..84229e2895 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
@@ -27,7 +27,6 @@ import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.HA
import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.HAS_ALL_PROPERTIES;
import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.WITH_CPS_PATH;
import static org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions.WITH_TRUST_LEVEL;
-import static org.onap.cps.ncmp.impl.utils.YangDataConverter.toNcmpServiceCmHandle;
import static org.onap.cps.spi.FetchDescendantsOption.DIRECT_CHILDREN_ONLY;
import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
@@ -40,10 +39,8 @@ import java.util.Map;
import java.util.function.Function;
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;
import org.onap.cps.ncmp.impl.inventory.models.InventoryQueryConditions;
import org.onap.cps.ncmp.impl.inventory.models.PropertyType;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
@@ -54,7 +51,6 @@ import org.onap.cps.spi.model.DataNode;
import org.springframework.stereotype.Service;
@Service
-@Slf4j
@RequiredArgsConstructor
public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHandleQueryService {
@@ -83,22 +79,18 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
}
@Override
- public Collection<NcmpServiceCmHandle> queryCmHandles(
- final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
-
+ public Collection<YangModelCmHandle> queryCmHandles(
+ final CmHandleQueryServiceParameters cmHandleQueryServiceParameters) {
if (cmHandleQueryServiceParameters.getCmHandleQueryParameters().isEmpty()) {
return getAllCmHandles();
}
-
final Collection<String> cmHandleIds = queryCmHandleIds(cmHandleQueryServiceParameters);
-
- return getNcmpServiceCmHandles(cmHandleIds);
+ return inventoryPersistence.getYangModelCmHandles(cmHandleIds);
}
- @Override
- public Collection<NcmpServiceCmHandle> getAllCmHandles() {
+ private Collection<YangModelCmHandle> getAllCmHandles() {
final DataNode dataNode = inventoryPersistence.getDataNode(NCMP_DMI_REGISTRY_PARENT).iterator().next();
- return dataNode.getChildDataNodes().stream().map(this::createNcmpServiceCmHandle).collect(Collectors.toSet());
+ return dataNode.getChildDataNodes().stream().map(YangDataConverter::toYangModelCmHandle).toList();
}
private Collection<String> queryCmHandlesByDmiPlugin(
@@ -226,22 +218,6 @@ public class ParameterizedCmHandleQueryServiceImpl implements ParameterizedCmHan
return collectCmHandleIdsFromDataNodes(dataNode.getChildDataNodes());
}
- private Collection<NcmpServiceCmHandle> getNcmpServiceCmHandles(final Collection<String> cmHandleIds) {
- final Collection<YangModelCmHandle> yangModelcmHandles
- = inventoryPersistence.getYangModelCmHandles(cmHandleIds);
-
- final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles = new ArrayList<>(yangModelcmHandles.size());
-
- yangModelcmHandles.forEach(yangModelcmHandle ->
- ncmpServiceCmHandles.add(YangDataConverter.toNcmpServiceCmHandle(yangModelcmHandle))
- );
- return ncmpServiceCmHandles;
- }
-
- private NcmpServiceCmHandle createNcmpServiceCmHandle(final DataNode dataNode) {
- return toNcmpServiceCmHandle(YangDataConverter.toYangModelCmHandle(dataNode));
- }
-
private Collection<String> executeQueries(final CmHandleQueryServiceParameters cmHandleQueryServiceParameters,
final Function<CmHandleQueryServiceParameters, Collection<String>>...
queryFunctions) {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java
index 433c67f100..8ba70b3a31 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java
@@ -36,10 +36,10 @@ import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.api.inventory.models.YangResource;
import org.onap.cps.ncmp.impl.dmi.DmiProperties;
import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
-import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.ncmp.impl.models.DmiRequestBody;
+import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters;
import org.onap.cps.spi.model.ModuleReference;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.ResponseEntity;
@@ -107,7 +107,7 @@ public class DmiModelOperations {
final String jsonRequestBody,
final String cmHandle,
final String resourceName) {
- final UrlTemplateParameters urlTemplateParameters = DmiServiceUrlTemplateBuilder.newInstance()
+ final UrlTemplateParameters urlTemplateParameters = RestServiceUrlTemplateBuilder.newInstance()
.fixedPathSegment("ch")
.variablePathSegment("cmHandleId", cmHandle)
.fixedPathSegment(resourceName)
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java
index 69fb7f59f5..97f1e8e70f 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleOperationsUtils.java
@@ -26,6 +26,7 @@ import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@@ -75,8 +76,8 @@ public class ModuleOperationsUtils {
*
* @return cm handles (data nodes) in ADVISED state (empty list if none found)
*/
- public List<DataNode> getAdvisedCmHandles() {
- final List<DataNode> advisedCmHandlesAsDataNodes =
+ public Collection<DataNode> getAdvisedCmHandles() {
+ final Collection<DataNode> advisedCmHandlesAsDataNodes =
cmHandleQueryService.queryCmHandlesByState(CmHandleState.ADVISED);
log.debug("Total number of fetched advised cm handle(s) is (are) {}", advisedCmHandlesAsDataNodes.size());
return advisedCmHandlesAsDataNodes;
@@ -90,7 +91,7 @@ public class ModuleOperationsUtils {
* return empty list if not found
*/
public List<YangModelCmHandle> getUnsynchronizedReadyCmHandles() {
- final List<DataNode> unsynchronizedCmHandles = cmHandleQueryService
+ final Collection<DataNode> unsynchronizedCmHandles = cmHandleQueryService
.queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED);
final List<YangModelCmHandle> yangModelCmHandles = new ArrayList<>();
@@ -110,8 +111,8 @@ public class ModuleOperationsUtils {
*
* @return a random LOCKED yang model cm handle, return null if not found
*/
- public List<YangModelCmHandle> getCmHandlesThatFailedModelSyncOrUpgrade() {
- final List<DataNode> lockedCmHandlesAsDataNodeList
+ public Collection<YangModelCmHandle> getCmHandlesThatFailedModelSyncOrUpgrade() {
+ final Collection<DataNode> lockedCmHandlesAsDataNodeList
= cmHandleQueryService.queryCmHandleAncestorsByCpsPath(CPS_PATH_CM_HANDLES_MODEL_SYNC_FAILED_OR_UPGRADE,
FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
return convertCmHandlesDataNodesToYangModelCmHandles(lockedCmHandlesAsDataNodeList);
@@ -236,8 +237,8 @@ public class ModuleOperationsUtils {
return jsonObjectMapper.asJsonString(Map.of(firstElement.getKey(), firstElement.getValue()));
}
- private List<YangModelCmHandle> convertCmHandlesDataNodesToYangModelCmHandles(
- final List<DataNode> cmHandlesAsDataNodeList) {
+ private Collection<YangModelCmHandle> convertCmHandlesDataNodesToYangModelCmHandles(
+ final Collection<DataNode> cmHandlesAsDataNodeList) {
return cmHandlesAsDataNodeList.stream().map(YangDataConverter::toYangModelCmHandle).toList();
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java
index 39ea38aafc..8e5c9f3066 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java
@@ -23,7 +23,6 @@ package org.onap.cps.ncmp.impl.inventory.sync;
import com.hazelcast.map.IMap;
import java.util.Collection;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
@@ -100,7 +99,7 @@ public class ModuleSyncTasks {
*
* @param failedCmHandles previously failed (locked) cm handles
*/
- public void resetFailedCmHandles(final List<YangModelCmHandle> failedCmHandles) {
+ public void resetFailedCmHandles(final Collection<YangModelCmHandle> failedCmHandles) {
final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle = new HashMap<>(failedCmHandles.size());
for (final YangModelCmHandle failedCmHandle : failedCmHandles) {
final CompositeState compositeState = failedCmHandle.getCompositeState();
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 b4dde18da0..cc724e1f07 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
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 Nordix Foundation
+ * Copyright (C) 2022-2024 Nordix Foundation
* Modifications Copyright (C) 2022 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,7 +24,6 @@ package org.onap.cps.ncmp.impl.inventory.sync;
import com.hazelcast.map.IMap;
import java.util.Collection;
import java.util.HashSet;
-import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -86,7 +85,7 @@ public class ModuleSyncWatchdog {
@Scheduled(fixedDelayString = "${ncmp.timers.locked-modules-sync.sleep-time-ms:300000}")
public void resetPreviouslyFailedCmHandles() {
log.info("Processing module sync retry-watchdog waking up.");
- final List<YangModelCmHandle> failedCmHandles
+ final Collection<YangModelCmHandle> failedCmHandles
= moduleOperationsUtils.getCmHandlesThatFailedModelSyncOrUpgrade();
log.info("Retrying {} cmHandles", failedCmHandles.size());
moduleSyncTasks.resetFailedCmHandles(failedCmHandles);
@@ -103,7 +102,7 @@ public class ModuleSyncWatchdog {
private void populateWorkQueueIfNeeded() {
if (moduleSyncWorkQueue.isEmpty()) {
- final List<DataNode> advisedCmHandles = moduleOperationsUtils.getAdvisedCmHandles();
+ final Collection<DataNode> advisedCmHandles = moduleOperationsUtils.getAdvisedCmHandles();
log.info("Processing module sync fetched {} advised cm handles from DB", advisedCmHandles.size());
for (final DataNode advisedCmHandle : advisedCmHandles) {
if (!moduleSyncWorkQueue.offer(advisedCmHandle)) {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java
index 617fe7f01d..efcbb78ace 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java
@@ -52,7 +52,7 @@ public class DeviceTrustLevelMessageConsumer {
final DeviceTrustLevel deviceTrustLevel =
CloudEventMapper.toTargetEvent(consumerRecord.value(), DeviceTrustLevel.class);
final String trustLevelAsString = deviceTrustLevel.getData().getTrustLevel();
- trustLevelManager.handleUpdateOfDeviceTrustLevel(cmHandleId, TrustLevel.valueOf(trustLevelAsString));
+ trustLevelManager.updateCmHandleTrustLevel(cmHandleId, TrustLevel.valueOf(trustLevelAsString));
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java
index c81e9b7840..7581c4af7a 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java
@@ -26,9 +26,9 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.inventory.models.TrustLevel;
import org.onap.cps.ncmp.impl.dmi.DmiRestClient;
-import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder;
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters;
import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService;
+import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder;
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@@ -67,13 +67,13 @@ public class DmiPluginTrustLevelWatchDog {
} else {
final Collection<String> cmHandleIds =
cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiServiceName);
- trustLevelManager.handleUpdateOfDmiTrustLevel(dmiServiceName, cmHandleIds, newDmiTrustLevel);
+ trustLevelManager.updateDmi(dmiServiceName, cmHandleIds, newDmiTrustLevel);
}
});
}
private String getDmiHealthStatus(final String dmiServiceBaseUrl) {
- final UrlTemplateParameters urlTemplateParameters = DmiServiceUrlTemplateBuilder.newInstance()
+ final UrlTemplateParameters urlTemplateParameters = RestServiceUrlTemplateBuilder.newInstance()
.createUrlTemplateParametersForHealthCheck(dmiServiceBaseUrl);
return dmiRestClient.getDmiHealthStatus(urlTemplateParameters).block();
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java
index 44079c0bc9..aff0e19981 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java
@@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration;
import org.onap.cps.ncmp.api.inventory.models.TrustLevel;
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
@@ -49,11 +50,26 @@ public class TrustLevelManager {
private static final String AVC_NO_OLD_VALUE = null;
/**
+ * Add dmi plugins to the cache.
+ *
+ * @param dmiPluginRegistration a dmi plugin being registered
+ */
+ public void registerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) {
+ final String dmiServiceName;
+ if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) {
+ dmiServiceName = dmiPluginRegistration.getDmiPlugin();
+ } else {
+ dmiServiceName = dmiPluginRegistration.getDmiDataPlugin();
+ }
+ trustLevelPerDmiPlugin.put(dmiServiceName, TrustLevel.COMPLETE);
+ }
+
+ /**
* Add cmHandles to the cache and publish notification for initial trust level of cmHandles if it is NONE.
*
* @param cmHandlesToBeCreated a list of cmHandles being created
*/
- public void handleInitialRegistrationOfTrustLevels(final Map<String, TrustLevel> cmHandlesToBeCreated) {
+ public void registerCmHandles(final Map<String, TrustLevel> cmHandlesToBeCreated) {
for (final Map.Entry<String, TrustLevel> entry : cmHandlesToBeCreated.entrySet()) {
final String cmHandleId = entry.getKey();
if (trustLevelPerCmHandle.containsKey(cmHandleId)) {
@@ -82,15 +98,15 @@ public class TrustLevelManager {
* @param affectedCmHandleIds cm handle ids belonging to dmi service name
* @param newDmiTrustLevel new trust level of the dmi plugin
*/
- public void handleUpdateOfDmiTrustLevel(final String dmiServiceName,
- final Collection<String> affectedCmHandleIds,
- final TrustLevel newDmiTrustLevel) {
+ public void updateDmi(final String dmiServiceName,
+ final Collection<String> affectedCmHandleIds,
+ final TrustLevel newDmiTrustLevel) {
final TrustLevel oldDmiTrustLevel = trustLevelPerDmiPlugin.get(dmiServiceName);
trustLevelPerDmiPlugin.put(dmiServiceName, newDmiTrustLevel);
for (final String affectedCmHandleId : affectedCmHandleIds) {
- final TrustLevel deviceTrustLevel = trustLevelPerCmHandle.get(affectedCmHandleId);
- final TrustLevel oldEffectiveTrustLevel = deviceTrustLevel.getEffectiveTrustLevel(oldDmiTrustLevel);
- final TrustLevel newEffectiveTrustLevel = deviceTrustLevel.getEffectiveTrustLevel(newDmiTrustLevel);
+ final TrustLevel cmHandleTrustLevel = trustLevelPerCmHandle.get(affectedCmHandleId);
+ final TrustLevel oldEffectiveTrustLevel = cmHandleTrustLevel.getEffectiveTrustLevel(oldDmiTrustLevel);
+ final TrustLevel newEffectiveTrustLevel = cmHandleTrustLevel.getEffectiveTrustLevel(newDmiTrustLevel);
sendAvcNotificationIfRequired(affectedCmHandleId, oldEffectiveTrustLevel, newEffectiveTrustLevel);
}
}
@@ -100,23 +116,52 @@ public class TrustLevelManager {
* changed.
*
* @param cmHandleId cm handle id
- * @param newDeviceTrustLevel new trust level of the device
+ * @param newCmHandleTrustLevel new trust level of the device
*/
- public void handleUpdateOfDeviceTrustLevel(final String cmHandleId,
- final TrustLevel newDeviceTrustLevel) {
- final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
- final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA);
+ public void updateCmHandleTrustLevel(final String cmHandleId,
+ final TrustLevel newCmHandleTrustLevel) {
+ final String dmiServiceName = getDmiServiceName(cmHandleId);
final TrustLevel dmiTrustLevel = trustLevelPerDmiPlugin.get(dmiServiceName);
- final TrustLevel oldDeviceTrustLevel = trustLevelPerCmHandle.get(cmHandleId);
+ final TrustLevel oldCmHandleTrustLevel = trustLevelPerCmHandle.get(cmHandleId);
- final TrustLevel oldEffectiveTrustLevel = oldDeviceTrustLevel.getEffectiveTrustLevel(dmiTrustLevel);
- final TrustLevel newEffectiveTrustLevel = newDeviceTrustLevel.getEffectiveTrustLevel(dmiTrustLevel);
+ final TrustLevel oldEffectiveTrustLevel = oldCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel);
+ final TrustLevel newEffectiveTrustLevel = newCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel);
- trustLevelPerCmHandle.put(cmHandleId, newDeviceTrustLevel);
+ trustLevelPerCmHandle.put(cmHandleId, newCmHandleTrustLevel);
sendAvcNotificationIfRequired(cmHandleId, oldEffectiveTrustLevel, newEffectiveTrustLevel);
}
+ /**
+ * Select effective trust level among device and dmi plugin.
+ *
+ * @param cmHandleId cm handle id
+ * @return TrustLevel effective trust level
+ */
+ public TrustLevel getEffectiveTrustLevel(final String dmiServiceName, final String cmHandleId) {
+ final TrustLevel dmiTrustLevel = trustLevelPerDmiPlugin.get(dmiServiceName);
+ final TrustLevel cmHandleTrustLevel = trustLevelPerCmHandle.get(cmHandleId);
+ return dmiTrustLevel.getEffectiveTrustLevel(cmHandleTrustLevel);
+ }
+
+ /**
+ * Remove cm handle trust level from the cache.
+ *
+ * @param cmHandleIds cm handle ids to be removed from the cache
+ */
+ public void removeCmHandles(final Collection<String> cmHandleIds) {
+ for (final String cmHandleId : cmHandleIds) {
+ if (trustLevelPerCmHandle.remove(cmHandleId) == null) {
+ log.debug("Removed Cm handle: {} is not in trust level cache", cmHandleId);
+ }
+ }
+ }
+
+ private String getDmiServiceName(final String cmHandleId) {
+ final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
+ return yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA);
+ }
+
private void sendAvcNotificationIfRequired(final String notificationCandidateCmHandleId,
final TrustLevel oldEffectiveTrustLevel,
final TrustLevel newEffectiveTrustLevel) {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfiguration.java
index a927764825..333030ccd2 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfiguration.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfiguration.java
@@ -22,7 +22,7 @@ package org.onap.cps.ncmp.impl.policyexecutor;
import lombok.RequiredArgsConstructor;
import org.onap.cps.ncmp.config.PolicyExecutorHttpClientConfig;
-import org.onap.cps.ncmp.impl.utils.WebClientConfiguration;
+import org.onap.cps.ncmp.impl.utils.http.WebClientConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java
index c408ff9b13..c526dfb297 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java
@@ -59,7 +59,7 @@ public class AlternateIdMatcher {
/**
* Get cm handle Id from given cmHandleReference.
*
- * @param cmHandleReference alternate ID
+ * @param cmHandleReference cm handle or alternate identifier
* @return cm handle id string
*/
public String getCmHandleId(final String cmHandleReference) {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilder.java
index e7dbea83f2..c850ca94a0 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilder.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.impl.dmi;
+package org.onap.cps.ncmp.impl.utils.http;
import java.util.Collections;
import java.util.HashMap;
@@ -30,7 +30,7 @@ import org.apache.logging.log4j.util.Strings;
import org.springframework.web.util.UriComponentsBuilder;
@NoArgsConstructor
-public class DmiServiceUrlTemplateBuilder {
+public class RestServiceUrlTemplateBuilder {
private final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance();
private static final String FIXED_PATH_SEGMENT = null;
@@ -43,8 +43,8 @@ public class DmiServiceUrlTemplateBuilder {
*
* @return a new instance of DmiServiceUrlTemplateBuilder
*/
- public static DmiServiceUrlTemplateBuilder newInstance() {
- return new DmiServiceUrlTemplateBuilder();
+ public static RestServiceUrlTemplateBuilder newInstance() {
+ return new RestServiceUrlTemplateBuilder();
}
/**
@@ -53,7 +53,7 @@ public class DmiServiceUrlTemplateBuilder {
* @param pathSegment the path segment
* @return this builder instance
*/
- public DmiServiceUrlTemplateBuilder fixedPathSegment(final String pathSegment) {
+ public RestServiceUrlTemplateBuilder fixedPathSegment(final String pathSegment) {
pathSegments.put(pathSegment, FIXED_PATH_SEGMENT);
return this;
}
@@ -66,7 +66,7 @@ public class DmiServiceUrlTemplateBuilder {
* @param value the value to be insert in teh URL for the given variable path segment
* @return this builder instance
*/
- public DmiServiceUrlTemplateBuilder variablePathSegment(final String pathSegment, final String value) {
+ public RestServiceUrlTemplateBuilder variablePathSegment(final String pathSegment, final String value) {
pathSegments.put(pathSegment, value);
return this;
}
@@ -80,8 +80,8 @@ public class DmiServiceUrlTemplateBuilder {
*
* @return this builder instance
*/
- public DmiServiceUrlTemplateBuilder queryParameter(final String queryParameterName,
- final String queryParameterValue) {
+ public RestServiceUrlTemplateBuilder queryParameter(final String queryParameterName,
+ final String queryParameterValue) {
if (Strings.isNotBlank(queryParameterValue)) {
queryParameters.put(queryParameterName, queryParameterValue);
}
@@ -91,14 +91,12 @@ public class DmiServiceUrlTemplateBuilder {
/**
* Constructs a URL template with variables based on the accumulated path segments and query parameters.
*
- * @param dmiServiceBaseUrl the base URL of the DMI service, e.g., "http://dmi-service.com".
- * @param dmiBasePath the base path of the DMI service
+ * @param serviceBaseUrl the base URL of the service, e.g., "http://dmi-service.com".
+ * @param basePath the base path of the service
* @return a UrlTemplateParameters instance containing the complete URL template and URL variables
*/
- public UrlTemplateParameters createUrlTemplateParameters(final String dmiServiceBaseUrl, final String dmiBasePath) {
- this.uriComponentsBuilder.pathSegment(dmiBasePath)
- .pathSegment(VERSION_SEGMENT);
-
+ public UrlTemplateParameters createUrlTemplateParameters(final String serviceBaseUrl, final String basePath) {
+ this.uriComponentsBuilder.pathSegment(basePath).pathSegment(VERSION_SEGMENT);
final Map<String, String> urlTemplateVariables = new HashMap<>();
pathSegments.forEach((pathSegmentName, variablePathValue) -> {
@@ -115,22 +113,21 @@ public class DmiServiceUrlTemplateBuilder {
urlTemplateVariables.put(paramName, paramValue);
});
- final String urlTemplate = dmiServiceBaseUrl + this.uriComponentsBuilder.build().toUriString();
+ final String urlTemplate = serviceBaseUrl + this.uriComponentsBuilder.build().toUriString();
return new UrlTemplateParameters(urlTemplate, urlTemplateVariables);
}
/**
- * Constructs a URL for DMI health check based on the given base URL.
+ * Constructs a URL for a spring actuator health check based on the given base URL.
*
- * @param dmiServiceBaseUrl the base URL of the DMI service, e.g., "http://dmi-service.com".
+ * @param serviceBaseUrl the base URL of the service, e.g., "http://dmi-service.com".
* @return a {@link UrlTemplateParameters} instance containing the complete URL template and empty URL variables,
* suitable for DMI health check.
*/
- public UrlTemplateParameters createUrlTemplateParametersForHealthCheck(final String dmiServiceBaseUrl) {
- this.uriComponentsBuilder.pathSegment("actuator")
- .pathSegment("health");
+ public UrlTemplateParameters createUrlTemplateParametersForHealthCheck(final String serviceBaseUrl) {
+ this.uriComponentsBuilder.pathSegment("actuator").pathSegment("health");
- final String urlTemplate = dmiServiceBaseUrl + this.uriComponentsBuilder.build().toUriString();
+ final String urlTemplate = serviceBaseUrl + this.uriComponentsBuilder.build().toUriString();
return new UrlTemplateParameters(urlTemplate, Collections.emptyMap());
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/UrlTemplateParameters.java
index f51511116a..839af71823 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/UrlTemplateParameters.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.impl.dmi;
+package org.onap.cps.ncmp.impl.utils.http;
import java.util.Map;
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/WebClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java
index 967f74e942..d8e8350345 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/WebClientConfiguration.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java
@@ -18,7 +18,7 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.impl.utils;
+package org.onap.cps.ncmp.impl.utils.http;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.netty.channel.ChannelOption;
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy
index e0ae204c8d..23f5edd890 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy
@@ -29,7 +29,7 @@ import spock.lang.Specification
@SpringBootTest
@ContextConfiguration(classes = [DmiHttpClientConfig])
-@EnableConfigurationProperties(DmiHttpClientConfig)
+@EnableConfigurationProperties
class DmiHttpClientConfigSpec extends Specification {
@Autowired
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy
index 1946a452b1..ca71c345c1 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy
@@ -34,7 +34,7 @@ class PolicyExecutorHttpClientConfigSpec extends Specification {
@Autowired
PolicyExecutorHttpClientConfig policyExecutorHttpClientConfig
- def 'Test http client configuration properties of data with custom and default values'() {
+ def 'Http client configuration properties for policy executor http client.'() {
expect: 'properties are populated correctly for all services'
with(policyExecutorHttpClientConfig.allServices) {
assert maximumInMemorySizeInMegabytes == 31
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
index 2324d48a93..fd76abb581 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
@@ -31,9 +31,9 @@ import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent
import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor
import org.onap.cps.ncmp.impl.dmi.DmiOperationsBaseSpec
import org.onap.cps.ncmp.impl.dmi.DmiProperties
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters
import org.onap.cps.ncmp.utils.TestUtils
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
@@ -49,6 +49,8 @@ import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
import static org.onap.cps.ncmp.api.data.models.DatastoreType.PASSTHROUGH_OPERATIONAL
import static org.onap.cps.ncmp.api.data.models.DatastoreType.PASSTHROUGH_RUNNING
import static org.onap.cps.ncmp.api.data.models.OperationType.CREATE
+import static org.onap.cps.ncmp.api.data.models.OperationType.DELETE
+import static org.onap.cps.ncmp.api.data.models.OperationType.PATCH
import static org.onap.cps.ncmp.api.data.models.OperationType.READ
import static org.onap.cps.ncmp.api.data.models.OperationType.UPDATE
import static org.onap.cps.ncmp.impl.models.RequiredDmiService.DATA
@@ -161,6 +163,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def 'Write data for pass-through:running datastore in DMI.'() {
given: 'a cm handle for #cmHandleId'
mockYangModelCmHandleRetrieval([yangModelCmHandleProperty])
+ alternateIdMatcher.getCmHandleId(cmHandleId) >> cmHandleId
and: 'a positive response from DMI service when it is called with the expected parameters'
def expectedUrlTemplateParameters = new UrlTemplateParameters('myServiceName/dmi/v1/ch/{cmHandleId}/data/ds/{datastore}?resourceIdentifier={resourceIdentifier}', ['resourceIdentifier': resourceIdentifier, 'datastore': 'ncmp-datastore:passthrough-running', 'cmHandleId': cmHandleId])
def expectedJson = '{"operation":"' + expectedOperationInUrl + '","dataType":"some data type","data":"requestData","cmHandleProperties":{"prop1":"val1"},"moduleSetTag":""}'
@@ -176,6 +179,8 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
operation || expectedOperationInUrl
CREATE || 'create'
UPDATE || 'update'
+ DELETE || 'delete'
+ PATCH || 'patch'
}
def 'State Ready validation'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy
deleted file mode 100644
index 4b09afa2ae..0000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.onap.cps.ncmp.impl.data
-
-import ch.qos.logback.classic.Level
-import ch.qos.logback.classic.Logger
-import ch.qos.logback.classic.spi.ILoggingEvent
-import ch.qos.logback.core.read.ListAppender
-import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor
-import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
-import org.slf4j.LoggerFactory
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.boot.test.context.SpringBootTest
-import org.springframework.test.context.ContextConfiguration
-import spock.lang.Specification
-
-import static org.onap.cps.ncmp.api.data.models.OperationType.PATCH
-
-@SpringBootTest
-@ContextConfiguration(classes = [PolicyExecutor])
-class PolicyExecutorSpec extends Specification {
-
- @Autowired
- PolicyExecutor objectUnderTest
-
- def logAppender = Spy(ListAppender<ILoggingEvent>)
-
- def setup() {
- setupLogger()
- }
-
- def cleanup() {
- ((Logger) LoggerFactory.getLogger(PolicyExecutor)).detachAndStopAllAppenders()
- }
-
- def 'Configuration properties.'() {
- expect: 'properties used from application.yml'
- assert objectUnderTest.enabled
- assert objectUnderTest.serverAddress == 'http://localhost'
- assert objectUnderTest.serverPort == '8785'
- }
-
- def 'Permission check logging.'() {
- when: 'permission is checked for an operation'
- def yangModelCmHandle = new YangModelCmHandle(id:'ch-1', alternateId:'fdn1')
- objectUnderTest.checkPermission(yangModelCmHandle, PATCH, 'my credentials','my resource','my change')
- then: 'correct details are logged '
- assert getLogEntry(0) == 'Policy Executor Enabled'
- assert getLogEntry(3).contains('my credentials')
- assert getLogEntry(4).contains('cm_patch')
- assert getLogEntry(5).contains('fdn1')
- assert getLogEntry(6).contains('ch-1')
- assert getLogEntry(7).contains('my resource')
- assert getLogEntry(8).contains('my change')
- }
-
- def 'Permission check with feature disabled.'() {
- given: 'feature is disabled'
- objectUnderTest.enabled = false
- when: 'permission is checked for an operation'
- objectUnderTest.checkPermission(new YangModelCmHandle(), PATCH, 'my credentials','my resource','my change')
- then: 'nothing is logged'
- assert logAppender.list.isEmpty()
- }
-
- def setupLogger() {
- def logger = LoggerFactory.getLogger(PolicyExecutor)
- logger.setLevel(Level.DEBUG)
- logger.addAppender(logAppender)
- logAppender.start()
- }
-
- def getLogEntry(index) {
- logAppender.list[index].formattedMessage
- }
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutorConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutorConfigurationSpec.groovy
new file mode 100644
index 0000000000..c859bb0a09
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutorConfigurationSpec.groovy
@@ -0,0 +1,45 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.impl.data.policyexecutor
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.ncmp.config.PolicyExecutorHttpClientConfig
+import org.onap.cps.ncmp.impl.policyexecutor.PolicyExecutorWebClientConfiguration
+import org.onap.cps.ncmp.utils.WebClientBuilderTestConfig
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.ContextConfiguration
+import spock.lang.Specification
+
+@SpringBootTest
+@ContextConfiguration(classes = [ObjectMapper, PolicyExecutor, PolicyExecutorWebClientConfiguration, PolicyExecutorHttpClientConfig, WebClientBuilderTestConfig ])
+class PolicyExecutorConfigurationSpec extends Specification {
+
+ @Autowired
+ PolicyExecutor objectUnderTest
+
+ def 'Policy executor configuration properties.'() {
+ expect: 'properties used from application.yml'
+ assert objectUnderTest.enabled
+ assert objectUnderTest.serverAddress == 'http://localhost'
+ assert objectUnderTest.serverPort == '8785'
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutorSpec.groovy
new file mode 100644
index 0000000000..63a915ab64
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutorSpec.groovy
@@ -0,0 +1,154 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.impl.data.policyexecutor
+
+import ch.qos.logback.classic.Level
+import ch.qos.logback.classic.Logger
+import ch.qos.logback.classic.spi.ILoggingEvent
+import ch.qos.logback.core.read.ListAppender
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.ncmp.api.exceptions.NcmpException
+import org.onap.cps.ncmp.api.exceptions.PolicyExecutorException
+import org.onap.cps.ncmp.api.exceptions.ServerNcmpException
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
+import org.slf4j.LoggerFactory
+import org.springframework.http.HttpStatus
+import org.springframework.http.ResponseEntity
+import org.springframework.web.reactive.function.client.WebClient
+import reactor.core.publisher.Mono
+import spock.lang.Specification
+
+import static org.onap.cps.ncmp.api.data.models.OperationType.CREATE
+import static org.onap.cps.ncmp.api.data.models.OperationType.DELETE
+import static org.onap.cps.ncmp.api.data.models.OperationType.PATCH
+import static org.onap.cps.ncmp.api.data.models.OperationType.UPDATE
+
+class PolicyExecutorSpec extends Specification {
+
+ def mockWebClient = Mock(WebClient)
+ def mockRequestBodyUriSpec = Mock(WebClient.RequestBodyUriSpec)
+ def mockResponseSpec = Mock(WebClient.ResponseSpec)
+ def spiedObjectMapper = Spy(ObjectMapper)
+
+ PolicyExecutor objectUnderTest = new PolicyExecutor(mockWebClient, spiedObjectMapper)
+
+ def logAppender = Spy(ListAppender<ILoggingEvent>)
+
+ def someValidJson = '{"Hello":"World"}'
+
+ def setup() {
+ setupLogger()
+ objectUnderTest.enabled = true
+ mockWebClient.post() >> mockRequestBodyUriSpec
+ mockRequestBodyUriSpec.uri(*_) >> mockRequestBodyUriSpec
+ mockRequestBodyUriSpec.header(*_) >> mockRequestBodyUriSpec
+ mockRequestBodyUriSpec.body(*_) >> mockRequestBodyUriSpec
+ mockRequestBodyUriSpec.retrieve() >> mockResponseSpec
+ }
+
+ def cleanup() {
+ ((Logger) LoggerFactory.getLogger(PolicyExecutor)).detachAndStopAllAppenders()
+ }
+
+ def 'Permission check with allow response.'() {
+ given: 'allow response'
+ mockResponse([decision:'allow'], HttpStatus.OK)
+ when: 'permission is checked for an operation'
+ objectUnderTest.checkPermission(new YangModelCmHandle(), operationType, 'my credentials','my resource',someValidJson)
+ then: 'system logs the operation is allowed'
+ assert getLogEntry(2) == 'Policy Executor allows the operation'
+ and: 'no exception occurs'
+ noExceptionThrown()
+ where: 'all write operations are tested'
+ operationType << [ CREATE, DELETE, PATCH, UPDATE ]
+ }
+
+ def 'Permission check with other response (not allowed).'() {
+ given: 'other response'
+ mockResponse([decision:'other', decisionId:123, message:'I dont like Mondays' ], HttpStatus.OK)
+ when: 'permission is checked for an operation'
+ objectUnderTest.checkPermission(new YangModelCmHandle(), PATCH, 'my credentials','my resource',someValidJson)
+ then: 'Policy Executor exception is thrown'
+ def thrownException = thrown(PolicyExecutorException)
+ assert thrownException.message == 'Policy Executor did not allow request. Decision #123 : other'
+ assert thrownException.details == 'I dont like Mondays'
+ }
+
+ def 'Permission check with non 2xx response.'() {
+ given: 'other response'
+ mockResponse([], HttpStatus.I_AM_A_TEAPOT)
+ when: 'permission is checked for an operation'
+ objectUnderTest.checkPermission(new YangModelCmHandle(), PATCH, 'my credentials','my resource',someValidJson)
+ then: 'Server Ncmp exception is thrown'
+ def thrownException = thrown(ServerNcmpException)
+ assert thrownException.message == 'Policy Executor invocation failed'
+ assert thrownException.details == 'HTTP status code: 418'
+ }
+
+ def 'Permission check with invalid response from Policy Executor.'() {
+ given: 'invalid response from Policy executor'
+ mockResponseSpec.toEntity(*_) >> invalidResponse
+ when: 'permission is checked for an operation'
+ objectUnderTest.checkPermission(new YangModelCmHandle(), CREATE, 'my credentials','my resource',someValidJson)
+ then: 'system logs the expected message'
+ assert getLogEntry(1) == expectedMessage
+ where: 'following invalid responses are received'
+ invalidResponse || expectedMessage
+ Mono.empty() || 'No valid response from policy, ignored'
+ Mono.just(new ResponseEntity<>(null, HttpStatus.OK)) || 'No valid response body from policy, ignored'
+ }
+
+ def 'Permission check with an invalid change request json.'() {
+ when: 'permission is checked for an invalid change request'
+ objectUnderTest.checkPermission(new YangModelCmHandle(), CREATE, 'my credentials', 'my resource', 'invalid json string')
+ then: 'an ncmp exception thrown'
+ def ncmpException = thrown(NcmpException)
+ ncmpException.message == 'Cannot convert Change Request data to Object'
+ ncmpException.details.contains('invalid json string')
+ }
+
+ def 'Permission check feature disabled.'() {
+ given: 'feature is disabled'
+ objectUnderTest.enabled = false
+ when: 'permission is checked for an operation'
+ objectUnderTest.checkPermission(new YangModelCmHandle(), PATCH, 'my credentials','my resource',someValidJson)
+ then: 'system logs that the feature not enabled'
+ assert getLogEntry(0) == 'Policy Executor Enabled: false'
+ }
+
+ def mockResponse(mockResponseAsMap, httpStatus) {
+ JsonNode jsonNode = spiedObjectMapper.readTree(spiedObjectMapper.writeValueAsString(mockResponseAsMap))
+ def mono = Mono.just(new ResponseEntity<>(jsonNode, httpStatus))
+ mockResponseSpec.toEntity(*_) >> mono
+ }
+
+ def setupLogger() {
+ def logger = LoggerFactory.getLogger(PolicyExecutor)
+ logger.setLevel(Level.TRACE)
+ logger.addAppender(logAppender)
+ logAppender.start()
+ }
+
+ def getLogEntry(index) {
+ logAppender.list[index].formattedMessage
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImplSpec.groovy
index 3af474040e..74bd0484df 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImplSpec.groovy
@@ -22,7 +22,7 @@ package org.onap.cps.ncmp.impl.datajobs
import org.onap.cps.ncmp.impl.dmi.DmiProperties
import org.onap.cps.ncmp.impl.dmi.DmiRestClient
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters
import reactor.core.publisher.Mono
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy
index d231dfa755..be46d885e0 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy
@@ -22,7 +22,7 @@ package org.onap.cps.ncmp.impl.datajobs
import org.onap.cps.ncmp.impl.dmi.DmiProperties
import org.onap.cps.ncmp.impl.dmi.DmiRestClient
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters
import reactor.core.publisher.Mono
import spock.lang.Specification
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
index affbf2aa4f..65fda8718c 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy
@@ -46,6 +46,7 @@ abstract class DmiOperationsBaseSpec extends Specification {
def yangModelCmHandle = new YangModelCmHandle()
def static dmiServiceName = 'myServiceName'
def static cmHandleId = 'some-cm-handle'
+ def static alternateId = 'alt-id-' + cmHandleId
def static resourceIdentifier = 'parent/child'
def mockYangModelCmHandleRetrieval(dmiProperties) {
@@ -68,6 +69,7 @@ abstract class DmiOperationsBaseSpec extends Specification {
yangModelCmHandle.dmiServiceName = dmiServiceName
yangModelCmHandle.dmiProperties = dmiProperties
yangModelCmHandle.id = cmHandleId
+ yangModelCmHandle.alternateId = alternateId
yangModelCmHandle.compositeState = new CompositeState()
yangModelCmHandle.compositeState.cmHandleState = CmHandleState.READY
yangModelCmHandle.moduleSetTag = moduleSetTag
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy
index d92e69a136..4d47ef14a0 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy
@@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.node.ObjectNode
import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters
import org.onap.cps.ncmp.utils.TestUtils
import org.onap.cps.utils.JsonObjectMapper
import org.springframework.http.HttpHeaders
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 36fd755774..cb3c4ffec1 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
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 Nordix Foundation
+ * Copyright (C) 2022-2024 Nordix Foundation
* Modifications Copyright (C) 2023 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,9 +21,10 @@
package org.onap.cps.ncmp.impl.inventory
+import org.onap.cps.api.CpsDataService
+import org.onap.cps.api.CpsQueryService
import org.onap.cps.ncmp.api.inventory.models.TrustLevel
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
-import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.model.DataNode
import org.onap.cps.spi.utils.CpsValidator
import spock.lang.Shared
@@ -37,7 +38,8 @@ import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
class CmHandleQueryServiceImplSpec extends Specification {
- def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
+ def mockCpsQueryService = Mock(CpsQueryService)
+ def mockCpsDataService = Mock(CpsDataService)
def trustLevelPerDmiPlugin = [:]
@@ -45,7 +47,7 @@ class CmHandleQueryServiceImplSpec extends Specification {
def mockCpsValidator = Mock(CpsValidator)
- def objectUnderTest = new CmHandleQueryServiceImpl(mockCpsDataPersistenceService, trustLevelPerDmiPlugin, trustLevelPerCmHandle, mockCpsValidator)
+ def objectUnderTest = new CmHandleQueryServiceImpl(mockCpsDataService, mockCpsQueryService, trustLevelPerDmiPlugin, trustLevelPerCmHandle, mockCpsValidator)
@Shared
def static sampleDataNodes = [new DataNode()]
@@ -104,7 +106,7 @@ class CmHandleQueryServiceImplSpec extends Specification {
def 'Query CmHandles by a private field\'s value.'() {
given: 'a data node exists with a certain additional-property'
- mockCpsDataPersistenceService.queryDataNodes(_, _, dataNodeWithPrivateField, _) >> [pnfDemo5]
+ mockCpsQueryService.queryDataNodes(_, _, dataNodeWithPrivateField, _) >> [pnfDemo5]
when: 'a query on CmHandle private properties is executed using a map'
def result = objectUnderTest.queryCmHandleAdditionalProperties(['Contact3': 'newemailforstore3@bookstore.com'])
then: 'one cm handle is returned'
@@ -115,7 +117,7 @@ class CmHandleQueryServiceImplSpec extends Specification {
given: 'a cm handle state to query'
def cmHandleState = CmHandleState.ADVISED
and: 'the persistence service returns a list of data nodes'
- mockCpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+ mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
'//state[@cm-handle-state="ADVISED"]/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS) >> sampleDataNodes
when: 'cm handles are fetched by state'
def result = objectUnderTest.queryCmHandlesByState(cmHandleState)
@@ -127,7 +129,7 @@ class CmHandleQueryServiceImplSpec extends Specification {
given: 'a cm handle state to compare'
def cmHandleState = state
and: 'the persistence service returns a list of data nodes'
- mockCpsDataPersistenceService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+ mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
NCMP_DMI_REGISTRY_PARENT + '/cm-handles[@id=\'some-cm-handle\']/state',
OMIT_DESCENDANTS) >> [new DataNode(leaves: ['cm-handle-state': 'READY'])]
when: 'cm handles are compared by state'
@@ -144,7 +146,7 @@ class CmHandleQueryServiceImplSpec extends Specification {
given: 'a cm handle state to query'
def cmHandleState = CmHandleState.READY
and: 'cps data service returns a list of data nodes'
- mockCpsDataPersistenceService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+ mockCpsDataService.getDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
NCMP_DMI_REGISTRY_PARENT + '/cm-handles[@id=\'some-cm-handle\']/state',
OMIT_DESCENDANTS) >> [new DataNode(leaves: ['cm-handle-state': 'READY'])]
when: 'cm handles are fetched by state and id'
@@ -157,7 +159,7 @@ class CmHandleQueryServiceImplSpec extends Specification {
given: 'a cm handle state to query'
def cmHandleState = CmHandleState.READY
and: 'cps data service returns a list of data nodes'
- mockCpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+ mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
'//state/datastores/operational[@sync-state="'+'UNSYNCHRONIZED'+'"]/ancestor::cm-handles', OMIT_DESCENDANTS) >> sampleDataNodes
when: 'cm handles are fetched by the UNSYNCHRONIZED operational sync state'
def result = objectUnderTest.queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED)
@@ -167,10 +169,10 @@ class CmHandleQueryServiceImplSpec extends Specification {
def 'Retrieve cm handle by cps path '() {
given: 'a cm handle state to query based on the cps path'
- def cmHandleDataNode = new DataNode(xpath: 'xpath', leaves: ['cm-handle-state': 'LOCKED'])
- def cpsPath = '//cps-path'
- and: 'cps data service returns a valid data node'
- mockCpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+ def cmHandleDataNode = new DataNode(xpath: "/dmi-registry/cm-handles[@id='ch-1']", leaves: ['id': 'ch-1'])
+ def cpsPath = "//state[@cm-handle-state='LOCKED']"
+ and: 'cps data service returns a valid data node for cm handle ancestor'
+ mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
cpsPath + '/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS)
>> Arrays.asList(cmHandleDataNode)
when: 'get cm handles by cps path is invoked'
@@ -179,6 +181,20 @@ class CmHandleQueryServiceImplSpec extends Specification {
assert result.contains(cmHandleDataNode)
}
+ def 'Retrieve cm handle by cps path querying cm handle directly'() {
+ given: 'a cm handle to query based on the cps path'
+ def cmHandleDataNode = new DataNode(xpath: "/dmi-registry/cm-handles[@id='ch-2']", leaves: ['id': 'ch-2'])
+ def cpsPath = "//cm-handles[@alternate-id='1']"
+ and: 'cps data service returns a valid data node'
+ mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
+ cpsPath, INCLUDE_ALL_DESCENDANTS)
+ >> Arrays.asList(cmHandleDataNode)
+ when: 'get cm handles by cps path is invoked'
+ def result = objectUnderTest.queryCmHandleAncestorsByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS)
+ then: 'the returned result is a list of data nodes returned by cps data service'
+ assert result.contains(cmHandleDataNode)
+ }
+
def 'Get all cm handles by dmi plugin identifier'() {
given: 'the DataNodes queried for a given cpsPath are returned from the persistence service.'
mockResponses()
@@ -191,15 +207,15 @@ class CmHandleQueryServiceImplSpec extends Specification {
}
void mockResponses() {
- mockCpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\"Contact\" and @value=\"newemailforstore@bookstore.com\"]/ancestor::cm-handles', _) >> [pnfDemo, pnfDemo2, pnfDemo4]
- mockCpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\"wont_match\" and @value=\"wont_match\"]/ancestor::cm-handles', _) >> []
- mockCpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\"Contact2\" and @value=\"newemailforstore2@bookstore.com\"]/ancestor::cm-handles', _) >> [pnfDemo4]
- mockCpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\"Contact2\" and @value=\"\"]/ancestor::cm-handles', _) >> []
- mockCpsDataPersistenceService.queryDataNodes(_, _, '//state[@cm-handle-state=\"READY\"]/ancestor::cm-handles', _) >> [pnfDemo, pnfDemo3]
- mockCpsDataPersistenceService.queryDataNodes(_, _, '//state[@cm-handle-state=\"LOCKED\"]/ancestor::cm-handles', _) >> [pnfDemo2, pnfDemo4]
- mockCpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo, pnfDemo2]
- mockCpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-data-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo, pnfDemo4]
- mockCpsDataPersistenceService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-model-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo2, pnfDemo4]
+ 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', _) >> []
+ mockCpsQueryService.queryDataNodes(_, _, '//public-properties[@name=\"Contact2\" and @value=\"newemailforstore2@bookstore.com\"]/ancestor::cm-handles', _) >> [pnfDemo4]
+ mockCpsQueryService.queryDataNodes(_, _, '//public-properties[@name=\"Contact2\" and @value=\"\"]/ancestor::cm-handles', _) >> []
+ mockCpsQueryService.queryDataNodes(_, _, '//state[@cm-handle-state=\"READY\"]/ancestor::cm-handles', _) >> [pnfDemo, pnfDemo3]
+ mockCpsQueryService.queryDataNodes(_, _, '//state[@cm-handle-state=\"LOCKED\"]/ancestor::cm-handles', _) >> [pnfDemo2, pnfDemo4]
+ mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo, pnfDemo2]
+ mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-data-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo, pnfDemo4]
+ mockCpsQueryService.queryDataNodes(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, '/dmi-registry/cm-handles[@dmi-model-service-name=\'my-dmi-plugin-identifier\']', OMIT_DESCENDANTS) >> [pnfDemo2, pnfDemo4]
}
def static createDataNode(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 0c702abea6..dcff2e9b89 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
@@ -59,13 +59,12 @@ class CmHandleRegistrationServiceSpec extends Specification {
def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler)
def mockCpsDataService = Mock(CpsDataService)
def mockModuleSyncStartedOnCmHandles = Mock(IMap<String, Object>)
- def trustLevelPerDmiPlugin = [:]
def mockTrustLevelManager = Mock(TrustLevelManager)
def mockAlternateIdChecker = Mock(AlternateIdChecker)
def objectUnderTest = Spy(new CmHandleRegistrationService(
mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCpsDataService, mockLcmEventsCmHandleStateHandler,
- mockModuleSyncStartedOnCmHandles, trustLevelPerDmiPlugin , mockTrustLevelManager, mockAlternateIdChecker))
+ mockModuleSyncStartedOnCmHandles, mockTrustLevelManager, mockAlternateIdChecker))
def setup() {
// always accept all cm handles
@@ -143,9 +142,6 @@ class CmHandleRegistrationServiceSpec extends Specification {
objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
then: 'create cm handles registration and sync modules is called with the correct plugin information'
1 * objectUnderTest.processCreatedCmHandles(dmiPluginRegistration, _)
- and: 'dmi is added to the dmi trustLevel map'
- assert trustLevelPerDmiPlugin.size() == 1
- assert trustLevelPerDmiPlugin.containsKey(expectedDmiPluginRegisteredName)
where:
scenario | dmiPlugin | dmiModelPlugin | dmiDataPlugin || expectedDmiPluginRegisteredName
'combined DMI plugin' | 'service1' | '' | '' || 'service1'
@@ -212,7 +208,7 @@ class CmHandleRegistrationServiceSpec extends Specification {
when: 'registration is updated'
objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
then: 'trustLevel is set for the created cm-handle'
- 1 * mockTrustLevelManager.handleInitialRegistrationOfTrustLevels(expectedMapping)
+ 1 * mockTrustLevelManager.registerCmHandles(expectedMapping)
where:
scenario | registrationTrustLevel || expectedMapping
'with trusted cm handle' | TrustLevel.COMPLETE || [ 'ch-1' : TrustLevel.COMPLETE ]
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 716efd8fdb..9e07de48bf 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
@@ -35,6 +35,8 @@ import org.onap.cps.ncmp.api.inventory.models.TrustLevel
import org.onap.cps.ncmp.impl.inventory.models.CmHandleState
import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
+import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager
+import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher
import org.onap.cps.spi.model.ConditionProperties
import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Specification
@@ -46,9 +48,9 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
def mockParameterizedCmHandleQueryService = Mock(ParameterizedCmHandleQueryService)
def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
def mockInventoryPersistence = Mock(InventoryPersistence)
- def trustLevelPerCmHandle = [:]
-
- def objectUnderTest = new NetworkCmProxyInventoryFacade(mockCmHandleRegistrationService, mockCmHandleQueryService, mockParameterizedCmHandleQueryService, mockInventoryPersistence, spiedJsonObjectMapper, trustLevelPerCmHandle)
+ def mockTrustLevelManager = Mock(TrustLevelManager)
+ def mockAlternateIdMatcher = Mock(AlternateIdMatcher)
+ def objectUnderTest = new NetworkCmProxyInventoryFacade(mockCmHandleRegistrationService, mockCmHandleQueryService, mockParameterizedCmHandleQueryService, mockInventoryPersistence, spiedJsonObjectMapper, mockTrustLevelManager, mockAlternateIdMatcher)
def 'Update DMI Registration'() {
given: 'an (updated) dmi plugin registration'
@@ -87,14 +89,20 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
assert result.containsAll('cm-handle-1','cm-handle-2')
}
- def 'Getting Yang Resources.'() {
+ def 'Getting Yang Resources for a given #scenario'() {
when: 'yang resources is called'
- objectUnderTest.getYangResourcesModuleReferences('some-cm-handle')
- then: 'CPS module services is invoked for the correct dataspace and cm handle'
+ objectUnderTest.getYangResourcesModuleReferences(cmHandleRef)
+ then: 'alternate id matcher is called'
+ mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> 'some-cm-handle'
+ and: 'CPS module services is invoked for the correct cm handle'
1 * mockInventoryPersistence.getYangResourcesModuleReferences('some-cm-handle')
+ where: 'following cm handle reference is used'
+ scenario | cmHandleRef
+ 'Cm Handle Reference as cm handle-id' | 'some-cm-handle'
+ 'Cm Handle Reference as alternate-id' | 'some-alternate-id'
}
- def 'Get a cm handle.'() {
+ def 'Get a cm handle details using #scenario'() {
given: 'the system returns a yang modelled cm handle'
def dmiServiceName = 'some service name'
def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED,
@@ -106,17 +114,18 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
def publicProperties = [new YangModelCmHandle.Property('Public Book', 'Public Romance Novel')]
def moduleSetTag = 'some-module-set-tag'
def alternateId = 'some-alternate-id'
- def yangModelCmHandle = new YangModelCmHandle(id: 'ch-1', dmiServiceName: dmiServiceName, dmiProperties: dmiProperties,
+ def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', dmiServiceName: dmiServiceName, dmiProperties: dmiProperties,
publicProperties: publicProperties, compositeState: compositeState, moduleSetTag: moduleSetTag, alternateId: alternateId)
- 1 * mockInventoryPersistence.getYangModelCmHandle('ch-1') >> yangModelCmHandle
+ mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> 'some-cm-handle'
+ 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
and: 'a trust level for the cm handle in the cache'
- trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE)
+ mockTrustLevelManager.getEffectiveTrustLevel(*_) >> TrustLevel.COMPLETE
when: 'getting cm handle details for a given cm handle id from ncmp service'
- def result = objectUnderTest.getNcmpServiceCmHandle('ch-1')
+ def result = objectUnderTest.getNcmpServiceCmHandle(cmHandleRef)
then: 'the result is a ncmpServiceCmHandle'
assert result.class == NcmpServiceCmHandle.class
and: 'the cm handle contains the cm handle id'
- assert result.cmHandleId == 'ch-1'
+ assert result.cmHandleId == 'some-cm-handle'
and: 'the cm handle contains the alternate id'
assert result.alternateId == 'some-alternate-id'
and: 'the cm handle contains the module-set-tag'
@@ -129,22 +138,34 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
assert result.compositeState == compositeState
and: 'the cm handle contains the trust level from the cache'
assert result.currentTrustLevel == TrustLevel.COMPLETE
+ where: 'following cm handle reference is used'
+ scenario | cmHandleRef
+ 'Cm Handle Reference as cm handle-id' | 'some-cm-handle'
+ 'Cm Handle Reference as alternate-id' | 'some-alternate-id'
}
- def 'Get cm handle public properties'() {
+ def 'Get cm handle public properties using #scenario'() {
given: 'a yang modelled cm handle'
def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
def publicProperties = [new YangModelCmHandle.Property('public prop', 'some public prop')]
- def yangModelCmHandle = new YangModelCmHandle(id:'some-cm-handle', dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties)
+ def cmHandleId = 'some-cm-handle'
+ def alternateId = 'some-alternate-id'
+ def yangModelCmHandle = new YangModelCmHandle(id:cmHandleId, alternateId: alternateId, dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties)
+ and: 'we have corresponding cm handle for the cm handle reference'
+ 1 * mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> cmHandleId
and: 'the system returns this yang modelled cm handle'
- 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
- when: 'getting cm handle public properties for a given cm handle id from ncmp service'
- def result = objectUnderTest.getCmHandlePublicProperties('some-cm-handle')
+ 1 * mockInventoryPersistence.getYangModelCmHandle(cmHandleId) >> yangModelCmHandle
+ when: 'getting cm handle public properties for a given cm handle reference from ncmp service'
+ def result = objectUnderTest.getCmHandlePublicProperties(cmHandleRef)
then: 'the result returns the correct data'
assert result == [ 'public prop' : 'some public prop' ]
+ where: 'following cm handle reference is used'
+ scenario | cmHandleRef
+ 'Cm Handle Reference as cm handle-id' | 'some-cm-handle'
+ 'Cm Handle Reference as alternate-id' | 'some-alternate-id'
}
- def 'Get cm handle composite state'() {
+ def 'Get cm handle composite state using #scenario'() {
given: 'a yang modelled cm handle'
def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED,
lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(),
@@ -153,13 +174,21 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
dataStores: dataStores())
def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
def publicProperties = [new YangModelCmHandle.Property('public prop', 'some public prop')]
- def yangModelCmHandle = new YangModelCmHandle(id:'some-cm-handle', dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState)
+ def cmHandleId = 'some-cm-handle'
+ def alternateId = 'some-alternate-id'
+ def yangModelCmHandle = new YangModelCmHandle(id:cmHandleId, alternateId: alternateId, dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState)
+ and: 'we have corresponding cm handle for the cm handle reference'
+ 1 * mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> cmHandleId
and: 'the system returns this yang modelled cm handle'
- 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
+ 1 * mockInventoryPersistence.getYangModelCmHandle(cmHandleId) >> yangModelCmHandle
when: 'getting cm handle composite state for a given cm handle id from ncmp service'
- def result = objectUnderTest.getCmHandleCompositeState('some-cm-handle')
+ def result = objectUnderTest.getCmHandleCompositeState(cmHandleRef)
then: 'the result returns the correct data'
assert result == compositeState
+ where: 'following cm handle reference is used'
+ scenario | cmHandleRef
+ 'Cm Handle Reference as cm handle-id' | 'some-cm-handle'
+ 'Cm Handle Reference as alternate-id' | 'some-alternate-id'
}
def 'Execute cm handle id search'() {
@@ -179,18 +208,30 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
assert result == ['cm-handle-id-1']
}
- def 'Getting module definitions by module'() {
- when: 'get module definitions is performed with module name'
- objectUnderTest.getModuleDefinitionsByCmHandleAndModule('some-cm-handle', 'some-module', '2021-08-04')
- then: 'ncmp inventory persistence service is invoked once with correct parameters'
+ def 'Getting module definitions by module for a given #scenario'() {
+ when: 'get module definitions is performed with module name and cm handle reference'
+ objectUnderTest.getModuleDefinitionsByCmHandleAndModule(cmHandleRef, 'some-module', '2021-08-04')
+ then: 'alternate id matcher returns some cm handle id for a given cm handle reference'
+ mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> 'some-cm-handle'
+ and: 'ncmp inventory persistence service is invoked once with correct parameters'
1 * mockInventoryPersistence.getModuleDefinitionsByCmHandleAndModule('some-cm-handle', 'some-module', '2021-08-04')
+ where: 'following cm handle reference is used'
+ scenario | cmHandleRef
+ 'Cm Handle Reference as cm handle-id' | 'some-cm-handle'
+ 'Cm Handle Reference as alternate-id' | 'some-alternate-id'
}
- def 'Getting module definitions by cm handle id'() {
- when: 'get module definitions is performed with cm handle id'
- objectUnderTest.getModuleDefinitionsByCmHandleId('some-cm-handle')
+ def 'Getting module definitions for a given #scenario'() {
+ when: 'get module definitions is performed with cm handle reference'
+ objectUnderTest.getModuleDefinitionsByCmHandleReference(cmHandleRef)
+ then: 'alternate id matcher returns some cm handle id for a given cm handle reference'
+ mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> 'some-cm-handle'
then: 'ncmp inventory persistence service is invoked once with correct parameter'
1 * mockInventoryPersistence.getModuleDefinitionsByCmHandleId('some-cm-handle')
+ where: 'following cm handle reference is used'
+ scenario | cmHandleRef
+ 'Cm Handle Reference as cm handle-id' | 'some-cm-handle'
+ 'Cm Handle Reference as alternate-id' | 'some-alternate-id'
}
def 'Execute cm handle search'() {
@@ -203,17 +244,18 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification {
and: 'query cm handle method returns two cm handles'
mockParameterizedCmHandleQueryService.queryCmHandles(
spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class))
- >> [new NcmpServiceCmHandle(cmHandleId: 'ch-0'), new NcmpServiceCmHandle(cmHandleId: 'ch-1')]
- and: ' a trust level for ch-1'
- trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE)
+ >> [new YangModelCmHandle(id: 'ch-0', dmiProperties: [], publicProperties: []),
+ new YangModelCmHandle(id: 'ch-1', dmiProperties: [], publicProperties: [])]
+ and: 'a trust level for cm handles'
+ mockTrustLevelManager.getEffectiveTrustLevel(*_) >> TrustLevel.COMPLETE
when: 'execute cm handle search is called'
def result = objectUnderTest.executeCmHandleSearch(cmHandleQueryApiParameters)
then: 'result consists of the two cm handles returned by the CPS Data Service'
assert result.size() == 2
assert result[0].cmHandleId == 'ch-0'
assert result[1].cmHandleId == 'ch-1'
- and: 'only ch-1 has a trust level'
- assert result[0].currentTrustLevel == null
+ and: 'cm handles have trust level'
+ assert result[0].currentTrustLevel == TrustLevel.COMPLETE
assert result[1].currentTrustLevel == TrustLevel.COMPLETE
}
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..08644202c6 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.
@@ -22,7 +22,6 @@ package org.onap.cps.ncmp.impl.inventory
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
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.exceptions.DataInUseException
@@ -139,10 +138,10 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
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: [])]
- and: 'the expected cm handle(s) are returned as NCMP Service cm handles'
- assert result[0] instanceof NcmpServiceCmHandle
+ and: 'the expected cm handle(s) are returned as Yang Model cm handles'
+ assert result[0] instanceof YangModelCmHandle
assert result.size() == 1
- assert result[0].dmiProperties == [name:'value']
+ assert result[0].dmiProperties.size() == 1
}
def 'Query cm handle ids when the query is empty.'() {
@@ -165,7 +164,7 @@ class ParameterizedCmHandleQueryServiceSpec extends Specification {
def result = objectUnderTest.queryCmHandles(cmHandleQueryParameters)
then: 'the correct cm handles are returned'
assert result.size() == 4
- assert result.cmHandleId.containsAll('PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4')
+ assert result.id.containsAll('PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4')
}
def 'Query CMHandleId with #scenario.' () {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy
index 196a1cd360..c80aa7b242 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy
@@ -25,7 +25,7 @@ import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.ncmp.impl.dmi.DmiOperationsBaseSpec
import org.onap.cps.ncmp.impl.dmi.DmiProperties
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy
index 6db304acd1..c7d0616bb2 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy
@@ -49,7 +49,7 @@ class DeviceTrustLevelMessageConsumerSpec extends Specification {
when: 'the event is consumed'
objectUnderTest.deviceTrustLevelListener(consumerRecord)
then: 'cm handles are stored with correct trust level'
- 1 * mockTrustLevelManager.handleUpdateOfDeviceTrustLevel('"ch-1"', TrustLevel.COMPLETE)
+ 1 * mockTrustLevelManager.updateCmHandleTrustLevel('"ch-1"', TrustLevel.COMPLETE)
}
def createTrustLevelEvent(eventPayload) {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy
index 0a34d267c5..32f4503005 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy
@@ -22,8 +22,8 @@ package org.onap.cps.ncmp.impl.inventory.trustlevel
import org.onap.cps.ncmp.api.inventory.models.TrustLevel
import org.onap.cps.ncmp.impl.dmi.DmiRestClient
-import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters
import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters
import reactor.core.publisher.Mono
import spock.lang.Specification
@@ -46,7 +46,7 @@ class DmiPluginTrustLevelWatchDogSpec extends Specification {
when: 'dmi watch dog method runs'
objectUnderTest.checkDmiAvailability()
then: 'the update delegated to manager'
- numberOfCalls * mockTrustLevelManager.handleUpdateOfDmiTrustLevel('dmi-1', _, newDmiTrustLevel)
+ numberOfCalls * mockTrustLevelManager.updateDmi('dmi-1', _, newDmiTrustLevel)
where: 'the following parameters are used'
dmiHealhStatus | dmiOldTrustLevel | newDmiTrustLevel || numberOfCalls
'UP' | TrustLevel.COMPLETE | TrustLevel.COMPLETE || 0
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy
index b5bfbc165c..7dc9602e46 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation
+ * Copyright (C) 2023-2024 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
package org.onap.cps.ncmp.impl.inventory.trustlevel
+import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration
import org.onap.cps.ncmp.api.inventory.models.TrustLevel
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
@@ -35,11 +36,20 @@ class TrustLevelManagerSpec extends Specification {
def mockAttributeValueChangeEventPublisher = Mock(CmAvcEventPublisher)
def objectUnderTest = new TrustLevelManager(trustLevelPerCmHandle, trustLevelPerDmiPlugin, mockInventoryPersistence, mockAttributeValueChangeEventPublisher)
+ def 'Initial dmi registration'() {
+ given: 'a dmi plugin'
+ def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'dmi-1')
+ when: 'method to register to the cache is called'
+ objectUnderTest.registerDmiPlugin(dmiPluginRegistration)
+ then: 'dmi plugin in the cache and trusted'
+ assert trustLevelPerDmiPlugin.get('dmi-1') == TrustLevel.COMPLETE
+ }
+
def 'Initial cm handle registration'() {
given: 'two cm handles: one with no trust level and one trusted'
def cmHandleModelsToBeCreated = ['ch-1': null, 'ch-2': TrustLevel.COMPLETE]
- when: 'the initial registration handled'
- objectUnderTest.handleInitialRegistrationOfTrustLevels(cmHandleModelsToBeCreated)
+ when: 'method to register to the cache is called'
+ objectUnderTest.registerCmHandles(cmHandleModelsToBeCreated)
then: 'no notification sent'
0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_)
and: 'both cm handles are in the cache and are trusted'
@@ -50,8 +60,8 @@ class TrustLevelManagerSpec extends Specification {
def 'Initial cm handle registration with a cm handle that is not trusted'() {
given: 'a not trusted cm handle'
def cmHandleModelsToBeCreated = ['ch-2': TrustLevel.NONE]
- when: 'the initial registration handled'
- objectUnderTest.handleInitialRegistrationOfTrustLevels(cmHandleModelsToBeCreated)
+ when: 'method to register to the cache is called'
+ objectUnderTest.registerCmHandles(cmHandleModelsToBeCreated)
then: 'notification is sent'
1 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_)
}
@@ -62,7 +72,7 @@ class TrustLevelManagerSpec extends Specification {
and: 'a trusted cm handle'
trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE)
when: 'the update is handled'
- objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.NONE)
+ objectUnderTest.updateDmi('my-dmi', ['ch-1'], TrustLevel.NONE)
then: 'notification is sent'
1 * mockAttributeValueChangeEventPublisher.publishAvcEvent('ch-1', 'trustLevel', 'COMPLETE', 'NONE')
and: 'the dmi in the cache is not trusted'
@@ -75,54 +85,74 @@ class TrustLevelManagerSpec extends Specification {
and: 'a trusted cm handle'
trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE)
when: 'the update is handled'
- objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.COMPLETE)
+ objectUnderTest.updateDmi('my-dmi', ['ch-1'], TrustLevel.COMPLETE)
then: 'no notification is sent'
0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_)
and: 'the dmi in the cache is trusted'
assert trustLevelPerDmiPlugin.get('my-dmi') == TrustLevel.COMPLETE
}
- def 'Device trust level updated'() {
+ def 'CmHandle trust level updated'() {
given: 'a non trusted cm handle'
trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE)
and: 'a trusted dmi plugin'
trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE)
and: 'inventory persistence service returns yang model cm handle'
mockInventoryPersistence.getYangModelCmHandle('ch-1') >> new YangModelCmHandle(id: 'ch-1', dmiDataServiceName: 'my-dmi')
- when: 'update of device to COMPLETE trust level handled'
- objectUnderTest.handleUpdateOfDeviceTrustLevel('ch-1', TrustLevel.COMPLETE)
+ when: 'update of CmHandle to COMPLETE trust level handled'
+ objectUnderTest.updateCmHandleTrustLevel('ch-1', TrustLevel.COMPLETE)
then: 'the cm handle in the cache is trusted'
assert trustLevelPerCmHandle.get('ch-1', TrustLevel.COMPLETE)
and: 'notification is sent'
1 * mockAttributeValueChangeEventPublisher.publishAvcEvent('ch-1', 'trustLevel', 'NONE', 'COMPLETE')
}
- def 'Device trust level updated with same value'() {
+ def 'CmHandle trust level updated with same value'() {
given: 'a non trusted cm handle'
trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE)
and: 'a trusted dmi plugin'
trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE)
and: 'inventory persistence service returns yang model cm handle'
mockInventoryPersistence.getYangModelCmHandle('ch-1') >> new YangModelCmHandle(id: 'ch-1', dmiDataServiceName: 'my-dmi')
- when: 'update of device trust to the same level (NONE)'
- objectUnderTest.handleUpdateOfDeviceTrustLevel('ch-1', TrustLevel.NONE)
+ when: 'update of CmHandle trust to the same level (NONE)'
+ objectUnderTest.updateCmHandleTrustLevel('ch-1', TrustLevel.NONE)
then: 'the cm handle in the cache is not trusted'
assert trustLevelPerCmHandle.get('ch-1', TrustLevel.NONE)
and: 'no notification is sent'
0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_)
}
- def 'Dmi trust level restored to complete with non trusted device'() {
+ def 'Dmi trust level restored to complete with non trusted CmHandle'() {
given: 'a non trusted dmi'
trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE)
- and: 'a non trusted device'
+ and: 'a non trusted CmHandle'
trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE)
when: 'restore the dmi trust level to COMPLETE'
- objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.COMPLETE)
+ objectUnderTest.updateDmi('my-dmi', ['ch-1'], TrustLevel.COMPLETE)
then: 'the cm handle in the cache is still NONE'
assert trustLevelPerCmHandle.get('ch-1') == TrustLevel.NONE
and: 'no notification is sent'
0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_)
}
+ def 'Select effective trust level among CmHandle and dmi plugin'() {
+ given: 'a non trusted dmi'
+ trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE)
+ and: 'a trusted CmHandle'
+ trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE)
+ when: 'effective trust level selected'
+ def effectiveTrustLevel = objectUnderTest.getEffectiveTrustLevel('my-dmi', 'ch-1')
+ then: 'effective trust level is trusted'
+ assert effectiveTrustLevel == TrustLevel.NONE
+ }
+
+ def 'CmHandle trust level removed'() {
+ given: 'a cm handle'
+ trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE)
+ when: 'the remove is handled'
+ objectUnderTest.removeCmHandles(['ch-1'])
+ then: 'cm handle removed from the cache'
+ assert trustLevelPerCmHandle.get('ch-1') == null
+ }
+
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilderSpec.groovy
index 9e1b37023b..9e051156f7 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilderSpec.groovy
@@ -18,14 +18,13 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.impl.dmi
-
+package org.onap.cps.ncmp.impl.utils.http
import spock.lang.Specification
-class DmiServiceUrlTemplateBuilderSpec extends Specification {
+class RestServiceUrlTemplateBuilderSpec extends Specification {
- def objectUnderTest = new DmiServiceUrlTemplateBuilder()
+ def objectUnderTest = new RestServiceUrlTemplateBuilder()
def 'Build URL template parameters with (variable) path segments and query parameters.'() {
given: 'the URL details are given to the builder'
@@ -35,9 +34,9 @@ class DmiServiceUrlTemplateBuilderSpec extends Specification {
objectUnderTest.queryParameter('param1', 'abc')
objectUnderTest.queryParameter('param2', 'value?with#special:characters')
when: 'the URL template parameters are created'
- def result = objectUnderTest.createUrlTemplateParameters('myDmiServer', 'myBasePath')
+ def result = objectUnderTest.createUrlTemplateParameters('myServer', 'myBasePath')
then: 'the URL template contains variable names instead of value and un-encoded fixed segment'
- assert result.urlTemplate == 'myDmiServer/myBasePath/v1/segment/{myVariableSegment}/segment?with:special&characters?param1={param1}&param2={param2}'
+ assert result.urlTemplate == 'myServer/myBasePath/v1/segment/{myVariableSegment}/segment?with:special&characters?param1={param1}&param2={param2}'
and: 'URL variables contains name and un-encoded value pairs'
assert result.urlVariables == ['myVariableSegment': 'someValue', 'param1': 'abc', 'param2': 'value?with#special:characters']
}
@@ -46,7 +45,7 @@ class DmiServiceUrlTemplateBuilderSpec extends Specification {
given: 'the query parameter is given to the builder'
objectUnderTest.queryParameter('my&param', 'special&characters=are?not\\encoded')
when: 'the URL template parameters are created'
- def result = objectUnderTest.createUrlTemplateParameters('myDmiServer', 'myBasePath')
+ def result = objectUnderTest.createUrlTemplateParameters('myServer', 'myBasePath')
then: 'Special characters are not encoded'
assert result.urlVariables == ['my&param': 'special&characters=are?not\\encoded']
}
@@ -55,7 +54,7 @@ class DmiServiceUrlTemplateBuilderSpec extends Specification {
when: 'the query parameter is given to the builder'
objectUnderTest.queryParameter('param', value)
and: 'the URL template parameters are create'
- def result = objectUnderTest.createUrlTemplateParameters('myDmiServer', 'myBasePath')
+ def result = objectUnderTest.createUrlTemplateParameters('myServer', 'myBasePath')
then: 'no parameter gets added'
assert result.urlVariables.isEmpty()
where: 'the following parameter values are used'
diff --git a/cps-ncmp-service/src/test/java/org/onap/cps/ncmp/utils/WebClientBuilderTestConfig.java b/cps-ncmp-service/src/test/java/org/onap/cps/ncmp/utils/WebClientBuilderTestConfig.java
new file mode 100644
index 0000000000..2f6b270076
--- /dev/null
+++ b/cps-ncmp-service/src/test/java/org/onap/cps/ncmp/utils/WebClientBuilderTestConfig.java
@@ -0,0 +1,40 @@
+/*
+ * ============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.utils;
+
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.reactive.function.client.WebClient;
+
+@TestConfiguration
+public class WebClientBuilderTestConfig {
+
+ /**
+ * Configures and creates a web client builder bean to make it accessible for the Spring Boot Test Context.
+ *
+ * @return a WebClient Builder instance.
+ */
+ @Bean
+ public WebClient.Builder webClientBuilder() {
+ return WebClient.builder();
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/resources/application.yml b/cps-ncmp-service/src/test/resources/application.yml
index 72d074ab5f..c76831da74 100644
--- a/cps-ncmp-service/src/test/resources/application.yml
+++ b/cps-ncmp-service/src/test/resources/application.yml
@@ -84,8 +84,8 @@ ncmp:
policy-executor:
enabled: true
server:
- address: "http://localhost"
- port: "8785"
+ address: http://localhost
+ port: 8785
httpclient:
all-services:
maximumInMemorySizeInMegabytes: 31
diff --git a/cps-parent/pom.xml b/cps-parent/pom.xml
index a4aeb5b5a5..430f4b5cd8 100644
--- a/cps-parent/pom.xml
+++ b/cps-parent/pom.xml
@@ -410,30 +410,6 @@
<artifactId>sonar-maven-plugin</artifactId>
<version>3.9.1.2184</version>
</plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>exec-maven-plugin</artifactId>
- <version>1.6.0</version>
- <executions>
- <execution>
- <id>generate-csv</id>
- <phase>prepare-package</phase>
- <goals>
- <goal>exec</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <executable>${script.executor}</executable>
- <workingDirectory>${parent.directory}/cps-ri/src/main/resources/</workingDirectory>
- <arguments>
- <argument>yangResourceCsvGenerator.py</argument>
- <argument>dmi-registry@2021-12-13</argument>
- <argument>dmi-registry@2022-02-10</argument>
- <argument>dmi-registry@2022-05-10</argument>
- </arguments>
- </configuration>
- </plugin>
</plugins>
</build>
</project>
diff --git a/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4 b/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4
index 3aef120fed..be8d968fcb 100644
--- a/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4
+++ b/cps-path-parser/src/main/antlr4/org/onap/cps/cpspath/parser/antlr4/CpsPath.g4
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation
+ * Copyright (C) 2021-2024 Nordix Foundation
* Modifications Copyright (C) 2023 TechMahindra Ltd
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,7 +27,7 @@
grammar CpsPath ;
-cpsPath : ( prefix | descendant | incorrectPrefix ) multipleLeafConditions? textFunctionCondition? containsFunctionCondition? ancestorAxis? invalidPostFix?;
+cpsPath : ( prefix | descendant ) multipleLeafConditions? textFunctionCondition? containsFunctionCondition? ancestorAxis? EOF ;
ancestorAxis : SLASH KW_ANCESTOR COLONCOLON ancestorPath ;
@@ -43,8 +43,6 @@ prefix : parent SLASH containerName ;
descendant : SLASH prefix ;
-incorrectPrefix : SLASH SLASH SLASH+ ;
-
yangElement : containerName listElementRef? ;
containerName : QName ;
@@ -61,8 +59,6 @@ booleanOperators : ( KW_AND | KW_OR ) ;
comparativeOperators : ( EQ | GT | LT | GE | LE ) ;
-invalidPostFix : (AT | CB | COLONCOLON | comparativeOperators ).+ ;
-
/*
* Lexer Rules
* Most of the lexer rules below are inspired by
diff --git a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
index 0bb09235ff..ac535f5efc 100644
--- a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
+++ b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathBuilder.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation
+ * Copyright (C) 2021-2024 Nordix Foundation
* Modifications Copyright (C) 2023 TechMahindra Ltd
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,7 +29,6 @@ import org.onap.cps.cpspath.parser.antlr4.CpsPathBaseListener;
import org.onap.cps.cpspath.parser.antlr4.CpsPathParser;
import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.AncestorAxisContext;
import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.DescendantContext;
-import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.IncorrectPrefixContext;
import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.LeafConditionContext;
import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.MultipleLeafConditionsContext;
import org.onap.cps.cpspath.parser.antlr4.CpsPathParser.PrefixContext;
@@ -43,7 +42,7 @@ public class CpsPathBuilder extends CpsPathBaseListener {
private final CpsPathQuery cpsPathQuery = new CpsPathQuery();
- private final List<CpsPathQuery.DataLeaf> leavesData = new ArrayList<>();
+ private final List<CpsPathQuery.LeafCondition> leafConditions = new ArrayList<>();
private final StringBuilder normalizedXpathBuilder = new StringBuilder();
@@ -55,13 +54,6 @@ public class CpsPathBuilder extends CpsPathBaseListener {
private final List<String> booleanOperators = new ArrayList<>();
- private final List<String> comparativeOperators = new ArrayList<>();
-
- @Override
- public void exitInvalidPostFix(final CpsPathParser.InvalidPostFixContext ctx) {
- throw new PathParsingException(ctx.getText());
- }
-
@Override
public void exitPrefix(final PrefixContext ctx) {
cpsPathQuery.setXpathPrefix(normalizedXpathBuilder.toString());
@@ -73,12 +65,9 @@ public class CpsPathBuilder extends CpsPathBaseListener {
}
@Override
- public void exitIncorrectPrefix(final IncorrectPrefixContext ctx) {
- throw new PathParsingException("CPS path can only start with one or two slashes (/)");
- }
-
- @Override
public void exitLeafCondition(final LeafConditionContext ctx) {
+ final String leafName = ctx.leafName().getText();
+ final String operator = ctx.comparativeOperators().getText();
final Object comparisonValue;
if (ctx.IntegerLiteral() != null) {
comparisonValue = Integer.valueOf(ctx.IntegerLiteral().getText());
@@ -87,7 +76,7 @@ public class CpsPathBuilder extends CpsPathBaseListener {
} else {
throw new PathParsingException("Unsupported comparison value encountered in expression" + ctx.getText());
}
- leafContext(ctx.leafName(), comparisonValue);
+ leafContext(leafName, operator, comparisonValue);
}
@Override
@@ -96,11 +85,6 @@ public class CpsPathBuilder extends CpsPathBaseListener {
}
@Override
- public void exitComparativeOperators(final CpsPathParser.ComparativeOperatorsContext ctx) {
- comparativeOperators.add(ctx.getText());
- }
-
- @Override
public void exitDescendant(final DescendantContext ctx) {
cpsPathQuery.setCpsPathPrefixType(DESCENDANT);
cpsPathQuery.setDescendantName(normalizedXpathBuilder.substring(1));
@@ -110,15 +94,14 @@ public class CpsPathBuilder extends CpsPathBaseListener {
@Override
public void enterMultipleLeafConditions(final MultipleLeafConditionsContext ctx) {
normalizedXpathBuilder.append(OPEN_BRACKET);
- leavesData.clear();
+ leafConditions.clear();
booleanOperators.clear();
- comparativeOperators.clear();
}
@Override
public void exitMultipleLeafConditions(final MultipleLeafConditionsContext ctx) {
normalizedXpathBuilder.append(CLOSE_BRACKET);
- cpsPathQuery.setLeavesData(leavesData);
+ cpsPathQuery.setLeafConditions(leafConditions);
}
@Override
@@ -164,11 +147,6 @@ public class CpsPathBuilder extends CpsPathBaseListener {
cpsPathQuery.setNormalizedXpath(normalizedXpathBuilder.toString());
cpsPathQuery.setContainerNames(containerNames);
cpsPathQuery.setBooleanOperators(booleanOperators);
- cpsPathQuery.setComparativeOperators(comparativeOperators);
- if (cpsPathQuery.hasAncestorAxis() && cpsPathQuery.getXpathPrefix()
- .endsWith("/" + cpsPathQuery.getAncestorSchemaNodeIdentifier())) {
- cpsPathQuery.setAncestorSchemaNodeIdentifier("");
- }
return cpsPathQuery;
}
@@ -183,16 +161,16 @@ public class CpsPathBuilder extends CpsPathBaseListener {
}
}
- private void leafContext(final CpsPathParser.LeafNameContext ctx, final Object comparisonValue) {
- leavesData.add(new CpsPathQuery.DataLeaf(ctx.getText(), comparisonValue));
- appendCondition(normalizedXpathBuilder, ctx.getText(), comparisonValue);
+ private void leafContext(final String leafName, final String operator, final Object comparisonValue) {
+ leafConditions.add(new CpsPathQuery.LeafCondition(leafName, operator, comparisonValue));
+ appendCondition(normalizedXpathBuilder, leafName, operator, comparisonValue);
if (processingAncestorAxis) {
- appendCondition(normalizedAncestorPathBuilder, ctx.getText(), comparisonValue);
+ appendCondition(normalizedAncestorPathBuilder, leafName, operator, comparisonValue);
}
}
private void appendCondition(final StringBuilder currentNormalizedPathBuilder, final String name,
- final Object value) {
+ final String operator, final Object value) {
final char lastCharacter = currentNormalizedPathBuilder.charAt(currentNormalizedPathBuilder.length() - 1);
final boolean isStartOfExpression = lastCharacter == '[';
if (!isStartOfExpression) {
@@ -200,7 +178,7 @@ public class CpsPathBuilder extends CpsPathBaseListener {
}
currentNormalizedPathBuilder.append("@")
.append(name)
- .append(getLastElement(comparativeOperators))
+ .append(operator)
.append("'")
.append(value.toString().replace("'", "''"))
.append("'");
diff --git a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java
index f98df05a28..03602b64f6 100644
--- a/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java
+++ b/cps-path-parser/src/main/java/org/onap/cps/cpspath/parser/CpsPathQuery.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2023 Nordix Foundation
+ * Copyright (C) 2021-2024 Nordix Foundation
* Modifications Copyright (C) 2023 TechMahindra Ltd
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,8 +25,6 @@ import static org.onap.cps.cpspath.parser.CpsPathPrefixType.ABSOLUTE;
import java.util.List;
import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@@ -40,12 +38,11 @@ public class CpsPathQuery {
private List<String> containerNames;
private CpsPathPrefixType cpsPathPrefixType = ABSOLUTE;
private String descendantName;
- private List<DataLeaf> leavesData;
+ private List<LeafCondition> leafConditions;
private String ancestorSchemaNodeIdentifier = "";
private String textFunctionConditionLeafName;
private String textFunctionConditionValue;
private List<String> booleanOperators;
- private List<String> comparativeOperators;
private String containsFunctionConditionLeafName;
private String containsFunctionConditionValue;
@@ -74,7 +71,7 @@ public class CpsPathQuery {
* @return boolean value.
*/
public boolean hasLeafConditions() {
- return leavesData != null;
+ return leafConditions != null;
}
/**
@@ -104,11 +101,6 @@ public class CpsPathQuery {
return cpsPathPrefixType == ABSOLUTE && hasLeafConditions();
}
- @Getter
- @EqualsAndHashCode
- @AllArgsConstructor
- public static class DataLeaf {
- private final String name;
- private final Object value;
- }
+ public record LeafCondition(String name, String operator, Object value) { }
+
}
diff --git a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
index 15f6b11823..d0df3c745a 100644
--- a/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
+++ b/cps-path-parser/src/test/groovy/org/onap/cps/cpspath/parser/CpsPathQuerySpec.groovy
@@ -48,8 +48,8 @@ class CpsPathQuerySpec extends Specification {
and: 'the right query parameters are set'
assert result.xpathPrefix == expectedXpathPrefix
assert result.hasLeafConditions()
- assert result.leavesData[0].name == expectedLeafName
- assert result.leavesData[0].value == expectedLeafValue
+ assert result.leafConditions[0].name() == expectedLeafName
+ assert result.leafConditions[0].value() == expectedLeafValue
where: 'the following data is used'
scenario | cpsPath || expectedXpathPrefix | expectedLeafName | expectedLeafValue
'leaf of type String' | '/parent/child[@common-leaf-name="common-leaf-value"]' || '/parent/child' | 'common-leaf-name' | 'common-leaf-value'
@@ -123,11 +123,11 @@ class CpsPathQuerySpec extends Specification {
when: 'the given cps path is parsed'
def result = CpsPathQuery.createFrom(cpsPath)
then: 'the expected number of leaves are returned'
- result.leavesData.size() == expectedNumberOfLeaves
+ result.leafConditions.size() == expectedNumberOfLeaves
and: 'the given operator(s) returns in the correct order'
result.booleanOperators == expectedOperators
and: 'the given comparativeOperator(s) returns in the correct order'
- result.comparativeOperators == expectedComparativeOperator
+ result.leafConditions.operator == expectedComparativeOperator
where: 'the following data is used'
cpsPath || expectedNumberOfLeaves || expectedOperators || expectedComparativeOperator
'/parent[@code=1]/child[@common-leaf-name-int=5]' || 1 || [] || ['=']
@@ -234,40 +234,23 @@ class CpsPathQuerySpec extends Specification {
when: 'the given cps path is parsed using multiple conditions on same leaf'
def result = CpsPathQuery.createFrom('/test[@same-name="value1" or @same-name="value2"]')
then: 'two leaves are present with correct values'
- assert result.leavesData.size() == 2
- assert result.leavesData[0].name == "same-name"
- assert result.leavesData[0].value == "value1"
- assert result.leavesData[1].name == "same-name"
- assert result.leavesData[1].value == "value2"
+ assert result.leafConditions.size() == 2
+ assert result.leafConditions[0].name == "same-name"
+ assert result.leafConditions[0].value == "value1"
+ assert result.leafConditions[1].name == "same-name"
+ assert result.leafConditions[1].value == "value2"
}
def 'Ordering of data leaves is preserved.'() {
when: 'the given cps path is parsed'
def result = CpsPathQuery.createFrom(cpsPath)
then: 'the order of the data leaves is preserved'
- assert result.leavesData[0].name == expectedFirstLeafName
- assert result.leavesData[1].name == expectedSecondLeafName
+ assert result.leafConditions[0].name == expectedFirstLeafName
+ assert result.leafConditions[1].name == expectedSecondLeafName
where: 'the following data is used'
cpsPath || expectedFirstLeafName | expectedSecondLeafName
'/test[@name1="value1" and @name2="value2"]' || 'name1' | 'name2'
'/test[@name2="value2" and @name1="value1"]' || 'name2' | 'name1'
}
- def 'Ancestor axis matching prefix'() {
- when: 'building a cps path query'
- def result = parseXPathAndBuild(xpath)
- then: 'ancestor axis is removed when same as prefix'
- assert result.hasAncestorAxis() == expectAncestorAxis
- where: 'the following xpaths are used'
- xpath || expectAncestorAxis
- '//abc/def/ancestor::abc' || true
- '//abc/def/ancestor::def' || false
- '//abc/def/ancestor::ef' || true
- }
-
- def parseXPathAndBuild(xpath) {
- def cpsPathBuilder = CpsPathUtil.getCpsPathBuilder(xpath)
- cpsPathBuilder.build()
- }
-
}
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java
index b2014757d7..eb61d56632 100644
--- a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentQueryBuilder.java
@@ -24,14 +24,12 @@ package org.onap.cps.spi.repository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
-import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.onap.cps.cpspath.parser.CpsPathPrefixType;
import org.onap.cps.cpspath.parser.CpsPathQuery;
import org.onap.cps.spi.PaginationOption;
@@ -43,10 +41,8 @@ import org.onap.cps.spi.utils.EscapeUtils;
import org.springframework.stereotype.Component;
@RequiredArgsConstructor
-@Slf4j
@Component
public class FragmentQueryBuilder {
- private static final AnchorEntity ACROSS_ALL_ANCHORS = null;
@PersistenceContext
private EntityManager entityManager;
@@ -59,8 +55,14 @@ public class FragmentQueryBuilder {
* @return a executable query object
*/
public Query getQueryForAnchorAndCpsPath(final AnchorEntity anchorEntity, final CpsPathQuery cpsPathQuery) {
- return getQueryForDataspaceOrAnchorAndCpsPath(anchorEntity.getDataspace(),
- anchorEntity, cpsPathQuery, Collections.emptyList());
+ final StringBuilder sqlStringBuilder = new StringBuilder();
+ final Map<String, Object> queryParameters = new HashMap<>();
+
+ sqlStringBuilder.append("SELECT fragment.* FROM fragment");
+ addWhereClauseForAnchor(anchorEntity, sqlStringBuilder, queryParameters);
+ addNodeSearchConditions(cpsPathQuery, sqlStringBuilder, queryParameters, false);
+
+ return getQuery(sqlStringBuilder.toString(), queryParameters, FragmentEntity.class);
}
/**
@@ -73,8 +75,18 @@ public class FragmentQueryBuilder {
public Query getQueryForDataspaceAndCpsPath(final DataspaceEntity dataspaceEntity,
final CpsPathQuery cpsPathQuery,
final List<Long> anchorIdsForPagination) {
- return getQueryForDataspaceOrAnchorAndCpsPath(dataspaceEntity, ACROSS_ALL_ANCHORS,
- cpsPathQuery, anchorIdsForPagination);
+ final StringBuilder sqlStringBuilder = new StringBuilder();
+ final Map<String, Object> queryParameters = new HashMap<>();
+
+ sqlStringBuilder.append("SELECT fragment.* FROM fragment");
+ if (anchorIdsForPagination.isEmpty()) {
+ addWhereClauseForDataspace(dataspaceEntity, sqlStringBuilder, queryParameters);
+ } else {
+ addWhereClauseForAnchorIds(anchorIdsForPagination, sqlStringBuilder, queryParameters);
+ }
+ addNodeSearchConditions(cpsPathQuery, sqlStringBuilder, queryParameters, true);
+
+ return getQuery(sqlStringBuilder.toString(), queryParameters, FragmentEntity.class);
}
/**
@@ -89,52 +101,52 @@ public class FragmentQueryBuilder {
final PaginationOption paginationOption) {
final StringBuilder sqlStringBuilder = new StringBuilder();
final Map<String, Object> queryParameters = new HashMap<>();
- sqlStringBuilder.append("SELECT distinct(fragment.anchor_id) FROM fragment "
- + "JOIN anchor ON anchor.id = fragment.anchor_id WHERE dataspace_id = :dataspaceId");
- queryParameters.put("dataspaceId", dataspaceEntity.getId());
- addAbsoluteParentXpathSearchCondition(cpsPathQuery, sqlStringBuilder, queryParameters, ACROSS_ALL_ANCHORS);
- addXpathSearchCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
- addLeafConditions(cpsPathQuery, sqlStringBuilder);
- addTextFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
- addContainsFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
- if (PaginationOption.NO_PAGINATION != paginationOption) {
- sqlStringBuilder.append(" ORDER BY fragment.anchor_id");
- addPaginationCondition(sqlStringBuilder, queryParameters, paginationOption);
- }
- final Query query = entityManager.createNativeQuery(sqlStringBuilder.toString());
+ sqlStringBuilder.append("SELECT distinct(fragment.anchor_id) FROM fragment");
+ addWhereClauseForDataspace(dataspaceEntity, sqlStringBuilder, queryParameters);
+ addNodeSearchConditions(cpsPathQuery, sqlStringBuilder, queryParameters, true);
+ sqlStringBuilder.append(" ORDER BY fragment.anchor_id");
+ addPaginationCondition(sqlStringBuilder, queryParameters, paginationOption);
+
+ return getQuery(sqlStringBuilder.toString(), queryParameters, Long.class);
+ }
+
+ private Query getQuery(final String sql, final Map<String, Object> queryParameters, final Class<?> returnType) {
+ final Query query = entityManager.createNativeQuery(sql, returnType);
setQueryParameters(query, queryParameters);
return query;
}
- private Query getQueryForDataspaceOrAnchorAndCpsPath(final DataspaceEntity dataspaceEntity,
- final AnchorEntity anchorEntity,
- final CpsPathQuery cpsPathQuery,
- final List<Long> anchorIdsForPagination) {
- final StringBuilder sqlStringBuilder = new StringBuilder();
- final Map<String, Object> queryParameters = new HashMap<>();
+ private static void addWhereClauseForAnchor(final AnchorEntity anchorEntity,
+ final StringBuilder sqlStringBuilder,
+ final Map<String, Object> queryParameters) {
+ sqlStringBuilder.append(" WHERE anchor_id = :anchorId");
+ queryParameters.put("anchorId", anchorEntity.getId());
+ }
- if (anchorEntity == ACROSS_ALL_ANCHORS) {
- sqlStringBuilder.append("SELECT fragment.* FROM fragment JOIN anchor ON anchor.id = fragment.anchor_id"
- + " WHERE dataspace_id = :dataspaceId");
- queryParameters.put("dataspaceId", dataspaceEntity.getId());
- if (!anchorIdsForPagination.isEmpty()) {
- sqlStringBuilder.append(" AND anchor_id IN (:anchorIdsForPagination)");
- queryParameters.put("anchorIdsForPagination", anchorIdsForPagination);
- }
- } else {
- sqlStringBuilder.append("SELECT * FROM fragment WHERE anchor_id = :anchorId");
- queryParameters.put("anchorId", anchorEntity.getId());
- }
- addAbsoluteParentXpathSearchCondition(cpsPathQuery, sqlStringBuilder, queryParameters, anchorEntity);
+ private static void addWhereClauseForAnchorIds(final List<Long> anchorIdsForPagination,
+ final StringBuilder sqlStringBuilder,
+ final Map<String, Object> queryParameters) {
+ sqlStringBuilder.append(" WHERE anchor_id IN (:anchorIdsForPagination)");
+ queryParameters.put("anchorIdsForPagination", anchorIdsForPagination);
+ }
+
+ private static void addWhereClauseForDataspace(final DataspaceEntity dataspaceEntity,
+ final StringBuilder sqlStringBuilder,
+ final Map<String, Object> queryParameters) {
+ sqlStringBuilder.append(" JOIN anchor ON anchor.id = fragment.anchor_id WHERE dataspace_id = :dataspaceId");
+ queryParameters.put("dataspaceId", dataspaceEntity.getId());
+ }
+
+ private static void addNodeSearchConditions(final CpsPathQuery cpsPathQuery,
+ final StringBuilder sqlStringBuilder,
+ final Map<String, Object> queryParameters,
+ final boolean acrossAnchors) {
+ addAbsoluteParentXpathSearchCondition(cpsPathQuery, sqlStringBuilder, queryParameters, acrossAnchors);
addXpathSearchCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
addLeafConditions(cpsPathQuery, sqlStringBuilder);
addTextFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
addContainsFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
-
- final Query query = entityManager.createNativeQuery(sqlStringBuilder.toString(), FragmentEntity.class);
- setQueryParameters(query, queryParameters);
- return query;
}
private static void addXpathSearchCondition(final CpsPathQuery cpsPathQuery,
@@ -152,12 +164,12 @@ public class FragmentQueryBuilder {
private static void addAbsoluteParentXpathSearchCondition(final CpsPathQuery cpsPathQuery,
final StringBuilder sqlStringBuilder,
final Map<String, Object> queryParameters,
- final AnchorEntity anchorEntity) {
+ final boolean acrossAnchors) {
if (CpsPathPrefixType.ABSOLUTE.equals(cpsPathQuery.getCpsPathPrefixType())) {
if (cpsPathQuery.getNormalizedParentPath().isEmpty()) {
sqlStringBuilder.append(" AND parent_id IS NULL");
} else {
- if (anchorEntity == ACROSS_ALL_ANCHORS) {
+ if (acrossAnchors) {
sqlStringBuilder.append(" AND parent_id IN (SELECT id FROM fragment WHERE xpath = :parentXpath)");
} else {
sqlStringBuilder.append(" AND parent_id = (SELECT id FROM fragment WHERE xpath = :parentXpath"
@@ -171,10 +183,12 @@ public class FragmentQueryBuilder {
private static void addPaginationCondition(final StringBuilder sqlStringBuilder,
final Map<String, Object> queryParameters,
final PaginationOption paginationOption) {
- final Integer offset = (paginationOption.getPageIndex() - 1) * paginationOption.getPageSize();
- sqlStringBuilder.append(" LIMIT :pageSize OFFSET :offset");
- queryParameters.put("pageSize", paginationOption.getPageSize());
- queryParameters.put("offset", offset);
+ if (PaginationOption.NO_PAGINATION != paginationOption) {
+ final Integer offset = (paginationOption.getPageIndex() - 1) * paginationOption.getPageSize();
+ sqlStringBuilder.append(" LIMIT :pageSize OFFSET :offset");
+ queryParameters.put("pageSize", paginationOption.getPageSize());
+ queryParameters.put("offset", offset);
+ }
}
private static Integer getTextValueAsInt(final CpsPathQuery cpsPathQuery) {
@@ -185,40 +199,34 @@ public class FragmentQueryBuilder {
}
}
- private void addLeafConditions(final CpsPathQuery cpsPathQuery, final StringBuilder sqlStringBuilder) {
+ private static void addLeafConditions(final CpsPathQuery cpsPathQuery, final StringBuilder sqlStringBuilder) {
if (cpsPathQuery.hasLeafConditions()) {
- queryLeafConditions(cpsPathQuery, sqlStringBuilder);
- }
- }
-
- private void queryLeafConditions(final CpsPathQuery cpsPathQuery, final StringBuilder sqlStringBuilder) {
- sqlStringBuilder.append(" AND (");
- final Queue<String> booleanOperatorsQueue = new LinkedList<>(cpsPathQuery.getBooleanOperators());
- final Queue<String> comparativeOperatorQueue = new LinkedList<>(cpsPathQuery.getComparativeOperators());
- cpsPathQuery.getLeavesData().forEach(leaf -> {
- final String nextComparativeOperator = comparativeOperatorQueue.poll();
- if (leaf.getValue() instanceof Integer) {
- sqlStringBuilder.append("(attributes ->> '").append(leaf.getName()).append("')\\:\\:int");
- sqlStringBuilder.append(nextComparativeOperator);
- sqlStringBuilder.append(leaf.getValue());
- } else {
- if ("=".equals(nextComparativeOperator)) {
- final String leafValueAsText = leaf.getValue().toString();
- sqlStringBuilder.append("attributes ->> '").append(leaf.getName()).append("'");
- sqlStringBuilder.append(" = '");
- sqlStringBuilder.append(EscapeUtils.escapeForSqlStringLiteral(leafValueAsText));
- sqlStringBuilder.append("'");
+ sqlStringBuilder.append(" AND (");
+ final Queue<String> booleanOperatorsQueue = new LinkedList<>(cpsPathQuery.getBooleanOperators());
+ cpsPathQuery.getLeafConditions().forEach(leafCondition -> {
+ if (leafCondition.value() instanceof Integer) {
+ sqlStringBuilder.append("(attributes ->> '").append(leafCondition.name()).append("')\\:\\:int");
+ sqlStringBuilder.append(leafCondition.operator());
+ sqlStringBuilder.append(leafCondition.value());
} else {
- throw new CpsPathException(" can use only " + nextComparativeOperator + " with integer ");
+ if ("=".equals(leafCondition.operator())) {
+ final String leafValueAsText = leafCondition.value().toString();
+ sqlStringBuilder.append("attributes ->> '").append(leafCondition.name()).append("'");
+ sqlStringBuilder.append(" = '");
+ sqlStringBuilder.append(EscapeUtils.escapeForSqlStringLiteral(leafValueAsText));
+ sqlStringBuilder.append("'");
+ } else {
+ throw new CpsPathException(" can use only " + leafCondition.operator() + " with integer ");
+ }
}
- }
- if (!booleanOperatorsQueue.isEmpty()) {
- sqlStringBuilder.append(" ");
- sqlStringBuilder.append(booleanOperatorsQueue.poll());
- sqlStringBuilder.append(" ");
- }
- });
- sqlStringBuilder.append(")");
+ if (!booleanOperatorsQueue.isEmpty()) {
+ sqlStringBuilder.append(" ");
+ sqlStringBuilder.append(booleanOperatorsQueue.poll());
+ sqlStringBuilder.append(" ");
+ }
+ });
+ sqlStringBuilder.append(")");
+ }
}
private static void addTextFunctionCondition(final CpsPathQuery cpsPathQuery,
diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md b/cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md
deleted file mode 100644
index 212acb9006..0000000000
--- a/cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
- ============LICENSE_START=======================================================
- Copyright (C) 2022 Nordix Foundation.
- ================================================================================
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- SPDX-License-Identifier: Apache-2.0
- ============LICENSE_END=========================================================
--->
-
-##Placeholder folder for generated CSV files as part of yang models.
-
-Do not remove this folder \ No newline at end of file
diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang b/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang
deleted file mode 100644
index ed3559bf61..0000000000
--- a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang
+++ /dev/null
@@ -1,63 +0,0 @@
-module dmi-registry {
-
- yang-version 1.1;
-
- namespace "org:onap:cps:ncmp";
-
- prefix dmi-reg;
-
- contact "dylan.byrne@est.tech";
-
- revision "2021-05-20" {
- description
- "Initial Version";
- }
-
- revision "2021-10-20" {
- description
- "Added dmi-data-service-name & dmi-model-service-name to allow separate DMI instances for each responsibility";
- }
-
- revision "2021-12-13" {
- description
- "Added new list of public additonal properties for a Cm-Handle which are exposed to clients of the NCMP interface";
- }
-
- container dmi-registry {
- list cm-handles {
- key "id";
- leaf id {
- type string;
- }
- leaf dmi-service-name {
- type string;
- }
- leaf dmi-data-service-name {
- type string;
- }
- leaf dmi-model-service-name {
- type string;
- }
-
- list additional-properties {
- key "name";
- leaf name {
- type string;
- }
- leaf value {
- type string;
- }
- }
-
- list public-properties {
- key "name";
- leaf name {
- type string;
- }
- leaf value {
- type string;
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-02-10.yang b/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-02-10.yang
deleted file mode 100644
index 3c6d990c5d..0000000000
--- a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-02-10.yang
+++ /dev/null
@@ -1,81 +0,0 @@
-module dmi-registry {
-
- yang-version 1.1;
-
- namespace "org:onap:cps:ncmp";
-
- prefix dmi-reg;
-
- contact "toine.siebelink@est.tech";
-
- revision "2022-02-10" {
- description
- "Added State, LockReason, LockReasonDetails to aid with cmHandle sync and timestamp to aid with retry/timeout scenarios";
- }
-
- revision "2021-12-13" {
- description
- "Added new list of public additional properties for a Cm-Handle which are exposed to clients of the NCMP interface";
- }
-
- revision "2021-10-20" {
- description
- "Added dmi-data-service-name & dmi-model-service-name to allow separate DMI instances for each responsibility";
- }
-
- revision "2021-05-20" {
- description
- "Initial Version";
- }
-
- container dmi-registry {
- list cm-handles {
- key "id";
- leaf id {
- type string;
- }
- leaf dmi-service-name {
- type string;
- }
- leaf dmi-data-service-name {
- type string;
- }
- leaf dmi-model-service-name {
- type string;
- }
-
- list additional-properties {
- key "name";
- leaf name {
- type string;
- }
- leaf value {
- type string;
- }
- }
-
- list public-properties {
- key "name";
- leaf name {
- type string;
- }
- leaf value {
- type string;
- }
- }
-
- leaf state {
- type string;
- }
- leaf lock-reason {
- type string;
- }
- leaf lock-reason-details {
- type string;
- }
- leaf last-update-time {
- type string;
- }
- }
- }
-}
diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-05-10.yang b/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-05-10.yang
deleted file mode 100644
index 77517968c6..0000000000
--- a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-05-10.yang
+++ /dev/null
@@ -1,123 +0,0 @@
-module dmi-registry {
-
- yang-version 1.1;
-
- namespace "org:onap:cps:ncmp";
-
- prefix dmi-reg;
-
- contact "toine.siebelink@est.tech";
-
- revision "2022-05-10" {
- description
- "Added DataSyncEnabled, SyncState with State, LastSyncTime, DataStoreSyncState with Operational and Running syncstate";
- }
-
- revision "2022-02-10" {
- description
- "Added State, LockReason, LockReasonDetails to aid with cmHandle sync and timestamp to aid with retry/timeout scenarios";
- }
-
- revision "2021-12-13" {
- description
- "Added new list of public additional properties for a Cm-Handle which are exposed to clients of the NCMP interface";
- }
-
- revision "2021-10-20" {
- description
- "Added dmi-data-service-name & dmi-model-service-name to allow separate DMI instances for each responsibility";
- }
-
- revision "2021-05-20" {
- description
- "Initial Version";
- }
-
- grouping LockReason {
- leaf reason {
- type string;
- }
- leaf details {
- type string;
- }
- }
-
- grouping SyncState {
- leaf sync-state {
- type string;
- }
- leaf last-sync-time {
- type string;
- }
- }
-
- grouping Datastores {
- container operational {
- uses SyncState;
- }
- container running {
- uses SyncState;
- }
- }
-
- container dmi-registry {
- list cm-handles {
- key "id";
- leaf id {
- type string;
- }
- leaf dmi-service-name {
- type string;
- }
- leaf dmi-data-service-name {
- type string;
- }
- leaf dmi-model-service-name {
- type string;
- }
-
- list additional-properties {
- key "name";
- leaf name {
- type string;
- }
- leaf value {
- type string;
- }
- }
-
- list public-properties {
- key "name";
- leaf name {
- type string;
- }
- leaf value {
- type string;
- }
- }
-
- container state {
- leaf cm-handle-state {
- type string;
- }
-
- container lock-reason {
- uses LockReason;
- }
-
- leaf last-update-time {
- type string;
- }
-
- leaf data-sync-enabled {
- type boolean;
- default "false";
- }
-
- container datastores {
- uses Datastores;
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/cps-ri/src/main/resources/yangResourceCsvGenerator.py b/cps-ri/src/main/resources/yangResourceCsvGenerator.py
deleted file mode 100644
index 3a076d4378..0000000000
--- a/cps-ri/src/main/resources/yangResourceCsvGenerator.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# ============LICENSE_START=======================================================
-# Copyright (C) 2022 Nordix Foundation
-# ================================================================================
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# SPDX-License-Identifier: Apache-2.0
-# ============LICENSE_END=========================================================
-
-
-import csv
-import datetime
-import hashlib
-import sys
-import re
-
-yang_source = ''
-checksum = ''
-regexForModuleName = '(?<=module)(.*)(?={)'
-regexForRevision = '(?<=revision)(.*)(?={)'
-
-def main():
- for yang_source in sys.argv[1:]:
- checksum = hashlib.sha256(str(yang_source).encode()).hexdigest()
-
- with open('changelog/db/changes/data/yang-models/' + yang_source + '.yang', 'r') as content:
- dmiRegistry = content.read()
-
- try:
- latestRevision = re.search(regexForRevision, dmiRegistry).group(0).replace('\"','').strip()
- except:
- print("ERROR IN in yangResourceCsvGenerator.py: Unable to find revision for " + yang_source + '.yang')
-
- try:
- module_name = re.search(regexForModuleName, dmiRegistry).group(0).strip()
- except:
- print("ERROR IN in yangResourceCsvGenerator.py: Unable to find module name for " + yang_source + '.yang')
-
- #If true, file was created after module_name and revision columns were added to yang-resources table
- writeWithModuleNameAndRevision = yang_source != 'dmi-registry@2021-12-13'
-
- try:
- # open the file in the write mode
- with open('changelog/db/changes/data/dmi/generated-csv/generated_yang_resource_' + yang_source + '.csv', 'w', newline='') \
- as file:
- writer = csv.writer(file, delimiter='|')
- if(writeWithModuleNameAndRevision):
- writer.writerow(["name", "content", "checksum", "module_name", "revision"])
- writer.writerow([yang_source + '.yang', dmiRegistry, checksum, module_name, latestRevision])
- else:
- writer.writerow(["name", "content", "checksum"])
- writer.writerow([yang_source + '.yang', dmiRegistry, checksum])
- except:
- print("ERROR IN in yangResourceCsvGenerator.py: Unable to write to changelog/db/changes/data/dmi/generated-csv/generated_yang_resource_" + yang_source + ".csv")
-
-
-main() \ No newline at end of file
diff --git a/cps-service/pom.xml b/cps-service/pom.xml
index f04b4e81c8..37a45957f3 100644
--- a/cps-service/pom.xml
+++ b/cps-service/pom.xml
@@ -144,18 +144,6 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
- <dependency>
- <groupId>io.cloudevents</groupId>
- <artifactId>cloudevents-json-jackson</artifactId>
- </dependency>
- <dependency>
- <groupId>io.cloudevents</groupId>
- <artifactId>cloudevents-kafka</artifactId>
- </dependency>
- <dependency>
- <groupId>io.cloudevents</groupId>
- <artifactId>cloudevents-spring</artifactId>
- </dependency>
<!-- T E S T D E P E N D E N C I E S -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
diff --git a/csit/install-deps.sh b/csit/install-deps.sh
new file mode 100755
index 0000000000..ef0b96a799
--- /dev/null
+++ b/csit/install-deps.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# Copyright 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.
+#
+
+echo "---> install-deps.sh"
+echo "Installing dependencies"
+
+# Create directory for downloaded binaries.
+mkdir -p bin
+touch bin/.gitignore
+
+# Add it to the PATH, so downloaded versions will be used.
+export PATH="$(pwd)/bin:$PATH"
+
+# Download docker-compose.
+if [ ! -x bin/docker-compose ]; then
+ echo " Downloading docker-compose"
+ curl -s -L https://github.com/docker/compose/releases/download/v2.29.2/docker-compose-linux-x86_64 > bin/docker-compose
+ chmod +x bin/docker-compose
+else
+ echo " docker-compose already installed"
+fi
+docker-compose version
diff --git a/csit/plans/cps/setup.sh b/csit/plans/cps/setup.sh
index 80829eba14..036f14b82f 100755
--- a/csit/plans/cps/setup.sh
+++ b/csit/plans/cps/setup.sh
@@ -1,7 +1,6 @@
#!/bin/bash
#
# Copyright 2016-2017 Huawei Technologies Co., Ltd.
-# Modifications Copyright (C) 2022 Nordix Foundation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -19,7 +18,7 @@
# Modifications copyright (c) 2020-2021 Samsung Electronics Co., Ltd.
# Modifications Copyright (C) 2021 Pantheon.tech
# Modifications Copyright (C) 2021 Bell Canada.
-# Modifications Copyright (C) 2021 Nordix Foundation.
+# Modifications Copyright (C) 2021-2024 Nordix Foundation.
#
# Branched from ccsdk/distribution to this repository Feb 23, 2021
#
@@ -59,10 +58,6 @@ export $(cut -d= -f1 $WORKSPACE/plans/cps/test.properties)
###################### setup cps-ncmp ############################
cd $CPS_HOME/docker-compose
-curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > docker-compose
-chmod +x docker-compose
-docker-compose version
-
# start CPS/NCMP, DMI Plugin, and PostgreSQL containers with docker compose
docker-compose --profile dmi-service up -d
@@ -82,4 +77,4 @@ check_health $DMI_HOST:$DMI_PORT 'dmi-plugin'
###################### ROBOT Configurations ##########################
# Pass variables required for Robot test suites in ROBOT_VARIABLES
-ROBOT_VARIABLES="-v CPS_CORE_HOST:$CPS_CORE_HOST -v CPS_CORE_PORT:$CPS_CORE_PORT -v DMI_HOST:$LOCAL_IP -v DMI_PORT:$DMI_PORT -v DMI_CSIT_STUB_HOST:$LOCAL_IP -v DMI_CSIT_STUB_PORT:$DMI_DEMO_STUB_PORT -v DMI_AUTH_ENABLED:$DMI_AUTH_ENABLED -v DATADIR_CPS_CORE:$WORKSPACE/data/cps-core -v DATADIR_NCMP:$WORKSPACE/data/ncmp -v DATADIR_SUBS_NOTIFICATION:$WORKSPACE/data/subscription-notification --exitonfailure" \ No newline at end of file
+ROBOT_VARIABLES="-v CPS_CORE_HOST:$CPS_CORE_HOST -v CPS_CORE_PORT:$CPS_CORE_PORT -v DMI_HOST:$LOCAL_IP -v DMI_PORT:$DMI_PORT -v DMI_CSIT_STUB_HOST:$LOCAL_IP -v DMI_CSIT_STUB_PORT:$DMI_DEMO_STUB_PORT -v DMI_AUTH_ENABLED:$DMI_AUTH_ENABLED -v DATADIR_CPS_CORE:$WORKSPACE/data/cps-core -v DATADIR_NCMP:$WORKSPACE/data/ncmp -v DATADIR_SUBS_NOTIFICATION:$WORKSPACE/data/subscription-notification --exitonfailure"
diff --git a/csit/run-project-csit.sh b/csit/run-project-csit.sh
index fcb3c925c1..f362cc7130 100755
--- a/csit/run-project-csit.sh
+++ b/csit/run-project-csit.sh
@@ -2,6 +2,7 @@
#
# Copyright 2020-2021 © Samsung Electronics Co., Ltd.
# Modifications Copyright (C) 2021 Pantheon.tech
+# Modifications 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.
@@ -28,6 +29,8 @@ rm -rf ${WORKSPACE}/archives
mkdir -p ${WORKSPACE}/archives
cd ${WORKSPACE}
+source install-deps.sh
+
# Execute all test-suites defined under plans subdirectory
for dir in plans/*/
do
diff --git a/csit/tests/cps-trust-level/cps-trust-level.robot b/csit/tests/cps-trust-level/cps-trust-level.robot
index e4deeff32b..810bcf4d12 100644
--- a/csit/tests/cps-trust-level/cps-trust-level.robot
+++ b/csit/tests/cps-trust-level/cps-trust-level.robot
@@ -36,7 +36,7 @@ ${ncmpBasePath} /ncmp/v1
${dmiUrl} http://${DMI_HOST}:${DMI_PORT}
${jsonCreateCmHandles} {"dmiPlugin":"${dmiUrl}","dmiDataPlugin":"","dmiModelPlugin":"","createdCmHandles":[{"trustLevel":"COMPLETE","cmHandle":"CH-1"},{"trustLevel":"COMPLETE","cmHandle":"CH-2"},{"cmHandle":"CH-3"},{"trustLevel":"NONE","cmHandle":"CH-4"}]}
${jsonTrustLevelPropertyQueryParameters} {"cmHandleQueryParameters": [{"conditionName": "cmHandleWithTrustLevel", "conditionParameters": [ {"trustLevel": "COMPLETE"} ] }]}
-${jsonTrustLevelQueryResponse} {"data":{"attributeValueChange":[{"attributeName":"trustLevel","newAttributeValue":"NONE"}]}}
+${jsonTrustLevelEventPayload} {"data":{"attributeValueChange":[{"attributeName":"trustLevel","newAttributeValue":"NONE"}]}}
*** Test Cases ***
Register data node
@@ -57,7 +57,7 @@ Verify notification
Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_type" "org.onap.cps.ncmp.events.avc.ncmp_to_client.AvcEvent"
Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_correlationid" "CH-4"
END
- Should Be Equal As Strings ${payload} ${jsonTrustLevelQueryResponse}
+ Should Be Equal As Strings ${payload} ${jsonTrustLevelEventPayload}
[Teardown] Basic Teardown ${group_id}
Retrieve CM Handle ids where query parameters Match (trust level query)
diff --git a/docker-compose/config/grafana/jvm-micrometer-dashboard.json b/docker-compose/config/grafana/jvm-micrometer-dashboard.json
new file mode 100644
index 0000000000..8f7747c596
--- /dev/null
+++ b/docker-compose/config/grafana/jvm-micrometer-dashboard.json
@@ -0,0 +1,3613 @@
+{
+ "annotations": {
+ "list": [
+ {
+ "builtIn": 1,
+ "datasource": {
+ "type": "datasource",
+ "uid": "grafana"
+ },
+ "enable": true,
+ "hide": true,
+ "iconColor": "rgba(0, 211, 255, 1)",
+ "limit": 100,
+ "name": "Annotations & Alerts",
+ "showIn": 0,
+ "type": "dashboard"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "enable": true,
+ "expr": "resets(process_uptime_seconds{application=\"$application\", instance=\"$instance\"}[1m]) > 0",
+ "iconColor": "rgba(255, 96, 96, 1)",
+ "name": "Restart Detection",
+ "showIn": 0,
+ "step": "1m",
+ "tagKeys": "restart-tag",
+ "textFormat": "uptime reset",
+ "titleFormat": "Restart"
+ }
+ ]
+ },
+ "description": "Dashboard for Micrometer instrumented applications (Java, Spring Boot, Micronaut)",
+ "editable": true,
+ "fiscalYearStartMonth": 0,
+ "gnetId": 4701,
+ "graphTooltip": 1,
+ "id": 1,
+ "links": [],
+ "panels": [
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
+ "id": 139,
+ "panels": [],
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Quick Facts",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "decimals": 1,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 3,
+ "w": 6,
+ "x": 0,
+ "y": 1
+ },
+ "id": 63,
+ "maxDataPoints": 100,
+ "options": {
+ "colorMode": "value",
+ "graphMode": "none",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.1.4",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "process_uptime_seconds{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "",
+ "metric": "",
+ "refId": "A",
+ "step": 14400
+ }
+ ],
+ "title": "Uptime",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "dateTimeAsIso"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 3,
+ "w": 6,
+ "x": 6,
+ "y": 1
+ },
+ "id": 92,
+ "maxDataPoints": 100,
+ "options": {
+ "colorMode": "value",
+ "graphMode": "none",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.1.4",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "process_start_time_seconds{application=\"$application\", instance=\"$instance\"}*1000",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "",
+ "metric": "",
+ "refId": "A",
+ "step": 14400
+ }
+ ],
+ "title": "Start time",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "decimals": 2,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ }
+ ],
+ "max": 100,
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "rgba(50, 172, 45, 0.97)",
+ "value": null
+ },
+ {
+ "color": "rgba(237, 129, 40, 0.89)",
+ "value": 70
+ },
+ {
+ "color": "rgba(245, 54, 54, 0.9)",
+ "value": 90
+ }
+ ]
+ },
+ "unit": "percent"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 3,
+ "w": 6,
+ "x": 12,
+ "y": 1
+ },
+ "id": 65,
+ "maxDataPoints": 100,
+ "options": {
+ "colorMode": "value",
+ "graphMode": "none",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.1.4",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"})*100/sum(jvm_memory_max_bytes{application=\"$application\",instance=\"$instance\", area=\"heap\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "",
+ "refId": "A",
+ "step": 14400
+ }
+ ],
+ "title": "Heap used",
+ "type": "stat"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "decimals": 2,
+ "mappings": [
+ {
+ "options": {
+ "match": "null",
+ "result": {
+ "text": "N/A"
+ }
+ },
+ "type": "special"
+ },
+ {
+ "options": {
+ "from": -1e+32,
+ "result": {
+ "text": "N/A"
+ },
+ "to": 0
+ },
+ "type": "range"
+ }
+ ],
+ "max": 100,
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "rgba(50, 172, 45, 0.97)",
+ "value": null
+ },
+ {
+ "color": "rgba(237, 129, 40, 0.89)",
+ "value": 70
+ },
+ {
+ "color": "rgba(245, 54, 54, 0.9)",
+ "value": 90
+ }
+ ]
+ },
+ "unit": "percent"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 3,
+ "w": 6,
+ "x": 18,
+ "y": 1
+ },
+ "id": 75,
+ "maxDataPoints": 100,
+ "options": {
+ "colorMode": "value",
+ "graphMode": "none",
+ "justifyMode": "auto",
+ "orientation": "horizontal",
+ "percentChangeColorMode": "standard",
+ "reduceOptions": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "fields": "",
+ "values": false
+ },
+ "showPercentChange": false,
+ "textMode": "auto",
+ "wideLayout": true
+ },
+ "pluginVersion": "11.1.4",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"})*100/sum(jvm_memory_max_bytes{application=\"$application\",instance=\"$instance\", area=\"nonheap\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "",
+ "refId": "A",
+ "step": 14400
+ }
+ ],
+ "title": "Non-Heap used",
+ "type": "stat"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 4
+ },
+ "id": 140,
+ "panels": [],
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "I/O Overview",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "ops"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 0,
+ "y": 5
+ },
+ "id": 111,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(rate(http_server_requests_seconds_count{application=\"$application\", instance=\"$instance\"}[1m]))",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "HTTP",
+ "refId": "A"
+ }
+ ],
+ "title": "Rate",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "ops"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "HTTP"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#890f02",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "HTTP - 5xx"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#bf1b00",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 6,
+ "y": 5
+ },
+ "id": 112,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(rate(http_server_requests_seconds_count{application=\"$application\", instance=\"$instance\", status=~\"5..\"}[1m]))",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "HTTP - 5xx",
+ "refId": "A"
+ }
+ ],
+ "title": "Errors",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "s"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 12,
+ "y": 5
+ },
+ "id": 113,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(rate(http_server_requests_seconds_sum{application=\"$application\", instance=\"$instance\", status!~\"5..\"}[1m]))/sum(rate(http_server_requests_seconds_count{application=\"$application\", instance=\"$instance\", status!~\"5..\"}[1m]))",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "HTTP - AVG",
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "max(http_server_requests_seconds_max{application=\"$application\", instance=\"$instance\", status!~\"5..\"})",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "HTTP - MAX",
+ "refId": "B"
+ }
+ ],
+ "title": "Duration",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "description": "",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 18,
+ "y": 5
+ },
+ "id": 119,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "tomcat_threads_busy_threads{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "TOMCAT - BSY",
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "tomcat_threads_current_threads{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "TOMCAT - CUR",
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "tomcat_threads_config_max_threads{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "TOMCAT - MAX",
+ "refId": "C"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jetty_threads_busy{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "JETTY - BSY",
+ "refId": "D"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jetty_threads_current{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "JETTY - CUR",
+ "refId": "E"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jetty_threads_config_max{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "JETTY - MAX",
+ "refId": "F"
+ }
+ ],
+ "title": "Utilisation",
+ "type": "timeseries"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 12
+ },
+ "id": 141,
+ "panels": [],
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "JVM Memory",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 0,
+ "y": 13
+ },
+ "id": 24,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "used",
+ "metric": "",
+ "refId": "A",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "committed",
+ "refId": "B",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "max",
+ "refId": "C",
+ "step": 2400
+ }
+ ],
+ "title": "JVM Heap",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 6,
+ "y": 13
+ },
+ "id": 25,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"})",
+ "format": "time_series",
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "used",
+ "metric": "",
+ "refId": "A",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "committed",
+ "refId": "B",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "max",
+ "refId": "C",
+ "step": 2400
+ }
+ ],
+ "title": "JVM Non-Heap",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 12,
+ "y": 13
+ },
+ "id": 26,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "used",
+ "metric": "",
+ "refId": "A",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "committed",
+ "refId": "B",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\"})",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "max",
+ "refId": "C",
+ "step": 2400
+ }
+ ],
+ "title": "JVM Total",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 18,
+ "y": 13
+ },
+ "id": 86,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "process_memory_vss_bytes{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": true,
+ "intervalFactor": 2,
+ "legendFormat": "vss",
+ "metric": "",
+ "refId": "A",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "process_memory_rss_bytes{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "rss",
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "process_memory_swap_bytes{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "swap",
+ "refId": "C"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "process_memory_rss_bytes{application=\"$application\", instance=\"$instance\"} + process_memory_swap_bytes{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "total",
+ "refId": "D"
+ }
+ ],
+ "title": "JVM Process Memory",
+ "type": "timeseries"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 20
+ },
+ "id": 142,
+ "panels": [],
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "JVM Misc",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "decimals": 1,
+ "mappings": [],
+ "max": 1,
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "percentunit"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 0,
+ "y": 21
+ },
+ "id": 106,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "system_cpu_usage{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "system",
+ "metric": "",
+ "refId": "A",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "process_cpu_usage{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "process",
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "avg_over_time(process_cpu_usage{application=\"$application\", instance=\"$instance\"}[15m])",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "process-15m",
+ "refId": "C"
+ }
+ ],
+ "title": "CPU Usage",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "decimals": 1,
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 6,
+ "y": 21
+ },
+ "id": 93,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "system_load_average_1m{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "system-1m",
+ "metric": "",
+ "refId": "A",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "system_cpu_count{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "cpus",
+ "refId": "B"
+ }
+ ],
+ "title": "Load",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "decimals": 0,
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 12,
+ "y": 21
+ },
+ "id": 32,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_threads_live_threads{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "live",
+ "metric": "",
+ "refId": "A",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_threads_daemon_threads{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "daemon",
+ "metric": "",
+ "refId": "B",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_threads_peak_threads{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "peak",
+ "refId": "C",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "process_threads{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "process",
+ "refId": "D",
+ "step": 2400
+ }
+ ],
+ "title": "Threads",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "blocked"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#bf1b00",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "new"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#fce2de",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "runnable"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#7eb26d",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "terminated"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#511749",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "timed-waiting"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#c15c17",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "waiting"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#eab839",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 18,
+ "y": 21
+ },
+ "id": 124,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_threads_states_threads{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "{{state}}",
+ "refId": "A"
+ }
+ ],
+ "title": "Thread States",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "description": "The percent of time spent on Garbage Collection over all CPUs assigned to the JVM process.",
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "decimals": 1,
+ "mappings": [],
+ "max": 1,
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "percentunit"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 0,
+ "y": 28
+ },
+ "id": 138,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "sum(rate(jvm_gc_pause_seconds_sum{application=\"$application\", instance=\"$instance\"}[1m])) by (application, instance) / on(application, instance) system_cpu_count",
+ "format": "time_series",
+ "intervalFactor": 1,
+ "legendFormat": "CPU time spent on GC",
+ "refId": "A"
+ }
+ ],
+ "title": "GC Pressure",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "decimals": 0,
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "opm"
+ },
+ "overrides": [
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "debug"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#1F78C1",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "error"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#BF1B00",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "info"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#508642",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "trace"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#6ED0E0",
+ "mode": "fixed"
+ }
+ }
+ ]
+ },
+ {
+ "matcher": {
+ "id": "byName",
+ "options": "warn"
+ },
+ "properties": [
+ {
+ "id": "color",
+ "value": {
+ "fixedColor": "#EAB839",
+ "mode": "fixed"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 6,
+ "y": 28
+ },
+ "id": 91,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "increase(logback_events_total{application=\"$application\", instance=\"$instance\"}[1m])",
+ "format": "time_series",
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "{{level}}",
+ "metric": "",
+ "refId": "A",
+ "step": 1200
+ }
+ ],
+ "title": "Log Events",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "log": 10,
+ "type": "log"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "decimals": 0,
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "short"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 6,
+ "x": 18,
+ "y": 28
+ },
+ "id": 61,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "process_files_open_files{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "open",
+ "metric": "",
+ "refId": "A",
+ "step": 2400
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "process_files_max_files{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "max",
+ "metric": "",
+ "refId": "B",
+ "step": 2400
+ }
+ ],
+ "title": "File Descriptors",
+ "type": "timeseries"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 35
+ },
+ "id": 143,
+ "panels": [],
+ "repeat": "persistence_counts",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "JVM Memory Pools (Heap)",
+ "type": "row"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "drawStyle": "line",
+ "fillOpacity": 10,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "never",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "min": 0,
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ },
+ "unit": "bytes"
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 0,
+ "y": 36
+ },
+ "id": 3,
+ "options": {
+ "legend": {
+ "calcs": [
+ "lastNotNull",
+ "max"
+ ],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "multi",
+ "sort": "none"
+ }
+ },
+ "repeat": "jvm_memory_pool_heap",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=~\"$jvm_memory_pool_heap\"}",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "used",
+ "metric": "",
+ "refId": "A",
+ "step": 1800
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", id=~\"$jvm_memory_pool_heap\"}",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "commited",
+ "metric": "",
+ "refId": "B",
+ "step": 1800
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", id=~\"$jvm_memory_pool_heap\"}",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "max",
+ "metric": "",
+ "refId": "C",
+ "step": 1800
+ }
+ ],
+ "title": "$jvm_memory_pool_heap",
+ "type": "timeseries"
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 43
+ },
+ "id": 144,
+ "panels": [],
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "JVM Memory Pools (Non-Heap)",
+ "type": "row"
+ },
+ {
+ "aliasColors": {},
+ "autoMigrateFrom": "graph",
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "editable": true,
+ "error": false,
+ "fill": 1,
+ "grid": {
+ "leftLogBase": 1,
+ "rightLogBase": 1
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 0,
+ "y": 44
+ },
+ "id": 78,
+ "legend": {
+ "alignAsTable": false,
+ "avg": false,
+ "current": true,
+ "max": true,
+ "min": false,
+ "rightSide": false,
+ "show": true,
+ "total": false,
+ "values": true
+ },
+ "lines": true,
+ "linewidth": 1,
+ "maxPerRow": 3,
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "repeat": "jvm_memory_pool_nonheap",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=~\"$jvm_memory_pool_nonheap\"}",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "used",
+ "metric": "",
+ "refId": "A",
+ "step": 1800
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", id=~\"$jvm_memory_pool_nonheap\"}",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "commited",
+ "metric": "",
+ "refId": "B",
+ "step": 1800
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", id=~\"$jvm_memory_pool_nonheap\"}",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 2,
+ "legendFormat": "max",
+ "metric": "",
+ "refId": "C",
+ "step": 1800
+ }
+ ],
+ "thresholds": [],
+ "title": "$jvm_memory_pool_nonheap",
+ "tooltip": {
+ "msResolution": false,
+ "shared": true,
+ "sort": 0,
+ "value_type": "cumulative"
+ },
+ "type": "timeseries",
+ "x-axis": true,
+ "xaxis": {
+ "mode": "time",
+ "show": true,
+ "values": []
+ },
+ "y-axis": true,
+ "y_formats": [
+ "mbytes",
+ "short"
+ ],
+ "yaxes": [
+ {
+ "format": "bytes",
+ "logBase": 1,
+ "min": 0,
+ "show": true
+ },
+ {
+ "format": "short",
+ "logBase": 1,
+ "show": true
+ }
+ ]
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 58
+ },
+ "id": 145,
+ "panels": [],
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Garbage Collection",
+ "type": "row"
+ },
+ {
+ "aliasColors": {},
+ "autoMigrateFrom": "graph",
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fill": 1,
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 0,
+ "y": 59
+ },
+ "id": 98,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "rate(jvm_gc_pause_seconds_count{application=\"$application\", instance=\"$instance\"}[1m])",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 1,
+ "legendFormat": "{{action}} ({{cause}})",
+ "refId": "A"
+ }
+ ],
+ "thresholds": [],
+ "title": "Collections",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "timeseries",
+ "xaxis": {
+ "mode": "time",
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "ops",
+ "logBase": 1,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "autoMigrateFrom": "graph",
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fill": 1,
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 8,
+ "y": 59
+ },
+ "id": 101,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "rate(jvm_gc_pause_seconds_sum{application=\"$application\", instance=\"$instance\"}[1m])/rate(jvm_gc_pause_seconds_count{application=\"$application\", instance=\"$instance\"}[1m])",
+ "format": "time_series",
+ "hide": false,
+ "instant": false,
+ "intervalFactor": 1,
+ "legendFormat": "avg {{action}} ({{cause}})",
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_gc_pause_seconds_max{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "hide": false,
+ "instant": false,
+ "intervalFactor": 1,
+ "legendFormat": "max {{action}} ({{cause}})",
+ "refId": "B"
+ }
+ ],
+ "thresholds": [],
+ "title": "Pause Durations",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "timeseries",
+ "xaxis": {
+ "mode": "time",
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "s",
+ "logBase": 1,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "autoMigrateFrom": "graph",
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fill": 1,
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 16,
+ "y": 59
+ },
+ "id": 99,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "rate(jvm_gc_memory_allocated_bytes_total{application=\"$application\", instance=\"$instance\"}[1m])",
+ "format": "time_series",
+ "interval": "",
+ "intervalFactor": 1,
+ "legendFormat": "allocated",
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "rate(jvm_gc_memory_promoted_bytes_total{application=\"$application\", instance=\"$instance\"}[1m])",
+ "format": "time_series",
+ "interval": "",
+ "intervalFactor": 1,
+ "legendFormat": "promoted",
+ "refId": "B"
+ }
+ ],
+ "thresholds": [],
+ "title": "Allocated/Promoted",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "timeseries",
+ "xaxis": {
+ "mode": "time",
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "Bps",
+ "logBase": 1,
+ "min": "0",
+ "show": true
+ },
+ {
+ "format": "short",
+ "logBase": 1,
+ "show": true
+ }
+ ]
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 66
+ },
+ "id": 146,
+ "panels": [],
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Classloading",
+ "type": "row"
+ },
+ {
+ "aliasColors": {},
+ "autoMigrateFrom": "graph",
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "editable": true,
+ "error": false,
+ "fill": 1,
+ "grid": {
+ "leftLogBase": 1,
+ "rightLogBase": 1
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 0,
+ "y": 67
+ },
+ "id": 37,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_classes_loaded_classes{application=\"$application\", instance=\"$instance\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "loaded",
+ "metric": "",
+ "refId": "A",
+ "step": 1200
+ }
+ ],
+ "thresholds": [],
+ "title": "Classes loaded",
+ "tooltip": {
+ "msResolution": false,
+ "shared": true,
+ "sort": 0,
+ "value_type": "cumulative"
+ },
+ "type": "timeseries",
+ "x-axis": true,
+ "xaxis": {
+ "mode": "time",
+ "show": true,
+ "values": []
+ },
+ "y-axis": true,
+ "y_formats": [
+ "short",
+ "short"
+ ],
+ "yaxes": [
+ {
+ "format": "short",
+ "logBase": 1,
+ "min": 0,
+ "show": true
+ },
+ {
+ "format": "short",
+ "logBase": 1,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "autoMigrateFrom": "graph",
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "editable": true,
+ "error": false,
+ "fill": 1,
+ "grid": {
+ "leftLogBase": 1,
+ "rightLogBase": 1
+ },
+ "gridPos": {
+ "h": 7,
+ "w": 12,
+ "x": 12,
+ "y": 67
+ },
+ "id": 38,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "delta(jvm_classes_loaded_classes{application=\"$application\",instance=\"$instance\"}[1m])",
+ "format": "time_series",
+ "hide": false,
+ "interval": "",
+ "intervalFactor": 1,
+ "legendFormat": "delta-1m",
+ "metric": "",
+ "refId": "A",
+ "step": 1200
+ }
+ ],
+ "thresholds": [],
+ "title": "Class delta",
+ "tooltip": {
+ "msResolution": false,
+ "shared": true,
+ "sort": 0,
+ "value_type": "cumulative"
+ },
+ "type": "timeseries",
+ "x-axis": true,
+ "xaxis": {
+ "mode": "time",
+ "show": true,
+ "values": []
+ },
+ "y-axis": true,
+ "y_formats": [
+ "ops",
+ "short"
+ ],
+ "yaxes": [
+ {
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "show": true
+ },
+ {
+ "format": "short",
+ "logBase": 1,
+ "show": true
+ }
+ ]
+ },
+ {
+ "collapsed": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "gridPos": {
+ "h": 1,
+ "w": 24,
+ "x": 0,
+ "y": 74
+ },
+ "id": 147,
+ "panels": [],
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "refId": "A"
+ }
+ ],
+ "title": "Buffer Pools",
+ "type": "row"
+ },
+ {
+ "aliasColors": {},
+ "autoMigrateFrom": "graph",
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fill": 1,
+ "gridPos": {
+ "h": 7,
+ "w": 8,
+ "x": 0,
+ "y": 75
+ },
+ "id": 131,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "maxPerRow": 3,
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "repeat": "jvm_buffer_pool",
+ "seriesOverrides": [
+ {
+ "alias": "count",
+ "yaxis": 2
+ },
+ {
+ "alias": "buffers",
+ "yaxis": 2
+ }
+ ],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_buffer_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=~\"$jvm_buffer_pool\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "used",
+ "refId": "A"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_buffer_total_capacity_bytes{application=\"$application\", instance=\"$instance\", id=~\"$jvm_buffer_pool\"}",
+ "format": "time_series",
+ "intervalFactor": 2,
+ "legendFormat": "capacity",
+ "refId": "B"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "expr": "jvm_buffer_count_buffers{application=\"$application\", instance=\"$instance\", id=~\"$jvm_buffer_pool\"}",
+ "format": "time_series",
+ "hide": false,
+ "intervalFactor": 2,
+ "legendFormat": "buffers",
+ "refId": "C"
+ }
+ ],
+ "thresholds": [],
+ "title": "$jvm_buffer_pool",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "timeseries",
+ "xaxis": {
+ "mode": "time",
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "decbytes",
+ "logBase": 1,
+ "min": "0",
+ "show": true
+ },
+ {
+ "decimals": 0,
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "min": "0",
+ "show": true
+ }
+ ]
+ }
+ ],
+ "refresh": "auto",
+ "schemaVersion": 39,
+ "tags": [],
+ "templating": {
+ "list": [
+ {
+ "current": {
+ "isNone": true,
+ "selected": false,
+ "text": "None",
+ "value": ""
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "definition": "",
+ "hide": 0,
+ "includeAll": false,
+ "label": "Application",
+ "multi": false,
+ "name": "application",
+ "options": [],
+ "query": "label_values(application)",
+ "refresh": 2,
+ "regex": "",
+ "skipUrlSync": false,
+ "sort": 0,
+ "tagValuesQuery": "",
+ "tagsQuery": "",
+ "type": "query",
+ "useTags": false
+ },
+ {
+ "allFormat": "glob",
+ "current": {
+ "selected": false,
+ "text": "docker-compose-cps-and-ncmp-1:8080",
+ "value": "docker-compose-cps-and-ncmp-1:8080"
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "definition": "",
+ "hide": 0,
+ "includeAll": false,
+ "label": "Instance",
+ "multi": false,
+ "multiFormat": "glob",
+ "name": "instance",
+ "options": [],
+ "query": "label_values(jvm_memory_used_bytes{application=\"$application\"}, instance)",
+ "refresh": 2,
+ "regex": "",
+ "skipUrlSync": false,
+ "sort": 0,
+ "tagValuesQuery": "",
+ "tagsQuery": "",
+ "type": "query",
+ "useTags": false
+ },
+ {
+ "allFormat": "glob",
+ "current": {
+ "selected": false,
+ "text": "All",
+ "value": "$__all"
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "definition": "",
+ "hide": 2,
+ "includeAll": true,
+ "label": "JVM Memory Pools Heap",
+ "multi": false,
+ "multiFormat": "glob",
+ "name": "jvm_memory_pool_heap",
+ "options": [],
+ "query": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"},id)",
+ "refresh": 1,
+ "regex": "",
+ "skipUrlSync": false,
+ "sort": 1,
+ "tagValuesQuery": "",
+ "tagsQuery": "",
+ "type": "query",
+ "useTags": false
+ },
+ {
+ "allFormat": "glob",
+ "current": {
+ "selected": false,
+ "text": "All",
+ "value": "$__all"
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "definition": "",
+ "hide": 2,
+ "includeAll": true,
+ "label": "JVM Memory Pools Non-Heap",
+ "multi": false,
+ "multiFormat": "glob",
+ "name": "jvm_memory_pool_nonheap",
+ "options": [],
+ "query": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"},id)",
+ "refresh": 1,
+ "regex": "",
+ "skipUrlSync": false,
+ "sort": 2,
+ "tagValuesQuery": "",
+ "tagsQuery": "",
+ "type": "query",
+ "useTags": false
+ },
+ {
+ "allFormat": "glob",
+ "current": {
+ "selected": false,
+ "text": "All",
+ "value": "$__all"
+ },
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "definition": "",
+ "hide": 2,
+ "includeAll": true,
+ "label": "JVM Buffer Pools",
+ "multi": false,
+ "multiFormat": "glob",
+ "name": "jvm_buffer_pool",
+ "options": [],
+ "query": "label_values(jvm_buffer_memory_used_bytes{application=\"$application\", instance=\"$instance\"},id)",
+ "refresh": 1,
+ "regex": "",
+ "skipUrlSync": false,
+ "sort": 1,
+ "tagValuesQuery": "",
+ "tagsQuery": "",
+ "type": "query",
+ "useTags": false
+ }
+ ]
+ },
+ "time": {
+ "from": "now-30m",
+ "to": "now"
+ },
+ "timepicker": {
+ "now": true,
+ "refresh_intervals": [
+ "5s",
+ "10s",
+ "30s",
+ "1m",
+ "5m",
+ "15m",
+ "30m",
+ "1h",
+ "2h",
+ "1d"
+ ],
+ "time_options": [
+ "5m",
+ "15m",
+ "1h",
+ "6h",
+ "12h",
+ "24h",
+ "2d",
+ "7d",
+ "30d"
+ ]
+ },
+ "timezone": "browser",
+ "title": "JVM (Micrometer)",
+ "uid": "bdvp1kgecrda8f",
+ "version": 1,
+ "weekStart": ""
+}
diff --git a/docker-compose/config/grafana/provisioning/dashboards/dashboard.yml b/docker-compose/config/grafana/provisioning/dashboards/dashboard.yml
new file mode 100644
index 0000000000..b6dba86680
--- /dev/null
+++ b/docker-compose/config/grafana/provisioning/dashboards/dashboard.yml
@@ -0,0 +1,9 @@
+apiVersion: 1
+
+providers:
+ - name: default
+ orgId: 1
+ type: file
+ options:
+ path: /var/lib/grafana/dashboards
+ foldersFromFilesStructure: true
diff --git a/docker-compose/config/grafana/provisioning/datasources/datasource.yml b/docker-compose/config/grafana/provisioning/datasources/datasource.yml
new file mode 100644
index 0000000000..86fd3465e1
--- /dev/null
+++ b/docker-compose/config/grafana/provisioning/datasources/datasource.yml
@@ -0,0 +1,8 @@
+apiVersion: 1
+
+datasources:
+ - name: Prometheus
+ type: prometheus
+ access: proxy
+ url: http://prometheus:9090
+ isDefault: true
diff --git a/docker-compose/nginx.conf b/docker-compose/config/nginx/nginx.conf
index 17fad1b876..17fad1b876 100644
--- a/docker-compose/nginx.conf
+++ b/docker-compose/config/nginx/nginx.conf
diff --git a/docker-compose/proxy_params b/docker-compose/config/nginx/proxy_params
index ab092a98f3..ab092a98f3 100644
--- a/docker-compose/proxy_params
+++ b/docker-compose/config/nginx/proxy_params
diff --git a/docker-compose/postgres-init.sql b/docker-compose/config/postgres-init.sql
index 0c96de5b55..0c96de5b55 100644
--- a/docker-compose/postgres-init.sql
+++ b/docker-compose/config/postgres-init.sql
diff --git a/docker-compose/prometheus.yml b/docker-compose/config/prometheus.yml
index 9640709089..89af4a6800 100644
--- a/docker-compose/prometheus.yml
+++ b/docker-compose/config/prometheus.yml
@@ -3,8 +3,10 @@ global:
evaluation_interval: 5s
scrape_configs:
- - job_name: 'cps-and-ncm'
+ - job_name: 'cps-and-ncmp'
metrics_path: '/actuator/prometheus'
scrape_interval: 5s
static_configs:
- - targets: ['cps-and-ncmp:8080']
+ - targets:
+ - 'docker-compose-cps-and-ncmp-1:8080'
+ - 'docker-compose-cps-and-ncmp-2:8080'
diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml
index 5af325a50b..f79c03dbab 100644
--- a/docker-compose/docker-compose.yml
+++ b/docker-compose/docker-compose.yml
@@ -33,7 +33,7 @@ services:
POSTGRES_USER: ${DB_USERNAME:-cps}
POSTGRES_PASSWORD: ${DB_PASSWORD:-cps}
volumes:
- - ./postgres-init.sql:/docker-entrypoint-initdb.d/postgres-init.sql
+ - ./config/postgres-init.sql:/docker-entrypoint-initdb.d/postgres-init.sql
deploy:
resources:
reservations:
@@ -79,8 +79,8 @@ services:
depends_on:
- cps-and-ncmp
volumes:
- - ./nginx.conf:/etc/nginx/nginx.conf
- - ./proxy_params:/etc/nginx/proxy_params
+ - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
+ - ./config/nginx/proxy_params:/etc/nginx/proxy_params
### if kafka is not required comment out zookeeper and kafka ###
zookeeper:
@@ -139,6 +139,7 @@ services:
KAFKA_BOOTSTRAP_SERVER: kafka:29092
NCMP_CONSUMER_GROUP_ID: ncmp-group
NCMP_ASYNC_M2M_TOPIC: ncmp-async-m2m
+ MODULE_INITIAL_PROCESSING_DELAY_MS: 0
MODULE_REFERENCES_DELAY_MS: 100
MODULE_RESOURCES_DELAY_MS: 1000
READ_DATA_FOR_CM_HANDLE_DELAY_MS: 300
@@ -158,26 +159,28 @@ services:
- policy-executor-stub
prometheus:
- container_name: prometheus-container
+ container_name: prometheus
image: prom/prometheus:latest
ports:
- 9090:9090
restart: always
volumes:
- - ./prometheus.yml:/etc/prometheus/prometheus.yml
+ - ./config/prometheus.yml:/etc/prometheus/prometheus.yml
profiles:
- monitoring
grafana:
image: grafana/grafana-oss:latest
user: ""
- container_name: grafana-container
+ container_name: grafana
depends_on:
prometheus:
condition: service_started
ports:
- 3000:3000
volumes:
+ - ./config/grafana/provisioning/:/etc/grafana/provisioning/
+ - ./config/grafana/jvm-micrometer-dashboard.json:/var/lib/grafana/dashboards/jvm-micrometer-dashboard.json
- grafana:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
diff --git a/docs/schemas/policy-executor/ncmp-create-schema-1.0.0.json b/docs/schemas/policy-executor/ncmp-create-schema-1.0.0.json
index 2ec9daf949..4d98bc8632 100644
--- a/docs/schemas/policy-executor/ncmp-create-schema-1.0.0.json
+++ b/docs/schemas/policy-executor/ncmp-create-schema-1.0.0.json
@@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
- "$id": "urn:cps:org.onap.cps.ncmp.policy-executor:ncmp-create-schema:1.0.0",
+ "$id": "urn:cps:org.onap.cps.ncmp.policy-executor.ncmp-create-schema:1.0.0",
"$ref": "#/definitions/NcmpCreate",
"definitions": {
"NcmpCreate": {
diff --git a/docs/schemas/policy-executor/ncmp-delete-schema-1.0.0.json b/docs/schemas/policy-executor/ncmp-delete-schema-1.0.0.json
index 5df0325e39..1246d9d815 100644
--- a/docs/schemas/policy-executor/ncmp-delete-schema-1.0.0.json
+++ b/docs/schemas/policy-executor/ncmp-delete-schema-1.0.0.json
@@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
- "$id": "urn:cps:org.onap.cps.ncmp.policy-executor:ncmp-delete-schema:1.0.0",
+ "$id": "urn:cps:org.onap.cps.ncmp.policy-executor.ncmp-delete-schema:1.0.0",
"$ref": "#/definitions/NcmpDelete",
"definitions": {
"NcmpDelete": {
diff --git a/docs/schemas/policy-executor/ncmp-patch-schema-1.0.0.json b/docs/schemas/policy-executor/ncmp-patch-schema-1.0.0.json
index e26c244c94..4917aea146 100644
--- a/docs/schemas/policy-executor/ncmp-patch-schema-1.0.0.json
+++ b/docs/schemas/policy-executor/ncmp-patch-schema-1.0.0.json
@@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
- "$id": "urn:cps:org.onap.cps.ncmp.policy-executor:ncmp-patch-schema:1.0.0",
+ "$id": "urn:cps:org.onap.cps.ncmp.policy-executor.ncmp-patch-schema:1.0.0",
"$ref": "#/definitions/NcmpPatch",
"definitions": {
"NcmpPatch": {
diff --git a/docs/schemas/policy-executor/ncmp-update-schema-1.0.0.json b/docs/schemas/policy-executor/ncmp-update-schema-1.0.0.json
index 0a497e38c5..831526cd52 100644
--- a/docs/schemas/policy-executor/ncmp-update-schema-1.0.0.json
+++ b/docs/schemas/policy-executor/ncmp-update-schema-1.0.0.json
@@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
- "$id": "urn:cps:org.onap.cps.ncmp.policy-executor:ncmp-update-schema:1.0.0",
+ "$id": "urn:cps:org.onap.cps.ncmp.policy-executor.ncmp-update-schema:1.0.0",
"$ref": "#/definitions/NcmpUpdate",
"definitions": {
"NcmpUpdate": {
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 5e46e95a0c..bd53c4ea13 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
@@ -46,6 +46,7 @@ import org.onap.cps.spi.utils.SessionManager
import org.onap.cps.utils.ContentType
import org.onap.cps.utils.JsonObjectMapper
import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
@@ -125,12 +126,19 @@ abstract class CpsIntegrationSpecBase extends Specification {
@Autowired
AlternateIdMatcher alternateIdMatcher
+
+ @Value('${ncmp.policy-executor.server.port:8080}')
+ private String policyServerPort;
+
MockWebServer mockDmiServer1 = new MockWebServer()
MockWebServer mockDmiServer2 = new MockWebServer()
+ MockWebServer mockPolicyServer = new MockWebServer()
DmiDispatcher dmiDispatcher1 = new DmiDispatcher()
DmiDispatcher dmiDispatcher2 = new DmiDispatcher()
+ PolicyDispatcher policyDispatcher = new PolicyDispatcher();
+
def DMI1_URL = null
def DMI2_URL = null
@@ -155,13 +163,18 @@ abstract class CpsIntegrationSpecBase extends Specification {
mockDmiServer2.setDispatcher(dmiDispatcher2)
mockDmiServer2.start()
+ mockPolicyServer.setDispatcher(policyDispatcher)
+ mockPolicyServer.start(Integer.valueOf(policyServerPort))
+
DMI1_URL = String.format("http://%s:%s", mockDmiServer1.getHostName(), mockDmiServer1.getPort())
DMI2_URL = String.format("http://%s:%s", mockDmiServer2.getHostName(), mockDmiServer2.getPort())
+
}
def cleanup() {
mockDmiServer1.shutdown()
mockDmiServer2.shutdown()
+ mockPolicyServer.shutdown()
}
def static readResourceDataFile(filename) {
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy
index fcc23db782..35a7b6a7c2 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/DmiDispatcher.groovy
@@ -20,18 +20,18 @@
package org.onap.cps.integration.base
-import static org.onap.cps.integration.base.CpsIntegrationSpecBase.readResourceDataFile
-
import groovy.json.JsonSlurper
-import java.util.regex.Matcher
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.RecordedRequest
-import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteRequest
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
+import java.util.regex.Matcher
+
+import static org.onap.cps.integration.base.CpsIntegrationSpecBase.readResourceDataFile
+
/**
* This class simulates responses from the DMI server in NCMP integration tests.
*
@@ -117,32 +117,32 @@ class DmiDispatcher extends Dispatcher {
return mockResponseWithBody(HttpStatus.OK, response)
}
- private getModuleReferencesResponse(cmHandleId) {
+ def getModuleReferencesResponse(cmHandleId) {
def moduleReferences = '{"schemas":[' + getModuleNamesForCmHandle(cmHandleId).collect {
MODULE_REFERENCES_RESPONSE_TEMPLATE.replaceAll("<MODULE_NAME>", it)
}.join(',') + ']}'
return mockResponseWithBody(HttpStatus.OK, moduleReferences)
}
- private getModuleResourcesResponse(cmHandleId) {
+ def getModuleResourcesResponse(cmHandleId) {
def moduleResources = '[' + getModuleNamesForCmHandle(cmHandleId).collect {
MODULE_RESOURCES_RESPONSE_TEMPLATE.replaceAll("<MODULE_NAME>", it)
}.join(',') + ']'
return mockResponseWithBody(HttpStatus.OK, moduleResources)
}
- private getModuleNamesForCmHandle(cmHandleId) {
+ def getModuleNamesForCmHandle(cmHandleId) {
if (!moduleNamesPerCmHandleId.containsKey(cmHandleId)) {
throw new IllegalArgumentException('Mock DMI has no modules configured for ' + cmHandleId)
}
return moduleNamesPerCmHandleId.get(cmHandleId)
}
- private static mockResponse(status) {
+ def static mockResponse(status) {
return new MockResponse().setResponseCode(status.value())
}
- private static mockResponseWithBody(status, responseBody) {
+ def static mockResponseWithBody(status, responseBody) {
return new MockResponse()
.setResponseCode(status.value())
.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy
new file mode 100644
index 0000000000..27e7563e61
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/PolicyDispatcher.groovy
@@ -0,0 +1,74 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.integration.base
+
+
+import okhttp3.mockwebserver.Dispatcher
+import okhttp3.mockwebserver.MockResponse
+import okhttp3.mockwebserver.RecordedRequest
+import org.springframework.http.HttpHeaders
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper
+
+/**
+ * This class simulates responses from the Policy Execution server in NCMP integration tests.
+ */
+class PolicyDispatcher extends Dispatcher {
+
+ def objectMapper = new ObjectMapper()
+ def expectedAuthorizationToken = 'ABC'
+ def allowAll = true; // Prevents legacy test being affected
+
+ @Override
+ MockResponse dispatch(RecordedRequest recordedRequest) {
+
+ if (!allowAll && !recordedRequest.getHeader('Authorization').contains(expectedAuthorizationToken)) {
+ return new MockResponse().setResponseCode(401)
+ }
+
+ if (recordedRequest.path != '/v1/execute') {
+ return new MockResponse().setResponseCode(400)
+ }
+
+ def body = objectMapper.readValue(recordedRequest.getBody().readUtf8(), Map.class)
+ def targetIdentifier = body.get('requests').get(0).get('data').get('targetIdentifier')
+ def responseAsMap = [:]
+ responseAsMap.put('decisionId',1)
+ if (allowAll || targetIdentifier == 'fdn1') {
+ responseAsMap.put('decision','allow')
+ responseAsMap.put('message','')
+ } else {
+ responseAsMap.put('decision','deny')
+ responseAsMap.put('message','I only like fdn1')
+ }
+ def responseAsString = objectMapper.writeValueAsString(responseAsMap)
+
+ return mockResponseWithBody(HttpStatus.OK, responseAsString)
+ }
+
+ static mockResponseWithBody(status, responseBody) {
+ return new MockResponse()
+ .setResponseCode(status.value())
+ .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
+ .setBody(responseBody)
+ }
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
index 69598a0604..5c2a4fc665 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/cps/QueryServiceIntegrationSpec.groovy
@@ -271,7 +271,6 @@ class QueryServiceIntegrationSpec extends FunctionalSpecBase {
'ancestor with parent list' | '//books/ancestor::bookstore/categories' || ["/bookstore/categories[@code='1']", "/bookstore/categories[@code='2']", "/bookstore/categories[@code='3']", "/bookstore/categories[@code='4']", "/bookstore/categories[@code='5']"]
'ancestor with parent list element' | '//books/ancestor::bookstore/categories[@code="2"]' || ["/bookstore/categories[@code='2']"]
'ancestor combined with text condition' | '//books/title[text()="Matilda"]/ancestor::bookstore' || ["/bookstore"]
- 'ancestor same as target type' | '//books/title[text()="Matilda"]/ancestor::books' || ["/bookstore/categories[@code='1']/books[@title='Matilda']"]
}
def 'Cps Path query across anchors with #scenario descendants.'() {
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy
new file mode 100644
index 0000000000..99f245ae8c
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/PolicyExecutorIntegrationSpec.groovy
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.integration.functional.ncmp
+
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.springframework.http.HttpHeaders
+import org.springframework.http.MediaType
+
+import static org.springframework.http.HttpMethod.POST
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request
+
+class PolicyExecutorIntegrationSpec extends CpsIntegrationSpecBase {
+
+ def setup() {
+ // Enable mocked policy executor logic
+ policyDispatcher.allowAll = false;
+ //minimum setup for 2 cm handles with alternate ids
+ dmiDispatcher1.moduleNamesPerCmHandleId = ['ch-1': [], 'ch-2': []]
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, 'fdn1')
+ registerCmHandle(DMI1_URL, 'ch-2', NO_MODULE_SET_TAG, 'fdn2')
+ }
+
+ def cleanup() {
+ deregisterCmHandle(DMI1_URL, 'ch-1')
+ deregisterCmHandle(DMI1_URL, 'ch-2')
+ }
+
+ def 'Policy Executor create request with #scenario.'() {
+ when: 'a pass-through write request is sent to NCMP'
+ def response = mvc.perform(request(POST, "/ncmp/v1/ch/$cmHandle/data/ds/ncmp-datastore:passthrough-running")
+ .queryParam('resourceIdentifier', 'my-resource-id')
+ .contentType(MediaType.APPLICATION_JSON)
+ .content('{ "some-json": "data" }')
+ .header(HttpHeaders.AUTHORIZATION, authorization))
+ .andReturn().response
+ then: 'the expected status code is returned'
+ response.getStatus() == execpectedStatusCode
+ where: 'following parameters are used'
+ scenario | cmHandle | authorization || execpectedStatusCode
+ 'accepted cm handle' | 'ch-1' | 'mock expects "ABC"' || 201
+ 'un-accepted cm handle' | 'ch-2' | 'mock expects "ABC"' || 409
+ 'invalid authorization' | 'ch-1' | 'something else' || 500
+ }
+
+}
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 33973e547b..1e1af556f1 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
@@ -41,7 +41,7 @@ class RestApiSpec extends CpsIntegrationSpecBase {
'ch-3': ['M1', 'M3']
]
when: 'a POST request is made to register the CM Handles'
- def requestBody = '{"dmiPlugin":"'+DMI1_URL+'","createdCmHandles":[{"cmHandle":"ch-1"},{"cmHandle":"ch-2"},{"cmHandle":"ch-3"}]}'
+ 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())
then: 'CM-handles go to READY state'
@@ -76,6 +76,27 @@ class RestApiSpec extends CpsIntegrationSpecBase {
'M3' || ['ch-3']
}
+ def 'Search for CM Handles using Cps Path Query.'() {
+ given: 'a JSON request body containing search parameter'
+ def requestBodyWithSearchCondition = """{
+ "cmHandleQueryParameters": [
+ {
+ "conditionName": "cmHandleWithCpsPath",
+ "conditionParameters": [ {"cpsPath" : "%s"} ]
+ }
+ ]
+ }""".formatted(cpsPath)
+ expect: "a search for cps path ${cpsPath} returns expected CM handles"
+ mvc.perform(post('/ncmp/v1/ch/id-searches').contentType(MediaType.APPLICATION_JSON).content(requestBodyWithSearchCondition))
+ .andExpect(status().is2xxSuccessful())
+ .andExpect(jsonPath('$[*]', containsInAnyOrder(expectedCmHandles.toArray())))
+ .andExpect(jsonPath('$', hasSize(expectedCmHandles.size())));
+ where:
+ scenario | cpsPath || expectedCmHandles
+ 'All Ready CM handles' | "//state[@cm-handle-state='READY']" || ['ch-1', 'ch-2', 'ch-3']
+ 'Having Alternate ID alt-3' | "//cm-handles[@alternate-id='alt-3']" || ['ch-3']
+ }
+
def 'De-register CM handles using REST API.'() {
when: 'a POST request is made to deregister the CM Handle'
def requestBody = '{"dmiPlugin":"'+DMI1_URL+'", "removedCmHandles": ["ch-1", "ch-2", "ch-3"]}'
diff --git a/integration-test/src/test/resources/application.yml b/integration-test/src/test/resources/application.yml
index fefae345e6..760dad01af 100644
--- a/integration-test/src/test/resources/application.yml
+++ b/integration-test/src/test/resources/application.yml
@@ -213,6 +213,20 @@ ncmp:
init:
mode: ALWAYS
+ policy-executor:
+ enabled: true
+ server:
+ address: http://localhost
+ port: 8790
+ httpclient:
+ all-services:
+ maximumInMemorySizeInMegabytes: 1
+ maximumConnectionsTotal: 10
+ pendingAcquireMaxCount: 10
+ connectionTimeoutInSeconds: 30
+ readTimeoutInSeconds: 30
+ writeTimeoutInSeconds: 30
+
hazelcast:
cluster-name: cps-and-ncmp-test-caches
mode:
diff --git a/k6-tests/install-deps.sh b/k6-tests/install-deps.sh
new file mode 100755
index 0000000000..bb5deb93dd
--- /dev/null
+++ b/k6-tests/install-deps.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+#
+# Copyright 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.
+#
+
+echo "---> install-deps.sh"
+echo "Installing dependencies"
+
+# Create directory for downloaded binaries.
+mkdir -p bin
+touch bin/.gitignore
+
+# Add it to the PATH, so downloaded versions will be used.
+export PATH="$(pwd)/bin:$PATH"
+
+# Download docker-compose.
+if [ ! -x bin/docker-compose ]; then
+ echo " Downloading docker-compose"
+ curl -s -L https://github.com/docker/compose/releases/download/v2.29.2/docker-compose-linux-x86_64 > bin/docker-compose
+ chmod +x bin/docker-compose
+else
+ echo " docker-compose already installed"
+fi
+docker-compose version
+
+# Download k6 with kafka extension.
+if [ ! -x bin/k6 ]; then
+ echo " Downloading k6 with kafka extension"
+ curl -s -L https://github.com/mostafa/xk6-kafka/releases/download/v0.26.0/xk6-kafka_v0.26.0_linux_amd64.tar.gz | tar -xz
+ mv dist/xk6-kafka_v0.26.0_linux_amd64 bin/k6 && rmdir dist
+ chmod +x bin/k6
+else
+ echo " k6 already installed"
+fi
+k6 --version
diff --git a/k6-tests/ncmp/common/cmhandle-crud.js b/k6-tests/ncmp/common/cmhandle-crud.js
index 88ecdb45b8..7fab62abd8 100644
--- a/k6-tests/ncmp/common/cmhandle-crud.js
+++ b/k6-tests/ncmp/common/cmhandle-crud.js
@@ -18,35 +18,42 @@
* ============LICENSE_END=========================================================
*/
-import http from 'k6/http';
-import { check, sleep } from 'k6';
-import { NCMP_BASE_URL, DMI_PLUGIN_URL, TOTAL_CM_HANDLES, MODULE_SET_TAGS, REGISTRATION_BATCH_SIZE, CONTENT_TYPE_JSON_PARAM, makeBatchOfCmHandleIds } from './utils.js';
+import { sleep } from 'k6';
+import { performPostRequest, NCMP_BASE_URL, DMI_PLUGIN_URL, TOTAL_CM_HANDLES, MODULE_SET_TAGS
+} from './utils.js';
import { executeCmHandleIdSearch } from './search-base.js';
-export function registerAllCmHandles() {
- forEachBatchOfCmHandles(createCmHandles);
- waitForAllCmHandlesToBeReady();
+export function createCmHandles(cmHandleIds) {
+ const url = `${NCMP_BASE_URL}/ncmpInventory/v1/ch`;
+ const payload = JSON.stringify(createCmHandlePayload(cmHandleIds));
+ return performPostRequest(url, payload, 'createCmHandles');
}
-export function deregisterAllCmHandles() {
- forEachBatchOfCmHandles(deleteCmHandles);
+export function deleteCmHandles(cmHandleIds) {
+ const url = `${NCMP_BASE_URL}/ncmpInventory/v1/ch`;
+ const payload = JSON.stringify({
+ "dmiPlugin": DMI_PLUGIN_URL,
+ "removedCmHandles": cmHandleIds,
+ });
+ return performPostRequest(url, payload, 'deleteCmHandles');
}
-function forEachBatchOfCmHandles(functionToExecute) {
- const TOTAL_BATCHES = Math.ceil(TOTAL_CM_HANDLES / REGISTRATION_BATCH_SIZE);
- for (let batchNumber = 0; batchNumber < TOTAL_BATCHES; batchNumber++) {
- const nextBatchOfCmHandleIds = makeBatchOfCmHandleIds(REGISTRATION_BATCH_SIZE, batchNumber);
- functionToExecute(nextBatchOfCmHandleIds);
- }
+export function waitForAllCmHandlesToBeReady() {
+ const POLLING_INTERVAL_SECONDS = 5;
+ let cmHandlesReady = 0;
+ do {
+ sleep(POLLING_INTERVAL_SECONDS);
+ cmHandlesReady = getNumberOfReadyCmHandles();
+ console.log(`${cmHandlesReady}/${TOTAL_CM_HANDLES} CM handles are READY`);
+ } while (cmHandlesReady < TOTAL_CM_HANDLES);
}
-function createCmHandles(cmHandleIds) {
- const url = `${NCMP_BASE_URL}/ncmpInventory/v1/ch`;
- const payload = {
+function createCmHandlePayload(cmHandleIds) {
+ return {
"dmiPlugin": DMI_PLUGIN_URL,
"createdCmHandles": cmHandleIds.map((cmHandleId, index) => ({
"cmHandle": cmHandleId,
- "alternateId": `alt-${cmHandleId}`,
+ "alternateId": cmHandleId.replace('ch-', 'alt-'),
"moduleSetTag": MODULE_SET_TAGS[index % MODULE_SET_TAGS.length],
"cmHandleProperties": {"neType": "RadioNode"},
"publicCmHandleProperties": {
@@ -56,30 +63,6 @@ function createCmHandles(cmHandleIds) {
}
})),
};
- const response = http.post(url, JSON.stringify(payload), CONTENT_TYPE_JSON_PARAM);
- check(response, { 'create CM-handles status equals 200': (r) => r.status === 200 });
- return response;
-}
-
-function deleteCmHandles(cmHandleIds) {
- const url = `${NCMP_BASE_URL}/ncmpInventory/v1/ch`;
- const payload = {
- "dmiPlugin": DMI_PLUGIN_URL,
- "removedCmHandles": cmHandleIds,
- };
- const response = http.post(url, JSON.stringify(payload), CONTENT_TYPE_JSON_PARAM);
- check(response, { 'delete CM-handles status equals 200': (r) => r.status === 200 });
- return response;
-}
-
-function waitForAllCmHandlesToBeReady() {
- const POLLING_INTERVAL_SECONDS = 5;
- let cmHandlesReady = 0;
- do {
- sleep(POLLING_INTERVAL_SECONDS);
- cmHandlesReady = getNumberOfReadyCmHandles();
- console.log(`${cmHandlesReady}/${TOTAL_CM_HANDLES} CM handles are READY`);
- } while (cmHandlesReady < TOTAL_CM_HANDLES);
}
function getNumberOfReadyCmHandles() {
diff --git a/k6-tests/ncmp/common/passthrough-crud.js b/k6-tests/ncmp/common/passthrough-crud.js
index 5617f9d093..0cd96ad64d 100644
--- a/k6-tests/ncmp/common/passthrough-crud.js
+++ b/k6-tests/ncmp/common/passthrough-crud.js
@@ -18,47 +18,37 @@
* ============LICENSE_END=========================================================
*/
-import http from 'k6/http';
+import { randomIntBetween } from 'https://jslib.k6.io/k6-utils/1.2.0/index.js';
import {
- CONTENT_TYPE_JSON_PARAM,
- getRandomCmHandleId,
+ performPostRequest,
+ performGetRequest,
NCMP_BASE_URL,
- TOPIC_DATA_OPERATIONS_BATCH_READ
+ TOPIC_DATA_OPERATIONS_BATCH_READ,
+ TOTAL_CM_HANDLES
} from './utils.js';
-export function passthroughRead() {
- const cmHandleId = getRandomCmHandleId();
+export function passthroughRead(useAlternateId) {
+ const cmHandleReference = getRandomCmHandleReference(useAlternateId);
const resourceIdentifier = 'my-resource-identifier';
- const includeDescendants = true;
const datastoreName = 'ncmp-datastore:passthrough-operational';
- const url = `${NCMP_BASE_URL}/ncmp/v1/ch/${cmHandleId}/data/ds/${datastoreName}?resourceIdentifier=${resourceIdentifier}&include-descendants=${includeDescendants}`
- const response = http.get(url);
- return response;
-}
-
-export function passthroughReadWithAltId() {
- const cmHandleId = getRandomCmHandleId();
- const resourceIdentifier = 'my-resource-identifier';
const includeDescendants = true;
- const datastoreName = 'ncmp-datastore:passthrough-operational';
- const url = `${NCMP_BASE_URL}/ncmp/v1/ch/alt-${cmHandleId}/data/ds/${datastoreName}?resourceIdentifier=${resourceIdentifier}&include-descendants=${includeDescendants}`
- const response = http.get(url);
- return response;
+ const url = generatePassthroughUrl(cmHandleReference, datastoreName, resourceIdentifier, includeDescendants);
+ return performGetRequest(url, 'passthroughRead');
}
-export function passthroughWrite() {
- const cmHandleId = getRandomCmHandleId();
+export function passthroughWrite(useAlternateId) {
+ const cmHandleReference = getRandomCmHandleReference(useAlternateId);
const resourceIdentifier = 'my-resource-identifier';
const datastoreName = 'ncmp-datastore:passthrough-running';
- const url = `${NCMP_BASE_URL}/ncmp/v1/ch/${cmHandleId}/data/ds/${datastoreName}?resourceIdentifier=${resourceIdentifier}`
- const body = `{"neType": "BaseStation"}`
- const response = http.post(url, JSON.stringify(body), CONTENT_TYPE_JSON_PARAM);
- return response;
+ const includeDescendants = false;
+ const url = generatePassthroughUrl(cmHandleReference, datastoreName, resourceIdentifier, includeDescendants);
+ const payload = JSON.stringify({"neType": "BaseStation"});
+ return performPostRequest(url, payload, 'passthroughWrite');
}
export function batchRead(cmHandleIds) {
- const url = `${NCMP_BASE_URL}/ncmp/v1/data?topic=${TOPIC_DATA_OPERATIONS_BATCH_READ}`
- const payload = {
+ const url = `${NCMP_BASE_URL}/ncmp/v1/data?topic=${TOPIC_DATA_OPERATIONS_BATCH_READ}`;
+ const payload = JSON.stringify({
"operations": [
{
"resourceIdentifier": "parent/child",
@@ -69,7 +59,16 @@ export function batchRead(cmHandleIds) {
"operation": "read"
}
]
- };
- const response = http.post(url, JSON.stringify(payload), CONTENT_TYPE_JSON_PARAM);
- return response;
+ });
+ return performPostRequest(url, payload, 'batchRead');
+}
+
+function getRandomCmHandleReference(useAlternateId) {
+ const prefix = useAlternateId ? 'alt' : 'ch';
+ return `${prefix}-${randomIntBetween(1, TOTAL_CM_HANDLES)}`;
+}
+
+function generatePassthroughUrl(cmHandleReference, datastoreName, resourceIdentifier, includeDescendants) {
+ const descendantsParam = includeDescendants ? `&include-descendants=${includeDescendants}` : '';
+ return `${NCMP_BASE_URL}/ncmp/v1/ch/${cmHandleReference}/data/ds/${datastoreName}?resourceIdentifier=${resourceIdentifier}${descendantsParam}`;
} \ No newline at end of file
diff --git a/k6-tests/ncmp/common/search-base.js b/k6-tests/ncmp/common/search-base.js
index bc964856af..a6424fe5d0 100644
--- a/k6-tests/ncmp/common/search-base.js
+++ b/k6-tests/ncmp/common/search-base.js
@@ -18,27 +18,7 @@
* ============LICENSE_END=========================================================
*/
-import http from 'k6/http';
-import { NCMP_BASE_URL, CONTENT_TYPE_JSON_PARAM } from './utils.js';
-
-const SEARCH_PARAMETERS_PER_SCENARIO = {
- 'module': {
- 'cmHandleQueryParameters': [
- {
- 'conditionName': 'hasAllModules',
- 'conditionParameters': [{'moduleName': 'ietf-yang-types-1'}]
- }
- ]
- },
- 'readyCmHandles': {
- 'cmHandleQueryParameters': [
- {
- 'conditionName': 'cmHandleWithCpsPath',
- 'conditionParameters': [{'cpsPath': '//state[@cm-handle-state="READY"]'}]
- }
- ]
- }
-};
+import {performPostRequest, NCMP_BASE_URL} from './utils.js';
export function executeCmHandleSearch(scenario) {
return executeSearchRequest('searches', scenario);
@@ -52,6 +32,28 @@ function executeSearchRequest(searchType, scenario) {
const searchParameters = SEARCH_PARAMETERS_PER_SCENARIO[scenario];
const payload = JSON.stringify(searchParameters);
const url = `${NCMP_BASE_URL}/ncmp/v1/ch/${searchType}`;
- const response = http.post(url, payload, CONTENT_TYPE_JSON_PARAM);
- return response;
+ return performPostRequest(url, payload, searchType);
}
+
+const SEARCH_PARAMETERS_PER_SCENARIO = {
+ "module-and-properties": {
+ "cmHandleQueryParameters": [
+ {
+ "conditionName": "hasAllModules",
+ "conditionParameters": [{"moduleName": "ietf-yang-types"}]
+ },
+ {
+ "conditionName": "hasAllProperties",
+ "conditionParameters": [{"Color": "yellow"}]
+ }
+ ]
+ },
+ "readyCmHandles": {
+ "cmHandleQueryParameters": [
+ {
+ "conditionName": "cmHandleWithCpsPath",
+ "conditionParameters": [{"cpsPath": "//state[@cm-handle-state='READY']"}]
+ }
+ ]
+ }
+};
diff --git a/k6-tests/ncmp/common/utils.js b/k6-tests/ncmp/common/utils.js
index 294789f940..e6d9c92ee6 100644
--- a/k6-tests/ncmp/common/utils.js
+++ b/k6-tests/ncmp/common/utils.js
@@ -18,25 +18,19 @@
* ============LICENSE_END=========================================================
*/
+import http from 'k6/http';
export const NCMP_BASE_URL = 'http://localhost:8883';
export const DMI_PLUGIN_URL = 'http://ncmp-dmi-plugin-demo-and-csit-stub:8092';
export const TOTAL_CM_HANDLES = 20000;
export const REGISTRATION_BATCH_SIZE = 100;
export const READ_DATA_FOR_CM_HANDLE_DELAY_MS = 300; // must have same value as in docker-compose.yml
export const WRITE_DATA_FOR_CM_HANDLE_DELAY_MS = 670; // must have same value as in docker-compose.yml
-export const CONTENT_TYPE_JSON_PARAM = { headers: {'Content-Type': 'application/json'} };
+export const CONTENT_TYPE_JSON_PARAM = {'Content-Type': 'application/json'};
export const DATA_OPERATION_READ_BATCH_SIZE = 200;
export const TOPIC_DATA_OPERATIONS_BATCH_READ = 'topic-data-operations-batch-read';
export const KAFKA_BOOTSTRAP_SERVERS = ['localhost:9092'];
export const MODULE_SET_TAGS = ['tagA','tagB','tagC',' tagD']
-export function recordTimeInSeconds(functionToExecute) {
- const startTimeInMillis = Date.now();
- functionToExecute();
- const endTimeInMillis = Date.now();
- const totalTimeInSeconds = (endTimeInMillis - startTimeInMillis) / 1000.0;
- return totalTimeInSeconds;
-}
/**
* Generates a batch of CM-handle IDs based on batch size and number.
@@ -45,29 +39,59 @@ export function recordTimeInSeconds(functionToExecute) {
* @returns {string[]} Array of CM-handle IDs, for example ['ch-201', 'ch-202' ... 'ch-300']
*/
export function makeBatchOfCmHandleIds(batchSize, batchNumber) {
- const batchOfIds = [];
const startIndex = 1 + batchNumber * batchSize;
- for (let i = 0; i < batchSize; i++) {
- let cmHandleId = `ch-${startIndex + i}`;
- batchOfIds.push(cmHandleId);
- }
- return batchOfIds;
+ return Array.from({ length: batchSize }, (_, i) => `ch-${startIndex + i}`);
+}
+
+/**
+ * Helper function to perform POST requests with JSON payload and content type.
+ * @param {string} url - The URL to send the POST request to.
+ * @param {Object} payload - The JSON payload to send in the POST request.
+ * @param {string} metricTag - A tag for the metric endpoint.
+ * @returns {Object} The response from the HTTP POST request.
+ */
+export function performPostRequest(url, payload, metricTag) {
+ const metricTags = {
+ endpoint: metricTag
+ };
+
+ return http.post(url, payload, {
+ headers: CONTENT_TYPE_JSON_PARAM,
+ tags: metricTags
+ });
}
-export function getRandomCmHandleId() {
- return `ch-${Math.floor(Math.random() * TOTAL_CM_HANDLES) + 1}`;
+/**
+ * Helper function to perform GET requests with metric tags.
+ *
+ * This function sends an HTTP GET request to the specified URL and attaches
+ * a metric tag to the request, which is useful for monitoring and analytics.
+ *
+ * @param {string} url - The URL to which the GET request will be sent.
+ * @param {string} metricTag - A string representing the metric tag to associate with the request.
+ * This tag is used for monitoring and tracking the request.
+ * @returns {Object} The response from the HTTP GET request. The response includes the status code,
+ * headers, body, and other related information.
+ */
+export function performGetRequest(url, metricTag) {
+ const metricTags = {
+ endpoint: metricTag
+ };
+ return http.get(url, {tags: metricTags});
}
export function makeCustomSummaryReport(data, options) {
const summaryCsvLines = [
'#,Test Name,Unit,Limit,Actual',
+ makeSummaryCsvLine('0', 'HTTP request failures for all tests', 'rate of failed requests', 'http_req_failed', data, options),
makeSummaryCsvLine('1', 'Registration of CM-handles', 'CM-handles/second', 'cmhandles_created_per_second', data, options),
makeSummaryCsvLine('2', 'De-registration of CM-handles', 'CM-handles/second', 'cmhandles_deleted_per_second', data, options),
- makeSummaryCsvLine('3', 'CM-handle ID search with Module filter', 'milliseconds', 'http_req_duration{scenario:id_search_module}', data, options),
- makeSummaryCsvLine('4', 'CM-handle search with Module filter', 'milliseconds', 'http_req_duration{scenario:cm_search_module}', data, options),
+ makeSummaryCsvLine('3', 'CM-handle ID search with Module and Property filter', 'milliseconds', 'id_search_duration', data, options),
+ makeSummaryCsvLine('4', 'CM-handle search with Module and Property filter', 'milliseconds', 'cm_search_duration', data, options),
makeSummaryCsvLine('5a', 'NCMP overhead for Synchronous single CM-handle pass-through read', 'milliseconds', 'ncmp_overhead_passthrough_read', data, options),
makeSummaryCsvLine('5b', 'NCMP overhead for Synchronous single CM-handle pass-through read with alternate id', 'milliseconds', 'ncmp_overhead_passthrough_read_alt_id', data, options),
- makeSummaryCsvLine('6', 'NCMP overhead for Synchronous single CM-handle pass-through write', 'milliseconds', 'ncmp_overhead_passthrough_write', data, options),
+ makeSummaryCsvLine('6a', 'NCMP overhead for Synchronous single CM-handle pass-through write', 'milliseconds', 'ncmp_overhead_passthrough_write', data, options),
+ makeSummaryCsvLine('6b', 'NCMP overhead for Synchronous single CM-handle pass-through write with alternate id', 'milliseconds', 'ncmp_overhead_passthrough_write_alt_id', data, options),
makeSummaryCsvLine('7', 'Data operations batch read', 'events/second', 'data_operations_batch_read_cmhandles_per_second', data, options),
];
return summaryCsvLines.join('\n') + '\n';
diff --git a/k6-tests/ncmp/ncmp-kpi.js b/k6-tests/ncmp/ncmp-kpi.js
index f4a44dba68..1d084f21e3 100644
--- a/k6-tests/ncmp/ncmp-kpi.js
+++ b/k6-tests/ncmp/ncmp-kpi.js
@@ -19,23 +19,26 @@
*/
import { check } from 'k6';
-import { Gauge, Trend } from 'k6/metrics';
+import { Trend } from 'k6/metrics';
import { Reader } from 'k6/x/kafka';
import {
TOTAL_CM_HANDLES, READ_DATA_FOR_CM_HANDLE_DELAY_MS, WRITE_DATA_FOR_CM_HANDLE_DELAY_MS,
- makeCustomSummaryReport, recordTimeInSeconds, makeBatchOfCmHandleIds, DATA_OPERATION_READ_BATCH_SIZE,
- TOPIC_DATA_OPERATIONS_BATCH_READ, KAFKA_BOOTSTRAP_SERVERS
+ makeCustomSummaryReport, makeBatchOfCmHandleIds, DATA_OPERATION_READ_BATCH_SIZE,
+ TOPIC_DATA_OPERATIONS_BATCH_READ, KAFKA_BOOTSTRAP_SERVERS, REGISTRATION_BATCH_SIZE
} from './common/utils.js';
-import { registerAllCmHandles, deregisterAllCmHandles } from './common/cmhandle-crud.js';
+import { createCmHandles, deleteCmHandles, waitForAllCmHandlesToBeReady } from './common/cmhandle-crud.js';
import { executeCmHandleSearch, executeCmHandleIdSearch } from './common/search-base.js';
import { passthroughRead, passthroughReadWithAltId, passthroughWrite, batchRead } from './common/passthrough-crud.js';
-let cmHandlesCreatedPerSecondGauge = new Gauge('cmhandles_created_per_second');
-let cmHandlesDeletedPerSecondGauge = new Gauge('cmhandles_deleted_per_second');
+let cmHandlesCreatedPerSecondTrend = new Trend('cmhandles_created_per_second', false);
+let cmHandlesDeletedPerSecondTrend = new Trend('cmhandles_deleted_per_second', false);
let passthroughReadNcmpOverheadTrend = new Trend('ncmp_overhead_passthrough_read', true);
let passthroughReadNcmpOverheadTrendWithAlternateId = new Trend('ncmp_overhead_passthrough_read_alt_id', true);
let passthroughWriteNcmpOverheadTrend = new Trend('ncmp_overhead_passthrough_write', true);
-let dataOperationsBatchReadCmHandlePerSecondTrend = new Trend('data_operations_batch_read_cmhandles_per_second');
+let passthroughWriteNcmpOverheadTrendWithAlternateId = new Trend('ncmp_overhead_passthrough_write_alt_id', true);
+let idSearchDurationTrend = new Trend('id_search_duration', true);
+let cmSearchDurationTrend = new Trend('cm_search_duration', true);
+let dataOperationsBatchReadCmHandlePerSecondTrend = new Trend('data_operations_batch_read_cmhandles_per_second', false);
const reader = new Reader({
brokers: KAFKA_BOOTSTRAP_SERVERS,
@@ -45,37 +48,43 @@ const reader = new Reader({
const DURATION = '15m';
export const options = {
- setupTimeout: '6m',
+ setupTimeout: '8m',
teardownTimeout: '6m',
scenarios: {
passthrough_read: {
executor: 'constant-vus',
- exec: 'passthrough_read',
- vus: 9,
+ exec: 'executePassthroughReadScenario',
+ vus: 4,
duration: DURATION,
},
passthrough_read_alt_id: {
executor: 'constant-vus',
- exec: 'passthrough_read_alt_id',
- vus: 1,
+ exec: 'executePassthroughReadAltIdScenario',
+ vus: 4,
duration: DURATION,
},
passthrough_write: {
executor: 'constant-vus',
- exec: 'passthrough_write',
- vus: 10,
+ exec: 'executePassthroughWriteScenario',
+ vus: 4,
duration: DURATION,
},
- id_search_module: {
+ passthrough_write_alt_id: {
executor: 'constant-vus',
- exec: 'id_search_module',
- vus: 3,
+ exec: 'executePassthroughWriteAltIdScenario',
+ vus: 4,
duration: DURATION,
},
- cm_search_module: {
+ cm_handle_id_search: {
executor: 'constant-vus',
- exec: 'cm_search_module',
- vus: 3,
+ exec: 'executeCmHandleIdSearchScenario',
+ vus: 5,
+ duration: DURATION,
+ },
+ cm_handle_search: {
+ executor: 'constant-vus',
+ exec: 'executeCmHandleSearchScenario',
+ vus: 5,
duration: DURATION,
},
data_operation_send_async_http_request: {
@@ -96,69 +105,108 @@ export const options = {
}
},
thresholds: {
- 'cmhandles_created_per_second': ['value >= 22'],
- 'cmhandles_deleted_per_second': ['value >= 22'],
- 'ncmp_overhead_passthrough_read': ['avg <= 100'],
- 'ncmp_overhead_passthrough_read_alt_id': ['avg <= 100'],
- 'ncmp_overhead_passthrough_write': ['avg <= 100'],
- 'http_req_duration{scenario:id_search_module}': ['avg <= 625'],
- 'http_req_duration{scenario:cm_search_module}': ['avg <= 13000'],
- 'http_req_failed{scenario:id_search_module}': ['rate == 0'],
- 'http_req_failed{scenario:cm_search_module}': ['rate == 0'],
- 'http_req_failed{scenario:passthrough_read}': ['rate == 0'],
- 'http_req_failed{scenario:passthrough_write}': ['rate == 0'],
- 'http_req_failed{scenario:data_operation_send_async_http_request}': ['rate == 0'],
- 'kafka_reader_error_count{scenario:data_operation_consume_kafka_responses}': ['count == 0'],
+ 'http_req_failed': ['rate == 0'],
+ 'cmhandles_created_per_second': ['avg >= 22'],
+ 'cmhandles_deleted_per_second': ['avg >= 22'],
+ 'ncmp_overhead_passthrough_read': ['avg <= 40'],
+ 'ncmp_overhead_passthrough_write': ['avg <= 40'],
+ 'ncmp_overhead_passthrough_read_alt_id': ['avg <= 40'],
+ 'ncmp_overhead_passthrough_write_alt_id': ['avg <= 40'],
+ 'id_search_duration': ['avg <= 2000'],
+ 'cm_search_duration': ['avg <= 15000'],
'data_operations_batch_read_cmhandles_per_second': ['avg >= 150'],
},
};
export function setup() {
- const totalRegistrationTimeInSeconds = recordTimeInSeconds(registerAllCmHandles);
- cmHandlesCreatedPerSecondGauge.add(TOTAL_CM_HANDLES / totalRegistrationTimeInSeconds);
+ const startTimeInMillis = Date.now();
+
+ const TOTAL_BATCHES = Math.ceil(TOTAL_CM_HANDLES / REGISTRATION_BATCH_SIZE);
+ for (let batchNumber = 0; batchNumber < TOTAL_BATCHES; batchNumber++) {
+ const nextBatchOfCmHandleIds = makeBatchOfCmHandleIds(REGISTRATION_BATCH_SIZE, batchNumber);
+ const response = createCmHandles(nextBatchOfCmHandleIds);
+ check(response, { 'create CM-handles status equals 200': (r) => r.status === 200 });
+ }
+
+ waitForAllCmHandlesToBeReady();
+
+ const endTimeInMillis = Date.now();
+ const totalRegistrationTimeInSeconds = (endTimeInMillis - startTimeInMillis) / 1000.0;
+
+ cmHandlesCreatedPerSecondTrend.add(TOTAL_CM_HANDLES / totalRegistrationTimeInSeconds);
}
export function teardown() {
- const totalDeregistrationTimeInSeconds = recordTimeInSeconds(deregisterAllCmHandles);
- cmHandlesDeletedPerSecondGauge.add(TOTAL_CM_HANDLES / totalDeregistrationTimeInSeconds);
+ const startTimeInMillis = Date.now();
+
+ let DEREGISTERED_CM_HANDLES = 0
+ const TOTAL_BATCHES = Math.ceil(TOTAL_CM_HANDLES / REGISTRATION_BATCH_SIZE);
+ for (let batchNumber = 0; batchNumber < TOTAL_BATCHES; batchNumber++) {
+ const nextBatchOfCmHandleIds = makeBatchOfCmHandleIds(REGISTRATION_BATCH_SIZE, batchNumber);
+ const response = deleteCmHandles(nextBatchOfCmHandleIds);
+ if (response.error_code === 0) {
+ DEREGISTERED_CM_HANDLES += REGISTRATION_BATCH_SIZE
+ }
+ check(response, { 'delete CM-handles status equals 200': (r) => r.status === 200 });
+ }
+
+ const endTimeInMillis = Date.now();
+ const totalDeregistrationTimeInSeconds = (endTimeInMillis - startTimeInMillis) / 1000.0;
+
+ cmHandlesDeletedPerSecondTrend.add(DEREGISTERED_CM_HANDLES / totalDeregistrationTimeInSeconds);
+}
+
+export function executePassthroughReadScenario() {
+ const response = passthroughRead(false);
+ if (check(response, { 'passthrough read status equals 200': (r) => r.status === 200 })) {
+ const overhead = response.timings.duration - READ_DATA_FOR_CM_HANDLE_DELAY_MS;
+ passthroughReadNcmpOverheadTrend.add(overhead);
+ }
}
-export function passthrough_read() {
- const response = passthroughRead();
- check(response, { 'passthrough read status equals 200': (r) => r.status === 200 });
- const overhead = response.timings.duration - READ_DATA_FOR_CM_HANDLE_DELAY_MS;
- passthroughReadNcmpOverheadTrend.add(overhead);
+export function executePassthroughReadAltIdScenario() {
+ const response = passthroughRead(true);
+ if (check(response, { 'passthrough read with alternate Id status equals 200': (r) => r.status === 200 })) {
+ const overhead = response.timings.duration - READ_DATA_FOR_CM_HANDLE_DELAY_MS;
+ passthroughReadNcmpOverheadTrendWithAlternateId.add(overhead);
+ }
}
-export function passthrough_read_alt_id() {
- const response = passthroughReadWithAltId();
- check(response, { 'passthrough read with alternate Id status equals 200': (r) => r.status === 200 });
- const overhead = response.timings.duration - READ_DATA_FOR_CM_HANDLE_DELAY_MS;
- passthroughReadNcmpOverheadTrendWithAlternateId.add(overhead);
+export function executePassthroughWriteScenario() {
+ const response = passthroughWrite(false);
+ if (check(response, { 'passthrough write status equals 201': (r) => r.status === 201 })) {
+ const overhead = response.timings.duration - WRITE_DATA_FOR_CM_HANDLE_DELAY_MS;
+ passthroughWriteNcmpOverheadTrend.add(overhead);
+ }
}
-export function passthrough_write() {
- const response = passthroughWrite();
- check(response, { 'passthrough write status equals 201': (r) => r.status === 201 });
- const overhead = response.timings.duration - WRITE_DATA_FOR_CM_HANDLE_DELAY_MS;
- passthroughWriteNcmpOverheadTrend.add(overhead);
+export function executePassthroughWriteAltIdScenario() {
+ const response = passthroughWrite(true);
+ if (check(response, { 'passthrough write with alternate Id status equals 201': (r) => r.status === 201 })) {
+ const overhead = response.timings.duration - WRITE_DATA_FOR_CM_HANDLE_DELAY_MS;
+ passthroughWriteNcmpOverheadTrendWithAlternateId.add(overhead);
+ }
}
-export function id_search_module() {
- const response = executeCmHandleIdSearch('module');
- check(response, { 'module ID search status equals 200': (r) => r.status === 200 });
- check(JSON.parse(response.body), { 'module ID search returned expected CM-handles': (arr) => arr.length === TOTAL_CM_HANDLES });
+export function executeCmHandleIdSearchScenario() {
+ const response = executeCmHandleIdSearch('module-and-properties');
+ if (check(response, { 'CM handle ID search status equals 200': (r) => r.status === 200 })
+ && check(response, { 'CM handle ID search returned expected CM-handles': (r) => r.json('#') === TOTAL_CM_HANDLES })) {
+ idSearchDurationTrend.add(response.timings.duration);
+ }
}
-export function cm_search_module() {
- const response = executeCmHandleSearch('module');
- check(response, { 'module search status equals 200': (r) => r.status === 200 });
- check(JSON.parse(response.body), { 'module search returned expected CM-handles': (arr) => arr.length === TOTAL_CM_HANDLES });
+export function executeCmHandleSearchScenario() {
+ const response = executeCmHandleSearch('module-and-properties');
+ if (check(response, { 'CM handle search status equals 200': (r) => r.status === 200 })
+ && check(response, { 'CM handle search returned expected CM-handles': (r) => r.json('#') === TOTAL_CM_HANDLES })) {
+ cmSearchDurationTrend.add(response.timings.duration);
+ }
}
export function data_operation_send_async_http_request() {
- const nextBatchOfCmHandleIds = makeBatchOfCmHandleIds(DATA_OPERATION_READ_BATCH_SIZE,1);
- const response = batchRead(nextBatchOfCmHandleIds)
+ const nextBatchOfCmHandleIds = makeBatchOfCmHandleIds(DATA_OPERATION_READ_BATCH_SIZE, 0);
+ const response = batchRead(nextBatchOfCmHandleIds);
check(response, { 'data operation batch read status equals 200': (r) => r.status === 200 });
}
diff --git a/k6-tests/ncmp/run-all-tests.sh b/k6-tests/ncmp/run-all-tests.sh
index 2db32ecd76..1fa661a472 100755
--- a/k6-tests/ncmp/run-all-tests.sh
+++ b/k6-tests/ncmp/run-all-tests.sh
@@ -19,7 +19,9 @@ pushd "$(dirname "$0")" >/dev/null || exit 1
number_of_failures=0
echo "Running K6 performance tests..."
-k6 --quiet run ncmp-kpi.js > summary.csv || ((number_of_failures++))
+
+# Redirecting stderr to /dev/null to prevent large log files
+k6 --quiet run ncmp-kpi.js > summary.csv 2>/dev/null || ((number_of_failures++))
if [ -f summary.csv ]; then
diff --git a/k6-tests/run-k6-tests.sh b/k6-tests/run-k6-tests.sh
index 9b8747b1ff..b1ad38911a 100755
--- a/k6-tests/run-k6-tests.sh
+++ b/k6-tests/run-k6-tests.sh
@@ -31,6 +31,10 @@ trap on_exit EXIT
pushd "$(dirname "$0")" || exit 1
+# Install needed dependencies.
+source install-deps.sh
+
+# Run k6 test suite.
./setup.sh
./ncmp/run-all-tests.sh
NCMP_RESULT=$?
diff --git a/k6-tests/teardown.sh b/k6-tests/teardown.sh
index 1b4d721a23..7693dc03a4 100755
--- a/k6-tests/teardown.sh
+++ b/k6-tests/teardown.sh
@@ -19,4 +19,10 @@ echo '================================== docker info =========================='
docker ps -a
echo 'Stopping, Removing containers and volumes...'
-docker-compose -f ../docker-compose/docker-compose.yml --profile dmi-stub down --volumes
+docker_compose_cmd="docker-compose -f ../docker-compose/docker-compose.yml --profile dmi-stub down --volumes"
+# Set an environment variable CLEAN_DOCKER_IMAGES=1 to also remove docker images when done (used on jenkins job)
+if [ "${CLEAN_DOCKER_IMAGES:-0}" -eq 1 ]; then
+ $docker_compose_cmd --rmi all
+else
+ $docker_compose_cmd
+fi
diff --git a/spotbugs/src/main/resources/spotbugs-exclude.xml b/spotbugs/src/main/resources/spotbugs-exclude.xml
index 78f61d290e..23e62cdbc7 100644
--- a/spotbugs/src/main/resources/spotbugs-exclude.xml
+++ b/spotbugs/src/main/resources/spotbugs-exclude.xml
@@ -36,6 +36,7 @@
<Bug pattern="NP_NULL_PARAM_DEREF" />
<Bug pattern="NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE" />
<Bug pattern="RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" />
+ <Bug pattern="NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE" />
<!-- https://stackoverflow.com/a/34674776. Doesn't detect Lombok All Args Constructor variables being used with map get key and value, which can lead to spotbugs being detected
on used fields -->