Merge "cps-core deployment document"
authorToine Siebelink <toine.siebelink@est.tech>
Tue, 12 Oct 2021 16:02:31 +0000 (16:02 +0000)
committerGerrit Code Review <gerrit@onap.org>
Tue, 12 Oct 2021 16:02:31 +0000 (16:02 +0000)
32 files changed:
cps-application/src/main/resources/application.yml
cps-ncmp-rest/docs/openapi/components.yaml
cps-ncmp-rest/docs/openapi/ncmp-inventory.yml [new file with mode: 0755]
cps-ncmp-rest/docs/openapi/ncmp.yml [moved from cps-ncmp-rest/docs/openapi/ncmproxy.yml with 89% similarity]
cps-ncmp-rest/docs/openapi/openapi-inventory.yml [new file with mode: 0755]
cps-ncmp-rest/docs/openapi/openapi.yml
cps-ncmp-rest/pom.xml
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java [new file with mode: 0755]
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy [new file with mode: 0644]
cps-ncmp-rest/src/test/resources/application.yml
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operation/DmiOperations.java
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operation/DmiOperationsSpec.groovy
cps-ncmp-service/src/test/resources/cmHandleModules.json
docker-compose/README.md
docs/_static/cps-r8-arch-diagram.png [deleted file]
docs/_static/cps-r9-arch-diagram.png [new file with mode: 0644]
docs/_static/star.png [new file with mode: 0644]
docs/admin-guide.rst
docs/api/swagger/ncmp/openapi-inventory.yaml [new file with mode: 0644]
docs/api/yang/dmiYangResource.yang [new file with mode: 0644]
docs/architecture.rst
docs/cps-path.rst
docs/design.rst
docs/index.rst
docs/modeling.rst
docs/overview.rst
docs/release-notes.rst

index 42addf1..6717d4e 100644 (file)
@@ -25,6 +25,7 @@ rest:
     api:\r
         cps-base-path: /cps/api\r
         ncmp-base-path: /ncmp\r
+        ncmp-inventory-base-path: /ncmpInventory\r
 \r
 spring:\r
     main:\r
@@ -93,10 +94,13 @@ springdoc:
               url: /api-docs/cps-core/openapi.yaml\r
             - name: cps-ncmp\r
               url: /api-docs/cps-ncmp/openapi.yaml\r
+            - name: cps-ncmp-inventory\r
+              url: /api-docs/cps-ncmp/openapi-inventory.yaml\r
+\r
 \r
 security:\r
     # comma-separated uri patterns which do not require authorization\r
-    permit-uri: /manage/**,/swagger-ui/**,/swagger-resources/**,/api-docs\r
+    permit-uri: /manage/**,/swagger-ui.html,/swagger-ui/**,/swagger-resources/**,/api-docs/**\r
     auth:\r
         username: ${CPS_USERNAME}\r
         password: ${CPS_PASSWORD}\r
index ffb8dde..d35919d 100644 (file)
@@ -104,13 +104,27 @@ components:
       schema:
         type: string
         default: /
-    resourceIdentifierInPath:
+    resourceIdentifierInQuery:
       name: resourceIdentifier
-      in: path
-      description: Resource identifier to get/set the resource data
+      in: query
+      description: The format of resource identifier depend on the associated DMI Plugin implementation. For ONAP DMI Plugin it will be RESTConf paths but it can really be anything.
       required: true
+      allowReserved: true
       schema:
         type: string
+      examples:
+        sample1:
+          value:
+            resourceIdentifier: \parent\child
+        sample2:
+          value:
+            resourceIdentifier: \parent\listElement[key=value]
+        sample3:
+          value:
+            resourceIdentifier: \parent\listElement[key=value]\grandChild
+        sample4:
+          value:
+            resourceIdentifier: parent=1,child=abc
     acceptParamInHeader:
       name: Accept
       in: header
@@ -119,21 +133,24 @@ components:
       schema:
         type: string
         enum: [ application/json, application/yang-data+json ]
-    fieldsParamInQuery:
-      name: fields
+    optionsParamInQuery:
+      name: options
       in: query
-      description: Fields parameter to filter resource
+      description: options parameter in query, it is mandatory to wrap key(s)=value(s) in parenthesis'()'.
       required: false
       schema:
         type: string
-    depthParamInQuery:
-      name: depth
-      in: query
-      description: Depth parameter for response
-      required: false
-      schema:
-        type: integer
-        minimum: 1
+      allowReserved: true
+      examples:
+        sample1:
+          value:
+            options: (key1=value1,key2=value2)
+        sample2:
+          value:
+            options: (key1=value1,key2=value1/value2)
+        sample3:
+          value:
+            options: (key1=10,key2=value2,key3=[val31;val32])
     contentParamInHeader:
       name: Content-Type
       in: header
diff --git a/cps-ncmp-rest/docs/openapi/ncmp-inventory.yml b/cps-ncmp-rest/docs/openapi/ncmp-inventory.yml
new file mode 100755 (executable)
index 0000000..b0a50aa
--- /dev/null
@@ -0,0 +1,40 @@
+#  ============LICENSE_START=======================================================
+#  Copyright (C) 2021 Bell Canada
+#  ================================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+#  SPDX-License-Identifier: Apache-2.0
+#  ============LICENSE_END=========================================================
+
+updateDmiRegistration:
+  post:
+    description: Register a DMI Plugin with any new, updated or removed CM Handles.
+    tags:
+      - network-cm-proxy-inventory
+    summary: DMI notifies NCMP of new CM Handles
+    operationId: updateDmiPluginRegistration
+    requestBody:
+      required: true
+      content:
+        application/json:
+          schema:
+            $ref: 'components.yaml#/components/schemas/RestDmiPluginRegistration'
+    responses:
+      201:
+        $ref: 'components.yaml#/components/responses/Created'
+      400:
+        $ref: 'components.yaml#/components/responses/BadRequest'
+      401:
+        $ref: 'components.yaml#/components/responses/Unauthorized'
+      403:
+        $ref: 'components.yaml#/components/responses/Forbidden'
similarity index 89%
rename from cps-ncmp-rest/docs/openapi/ncmproxy.yml
rename to cps-ncmp-rest/docs/openapi/ncmp.yml
index 2e5eba7..52245c3 100755 (executable)
@@ -1,6 +1,7 @@
 #  ============LICENSE_START=======================================================
 #  Copyright (C) 2021 Nordix Foundation
 #  Modifications Copyright (C) 2021 Pantheon.tech
+#  Modifications Copyright (C) 2021 Bell Canada
 #  ================================================================================
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -179,29 +180,6 @@ listNodeByCmHandleAndXpath:
       404:
         $ref: 'components.yaml#/components/responses/NotFound'
 
-updateDmiRegistration:
-  post:
-    description: Register a DMI Plugin with any new, updated or removed CM Handles.
-    tags:
-      - network-cm-proxy
-    summary: DMI notifies NCMP of new CM Handles
-    operationId: updateDmiPluginRegistration
-    requestBody:
-      required: true
-      content:
-        application/json:
-          schema:
-            $ref: 'components.yaml#/components/schemas/RestDmiPluginRegistration'
-    responses:
-      201:
-        $ref: 'components.yaml#/components/responses/Created'
-      400:
-        $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
-      403:
-        $ref: 'components.yaml#/components/responses/Forbidden'
-
 getResourceDataForPassthroughOperational:
   get:
     tags:
@@ -211,10 +189,9 @@ getResourceDataForPassthroughOperational:
     operationId: getResourceDataOperationalForCmHandle
     parameters:
       - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
-      - $ref: 'components.yaml#/components/parameters/resourceIdentifierInPath'
+      - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
       - $ref: 'components.yaml#/components/parameters/acceptParamInHeader'
-      - $ref: 'components.yaml#/components/parameters/fieldsParamInQuery'
-      - $ref: 'components.yaml#/components/parameters/depthParamInQuery'
+      - $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
     responses:
       200:
         $ref: 'components.yaml#/components/responses/Ok'
@@ -236,10 +213,9 @@ resourceDataForPassthroughRunning:
     operationId: getResourceDataRunningForCmHandle
     parameters:
       - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
-      - $ref: 'components.yaml#/components/parameters/resourceIdentifierInPath'
+      - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
       - $ref: 'components.yaml#/components/parameters/acceptParamInHeader'
-      - $ref: 'components.yaml#/components/parameters/fieldsParamInQuery'
-      - $ref: 'components.yaml#/components/parameters/depthParamInQuery'
+      - $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
     responses:
       200:
         $ref: 'components.yaml#/components/responses/Ok'
@@ -259,7 +235,7 @@ resourceDataForPassthroughRunning:
     operationId: createResourceDataRunningForCmHandle
     parameters:
       - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
-      - $ref: 'components.yaml#/components/parameters/resourceIdentifierInPath'
+      - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
       - $ref: 'components.yaml#/components/parameters/contentParamInHeader'
     requestBody:
       required: true
diff --git a/cps-ncmp-rest/docs/openapi/openapi-inventory.yml b/cps-ncmp-rest/docs/openapi/openapi-inventory.yml
new file mode 100755 (executable)
index 0000000..ee09d05
--- /dev/null
@@ -0,0 +1,28 @@
+#  ============LICENSE_START=======================================================
+#  Copyright (C) 2021 Bell Canada
+#  ================================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+#  SPDX-License-Identifier: Apache-2.0
+#  ============LICENSE_END=========================================================
+
+openapi: 3.0.1
+info:
+  title: NCMP Inventory API
+  description: NCMP Inventory API
+  version: "1.0"
+servers:
+  - url: /ncmpInventory
+paths:
+  /v1/ch:
+    $ref: 'ncmp-inventory.yml#/updateDmiRegistration'
index 12356b5..69c2a11 100755 (executable)
@@ -27,25 +27,22 @@ servers:
   - url: /ncmp
 paths:
   /v1/cm-handles/{cm-handle}/node:
-    $ref: 'ncmproxy.yml#/nodeByCmHandleAndXpath'
+    $ref: 'ncmp.yml#/nodeByCmHandleAndXpath'
 
   /v1/cm-handles/{cm-handle}/list-node:
-    $ref: 'ncmproxy.yml#/listNodeByCmHandleAndXpath'
+    $ref: 'ncmp.yml#/listNodeByCmHandleAndXpath'
 
   /v1/cm-handles/{cm-handle}/nodes/query:
-    $ref: 'ncmproxy.yml#/nodesByCmHandleAndCpsPath'
+    $ref: 'ncmp.yml#/nodesByCmHandleAndCpsPath'
 
   /v1/cm-handles/{cm-handle}/nodes:
-    $ref: 'ncmproxy.yml#/nodesByCmHandleAndXpath'
+    $ref: 'ncmp.yml#/nodesByCmHandleAndXpath'
 
-  /v1/ch:
-    $ref: 'ncmproxy.yml#/updateDmiRegistration'
+  /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-operational:
+    $ref: 'ncmp.yml#/getResourceDataForPassthroughOperational'
 
-  /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-operational/{resourceIdentifier}:
-    $ref: 'ncmproxy.yml#/getResourceDataForPassthroughOperational'
-
-  /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-running/{resourceIdentifier}:
-    $ref: 'ncmproxy.yml#/resourceDataForPassthroughRunning'
+  /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-running:
+    $ref: 'ncmp.yml#/resourceDataForPassthroughRunning'
 
   /v1/ch/{cm-handle}/modules:
-    $ref: 'ncmproxy.yml#/fetchModuleReferencesByCmHandle'
\ No newline at end of file
+    $ref: 'ncmp.yml#/fetchModuleReferencesByCmHandle'
\ No newline at end of file
index b47ea17..c4c72bb 100644 (file)
                 <artifactId>swagger-codegen-maven-plugin</artifactId>
                 <executions>
                     <execution>
-                        <id>code-gen</id>
+                        <id>ncmp-code-gen</id>
                         <goals>
                             <goal>generate</goal>
                         </goals>
                             </configOptions>
                         </configuration>
                     </execution>
+                    <execution>
+                        <id>ncmp-code-gen-inventory</id>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                        <configuration>
+                            <inputSpec>${project.basedir}/docs/openapi/openapi-inventory.yml</inputSpec>
+                            <invokerPackage>org.onap.cps.ncmp.rest.controller</invokerPackage>
+                            <modelPackage>org.onap.cps.ncmp.rest.model</modelPackage>
+                            <apiPackage>org.onap.cps.ncmp.rest.api</apiPackage>
+                            <language>spring</language>
+                            <generateSupportingFiles>false</generateSupportingFiles>
+                            <configOptions>
+                                <sourceFolder>src/gen/java</sourceFolder>
+                                <dateLibrary>java11</dateLibrary>
+                                <interfaceOnly>true</interfaceOnly>
+                                <useTags>true</useTags>
+                            </configOptions>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>ncmp-inventory-openapi-yaml-gen</id>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                        <phase>compile</phase>
+                        <configuration>
+                            <inputSpec>${project.basedir}/docs/openapi/openapi-inventory.yml</inputSpec>
+                            <language>openapi-yaml</language>
+                            <configOptions>
+                                <outputFile>openapi-inventory.yaml</outputFile>
+                            </configOptions>
+                        </configuration>
+                    </execution>
                 </executions>
             </plugin>
             <plugin>
                                 <resource>
                                     <directory>${project.basedir}/target/generated-sources/swagger/</directory>
                                     <includes>
-                                        <include>openapi.yaml</include>
+                                        <include>openapi*.yaml</include>
                                     </includes>
                                 </resource>
                             </resources>
index a4d94ce..9b15a78 100755 (executable)
@@ -3,6 +3,7 @@
  *  Copyright (C) 2021 Pantheon.tech
  *  Modifications (C) 2021 Nordix Foundation
  *  Modification Copyright (C) 2021 highstreet technologies GmbH
+ *  Modifications (C) 2021 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.rest.controller;
 
-
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import java.util.Collection;
 import javax.validation.Valid;
-import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
-import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
 import org.onap.cps.ncmp.rest.api.NetworkCmProxyApi;
-import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration;
 import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.spi.model.DataNode;
 import org.onap.cps.spi.model.ModuleReference;
@@ -50,17 +46,12 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
 
     private final NetworkCmProxyDataService networkCmProxyDataService;
 
-    private final ObjectMapper objectMapper;
-
     /**
      * Constructor Injection for Dependencies.
      * @param networkCmProxyDataService Data Service Interface
-     * @param objectMapper Object Mapper
      */
-    public NetworkCmProxyController(final NetworkCmProxyDataService networkCmProxyDataService,
-        final ObjectMapper objectMapper) {
+    public NetworkCmProxyController(final NetworkCmProxyDataService networkCmProxyDataService) {
         this.networkCmProxyDataService = networkCmProxyDataService;
-        this.objectMapper = objectMapper;
     }
 
     /**
@@ -101,19 +92,6 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
         return new ResponseEntity<>(DataMapUtils.toDataMap(dataNode), HttpStatus.OK);
     }
 
-    /**
-     * Update DMI Plugin Registration (used for first registration also).
-     * @param restDmiPluginRegistration the registration data
-     */
-    @Override
-    public ResponseEntity<Void> updateDmiPluginRegistration(
-        final @Valid RestDmiPluginRegistration restDmiPluginRegistration) {
-        final DmiPluginRegistration dmiPluginRegistration =
-            convertRestObjectToJavaApiObject(restDmiPluginRegistration);
-        networkCmProxyDataService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration);
-        return new ResponseEntity<>(HttpStatus.CREATED);
-    }
-
     /**
      * Query Data Nodes.
      * @deprecated This Method is no longer used as part of NCMP.
@@ -158,22 +136,19 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      *
      * @param cmHandle cm handle identifier
      * @param resourceIdentifier resource identifier
-     * @param accept accept header parameter
-     * @param fields fields query parameter
-     * @param depth depth query parameter
+     * @param acceptParamInHeader accept header parameter
+     * @param optionsParamInQuery options query parameter
      * @return {@code ResponseEntity} response from dmi plugin
      */
     @Override
     public ResponseEntity<Object> getResourceDataOperationalForCmHandle(final String cmHandle,
-                                                                        final String resourceIdentifier,
-                                                                        final String accept,
-                                                                        final @Valid String fields,
-                                                                        final @Min(1) @Valid Integer depth) {
+                                                                        final @NotNull @Valid String resourceIdentifier,
+                                                                        final String acceptParamInHeader,
+                                                                        final @Valid String optionsParamInQuery) {
         final Object responseObject = networkCmProxyDataService.getResourceDataOperationalForCmHandle(cmHandle,
                 resourceIdentifier,
-                accept,
-                fields,
-                depth);
+                acceptParamInHeader,
+                optionsParamInQuery);
         return ResponseEntity.ok(responseObject);
     }
 
@@ -182,22 +157,19 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      *
      * @param cmHandle cm handle identifier
      * @param resourceIdentifier resource identifier
-     * @param accept accept header parameter
-     * @param fields fields query parameter
-     * @param depth depth query parameter
+     * @param acceptParamInHeader accept header parameter
+     * @param optionsParamInQuery options query parameter
      * @return {@code ResponseEntity} response from dmi plugin
      */
     @Override
     public ResponseEntity<Object> getResourceDataRunningForCmHandle(final String cmHandle,
-                                                                    final String resourceIdentifier,
-                                                                    final String accept,
-                                                                    final @Valid String fields,
-                                                                    final @Min(1) @Valid Integer depth) {
+                                                                    final @NotNull @Valid String resourceIdentifier,
+                                                                    final String acceptParamInHeader,
+                                                                    final @Valid String optionsParamInQuery) {
         final Object responseObject = networkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle(cmHandle,
                 resourceIdentifier,
-                accept,
-                fields,
-                depth);
+                acceptParamInHeader,
+                optionsParamInQuery);
         return ResponseEntity.ok(responseObject);
     }
 
@@ -205,15 +177,15 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      * Create resource data in datastore pass through running
      * for given cm-handle.
      *
-     * @param cmHandle cm handle identifier
      * @param resourceIdentifier resource identifier
+     * @param cmHandle cm handle identifier
      * @param requestBody requestBody
      * @param contentType content type of body
      * @return {@code ResponseEntity} response from dmi plugi
      */
     @Override
-    public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String cmHandle,
-                                                                     final String resourceIdentifier,
+    public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String resourceIdentifier,
+                                                                     final String cmHandle,
                                                                      final String requestBody,
                                                                      final String contentType) {
         networkCmProxyDataService.createResourceDataPassThroughRunningForCmHandle(cmHandle,
@@ -228,9 +200,4 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
         return new ResponseEntity<>(new Gson().toJson(moduleReferences), HttpStatus.OK);
     }
 
-    private DmiPluginRegistration convertRestObjectToJavaApiObject(
-        final RestDmiPluginRegistration restDmiPluginRegistration) {
-        return objectMapper.convertValue(restDmiPluginRegistration, DmiPluginRegistration.class);
-    }
-
 }
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java
new file mode 100755 (executable)
index 0000000..3b72cec
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Bell Canada
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.rest.controller;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import javax.validation.Valid;
+import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
+import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
+import org.onap.cps.ncmp.rest.api.NetworkCmProxyInventoryApi;
+import org.onap.cps.ncmp.rest.model.RestDmiPluginRegistration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("${rest.api.ncmp-inventory-base-path}")
+public class NetworkCmProxyInventoryController implements NetworkCmProxyInventoryApi {
+
+    private final NetworkCmProxyDataService networkCmProxyDataService;
+    private final ObjectMapper objectMapper;
+
+    /**
+     * Constructor Injection for Dependencies.
+     * @param networkCmProxyDataService Data Service Interface
+     * @param objectMapper Object Mapper
+     */
+    public NetworkCmProxyInventoryController(final NetworkCmProxyDataService networkCmProxyDataService,
+        final ObjectMapper objectMapper) {
+        this.networkCmProxyDataService = networkCmProxyDataService;
+        this.objectMapper = objectMapper;
+    }
+
+    /**
+     * Update DMI Plugin Registration (used for first registration also).
+     * @param restDmiPluginRegistration the registration data
+     */
+    @Override
+    public ResponseEntity<Void> updateDmiPluginRegistration(
+        final @Valid RestDmiPluginRegistration restDmiPluginRegistration) {
+        final DmiPluginRegistration dmiPluginRegistration =
+            convertRestObjectToJavaApiObject(restDmiPluginRegistration);
+        networkCmProxyDataService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration);
+        return new ResponseEntity<>(HttpStatus.CREATED);
+    }
+
+    private DmiPluginRegistration convertRestObjectToJavaApiObject(
+        final RestDmiPluginRegistration restDmiPluginRegistration) {
+        return objectMapper.convertValue(restDmiPluginRegistration, DmiPluginRegistration.class);
+    }
+
+}
index 9f2b4e1..342f41b 100644 (file)
@@ -31,9 +31,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
 
-import com.fasterxml.jackson.databind.ObjectMapper
 import com.google.gson.Gson
-import org.onap.cps.TestUtils
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService
 import org.onap.cps.spi.model.DataNodeBuilder
 import org.spockframework.spring.SpringBean
@@ -54,9 +52,6 @@ class NetworkCmProxyControllerSpec extends Specification {
     @SpringBean
     NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock()
 
-    @SpringBean
-    ObjectMapper objectMapper = new ObjectMapper()
-
     @Value('${rest.api.ncmp-base-path}/v1')
     def ncmpBasePathV1
 
@@ -175,25 +170,10 @@ class NetworkCmProxyControllerSpec extends Specification {
             response.contentAsString.contains('"leaf":"value"')
     }
 
-    def 'Register CM Handle Event' () {
-        given: 'jsonData'
-            def jsonData = TestUtils.getResourceFileContent('dmi-registration.json')
-        when: 'post request is performed'
-            def response = mvc.perform(
-                post("$ncmpBasePathV1/ch")
-                .contentType(MediaType.APPLICATION_JSON)
-                .content(jsonData)
-            ).andReturn().response
-        then: 'the cm handles are registered with the service'
-            1 * mockNetworkCmProxyDataService.updateDmiRegistrationAndSyncModule(_)
-        and: 'response status is created'
-            response.status == HttpStatus.CREATED.value()
-    }
-
     def 'Get Resource Data from pass-through operational.' () {
         given: 'resource data url'
             def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-operational" +
-                    "/testResourceIdentifier?fields=testFields&depth=5"
+                    "?resourceIdentifier=parent/child&options=(a=1,b=2)"
         when: 'get data resource request is performed'
             def response = mvc.perform(
                     get(getUrl)
@@ -202,24 +182,22 @@ class NetworkCmProxyControllerSpec extends Specification {
             ).andReturn().response
         then: 'the NCMP data service is called with getResourceDataOperationalForCmHandle'
             1 * mockNetworkCmProxyDataService.getResourceDataOperationalForCmHandle('testCmHandle',
-                    'testResourceIdentifier',
+                    'parent/child',
                     'application/json',
-                    'testFields',
-                    5)
+                    '(a=1,b=2)')
         and: 'response status is Ok'
             response.status == HttpStatus.OK.value()
     }
 
-    def 'Get Resource Data from pass-through running.' () {
+    def 'Get Resource Data from pass-through running with #scenario value in resource identifier param.' () {
         given: 'resource data url'
             def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
-                    "/testResourceIdentifier?fields=testFields&depth=5"
+                    "?resourceIdentifier=" + resourceIdentifier + "&options=(a=1,b=2)"
         and: 'ncmp service returns json object'
             mockNetworkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                'testResourceIdentifier',
-                'application/json',
-                'testFields',
-                5) >> '{valid-json}'
+                    resourceIdentifier,
+                    'application/json',
+                    '(a=1,b=2)') >> '{valid-json}'
         when: 'get data resource request is performed'
             def response = mvc.perform(
                     get(getUrl)
@@ -230,12 +208,20 @@ class NetworkCmProxyControllerSpec extends Specification {
             response.status == HttpStatus.OK.value()
         and: 'response contains valid object body'
             response.getContentAsString() == '{valid-json}'
+        where: 'tokens are used in the resource identifier parameter'
+            scenario                       | resourceIdentifier
+            '/'                            | 'id/with/slashes'
+            '?'                            | 'idWith?'
+            ','                            | 'idWith,'
+            '='                            | 'idWith='
+            '[]'                           | 'idWith[]'
+            '? needs to be encoded as %3F' | 'idWith%3F'
     }
 
     def 'Create Resource Data from pass-through running with #scenario.' () {
         given: 'resource data url'
             def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
-                    "/testResourceIdentifier"
+                    "?resourceIdentifier=parent/child"
         when: 'get data resource request is performed'
             def response = mvc.perform(
                     post(getUrl)
@@ -244,7 +230,7 @@ class NetworkCmProxyControllerSpec extends Specification {
             ).andReturn().response
         then: 'ncmp service method to create resource called'
             1 * mockNetworkCmProxyDataService.createResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                    'testResourceIdentifier', requestBody, 'application/json;charset=UTF-8')
+                    'parent/child', requestBody, 'application/json;charset=UTF-8')
         and: 'resource is created'
             response.status == HttpStatus.CREATED.value()
         where: 'given request body'
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy
new file mode 100644 (file)
index 0000000..e558ac4
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Bell Canada
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.rest.controller
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.TestUtils
+import org.onap.cps.ncmp.api.NetworkCmProxyDataService
+import org.spockframework.spring.SpringBean
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
+import org.springframework.context.annotation.Import
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.springframework.test.web.servlet.MockMvc
+import spock.lang.Specification
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
+
+@WebMvcTest(NetworkCmProxyInventoryController)
+@Import(ObjectMapper)
+class NetworkCmProxyInventoryControllerSpec extends Specification {
+
+    @Autowired
+    MockMvc mvc
+
+    @SpringBean
+    NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock()
+
+    @Value('${rest.api.ncmp-inventory-base-path}/v1')
+    def ncmpBasePathV1
+
+    def 'Register CM Handle Event' () {
+        given: 'jsonData'
+            def jsonData = TestUtils.getResourceFileContent('dmi-registration.json')
+        when: 'post request is performed'
+            def response = mvc.perform(
+                post("$ncmpBasePathV1/ch")
+                .contentType(MediaType.APPLICATION_JSON)
+                .content(jsonData)
+            ).andReturn().response
+        then: 'the cm handles are registered with the service'
+            1 * mockNetworkCmProxyDataService.updateDmiRegistrationAndSyncModule(_)
+        and: 'response status is created'
+            response.status == HttpStatus.CREATED.value()
+    }
+
+}
+
index 848738a..f2ca8c7 100644 (file)
@@ -20,4 +20,4 @@
 rest:
     api:
         ncmp-base-path: /ncmp
-spring:
+        ncmp-inventory-base-path: /ncmpInventory
index 2f91ed3..cb2f782 100644 (file)
@@ -114,16 +114,14 @@ public interface NetworkCmProxyDataService {
      *
      * @param cmHandle cm handle
      * @param resourceIdentifier resource identifier
-     * @param accept accept param
-     * @param fields fields query
-     * @param depth depth query
+     * @param acceptParamInHeader accept param
+     * @param optionsParamInQuery options query
      * @return {@code Object} resource data
      */
     Object getResourceDataOperationalForCmHandle(@NotNull String cmHandle,
                                                  @NotNull String resourceIdentifier,
-                                                 String accept,
-                                                 String fields,
-                                                 Integer depth);
+                                                 String acceptParamInHeader,
+                                                 String optionsParamInQuery);
 
     /**
      * Get resource data for data store pass-through running
@@ -131,16 +129,14 @@ public interface NetworkCmProxyDataService {
      *
      * @param cmHandle cm handle
      * @param resourceIdentifier resource identifier
-     * @param acceptParam accept param
-     * @param fields fields query
-     * @param depth depth query
+     * @param acceptParamInHeader accept param
+     * @param optionsParamInQuery options query
      * @return {@code Object} resource data
      */
     Object getResourceDataPassThroughRunningForCmHandle(@NotNull String cmHandle,
                                                         @NotNull String resourceIdentifier,
-                                                        String acceptParam,
-                                                        String fields,
-                                                        Integer depth);
+                                                        String acceptParamInHeader,
+                                                        String optionsParamInQuery);
 
     /**
      * Create resource data for data store pass-through running
index 291b0bf..d6aaf36 100755 (executable)
@@ -59,7 +59,6 @@ import org.onap.cps.spi.exceptions.DataValidationException;
 import org.onap.cps.spi.model.DataNode;
 import org.onap.cps.spi.model.ModuleReference;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
@@ -169,9 +168,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
     @Override
     public Object getResourceDataOperationalForCmHandle(final @NotNull String cmHandle,
                                                         final @NotNull String resourceIdentifier,
-                                                        final String acceptParam,
-                                                        final String fieldsQueryParam,
-                                                        final Integer depthQueryParam) {
+                                                        final String acceptParamInHeader,
+                                                        final String optionsParamInQuery) {
 
         final DataNode cmHandleDataNode = fetchDataNodeFromDmiRegistryForCmHandle(cmHandle);
         final String dmiServiceName = String.valueOf(cmHandleDataNode.getLeaves().get(NCMP_DMI_SERVICE_NAME));
@@ -179,9 +177,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
         final ResponseEntity<Object> response = dmiOperations.getResourceDataOperationalFromDmi(dmiServiceName,
                 cmHandle,
                 resourceIdentifier,
-                fieldsQueryParam,
-                depthQueryParam,
-                acceptParam,
+                optionsParamInQuery,
+                acceptParamInHeader,
                 dmiRequestBody);
         return handleResponse(response);
     }
@@ -189,18 +186,16 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
     @Override
     public Object getResourceDataPassThroughRunningForCmHandle(final @NotNull String cmHandle,
                                                                final @NotNull String resourceIdentifier,
-                                                               final String acceptParam,
-                                                               final String fields,
-                                                               final Integer depth) {
+                                                               final String acceptParamInHeader,
+                                                               final String optionsParamInQuery) {
         final DataNode cmHandleDataNode = fetchDataNodeFromDmiRegistryForCmHandle(cmHandle);
         final String dmiServiceName = String.valueOf(cmHandleDataNode.getLeaves().get(NCMP_DMI_SERVICE_NAME));
         final String dmiRequestBody = getGenericRequestBody(cmHandleDataNode);
         final ResponseEntity<Object> response = dmiOperations.getResourceDataPassThroughRunningFromDmi(dmiServiceName,
                 cmHandle,
                 resourceIdentifier,
-                fields,
-                depth,
-                acceptParam,
+                optionsParamInQuery,
+                acceptParamInHeader,
                 dmiRequestBody);
         return handleResponse(response);
     }
@@ -289,7 +284,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
     }
 
     private static void handleResponseForPost(final @NotNull ResponseEntity<String> responseEntity) {
-        if (responseEntity.getStatusCode() != HttpStatus.OK) {
+        if (!HttpStatus.valueOf(responseEntity.getStatusCodeValue()).is2xxSuccessful()) {
             throw new NcmpException("Not able to create resource data.",
                     "DMI status code: " + responseEntity.getStatusCodeValue()
                             + ", DMI response body: " + responseEntity.getBody());
@@ -349,13 +344,13 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
             cmHandleJsonData, NO_TIMESTAMP);
 
         for (final PersistenceCmHandle persistenceCmHandle : persistenceCmHandlesList.getPersistenceCmHandles()) {
-            createAnchorAndSyncModel(persistenceCmHandle);
+            syncModulesAndCreateAnchor(persistenceCmHandle);
         }
     }
 
-    protected void createAnchorAndSyncModel(final PersistenceCmHandle persistenceCmHandle) {
-        createAnchor(persistenceCmHandle);
+    protected void syncModulesAndCreateAnchor(final PersistenceCmHandle persistenceCmHandle) {
         fetchAndSyncModules(persistenceCmHandle);
+        createAnchor(persistenceCmHandle);
     }
 
     private static PersistenceCmHandle toPersistenceCmHandle(final String dmiPluginService,
@@ -392,9 +387,13 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
         final List<ModuleReference> unknownModuleReferences = new ArrayList<>();
         prepareModuleSubsets(moduleReferencesFromCmHandle, existingModuleReferences, unknownModuleReferences);
 
-        final Map<String, String> newYangResourcesModuleNameToContentMap =
-            getNewYangResourcesFromDmi(persistenceCmHandle, unknownModuleReferences, cmHandlePropertiesAsMap);
-
+        final Map<String, String> newYangResourcesModuleNameToContentMap;
+        if (unknownModuleReferences.size() > 0) {
+            newYangResourcesModuleNameToContentMap = getNewYangResourcesFromDmi(persistenceCmHandle,
+                    unknownModuleReferences, cmHandlePropertiesAsMap);
+        } else {
+            newYangResourcesModuleNameToContentMap = new HashMap<>();
+        }
         cpsModuleService.createSchemaSetFromModules(NF_PROXY_DATASPACE_NAME, persistenceCmHandle.getId(),
             newYangResourcesModuleNameToContentMap, existingModuleReferences);
     }
@@ -417,14 +416,13 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
 
     private List<ModuleReference> fetchModuleReferencesFromDmi(final PersistenceCmHandle persistenceCmHandle,
                                                                final Map<String, String> cmHandlePropertiesAsMap) {
-        final GenericRequestBody requestBodyObject = GenericRequestBody.builder()
-                .operation(GenericRequestBody.OperationEnum.READ)
+        final GenericRequestBody genericRequestBody = GenericRequestBody.builder()
                 .cmHandleProperties(cmHandlePropertiesAsMap)
                 .build();
-        final String jsonBody = prepareOperationBody(requestBodyObject);
+        final String jsonBodyWithOnlyCmHandleProperties = prepareOperationBody(genericRequestBody);
         final ResponseEntity<String> dmiFetchModulesResponseEntity =
             dmiOperations.getResourceFromDmiWithJsonData(persistenceCmHandle.getDmiServiceName(),
-                    jsonBody, persistenceCmHandle.getId(), "modules");
+                    jsonBodyWithOnlyCmHandleProperties, persistenceCmHandle.getId(), "modules");
         return toModuleReferences(dmiFetchModulesResponseEntity);
     }
 
@@ -437,13 +435,11 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
         final JsonArray moduleReferencesAsJson = getModuleReferencesAsJson(unknownModuleReferences);
         final JsonObject data = new JsonObject();
         data.add("modules", moduleReferencesAsJson);
-        final GenericRequestBody dmiRequestBodyObject = GenericRequestBody.builder()
-                .operation(GenericRequestBody.OperationEnum.READ)
-                .dataType(MediaType.APPLICATION_JSON_VALUE)
-                .data(data.toString())
-                .cmHandleProperties(cmHandlePropertiesAsMap)
-                .build();
-        return prepareOperationBody(dmiRequestBodyObject);
+        final JsonObject jsonRequestObject = new JsonObject();
+        jsonRequestObject.add("data", data);
+        final Gson gson = new Gson();
+        jsonRequestObject.add("cmHandleProperties", gson.toJsonTree(cmHandlePropertiesAsMap));
+        return jsonRequestObject.toString();
     }
 
     private static JsonArray getModuleReferencesAsJson(final List<ModuleReference> unknownModuleReferences) {
@@ -461,12 +457,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
     private Map<String, String> getNewYangResourcesFromDmi(final PersistenceCmHandle persistenceCmHandle,
                                                            final List<ModuleReference> unknownModuleReferences,
                                                            final Map<String, String> cmHandlePropertiesAsMap) {
-        final String jsonData = getRequestBodyToFetchYangResourceFromDmi(
+        final String jsonDataWithDataAndCmHandleProperties = getRequestBodyToFetchYangResourceFromDmi(
                 unknownModuleReferences, cmHandlePropertiesAsMap);
 
         final ResponseEntity<String> moduleResourcesAsJsonString =  dmiOperations.getResourceFromDmiWithJsonData(
                 persistenceCmHandle.getDmiServiceName(),
-                jsonData,
+                jsonDataWithDataAndCmHandleProperties,
                 persistenceCmHandle.getId(),
                 "moduleResources");
 
index 71af3d4..f7421cd 100644 (file)
@@ -52,6 +52,9 @@ public class DmiOperations {
     private static final String DMI_CM_HANDLE_PATH = "/v1/ch/{cmHandle}";
     private static final String DMI_CM_HANDLE_DATASTORE_PATH = DMI_CM_HANDLE_PATH + "/data/ds";
     private static final String URL_SEPARATOR = "/";
+    private static final String RESOURCE_IDENTIFIER = "resourceIdentifier";
+    private static final String OPTIONS_QUERY_KEY = "options";
+
 
     /**
      * Constructor for {@code DmiOperations}. This method also manipulates url properties.
@@ -102,22 +105,20 @@ public class DmiOperations {
      * @param dmiServiceName dmi service name
      * @param cmHandle    network resource identifier
      * @param resourceId  resource identifier
-     * @param fieldsQuery fields query
-     * @param depthQuery  depth query
-     * @param acceptParam accept parameter
+     * @param optionsParamInQuery options query
+     * @param acceptParamInHeader accept parameter
      * @param jsonBody    json body for put operation
      * @return {@code ResponseEntity} response entity
      */
     public ResponseEntity<Object> getResourceDataOperationalFromDmi(final String dmiServiceName,
                                                                     final String cmHandle,
                                                                     final String resourceId,
-                                                                    final String fieldsQuery,
-                                                                    final Integer depthQuery,
-                                                                    final String acceptParam,
+                                                                    final String optionsParamInQuery,
+                                                                    final String acceptParamInHeader,
                                                                     final String jsonBody) {
         final var dmiResourceDataUrl = getDmiDatastoreUrl(dmiServiceName, cmHandle, resourceId,
-            fieldsQuery, depthQuery, DataStoreEnum.PASSTHROUGH_OPERATIONAL);
-        final var httpHeaders = prepareHeader(acceptParam);
+            optionsParamInQuery, DataStoreEnum.PASSTHROUGH_OPERATIONAL);
+        final var httpHeaders = prepareHeader(acceptParamInHeader);
         return dmiRestClient.putOperationWithJsonData(dmiResourceDataUrl, jsonBody, httpHeaders);
     }
 
@@ -128,22 +129,20 @@ public class DmiOperations {
      * @param dmiServiceName dmi service name
      * @param cmHandle    network resource identifier
      * @param resourceId  resource identifier
-     * @param fieldsQuery fields query
-     * @param depthQuery  depth query
-     * @param acceptParam accept parameter
+     * @param optionsParamInQuery fields query
+     * @param acceptParamInHeader accept parameter
      * @param jsonBody    json body for put operation
      * @return {@code ResponseEntity} response entity
      */
     public ResponseEntity<Object> getResourceDataPassThroughRunningFromDmi(final String dmiServiceName,
                                                                            final String cmHandle,
                                                                            final String resourceId,
-                                                                           final String fieldsQuery,
-                                                                           final Integer depthQuery,
-                                                                           final String acceptParam,
+                                                                           final String optionsParamInQuery,
+                                                                           final String acceptParamInHeader,
                                                                            final String jsonBody) {
         final var dmiResourceDataUrl = getDmiDatastoreUrl(dmiServiceName, cmHandle, resourceId,
-            fieldsQuery, depthQuery, DataStoreEnum.PASSTHROUGH_RUNNING);
-        final var httpHeaders = prepareHeader(acceptParam);
+            optionsParamInQuery, DataStoreEnum.PASSTHROUGH_RUNNING);
+        final var httpHeaders = prepareHeader(acceptParamInHeader);
         return dmiRestClient.putOperationWithJsonData(dmiResourceDataUrl, jsonBody, httpHeaders);
     }
 
@@ -161,7 +160,7 @@ public class DmiOperations {
                                                                             final String cmHandle,
                                                                             final String resourceId,
                                                                             final String jsonBody) {
-        final var stringBuilder = getStringBuilderForPassThroughRunningUrl(dmiServiceName,
+        final var stringBuilder = getStringBuilderForPassThroughUrl(dmiServiceName,
             cmHandle, resourceId, DataStoreEnum.PASSTHROUGH_RUNNING);
         return dmiRestClient.postOperationWithJsonData(stringBuilder.toString(), jsonBody, new HttpHeaders());
     }
@@ -181,50 +180,37 @@ public class DmiOperations {
     private String getDmiDatastoreUrl(final String dmiServiceName,
                                       final String cmHandle,
                                       final String resourceId,
-                                      final String fieldsQuery,
-                                      final Integer depthQuery,
+                                      final String optionsParamInQuery,
                                       final DataStoreEnum dataStoreEnum) {
-        final var stringBuilder = getStringBuilderForPassThroughRunningUrl(dmiServiceName,
+        final var stringBuilder = getStringBuilderForPassThroughUrl(dmiServiceName,
             cmHandle, resourceId, dataStoreEnum);
-        appendFieldsAndDepth(stringBuilder, fieldsQuery, depthQuery);
+        appendOptionsQuery(stringBuilder, optionsParamInQuery);
         return stringBuilder.toString();
     }
 
     @NotNull
-    private StringBuilder getStringBuilderForPassThroughRunningUrl(final String dmiServiceName,
-                                                                   final String cmHandle,
-                                                                   final String resourceId,
-                                                                   final DataStoreEnum dataStoreEnum) {
+    private StringBuilder getStringBuilderForPassThroughUrl(final String dmiServiceName,
+                                                            final String cmHandle,
+                                                            final String resourceId,
+                                                            final DataStoreEnum dataStoreEnum) {
         final var stringBuilder = new StringBuilder(dmiServiceName);
         stringBuilder.append(DMI_API_PATH);
         stringBuilder.append(DMI_CM_HANDLE_DATASTORE_PATH.replace("{cmHandle}", cmHandle));
         stringBuilder.append(URL_SEPARATOR + dataStoreEnum.getValue());
-        stringBuilder.append(URL_SEPARATOR + resourceId);
+        stringBuilder.append("?" + RESOURCE_IDENTIFIER + "=" + resourceId);
         return stringBuilder;
     }
 
-    private void appendFieldsAndDepth(final StringBuilder stringBuilder,
-                                      final String fieldsQuery,
-                                      final Integer depthQuery) {
-        final var doesFieldExists = (fieldsQuery != null && !fieldsQuery.isEmpty());
-        if (doesFieldExists) {
-            stringBuilder.append("?").append("fields=").append(fieldsQuery);
-        }
-        if (depthQuery != null) {
-            if (doesFieldExists) {
-                stringBuilder.append("&");
-            } else {
-                stringBuilder.append("?");
-            }
-            stringBuilder.append("depth=").append(depthQuery);
+    private void appendOptionsQuery(final StringBuilder stringBuilder,
+                                    final String optionsParamInQuery) {
+        if (optionsParamInQuery != null) {
+            stringBuilder.append("&").append(OPTIONS_QUERY_KEY).append("=").append(optionsParamInQuery);
         }
     }
 
     private HttpHeaders prepareHeader(final String acceptParam) {
         final var httpHeaders = new HttpHeaders();
-        if (acceptParam != null && !acceptParam.isEmpty()) {
-            httpHeaders.set(HttpHeaders.ACCEPT, acceptParam);
-        }
+        httpHeaders.set(HttpHeaders.ACCEPT, acceptParam);
         return httpHeaders;
     }
 }
index 2b376e9..1bad8ce 100644 (file)
@@ -231,16 +231,14 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             mockDmiOperations.getResourceDataOperationalFromDmi('testDmiService',
                 'testCmHandle',
                 'testResourceId',
-                'testFieldQuery',
-                5,
+                '(a=1,b=2)',
                 'testAcceptParam',
                 '{"operation":"read","cmHandleProperties":{"testName":"testValue"}}') >> new ResponseEntity<>('result-json', HttpStatus.OK)
         when: 'get resource data is called'
             def response = objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
             'testResourceId',
             'testAcceptParam',
-            'testFieldQuery',
-            5)
+            '(a=1,b=2)')
         then: 'dmi returns ok response'
             response == 'result-json'
     }
@@ -259,8 +257,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             def response = objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
                     'testResourceId',
                     'testAcceptParam',
-                    'testFieldQuery',
-                    5)
+                    '(a=1,b=2)')
         then: 'exception is thrown with the expected details'
             def exceptionThrown = thrown(NcmpException.class)
             exceptionThrown.details == 'testException'
@@ -276,8 +273,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             mockDmiOperations.getResourceDataOperationalFromDmi('testDmiService',
                     'testCmHandle',
                     'testResourceId',
-                    'testFieldQuery',
-                    5,
+                    '(a=1,b=2)',
                     'testAcceptParam',
                     '{"operation":"read","cmHandleProperties":{"testName":"testValue"}}')
                     >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
@@ -285,8 +281,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             def response = objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
                     'testResourceId',
                     'testAcceptParam',
-                    'testFieldQuery',
-                    5)
+                    '(a=1,b=2)')
         then: 'exception is thrown'
             def exceptionThrown = thrown(NcmpException.class)
         and: 'details contains the original response'
@@ -303,16 +298,14 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             mockDmiOperations.getResourceDataPassThroughRunningFromDmi('testDmiService',
                     'testCmHandle',
                     'testResourceId',
-                    'testFieldQuery',
-                    5,
+                    '(a=1,b=2)',
                     'testAcceptParam',
                     '{"operation":"read","cmHandleProperties":{"testName":"testValue"}}') >> new ResponseEntity<>('{result-json}', HttpStatus.OK)
         when: 'get resource data is called'
             def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
                     'testResourceId',
                     'testAcceptParam',
-                    'testFieldQuery',
-                    5)
+                    '(a=1,b=2)')
         then: 'get resource data returns expected response'
             response == '{result-json}'
     }
@@ -331,8 +324,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
                     'testResourceId',
                     'testAcceptParam',
-                    'testFieldQuery',
-                    5)
+                    '(a=1,b=2)')
         then: 'exception is thrown with the expected details'
             def exceptionThrown = thrown(NcmpException.class)
             exceptionThrown.details == 'testException'
@@ -348,8 +340,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             mockDmiOperations.getResourceDataPassThroughRunningFromDmi('testDmiService',
                     'testCmHandle',
                     'testResourceId',
-                    'testFieldQuery',
-                    5,
+                    '(a=1,b=2)',
                     'testAcceptParam',
                     '{"operation":"read","cmHandleProperties":{"testName":"testValue"}}')
                     >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
@@ -357,8 +348,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
                     'testResourceId',
                     'testAcceptParam',
-                    'testFieldQuery',
-                    5)
+                    '(a=1,b=2)')
         then: 'exception is thrown'
             def exceptionThrown = thrown(NcmpException.class)
         and: 'details contains the original response'
@@ -381,7 +371,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
                 'testResourceId',
                 '{"operation":"create","dataType":"application/json","data":"{some-json}","cmHandleProperties":'
                 + expectedJsonForCmhandleProperties+ '}')
-                >> { new ResponseEntity<>(HttpStatus.OK) }
+                >> { new ResponseEntity<>(HttpStatus.CREATED) }
         where:
             scenario  | includeCmHandleProperties || expectedJsonForCmhandleProperties
             'with'    | true                      || '{"testName":"testValue"}'
@@ -408,10 +398,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
     }
 
     def 'Sync model for a (new) cm handle with #scenario'() {
-        given: 'DMI Plug-in returns a list of module references'
-            def knownModule1 = new ModuleReference('module1', '1')
-            def knownOtherModule = new ModuleReference('some other module', 'some revision')
-        and: 'persistence cm handle is given'
+        given: 'persistence cm handle is given'
             def cmHandleForModelSync = new PersistenceCmHandle(id:'some cm handle', dmiServiceName: 'some service name')
         and: 'additional properties are set as required'
             if (additionalProperties!=null) {
@@ -419,29 +406,29 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             }
         and: 'dmi operations returns some module references'
             def jsonData = TestUtils.getResourceFileContent('cmHandleModules.json')
-            def expectedJsonBody = '{"operation":"read","cmHandleProperties":' + expectedJsonForAdditionalProperties + '}'
+            def expectedJsonBody = '{"cmHandleProperties":' + expectedJsonForAdditionalProperties + '}'
             mockDmiProperties.getAuthUsername() >> 'someUser'
             mockDmiProperties.getAuthPassword() >> 'somePassword'
             def moduleReferencesFromCmHandleAsJson = new ResponseEntity<String>(jsonData, HttpStatus.OK)
             mockDmiOperations.getResourceFromDmiWithJsonData('some service name', expectedJsonBody, 'some cm handle', 'modules') >> moduleReferencesFromCmHandleAsJson
         and: 'CPS-Core returns list of known modules'
-            mockCpsModuleService.getYangResourceModuleReferences(_) >> [knownModule1, knownOtherModule]
+            mockCpsModuleService.getYangResourceModuleReferences(_) >> existingModuleResourcesInCps
         and: 'DMI-Plugin returns resource(s) for "new" module(s)'
             def moduleResources = new ResponseEntity<String>(sdncReponseBody, HttpStatus.OK)
-            def jsonDataToFetchYangResource = '{"operation":"read","dataType":"application/json","data":"{\\"modules\\":[{\\"name\\":\\"module2\\",\\"revision\\":\\"1\\"}]}","cmHandleProperties":' + expectedJsonForAdditionalProperties + '}'
+            def jsonDataToFetchYangResource = '{"data":{"modules":[{"name":"module1","revision":"1"}]},"cmHandleProperties":' + expectedJsonForAdditionalProperties + '}'
             mockDmiOperations.getResourceFromDmiWithJsonData('some service name', jsonDataToFetchYangResource, 'some cm handle', 'moduleResources') >> moduleResources
         when: 'module Sync is triggered'
-            objectUnderTest.createAnchorAndSyncModel(cmHandleForModelSync)
+            objectUnderTest.syncModulesAndCreateAnchor(cmHandleForModelSync)
         then: 'the CPS module service is called once with the correct parameters'
-            1 * mockCpsModuleService.createSchemaSetFromModules(expectedDataspaceName, cmHandleForModelSync.getId(), expectedYangResourceToContentMap, [knownModule1])
+            1 * mockCpsModuleService.createSchemaSetFromModules(expectedDataspaceName, cmHandleForModelSync.getId(), expectedYangResourceToContentMap, expectedKnownModules)
         and: 'admin service create anchor method has been called with correct parameters'
             1 * mockCpsAdminService.createAnchor(expectedDataspaceName, cmHandleForModelSync.getId(), cmHandleForModelSync.getId())
         where: 'the following responses are received from SDNC'
-            scenario                         | additionalProperties | sdncReponseBody                                                                        || expectedYangResourceToContentMap | expectedJsonForAdditionalProperties
-            'one unknown module'             | ['name1':'value1']   | '[{"moduleName" : "someModule", "revision" : "1","yangSource": "[some yang source]"}]' || [someModule: 'some yang source'] | '{"name1":"value1"}'
-            'no add. properties'             | [:]                  | '[{"moduleName" : "someModule", "revision" : "1","yangSource": "[some yang source]"}]' || [someModule: 'some yang source'] | '{}'
-            'additional properties is null'  | null                 | '[{"moduleName" : "someModule", "revision" : "1","yangSource": "[some yang source]"}]' || [someModule: 'some yang source'] | '{}'
-            'no unknown module'              | [:]                  | '[]'                                                                                   || [:]                              | '{}'
+            scenario                         | additionalProperties | existingModuleResourcesInCps                                                  | sdncReponseBody                                                                     || expectedYangResourceToContentMap | expectedKnownModules                                                       | expectedJsonForAdditionalProperties
+            'one unknown module'             | ['name1':'value1']   | [new ModuleReference('module2', '2'), new ModuleReference('module3', '3')]    | '[{"moduleName" : "module1", "revision" : "1","yangSource": "[some yang source]"}]' || [module1: 'some yang source']    | [new ModuleReference('module2', '2')]                                      |'{"name1":"value1"}'
+            'no add. properties'             | [:]                  | [new ModuleReference('module2', '2'), new ModuleReference('module3', '3')]    | '[{"moduleName" : "module1", "revision" : "1","yangSource": "[some yang source]"}]' || [module1: 'some yang source']    | [new ModuleReference('module2', '2')]                                      |'{}'
+            'additional properties is null'  | null                 | [new ModuleReference('module2', '2'), new ModuleReference('module3', '3')]    | '[{"moduleName" : "module1", "revision" : "1","yangSource": "[some yang source]"}]' || [module1: 'some yang source']    | [new ModuleReference('module2', '2')]                                      |'{}'
+            'no unknown module'              | [:]                  | [new ModuleReference('module1', '1'),    new ModuleReference('module2', '2')] | '[]'                                                                                || [:]                              | [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')] |'{}'
     }
 
     def 'Getting Yang Resources.'() {
@@ -451,10 +438,22 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             1 * mockCpsModuleService.getYangResourcesModuleReferences('NFP-Operational','some cm handle')
     }
 
+    def 'Create the request body to get yang resources from DMI.'() {
+        given: 'the expected json request'
+            def expectedRequestBody = '{"data":{"modules":[{"name":"module1","revision":"1"},{"name":"module2","revision":"2"}]},"cmHandleProperties":{"name1":"value1"}}'
+        and: 'module references and cm handle properties'
+            def moduleReferences = [new ModuleReference('module1', '1'),new ModuleReference('module2', '2')]
+            def cmHandleProperties = ['name1':'value1']
+        when: 'get request body to fetch yang resources from DMI is called'
+            def result = objectUnderTest.getRequestBodyToFetchYangResourceFromDmi(moduleReferences, cmHandleProperties)
+        then: 'the result is the same as the expected request body'
+            result == expectedRequestBody
+    }
+
     def getObjectUnderTestWithModelSyncDisabled() {
         def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(mockDmiOperations, mockCpsModuleService,
                 mockCpsDataService, mockCpsQueryService, mockCpsAdminService, spyObjectMapper))
-        objectUnderTest.createAnchorAndSyncModel(_) >> null
+        objectUnderTest.syncModulesAndCreateAnchor(_) >> null
         return objectUnderTest
     }
 
index 6a1ce1a..9405b66 100644 (file)
@@ -41,29 +41,41 @@ class DmiOperationsSpec extends Specification {
 
     def 'call get resource data for pass-through:operational datastore from DMI.'() {
         given: 'expected url'
-        def expectedUrl = 'testDmiBasePath/dmi/v1/ch/testCmhandle/data/ds' +
-                '/ncmp-datastore:passthrough-operational/testResourceId?fields=testFieldsQuery&depth=10'
+            def expectedUrl = 'testDmiBasePath/dmi/v1/ch/testCmhandle/data/ds' +
+                    '/ncmp-datastore:passthrough-operational?resourceIdentifier=parent/child&options=(a=1,b=2)'
         when: 'get resource data is called to DMI'
-        objectUnderTest.getResourceDataOperationalFromDmi('testDmiBasePath',
-                'testCmhandle',
-                'testResourceId',
-                'testFieldsQuery',
-                10,
-                'testAcceptJson',
-                'testJsonbody')
+            objectUnderTest.getResourceDataOperationalFromDmi('testDmiBasePath',
+                    'testCmhandle',
+                    'parent/child',
+                    '(a=1,b=2)',
+                    'testAcceptJson',
+                    'testJsonbody')
         then: 'the put operation is executed with the correct URL'
-        1 * mockDmiRestClient.putOperationWithJsonData(expectedUrl, 'testJsonbody', _ as HttpHeaders)
+            1 * mockDmiRestClient.putOperationWithJsonData(expectedUrl, 'testJsonbody', _ as HttpHeaders)
     }
     def 'call get resource data for pass-through:running datastore from DMI.'() {
+        given: 'expected url'
+            def expectedUrl = 'testDmiBasePath/dmi/v1/ch/testCmhandle/data/ds' +
+                    '/ncmp-datastore:passthrough-running?resourceIdentifier=parent/child&options=(a=1,b=2)'
+        when: 'get resource data is called to DMI'
+            objectUnderTest.getResourceDataPassThroughRunningFromDmi('testDmiBasePath',
+                    'testCmhandle',
+                    'parent/child',
+                    '(a=1,b=2)',
+                    'testAcceptJson',
+                    'testJsonbody')
+        then: 'the put operation is executed with the correct URL'
+            1 * mockDmiRestClient.putOperationWithJsonData(expectedUrl, 'testJsonbody', _ as HttpHeaders)
+    }
+    def 'call get resource data for pass-through:operational datastore from DMI when options is null.'() {
         given: 'expected url'
         def expectedUrl = 'testDmiBasePath/dmi/v1/ch/testCmhandle/data/ds' +
-                '/ncmp-datastore:passthrough-running/testResourceId?fields=testFieldsQuery&depth=10'
+                '/ncmp-datastore:passthrough-operational?resourceIdentifier=parent/child'
         when: 'get resource data is called to DMI'
-        objectUnderTest.getResourceDataPassThroughRunningFromDmi('testDmiBasePath',
+        objectUnderTest.getResourceDataOperationalFromDmi('testDmiBasePath',
                 'testCmhandle',
-                'testResourceId',
-                'testFieldsQuery',
-                10,
+                'parent/child',
+                null,
                 'testAcceptJson',
                 'testJsonbody')
         then: 'the put operation is executed with the correct URL'
@@ -71,15 +83,15 @@ class DmiOperationsSpec extends Specification {
     }
     def 'call create resource data for pass-through:running datastore from DMI.'() {
         given: 'expected url'
-        def expectedUrl = 'testDmiBasePath/dmi/v1/ch/testCmhandle/data/ds' +
-                '/ncmp-datastore:passthrough-running/testResourceId'
+            def expectedUrl = 'testDmiBasePath/dmi/v1/ch/testCmhandle/data/ds' +
+                    '/ncmp-datastore:passthrough-running?resourceIdentifier=parent/child'
         when: 'get resource data is called to DMI'
-        objectUnderTest.createResourceDataPassThroughRunningFromDmi('testDmiBasePath',
-                'testCmhandle',
-                'testResourceId',
-                'testJsonbody')
+            objectUnderTest.createResourceDataPassThroughRunningFromDmi('testDmiBasePath',
+                    'testCmhandle',
+                    'parent/child',
+                    'testJsonbody')
         then: 'the put operation is executed with the correct URL'
-        1 * mockDmiRestClient.postOperationWithJsonData(expectedUrl, 'testJsonbody', _ as HttpHeaders)
+            1 * mockDmiRestClient.postOperationWithJsonData(expectedUrl, 'testJsonbody', _ as HttpHeaders)
     }
 
     def 'Call get resource from dmi.'() {
index d1665be..43e8175 100644 (file)
@@ -6,7 +6,7 @@
   },
   {
     "moduleName": "module2",
-    "revision": "1",
+    "revision": "2",
     "namespace": "some namespace"
   }]
 }
\ No newline at end of file
index ae26868..3e6ab83 100644 (file)
@@ -106,6 +106,7 @@ Swagger UI and Open API specifications are available to discover service endpoin
 * `http://localhost:<port-number>/swagger-ui.html`
 * `http://localhost:<port-number>/api-docs/cps-core/openapi.yaml`
 * `http://localhost:<port-number>/api-docs/cps-ncmp/openapi.yaml`
+* `http://localhost:<port-number>/api-docs/cps-ncmp/openapi-inventory.yaml`
 
 with <port-number> being either `8080` if running the plain Java build or retrieved using following command
 if running from `docker-compose`:
diff --git a/docs/_static/cps-r8-arch-diagram.png b/docs/_static/cps-r8-arch-diagram.png
deleted file mode 100644 (file)
index f5a90a6..0000000
Binary files a/docs/_static/cps-r8-arch-diagram.png and /dev/null differ
diff --git a/docs/_static/cps-r9-arch-diagram.png b/docs/_static/cps-r9-arch-diagram.png
new file mode 100644 (file)
index 0000000..1818041
Binary files /dev/null and b/docs/_static/cps-r9-arch-diagram.png differ
diff --git a/docs/_static/star.png b/docs/_static/star.png
new file mode 100644 (file)
index 0000000..570345c
Binary files /dev/null and b/docs/_static/star.png differ
index 8e917e1..3a6f8e2 100644 (file)
@@ -9,10 +9,64 @@
 CPS Admin Guide
 ###############
 
-.. warning:: draft
-
 .. toctree::
    :maxdepth: 1
 
 Logging & Diagnostics
 =====================
+
+General Guidelines
+------------------
+CPS-Core logs are sent to `STDOUT` in order to leverage the Kubernetes logging architecture.
+
+These logs are available using the following command:
+
+.. code:: bash
+
+    kubectl logs <cps-core-pod>
+
+The default configuration for CPS logs is the INFO level.
+
+This architecture also makes all logs ready to be sent to an Elastic-search Log-stash and Kibana (ELK) stack or similar.
+
+Enabling tracing for all executed sql statements is done by changing hibernate
+loggers log level
+
+Logger configuration is provided as a chart resource :
+
+    +--------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+    | cps-component-service-name     | logback.xml location                                                                                                            |
+    +================================+=================================================================================================================================+
+    | cps-core                       | `logback.xml <https://github.com/onap/oom/blob/master/kubernetes/cps/components/cps-core/resources/config/logback.xml>`_        |
+    +--------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+    | cps-temporal                   | `logback.xml <https://github.com/onap/oom/blob/master/kubernetes/cps/components/cps-temporal/resources/config/logback.xml>`_    |
+    +--------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+    | ncmp-dmi-plugin                | Not yet applicable to DMI-Plugin                                                                                                |
+    +--------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+
+Monitoring
+==========
+Once CPS-Core is deployed, information related to the running instance of the application is available
+
+.. code::
+
+    http://<cps-component-service-name>:8081/manage/info/
+
+Health
+------
+
+Cps-Core health status and state can be checked using the following endpoint.
+This also includes both the liveliness state and readiness state.
+
+.. code::
+
+    http://<cps-component-service-name>:8081/manage/health/
+
+Metrics
+-------
+
+Prometheus Metrics can be checked at the following endpoint
+
+.. code::
+
+    http://<cps-component-service-name>:8081/manage/prometheus
\ No newline at end of file
diff --git a/docs/api/swagger/ncmp/openapi-inventory.yaml b/docs/api/swagger/ncmp/openapi-inventory.yaml
new file mode 100644 (file)
index 0000000..627816b
--- /dev/null
@@ -0,0 +1,88 @@
+openapi: 3.0.1
+info:
+  title: NCMP Inventory API
+  description: NCMP Inventory API
+  version: "1.0"
+servers:
+- url: /ncmpInventory
+paths:
+  /v1/ch:
+    post:
+      tags:
+      - network-cm-proxy-inventory
+      summary: DMI notifies NCMP of new CM Handles
+      description: "Register a DMI Plugin with any new, updated or removed CM Handles."
+      operationId: updateDmiPluginRegistration
+      requestBody:
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/RestDmiPluginRegistration'
+        required: true
+      responses:
+        "201":
+          description: Created
+          content: {}
+        "400":
+          description: Bad Request
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+        "401":
+          description: Unauthorized
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+        "403":
+          description: Forbidden
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorMessage'
+components:
+  schemas:
+    RestDmiPluginRegistration:
+      type: object
+      properties:
+        dmiPlugin:
+          type: string
+          example: onap-dmi-plugin
+        createdCmHandles:
+          type: array
+          items:
+            $ref: '#/components/schemas/RestCmHandle'
+        updatedCmHandles:
+          type: array
+          items:
+            $ref: '#/components/schemas/RestCmHandle'
+        removedCmHandles:
+          type: array
+          items:
+            type: string
+    RestCmHandle:
+      required:
+      - cmHandle
+      type: object
+      properties:
+        cmHandle:
+          type: string
+          example: cmHandle123
+        cmHandleProperties:
+          $ref: '#/components/schemas/RestCmHandleAdditionalProperties'
+    RestCmHandleAdditionalProperties:
+      type: object
+      additionalProperties:
+        type: string
+        example: system-001
+    ErrorMessage:
+      title: Error
+      type: object
+      properties:
+        status:
+          type: string
+        message:
+          type: string
+        details:
+          type: string
diff --git a/docs/api/yang/dmiYangResource.yang b/docs/api/yang/dmiYangResource.yang
new file mode 100644 (file)
index 0000000..8e06a26
--- /dev/null
@@ -0,0 +1,46 @@
+module dmi-registry {
+
+  yang-version 1.1;
+
+  namespace \"org:onap:cps:ncmp\";
+
+  prefix dmi-reg;
+
+  organization \"Nordix Foundation\";
+
+  contact \"rahul.tyagi@est.tech\";
+
+  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;
+      }
+
+      list additional-properties {
+
+        key \"name\";
+
+        leaf name {
+          type string;
+        }
+
+        leaf value {
+          type string;
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
index b703cfa..26a8c63 100644 (file)
@@ -6,8 +6,6 @@
 CPS Architecture
 ################
 
-.. warning:: draft
-
 .. toctree::
    :maxdepth: 1
 
@@ -18,19 +16,24 @@ High Level Component Definition and Architectural Relationships
 The Configuration Persistence Service (CPS) provides storage for run-time configuration and operational
 parameters that need to be used by ONAP.
 
-In this release CPS is no longer a stand alone component and is released along with Cps-Temporal and the NCMP-DMI Plugin.
+In this release CPS is no longer a stand alone component and is released along with Cps-Temporal and the NCMP-DMI-Plugin.
 
 Project page describing eventual scope and ambition is here:
 `Configuration Persistence Service Project <https://wiki.onap.org/display/DW/Configuration+Persistence+Service+Project>`_
 
 This page reflects the state for Istanbul-R9 release.
 
-.. image:: _static/cps-r8-arch-diagram.png
+.. image:: _static/star.png
+    :class: float-left
+
+**Note:** SDC and AAI interfaces have not yet been implemented.
+
+.. image:: _static/cps-r9-arch-diagram.png
 
 API definitions
 ===============
 
-Configuration Persistence Service provides following interfaces.
+Configuration Persistence Service provides the following interfaces.
 
 .. list-table::
    :header-rows: 1
@@ -41,7 +44,7 @@ Configuration Persistence Service provides following interfaces.
      - Protocol
    * - CPS-E-01
      - Administrative Data Management
-     - - create/delete dataspace
+     - - create dataspace
        - create/delete schema set
        - create/delete anchor
      - REST
@@ -57,12 +60,25 @@ Configuration Persistence Service provides following interfaces.
      - REST
    * - CPS-E-04
      - Change Notification
-     - *Not available in Honolulu-R8*
-     - *N/A*
+     - - Kafka is used as the event messaging system
+       - running instance is supplied independently from ONAP DMaaP component or any Kafka instance deployed from ONAP
+       - published events contain Timestamp, Dataspace, Schema set, Anchor and JSON Data Payload
+     - DMaaP
    * - CPS-E-05
      - xNF Data Access
      - - read xNF data
        - query xNF data
      - REST
+   * - CPS-E-06
+     - Temporal Data Access
+     - - data storage and access
+     - REST
+   * - CPS-E-07
+     - Admin
+     - - logging levels and configuration
+       - monitoring
+       - health including liveliness state and readiness state
+       - metrics through Prometheus
+     - Various
 
 The CPS Basic Concepts are described in :doc:`modeling`.
index cb26548..5834d68 100644 (file)
@@ -9,8 +9,6 @@
 CPS Path
 ########
 
-.. warning:: draft
-
 .. toctree::
    :maxdepth: 1
 
index f9f12de..02836c5 100755 (executable)
@@ -9,22 +9,37 @@
 CPS Design
 ##########
 
-.. warning:: draft
-
 .. toctree::
    :maxdepth: 1
 
 Offered APIs
 ============
 
-CPS supports the public APIs listed in the link below:
+CPS supports the public APIs listed in the following sections.
+
+CPS-Core
+--------
+
+CPS-Core functionality.
 
 :download:`CPS Rest OpenApi Specification <api/swagger/cps/openapi.yaml>`
 
+CPS-NCMP
+--------
+
+XNF data access and module information.
+
 :download:`CPS NCMP RestOpenApi Specification <api/swagger/ncmp/openapi.yaml>`
 
-Exposed API
------------
+CPS-NCMP-Inventory
+------------------
+
+DMI-Plugin Inventory.
+
+:download:`CPS NCMP RestOpenApi Inventory Specification <api/swagger/ncmp/openapi-inventory.yaml>`
+
+View Offered APIs
+-----------------
 
 The standard for API definition in the RESTful API world is the OpenAPI Specification (OAS).
 The OAS 3, which is based on the original "Swagger Specification", is being widely used in API developments.
@@ -33,7 +48,23 @@ Specification can be accessed using following URI:
 
 .. code-block:: bash
 
-  “http://<hostname>:<port>/v3/api-docs?group=cps-docket”
+  http://<hostname>:<port>/v3/api-docs?group=cps-docket
+
+Additionally, the Swagger User Interface can be found at the following URI. The component may be changed between CPS-Core, CPS-NCMP
+and CPS-NCMP-Inventory using the drop down table in the top right:
+
+.. code-block:: bash
+
+  http://<hostname>:<port>/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/
+
+Consumed APIs
+=============
+
+CPS Core uses API's from the following ONAP components
+
+* DMI-Plugin: REST based interface which is used to provide integration
+  and allow the DMI registry API's have access to the corresponding NCMP API's within CPS Core.
+  More information on the DMI-Plugins offered APIs can be found on the `DMI-Plugin's Design Page <https://docs.onap.org/projects/onap-cps-ncmp-dmi-plugin/en/latest/design.html>`_.
 
 CPS Path
 ========
index ec9753f..cbe1b69 100755 (executable)
@@ -8,10 +8,8 @@
 .. THIS IS USED INTERNALLY IN CPS ONLY
 .. _cps-framework-doc:
 
-CPS-Core Documentation
-----------------------
-
-.. warning:: draft
+CPS Documentation
+-----------------
 
 .. toctree::
    :maxdepth: 1
@@ -24,12 +22,12 @@ CPS-Core Documentation
    deployment.rst
    release-notes.rst
 
-ONAP DMI Plugin Documentation
+DMI-Plugin Documentation
 -----------------------------
 
-* `DMI Plugin(placeholder)  `_
+* `DMI-Plugin <https://docs.onap.org/projects/onap-cps-ncmp-dmi-plugin/en/latest/index.html>`_
 
 CPS-Temporal Documentation
 --------------------------
 
-* `CPS Temporal(placeholder)  `_
+* `CPS-Temporal <https://docs.onap.org/projects/onap-cps-cps-temporal/en/latest/index.html>`_
index 22c4b0b..a91eb01 100644 (file)
@@ -3,20 +3,24 @@
 .. Copyright (C) 2021 Pantheon.tech
 .. _modeling:
 
+.. toctree::
+   :maxdepth: 1
+
 CPS Modeling
 ############
 
-.. warning:: draft
+CPS-Core Modeling
+=================
 
-.. toctree::
-   :maxdepth: 1
-
-Basic Concepts
-==============
+Data Model
+----------
 
 .. image:: _static/cps-modeling-concepts.png
    :alt: Basic entities relationship
 
+Basic Concepts
+--------------
+
 Administrative entities
 
 - **Dataspace** is a primary logical separation of data.
@@ -30,7 +34,7 @@ Administrative entities
   and uniquely identified by its name (within its own dataspace). Same YANG resources (source files) can be
   referenced by multiple schema sets from different dataspaces.
 
-- **Anchor** identifies the unique data set (data record) within a dataspace
+- **Anchor** identifies the unique data set (data record) within a dataspace.
 
   Anchor always references a schema set within same dataspace which describes a data model of associated data.
   Multiple anchors may reference same schema set. Anchor is uniquely identified by its name (within own dataspace).
@@ -50,13 +54,33 @@ Data
 
 Querying
 
-- **CPS Path** is used to query data nodes. The CPS Path is described in detail in the :doc:`cps-path` sub-page.
+- **CPS Path** is used to query data nodes. The CPS Path is described in detail in :doc:`cps-path`.
 
-CPS Path
-========
+NCMP Modeling
+=============
 
-.. toctree::
-   :maxdepth: 1
+Data Model
+----------
+
+NCMP stores DMI-Plugin and CM Handle relations using a data model described as per this Yang module.
+
+:download:`DMI Yang Module <api/yang/dmiYangResource.yang>`
+
+Basic Concepts
+--------------
+
+- **CM-Handle** represents an instance a modeled Network Function(node) in ONAP.
+
+    These are stored as Anchors within CPS-Core.
+
+- **Datastores** represent different views of the cm data.
 
-   cps-path.rst
+    Datastores are defined for NCMP to access the CPS running or operational datastores. Currently supported datastores are:
 
+    +--------------------------------+-------------------------------------+-------------------------+
+    | Datastore                      | Configurations                      | Data access type        |
+    +================================+=====================================+=========================+
+    | Passthrough-operational        | config-true, config-false           | read-only               |
+    +--------------------------------+-------------------------------------+-------------------------+
+    | Passthrough-running            | config-true                         | read-write              |
+    +--------------------------------+-------------------------------------+-------------------------+
\ No newline at end of file
index b1f4755..4b69dd8 100644 (file)
@@ -6,8 +6,6 @@
 CPS Overview
 ============
 
-.. warning:: draft
-
 The Configuration Persistence Service (CPS) is a platform component that is designed to serve as a
 data repository for runtime data that needs persistence.
 
@@ -29,6 +27,35 @@ Types of data that is stored:
   information, meaning it is information that doesn't belong in A&AI. In principle, some parameters might be both
   configuration and operational parameters depending on how they are used.
 
+CPS Components
+--------------
+
+CPS-Core
+########
+This is the component of CPS which encompasses the generic storage of Yang module data.
+
+**NCMP**
+
+The Network Configuration Management Proxy (NCMP) provides access to network configuration data and is a part of CPS-Core.
+NCMP accesses all network Data-Model-Inventory (DMI) information via NCMP-DMI-Plugins. The ONAP0-DMI-Plugin described in the next section is one such plugin.
+
+**Note:** This documentation will often refer to "CPS-NCMP" which is the component (container image) that contains both CPS-Core and NCMP since NCMP is not a stand-alone component
+even though CPS-Core could be deployed without the NCMP extension.
+
+NCMP-DMI-Plugin
+####################
+
+The Data-Model-Inventory (DMI) Plugin is a rest interface used to synchronize CM-Handles data between CPS and DMI through the DMI-Plugin.
+This is built previously from the CPS-NF-Proxy component.
+
+CPS-Temporal
+############
+
+This service is responsible to provide a time oriented perspective for
+operational network data. It provides features to store and retrieve sequences
+of configurations or states along with the associated times when they occurred
+or have been observed.
+
 CPS Project
 -----------
 
index 797a11c..6e5d917 100755 (executable)
@@ -11,8 +11,6 @@
 CPS Release Notes
 =================
 
-.. warning:: draft
-
 .. contents::
     :depth: 2
 ..
@@ -21,6 +19,60 @@ CPS Release Notes
 ..      * * *   ISTANBUL   * * *
 ..      ========================
 
+Version: 2.0.1
+==============
+
+Release Data
+------------
+
++--------------------------------------+--------------------------------------------------------+
+| **CPS Project**                      |                                                        |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+| **Docker images**                    | onap/cps-and-ncmp:2.0.1                                |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+| **Release designation**              | 2.0.1 Istanbul                                         |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+| **Release date**                     | 2021-14-10                                             |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+
+Bug Fixes
+---------
+
+   - `CPS-594 <https://jira.onap.org/browse/CPS-594>`_ SQL ConstraintViolationException when updating the list node element using PATCH List node API
+   - `CPS-653 <https://jira.onap.org/browse/CPS-653>`_ cmHandleProperties not supported by dmi in fetch modules
+   - `CPS-673 <https://jira.onap.org/browse/CPS-673>`_ Improvement and cleanup for CPS Core charts
+   - `CPS-691 <https://jira.onap.org/browse/CPS-691>`_ NCMP no master index label on index documentation page
+
+Known Limitations, Issues and Workarounds
+-----------------------------------------
+
+*System Limitations*
+
+Limitations to the amount of child nodes that can be added to the fix above. The current limit is 3.
+
+*Known Vulnerabilities*
+
+   - `CPS-725 <https://jira.onap.org/browse/CPS-725>`_ fix sample docker compose of cps/ncmp and onap dmi plugin
+
+*Workarounds*
+
+Add recursive method to save list node data to loop through all corresponding child nodes.
+
+Security Notes
+--------------
+
+*Fixed Security Issues*
+
+   - `CPS-581 <https://jira.onap.org/browse/CPS-581>`_ Remove security vulnerabilities
+
+*Known Security Issues*
+
+None
+
 Version: 2.0.0
 ==============
 
@@ -42,19 +94,17 @@ Release Data
 | **Release designation**              | 2.0.0 Istanbul                                         |
 |                                      |                                                        |
 +--------------------------------------+--------------------------------------------------------+
-| **Release date**                     | 2021-14-10                                             |
+| **Release date**                     | 2021-14-09                                             |
 |                                      |                                                        |
 +--------------------------------------+--------------------------------------------------------+
 
 Features
 --------
-* Register DMI Plugins with NCMP for CM Handle registrations.
+* Register DMI-Plugins with NCMP for CM Handle registrations.
 * Update, Create and Remove CM Handles.
 * Add support for retrieving and writing CM Handle data through NCMP datastores.
 * Automatic retrieval and caching of model information for CM Handles within NCMP.
 
-.. _istanbul_deliverable:
-
 Deliverables
 ------------
 
@@ -69,22 +119,32 @@ Software Deliverables
 Bug Fixes
 ---------
 
+   - `CPS-310 <https://jira.onap.org/browse/CPS-310>`_ Data schema migration from Honolulu to Istanbul is failing
    - `CPS-316 <https://jira.onap.org/browse/CPS-316>`_ Xpath cannot be created for augmentation data node
    - `CPS-336 <https://jira.onap.org/browse/CPS-336>`_ Ends-with functionality in cpsPath does not conform with standard xPath behavior
+   - `CPS-345 <https://jira.onap.org/browse/CPS-345>`_ Leaf String value comparison matches mix of single and double quotes
+   - `CPS-357 <https://jira.onap.org/browse/CPS-357>`_ cps-review-verification-maven-master Jenkins job is failing when running csit test
    - `CPS-367 <https://jira.onap.org/browse/CPS-367>`_ Get descendent does not support xpaths that end in list values
-   - `CPS-377 <https://jira.onap.org/browse/CPS-377>`_ Init ran model validation is failing, error details are not provided
+   - `CPS-377 <https://jira.onap.org/browse/CPS-377>`_ Init ran model validation is failing error details are not provided
    - `CPS-422 <https://jira.onap.org/browse/CPS-422>`_ REST 404 response returned instead of 400 for POST/PUT/PATCH request types
    - `CPS-450 <https://jira.onap.org/browse/CPS-450>`_ Datanode query using full path to node causes NPE
+   - `CPS-451 <https://jira.onap.org/browse/CPS-451>`_ cps-ran-schema-model@2021-01-28.yang missing root container
+   - `CPS-464 <https://jira.onap.org/browse/CPS-464>`_ Request to update node leaves (patch) responds with Internal Server Error
+   - `CPS-465 <https://jira.onap.org/browse/CPS-465>`_ Request to update node leaves (patch) responds with json parsing failure
    - `CPS-466 <https://jira.onap.org/browse/CPS-466>`_ Concurrent requests to create schema sets for the same yang model are not supported
    - `CPS-479 <https://jira.onap.org/browse/CPS-479>`_ Get Nodes API does not always return the object from the root
+   - `CPS-500 <https://jira.onap.org/browse/CPS-500>`_ Special Character Limitations of cpsPath Queries
    - `CPS-501 <https://jira.onap.org/browse/CPS-501>`_ Put DataNode API has missing transaction and error handling for concurrency issues
-   - `CPS-504 <https://jira.onap.org/browse/CPS-504>`_ Checkstyle rules are not enforced for cps-ncmp-dmi-plugin
-   - `CPS-515 <https://jira.onap.org/browse/CPS-515>`_ Maven build is not failing when test containers are not able to run
-   - `CPS-520 <https://jira.onap.org/browse/CPS-520>`_ Fix docker profile in cps-temporal and cps-ncmp-dmi-plugin
    - `CPS-524 <https://jira.onap.org/browse/CPS-524>`_ Issue with CPSData API to add an item to an existing list node
    - `CPS-560 <https://jira.onap.org/browse/CPS-560>`_ Response from cps query using text() contains escape characters
    - `CPS-566 <https://jira.onap.org/browse/CPS-566>`_ Can't access grandparent node through ancestor axis
-   - `CPS-586 <https://jira.onap.org/browse/CPS-586>`_ App username and password environment variables are missing from temporal docker compose
+   - `CPS-573 <https://jira.onap.org/browse/CPS-573>`_ /v1/ch/PNFDemo1/modules returning 401 unauthorised.
+   - `CPS-587 <https://jira.onap.org/browse/CPS-587>`_ cps-ncmp-service NullpointerException when DmiPluginRegistration has no additionProperties
+   - `CPS-591 <https://jira.onap.org/browse/CPS-591>`_ CPS-Core Leaf stored as integer is being returned from DB as float
+   - `CPS-601 <https://jira.onap.org/browse/CPS-601>`_ CPS swagger-ui does not show NCMP endpoints   
+   - `CPS-616 <https://jira.onap.org/browse/CPS-616>`_ NCMP base path does not conform to agreed API URL
+   - `CPS-630 <https://jira.onap.org/browse/CPS-630>`_ Incorrect information sent when same anchor is updated faster than notification service processes
+   - `CPS-635 <https://jira.onap.org/browse/CPS-635>`_ Module Resource call does not include body
 
 This document provides the release notes for Istanbul release.
 
@@ -100,9 +160,9 @@ Following CPS components are available with default ONAP/CPS installation.
 
     * Service components
 
-        - CPS Core and NCMP
-        - CPS Temporal
-        - DMI Plugin
+        - CPS-NCMP
+        - CPS-Temporal
+        - DMI-Plugin
 
     * Additional resources that CPS utilizes deployed using ONAP common charts
 
@@ -118,15 +178,15 @@ Under OOM (Kubernetes) all CPS component containers are deployed as Kubernetes P
 Known Limitations, Issues and Workarounds
 -----------------------------------------
 
-   - `CPS-524 <https://jira.onap.org/browse/CPS-524>`_ Issue with CPSData API to add an item to an existing list node
-
 *System Limitations*
 
 Limitations to the amount of child nodes that can be added to the fix above. The current limit is 3.
 
 *Known Vulnerabilities*
 
-None
+   - `CPS-594 <https://jira.onap.org/browse/CPS-594>`_ SQL ConstraintViolationException when updating the list node element using PATCH List node API
+   - `CPS-653 <https://jira.onap.org/browse/CPS-653>`_ cmHandleProperties not supported by dmi in fetch modules
+   - `CPS-673 <https://jira.onap.org/browse/CPS-673>`_ Improvement and cleanup for CPS Core charts
 
 *Workarounds*
 
@@ -138,10 +198,11 @@ Security Notes
 *Fixed Security Issues*
 
    - `CPS-249 <https://jira.onap.org/browse/CPS-249>`_ Exception stack trace is exposed
-   - `CPS-581 <https://jira.onap.org/browse/CPS-581>`_ Remove security vulnerabilities
 
 *Known Security Issues*
 
+   - `CPS-581 <https://jira.onap.org/browse/CPS-581>`_ Remove security vulnerabilities
+
 Test Results
 ------------
     * `Integration tests`