summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosephKeenan <joseph.keenan@est.tech>2021-12-08 18:16:44 +0000
committerJosephKeenan <joseph.keenan@est.tech>2021-12-14 16:13:40 +0000
commit82ebf531110deba98086f8f7cb9c745519bbc4f4 (patch)
tree6a64017dc6986dc4d2e042ea33e09e1ffdcd495f
parent4207fab422760b17187d37776ebc1867b995bba1 (diff)
Changing putOperationWithJson to postOperationWithJson
-Modified responseEntity<String> to reesponseEntity<Object> -Changed behaviour of sync to use new repsonses and removed JSON parsing -Updated tests to use new responsess -Tests have been updated and added jira to docs -Added messageConverters to RestTemplate to support plain text with ResponseEntity<Object> -Added docker log output for cps & dmi containers during CSIT teardown -Moved reponse conversion from service into DMIModelOperations class -Added response handling test (edgecases) -Updated response request body for passthrough-running CSIT test to pass Issue-ID: CPS-777 Signed-off-by: JosephKeenan <joseph.keenan@est.tech> Change-Id: If2acf83a97b8aad5aa2c342154d807a47cace6a0
-rwxr-xr-xcps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java51
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java8
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java23
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java52
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy28
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy5
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy17
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy101
-rwxr-xr-xcsit/plans/cps/teardown.sh6
-rw-r--r--csit/tests/ncmp-passthrough/ncmp-passthrough.robot2
-rwxr-xr-xdocs/release-notes.rst2
13 files changed, 191 insertions, 112 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
index faa2efe3a9..bd86cd0c33 100755
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
@@ -28,10 +28,6 @@ import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Collection;
@@ -52,7 +48,6 @@ import org.onap.cps.ncmp.api.models.CmHandle;
import org.onap.cps.ncmp.api.models.DmiPluginRegistration;
import org.onap.cps.ncmp.api.models.PersistenceCmHandle;
import org.onap.cps.ncmp.api.models.PersistenceCmHandlesList;
-import org.onap.cps.ncmp.api.models.YangResource;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
import org.onap.cps.spi.exceptions.DataValidationException;
@@ -308,9 +303,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
}
private void syncAndCreateSchemaSet(final PersistenceCmHandle persistenceCmHandle) {
-
final List<ModuleReference> moduleReferencesFromCmHandle =
- toModuleReferences(dmiModelOperations.getModuleReferences(persistenceCmHandle));
+ dmiModelOperations.getModuleReferences(persistenceCmHandle);
final List<ModuleReference> existingModuleReferences = new ArrayList<>();
final List<ModuleReference> unknownModuleReferences = new ArrayList<>();
prepareModuleSubsets(moduleReferencesFromCmHandle, existingModuleReferences, unknownModuleReferences);
@@ -319,7 +313,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
if (unknownModuleReferences.isEmpty()) {
newYangResourcesModuleNameToContentMap = new HashMap<>();
} else {
- newYangResourcesModuleNameToContentMap = getNewYangResourcesFromDmi(persistenceCmHandle,
+ newYangResourcesModuleNameToContentMap = dmiModelOperations.getNewYangResourcesFromDmi(persistenceCmHandle,
unknownModuleReferences);
}
cpsModuleService
@@ -348,47 +342,6 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
persistenceCmHandle.getId());
}
- private Map<String, String> getNewYangResourcesFromDmi(final PersistenceCmHandle persistenceCmHandle,
- final List<ModuleReference> unknownModuleReferences) {
- final ResponseEntity<String> responseEntity =
- dmiModelOperations.getNewYangResourcesFromDmi(persistenceCmHandle, unknownModuleReferences);
-
- final JsonArray moduleResources = new Gson().fromJson(responseEntity.getBody(),
- JsonArray.class);
- final Map<String, String> newYangResourcesModuleNameToContentMap = new HashMap<>();
-
- for (final JsonElement moduleResource : moduleResources) {
- final YangResource yangResource = toYangResource((JsonObject) moduleResource);
- newYangResourcesModuleNameToContentMap.put(yangResource.getModuleName(), yangResource.getYangSource());
- }
- return newYangResourcesModuleNameToContentMap;
- }
-
- private static YangResource toYangResource(final JsonObject yangResourceAsJson) {
- final YangResource yangResource = new YangResource();
- yangResource.setModuleName(yangResourceAsJson.get("moduleName").getAsString());
- yangResource.setRevision(yangResourceAsJson.get("revision").getAsString());
- yangResource.setYangSource(yangResourceAsJson.get("yangSource").getAsString());
- return yangResource;
- }
- private static List<ModuleReference> toModuleReferences(
- final ResponseEntity<String> dmiFetchModulesResponseEntity) {
- final List<ModuleReference> moduleReferences = new ArrayList<>();
- final JsonObject bodyAsJsonObject = new Gson().fromJson(dmiFetchModulesResponseEntity.getBody(),
- JsonObject.class);
- final JsonArray moduleReferencesAsJson = bodyAsJsonObject.getAsJsonArray("schemas");
- for (final JsonElement moduleReferenceAsJson : moduleReferencesAsJson) {
- final ModuleReference moduleReference = toModuleReference((JsonObject) moduleReferenceAsJson);
- moduleReferences.add(moduleReference);
- }
- return moduleReferences;
- }
- private static ModuleReference toModuleReference(final JsonObject moduleReferenceAsJson) {
- final ModuleReference moduleReference = new ModuleReference();
- moduleReference.setModuleName(moduleReferenceAsJson.get("moduleName").getAsString());
- moduleReference.setRevision(moduleReferenceAsJson.get("revision").getAsString());
- return moduleReference;
- }
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
index 9f3df6b9a5..94faa557fa 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
@@ -53,11 +53,11 @@ public class DmiRestClient {
* @param httpHeaders http headers
* @return response entity of type String
*/
- public ResponseEntity<String> postOperationWithJsonData(final String dmiResourceUrl,
+ public ResponseEntity<Object> postOperationWithJsonData(final String dmiResourceUrl,
final String jsonData,
final HttpHeaders httpHeaders) {
final var httpEntity = new HttpEntity<>(jsonData, configureHttpHeaders(httpHeaders));
- return restTemplate.postForEntity(dmiResourceUrl, httpEntity, String.class);
+ return restTemplate.postForEntity(dmiResourceUrl, httpEntity, Object.class);
}
private HttpHeaders configureHttpHeaders(final HttpHeaders httpHeaders) {
@@ -72,8 +72,8 @@ public class DmiRestClient {
* @param httpHeaders http headers
* @return response entity of type String
*/
- public ResponseEntity<String> postOperation(final String dmiResourceUrl, final HttpHeaders httpHeaders) {
+ public ResponseEntity<Object> postOperation(final String dmiResourceUrl, final HttpHeaders httpHeaders) {
final var httpEntity = new HttpEntity<>(configureHttpHeaders(httpHeaders));
- return restTemplate.exchange(dmiResourceUrl, HttpMethod.POST, httpEntity, String.class);
+ return restTemplate.exchange(dmiResourceUrl, HttpMethod.POST, httpEntity, Object.class);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java
index 81c9dff402..60b44c2461 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java
@@ -20,11 +20,15 @@
package org.onap.cps.ncmp.api.impl.config;
+import java.util.Arrays;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@@ -42,8 +46,25 @@ public class NcmpConfiguration {
private String dmiBasePath;
}
+ /**
+ * Rest template bean.
+ *
+ * @param restTemplateBuilder the rest template builder
+ * @return rest template instance
+ */
@Bean
+ @Scope("singleton")
public static RestTemplate restTemplate(final RestTemplateBuilder restTemplateBuilder) {
- return restTemplateBuilder.build();
+ final RestTemplate restTemplate = restTemplateBuilder.build();
+ setRestTemplateMessageConverters(restTemplate);
+ return restTemplate;
+ }
+
+ private static void setRestTemplateMessageConverters(final RestTemplate restTemplate) {
+ final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
+ new MappingJackson2HttpMessageConverter();
+ mappingJackson2HttpMessageConverter.setSupportedMediaTypes(
+ Arrays.asList(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN));
+ restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
index eccb9a0987..095f677ef8 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
@@ -62,7 +62,7 @@ public class DmiDataOperations extends DmiOperations {
* @param dataStore data store enum
* @return {@code ResponseEntity} response entity
*/
- public ResponseEntity<String> getResourceDataFromDmi(final String cmHandle,
+ public ResponseEntity<Object> getResourceDataFromDmi(final String cmHandle,
final String resourceId,
final String optionsParamInQuery,
final String acceptParamInHeader,
@@ -93,7 +93,7 @@ public class DmiDataOperations extends DmiOperations {
* @param dataType data type
* @return {@code ResponseEntity} response entity
*/
- public ResponseEntity<String> writeResourceDataPassThroughRunningFromDmi(final String cmHandle,
+ public ResponseEntity<Object> writeResourceDataPassThroughRunningFromDmi(final String cmHandle,
final String resourceId,
final OperationEnum operation,
final String requestData,
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
index c582584667..f74616ab30 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
@@ -25,10 +25,14 @@ import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.MODEL;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
import org.onap.cps.ncmp.api.models.PersistenceCmHandle;
+import org.onap.cps.ncmp.api.models.YangResource;
import org.onap.cps.spi.model.ModuleReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
@@ -55,12 +59,14 @@ public class DmiModelOperations extends DmiOperations {
* @param persistenceCmHandle the persistence cm handle
* @return module references
*/
- public ResponseEntity<String> getModuleReferences(final PersistenceCmHandle persistenceCmHandle) {
+ public List<ModuleReference> getModuleReferences(final PersistenceCmHandle persistenceCmHandle) {
final DmiRequestBody dmiRequestBody = DmiRequestBody.builder()
.build();
dmiRequestBody.asCmHandleProperties(persistenceCmHandle.getAdditionalProperties());
- return getResourceFromDmiWithJsonData(persistenceCmHandle.resolveDmiServiceName(MODEL),
+ final ResponseEntity<Object> dmiFetchModulesResponseEntity = getResourceFromDmiWithJsonData(
+ persistenceCmHandle.resolveDmiServiceName(MODEL),
getDmiRequestBodyAsString(dmiRequestBody), persistenceCmHandle.getId(), "modules");
+ return toModuleReferences((Map) dmiFetchModulesResponseEntity.getBody());
}
/**
@@ -68,17 +74,18 @@ public class DmiModelOperations extends DmiOperations {
*
* @param persistenceCmHandle the persistenceCmHandle
* @param unknownModuleReferences the unknown module references
- * @return yang resources
+ * @return yang resources as map of module name to yang(re)source
*/
- public ResponseEntity<String> getNewYangResourcesFromDmi(final PersistenceCmHandle persistenceCmHandle,
- final List<ModuleReference> unknownModuleReferences) {
+ public Map<String, String> getNewYangResourcesFromDmi(final PersistenceCmHandle persistenceCmHandle,
+ final List<ModuleReference> unknownModuleReferences) {
final String jsonDataWithDataAndCmHandleProperties = getRequestBodyToFetchYangResources(
unknownModuleReferences, persistenceCmHandle.getAdditionalProperties());
- return getResourceFromDmiWithJsonData(
+ final ResponseEntity<Object> responseEntity = getResourceFromDmiWithJsonData(
persistenceCmHandle.resolveDmiServiceName(MODEL),
jsonDataWithDataAndCmHandleProperties,
persistenceCmHandle.getId(),
"moduleResources");
+ return asModuleNameToYangResourceMap(responseEntity);
}
/**
@@ -90,7 +97,7 @@ public class DmiModelOperations extends DmiOperations {
* @param resourceName name of the resource(s)
* @return {@code ResponseEntity} response entity
*/
- private ResponseEntity<String> getResourceFromDmiWithJsonData(final String dmiServiceName,
+ private ResponseEntity<Object> getResourceFromDmiWithJsonData(final String dmiServiceName,
final String jsonData,
final String cmHandle,
final String resourceName) {
@@ -122,7 +129,6 @@ public class DmiModelOperations extends DmiOperations {
}
private static JsonObject toJsonObject(final List<PersistenceCmHandle.AdditionalProperty> cmHandleProperties) {
- //TODO Toine/Joe Double check format with existing test data
final JsonObject asJsonObject = new JsonObject();
for (final PersistenceCmHandle.AdditionalProperty additionalProperty : cmHandleProperties) {
asJsonObject.addProperty(additionalProperty.getName(), additionalProperty.getValue());
@@ -130,4 +136,34 @@ public class DmiModelOperations extends DmiOperations {
return asJsonObject;
}
+ private List<ModuleReference> toModuleReferences(final Map dmiFetchModulesResponseAsMap) {
+ final List<ModuleReference> moduleReferences = new ArrayList<>();
+
+ if (dmiFetchModulesResponseAsMap != null) {
+ final List moduleReferencesAsList = (List) dmiFetchModulesResponseAsMap.get("schemas");
+ if (moduleReferencesAsList != null) {
+ moduleReferencesAsList.forEach(moduleReferenceAsMap -> {
+ final ModuleReference moduleReference =
+ objectMapper.convertValue(moduleReferenceAsMap, ModuleReference.class);
+ moduleReferences.add(moduleReference);
+ });
+ }
+ }
+ return moduleReferences;
+ }
+
+ private Map<String, String> asModuleNameToYangResourceMap(final ResponseEntity<Object> responseEntity) {
+ final Map<String, String> yangResourcesModuleNameToContentMap = new HashMap<>();
+ final List<Map<String, String>> yangResourcesAsList = (List) responseEntity.getBody();
+
+ if (yangResourcesAsList != null) {
+ yangResourcesAsList.forEach(yangResourceAsMap -> {
+ final YangResource yangResource =
+ objectMapper.convertValue(yangResourceAsMap, YangResource.class);
+ yangResourcesModuleNameToContentMap.put(yangResource.getModuleName(),
+ yangResource.getYangSource());
+ });
+ }
+ return yangResourcesModuleNameToContentMap;
+ }
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy
index a5c1f45d54..de60a01930 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy
@@ -20,15 +20,12 @@
package org.onap.cps.ncmp.api.impl
-
+import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.api.CpsAdminService
import org.onap.cps.api.CpsModuleService
import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations
import org.onap.cps.ncmp.api.models.PersistenceCmHandle
-import org.onap.cps.ncmp.utils.TestUtils
import org.onap.cps.spi.model.ModuleReference
-import org.springframework.http.HttpStatus
-import org.springframework.http.ResponseEntity
import spock.lang.Specification
class NetworkCmProxyDataServiceImplModelSyncSpec extends Specification {
@@ -38,7 +35,7 @@ class NetworkCmProxyDataServiceImplModelSyncSpec extends Specification {
def mockDmiModelOperations = Mock(DmiModelOperations)
def objectUnderTest = new NetworkCmProxyDataServiceImpl(null, mockDmiModelOperations,
- mockCpsModuleService, null, null, mockCpsAdminService, null)
+ mockCpsModuleService, null, null, mockCpsAdminService, new ObjectMapper())
def expectedDataspaceName = 'NFP-Operational'
@@ -50,25 +47,24 @@ class NetworkCmProxyDataServiceImplModelSyncSpec extends Specification {
cmHandleForModelSync.asAdditionalProperties(additionalProperties)
}
and: 'dmi operations returns some module references'
- def jsonData = TestUtils.getResourceFileContent('cmHandleModules.json')
- def moduleReferencesFromCmHandleAsJson = new ResponseEntity<String>(jsonData, HttpStatus.OK)
- mockDmiModelOperations.getModuleReferences(cmHandleForModelSync) >> moduleReferencesFromCmHandleAsJson
+ def moduleReferences = [ new ModuleReference(moduleName:'module1',revision:'1'),
+ new ModuleReference(moduleName:'module2',revision:'2') ]
+ mockDmiModelOperations.getModuleReferences(cmHandleForModelSync) >> moduleReferences
and: 'CPS-Core returns list of existing module resources'
mockCpsModuleService.getYangResourceModuleReferences(expectedDataspaceName) >> existingModuleResourcesInCps
and: 'DMI-Plugin returns resource(s) for "new" module(s)'
- def moduleResources = new ResponseEntity<String>(sdncReponseBody, HttpStatus.OK)
- mockDmiModelOperations.getNewYangResourcesFromDmi(cmHandleForModelSync, [new ModuleReference('module1', '1')]) >> moduleResources
+ mockDmiModelOperations.getNewYangResourcesFromDmi(cmHandleForModelSync, [new ModuleReference('module1', '1')]) >> yangResourceToContentMap
when: 'module sync is triggered'
objectUnderTest.syncModulesAndCreateAnchor(cmHandleForModelSync)
then: 'the CPS module service is called once with the correct parameters'
- 1 * mockCpsModuleService.createSchemaSetFromModules(expectedDataspaceName, cmHandleForModelSync.getId(), expectedYangResourceToContentMap, expectedKnownModules)
+ 1 * mockCpsModuleService.createSchemaSetFromModules(expectedDataspaceName, cmHandleForModelSync.getId(), yangResourceToContentMap, expectedKnownModules)
and: 'admin service create anchor method has been called with correct parameters'
1 * mockCpsAdminService.createAnchor(expectedDataspaceName, cmHandleForModelSync.getId(), cmHandleForModelSync.getId())
where: 'the following parameters are used'
- scenario | additionalProperties | existingModuleResourcesInCps | sdncReponseBody || expectedYangResourceToContentMap | expectedKnownModules | expectedJsonForAdditionalProperties
- 'one unknown module' | ['name1': 'value1'] | [new ModuleReference('module2', '2'), new ModuleReference('module3', '3')] | '[{"moduleName" : "module1", "revision" : "1","yangSource": "some yang source"}]' || [module1: 'some yang source'] | [new ModuleReference('module2', '2')] | '{"name1":"value1"}'
- 'no add. properties' | [:] | [new ModuleReference('module2', '2'), new ModuleReference('module3', '3')] | '[{"moduleName" : "module1", "revision" : "1","yangSource": "some yang source"}]' || [module1: 'some yang source'] | [new ModuleReference('module2', '2')] | '{}'
- 'additional properties is null' | null | [new ModuleReference('module2', '2'), new ModuleReference('module3', '3')] | '[{"moduleName" : "module1", "revision" : "1","yangSource": "some yang source"}]' || [module1: 'some yang source'] | [new ModuleReference('module2', '2')] | '{}'
- 'no unknown module' | [:] | [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')] | '[]' || [:] | [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')] | '{}'
+ scenario | additionalProperties | existingModuleResourcesInCps | yangResourceToContentMap || expectedKnownModules | expectedJsonForAdditionalProperties
+ 'one unknown module' | ['name1': 'value1'] | [new ModuleReference('module2', '2'), new ModuleReference('module3', '3')] | [module1: 'some yang source'] || [new ModuleReference('module2', '2')] | '{"name1":"value1"}'
+ 'no add. properties' | [:] | [new ModuleReference('module2', '2'), new ModuleReference('module3', '3')] | [module1: 'some yang source'] || [new ModuleReference('module2', '2')] | '{}'
+ 'additional properties is null' | null | [new ModuleReference('module2', '2'), new ModuleReference('module3', '3')] | [module1: 'some yang source'] || [new ModuleReference('module2', '2')] | '{}'
+ 'no unknown module' | [:] | [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')] | [:] || [new ModuleReference('module1', '1'), new ModuleReference('module2', '2')] | '{}'
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
index c396a2ef26..62492710e0 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
@@ -22,10 +22,6 @@
package org.onap.cps.ncmp.api.impl
-import org.onap.cps.ncmp.api.impl.client.DmiRestClient
-import org.onap.cps.ncmp.api.impl.operations.DmiRequestBody
-import org.springframework.http.HttpHeaders
-
import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL
import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE
@@ -40,7 +36,6 @@ import org.onap.cps.api.CpsModuleService
import org.onap.cps.api.CpsQueryService
import org.onap.cps.ncmp.api.impl.exception.NcmpException
import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
-import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.model.DataNode
import org.springframework.http.HttpStatus
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
index 8c46178ddd..389086c770 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
@@ -46,7 +46,7 @@ class DmiRestClientSpec extends Specification {
def 'DMI POST operation'() {
given: 'the rest template returns a valid response entity'
def mockResponseEntity = Mock(ResponseEntity)
- mockRestTemplate.exchange(resourceUrl, HttpMethod.POST, _ as HttpEntity, String.class) >> mockResponseEntity
+ mockRestTemplate.exchange(resourceUrl, HttpMethod.POST, _ as HttpEntity, Object.class) >> mockResponseEntity
when: 'POST operation is invoked'
def result = objectUnderTest.postOperation(resourceUrl, new HttpHeaders())
then: 'the output of the method is equal to the output from the rest template'
@@ -56,7 +56,7 @@ class DmiRestClientSpec extends Specification {
def 'DMI POST operation with JSON.'() {
given: 'the rest template returns a valid response entity'
def mockResponseEntity = Mock(ResponseEntity)
- mockRestTemplate.postForEntity(resourceUrl, _ as HttpEntity, String.class) >> mockResponseEntity
+ mockRestTemplate.postForEntity(resourceUrl, _ as HttpEntity, Object.class) >> mockResponseEntity
when: 'POST operation is invoked'
def result = objectUnderTest.postOperationWithJsonData(resourceUrl, 'json-data', new HttpHeaders())
then: 'the output of the method is equal to the output from the test template'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy
index 2c4ba68f29..e1aba79a50 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy
@@ -22,6 +22,8 @@ package org.onap.cps.ncmp.api.impl.config
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.web.client.RestTemplateBuilder
+import org.springframework.http.MediaType
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.test.context.ContextConfiguration
import org.springframework.web.client.RestTemplate
import spock.lang.Specification
@@ -33,6 +35,8 @@ class NcmpConfigurationSpec extends Specification{
@Autowired
NcmpConfiguration.DmiProperties dmiProperties
+ def mockRestTemplateBuilder = new RestTemplateBuilder()
+
def 'NcmpConfiguration Construction.'() {
expect: 'the system can create an instance'
new NcmpConfiguration() != null
@@ -45,13 +49,14 @@ class NcmpConfigurationSpec extends Specification{
}
def 'Rest Template creation.'() {
- given: 'a rest template builder'
- def mockRestTemplateBuilder = Mock(RestTemplateBuilder)
- def expectedRestTemplate = Mock(RestTemplate)
- mockRestTemplateBuilder.build() >> expectedRestTemplate
when: 'a rest template is created'
def result = NcmpConfiguration.restTemplate(mockRestTemplateBuilder)
- then: 'the rest template from the builder is returned'
- assert result == expectedRestTemplate
+ then: 'the rest template is returned'
+ assert result instanceof RestTemplate
+ and: 'a jackson media converter has been added'
+ def lastMessageConverter = result.getMessageConverters().get(result.getMessageConverters().size()-1)
+ lastMessageConverter instanceof MappingJackson2HttpMessageConverter
+ and: 'the jackson media converters supports the expected media types'
+ lastMessageConverter.getSupportedMediaTypes() == [MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN];
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
index d9d12711fb..335bc062cc 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
@@ -41,8 +41,41 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
@Autowired
DmiModelOperations objectUnderTest
- def 'Module references for a persistence cm handle #scenario.'() {
- given: 'a persistence cm handle for #cmHandleId'
+ def 'Retrieving module references.'() {
+ given: 'a persistence cm handle'
+ mockPersistenceCmHandleRetrieval([])
+ and: 'a positive response from dmi service when it is called with the expected parameters'
+ def moduleReferencesAsLisOfMaps = [[moduleName:'mod1',revision:'A'],[moduleName:'mod2',revision:'X']]
+ def responseFromDmi = new ResponseEntity([schemas:moduleReferencesAsLisOfMaps], HttpStatus.OK)
+ mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules",
+ '{"cmHandleProperties":{}}', [:]) >> responseFromDmi
+ when: 'get module references is called'
+ def result = objectUnderTest.getModuleReferences(persistenceCmHandle)
+ then: 'the result consists of expected module references'
+ assert result == [new ModuleReference(moduleName:'mod1',revision:'A'), new ModuleReference(moduleName:'mod2',revision:'X')]
+ }
+
+ def 'Retrieving module references edge case: #scenario.'() {
+ given: 'a persistence cm handle'
+ mockPersistenceCmHandleRetrieval([])
+ and: 'any response from dmi service when it is called with the expected parameters'
+ // TODO (toine): production code ignores any error code from DMI, this should be improved in future
+ def responseFromDmi = new ResponseEntity(bodyAsMap, HttpStatus.NO_CONTENT)
+ mockDmiRestClient.postOperationWithJsonData(*_) >> responseFromDmi
+ when: 'get module references is called'
+ def result = objectUnderTest.getModuleReferences(persistenceCmHandle)
+ then: 'the result is empty'
+ assert result == []
+ where: 'the dmi response body has the following content'
+ scenario | bodyAsMap
+ 'no modules' | [schemas:[]]
+ 'modules null' | [schemas:null]
+ 'no schema' | [something:'else']
+ 'no body' | null
+ }
+
+ def 'Retrieving module references, additional property handling: #scenario.'() {
+ given: 'a persistence cm handle'
mockPersistenceCmHandleRetrieval(additionalPropertiesObject)
and: 'a positive response from dmi service when it is called with tha expected parameters'
def responseFromDmi = new ResponseEntity<String>(HttpStatus.OK)
@@ -51,35 +84,69 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
when: 'a get module references is called'
def result = objectUnderTest.getModuleReferences(persistenceCmHandle)
then: 'the result is the response from dmi service'
- assert result == responseFromDmi
- where:
+ assert result == []
+ where: 'the following additional properties are used'
scenario | additionalPropertiesObject || expectedAdditionalPropertiesInRequest
'with properties' | [sampleAdditionalProperty] || '{"prop1":"val1"}'
- 'with null properties' | null || "{}"
- 'without properties' | [] || "{}"
+ 'with null properties' | null || '{}'
+ 'without properties' | [] || '{}'
}
- def 'New yang resources from dmi using persistence cm handle #scenario.'() {
- given: 'a persistence cm handle for #cmHandleId'
- mockPersistenceCmHandleRetrieval(additionalPropertiesObject)
+ def 'Retrieving yang resources.'() {
+ given: 'a persistence cm handle'
+ mockPersistenceCmHandleRetrieval([])
and: 'a positive response from dmi service when it is called with tha expected parameters'
- def responseFromDmi = new ResponseEntity<String>(HttpStatus.OK)
+ def responseFromDmi = new ResponseEntity([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source'],
+ [moduleName: 'mod2', revision: 'C', yangSource: 'other yang source']], HttpStatus.OK)
+ def expectedModuleReferencesInRequest = '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}'
+ mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
+ '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}', [:]) >> responseFromDmi
+ when: 'get new yang resources from dmi service'
+ def result = objectUnderTest.getNewYangResourcesFromDmi(persistenceCmHandle, newModuleReferences)
+ then: 'the result has the 2 expected yang (re)sources (order is not guaranteed)'
+ assert result.size() == 2
+ assert result.get('mod1') == 'some yang source'
+ assert result.get('mod2') == 'other yang source'
+ }
+
+ def 'Retrieving yang resources, edge case: scenario.'() {
+ given: 'a persistence cm handle'
+ mockPersistenceCmHandleRetrieval([])
+ and: 'a positive response from dmi service when it is called with tha expected parameters'
+ // TODO (toine): production code ignores any error code from DMI, this should be improved in future
+ def responseFromDmi = new ResponseEntity(responseFromDmiBody, HttpStatus.NO_CONTENT)
+ mockDmiRestClient.postOperationWithJsonData(*_) >> responseFromDmi
+ when: 'get new yang resources from dmi service'
+ def result = objectUnderTest.getNewYangResourcesFromDmi(persistenceCmHandle, newModuleReferences)
+ then: 'the result is empty'
+ assert result == [:]
+ where: 'the dmi response body has the following content'
+ scenario | responseFromDmiBody
+ 'empty array' | []
+ 'null array' | null
+ }
+
+ def 'Retrieving yang resources, additional property handling #scenario.'() {
+ given: 'a persistence cm handle'
+ mockPersistenceCmHandleRetrieval(additionalPropertiesObject)
+ and: 'a positive response from dmi service when it is called with the expected parameters'
+ def responseFromDmi = new ResponseEntity<>([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source']], HttpStatus.OK)
mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
'{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":'+expectedAdditionalPropertiesInRequest+'}',
[:]) >> responseFromDmi
when: 'get new yang resources from dmi service'
def result = objectUnderTest.getNewYangResourcesFromDmi(persistenceCmHandle, unknownModuleReferences)
then: 'the result is the response from dmi service'
- assert result == responseFromDmi
- where:
+ assert result == [mod1:'some yang source']
+ where: 'the following additional properties are used'
scenario | additionalPropertiesObject | unknownModuleReferences || expectedAdditionalPropertiesInRequest | expectedModuleReferencesInRequest
'with module references and properties' | [sampleAdditionalProperty] | newModuleReferences || '{"prop1":"val1"}' | '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}'
'without module references' | [sampleAdditionalProperty] | [] || '{"prop1":"val1"}' | ''
'without properties' | [] | newModuleReferences || '{}' | '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}'
}
- def 'New yang resources from dmi with additional properties null'() {
- given: 'a persistence cm handle for #cmHandleId'
+ def 'Retrieving yang resources from dmi with additional properties null.'() {
+ given: 'a persistence cm handle'
mockPersistenceCmHandleRetrieval(null)
when: 'a get new yang resources from dmi is called'
objectUnderTest.getNewYangResourcesFromDmi(persistenceCmHandle, [])
@@ -87,8 +154,8 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
thrown(NullPointerException)
}
- def 'Json Processing Exception'() {
- given: 'a persistence cm handle for #cmHandleId'
+ def 'Retrieving module references with Json processing exception.'() {
+ given: 'a persistence cm handle'
mockPersistenceCmHandleRetrieval([])
and: 'a Json processing exception occurs'
spyObjectMapper.writeValueAsString(_) >> {throw (new JsonProcessingException(''))}
@@ -97,7 +164,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
then: 'an ncmp exception is thrown'
def exceptionThrown = thrown(NcmpException)
and: 'the message indicates a parsing error'
- exceptionThrown.message.toLowerCase().contains("parsing error")
+ exceptionThrown.message.toLowerCase().contains('parsing error')
}
}
diff --git a/csit/plans/cps/teardown.sh b/csit/plans/cps/teardown.sh
index 75f0af41fc..f1939cf4b3 100755
--- a/csit/plans/cps/teardown.sh
+++ b/csit/plans/cps/teardown.sh
@@ -21,6 +21,12 @@
# Branched from ccsdk/distribution to this repository Feb 23, 2021
#
+echo '================================== CPS-NCMP Logs ========================'
+docker logs cps-and-ncmp
+
+echo '================================== DMI Logs ============================='
+docker logs ncmp-dmi-plugin
+
echo 'Stopping, Removing all running containers...'
docker stop $(docker ps -aq) && docker rm $(docker ps -aq)
diff --git a/csit/tests/ncmp-passthrough/ncmp-passthrough.robot b/csit/tests/ncmp-passthrough/ncmp-passthrough.robot
index 51eabc87e9..1673baa601 100644
--- a/csit/tests/ncmp-passthrough/ncmp-passthrough.robot
+++ b/csit/tests/ncmp-passthrough/ncmp-passthrough.robot
@@ -100,7 +100,7 @@ Verify update to bookstore using passthrough-running did not remove category 02
Delete Bookstore using passthrough-running for Category 01
${uri}= Set Variable ${ncmpBasePath}/v1/ch/PNFDemo/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=stores:bookstore/categories=01
${headers}= Create Dictionary Content-Type=application/json Authorization=${auth}
- ${response}= DELETE On Session CPS_URL ${uri} headers=${headers} data=''
+ ${response}= DELETE On Session CPS_URL ${uri} headers=${headers} data={}
Should Be Equal As Strings ${response.status_code} 204
Verify delete to bookstore using passthrough-running removed only category 01
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
index da96970722..0ee8b1ba80 100755
--- a/docs/release-notes.rst
+++ b/docs/release-notes.rst
@@ -26,11 +26,11 @@ This section lists the main changes & fixes merged into master (snapshot) versio
Features
--------
-
- `CPS-559 <https://jira.onap.org/browse/CPS-559>`_ Define response objects (schemas) in cps-ncmp
- `CPS-636 <https://jira.onap.org/browse/CPS-636>`_ Update operation for datastore pass through running
- `CPS-638 <https://jira.onap.org/browse/CPS-638>`_ Delete operation for datastore pass through running
- `CPS-741 <https://jira.onap.org/browse/CPS-741>`_ Re sync after removing cm handles
+ - `CPS-777 <https://jira.onap.org/browse/CPS-777>`_ Ensure all DMI operations use POST method
- `CPS-780 <https://jira.onap.org/browse/CPS-780>`_ Add examples for parameters, request and response in openapi yaml for cps-core
Bug Fixes