diff options
32 files changed, 866 insertions, 349 deletions
diff --git a/cps-application/src/main/resources/application.yml b/cps-application/src/main/resources/application.yml index 42addf1b0c..6717d4e92b 100644 --- a/cps-application/src/main/resources/application.yml +++ b/cps-application/src/main/resources/application.yml @@ -25,6 +25,7 @@ rest: api:
cps-base-path: /cps/api
ncmp-base-path: /ncmp
+ ncmp-inventory-base-path: /ncmpInventory
spring:
main:
@@ -93,10 +94,13 @@ springdoc: url: /api-docs/cps-core/openapi.yaml
- name: cps-ncmp
url: /api-docs/cps-ncmp/openapi.yaml
+ - name: cps-ncmp-inventory
+ url: /api-docs/cps-ncmp/openapi-inventory.yaml
+
security:
# comma-separated uri patterns which do not require authorization
- permit-uri: /manage/**,/swagger-ui/**,/swagger-resources/**,/api-docs
+ permit-uri: /manage/**,/swagger-ui.html,/swagger-ui/**,/swagger-resources/**,/api-docs/**
auth:
username: ${CPS_USERNAME}
password: ${CPS_PASSWORD}
diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml index ffb8dde113..d35919da4b 100644 --- a/cps-ncmp-rest/docs/openapi/components.yaml +++ b/cps-ncmp-rest/docs/openapi/components.yaml @@ -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 index 0000000000..b0a50aa83a --- /dev/null +++ b/cps-ncmp-rest/docs/openapi/ncmp-inventory.yml @@ -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' diff --git a/cps-ncmp-rest/docs/openapi/ncmproxy.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml index 2e5eba754d..52245c3cc0 100755 --- a/cps-ncmp-rest/docs/openapi/ncmproxy.yml +++ b/cps-ncmp-rest/docs/openapi/ncmp.yml @@ -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 index 0000000000..ee09d050f3 --- /dev/null +++ b/cps-ncmp-rest/docs/openapi/openapi-inventory.yml @@ -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' diff --git a/cps-ncmp-rest/docs/openapi/openapi.yml b/cps-ncmp-rest/docs/openapi/openapi.yml index 12356b5887..69c2a117d6 100755 --- a/cps-ncmp-rest/docs/openapi/openapi.yml +++ b/cps-ncmp-rest/docs/openapi/openapi.yml @@ -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 diff --git a/cps-ncmp-rest/pom.xml b/cps-ncmp-rest/pom.xml index b47ea17331..c4c72bb93b 100644 --- a/cps-ncmp-rest/pom.xml +++ b/cps-ncmp-rest/pom.xml @@ -112,7 +112,7 @@ <artifactId>swagger-codegen-maven-plugin</artifactId> <executions> <execution> - <id>code-gen</id> + <id>ncmp-code-gen</id> <goals> <goal>generate</goal> </goals> @@ -131,6 +131,40 @@ </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> @@ -148,7 +182,7 @@ <resource> <directory>${project.basedir}/target/generated-sources/swagger/</directory> <includes> - <include>openapi.yaml</include> + <include>openapi*.yaml</include> </includes> </resource> </resources> diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java index a4d94cebfd..9b15a7890d 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java @@ -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. @@ -21,18 +22,13 @@ 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; } /** @@ -102,19 +93,6 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { } /** - * 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 index 0000000000..3b72cec389 --- /dev/null +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java @@ -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); + } + +} diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy index 9f2b4e19a3..342f41b26f 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy @@ -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 index 0000000000..e558ac45bf --- /dev/null +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy @@ -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() + } + +} + diff --git a/cps-ncmp-rest/src/test/resources/application.yml b/cps-ncmp-rest/src/test/resources/application.yml index 848738a764..f2ca8c759b 100644 --- a/cps-ncmp-rest/src/test/resources/application.yml +++ b/cps-ncmp-rest/src/test/resources/application.yml @@ -20,4 +20,4 @@ rest: api: ncmp-base-path: /ncmp -spring: + ncmp-inventory-base-path: /ncmpInventory diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java index 2f91ed30e1..cb2f78206c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java @@ -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 diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index 291b0bf330..d6aaf36d3a 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -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"); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operation/DmiOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operation/DmiOperations.java index 71af3d4cfe..f7421cdb71 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operation/DmiOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operation/DmiOperations.java @@ -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; } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy index 2b376e97bf..1bad8ce0ba 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy @@ -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 } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operation/DmiOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operation/DmiOperationsSpec.groovy index 6a1ce1a18b..9405b66325 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operation/DmiOperationsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operation/DmiOperationsSpec.groovy @@ -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.'() { diff --git a/cps-ncmp-service/src/test/resources/cmHandleModules.json b/cps-ncmp-service/src/test/resources/cmHandleModules.json index d1665bee7d..43e8175ca0 100644 --- a/cps-ncmp-service/src/test/resources/cmHandleModules.json +++ b/cps-ncmp-service/src/test/resources/cmHandleModules.json @@ -6,7 +6,7 @@ }, { "moduleName": "module2", - "revision": "1", + "revision": "2", "namespace": "some namespace" }] }
\ No newline at end of file diff --git a/docker-compose/README.md b/docker-compose/README.md index ae26868224..3e6ab8367e 100644 --- a/docker-compose/README.md +++ b/docker-compose/README.md @@ -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 Binary files differdeleted file mode 100644 index f5a90a6ea1..0000000000 --- a/docs/_static/cps-r8-arch-diagram.png +++ /dev/null diff --git a/docs/_static/cps-r9-arch-diagram.png b/docs/_static/cps-r9-arch-diagram.png Binary files differnew file mode 100644 index 0000000000..181804139b --- /dev/null +++ b/docs/_static/cps-r9-arch-diagram.png diff --git a/docs/_static/star.png b/docs/_static/star.png Binary files differnew file mode 100644 index 0000000000..570345c77f --- /dev/null +++ b/docs/_static/star.png diff --git a/docs/admin-guide.rst b/docs/admin-guide.rst index 8e917e1f51..3a6f8e2559 100644 --- a/docs/admin-guide.rst +++ b/docs/admin-guide.rst @@ -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 index 0000000000..627816bf8f --- /dev/null +++ b/docs/api/swagger/ncmp/openapi-inventory.yaml @@ -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 index 0000000000..8e06a26948 --- /dev/null +++ b/docs/api/yang/dmiYangResource.yang @@ -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 diff --git a/docs/architecture.rst b/docs/architecture.rst index b703cfa535..26a8c63b52 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -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`. diff --git a/docs/cps-path.rst b/docs/cps-path.rst index cb26548de2..5834d68e1e 100644 --- a/docs/cps-path.rst +++ b/docs/cps-path.rst @@ -9,8 +9,6 @@ CPS Path ######## -.. warning:: draft - .. toctree:: :maxdepth: 1 diff --git a/docs/design.rst b/docs/design.rst index f9f12de432..02836c5f37 100755 --- a/docs/design.rst +++ b/docs/design.rst @@ -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 ======== diff --git a/docs/index.rst b/docs/index.rst index ec9753ff00..cbe1b69d08 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -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>`_ diff --git a/docs/modeling.rst b/docs/modeling.rst index 22c4b0ba32..a91eb0178a 100644 --- a/docs/modeling.rst +++ b/docs/modeling.rst @@ -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 diff --git a/docs/overview.rst b/docs/overview.rst index b1f4755b66..4b69dd8109 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -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 ----------- diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 797a11cf5f..6e5d917ab4 100755 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -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` |