aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToine Siebelink <toine.siebelink@est.tech>2021-02-26 11:35:17 +0000
committerGerrit Code Review <gerrit@onap.org>2021-02-26 11:35:17 +0000
commitd3609db46635b9bdb0a49a7d0e18ebe144bb7f29 (patch)
treeac1031feb7f07e2f972c30d97d5c1fe747f98f37
parentb4f6f0509e4bb97ba0ed24c3b8906905d656c682 (diff)
parent83e318f8c7d3cacb24b2ef9b76162b0af12e817c (diff)
Merge "Implement getDataNode(anchorName, xPath) in NF-Proxy"
-rw-r--r--cps-nf-proxy-rest/docs/openapi/components.yaml30
-rwxr-xr-xcps-nf-proxy-rest/docs/openapi/openapi.yml6
-rw-r--r--cps-nf-proxy-rest/docs/openapi/xnfProxy.yml31
-rw-r--r--cps-nf-proxy-rest/src/main/java/org/onap/cps/nfproxy/rest/controller/NfProxyController.java29
-rw-r--r--cps-nf-proxy-rest/src/test/groovy/org/onap/cps/nfproxy/rest/controller/NfProxyControllerSpec.groovy43
-rw-r--r--cps-nf-proxy-service/pom.xml6
-rw-r--r--cps-nf-proxy-service/src/main/java/org/onap/cps/nfproxy/api/NfProxyDataService.java44
-rwxr-xr-xcps-nf-proxy-service/src/main/java/org/onap/cps/nfproxy/api/impl/NfProxyDataServiceImpl.java43
-rw-r--r--cps-rest/src/test/groovy/org/onap/cps/rest/utils/MultipartFileUtilSpec.groovy11
9 files changed, 196 insertions, 47 deletions
diff --git a/cps-nf-proxy-rest/docs/openapi/components.yaml b/cps-nf-proxy-rest/docs/openapi/components.yaml
index 535219983..0b5d52a3a 100644
--- a/cps-nf-proxy-rest/docs/openapi/components.yaml
+++ b/cps-nf-proxy-rest/docs/openapi/components.yaml
@@ -20,7 +20,29 @@ components:
format: binary
parameters:
-
+ cmHandleInPath:
+ name: cm-handle
+ in: path
+ description: The identifier for a network function, network element, subnetwork or any other cm object by managed NF-Proxy
+ required: true
+ schema:
+ type: string
+ xpathInQuery:
+ name: xpath
+ in: query
+ description: xpath
+ required: false
+ schema:
+ type: string
+ default: /
+ includeDescendantsOptionInQuery:
+ name: include-descendants
+ in: query
+ description: include-descendants
+ required: false
+ schema:
+ type: boolean
+ default: false
responses:
NotFound:
@@ -53,6 +75,12 @@ components:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
+ NotImplemented:
+ description: The given path has not been implemented
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorMessage'
Ok:
description: OK
content:
diff --git a/cps-nf-proxy-rest/docs/openapi/openapi.yml b/cps-nf-proxy-rest/docs/openapi/openapi.yml
index 0dbab34ee..efa8e7253 100755
--- a/cps-nf-proxy-rest/docs/openapi/openapi.yml
+++ b/cps-nf-proxy-rest/docs/openapi/openapi.yml
@@ -6,8 +6,6 @@ info:
servers:
- url: //localhost:8088/
paths:
- /v1/hello-world:
- $ref: 'xnfProxy.yml#/helloWorld'
- /v1/hello-error:
- $ref: 'xnfProxy.yml#/helloError'
+ /v1/cm-handles/{cm-handle}/node:
+ $ref: 'xnfProxy.yml#/nodeByCmHandleAndXpath'
diff --git a/cps-nf-proxy-rest/docs/openapi/xnfProxy.yml b/cps-nf-proxy-rest/docs/openapi/xnfProxy.yml
index 0bb673ac3..4abe81aff 100644
--- a/cps-nf-proxy-rest/docs/openapi/xnfProxy.yml
+++ b/cps-nf-proxy-rest/docs/openapi/xnfProxy.yml
@@ -1,9 +1,14 @@
-helloWorld:
+nodeByCmHandleAndXpath:
get:
+ description: Get a node with an option to retrieve all the children for a given cm Handle
tags:
- nf-proxy
- summary: rest interface validation
- operationId: helloWorld
+ 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'
@@ -13,19 +18,7 @@ helloWorld:
$ref: 'components.yaml#/components/responses/Unauthorized'
403:
$ref: 'components.yaml#/components/responses/Forbidden'
-
-helloError:
- get:
- tags:
- - nf-proxy
- summary: error handler validation
- operationId: helloError
- 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' \ No newline at end of file
+ 404:
+ $ref: 'components.yaml#/components/responses/NotFound'
+ 501:
+ $ref: 'components.yaml#/components/responses/NotImplemented'
diff --git a/cps-nf-proxy-rest/src/main/java/org/onap/cps/nfproxy/rest/controller/NfProxyController.java b/cps-nf-proxy-rest/src/main/java/org/onap/cps/nfproxy/rest/controller/NfProxyController.java
index 99451e69a..494e7f659 100644
--- a/cps-nf-proxy-rest/src/main/java/org/onap/cps/nfproxy/rest/controller/NfProxyController.java
+++ b/cps-nf-proxy-rest/src/main/java/org/onap/cps/nfproxy/rest/controller/NfProxyController.java
@@ -2,6 +2,8 @@
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Pantheon.tech
* ================================================================================
+ * Modification Copyright (C) 2021 highstreet technologies GmbH
+ * ================================================================================
* 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
@@ -19,24 +21,37 @@
package org.onap.cps.nfproxy.rest.controller;
+import javax.validation.Valid;
+import org.onap.cps.nfproxy.api.NfProxyDataService;
import org.onap.cps.nfproxy.rest.api.NfProxyApi;
-import org.onap.cps.spi.exceptions.CpsException;
+import org.onap.cps.spi.FetchDescendantsOption;
+import org.onap.cps.spi.model.DataNode;
+import org.onap.cps.utils.DataMapUtils;
+import org.springframework.beans.factory.annotation.Autowired;
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.xnf-base-path}")
public class NfProxyController implements NfProxyApi {
- @Override
- public ResponseEntity<Object> helloWorld() {
- return new ResponseEntity<>("Hello World!", HttpStatus.OK);
- }
+ private static final String XPATH_ROOT = "/";
+
+ @Autowired
+ private NfProxyDataService nfProxyDataService;
@Override
- public ResponseEntity<Object> helloError() {
- throw new CpsException("Example error Message", "Example error description");
+ public ResponseEntity<Object> getNodeByCmHandleAndXpath(final String cmHandle, @Valid final String xpath,
+ @Valid final Boolean includeDescendants) {
+ if (XPATH_ROOT.equals(xpath)) {
+ return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+ }
+ final FetchDescendantsOption fetchDescendantsOption = Boolean.TRUE.equals(includeDescendants)
+ ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS : FetchDescendantsOption.OMIT_DESCENDANTS;
+ final DataNode dataNode = nfProxyDataService.getDataNode(cmHandle, xpath, fetchDescendantsOption);
+ return new ResponseEntity<>(DataMapUtils.toDataMap(dataNode), HttpStatus.OK);
}
}
diff --git a/cps-nf-proxy-rest/src/test/groovy/org/onap/cps/nfproxy/rest/controller/NfProxyControllerSpec.groovy b/cps-nf-proxy-rest/src/test/groovy/org/onap/cps/nfproxy/rest/controller/NfProxyControllerSpec.groovy
index 874a1b004..3cd6b9a9f 100644
--- a/cps-nf-proxy-rest/src/test/groovy/org/onap/cps/nfproxy/rest/controller/NfProxyControllerSpec.groovy
+++ b/cps-nf-proxy-rest/src/test/groovy/org/onap/cps/nfproxy/rest/controller/NfProxyControllerSpec.groovy
@@ -2,6 +2,8 @@
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Pantheon.tech
* ================================================================================
+ * Modification Copyright (C) 2021 highstreet technologies GmbH
+ * ================================================================================
* 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
@@ -19,13 +21,19 @@
package org.onap.cps.nfproxy.rest.controller
+import org.onap.cps.nfproxy.api.NfProxyDataService
+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
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.http.HttpStatus
import org.springframework.test.web.servlet.MockMvc
-import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import spock.lang.Specification
+import spock.lang.Unroll
+
+import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
@WebMvcTest
class NfProxyControllerSpec extends Specification {
@@ -33,22 +41,31 @@ class NfProxyControllerSpec extends Specification {
@Autowired
MockMvc mvc
+ @SpringBean
+ NfProxyDataService mockNfProxyDataService = Mock()
+
@Value('${rest.api.xnf-base-path}')
def basePath
- def 'Hello world method invocation.'(){
- when: 'hello-world request performed'
- def response = mvc.perform(MockMvcRequestBuilders.get("$basePath/v1/hello-world")).andReturn().response
- then: 'success response returned'
- response.status == HttpStatus.OK.value()
- response.getContentAsString().contains("Hello World!")
+ def dataNodeBaseEndpoint
+
+ def setup() {
+ dataNodeBaseEndpoint = "$basePath/v1"
}
- def 'Example error handling.'(){
- when: 'hello-error request performed'
- def response = mvc.perform(MockMvcRequestBuilders.get("$basePath/v1/hello-error")).andReturn().response
- then: 'error response returned'
- response.status == HttpStatus.INTERNAL_SERVER_ERROR.value()
- response.getContentAsString().contains("Example error")
+ @Unroll
+ def 'Get data node.'() {
+ given: 'the service returns a data node'
+ def xpath = 'some xpath'
+ def cmHandle = 'some handle'
+ def dataNode = new DataNodeBuilder().withXpath(xpath).withLeaves(["leaf": "value"]).build()
+ def endpoint = "$dataNodeBaseEndpoint/cm-handles/$cmHandle/node"
+ mockNfProxyDataService.getDataNode(cmHandle, xpath, OMIT_DESCENDANTS) >> dataNode
+ 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"')
}
}
diff --git a/cps-nf-proxy-service/pom.xml b/cps-nf-proxy-service/pom.xml
index 67ffaeb20..593d6cf79 100644
--- a/cps-nf-proxy-service/pom.xml
+++ b/cps-nf-proxy-service/pom.xml
@@ -18,12 +18,12 @@
<dependencies>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>cps-service</artifactId>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>cps-ri</artifactId>
+ <artifactId>cps-service</artifactId>
</dependency>
</dependencies>
</project> \ No newline at end of file
diff --git a/cps-nf-proxy-service/src/main/java/org/onap/cps/nfproxy/api/NfProxyDataService.java b/cps-nf-proxy-service/src/main/java/org/onap/cps/nfproxy/api/NfProxyDataService.java
new file mode 100644
index 000000000..644dfab11
--- /dev/null
+++ b/cps-nf-proxy-service/src/main/java/org/onap/cps/nfproxy/api/NfProxyDataService.java
@@ -0,0 +1,44 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 highstreet technologies GmbH
+ * ================================================================================
+ * 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.nfproxy.api;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.onap.cps.spi.FetchDescendantsOption;
+import org.onap.cps.spi.model.DataNode;
+
+/*
+ * Datastore interface for handling CPS data.
+ */
+public interface NfProxyDataService {
+
+ /**
+ * 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 NF-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);
+
+}
diff --git a/cps-nf-proxy-service/src/main/java/org/onap/cps/nfproxy/api/impl/NfProxyDataServiceImpl.java b/cps-nf-proxy-service/src/main/java/org/onap/cps/nfproxy/api/impl/NfProxyDataServiceImpl.java
new file mode 100755
index 000000000..d30702e77
--- /dev/null
+++ b/cps-nf-proxy-service/src/main/java/org/onap/cps/nfproxy/api/impl/NfProxyDataServiceImpl.java
@@ -0,0 +1,43 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 highstreet technologies GmbH
+ * ================================================================================
+ * 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.nfproxy.api.impl;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.onap.cps.api.CpsDataService;
+import org.onap.cps.nfproxy.api.NfProxyDataService;
+import org.onap.cps.spi.FetchDescendantsOption;
+import org.onap.cps.spi.model.DataNode;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class NfProxyDataServiceImpl implements NfProxyDataService {
+
+ private static final String NF_PROXY_DATASPACE_NAME = "NFP-Operational";
+
+ @Autowired
+ private CpsDataService cpsDataService;
+
+ @Override
+ public DataNode getDataNode(@NonNull final String cmHandle, @NonNull final String xpath,
+ @NonNull final FetchDescendantsOption fetchDescendantsOption) {
+ return cpsDataService.getDataNode(NF_PROXY_DATASPACE_NAME, cmHandle, xpath, fetchDescendantsOption);
+ }
+}
diff --git a/cps-rest/src/test/groovy/org/onap/cps/rest/utils/MultipartFileUtilSpec.groovy b/cps-rest/src/test/groovy/org/onap/cps/rest/utils/MultipartFileUtilSpec.groovy
index 3e2bdec37..2c3d46e5d 100644
--- a/cps-rest/src/test/groovy/org/onap/cps/rest/utils/MultipartFileUtilSpec.groovy
+++ b/cps-rest/src/test/groovy/org/onap/cps/rest/utils/MultipartFileUtilSpec.groovy
@@ -21,6 +21,8 @@ package org.onap.cps.rest.utils
import org.onap.cps.spi.exceptions.CpsException
import org.onap.cps.spi.exceptions.ModelValidationException
+import org.onap.cps.spi.model.DataNodeBuilder
+import org.onap.cps.utils.DataMapUtils
import org.springframework.mock.web.MockMultipartFile
import org.springframework.web.multipart.MultipartFile
import spock.lang.Specification
@@ -28,6 +30,15 @@ import spock.lang.Unroll
class MultipartFileUtilSpec extends Specification {
+ def 'Data node without leaves and without children.'() {
+ given: 'a datanode with no leaves and no children'
+ def dataNodeWithoutData = new DataNodeBuilder().withXpath('some xpath').build()
+ when: 'it is converted to a map'
+ def result = DataMapUtils.toDataMap(dataNodeWithoutData)
+ then: 'an empty object map is returned'
+ result.isEmpty()
+ }
+
def 'Extract yang resource from yang file.'() {
given: 'uploaded yang file'
def multipartFile = new MockMultipartFile("file", "filename.yang", "text/plain", "content".getBytes())