diff options
18 files changed, 149 insertions, 1011 deletions
diff --git a/cps-ncmp-rest/docs/openapi/ncmp.yml b/cps-ncmp-rest/docs/openapi/ncmp.yml index 7845a34ad6..71b4f1c453 100755 --- a/cps-ncmp-rest/docs/openapi/ncmp.yml +++ b/cps-ncmp-rest/docs/openapi/ncmp.yml @@ -1,5 +1,5 @@ # ============LICENSE_START======================================================= -# Copyright (C) 2021 Nordix Foundation +# Copyright (C) 2021-2022 Nordix Foundation # Modifications Copyright (C) 2021 Pantheon.tech # Modifications Copyright (C) 2021 Bell Canada # ================================================================================ @@ -17,181 +17,6 @@ # # SPDX-License-Identifier: Apache-2.0 # ============LICENSE_END========================================================= - -nodeByCmHandleAndXpath: - get: - description: Get a node with an option to retrieve all the children for a given cm Handle - deprecated: true - tags: - - network-cm-proxy - summary: Get a node given a cm Handle and xpath - operationId: getNodeByCmHandleAndXpath - parameters: - - $ref: 'components.yaml#/components/parameters/cmHandleInPath' - - $ref: 'components.yaml#/components/parameters/xpathInQuery' - - $ref: 'components.yaml#/components/parameters/includeDescendantsOptionInQuery' - responses: - 200: - $ref: 'components.yaml#/components/responses/Ok' - 400: - $ref: 'components.yaml#/components/responses/BadRequest' - 401: - $ref: 'components.yaml#/components/responses/Unauthorized' - 403: - $ref: 'components.yaml#/components/responses/Forbidden' - 404: - $ref: 'components.yaml#/components/responses/NotFound' - -nodesByCmHandleAndCpsPath: - get: - description: Query nodes for the given cps path and cm Handle - deprecated: true - tags: - - network-cm-proxy - summary: Query data nodes - operationId: queryNodesByCmHandleAndCpsPath - parameters: - - $ref: 'components.yaml#/components/parameters/cmHandleInPath' - - $ref: 'components.yaml#/components/parameters/cpsPathInQuery' - - $ref: 'components.yaml#/components/parameters/includeDescendantsOptionInQuery' - responses: - 200: - $ref: 'components.yaml#/components/responses/Ok' - 400: - $ref: 'components.yaml#/components/responses/BadRequest' - 401: - $ref: 'components.yaml#/components/responses/Unauthorized' - 403: - $ref: 'components.yaml#/components/responses/Forbidden' - 404: - $ref: 'components.yaml#/components/responses/NotFound' - -nodesByCmHandleAndXpath: - post: - description: Create a node with descendants for the given CM Handle; top level or under existing node (requires xpath) - deprecated: true - tags: - - network-cm-proxy - summary: Create a node with descendants - operationId: createNode - parameters: - - $ref: 'components.yaml#/components/parameters/cmHandleInPath' - - $ref: 'components.yaml#/components/parameters/xpathInQuery' - requestBody: - required: true - content: - application/json: - schema: - type: object - examples: - dataSampleRequest: - $ref: 'components.yaml#/components/examples/dataSampleRequest' - 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' - 404: - $ref: 'components.yaml#/components/responses/NotFound' - - patch: - description: Update node leaves for the given cps path and cm Handle - deprecated: true - tags: - - network-cm-proxy - summary: Update node leaves - operationId: updateNodeLeaves - parameters: - - $ref: 'components.yaml#/components/parameters/cmHandleInPath' - - $ref: 'components.yaml#/components/parameters/xpathInQuery' - requestBody: - required: true - content: - application/json: - schema: - type: object - examples: - dataSampleRequest: - $ref: 'components.yaml#/components/examples/dataSampleRequest' - responses: - 200: - $ref: 'components.yaml#/components/responses/Ok' - 400: - $ref: 'components.yaml#/components/responses/BadRequest' - 401: - $ref: 'components.yaml#/components/responses/Unauthorized' - 403: - $ref: 'components.yaml#/components/responses/Forbidden' - 404: - $ref: 'components.yaml#/components/responses/NotFound' - - put: - description: Replace a node with descendants for the given cps path and cm Handle - deprecated: true - tags: - - network-cm-proxy - summary: Replace a node with descendants - operationId: replaceNode - parameters: - - $ref: 'components.yaml#/components/parameters/cmHandleInPath' - - $ref: 'components.yaml#/components/parameters/xpathInQuery' - requestBody: - required: true - content: - application/json: - schema: - type: object - examples: - dataSampleRequest: - $ref: 'components.yaml#/components/examples/dataSampleRequest' - responses: - 200: - $ref: 'components.yaml#/components/responses/Ok' - 400: - $ref: 'components.yaml#/components/responses/BadRequest' - 401: - $ref: 'components.yaml#/components/responses/Unauthorized' - 403: - $ref: 'components.yaml#/components/responses/Forbidden' - 404: - $ref: 'components.yaml#/components/responses/NotFound' - -listNodeByCmHandleAndXpath: - post: - description: Add one or more list-node child elements under existing node for the given CM Handle - deprecated: true - tags: - - network-cm-proxy - summary: Add list-node child element(s) - operationId: addListNodeElements - parameters: - - $ref: 'components.yaml#/components/parameters/cmHandleInPath' - - $ref: 'components.yaml#/components/parameters/requiredXpathInQuery' - requestBody: - required: true - content: - application/json: - schema: - type: object - examples: - dataSampleRequest: - $ref: 'components.yaml#/components/examples/dataSampleRequest' - 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' - 404: - $ref: 'components.yaml#/components/responses/NotFound' - getResourceDataForPassthroughOperational: get: tags: diff --git a/cps-ncmp-rest/docs/openapi/openapi.yml b/cps-ncmp-rest/docs/openapi/openapi.yml index 64a74c5933..838a0d08ed 100755 --- a/cps-ncmp-rest/docs/openapi/openapi.yml +++ b/cps-ncmp-rest/docs/openapi/openapi.yml @@ -1,5 +1,5 @@ # ============LICENSE_START======================================================= -# Copyright (C) 2021 Nordix Foundation +# Copyright (C) 2021-2022 Nordix Foundation # Modifications Copyright (C) 2021 Pantheon.tech # Modifications Copyright (C) 2021 Bell Canada # ================================================================================ @@ -26,18 +26,6 @@ info: servers: - url: /ncmp paths: - /v1/cm-handles/{cm-handle}/node: - $ref: 'ncmp.yml#/nodeByCmHandleAndXpath' - - /v1/cm-handles/{cm-handle}/list-node: - $ref: 'ncmp.yml#/listNodeByCmHandleAndXpath' - - /v1/cm-handles/{cm-handle}/nodes/query: - $ref: 'ncmp.yml#/nodesByCmHandleAndCpsPath' - - /v1/cm-handles/{cm-handle}/nodes: - $ref: 'ncmp.yml#/nodesByCmHandleAndXpath' - /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-operational: $ref: 'ncmp.yml#/getResourceDataForPassthroughOperational' 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 e3c457eaf4..a97852fe2b 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 @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 Pantheon.tech - * Modifications (C) 2021 Nordix Foundation + * Modifications (C) 2021-2022 Nordix Foundation * Modification Copyright (C) 2021 highstreet technologies GmbH * Modifications (C) 2021 Bell Canada * ================================================================================ @@ -48,9 +48,6 @@ import org.onap.cps.ncmp.rest.model.Conditions; import org.onap.cps.ncmp.rest.model.ModuleNameAsJsonObject; import org.onap.cps.ncmp.rest.model.ModuleNamesAsJsonArray; import org.onap.cps.ncmp.rest.model.ModuleReference; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.utils.DataMapUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; @@ -76,89 +73,6 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { } /** - * Create Node. - * @deprecated This Method is no longer used as part of NCMP. - */ - // All deprecated APIs methods will be address into https://jira.onap.org/browse/CPS-642 - @Override - @Deprecated(forRemoval = false) - public ResponseEntity<Void> createNode(final String cmHandle, @Valid final Object jsonData, - @Valid final String parentNodeXpath) { - networkCmProxyDataService.createDataNode(cmHandle, parentNodeXpath, GSON.toJson(jsonData)); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - /** - * Add List-node Child Element. - * @deprecated This Method is no longer used as part of NCMP. - */ - // All deprecated APIs methods will be address into https://jira.onap.org/browse/CPS-642 - @Override - @Deprecated(forRemoval = false) - public ResponseEntity<Void> addListNodeElements(@NotNull @Valid final String parentNodeXpath, - final String cmHandle, @Valid final Object jsonData) { - networkCmProxyDataService.addListNodeElements(cmHandle, parentNodeXpath, GSON.toJson(jsonData)); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - /** - * Get Node By CM Handle and X-Path. - * @deprecated This Method is no longer used as part of NCMP. - */ - // All deprecated APIs methods will be address into https://jira.onap.org/browse/CPS-642 - @Override - @Deprecated(forRemoval = false) - public ResponseEntity<Object> getNodeByCmHandleAndXpath(final String cmHandle, @Valid final String xpath, - @Valid final Boolean includeDescendants) { - final FetchDescendantsOption fetchDescendantsOption = Boolean.TRUE.equals(includeDescendants) - ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS : FetchDescendantsOption.OMIT_DESCENDANTS; - final var dataNode = networkCmProxyDataService.getDataNode(cmHandle, xpath, fetchDescendantsOption); - return new ResponseEntity<>(DataMapUtils.toDataMap(dataNode), HttpStatus.OK); - } - - /** - * Query Data Nodes. - * @deprecated This Method is no longer used as part of NCMP. - */ - // All deprecated APIs methods will be address into https://jira.onap.org/browse/CPS-642 - @Override - @Deprecated(forRemoval = false) - public ResponseEntity<Object> queryNodesByCmHandleAndCpsPath(final String cmHandle, @Valid final String cpsPath, - @Valid final Boolean includeDescendants) { - final FetchDescendantsOption fetchDescendantsOption = Boolean.TRUE.equals(includeDescendants) - ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS : FetchDescendantsOption.OMIT_DESCENDANTS; - final Collection<DataNode> dataNodes = - networkCmProxyDataService.queryDataNodes(cmHandle, cpsPath, fetchDescendantsOption); - return new ResponseEntity<>(GSON.toJson(dataNodes), HttpStatus.OK); - } - - /** - * Replace Node With Descendants. - * @deprecated This Method is no longer used as part of NCMP. - */ - // All deprecated APIs methods will be address into https://jira.onap.org/browse/CPS-642 - @Override - @Deprecated(forRemoval = false) - public ResponseEntity<Object> replaceNode(final String cmHandle, @Valid final Object jsonData, - @Valid final String parentNodeXpath) { - networkCmProxyDataService.replaceNodeTree(cmHandle, parentNodeXpath, GSON.toJson(jsonData)); - return new ResponseEntity<>(HttpStatus.OK); - } - - /** - * Update Node Leaves. - * @deprecated This Method is no longer used as part of NCMP. - */ - // All deprecated APIs methods will be address into https://jira.onap.org/browse/CPS-642 - @Override - @Deprecated(forRemoval = false) - public ResponseEntity<Object> updateNodeLeaves(final String cmHandle, @Valid final Object jsonData, - @Valid final String parentNodeXpath) { - networkCmProxyDataService.updateNodeLeaves(cmHandle, parentNodeXpath, GSON.toJson(jsonData)); - return new ResponseEntity<>(HttpStatus.OK); - } - - /** * Get resource data from operational datastore. * * @param cmHandle cm handle identifier 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 a3d8afaf24..b5dc2eabbb 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 @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2021 Pantheon.tech * Modification Copyright (C) 2021 highstreet technologies GmbH - * Modification Copyright (C) 2021 Nordix Foundation + * Modification Copyright (C) 2021-2022 Nordix Foundation * Modification Copyright (C) 2021 Bell Canada. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,8 +26,6 @@ import org.onap.cps.TestUtils import org.onap.cps.spi.model.ModuleReference import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS -import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch @@ -37,9 +35,7 @@ import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.DELETE -import com.google.gson.Gson import org.onap.cps.ncmp.api.NetworkCmProxyDataService -import org.onap.cps.spi.model.DataNodeBuilder import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value @@ -61,115 +57,8 @@ class NetworkCmProxyControllerSpec extends Specification { @Value('${rest.api.ncmp-base-path}/v1') def ncmpBasePathV1 - def cmHandle = 'some handle' - def xpath = 'some xpath' def jsonString = '{"some-key":"some-value"}' - def 'Query data node by cps path for the given cm handle with #scenario.'() { - given: 'service method returns a list containing a data node' - def dataNode = new DataNodeBuilder().withXpath('/xpath').build() - def cpsPath = 'some cps-path' - mockNetworkCmProxyDataService.queryDataNodes(cmHandle, cpsPath, expectedCpsDataServiceOption) >> [dataNode] - and: 'the query endpoint' - def dataNodeEndpoint = "$ncmpBasePathV1/cm-handles/$cmHandle/nodes/query" - when: 'query data nodes API is invoked' - def response = mvc.perform(get(dataNodeEndpoint) - .param('cps-path', cpsPath) - .param('include-descendants', includeDescendantsOption)) - .andReturn().response - then: 'the response contains the the datanode in json format' - response.status == HttpStatus.OK.value() - def expectedJsonContent = new Gson().toJson(dataNode) - response.getContentAsString().contains(expectedJsonContent) - where: 'the following options for include descendants are provided in the request' - scenario | includeDescendantsOption || expectedCpsDataServiceOption - 'no descendants by default' | '' || OMIT_DESCENDANTS - 'no descendant explicitly' | 'false' || OMIT_DESCENDANTS - 'descendants' | 'true' || INCLUDE_ALL_DESCENDANTS - } - - def 'Create data node: #scenario.'() { - when: 'post request is performed' - def response = mvc.perform( - post("$ncmpBasePathV1/cm-handles/$cmHandle/nodes") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonString) - .param('xpath', reqXpath) - ).andReturn().response - then: 'the service method is invoked once with expected parameters' - 1 * mockNetworkCmProxyDataService.createDataNode(cmHandle, usedXpath, jsonString) - and: 'response status indicates success' - response.status == HttpStatus.CREATED.value() - where: 'following parameters were used' - scenario | reqXpath || usedXpath - 'no xpath parameter' | '' || '/' - 'root xpath' | '/' || '/' - 'parent node xpath' | '/xpath' || '/xpath' - } - - def 'Add list-node elements.'() { - given: ' parent node xpath' - def parentNodeXpath = 'parent node xpath' - when: 'post request is performed' - def response = mvc.perform( - post("$ncmpBasePathV1/cm-handles/$cmHandle/list-node") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonString) - .param('xpath', parentNodeXpath) - ).andReturn().response - then: 'the service method is invoked once with expected parameters' - 1 * mockNetworkCmProxyDataService.addListNodeElements(cmHandle, parentNodeXpath, jsonString) - and: 'response status indicates success' - response.status == HttpStatus.CREATED.value() - } - - def 'Update data node leaves.'() { - given: 'the query endpoint' - def endpoint = "$ncmpBasePathV1/cm-handles/$cmHandle/nodes" - when: 'patch request is performed' - def response = mvc.perform( - patch(endpoint) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonString) - .param('xpath', xpath) - ).andReturn().response - then: 'the service method is invoked once with expected parameters' - 1 * mockNetworkCmProxyDataService.updateNodeLeaves(cmHandle, xpath, jsonString) - and: 'response status indicates success' - response.status == HttpStatus.OK.value() - } - - def 'Replace data node tree.'() { - given: 'the query endpoint' - def endpoint = "$ncmpBasePathV1/cm-handles/$cmHandle/nodes" - when: 'put request is performed' - def response = mvc.perform( - put(endpoint) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonString) - .param('xpath', xpath) - ).andReturn().response - then: 'the service method is invoked once with expected parameters' - 1 * mockNetworkCmProxyDataService.replaceNodeTree(cmHandle, xpath, jsonString) - and: 'response status indicates success' - response.status == HttpStatus.OK.value() - } - - def 'Get data node.'() { - given: 'the service returns a data node' - def xpath = 'some xpath' - def dataNode = new DataNodeBuilder().withXpath(xpath).withLeaves(["leaf": "value"]).build() - mockNetworkCmProxyDataService.getDataNode(cmHandle, xpath, OMIT_DESCENDANTS) >> dataNode - and: 'the query endpoint' - def endpoint = "$ncmpBasePathV1/cm-handles/$cmHandle/node" - when: 'get request is performed through REST API' - def response = mvc.perform(get(endpoint).param('xpath', xpath)).andReturn().response - then: 'a success response is returned' - response.status == HttpStatus.OK.value() - and: 'response contains expected leaf and value' - response.contentAsString.contains('"leaf":"value"') - } - def 'Get Resource Data from pass-through operational.' () { given: 'resource data url' def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-operational" + diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy index 3fcf818aff..f36a706937 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/exceptions/NetworkCmProxyRestExceptionHandlerSpec.groovy @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 highstreet technologies GmbH - * Modification Copyright (C) 2021 Nordix Foundation + * Modification Copyright (C) 2021-2022 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,6 @@ package org.onap.cps.ncmp.rest.exceptions import groovy.json.JsonSlurper import org.onap.cps.ncmp.api.NetworkCmProxyDataService import org.onap.cps.ncmp.api.impl.exception.NcmpException -import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.exceptions.CpsException import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired @@ -55,9 +54,6 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { @Shared def errorDetails = 'some error details' - def cmHandle = 'some handle' - def xpath = 'some xpath' - def setup() { dataNodeBaseEndpoint = "$basePath/v1" } @@ -75,18 +71,16 @@ class NetworkCmProxyRestExceptionHandlerSpec extends Specification { 'other' | new IllegalStateException(errorMessage) || null } - def setupTestException(exception) { - mockNetworkCmProxyDataService.getDataNode(cmHandle, xpath, FetchDescendantsOption.OMIT_DESCENDANTS) >> + def setupTestException(exception){ + mockNetworkCmProxyDataService.getYangResourcesModuleReferences('testCmHandle')>> { throw exception} } - def performTestRequest() { - return mvc.perform(get("$dataNodeBaseEndpoint/cm-handles/$cmHandle/node").param('xpath', xpath)) - .andReturn().response + def performTestRequest(){ + return mvc.perform(get("$dataNodeBaseEndpoint/ch/testCmHandle/modules")).andReturn().response } - static void assertTestResponse(response, expectedStatus,expectedErrorMessage, - expectedErrorDetails) { + static void assertTestResponse(response, expectedStatus , expectedErrorMessage , expectedErrorDetails) { assert response.status == expectedStatus.value() def content = new JsonSlurper().parseText(response.contentAsString) assert content['status'] == expectedStatus.toString() 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 ec816ed730..dddf089107 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 @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 highstreet technologies GmbH - * Modifications Copyright (C) 2021 Nordix Foundation + * Modifications Copyright (C) 2021-2022 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,10 +25,7 @@ package org.onap.cps.ncmp.api; import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum; import java.util.Collection; -import org.checkerframework.checker.nullness.qual.NonNull; import org.onap.cps.ncmp.api.models.DmiPluginRegistration; -import org.onap.cps.spi.FetchDescendantsOption; -import org.onap.cps.spi.model.DataNode; import org.onap.cps.spi.model.ModuleReference; /* @@ -37,72 +34,6 @@ import org.onap.cps.spi.model.ModuleReference; public interface NetworkCmProxyDataService { /** - * Retrieves datanode by XPath for a given cm handle. - * - * @param cmHandle The identifier for a network function, network element, subnetwork or any other cm - * object by managed Network CM Proxy - * @param xpath xpath - * @param fetchDescendantsOption defines the scope of data to fetch: either single node or all the descendant nodes - * (recursively) as well - * @return data node object - */ - DataNode getDataNode(@NonNull String cmHandle, @NonNull String xpath, - @NonNull FetchDescendantsOption fetchDescendantsOption); - - /** - * Get datanodes for the given cm handle by cps path. - * - * @param cmHandle The identifier for a network function, network element, subnetwork or any other cm - * object by managed Network CM Proxy - * @param cpsPath cps path - * @param fetchDescendantsOption defines whether the descendants of the node(s) found by the query should be - * included in the output - * @return a collection of datanodes - */ - Collection<DataNode> queryDataNodes(@NonNull String cmHandle, @NonNull String cpsPath, - @NonNull FetchDescendantsOption fetchDescendantsOption); - - /** - * Creates data node with descendants at root level or under existing node (if parent node xpath is provided). - * - * @param cmHandle The identifier for a network function, network element, subnetwork or any other cm - * object managed by Network CM Proxy - * @param parentNodeXpath xpath to parent node or '/' for root level - * @param jsonData data as JSON string - */ - void createDataNode(@NonNull String cmHandle, @NonNull String parentNodeXpath, @NonNull String jsonData); - - /** - * Creates one or more child node elements with descendants under existing node from list-node data fragment. - * - * @param cmHandle The identifier for a network function, network element, subnetwork or any other cm - * object managed by Network CM Proxy - * @param parentNodeXpath xpath to parent node - * @param jsonData data as JSON string - */ - void addListNodeElements(@NonNull String cmHandle, @NonNull String parentNodeXpath, @NonNull String jsonData); - - /** - * Updates data node for given cm handle using xpath to parent node. - * - * @param cmHandle The identifier for a network function, network element, subnetwork or any other cm object - * by managed Network CM Proxy - * @param parentNodeXpath xpath to parent node - * @param jsonData json data - */ - void updateNodeLeaves(@NonNull String cmHandle, @NonNull String parentNodeXpath, @NonNull String jsonData); - - /** - * Replaces existing data node content including descendants. - * - * @param cmHandle The identifier for a network function, network element, subnetwork or any other cm object - * by managed Network CM Proxy - * @param parentNodeXpath xpath to parent node - * @param jsonData json data - */ - void replaceNodeTree(@NonNull String cmHandle, @NonNull String parentNodeXpath, @NonNull String jsonData); - - /** * Registration of New CM Handles. * * @param dmiPluginRegistration Dmi Plugin Registration 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 7ded95fa06..eeb004ad51 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 @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 highstreet technologies GmbH - * Modifications Copyright (C) 2021 Nordix Foundation + * Modifications Copyright (C) 2021-2022 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2021 Bell Canada * ================================================================================ @@ -38,7 +38,6 @@ import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsAdminService; import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsModuleService; -import org.onap.cps.api.CpsQueryService; import org.onap.cps.ncmp.api.NetworkCmProxyDataService; import org.onap.cps.ncmp.api.impl.exception.NcmpException; import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations; @@ -48,14 +47,11 @@ import org.onap.cps.ncmp.api.models.CmHandle; import org.onap.cps.ncmp.api.models.DmiPluginRegistration; import org.onap.cps.ncmp.api.models.PersistenceCmHandle; import org.onap.cps.ncmp.api.models.PersistenceCmHandlesList; -import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; 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.ResponseEntity; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; @Slf4j @Service @@ -73,8 +69,6 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private ObjectMapper objectMapper; - private CpsQueryService cpsQueryService; - private DmiDataOperations dmiDataOperations; private DmiModelOperations dmiModelOperations; @@ -87,69 +81,23 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService * Constructor Injection for Dependencies. * @param dmiDataOperations DMI operation * @param cpsDataService Data Service Interface - * @param cpsQueryService Query Service Interface * @param objectMapper Object Mapper */ public NetworkCmProxyDataServiceImpl(final DmiDataOperations dmiDataOperations, final DmiModelOperations dmiModelOperations, final CpsModuleService cpsModuleService, final CpsDataService cpsDataService, - final CpsQueryService cpsQueryService, final CpsAdminService cpsAdminService, final ObjectMapper objectMapper) { this.dmiDataOperations = dmiDataOperations; this.dmiModelOperations = dmiModelOperations; this.cpsModuleService = cpsModuleService; this.cpsDataService = cpsDataService; - this.cpsQueryService = cpsQueryService; this.cpsAdminService = cpsAdminService; this.objectMapper = objectMapper; } @Override - public DataNode getDataNode(final String cmHandle, final String xpath, - final FetchDescendantsOption fetchDescendantsOption) { - return cpsDataService - .getDataNode(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, xpath, fetchDescendantsOption); - } - - @Override - public Collection<DataNode> queryDataNodes(final String cmHandle, final String cpsPath, - final FetchDescendantsOption fetchDescendantsOption) { - return cpsQueryService - .queryDataNodes(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, cpsPath, fetchDescendantsOption); - } - - @Override - public void createDataNode(final String cmHandle, final String parentNodeXpath, final String jsonData) { - if (!StringUtils.hasText(parentNodeXpath) || "/".equals(parentNodeXpath)) { - cpsDataService.saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, jsonData, NO_TIMESTAMP); - } else { - cpsDataService - .saveData(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData, NO_TIMESTAMP); - } - } - - @Override - public void addListNodeElements(final String cmHandle, final String parentNodeXpath, final String jsonData) { - cpsDataService.saveListElements(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData, - NO_TIMESTAMP); - } - - @Override - public void updateNodeLeaves(final String cmHandle, final String parentNodeXpath, final String jsonData) { - cpsDataService - .updateNodeLeaves(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData, - NO_TIMESTAMP); - } - - @Override - public void replaceNodeTree(final String cmHandle, final String parentNodeXpath, final String jsonData) { - cpsDataService.replaceNodeTree(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandle, parentNodeXpath, jsonData, - NO_TIMESTAMP); - } - - @Override public void updateDmiRegistrationAndSyncModule(final DmiPluginRegistration dmiPluginRegistration) { dmiPluginRegistration.validateDmiPluginRegistration(); try { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy index de60a01930..b7f059a7ce 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy @@ -35,7 +35,7 @@ class NetworkCmProxyDataServiceImplModelSyncSpec extends Specification { def mockDmiModelOperations = Mock(DmiModelOperations) def objectUnderTest = new NetworkCmProxyDataServiceImpl(null, mockDmiModelOperations, - mockCpsModuleService, null, null, mockCpsAdminService, new ObjectMapper()) + mockCpsModuleService, null, mockCpsAdminService, new ObjectMapper()) def expectedDataspaceName = 'NFP-Operational' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy index 304c08ae8d..90fcbfc612 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy @@ -183,7 +183,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def getObjectUnderTestWithModelSyncDisabled() { def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(null, null, mockCpsModuleService, - mockCpsDataService, null, null, spyObjectMapper)) + mockCpsDataService, null, spyObjectMapper)) objectUnderTest.syncModulesAndCreateAnchor(*_) >> null return objectUnderTest } 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 62492710e0..5753d7b675 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 @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021-2022 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2021 Bell Canada * ================================================================================ @@ -33,7 +33,6 @@ import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.api.CpsAdminService import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsModuleService -import org.onap.cps.api.CpsQueryService import org.onap.cps.ncmp.api.impl.exception.NcmpException import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations import org.onap.cps.spi.FetchDescendantsOption @@ -45,52 +44,16 @@ import spock.lang.Specification class NetworkCmProxyDataServiceImplSpec extends Specification { def mockCpsDataService = Mock(CpsDataService) - def mockCpsQueryService = Mock(CpsQueryService) def mockCpsModuleService = Mock(CpsModuleService) def mockCpsAdminService = Mock(CpsAdminService) def spyObjectMapper = Spy(ObjectMapper) def mockDmiDataOperations = Mock(DmiDataOperations) def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockDmiDataOperations, null, - mockCpsModuleService, mockCpsDataService, mockCpsQueryService, mockCpsAdminService, spyObjectMapper) + mockCpsModuleService, mockCpsDataService, mockCpsAdminService, spyObjectMapper) - def cmHandle = 'some handle' - def noTimestamp = null def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']" - def expectedDataspaceName = 'NFP-Operational' - def 'Create full data node: #scenario.'() { - given: 'json data' - def jsonData = 'some json' - when: 'createDataNode is invoked' - objectUnderTest.createDataNode(cmHandle, xpath, jsonData) - then: 'save data is invoked once with the expected parameters' - 1 * mockCpsDataService.saveData(expectedDataspaceName, cmHandle, jsonData, noTimestamp) - where: 'following parameters were used' - scenario | xpath - 'no xpath' | '' - 'root level xpath' | '/' - } - - def 'Create child data node.'() { - given: 'json data and xpath' - def jsonData = 'some json' - def xpath = '/test-node' - when: 'create data node is invoked' - objectUnderTest.createDataNode(cmHandle, xpath, jsonData) - then: 'save data is invoked once with the expected parameters' - 1 * mockCpsDataService.saveData(expectedDataspaceName, cmHandle, xpath, jsonData, noTimestamp) - } - - def 'Add list-node elements.'() { - given: 'json data and xpath' - def jsonData = 'some json' - def xpath = '/test-node' - when: 'add list node element is invoked' - objectUnderTest.addListNodeElements(cmHandle, xpath, jsonData) - then: 'the save list elements is invoked once with the expected parameters' - 1 * mockCpsDataService.saveListElements(expectedDataspaceName, cmHandle, xpath, jsonData, noTimestamp) - } def 'Write resource data for pass-through running from dmi using POST #scenario cm handle properties.'() { given: 'a data node' @@ -133,14 +96,6 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { exceptionThrown.details.contains('404') } - def 'Get data node.'() { - when: 'get data node is invoked' - objectUnderTest.getDataNode(cmHandle, 'some xpath', fetchDescendantsOption) - then: 'the persistence data service is called once with the correct parameters' - 1 * mockCpsDataService.getDataNode(expectedDataspaceName, cmHandle, 'some xpath', fetchDescendantsOption) - where: 'all fetch descendants options are supported' - fetchDescendantsOption << FetchDescendantsOption.values() - } def 'Get resource data for pass-through operational from dmi.'() { given: 'a data node' @@ -270,25 +225,6 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 1 * mockCpsAdminService.queryAnchorNames('NFP-Operational', ['some-module-name']) } - def 'Update data node leaves.'() { - given: 'json data and xpath' - def jsonData = 'some json' - def xpath = '/xpath' - when: 'update node leaves is invoked' - objectUnderTest.updateNodeLeaves(cmHandle, xpath, jsonData) - then: 'the persistence service is called once with the correct parameters' - 1 * mockCpsDataService.updateNodeLeaves(expectedDataspaceName, cmHandle, xpath, jsonData, noTimestamp) - } - - def 'Replace data node tree.'() { - given: 'json data and xpath' - def jsonData = 'some json' - def xpath = '/xpath' - when: 'replace node tree is invoked' - objectUnderTest.replaceNodeTree(cmHandle, xpath, jsonData) - then: 'the persistence service is called once with the correct parameters' - 1 * mockCpsDataService.replaceNodeTree(expectedDataspaceName, cmHandle, xpath, jsonData, noTimestamp) - } def 'Update resource data for pass-through running from dmi using POST #scenario cm handle properties.'() { given: 'a data node' @@ -331,17 +267,6 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 'UPDATE' | UPDATE || 'Not able to update resource data.' } - def 'Query data nodes by cps path with #fetchDescendantsOption.'() { - given: 'a cps path' - def cpsPath = '/cps-path' - when: 'query data nodes is invoked' - objectUnderTest.queryDataNodes(cmHandle, cpsPath, fetchDescendantsOption) - then: 'the persistence query service is called once with the correct parameters' - 1 * mockCpsQueryService.queryDataNodes(expectedDataspaceName, cmHandle, cpsPath, fetchDescendantsOption) - where: 'all fetch descendants options are supported' - fetchDescendantsOption << FetchDescendantsOption.values() - } - def getDataNode(boolean includeCmHandleProperties) { def dataNode = new DataNode() dataNode.leaves = ['dmi-service-name': 'testDmiService'] diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java index 1445ccadf0..a23bc95f3e 100755 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 Nordix Foundation - * Modifications Copyright (C) 2020-2021 Bell Canada. + * Modifications Copyright (C) 2020-2022 Bell Canada. * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,8 +27,8 @@ import java.util.Collection; import lombok.extern.slf4j.Slf4j; import org.onap.cps.api.CpsAdminService; import org.onap.cps.api.CpsDataService; -import org.onap.cps.api.CpsModuleService; import org.onap.cps.notification.NotificationService; +import org.onap.cps.notification.Operation; import org.onap.cps.spi.CpsDataPersistenceService; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.exceptions.DataValidationException; @@ -53,9 +53,6 @@ public class CpsDataServiceImpl implements CpsDataService { private CpsAdminService cpsAdminService; @Autowired - private CpsModuleService cpsModuleService; - - @Autowired private YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache; @Autowired @@ -66,7 +63,7 @@ public class CpsDataServiceImpl implements CpsDataService { final OffsetDateTime observedTimestamp) { final var dataNode = buildDataNode(dataspaceName, anchorName, ROOT_NODE_XPATH, jsonData); cpsDataPersistenceService.storeDataNode(dataspaceName, anchorName, dataNode); - processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp); + processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, ROOT_NODE_XPATH, Operation.CREATE); } @Override @@ -74,7 +71,7 @@ public class CpsDataServiceImpl implements CpsDataService { final String jsonData, final OffsetDateTime observedTimestamp) { final var dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData); cpsDataPersistenceService.addChildDataNode(dataspaceName, anchorName, parentNodeXpath, dataNode); - processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp); + processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.CREATE); } @Override @@ -84,7 +81,7 @@ public class CpsDataServiceImpl implements CpsDataService { buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonData); cpsDataPersistenceService.addListElements(dataspaceName, anchorName, parentNodeXpath, listElementDataNodeCollection); - processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp); + processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE); } @Override @@ -99,7 +96,7 @@ public class CpsDataServiceImpl implements CpsDataService { final var dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData); cpsDataPersistenceService .updateDataLeaves(dataspaceName, anchorName, dataNode.getXpath(), dataNode.getLeaves()); - processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp); + processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE); } @Override @@ -113,7 +110,7 @@ public class CpsDataServiceImpl implements CpsDataService { for (final DataNode dataNodeUpdate : dataNodeUpdates) { processDataNodeUpdate(dataspaceName, anchorName, dataNodeUpdate); } - processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp); + processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE); } @Override @@ -121,7 +118,7 @@ public class CpsDataServiceImpl implements CpsDataService { final String jsonData, final OffsetDateTime observedTimestamp) { final var dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData); cpsDataPersistenceService.replaceDataNodeTree(dataspaceName, anchorName, dataNode); - processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp); + processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE); } @Override @@ -130,21 +127,21 @@ public class CpsDataServiceImpl implements CpsDataService { final Collection<DataNode> newListElements = buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonData); cpsDataPersistenceService.replaceListContent(dataspaceName, anchorName, parentNodeXpath, newListElements); - processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp); + processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE); } @Override public void deleteDataNode(final String dataspaceName, final String anchorName, final String dataNodeXpath, final OffsetDateTime observedTimestamp) { cpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, dataNodeXpath); - processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp); + processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, dataNodeXpath, Operation.DELETE); } @Override public void deleteListOrListElement(final String dataspaceName, final String anchorName, final String listNodeXpath, final OffsetDateTime observedTimestamp) { cpsDataPersistenceService.deleteListDataNode(dataspaceName, anchorName, listNodeXpath); - processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp); + processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, listNodeXpath, Operation.DELETE); } private DataNode buildDataNode(final String dataspaceName, final String anchorName, @@ -186,9 +183,10 @@ public class CpsDataServiceImpl implements CpsDataService { } private void processDataUpdatedEventAsync(final String dataspaceName, final String anchorName, - final OffsetDateTime observedTimestamp) { + final OffsetDateTime observedTimestamp, final String xpath, + final Operation operation) { try { - notificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp); + notificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, xpath, operation); } catch (final Exception exception) { log.error("Failed to send message to notification service", exception); } @@ -210,4 +208,5 @@ public class CpsDataServiceImpl implements CpsDataService { processDataNodeUpdate(dataspaceName, anchorName, childDataNodeUpdate); } } + } diff --git a/cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java b/cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java index 2985ed53bb..6054ce5d76 100644 --- a/cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java +++ b/cps-service/src/main/java/org/onap/cps/notification/CpsDataUpdatedEventFactory.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (c) 2021 Bell Canada. + * Copyright (c) 2021-2022 Bell Canada. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -71,20 +71,21 @@ public class CpsDataUpdatedEventFactory { * @param dataspaceName dataspaceName * @param anchorName anchorName * @param observedTimestamp observedTimestamp + * @param operation operation * @return CpsDataUpdatedEvent */ public CpsDataUpdatedEvent createCpsDataUpdatedEvent(final String dataspaceName, final String anchorName, - final OffsetDateTime observedTimestamp) { + final OffsetDateTime observedTimestamp, final Operation operation) { final var dataNode = cpsDataService .getDataNode(dataspaceName, anchorName, "/", FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); final var anchor = cpsAdminService.getAnchor(dataspaceName, anchorName); - return toCpsDataUpdatedEvent(anchor, dataNode, observedTimestamp); + return toCpsDataUpdatedEvent(anchor, dataNode, observedTimestamp, operation); } private CpsDataUpdatedEvent toCpsDataUpdatedEvent(final Anchor anchor, final DataNode dataNode, - final OffsetDateTime observedTimestamp) { + final OffsetDateTime observedTimestamp, final Operation operation) { final var cpsDataUpdatedEvent = new CpsDataUpdatedEvent(); - cpsDataUpdatedEvent.withContent(createContent(anchor, dataNode, observedTimestamp)); + cpsDataUpdatedEvent.withContent(createContent(anchor, dataNode, observedTimestamp, operation)); cpsDataUpdatedEvent.withId(UUID.randomUUID().toString()); cpsDataUpdatedEvent.withSchema(EVENT_SCHEMA); cpsDataUpdatedEvent.withSource(EVENT_SOURCE); @@ -99,12 +100,13 @@ public class CpsDataUpdatedEventFactory { } private Content createContent(final Anchor anchor, final DataNode dataNode, - final OffsetDateTime observedTimestamp) { + final OffsetDateTime observedTimestamp, final Operation operation) { final var content = new Content(); content.withAnchorName(anchor.getName()); content.withDataspaceName(anchor.getDataspaceName()); content.withSchemaSetName(anchor.getSchemaSetName()); content.withData(createData(dataNode)); + content.withOperation(Content.Operation.fromValue(operation.name())); content.withObservedTimestamp( DATE_TIME_FORMATTER.format(observedTimestamp == null ? OffsetDateTime.now() : observedTimestamp)); return content; diff --git a/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java b/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java index 029efbe795..97a14797b5 100644 --- a/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java +++ b/cps-service/src/main/java/org/onap/cps/notification/NotificationService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (c) 2021 Bell Canada. + * Copyright (c) 2021-2022 Bell Canada. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,8 @@ import org.springframework.stereotype.Service; @Slf4j public class NotificationService { + private static final String ROOT_NODE_XPATH = "/"; + private NotificationProperties notificationProperties; private NotificationPublisher notificationPublisher; private CpsDataUpdatedEventFactory cpsDataUpdatedEventFactory; @@ -78,19 +80,23 @@ public class NotificationService { /** * Process Data Updated Event and publishes the notification. * - * @param dataspaceName dataspace name - * @param anchorName anchor name + * @param dataspaceName dataspace name + * @param anchorName anchor name * @param observedTimestamp observedTimestamp + * @param xpath xpath of changed data node + * @param operation operation * @return future */ @Async("notificationExecutor") public Future<Void> processDataUpdatedEvent(final String dataspaceName, final String anchorName, - final OffsetDateTime observedTimestamp) { + final OffsetDateTime observedTimestamp, + final String xpath, final Operation operation) { log.debug("process data updated event for dataspace '{}' & anchor '{}'", dataspaceName, anchorName); try { if (shouldSendNotification(dataspaceName)) { final var cpsDataUpdatedEvent = - cpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp); + cpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(dataspaceName, anchorName, + observedTimestamp, getRootNodeOperation(xpath, operation)); log.debug("data updated event to be published {}", cpsDataUpdatedEvent); notificationPublisher.sendNotification(cpsDataUpdatedEvent); } @@ -114,4 +120,8 @@ public class NotificationService { .anyMatch(pattern -> pattern.matcher(dataspaceName).find()); } + private Operation getRootNodeOperation(final String xpath, final Operation operation) { + return ROOT_NODE_XPATH.equals(xpath) ? operation : Operation.UPDATE; + } + } diff --git a/cps-service/src/main/java/org/onap/cps/notification/Operation.java b/cps-service/src/main/java/org/onap/cps/notification/Operation.java new file mode 100644 index 0000000000..83e1ccf79f --- /dev/null +++ b/cps-service/src/main/java/org/onap/cps/notification/Operation.java @@ -0,0 +1,27 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (c) 2022 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.notification; + +public enum Operation { + CREATE, + UPDATE, + DELETE +} diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy index ba9c156d75..6c899c7933 100644 --- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * Copyright (C) 2021 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech - * Modifications Copyright (C) 2021 Bell Canada. + * Modifications Copyright (C) 2021-2022 Bell Canada. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import org.onap.cps.TestUtils import org.onap.cps.api.CpsAdminService import org.onap.cps.api.CpsModuleService import org.onap.cps.notification.NotificationService +import org.onap.cps.notification.Operation import org.onap.cps.spi.CpsDataPersistenceService import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.exceptions.DataValidationException @@ -40,7 +41,6 @@ import java.time.OffsetDateTime class CpsDataServiceImplSpec extends Specification { def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService) def mockCpsAdminService = Mock(CpsAdminService) - def mockCpsModuleService = Mock(CpsModuleService) def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache) def mockNotificationService = Mock(NotificationService) @@ -49,7 +49,6 @@ class CpsDataServiceImplSpec extends Specification { def setup() { objectUnderTest.cpsDataPersistenceService = mockCpsDataPersistenceService objectUnderTest.cpsAdminService = mockCpsAdminService - objectUnderTest.cpsModuleService = mockCpsModuleService objectUnderTest.yangTextSchemaSourceSetCache = mockYangTextSchemaSourceSetCache objectUnderTest.notificationService = mockNotificationService } @@ -69,7 +68,7 @@ class CpsDataServiceImplSpec extends Specification { 1 * mockCpsDataPersistenceService.storeDataNode(dataspaceName, anchorName, { dataNode -> dataNode.xpath == '/test-tree' }) and: 'data updated event is sent to notification service' - 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp) + 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/', Operation.CREATE) } def 'Saving child data fragment under existing node.'() { @@ -82,7 +81,7 @@ class CpsDataServiceImplSpec extends Specification { 1 * mockCpsDataPersistenceService.addChildDataNode(dataspaceName, anchorName, '/test-tree', { dataNode -> dataNode.xpath == '/test-tree/branch[@name=\'New\']' }) and: 'data updated event is sent to notification service' - 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp) + 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/test-tree', Operation.CREATE) } def 'Saving list element data fragment under existing node.'() { @@ -102,7 +101,7 @@ class CpsDataServiceImplSpec extends Specification { } ) and: 'data updated event is sent to notification service' - 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp) + 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/test-tree', Operation.UPDATE) } def 'Saving empty list element data fragment.'() { @@ -134,7 +133,7 @@ class CpsDataServiceImplSpec extends Specification { then: 'the persistence service method is invoked with correct parameters' 1 * mockCpsDataPersistenceService.updateDataLeaves(dataspaceName, anchorName, expectedNodeXpath, leaves) and: 'data updated event is sent to notification service' - 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp) + 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE) where: 'following parameters were used' scenario | parentNodeXpath | jsonData || expectedNodeXpath | leaves 'top level node' | '/' | '{"test-tree": {"branch": []}}' || '/test-tree' | Collections.emptyMap() @@ -167,7 +166,7 @@ class CpsDataServiceImplSpec extends Specification { 1 * mockCpsDataPersistenceService.updateDataLeaves(dataspaceName, anchorName, "/dmi-registry/cm-handles[@id='cmHandle001']", ['id': 'cmHandle001']) and: 'the data updated event is sent to the notification service' - 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp) + 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/dmi-registry', Operation.UPDATE) } def 'Replace data node: #scenario.'() { @@ -179,7 +178,7 @@ class CpsDataServiceImplSpec extends Specification { 1 * mockCpsDataPersistenceService.replaceDataNodeTree(dataspaceName, anchorName, { dataNode -> dataNode.xpath == expectedNodeXpath }) and: 'data updated event is sent to notification service' - 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp) + 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE) where: 'following parameters were used' scenario | parentNodeXpath | jsonData || expectedNodeXpath 'top level node' | '/' | '{"test-tree": {"branch": []}}' || '/test-tree' @@ -203,7 +202,7 @@ class CpsDataServiceImplSpec extends Specification { } ) and: 'data updated event is sent to notification service' - 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp) + 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/test-tree', Operation.UPDATE) } def 'Replace whole list content with empty list element.'() { @@ -224,7 +223,7 @@ class CpsDataServiceImplSpec extends Specification { then: 'the persistence service method is invoked with correct parameters' 1 * mockCpsDataPersistenceService.deleteListDataNode(dataspaceName, anchorName, '/test-tree/branch') and: 'data updated event is sent to notification service' - 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp) + 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/test-tree/branch', Operation.DELETE) } def 'Delete data node under anchor and dataspace.'() { @@ -235,7 +234,7 @@ class CpsDataServiceImplSpec extends Specification { then: 'the persistence service method is invoked with the correct parameters' 1 * mockCpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, '/data-node') and: 'data updated event is sent to notification service' - 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp) + 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/data-node', Operation.DELETE) } def setupSchemaSetMocks(String... yangResources) { diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdateEventFactorySpec.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdateEventFactorySpec.groovy index aa0c7c0b39..67ed3d90fa 100644 --- a/cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdateEventFactorySpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/notification/CpsDataUpdateEventFactorySpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (c) 2021 Bell Canada. + * Copyright (c) 2021-2022 Bell Canada. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import java.time.format.DateTimeFormatter import org.onap.cps.utils.DateTimeUtility import org.onap.cps.api.CpsAdminService import org.onap.cps.api.CpsDataService +import org.onap.cps.event.model.Content import org.onap.cps.event.model.Data import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.model.Anchor @@ -45,7 +46,6 @@ class CpsDataUpdateEventFactorySpec extends Specification { def dateTimeFormat = 'yyyy-MM-dd\'T\'HH:mm:ss.SSSZ' def 'Create a CPS data updated event successfully: #scenario'() { - given: 'cps admin service is able to return anchor details' mockCpsAdminService.getAnchor(myDataspaceName, myAnchorName) >> new Anchor(myAnchorName, myDataspaceName, mySchemasetName) @@ -54,13 +54,10 @@ class CpsDataUpdateEventFactorySpec extends Specification { def dataNode = new DataNodeBuilder().withXpath(xpath).withLeaves(['leafName': 'leafValue']).build() mockCpsDataService.getDataNode( myDataspaceName, myAnchorName, xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode - when: 'CPS data updated event is created' def cpsDataUpdatedEvent = objectUnderTest.createCpsDataUpdatedEvent(myDataspaceName, - myAnchorName, DateTimeUtility.toOffsetDateTime(inputObservedTimestamp)) - + myAnchorName, DateTimeUtility.toOffsetDateTime(inputObservedTimestamp), Operation.CREATE) then: 'CPS data updated event is created with correct envelope' - with(cpsDataUpdatedEvent) { type == 'org.onap.cps.data-updated-event' source == new URI('urn:cps:org.onap.cps') @@ -79,6 +76,7 @@ class CpsDataUpdateEventFactorySpec extends Specification { assert anchorName == myAnchorName assert dataspaceName == myDataspaceName assert schemaSetName == mySchemasetName + assert operation == Content.Operation.CREATE assert data == new Data().withAdditionalProperty('leafName', 'leafValue') } where: diff --git a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy index ca704edb4c..306e187a00 100644 --- a/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/notification/NotificationServiceSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (c) 2021 Bell Canada. + * Copyright (c) 2021-2022 Bell Canada. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,7 +61,7 @@ class NotificationServiceSpec extends Specification { given: 'notification is disabled' spyNotificationProperties.isEnabled() >> false when: 'dataUpdatedEvent is received' - objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp) + objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp, '/', Operation.CREATE) then: 'the notification is not sent' 0 * mockNotificationPublisher.sendNotification(_) } @@ -71,10 +71,12 @@ class NotificationServiceSpec extends Specification { spyNotificationProperties.isEnabled() >> true and: 'event factory can create event successfully' def cpsDataUpdatedEvent = new CpsDataUpdatedEvent() - mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(dataspaceName, myAnchorName, myObservedTimestamp) >> - cpsDataUpdatedEvent + mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(dataspaceName, myAnchorName, myObservedTimestamp, + Operation.CREATE) >> + cpsDataUpdatedEvent when: 'dataUpdatedEvent is received' - def future = objectUnderTest.processDataUpdatedEvent(dataspaceName, myAnchorName, myObservedTimestamp) + def future = objectUnderTest.processDataUpdatedEvent(dataspaceName, myAnchorName, myObservedTimestamp, + '/', Operation.CREATE) and: 'wait for async processing to complete' future.get(10, TimeUnit.SECONDS) then: 'async process completed successfully' @@ -87,14 +89,57 @@ class NotificationServiceSpec extends Specification { 'dataspace name matches filter' | myDataspacePublishedName || 1 } + def 'Send UPDATE operation when non-root data nodes are changed.'() { + given: 'notification is enabled' + spyNotificationProperties.isEnabled() >> true + and: 'event factory creates event if operation is UPDATE' + def cpsDataUpdatedEvent = new CpsDataUpdatedEvent() + mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp, + Operation.UPDATE) >> cpsDataUpdatedEvent + when: 'dataUpdatedEvent is received for non-root xpath' + def future = objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp, '/non-root-node', + operation) + and: 'wait for async processing to complete' + future.get(10, TimeUnit.SECONDS) + then: 'async process completed successfully' + future.isDone() + and: 'notification is sent' + 1 * mockNotificationPublisher.sendNotification(cpsDataUpdatedEvent) + where: + operation << [Operation.CREATE, Operation.UPDATE, Operation.DELETE] + } + + def 'Send same operation when root nodes are changed.'() { + given: 'notification is enabled' + spyNotificationProperties.isEnabled() >> true + and: 'event factory creates event if operation is #operation' + def cpsDataUpdatedEvent = new CpsDataUpdatedEvent() + mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp, + operation) >> cpsDataUpdatedEvent + when: 'dataUpdatedEvent is received for root xpath' + def future = objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp, '/', + operation) + and: 'wait for async processing to complete' + future.get(10, TimeUnit.SECONDS) + then: 'async process completed successfully' + future.isDone() + and: 'notification is sent' + 1 * mockNotificationPublisher.sendNotification(cpsDataUpdatedEvent) + where: + operation << [Operation.CREATE, Operation.UPDATE, Operation.DELETE] + } + + def 'Error handling in notification service.'() { given: 'notification is enabled' spyNotificationProperties.isEnabled() >> true and: 'event factory can not create event successfully' - mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp) >> - { throw new Exception("Could not create event") } + mockCpsDataUpdatedEventFactory.createCpsDataUpdatedEvent(myDataspacePublishedName, myAnchorName, + myObservedTimestamp, Operation.CREATE) >> + { throw new Exception("Could not create event") } when: 'event is sent for processing' - def future = objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, myObservedTimestamp) + def future = objectUnderTest.processDataUpdatedEvent(myDataspacePublishedName, myAnchorName, + myObservedTimestamp, '/', Operation.CREATE) and: 'wait for async processing to complete' future.get(10, TimeUnit.SECONDS) then: 'async process completed successfully' diff --git a/docs/api/swagger/ncmp/openapi.yaml b/docs/api/swagger/ncmp/openapi.yaml index 509adf469e..a3b9dc7501 100644 --- a/docs/api/swagger/ncmp/openapi.yaml +++ b/docs/api/swagger/ncmp/openapi.yaml @@ -6,362 +6,6 @@ info: servers: - url: /ncmp paths: - /v1/cm-handles/{cm-handle}/node: - get: - tags: - - network-cm-proxy - summary: Get a node given a cm Handle and xpath - description: Get a node with an option to retrieve all the children for a given - cm Handle - operationId: getNodeByCmHandleAndXpath - parameters: - - name: cm-handle - in: path - description: "The identifier for a network function, network element, subnetwork\ - \ or any other cm object by managed Network CM Proxy" - required: true - schema: - type: string - - name: xpath - in: query - description: xpath - required: false - schema: - type: string - default: / - - name: include-descendants - in: query - description: include-descendants - required: false - schema: - type: boolean - default: false - responses: - "200": - description: OK - content: - application/json: - schema: - type: object - "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' - "404": - description: The specified resource was not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' - deprecated: true - /v1/cm-handles/{cm-handle}/list-node: - post: - tags: - - network-cm-proxy - summary: Add list-node child element(s) - description: Add one or more list-node child elements under existing node for - the given CM Handle - operationId: addListNodeElements - parameters: - - name: cm-handle - in: path - description: "The identifier for a network function, network element, subnetwork\ - \ or any other cm object by managed Network CM Proxy" - required: true - schema: - type: string - - name: xpath - in: query - description: xpath - required: true - schema: - type: string - requestBody: - content: - application/json: - schema: - type: string - 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' - "404": - description: The specified resource was not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' - deprecated: true - /v1/cm-handles/{cm-handle}/nodes/query: - get: - tags: - - network-cm-proxy - summary: Query data nodes - description: Query nodes for the given cps path and cm Handle - operationId: queryNodesByCmHandleAndCpsPath - parameters: - - name: cm-handle - in: path - description: "The identifier for a network function, network element, subnetwork\ - \ or any other cm object by managed Network CM Proxy" - required: true - schema: - type: string - - name: cps-path - in: query - description: cps-path - required: false - schema: - type: string - default: / - - name: include-descendants - in: query - description: include-descendants - required: false - schema: - type: boolean - default: false - responses: - "200": - description: OK - content: - application/json: - schema: - type: object - "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' - "404": - description: The specified resource was not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' - deprecated: true - /v1/cm-handles/{cm-handle}/nodes: - put: - tags: - - network-cm-proxy - summary: Replace a node with descendants - description: Replace a node with descendants for the given cps path and cm Handle - operationId: replaceNode - parameters: - - name: cm-handle - in: path - description: "The identifier for a network function, network element, subnetwork\ - \ or any other cm object by managed Network CM Proxy" - required: true - schema: - type: string - - name: xpath - in: query - description: xpath - required: false - schema: - type: string - default: / - requestBody: - content: - application/json: - schema: - type: string - required: true - responses: - "200": - description: OK - content: - application/json: - schema: - type: object - "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' - "404": - description: The specified resource was not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' - deprecated: true - post: - tags: - - network-cm-proxy - summary: Create a node with descendants - description: Create a node with descendants for the given CM Handle; top level - or under existing node (requires xpath) - operationId: createNode - parameters: - - name: cm-handle - in: path - description: "The identifier for a network function, network element, subnetwork\ - \ or any other cm object by managed Network CM Proxy" - required: true - schema: - type: string - - name: xpath - in: query - description: xpath - required: false - schema: - type: string - default: / - requestBody: - content: - application/json: - schema: - type: string - 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' - "404": - description: The specified resource was not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' - deprecated: true - patch: - tags: - - network-cm-proxy - summary: Update node leaves - description: Update node leaves for the given cps path and cm Handle - operationId: updateNodeLeaves - parameters: - - name: cm-handle - in: path - description: "The identifier for a network function, network element, subnetwork\ - \ or any other cm object by managed Network CM Proxy" - required: true - schema: - type: string - - name: xpath - in: query - description: xpath - required: false - schema: - type: string - default: / - requestBody: - content: - application/json: - schema: - type: string - required: true - responses: - "200": - description: OK - content: - application/json: - schema: - type: object - "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' - "404": - description: The specified resource was not found - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorMessage' - deprecated: true /v1/ch/{cm-handle}/data/ds/ncmp-datastore:passthrough-operational: get: tags: |