diff options
Diffstat (limited to 'src')
14 files changed, 319 insertions, 215 deletions
diff --git a/src/main/java/org/onap/cps/ncmp/dmi/rest/controller/DmiRestController.java b/src/main/java/org/onap/cps/ncmp/dmi/rest/controller/DmiRestController.java index b17280ae..97848c3e 100644 --- a/src/main/java/org/onap/cps/ncmp/dmi/rest/controller/DmiRestController.java +++ b/src/main/java/org/onap/cps/ncmp/dmi/rest/controller/DmiRestController.java @@ -26,8 +26,7 @@ import java.util.List; import javax.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.dmi.model.CmHandles; -import org.onap.cps.ncmp.dmi.model.DataAccessReadRequest; -import org.onap.cps.ncmp.dmi.model.DataAccessWriteRequest; +import org.onap.cps.ncmp.dmi.model.DataAccessRequest; import org.onap.cps.ncmp.dmi.model.ModuleReferencesRequest; import org.onap.cps.ncmp.dmi.model.ModuleResourcesReadRequest; import org.onap.cps.ncmp.dmi.model.ModuleSet; @@ -74,25 +73,6 @@ public class DmiRestController implements DmiPluginApi, DmiPluginInternalApi { } /** - * Write data using passthrough for the given cmHandle. - * - * @param dataAccessWriteRequest pass through request - * @param resourceIdentifier resource identifier - * @param cmHandle cmHandle - * @return (@ code ResponseEntity) response entity - */ - @Override - public ResponseEntity<String> writeDataByPassthroughRunningForCmHandle( - final DataAccessWriteRequest dataAccessWriteRequest, - final String resourceIdentifier, final String cmHandle) { - final String response = dmiService.writeResourceDataPassthroughForCmHandle(cmHandle, - resourceIdentifier, - MediaType.APPLICATION_JSON_VALUE, - dataAccessWriteRequest.getData()); - return new ResponseEntity<>(response, HttpStatus.CREATED); - } - - /** * This method register given list of cm-handles to ncmp. * * @param cmHandles list of cm-handles @@ -109,52 +89,84 @@ public class DmiRestController implements DmiPluginApi, DmiPluginInternalApi { /** * This method fetches the resource for given cm handle using pass through operational. It filters the response on - * the basis of options query parameters and returns response. + * the basis of options query parameters and returns response. Does not support write operations. * * @param resourceIdentifier resource identifier to fetch data * @param cmHandle cm handle identifier - * @param dataAccessReadRequest data Access Read Request + * @param dataAccessRequest data Access Request * @param acceptParamInHeader accept header parameter * @param optionsParamInQuery options query parameter * @return {@code ResponseEntity} response entity */ @Override - public ResponseEntity<Object> getResourceDataOperationalForCmHandle(final String resourceIdentifier, - final String cmHandle, - final @Valid DataAccessReadRequest dataAccessReadRequest, - final String acceptParamInHeader, - final @Valid String optionsParamInQuery) { - final var modulesListAsJson = dmiService.getResourceDataOperationalForCmHandle(cmHandle, - resourceIdentifier, - acceptParamInHeader, - optionsParamInQuery, - dataAccessReadRequest.getCmHandleProperties()); - return ResponseEntity.ok(modulesListAsJson); + public ResponseEntity<Object> dataAccessPassthroughOperational(final String resourceIdentifier, + final String cmHandle, + final @Valid DataAccessRequest + dataAccessRequest, + final String acceptParamInHeader, + final @Valid String optionsParamInQuery) { + if (isReadOperation(dataAccessRequest)) { + final String resourceDataAsJson = dmiService.getResourceData(cmHandle, + resourceIdentifier, + acceptParamInHeader, + optionsParamInQuery, + DmiService.RESTCONF_CONTENT_PASSTHROUGH_OPERATIONAL_QUERY_PARAM); + return ResponseEntity.ok(resourceDataAsJson); + } + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } - /** - * This method fetches the resource for given cm handle using pass through running. It filters the response on the - * basis of options query parameters and returns response. - * - * @param resourceIdentifier resource identifier to fetch data - * @param cmHandle cm handle identifier - * @param dataAccessReadRequest data Access Read Request - * @param acceptParamInHeader accept header parameter - * @param optionsParamInQuery options query parameter - * @return {@code ResponseEntity} response entity - */ @Override - public ResponseEntity<Object> getResourceDataPassthroughRunningForCmHandle(final String resourceIdentifier, - final String cmHandle, - final @Valid DataAccessReadRequest dataAccessReadRequest, - final String acceptParamInHeader, - final @Valid String optionsParamInQuery) { - final var modulesListAsJson = dmiService.getResourceDataPassThroughRunningForCmHandle(cmHandle, - resourceIdentifier, - acceptParamInHeader, - optionsParamInQuery, - dataAccessReadRequest.getCmHandleProperties()); - return ResponseEntity.ok(modulesListAsJson); + public ResponseEntity<String> dataAccessPassthroughRunning(final String resourceIdentifier, + final String cmHandle, + final @Valid DataAccessRequest + dataAccessRequest, + final String acceptParamInHeader, + final @Valid String optionsParamInQuery) { + final String sdncResponse; + if (isReadOperation(dataAccessRequest)) { + sdncResponse = dmiService.getResourceData(cmHandle, + resourceIdentifier, + acceptParamInHeader, + optionsParamInQuery, + DmiService.RESTCONF_CONTENT_PASSTHROUGH_RUNNING_QUERY_PARAM); + } else { + sdncResponse = dmiService.writeData( + dataAccessRequest.getOperation(), + cmHandle, + resourceIdentifier, + MediaType.APPLICATION_JSON_VALUE, + dataAccessRequest.getData()); + } + return new ResponseEntity<>(sdncResponse, getHttpStatus(dataAccessRequest)); + } + + private boolean isReadOperation(final @Valid DataAccessRequest dataAccessRequest) { + return dataAccessRequest.getOperation() == null + || dataAccessRequest.getOperation().equals(DataAccessRequest.OperationEnum.READ); + } + + private HttpStatus getHttpStatus(final DataAccessRequest dataAccessRequest) { + final HttpStatus httpStatus; + if (dataAccessRequest.getOperation() == null) { + httpStatus = HttpStatus.OK; + } else { + switch (dataAccessRequest.getOperation()) { + case CREATE: + httpStatus = HttpStatus.CREATED; + break; + case READ: + case UPDATE: + httpStatus = HttpStatus.OK; + break; + case DELETE: + httpStatus = HttpStatus.NO_CONTENT; + break; + default: + httpStatus = HttpStatus.BAD_REQUEST; + } + } + return httpStatus; } private List<ModuleReference> convertRestObjectToJavaApiObject( diff --git a/src/main/java/org/onap/cps/ncmp/dmi/service/DmiService.java b/src/main/java/org/onap/cps/ncmp/dmi/service/DmiService.java index c6910399..0f3fcc0c 100644 --- a/src/main/java/org/onap/cps/ncmp/dmi/service/DmiService.java +++ b/src/main/java/org/onap/cps/ncmp/dmi/service/DmiService.java @@ -21,18 +21,23 @@ package org.onap.cps.ncmp.dmi.service; import java.util.List; -import java.util.Map; import javax.validation.constraints.NotNull; import org.onap.cps.ncmp.dmi.exception.DmiException; +import org.onap.cps.ncmp.dmi.model.DataAccessRequest; import org.onap.cps.ncmp.dmi.model.ModuleSet; import org.onap.cps.ncmp.dmi.model.YangResources; import org.onap.cps.ncmp.dmi.service.model.ModuleReference; + + /** * Interface for handling Dmi plugin Data. */ public interface DmiService { + String RESTCONF_CONTENT_PASSTHROUGH_OPERATIONAL_QUERY_PARAM = "content=all"; + String RESTCONF_CONTENT_PASSTHROUGH_RUNNING_QUERY_PARAM = "content=config"; + /** * This method fetches all modules for given Cm Handle. * @@ -60,41 +65,24 @@ public interface DmiService { YangResources getModuleResources(String cmHandle, List<ModuleReference> modules); /** - * This method use to fetch the resource data from cm handle for datastore pass-through operational and resource - * Identifier. Options query parameter are used to filter the response from network resource. - * - * @param cmHandle cm handle identifier - * @param resourceIdentifier resource identifier - * @param acceptParamInHeader accept header parameter - * @param optionsParamInQuery options query parameter - * @param cmHandlePropertyMap cm handle properties - * @return {@code Object} response from network function - */ - Object getResourceDataOperationalForCmHandle(@NotNull String cmHandle, - @NotNull String resourceIdentifier, - String acceptParamInHeader, - String optionsParamInQuery, - Map<String, String> cmHandlePropertyMap); - - /** - * This method use to fetch the resource data from cm handle for datastore pass-through running and resource + * This method use to fetch the resource data from cm handle for the given datastore and resource * Identifier. Options query parameter are used to filter the response from network resource. * - * @param cmHandle cm handle identifier - * @param resourceIdentifier resource identifier - * @param acceptParamInHeader accept header parameter - * @param optionsParamInQuery options query parameter - * @param cmHandlePropertyMap cm handle properties + * @param cmHandle cm handle identifier + * @param resourceIdentifier resource identifier + * @param acceptParamInHeader accept header parameter + * @param optionsParamInQuery options query parameter + * @param restconfContentQueryParam restconf content i.e. datastore to use * @return {@code Object} response from network function */ - Object getResourceDataPassThroughRunningForCmHandle(@NotNull String cmHandle, + String getResourceData(@NotNull String cmHandle, @NotNull String resourceIdentifier, String acceptParamInHeader, String optionsParamInQuery, - Map<String, String> cmHandlePropertyMap); + String restconfContentQueryParam); /** - * Write resource data to sdnc using passthrough running. + * Write resource data to sdnc (will default to 'content=config', does not need to be specified). * * @param cmHandle cmHandle * @param resourceIdentifier resource identifier @@ -102,6 +90,7 @@ public interface DmiService { * @param data request data * @return response from sdnc */ - String writeResourceDataPassthroughForCmHandle(String cmHandle, String resourceIdentifier, String dataType, - String data); + String writeData(DataAccessRequest.OperationEnum operation, String cmHandle, + String resourceIdentifier, String dataType, + String data); } diff --git a/src/main/java/org/onap/cps/ncmp/dmi/service/DmiServiceImpl.java b/src/main/java/org/onap/cps/ncmp/dmi/service/DmiServiceImpl.java index 10ae1cf8..99127e66 100644 --- a/src/main/java/org/onap/cps/ncmp/dmi/service/DmiServiceImpl.java +++ b/src/main/java/org/onap/cps/ncmp/dmi/service/DmiServiceImpl.java @@ -29,8 +29,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import javax.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.dmi.config.DmiPluginConfig.DmiPluginProperties; import org.onap.cps.ncmp.dmi.exception.CmHandleRegistrationException; @@ -38,6 +36,7 @@ import org.onap.cps.ncmp.dmi.exception.DmiException; import org.onap.cps.ncmp.dmi.exception.ModuleResourceNotFoundException; import org.onap.cps.ncmp.dmi.exception.ModulesNotFoundException; import org.onap.cps.ncmp.dmi.exception.ResourceDataNotFound; +import org.onap.cps.ncmp.dmi.model.DataAccessRequest; import org.onap.cps.ncmp.dmi.model.ModuleSet; import org.onap.cps.ncmp.dmi.model.ModuleSetSchemas; import org.onap.cps.ncmp.dmi.model.YangResource; @@ -60,8 +59,6 @@ public class DmiServiceImpl implements DmiService { private NcmpRestClient ncmpRestClient; private ObjectMapper objectMapper; private DmiPluginProperties dmiPluginProperties; - private static final String RESTCONF_CONTENT_PASSTHROUGH_OPERATIONAL_QUERY_PARAM = "content=all"; - private static final String REST_CONF_CONTENT_PASSTHROUGH_RUNNING_QUERY_PARAM = "content=config"; private static final String RESPONSE_CODE = "response code : "; private static final String MESSAGE = " message : "; private static final String IETF_NETCONF_MONITORING_OUTPUT = "ietf-netconf-monitoring:output"; @@ -151,40 +148,26 @@ public class DmiServiceImpl implements DmiService { } @Override - public Object getResourceDataOperationalForCmHandle(final @NotNull String cmHandle, - final @NotNull String resourceIdentifier, + public String getResourceData(final String cmHandle, + final String resourceIdentifier, final String acceptParamInHeader, final String optionsParamInQuery, - final Map<String, String> cmHandlePropertyMap) { - // not using cmHandlePropertyMap of onap dmi impl , other dmi impl might use this. + final String restconfContentQueryParam) { final ResponseEntity<String> responseEntity = sdncOperations.getResouceDataForOperationalAndRunning(cmHandle, resourceIdentifier, optionsParamInQuery, acceptParamInHeader, - RESTCONF_CONTENT_PASSTHROUGH_OPERATIONAL_QUERY_PARAM); + restconfContentQueryParam); return prepareAndSendResponse(responseEntity, cmHandle); } @Override - public Object getResourceDataPassThroughRunningForCmHandle(final @NotNull String cmHandle, - final @NotNull String resourceIdentifier, - final String acceptParamInHeader, - final String optionsParamInQuery, - final Map<String, String> cmHandlePropertyMap) { - // not using cmHandlePropertyMap of onap dmi impl , other dmi impl might use this. - final ResponseEntity<String> responseEntity = sdncOperations.getResouceDataForOperationalAndRunning(cmHandle, - resourceIdentifier, - optionsParamInQuery, - acceptParamInHeader, - REST_CONF_CONTENT_PASSTHROUGH_RUNNING_QUERY_PARAM); - return prepareAndSendResponse(responseEntity, cmHandle); - } - - @Override - public String writeResourceDataPassthroughForCmHandle(final String cmHandle, final String resourceIdentifier, - final String dataType, final String data) { + public String writeData(final DataAccessRequest.OperationEnum operation, + final String cmHandle, + final String resourceIdentifier, + final String dataType, final String data) { final ResponseEntity<String> responseEntity = - sdncOperations.writeResourceDataPassthroughRunning(cmHandle, resourceIdentifier, dataType, data); + sdncOperations.writeData(operation, cmHandle, resourceIdentifier, dataType, data); if (responseEntity.getStatusCode().is2xxSuccessful()) { return responseEntity.getBody(); } else { diff --git a/src/main/java/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClient.java b/src/main/java/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClient.java index b8e33dfc..cf7b4599 100644 --- a/src/main/java/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClient.java +++ b/src/main/java/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClient.java @@ -57,28 +57,30 @@ public class SdncRestconfClient { * @return the response entity */ public ResponseEntity<String> getOperation(final String getResourceUrl, final HttpHeaders httpHeaders) { - final String sdncBaseUrl = sdncProperties.getBaseUrl(); - final String sdncRestconfUrl = sdncBaseUrl.concat(getResourceUrl); - httpHeaders.setBasicAuth(sdncProperties.getAuthUsername(), sdncProperties.getAuthPassword()); - final var httpEntity = new HttpEntity<>(httpHeaders); - return restTemplate.exchange(sdncRestconfUrl, - HttpMethod.GET, httpEntity, String.class); + return httpOperationWithJsonData(HttpMethod.GET, getResourceUrl, null, httpHeaders); } /** - * restconf post operation on sdnc. + * restconf http operations on sdnc. * - * @param postResourceUrl sdnc post resource url - * @param jsonData json data - * @param httpHeaders HTTP headers - * @return the response entity + * @param httpMethod HTTP Method + * @param resourceUrl sdnc resource url + * @param jsonData json data + * @param httpHeaders HTTP Headers + * @return response entity */ - public ResponseEntity<String> postOperationWithJsonData(final String postResourceUrl, - final String jsonData, final HttpHeaders httpHeaders) { - final var sdncBaseUrl = sdncProperties.getBaseUrl(); - final var sdncRestconfUrl = sdncBaseUrl.concat(postResourceUrl); + public ResponseEntity<String> httpOperationWithJsonData(final HttpMethod httpMethod, final String resourceUrl, + final String jsonData, + final HttpHeaders httpHeaders) { + final String sdncBaseUrl = sdncProperties.getBaseUrl(); + final String sdncRestconfUrl = sdncBaseUrl.concat(resourceUrl); httpHeaders.setBasicAuth(sdncProperties.getAuthUsername(), sdncProperties.getAuthPassword()); - final var httpEntity = new HttpEntity<>(jsonData, httpHeaders); - return restTemplate.exchange(sdncRestconfUrl, HttpMethod.POST, httpEntity, String.class); + final HttpEntity<String> httpEntity; + if (jsonData == null) { + httpEntity = new HttpEntity<>(httpHeaders); + } else { + httpEntity = new HttpEntity<>(jsonData, httpHeaders); + } + return restTemplate.exchange(sdncRestconfUrl, httpMethod, httpEntity, String.class); } -}
\ No newline at end of file +} diff --git a/src/main/java/org/onap/cps/ncmp/dmi/service/operation/SdncOperations.java b/src/main/java/org/onap/cps/ncmp/dmi/service/operation/SdncOperations.java index 43e2a5e6..ced9b061 100644 --- a/src/main/java/org/onap/cps/ncmp/dmi/service/operation/SdncOperations.java +++ b/src/main/java/org/onap/cps/ncmp/dmi/service/operation/SdncOperations.java @@ -35,9 +35,11 @@ import java.util.List; import org.apache.groovy.parser.antlr4.util.StringUtils; import org.onap.cps.ncmp.dmi.config.DmiConfiguration.SdncProperties; import org.onap.cps.ncmp.dmi.exception.SdncException; +import org.onap.cps.ncmp.dmi.model.DataAccessRequest; import org.onap.cps.ncmp.dmi.service.client.SdncRestconfClient; import org.onap.cps.ncmp.dmi.service.model.ModuleSchema; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -110,8 +112,8 @@ public class SdncOperations { final var getYangResourceUrl = prepareGetOperationSchemaUrl(nodeId); final var httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.APPLICATION_JSON); - return sdncRestconfClient - .postOperationWithJsonData(getYangResourceUrl, moduleProperties, httpHeaders); + return sdncRestconfClient.httpOperationWithJsonData( + HttpMethod.POST, getYangResourceUrl, moduleProperties, httpHeaders); } /** @@ -140,7 +142,7 @@ public class SdncOperations { } /** - * Write resource data using passthrough running. + * Write resource data. * * @param nodeId network resource identifier * @param resourceId resource identifier @@ -148,12 +150,16 @@ public class SdncOperations { * @param requestData request data * @return {@code ResponseEntity} response entity */ - public ResponseEntity<String> writeResourceDataPassthroughRunning(final String nodeId, - final String resourceId, final String contentType, final String requestData) { - final var getResourceDataUrl = preparePassthroughRunningUrl(nodeId, resourceId); + public ResponseEntity<String> writeData(final DataAccessRequest.OperationEnum operation, + final String nodeId, + final String resourceId, + final String contentType, + final String requestData) { + final var getResourceDataUrl = prepareWriteUrl(nodeId, resourceId); final var httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.parseMediaType(contentType)); - return sdncRestconfClient.postOperationWithJsonData(getResourceDataUrl, requestData, httpHeaders); + final HttpMethod httpMethod = getHttpMethod(operation); + return sdncRestconfClient.httpOperationWithJsonData(httpMethod, getResourceDataUrl, requestData, httpHeaders); } private List<String> buildQueryParamList(final String optionsParamInQuery, final String restconfContentQueryParam) { @@ -179,7 +185,7 @@ public class SdncOperations { return addResource(addTopologyDataUrlwithNode(nodeId), GET_SCHEMA_URL); } - private String preparePassthroughRunningUrl(final String nodeId, final String resourceId) { + private String prepareWriteUrl(final String nodeId, final String resourceId) { return addResource(addTopologyDataUrlwithNode(nodeId), "/" + resourceId); } @@ -233,4 +239,25 @@ public class SdncOperations { } } -}
\ No newline at end of file + private HttpMethod getHttpMethod(final DataAccessRequest.OperationEnum operation) { + HttpMethod httpMethod = null; + switch (operation) { + case READ: + httpMethod = HttpMethod.GET; + break; + case CREATE: + httpMethod = HttpMethod.POST; + break; + case UPDATE: + httpMethod = HttpMethod.PUT; + break; + case DELETE: + httpMethod = HttpMethod.DELETE; + break; + default: + //unreachable code but checkstyle made me do this! + } + return httpMethod; + } + +} diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy index 1446a5aa..221603c2 100644 --- a/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy +++ b/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy @@ -43,8 +43,15 @@ import org.springframework.security.test.context.support.WithMockUser import org.springframework.test.web.servlet.MockMvc import spock.lang.Specification +import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.DELETE +import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.READ +import static org.springframework.http.HttpStatus.BAD_REQUEST +import static org.springframework.http.HttpStatus.NO_CONTENT import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put +import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.CREATE +import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.UPDATE +import static org.springframework.http.HttpStatus.CREATED +import static org.springframework.http.HttpStatus.OK @WebMvcTest(DmiRestController) @WithMockUser @@ -60,7 +67,7 @@ class DmiRestControllerSpec extends Specification { @Value('${rest.api.dmi-base-path}/v1') def basePathV1 - def 'Get all modules for given cm handle.'() { + def 'Get all modules.'() { given: 'REST endpoint for getting all modules' def getModuleUrl = "$basePathV1/ch/node1/modules" and: 'get modules for cm-handle returns a json' @@ -77,12 +84,12 @@ class DmiRestControllerSpec extends Specification { .contentType(MediaType.APPLICATION_JSON).content(json)) .andReturn().response then: 'status is OK' - response.status == HttpStatus.OK.value() + response.status == OK.value() and: 'the response content matches the result from the DMI service' response.getContentAsString() == '{"schemas":[{"moduleName":"some-moduleName","revision":"some-revision","namespace":"some-namespace"}]}' } - def 'Get all modules for given cm handle with exception handling of #scenario.'() { + def 'Get all modules with exception handling of #scenario.'() { given: 'REST endpoint for getting all modules' def getModuleUrl = "$basePathV1/ch/node1/modules" and: 'given request body and get modules for cm-handle throws #exceptionClass' @@ -101,20 +108,20 @@ class DmiRestControllerSpec extends Specification { 'any other runtime exception' | RuntimeException.class || HttpStatus.INTERNAL_SERVER_ERROR.value() } - def 'Register given list of cm handles.'() { + def 'Register given list.'() { given: 'register cm handle url and cm handles json' def registerCmhandlesPost = "${basePathV1}/inventory/cmHandles" def cmHandleJson = '{"cmHandles":["node1", "node2"]}' - when: 'post register cm handles api is invoked' + when: 'register cm handles api is invoked with POST' def response = mvc.perform( post(registerCmhandlesPost) .contentType(MediaType.APPLICATION_JSON) .content(cmHandleJson) ).andReturn().response - then: 'register cm handles in dmi service is called once' + then: 'register cm handles in dmi service is invoked with correct parameters' 1 * mockDmiService.registerCmHandles(_ as List<String>) and: 'response status is created' - response.status == HttpStatus.CREATED.value() + response.status == CREATED.value() } def 'register cm handles called with empty content.'() { @@ -127,7 +134,7 @@ class DmiRestControllerSpec extends Specification { .content(emptyJson) ).andReturn().response then: 'response status is "bad request"' - response.status == HttpStatus.BAD_REQUEST.value() + response.status == BAD_REQUEST.value() and: 'dmi service is not called' 0 * mockDmiService.registerCmHandles(_) } @@ -149,7 +156,7 @@ class DmiRestControllerSpec extends Specification { .contentType(MediaType.APPLICATION_JSON) .content(jsonData)).andReturn().response then: 'a OK status is returned' - response.status == HttpStatus.OK.value() + response.status == OK.value() and: 'the expected response is returned' response.getContentAsString() == '[{"yangSource":"\\"some-data\\"","moduleName":"NAME","revision":"REVISION"}]' } @@ -168,68 +175,105 @@ class DmiRestControllerSpec extends Specification { response.status == HttpStatus.NOT_FOUND.value() } - def 'Get resource data for pass-through operational from cm handle.'() { + def 'Get resource data for pass-through operational.'() { given: 'Get resource data url' def getResourceDataForCmHandleUrl = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-operational" + "?resourceIdentifier=parent/child&options=(fields=myfields,depth=5)" def json = '{"cmHandleProperties" : { "prop1" : "value1", "prop2" : "value2"}}' - when: 'get resource data PUT api is invoked' + when: 'get resource data POST api is invoked' def response = mvc.perform( - put(getResourceDataForCmHandleUrl).contentType(MediaType.APPLICATION_JSON) + post(getResourceDataForCmHandleUrl).contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON).content(json) ).andReturn().response then: 'response status is ok' - response.status == HttpStatus.OK.value() - and: 'dmi service called with get resource data for cm handle' - 1 * mockDmiService.getResourceDataOperationalForCmHandle('some-cmHandle', + response.status == OK.value() + and: 'dmi service called with get resource data' + 1 * mockDmiService.getResourceData('some-cmHandle', 'parent/child', 'application/json', '(fields=myfields,depth=5)', - ['prop1': 'value1', 'prop2': 'value2']) + 'content=all') } - def 'Write data using passthrough running for a cm handle using #scenario.'() { - given: 'write data for cmHandle url and jsonData' - def writeDataforCmHandlePassthroughRunning = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-running" + + def 'Get resource data for pass-through operational with bad request.'() { + given: 'Get resource data url' + def getResourceDataForCmHandleUrl = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-operational" + + "?resourceIdentifier=parent/child&options=(fields=myfields,depth=5)" + def jsonData = TestUtils.getResourceFileContent('createDataWithNormalChar.json') + when: 'get resource data POST api is invoked' + def response = mvc.perform( + post(getResourceDataForCmHandleUrl).contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON).content(jsonData) + ).andReturn().response + then: 'response status is bad request' + response.status == BAD_REQUEST.value() + and: 'dmi service is not invoked' + 0 * mockDmiService.getResourceData(*_) + } + + def 'write data with #scenario operation using passthrough running.'() { + given: 'write data for passthrough running url and jsonData' + def writeDataForPassthroughRunning = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-running" + "?resourceIdentifier=some-resourceIdentifier" def jsonData = TestUtils.getResourceFileContent(requestBodyFile) and: 'dmi service is called' - mockDmiService.writeResourceDataPassthroughForCmHandle('some-cmHandle', + mockDmiService.writeData(operationEnum, 'some-cmHandle', 'some-resourceIdentifier', 'application/json', - expectedRequestData) >> '{some-json}' - when: 'write cmHandle passthrough running post api is invoked with json data' + 'normal request body' ) >> '{some-json}' + when: 'write data for passthrough running post api is invoked with json data' def response = mvc.perform( - post(writeDataforCmHandlePassthroughRunning).contentType(MediaType.APPLICATION_JSON) + post(writeDataForPassthroughRunning).contentType(MediaType.APPLICATION_JSON) .content(jsonData) ).andReturn().response - then: 'response status is 201 CREATED' - response.status == HttpStatus.CREATED.value() + then: 'response status is #expectedResponseStatus' + response.status == expectedResponseStatus and: 'the data in the request body is as expected' - response.getContentAsString() == '{some-json}' + response.getContentAsString() == expectedJsonResponse where: 'given request body and data' - scenario | requestBodyFile || expectedRequestData - 'data with normal chars' | 'dataWithNormalChar.json' || 'normal request body' - 'data with special chars' | 'dataWithSpecialChar.json'|| 'data with quote \" and new line \n' + scenario | requestBodyFile | operationEnum || expectedResponseStatus | expectedJsonResponse + 'Create' | 'createDataWithNormalChar.json' | CREATE || CREATED.value() | '{some-json}' + 'Update' | 'updateData.json' | UPDATE || OK.value() | '{some-json}' + 'Delete' | 'deleteData.json' | DELETE || NO_CONTENT.value() | '{some-json}' + 'Read' | 'readData.json' | READ || OK.value() | '' } - def 'Get resource data for pass-through running from cm handle with #scenario value in resource identifier param.'() { + def 'Create data using passthrough for special characters.'(){ + given: 'create data for cmHandle url and JsonData' + def writeDataForCmHandlePassthroughRunning = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-running" + + "?resourceIdentifier=some-resourceIdentifier" + def jsonData = TestUtils.getResourceFileContent('createDataWithSpecialChar.json') + and: 'dmi service is called' + mockDmiService.writeData(CREATE, 'some-cmHandle', 'some-resourceIdentifier', 'application/json', + 'data with quote \" and new line \n') >> '{some-json}' + when: 'create cmHandle passthrough running post api is invoked with json data with special chars' + def response = mvc.perform( + post(writeDataForCmHandlePassthroughRunning).contentType(MediaType.APPLICATION_JSON).content(jsonData) + ).andReturn().response + then: 'response status is CREATED' + response.status == CREATED.value() + and: 'the data in the request body is as expected' + response.getContentAsString() == '{some-json}' + } + + + def 'Get resource data for pass-through running with #scenario value in resource identifier param.'() { given: 'Get resource data url' def getResourceDataForCmHandleUrl = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-running" + "?resourceIdentifier="+resourceIdentifier+"&options=(fields=myfields,depth=5)" def json = '{"cmHandleProperties" : { "prop1" : "value1", "prop2" : "value2"}}' - when: 'get resource data PUT api is invoked' + when: 'get resource data POST api is invoked' def response = mvc.perform( - put(getResourceDataForCmHandleUrl).contentType(MediaType.APPLICATION_JSON) + post(getResourceDataForCmHandleUrl).contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON).content(json) ).andReturn().response then: 'response status is ok' - response.status == HttpStatus.OK.value() - and: 'dmi service called with get resource data for cm handle' - 1 * mockDmiService.getResourceDataPassThroughRunningForCmHandle('some-cmHandle', + response.status == OK.value() + and: 'dmi service called with get resource data for a cm handle' + 1 * mockDmiService.getResourceData('some-cmHandle', resourceIdentifier, 'application/json', '(fields=myfields,depth=5)', - ['prop1':'value1', 'prop2':'value2']) + 'content=config') where: 'tokens are used in the resource identifier parameter' scenario | resourceIdentifier '/' | 'id/with/slashes' diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy index d5353754..a463a344 100644 --- a/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy +++ b/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy @@ -40,6 +40,9 @@ import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import spock.lang.Specification +import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.CREATE +import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.UPDATE + class DmiServiceImplSpec extends Specification { @@ -191,8 +194,8 @@ class DmiServiceImplSpec extends Specification { thrownException.cause == jsonProcessingException } - def 'Get resource data for pass through operational from cm handle.'() { - given: 'cm-handle, pass through parameter, resourceId, accept header, fields, depth' + def 'Get resource data for passthrough operational.'() { + given: 'cm-handle, passthrough parameter, resourceId, accept header, fields, depth' def cmHandle = 'testCmHandle' def resourceId = 'testResourceId' def acceptHeaderParam = 'testAcceptParam' @@ -201,31 +204,32 @@ class DmiServiceImplSpec extends Specification { and: 'sdnc operation returns OK response' mockSdncOperations.getResouceDataForOperationalAndRunning(cmHandle, resourceId, optionsParam, acceptHeaderParam, contentQuery) >> new ResponseEntity<>('response json', HttpStatus.OK) when: 'get resource data from cm handles service method invoked' - def response = objectUnderTest.getResourceDataOperationalForCmHandle(cmHandle, + def response = objectUnderTest.getResourceData(cmHandle, resourceId, acceptHeaderParam, - optionsParam, null) + optionsParam, contentQuery) then: 'response have expected json' response == 'response json' } - def 'Get resource data from cm handle with exception.'() { - given: 'cm-handle, pass through parameter, resourceId, accept header, fields, depth' + def 'Get resource data with not found exception.'() { + given: 'cm-handle, passthrough parameter, resourceId, accept header, fields, depth, query param' def cmHandle = 'testCmHandle' def resourceId = 'testResourceId' def acceptHeaderParam = 'testAcceptParam' def optionsParam = '(fields=x/y/z,depth=10,test=abc)' + def restConfQueryParam = 'content=config' and: 'sdnc operation returns "NOT_FOUND" response' mockSdncOperations.getResouceDataForOperationalAndRunning(cmHandle, resourceId, optionsParam, acceptHeaderParam, _ as String) >> new ResponseEntity<>(HttpStatus.NOT_FOUND) when: 'get resource data from cm handles service method invoked' - objectUnderTest.getResourceDataOperationalForCmHandle(cmHandle, + objectUnderTest.getResourceData(cmHandle, resourceId, acceptHeaderParam, - optionsParam, null) + optionsParam, restConfQueryParam) then: 'resource data not found' thrown(ResourceDataNotFound.class) } - def 'Get resource data for pass through running from cm handle.'() { - given: 'cm-handle, pass through parameter, resourceId, accept header, fields, depth' + def 'Get resource data for passthrough running.'() { + given: 'cm-handle, passthrough parameter, resourceId, accept header, fields, depth' def cmHandle = 'testCmHandle' def resourceId = 'testResourceId' def acceptHeaderParam = 'testAcceptParam' @@ -235,47 +239,43 @@ class DmiServiceImplSpec extends Specification { mockSdncOperations.getResouceDataForOperationalAndRunning(cmHandle, resourceId, optionsParam, acceptHeaderParam, contentQuery) >> new ResponseEntity<>('response json', HttpStatus.OK) when: 'get resource data from cm handles service method invoked' - def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle(cmHandle, + def response = objectUnderTest.getResourceData(cmHandle, resourceId, acceptHeaderParam, - optionsParam, null) + optionsParam, contentQuery) then: 'response have expected json' response == 'response json' } - def 'Write resource data for passthrough running for the given cm handle with a #scenario from sdnc.'() { + def 'Write resource data for passthrough running with a #scenario from sdnc.'() { given: 'sdnc returns a response with #scenario' - mockSdncOperations.writeResourceDataPassthroughRunning(_, _, _, _) >> new ResponseEntity<String>('response json', httpResponse) + mockSdncOperations.writeData(operationEnum, _, _, _, _) >> new ResponseEntity<String>('response json', httpResponse) when: 'write resource data for cm handle method invoked' - def response = objectUnderTest.writeResourceDataPassthroughForCmHandle('some-cmHandle', + def response = objectUnderTest.writeData(operationEnum,'some-cmHandle', 'some-resourceIdentifier', 'some-dataType', '{some-data}') then: 'the response contains the expected json data from sdnc' response == 'response json' where: 'the following values are used' - scenario | httpResponse - '200 OK response' | HttpStatus.OK - '201 CREATED response' | HttpStatus.CREATED + scenario | httpResponse | operationEnum + '200 OK with an update operation' | HttpStatus.OK | UPDATE + '201 CREATED with a create operation' | HttpStatus.CREATED | CREATE } - def 'Write resource data using for passthrough running for the given cm handle with #scenario.'() { + def 'Write resource data with special characters.'() { given: 'sdnc returns a created response' - mockSdncOperations.writeResourceDataPassthroughRunning('some-cmHandle', - 'some-resourceIdentifier', 'some-dataType', requestBody) >> new ResponseEntity<String>('response json', HttpStatus.CREATED) + mockSdncOperations.writeData(CREATE, 'some-cmHandle', + 'some-resourceIdentifier', 'some-dataType', 'data with quote " and \n new line') >> new ResponseEntity<String>('response json', HttpStatus.CREATED) when: 'write resource data from cm handles service method invoked' - def response = objectUnderTest.writeResourceDataPassthroughForCmHandle('some-cmHandle', - 'some-resourceIdentifier', 'some-dataType', requestBody) + def response = objectUnderTest.writeData(CREATE, 'some-cmHandle', + 'some-resourceIdentifier', 'some-dataType', 'data with quote " and \n new line') then: 'response have expected json' response == 'response json' - where: 'given request body' - scenario | requestBody - 'data contains normal char' | 'normal char string' - 'data contains quote and new line' | 'data with quote " and \n new line' } def 'Write resource data for passthrough running with a 500 response from sdnc.'() { given: 'sdnc returns a 500 response for the write operation' - mockSdncOperations.writeResourceDataPassthroughRunning(_, _, _, _) >> new ResponseEntity<String>('response json', HttpStatus.INTERNAL_SERVER_ERROR) - when: 'write resource data for pass through method is invoked' - objectUnderTest.writeResourceDataPassthroughForCmHandle('some-cmHandle', + mockSdncOperations.writeData(CREATE, _, _, _, _) >> new ResponseEntity<String>('response json', HttpStatus.INTERNAL_SERVER_ERROR) + when: 'write resource data for passthrough method is invoked' + objectUnderTest.writeData(CREATE, 'some-cmHandle', 'some-resourceIdentifier', 'some-dataType', _ as String) then: 'a dmi exception is thrown' thrown(DmiException.class) diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClientSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClientSpec.groovy index 2184c7e7..8a3170b4 100644 --- a/src/test/groovy/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClientSpec.groovy +++ b/src/test/groovy/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClientSpec.groovy @@ -28,6 +28,11 @@ import org.springframework.http.ResponseEntity import org.springframework.web.client.RestTemplate import spock.lang.Specification +import static org.springframework.http.HttpMethod.GET +import static org.springframework.http.HttpMethod.POST +import static org.springframework.http.HttpMethod.DELETE +import static org.springframework.http.HttpMethod.PUT + class SdncRestconfClientSpec extends Specification { def mockSdncProperties = Mock(DmiConfiguration.SdncProperties) @@ -49,7 +54,7 @@ class SdncRestconfClientSpec extends Specification { result == mockResponseEntity } - def 'SDNC POST operation called.'() { + def 'SDNC #scenario operation called.'() { given: 'json data' def jsonData = 'some-json' and: 'a url for get module resources' @@ -59,12 +64,18 @@ class SdncRestconfClientSpec extends Specification { and: 'the rest template returns a valid response entity' def mockResponseEntity = Mock(ResponseEntity) when: 'get module resources is invoked' - def result = objectUnderTest.postOperationWithJsonData(getModuleResourceUrl, jsonData, new HttpHeaders()) + def result = objectUnderTest.httpOperationWithJsonData(expectedHttpMethod, getModuleResourceUrl, jsonData, new HttpHeaders()) then: 'the rest template is called with the correct uri and json in the body' 1 * mockRestTemplate.exchange({ it.toString() == 'http://some-uri/getModuleResourceUrl' }, - HttpMethod.POST, { it.body.contains(jsonData) }, String.class) >> mockResponseEntity + expectedHttpMethod, { it.body.contains(jsonData) }, String.class) >> mockResponseEntity and: 'the output of the method is the same as the output from the test template' result == mockResponseEntity + where: 'the following values are used' + scenario || expectedHttpMethod + 'POST' || POST + 'PUT' || PUT + 'GET' || GET + 'DELETE' || DELETE } def 'SDNC GET operation with header.'() { diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/service/operation/SdncOperationsSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/service/operation/SdncOperationsSpec.groovy index 2ce870ab..5079ada7 100644 --- a/src/test/groovy/org/onap/cps/ncmp/dmi/service/operation/SdncOperationsSpec.groovy +++ b/src/test/groovy/org/onap/cps/ncmp/dmi/service/operation/SdncOperationsSpec.groovy @@ -29,11 +29,17 @@ import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.http.HttpHeaders +import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.test.context.ContextConfiguration import spock.lang.Specification +import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.CREATE +import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.DELETE +import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.UPDATE +import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.READ + @SpringBootTest @ContextConfiguration(classes = [DmiConfiguration.SdncProperties, SdncOperations]) class SdncOperationsSpec extends Specification { @@ -106,7 +112,7 @@ class SdncOperationsSpec extends Specification { when: 'get module resources is called with the expected parameters' objectUnderTest.getModuleResource(nodeId, 'some-json-data') then: 'the SDNC Rest client is invoked with the correct URL and json data' - 1 * mockSdncRestClient.postOperationWithJsonData(expectedUrl, 'some-json-data', _ as HttpHeaders) + 1 * mockSdncRestClient.httpOperationWithJsonData(HttpMethod.POST, expectedUrl, 'some-json-data', _ as HttpHeaders) } def 'Get resource data from node to SDNC.'() { @@ -119,13 +125,19 @@ class SdncOperationsSpec extends Specification { 1 * mockSdncRestClient.getOperation(expectedUrl, _ as HttpHeaders) } - def 'Write resource data to SDNC.'() { + def 'Write resource data with #scenario operation to SDNC.'() { given: 'expected url, topology-id, sdncOperation object' def expectedUrl = '/rests/data/network-topology:network-topology/topology=test-topology/node=node1/yang-ext:mount/testResourceId' - when: 'write resource data for pass through running is called' - objectUnderTest.writeResourceDataPassthroughRunning('node1', 'testResourceId', 'application/json', 'requestData') - then: 'the post operation is executed with the correct URL and data' - 1 * mockSdncRestClient.postOperationWithJsonData(expectedUrl, 'requestData', _ as HttpHeaders) + when: 'write resource data for passthrough running is called' + objectUnderTest.writeData(operationEnum, 'node1', 'testResourceId', 'application/json', 'requestData') + then: 'the #expectedHttpMethod operation is executed with the correct URL and data' + 1 * mockSdncRestClient.httpOperationWithJsonData(expectedHttpMethod, expectedUrl, 'requestData', _ as HttpHeaders) + where: 'the following values are used' + scenario | operationEnum || expectedHttpMethod + 'Create' | CREATE || HttpMethod.POST + 'Update' | UPDATE || HttpMethod.PUT + 'Read' | READ || HttpMethod.GET + 'Delete' | DELETE || HttpMethod.DELETE } def 'build query param list for SDNC where options contains a #scenario'() { diff --git a/src/test/resources/dataWithNormalChar.json b/src/test/resources/createDataWithNormalChar.json index 31cdf1c5..31cdf1c5 100644 --- a/src/test/resources/dataWithNormalChar.json +++ b/src/test/resources/createDataWithNormalChar.json diff --git a/src/test/resources/dataWithSpecialChar.json b/src/test/resources/createDataWithSpecialChar.json index 1e7622ee..1e7622ee 100644 --- a/src/test/resources/dataWithSpecialChar.json +++ b/src/test/resources/createDataWithSpecialChar.json diff --git a/src/test/resources/deleteData.json b/src/test/resources/deleteData.json new file mode 100644 index 00000000..2233fa01 --- /dev/null +++ b/src/test/resources/deleteData.json @@ -0,0 +1,8 @@ +{ + "operation": "delete", + "dataType": "application/json", + "data": "normal request body", + "cmHandleProperties": { + "some-property": "some-property-value" + } +}
\ No newline at end of file diff --git a/src/test/resources/readData.json b/src/test/resources/readData.json new file mode 100644 index 00000000..9f2b154f --- /dev/null +++ b/src/test/resources/readData.json @@ -0,0 +1,8 @@ +{ + "operation": "read", + "dataType": "application/json", + "data": "normal request body", + "cmHandleProperties": { + "some-property": "some-property-value" + } +}
\ No newline at end of file diff --git a/src/test/resources/updateData.json b/src/test/resources/updateData.json new file mode 100644 index 00000000..7cbf4f0c --- /dev/null +++ b/src/test/resources/updateData.json @@ -0,0 +1,8 @@ +{ + "operation": "update", + "dataType": "application/json", + "data": "normal request body", + "cmHandleProperties": { + "some-property": "some-property-value" + } +}
\ No newline at end of file |