diff options
Diffstat (limited to 'src/main/java')
-rw-r--r-- | src/main/java/org/onap/cps/ncmp/dmi/exception/SdncException.java (renamed from src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchemaList.java) | 35 | ||||
-rw-r--r-- | src/main/java/org/onap/cps/ncmp/dmi/rest/controller/DmiRestController.java | 124 | ||||
-rw-r--r-- | src/main/java/org/onap/cps/ncmp/dmi/service/DmiService.java | 47 | ||||
-rw-r--r-- | src/main/java/org/onap/cps/ncmp/dmi/service/DmiServiceImpl.java | 127 | ||||
-rw-r--r-- | src/main/java/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClient.java | 38 | ||||
-rw-r--r-- | src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchema.java (renamed from src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchemaProperties.java) | 12 | ||||
-rw-r--r-- | src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchemas.java | 36 | ||||
-rw-r--r-- | src/main/java/org/onap/cps/ncmp/dmi/service/operation/SdncOperations.java | 106 |
8 files changed, 259 insertions, 266 deletions
diff --git a/src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchemaList.java b/src/main/java/org/onap/cps/ncmp/dmi/exception/SdncException.java index a4af1761..a83485a9 100644 --- a/src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchemaList.java +++ b/src/main/java/org/onap/cps/ncmp/dmi/exception/SdncException.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,19 +18,32 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.dmi.service.model; +package org.onap.cps.ncmp.dmi.exception; -import java.util.List; -import lombok.Getter; -import lombok.Setter; +import org.springframework.http.HttpStatus; -/** - * ModuleSchemaList. +/* +Use this exception when SDNC contract fails */ -@Getter -@Setter -public class ModuleSchemaList { +public class SdncException extends DmiException { + + private static final long serialVersionUID = -2076096996672060566L; + + /** + * Constructor. + * + * @param message message + * @param httpStatus httpStatus + * @param responseBody responseBody + */ + public SdncException(final String message, final HttpStatus httpStatus, final String responseBody) { + super(message, String.format("sdnc http status: %s, response body : %s ", + httpStatus.toString(), + responseBody)); + } - private List<ModuleSchemaProperties> schema; + public SdncException(final String message, final String details, final Throwable cause) { + super(message, details, cause); + } } 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 b66e5c1b..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 @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 Nordix Foundation + * Modifications Copyright (C) 2021 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,18 +26,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.google.gson.JsonObject; 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.apache.groovy.parser.antlr4.util.StringUtils; import org.onap.cps.ncmp.dmi.config.DmiPluginConfig.DmiPluginProperties; import org.onap.cps.ncmp.dmi.exception.CmHandleRegistrationException; 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; @@ -45,8 +45,7 @@ import org.onap.cps.ncmp.dmi.service.client.NcmpRestClient; import org.onap.cps.ncmp.dmi.service.model.CmHandleOperation; import org.onap.cps.ncmp.dmi.service.model.CreatedCmHandle; import org.onap.cps.ncmp.dmi.service.model.ModuleReference; -import org.onap.cps.ncmp.dmi.service.model.ModuleSchemaProperties; -import org.onap.cps.ncmp.dmi.service.model.ModuleSchemas; +import org.onap.cps.ncmp.dmi.service.model.ModuleSchema; import org.onap.cps.ncmp.dmi.service.operation.SdncOperations; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -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"; @@ -75,8 +72,8 @@ public class DmiServiceImpl implements DmiService { * @param objectMapper objectMapper */ public DmiServiceImpl(final DmiPluginProperties dmiPluginProperties, - final NcmpRestClient ncmpRestClient, - final SdncOperations sdncOperations, final ObjectMapper objectMapper) { + final NcmpRestClient ncmpRestClient, + final SdncOperations sdncOperations, final ObjectMapper objectMapper) { this.dmiPluginProperties = dmiPluginProperties; this.ncmpRestClient = ncmpRestClient; this.objectMapper = objectMapper; @@ -85,16 +82,14 @@ public class DmiServiceImpl implements DmiService { @Override public ModuleSet getModulesForCmHandle(final String cmHandle) throws DmiException { - final ResponseEntity<String> responseEntity = sdncOperations.getModulesFromNode(cmHandle); - if (responseEntity.getStatusCode() == HttpStatus.OK) { - final String responseBody = responseEntity.getBody(); - if (StringUtils.isEmpty(responseBody)) { - throw new ModulesNotFoundException(cmHandle, "SDNC returned no modules for given cm-handle."); - } - return createModuleSchema(responseBody); + final Collection<ModuleSchema> moduleSchemas = sdncOperations.getModuleSchemasFromNode(cmHandle); + if (moduleSchemas.isEmpty()) { + throw new ModulesNotFoundException(cmHandle, "SDNC returned no modules for given cm-handle."); } else { - throw new DmiException("SDNC is not able to process request.", - RESPONSE_CODE + responseEntity.getStatusCode() + MESSAGE + responseEntity.getBody()); + final ModuleSet moduleSet = new ModuleSet(); + moduleSchemas.forEach(moduleSchema -> + moduleSet.addSchemasItem(toModuleSetSchemas(moduleSchema))); + return moduleSet; } } @@ -109,11 +104,11 @@ public class DmiServiceImpl implements DmiService { } else if (responseEntity.getStatusCode() == HttpStatus.NOT_FOUND) { log.error("SDNC did not return a module resource for the given cmHandle {}", cmHandle); throw new ModuleResourceNotFoundException(cmHandle, - "SDNC did not return a module resource for the given cmHandle."); + "SDNC did not return a module resource for the given cmHandle."); } else { log.error("Error occurred when getting module resources from SDNC for the given cmHandle {}", cmHandle); throw new DmiException(cmHandle, - RESPONSE_CODE + responseEntity.getStatusCode() + MESSAGE + responseEntity.getBody()); + RESPONSE_CODE + responseEntity.getStatusCode() + MESSAGE + responseEntity.getBody()); } } return yangResources; @@ -136,7 +131,7 @@ public class DmiServiceImpl implements DmiService { } catch (final JsonProcessingException e) { log.error("Parsing error occurred while converting cm-handles to JSON {}", cmHandles); throw new DmiException("Internal Server Error.", - "Parsing error occurred while converting given cm-handles object list to JSON "); + "Parsing error occurred while converting given cm-handles object list to JSON "); } final ResponseEntity<String> responseEntity = ncmpRestClient.registerCmHandlesWithNcmp(cmHandlesJson); if ((responseEntity.getStatusCode() != HttpStatus.CREATED)) { @@ -144,76 +139,40 @@ public class DmiServiceImpl implements DmiService { } } - private ModuleSet createModuleSchema(final String responseBody) { - final var moduleSchemas = convertModulesToNodeSchema(responseBody); - final List<ModuleSetSchemas> moduleSetSchemas = new ArrayList<>(); - for (final ModuleSchemaProperties schemaProperties : moduleSchemas.getSchemas().getSchema()) { - moduleSetSchemas.add(convertModulesToModuleSchemas(schemaProperties)); - } - final var moduleSet = new ModuleSet(); - moduleSet.setSchemas(moduleSetSchemas); - return moduleSet; - } - - private ModuleSetSchemas convertModulesToModuleSchemas(final ModuleSchemaProperties moduleSchemaProperties) { + private ModuleSetSchemas toModuleSetSchemas(final ModuleSchema moduleSchema) { final var moduleSetSchemas = new ModuleSetSchemas(); - moduleSetSchemas.setModuleName(moduleSchemaProperties.getIdentifier()); - moduleSetSchemas.setNamespace(moduleSchemaProperties.getNamespace()); - moduleSetSchemas.setRevision(moduleSchemaProperties.getVersion()); + moduleSetSchemas.setModuleName(moduleSchema.getIdentifier()); + moduleSetSchemas.setNamespace(moduleSchema.getNamespace()); + moduleSetSchemas.setRevision(moduleSchema.getVersion()); return moduleSetSchemas; } - private ModuleSchemas convertModulesToNodeSchema(final String modulesListAsJson) { - try { - return objectMapper.readValue(modulesListAsJson, ModuleSchemas.class); - } catch (final JsonProcessingException e) { - log.error("JSON exception occurred when converting the following modules to node schema " - + "{}", modulesListAsJson); - throw new DmiException("Unable to process JSON.", - "JSON exception occurred when mapping modules.", e); - } - } - - @Override - public Object getResourceDataOperationalForCmHandle(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, - RESTCONF_CONTENT_PASSTHROUGH_OPERATIONAL_QUERY_PARAM); - 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. + public String getResourceData(final String cmHandle, + final String resourceIdentifier, + final String acceptParamInHeader, + final String optionsParamInQuery, + final String restconfContentQueryParam) { final ResponseEntity<String> responseEntity = sdncOperations.getResouceDataForOperationalAndRunning(cmHandle, - resourceIdentifier, - optionsParamInQuery, - acceptParamInHeader, - REST_CONF_CONTENT_PASSTHROUGH_RUNNING_QUERY_PARAM); + resourceIdentifier, + optionsParamInQuery, + acceptParamInHeader, + restconfContentQueryParam); 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 { throw new DmiException(cmHandle, - RESPONSE_CODE + responseEntity.getStatusCode() + MESSAGE + responseEntity.getBody()); + RESPONSE_CODE + responseEntity.getStatusCode() + MESSAGE + responseEntity.getBody()); } } @@ -222,7 +181,7 @@ public class DmiServiceImpl implements DmiService { return responseEntity.getBody(); } else { throw new ResourceDataNotFound(cmHandle, - RESPONSE_CODE + responseEntity.getStatusCode() + MESSAGE + responseEntity.getBody()); + RESPONSE_CODE + responseEntity.getStatusCode() + MESSAGE + responseEntity.getBody()); } } @@ -236,15 +195,15 @@ public class DmiServiceImpl implements DmiService { moduleRequest = writer.writeValueAsString(ietfNetconfModuleReferences); } catch (final JsonProcessingException e) { log.error("JSON exception occurred when creating the module request for the given module reference {}", - moduleReference.getName()); + moduleReference.getName()); throw new DmiException("Unable to process JSON.", - "JSON exception occurred when creating the module request.", e); + "JSON exception occurred when creating the module request.", e); } return moduleRequest; } private YangResource toYangResource(final ModuleReference moduleReference, - final ResponseEntity<String> response) { + final ResponseEntity<String> response) { final YangResource yangResource = new YangResource(); yangResource.setModuleName(moduleReference.getName()); yangResource.setRevision(moduleReference.getRevision()); @@ -255,13 +214,13 @@ public class DmiServiceImpl implements DmiService { private String extractYangSourceFromBody(final ResponseEntity<String> responseEntity) { final var responseBodyAsJsonObject = new Gson().fromJson(responseEntity.getBody(), JsonObject.class); if (responseBodyAsJsonObject.getAsJsonObject(IETF_NETCONF_MONITORING_OUTPUT) == null - || responseBodyAsJsonObject.getAsJsonObject(IETF_NETCONF_MONITORING_OUTPUT) - .getAsJsonPrimitive("data") == null) { + || responseBodyAsJsonObject.getAsJsonObject(IETF_NETCONF_MONITORING_OUTPUT) + .getAsJsonPrimitive("data") == null) { log.error("Error occurred when trying to parse the response body from sdnc {}", responseEntity.getBody()); throw new ModuleResourceNotFoundException(responseEntity.getBody(), - "Error occurred when trying to parse the response body from sdnc."); + "Error occurred when trying to parse the response body from sdnc."); } return responseBodyAsJsonObject.getAsJsonObject(IETF_NETCONF_MONITORING_OUTPUT).getAsJsonPrimitive("data") - .toString(); + .toString(); } } 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/model/ModuleSchemaProperties.java b/src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchema.java index 6de7d131..c77e0e41 100644 --- a/src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchemaProperties.java +++ b/src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchema.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 Nordix Foundation + * Modifications Copyright (C) 2021 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,15 +22,10 @@ package org.onap.cps.ncmp.dmi.service.model; import java.util.List; -import lombok.Getter; -import lombok.Setter; +import lombok.Data; -/** - * ModuleSchemaProperties. - */ -@Getter -@Setter -public class ModuleSchemaProperties { +@Data +public class ModuleSchema { private String identifier; private String version; diff --git a/src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchemas.java b/src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchemas.java deleted file mode 100644 index a7b2430d..00000000 --- a/src/main/java/org/onap/cps/ncmp/dmi/service/model/ModuleSchemas.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.dmi.service.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Getter; -import lombok.Setter; - -/** - * ModuleSchemas. - */ -@Getter -@Setter -public class ModuleSchemas { - - @JsonProperty("ietf-netconf-monitoring:schemas") - private ModuleSchemaList schemas; -} 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 98371bf9..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 @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 Nordix Foundation + * Modifications Copyright (C) 2021 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,14 +21,26 @@ package org.onap.cps.ncmp.dmi.service.operation; +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.JsonPathException; +import com.jayway.jsonpath.TypeRef; +import com.jayway.jsonpath.spi.json.JacksonJsonProvider; +import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.apache.groovy.parser.antlr4.util.StringUtils; -import org.jetbrains.annotations.NotNull; 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; import org.springframework.stereotype.Component; @@ -42,12 +55,18 @@ public class SdncOperations { private static final String MOUNT_URL_TEMPLATE = "/node={nodeId}/yang-ext:mount"; private static final String GET_SCHEMA_URL = "/ietf-netconf-monitoring:netconf-state/schemas"; private static final String GET_SCHEMA_SOURCES_URL = "/ietf-netconf-monitoring:get-schema"; + private static final String PATH_TO_MODULE_SCHEMAS = "$.ietf-netconf-monitoring:schemas.schema"; private SdncProperties sdncProperties; private SdncRestconfClient sdncRestconfClient; private final String topologyUrlData; private final String topologyUrlOperational; + private Configuration jsonPathConfiguration = Configuration.builder() + .mappingProvider(new JacksonMappingProvider()) + .jsonProvider(new JacksonJsonProvider()) + .build(); + /** * Constructor for {@code SdncOperations}. This method also manipulates url properties. * @@ -66,11 +85,20 @@ public class SdncOperations { * This method fetches list of modules usind sdnc client. * * @param nodeId node id for node - * @return returns {@code ResponseEntity} which contains list of modules + * @return a collection of module schemas */ - public ResponseEntity<String> getModulesFromNode(final String nodeId) { + public Collection<ModuleSchema> getModuleSchemasFromNode(final String nodeId) { final String urlWithNodeId = prepareGetSchemaUrl(nodeId); - return sdncRestconfClient.getOperation(urlWithNodeId); + final ResponseEntity<String> modulesResponseEntity = sdncRestconfClient.getOperation(urlWithNodeId); + if (modulesResponseEntity.getStatusCode() == HttpStatus.OK) { + final String modulesResponseBody = modulesResponseEntity.getBody(); + return (StringUtils.isEmpty(modulesResponseBody)) ? Collections.emptyList() + : convertToModuleSchemas(modulesResponseBody); + } else { + throw new SdncException( + String.format("SDNC failed to get Modules Schema for node %s", nodeId), + modulesResponseEntity.getStatusCode(), modulesResponseEntity.getBody()); + } } /** @@ -84,17 +112,17 @@ 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); } /** * This method fetches the resource data for given node identifier on given resource using sdnc client. * - * @param nodeId network resource identifier - * @param resourceId resource identifier - * @param optionsParamInQuery fields query - * @param acceptParamInHeader accept parameter + * @param nodeId network resource identifier + * @param resourceId resource identifier + * @param optionsParamInQuery fields query + * @param acceptParamInHeader accept parameter * @param restconfContentQueryParam restconf content query param * @return {@code ResponseEntity} response entity */ @@ -114,7 +142,7 @@ public class SdncOperations { } /** - * Write resource data using passthrough running. + * Write resource data. * * @param nodeId network resource identifier * @param resourceId resource identifier @@ -122,15 +150,18 @@ 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); } - @NotNull private List<String> buildQueryParamList(final String optionsParamInQuery, final String restconfContentQueryParam) { final List<String> queryParamAsList = getOptionsParamAsList(optionsParamInQuery); queryParamAsList.add(restconfContentQueryParam); @@ -146,17 +177,15 @@ public class SdncOperations { return queryParamAsList; } - @NotNull private String stripParenthesisFromOptionsQuery(final String optionsParamInQuery) { return optionsParamInQuery.substring(1, optionsParamInQuery.length() - 1); } - @NotNull private String prepareGetSchemaUrl(final String nodeId) { 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); } @@ -166,14 +195,12 @@ public class SdncOperations { return topologyMountUrlWithNodeId.concat(GET_SCHEMA_SOURCES_URL); } - @NotNull private String prepareResourceDataUrl(final String nodeId, final String resourceId, final List<String> queryList) { return addQuery(addResource(addTopologyDataUrlwithNode(nodeId), resourceId), queryList); } - @NotNull private String addResource(final String url, final String resourceId) { if (resourceId.startsWith("/")) { return url.concat(resourceId); @@ -182,7 +209,6 @@ public class SdncOperations { } } - @NotNull private String addQuery(final String url, final List<String> queryList) { if (queryList.isEmpty()) { return url; @@ -197,9 +223,41 @@ public class SdncOperations { return urlBuilder.toString(); } - @NotNull private String addTopologyDataUrlwithNode(final String nodeId) { final String topologyMountUrl = topologyUrlData + MOUNT_URL_TEMPLATE; return topologyMountUrl.replace("{nodeId}", nodeId); } -}
\ No newline at end of file + + private List<ModuleSchema> convertToModuleSchemas(final String modulesListAsJson) { + try { + return JsonPath.using(jsonPathConfiguration).parse(modulesListAsJson).read( + PATH_TO_MODULE_SCHEMAS, new TypeRef<>() { + }); + } catch (final JsonPathException jsonPathException) { + throw new SdncException("SDNC Response processing failed", + "SDNC response is not in the expected format.", jsonPathException); + } + } + + 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; + } + +} |