From 63132cec2c18363a8224646039cc23b6144d8e6c Mon Sep 17 00:00:00 2001 From: DylanB95EST Date: Tue, 14 Dec 2021 16:34:38 +0000 Subject: [PATCH] Support 'public' Cm Handle Properties Add support for new Public Additional Properties list to Register CM Handles API Issue-ID: CPS-677 Change-Id: I6efc88734da2416f72f71a403622e519398b502d Signed-off-by: DylanB95EST --- .gitignore | 1 + cps-ncmp-rest/docs/openapi/components.yaml | 10 ++- .../NetworkCmProxyInventoryControllerSpec.groovy | 3 +- .../src/test/resources/dmi-registration.json | 5 +- .../api/impl/operations/DmiDataOperations.java | 8 +- .../api/impl/operations/DmiModelOperations.java | 21 ++--- .../ncmp/api/impl/operations/DmiRequestBody.java | 30 +++----- .../operations/PersistenceCmHandleRetriever.java | 43 +++++------ .../org/onap/cps/ncmp/api/models/CmHandle.java | 15 +++- .../cps/ncmp/api/models/PersistenceCmHandle.java | 36 ++++----- ...tworkCmProxyDataServiceImplModelSyncSpec.groovy | 32 ++++---- ...rkCmProxyDataServiceImplRegistrationSpec.groovy | 17 ++-- .../impl/NetworkCmProxyDataServiceImplSpec.groovy | 90 +++++++--------------- .../impl/operations/DmiDataOperationsSpec.groovy | 25 +++--- .../impl/operations/DmiModelOperationsSpec.groovy | 59 +++++++------- .../impl/operations/DmiOperationsBaseSpec.groovy | 28 ++++++- .../PersistenceCmHandleRetrieverSpec.groovy | 39 +++++++--- .../ncmp/api/models/PersistenceCmHandleSpec.groovy | 33 ++++---- cps-parent/pom.xml | 47 +++++++++++ .../09-loadData-dmi-registry-schema-set.yaml | 50 +++++++++++- .../db/changes/data/dmi/generated-csv/README.md | 23 ++++++ .../dmi/schema_set_yang_resources@2021-12-13.csv | 3 + .../data/yang-models/dmi-registry@2021-12-13.yang | 63 +++++++++++++++ .../src/main/resources/yangResourceCsvGenerator.py | 38 +++++++++ .../cps/api/impl/CpsDataServiceImplSpec.groovy | 16 ++-- cps-service/src/test/resources/dmi-registry.yang | 42 ---------- docs/api/swagger/ncmp/openapi-inventory.yaml | 37 +++++++-- 27 files changed, 513 insertions(+), 301 deletions(-) create mode 100644 cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md create mode 100644 cps-ri/src/main/resources/changelog/db/changes/data/dmi/schema_set_yang_resources@2021-12-13.csv create mode 100644 cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang create mode 100644 cps-ri/src/main/resources/yangResourceCsvGenerator.py delete mode 100644 cps-service/src/test/resources/dmi-registry.yang diff --git a/.gitignore b/.gitignore index 58f1b2b12..624bc1ac1 100755 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.log.zip cps-application/archunit_store +cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/generated_yang_resource_* target/ log/ diff --git a/cps-ncmp-rest/docs/openapi/components.yaml b/cps-ncmp-rest/docs/openapi/components.yaml index e63f9c0b8..021a79037 100644 --- a/cps-ncmp-rest/docs/openapi/components.yaml +++ b/cps-ncmp-rest/docs/openapi/components.yaml @@ -1,5 +1,5 @@ # ============LICENSE_START======================================================= -# Copyright (C) 2021 Nordix Foundation +# Copyright (C) 2021-2022 Nordix Foundation # Modifications Copyright (C) 2021 Pantheon.tech # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); @@ -67,12 +67,14 @@ components: type: string example: my-cm-handle cmHandleProperties: - $ref: '#/components/schemas/RestCmHandleAdditionalProperties' - RestCmHandleAdditionalProperties: + $ref: '#/components/schemas/RestCmHandleProperties' + publicCmHandleProperties: + $ref: '#/components/schemas/RestCmHandleProperties' + RestCmHandleProperties: type: object additionalProperties: type: string - example: my-additional-property + example: my-property Conditions: type: object diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy index 4addf7bdf..8d434e775 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryControllerSpec.groovy @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 Bell Canada + * Modifications Copyright (C) 2021-2022 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,10 +23,8 @@ package org.onap.cps.ncmp.rest.controller import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.TestUtils import org.onap.cps.ncmp.api.NetworkCmProxyDataService -import org.onap.cps.ncmp.api.impl.NetworkCmProxyDataServiceImpl 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.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value diff --git a/cps-ncmp-rest/src/test/resources/dmi-registration.json b/cps-ncmp-rest/src/test/resources/dmi-registration.json index 24bc9f963..4f27e1184 100644 --- a/cps-ncmp-rest/src/test/resources/dmi-registration.json +++ b/cps-ncmp-rest/src/test/resources/dmi-registration.json @@ -4,7 +4,10 @@ { "cmHandle": "example-name", "cmHandleProperties": { - "subSystemId" : "system-001" + "subSystemId" : "system-001" + }, + "publicCmHandleProperties": { + "area" : "south" } } ] 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 3bfb424a2..bce3ac384 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 @@ -68,11 +68,11 @@ public class DmiDataOperations extends DmiOperations { final String acceptParamInHeader, final DataStoreEnum dataStore) { final PersistenceCmHandle persistenceCmHandle = - cmHandlePropertiesRetriever.retrieveCmHandleDmiServiceNameAndProperties(cmHandle); + cmHandlePropertiesRetriever.retrieveCmHandleDmiServiceNameAndDmiProperties(cmHandle); final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() .operation(READ) .build(); - dmiRequestBody.asCmHandleProperties(persistenceCmHandle.getAdditionalProperties()); + dmiRequestBody.asDmiProperties(persistenceCmHandle.getDmiProperties()); final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody); final var dmiResourceDataUrl = getDmiDatastoreUrlWithOptions( @@ -99,13 +99,13 @@ public class DmiDataOperations extends DmiOperations { final String requestData, final String dataType) { final PersistenceCmHandle persistenceCmHandle = - cmHandlePropertiesRetriever.retrieveCmHandleDmiServiceNameAndProperties(cmHandle); + cmHandlePropertiesRetriever.retrieveCmHandleDmiServiceNameAndDmiProperties(cmHandle); final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() .operation(operation) .data(requestData) .dataType(dataType) .build(); - dmiRequestBody.asCmHandleProperties(persistenceCmHandle.getAdditionalProperties()); + dmiRequestBody.asDmiProperties(persistenceCmHandle.getDmiProperties()); final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody); final String dmiUrl = getResourceInDataStoreUrl(persistenceCmHandle.resolveDmiServiceName(DATA), 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 1ce6dcfcd..657b0b474 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 @@ -49,11 +49,11 @@ public class DmiModelOperations extends DmiOperations { * * @param dmiRestClient {@code DmiRestClient} */ - public DmiModelOperations(final PersistenceCmHandleRetriever cmHandlePropertiesRetriever, + public DmiModelOperations(final PersistenceCmHandleRetriever dmiPropertiesRetriever, final JsonObjectMapper jsonObjectMapper, final NcmpConfiguration.DmiProperties dmiProperties, final DmiRestClient dmiRestClient) { - super(cmHandlePropertiesRetriever, jsonObjectMapper, dmiProperties, dmiRestClient); + super(dmiPropertiesRetriever, jsonObjectMapper, dmiProperties, dmiRestClient); } /** @@ -65,7 +65,7 @@ public class DmiModelOperations extends DmiOperations { public List getModuleReferences(final PersistenceCmHandle persistenceCmHandle) { final DmiRequestBody dmiRequestBody = DmiRequestBody.builder() .build(); - dmiRequestBody.asCmHandleProperties(persistenceCmHandle.getAdditionalProperties()); + dmiRequestBody.asDmiProperties(persistenceCmHandle.getDmiProperties()); final ResponseEntity dmiFetchModulesResponseEntity = getResourceFromDmiWithJsonData( persistenceCmHandle.resolveDmiServiceName(MODEL), jsonObjectMapper.asJsonString(dmiRequestBody), persistenceCmHandle.getId(), "modules"); @@ -81,11 +81,11 @@ public class DmiModelOperations extends DmiOperations { */ public Map getNewYangResourcesFromDmi(final PersistenceCmHandle persistenceCmHandle, final List unknownModuleReferences) { - final String jsonDataWithDataAndCmHandleProperties = getRequestBodyToFetchYangResources( - unknownModuleReferences, persistenceCmHandle.getAdditionalProperties()); + final String jsonWithDataAndDmiProperties = getRequestBodyToFetchYangResources( + unknownModuleReferences, persistenceCmHandle.getDmiProperties()); final ResponseEntity responseEntity = getResourceFromDmiWithJsonData( persistenceCmHandle.resolveDmiServiceName(MODEL), - jsonDataWithDataAndCmHandleProperties, + jsonWithDataAndDmiProperties, persistenceCmHandle.getId(), "moduleResources"); return asModuleNameToYangResourceMap(responseEntity); @@ -109,13 +109,13 @@ public class DmiModelOperations extends DmiOperations { } private static String getRequestBodyToFetchYangResources(final List unknownModuleReferences, - final List cmHandleProperties) { + final List dmiProperties) { final JsonArray moduleReferencesAsJson = getModuleReferencesAsJson(unknownModuleReferences); final JsonObject data = new JsonObject(); data.add("modules", moduleReferencesAsJson); final JsonObject jsonRequestObject = new JsonObject(); jsonRequestObject.add("data", data); - jsonRequestObject.add("cmHandleProperties", toJsonObject(cmHandleProperties)); + jsonRequestObject.add("cmHandleProperties", toJsonObject(dmiProperties)); return jsonRequestObject.toString(); } @@ -131,9 +131,10 @@ public class DmiModelOperations extends DmiOperations { return moduleReferences; } - private static JsonObject toJsonObject(final List cmHandleProperties) { + private static JsonObject toJsonObject(final List + dmiProperties) { final JsonObject asJsonObject = new JsonObject(); - for (final PersistenceCmHandle.AdditionalProperty additionalProperty : cmHandleProperties) { + for (final PersistenceCmHandle.Property additionalProperty : dmiProperties) { asJsonObject.addProperty(additionalProperty.getName(), additionalProperty.getValue()); } return asJsonObject; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java index 26feeeaf4..1066eacf7 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiRequestBody.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021-2022 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +21,8 @@ package org.onap.cps.ncmp.api.impl.operations; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -40,7 +40,7 @@ public class DmiRequestBody { UPDATE("update"), PATCH("patch"), DELETE("delete"); - private String value; + private final String value; OperationEnum(final String value) { this.value = value; @@ -56,25 +56,19 @@ public class DmiRequestBody { private OperationEnum operation; private String dataType; private String data; - private Map cmHandleProperties; + @JsonProperty("cmHandleProperties") + private Map dmiProperties; /** - * Set CmHandleProperties by converting a list of PersistenceCmHandle.AdditionalProperty objects. + * Set DMI Properties by converting a list of PersistenceCmHandle.Property objects. * - * @param cmHandlePropertiesAsList the cm handle additional properties + * @param dmiPropertiesAsList list of cm handle dmi properties */ - public void asCmHandleProperties( - final List cmHandlePropertiesAsList) { - final boolean isCmHandlePropertiesNullOrEmpty = - cmHandlePropertiesAsList == null || cmHandlePropertiesAsList.isEmpty(); - if (isCmHandlePropertiesNullOrEmpty) { - cmHandleProperties = Collections.emptyMap(); - } else { - cmHandleProperties = new LinkedHashMap<>(); - for (final PersistenceCmHandle.AdditionalProperty additionalProperty : cmHandlePropertiesAsList) { - cmHandleProperties.put(additionalProperty.getName(), - additionalProperty.getValue()); - } + public void asDmiProperties( + final List dmiPropertiesAsList) { + dmiProperties = new LinkedHashMap<>(); + for (final PersistenceCmHandle.Property dmiProperty : dmiPropertiesAsList) { + dmiProperties.put(dmiProperty.getName(), dmiProperty.getValue()); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetriever.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetriever.java index 78b5c318d..c489eef8e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetriever.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetriever.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021-2022 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +20,9 @@ package org.onap.cps.ncmp.api.impl.operations; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; +import lombok.AllArgsConstructor; import org.onap.cps.api.CpsDataService; import org.onap.cps.ncmp.api.models.CmHandle; import org.onap.cps.ncmp.api.models.PersistenceCmHandle; @@ -34,30 +34,24 @@ import org.springframework.stereotype.Component; * Retrieves PersistenceCmHandles & properties. */ @Component +@AllArgsConstructor public class PersistenceCmHandleRetriever { private static final String NCMP_DATASPACE_NAME = "NCMP-Admin"; private static final String NCMP_DMI_REGISTRY_ANCHOR = "ncmp-dmi-registry"; - private CpsDataService cpsDataService; + private final CpsDataService cpsDataService; /** - * Constructor for PersistenceCmHandleRetriever. - * - * @param cpsDataService the cps data service. - */ - public PersistenceCmHandleRetriever(final CpsDataService cpsDataService) { - this.cpsDataService = cpsDataService; - } - - /** - * This method retieves dmi service name and properties for a given cm handle. + * This method retrieves DMI service name and DMI properties for a given cm handle. * @param cmHandleId the id of the cm handle * @return persistence cm handle */ - public PersistenceCmHandle retrieveCmHandleDmiServiceNameAndProperties(final String cmHandleId) { + public PersistenceCmHandle retrieveCmHandleDmiServiceNameAndDmiProperties(final String cmHandleId) { final DataNode cmHandleDataNode = getCmHandleDataNode(cmHandleId); - final CmHandle cmHandle = new CmHandle(cmHandleId, getCmHandleProperties(cmHandleDataNode)); + final CmHandle cmHandle = new CmHandle(); + cmHandle.setCmHandleID(cmHandleId); + populateCmHandleDmiProperties(cmHandleDataNode, cmHandle); return PersistenceCmHandle.toPersistenceCmHandle( String.valueOf(cmHandleDataNode.getLeaves().get("dmi-service-name")), String.valueOf(cmHandleDataNode.getLeaves().get("dmi-data-service-name")), @@ -74,16 +68,19 @@ public class PersistenceCmHandleRetriever { FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); } - private static Map getCmHandleProperties(final DataNode cmHandleDataNode) { - if (cmHandleDataNode.getChildDataNodes().isEmpty()) { - return Collections.emptyMap(); - } - final Map cmHandlePropertiesAsMap = new LinkedHashMap<>(); + private static void populateCmHandleDmiProperties(final DataNode cmHandleDataNode, final CmHandle cmHandle) { + final Map dmiProperties = new LinkedHashMap<>(); for (final DataNode childDataNode: cmHandleDataNode.getChildDataNodes()) { - cmHandlePropertiesAsMap.put(String.valueOf(childDataNode.getLeaves().get("name")), - String.valueOf(childDataNode.getLeaves().get("value"))); + if (childDataNode.getXpath().contains("/additional-properties[@name=")) { + addProperty(childDataNode, dmiProperties); + } } - return cmHandlePropertiesAsMap; + cmHandle.setDmiProperties(dmiProperties); + } + + private static void addProperty(final DataNode propertyDataNode, final Map propertiesAsMap) { + propertiesAsMap.put(String.valueOf(propertyDataNode.getLeaves().get("name")), + String.valueOf(propertyDataNode.getLeaves().get("value"))); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandle.java index a38442b09..9a9b6faaf 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/CmHandle.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021-2022 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +21,10 @@ package org.onap.cps.ncmp.api.models; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; +import java.util.Collections; import java.util.Map; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -34,13 +36,18 @@ import org.springframework.validation.annotation.Validated; @Validated @Getter @Setter -@AllArgsConstructor @NoArgsConstructor public class CmHandle { @JsonProperty("cmHandle") private String cmHandleID; - private Map cmHandleProperties; + @JsonSetter(nulls = Nulls.AS_EMPTY) + @JsonProperty("cmHandleProperties") + private Map dmiProperties = Collections.emptyMap(); + + @JsonSetter(nulls = Nulls.AS_EMPTY) + @JsonProperty("publicCmHandleProperties") + private Map publicProperties = Collections.emptyMap(); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandle.java index 8b959e327..cc32bb75c 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandle.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/PersistenceCmHandle.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021-2022 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ package org.onap.cps.ncmp.api.models; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.Strings; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import lombok.AllArgsConstructor; @@ -54,7 +53,10 @@ public class PersistenceCmHandle { private String dmiModelServiceName; @JsonProperty("additional-properties") - private List additionalProperties; + private List dmiProperties; + + @JsonProperty("public-properties") + private List publicProperties; /** * Create a persistenceCmHandle. @@ -73,25 +75,11 @@ public class PersistenceCmHandle { persistenceCmHandle.setDmiServiceName(dmiServiceName); persistenceCmHandle.setDmiDataServiceName(dmiDataServiceName); persistenceCmHandle.setDmiModelServiceName(dmiModelServiceName); - if (cmHandle.getCmHandleProperties() == null) { - persistenceCmHandle.asAdditionalProperties(Collections.emptyMap()); - } else { - persistenceCmHandle.asAdditionalProperties(cmHandle.getCmHandleProperties()); - } + persistenceCmHandle.setDmiProperties(asPersistenceCmHandleProperties(cmHandle.getDmiProperties())); + persistenceCmHandle.setPublicProperties(asPersistenceCmHandleProperties(cmHandle.getPublicProperties())); return persistenceCmHandle; } - /** - * Set Additional Properties map, key and value pair. - * @param additionalPropertiesAsMap Map of Additional Properties - */ - public void asAdditionalProperties(final Map additionalPropertiesAsMap) { - additionalProperties = new ArrayList<>(additionalPropertiesAsMap.size()); - for (final Map.Entry entry : additionalPropertiesAsMap.entrySet()) { - additionalProperties.add(new AdditionalProperty(entry.getKey(), entry.getValue())); - } - } - /** * Resolve a dmi service name. * @param requiredService indicates what typo of service is required @@ -107,13 +95,21 @@ public class PersistenceCmHandle { return dmiServiceName; } + private static List asPersistenceCmHandleProperties(final Map propertiesAsMap) { + final List persistenceCmHandleProperties = new ArrayList<>(propertiesAsMap.size()); + for (final Map.Entry entry : propertiesAsMap.entrySet()) { + persistenceCmHandleProperties.add(new PersistenceCmHandle.Property(entry.getKey(), entry.getValue())); + } + return persistenceCmHandleProperties; + } + private static boolean isNullEmptyOrBlank(final String serviceName) { return Strings.isNullOrEmpty(serviceName) || serviceName.isBlank(); } @AllArgsConstructor @Data - public static class AdditionalProperty { + public static class Property { @JsonProperty() private final String name; 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 464757158..67108a5fe 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 @@ -24,6 +24,7 @@ import org.onap.cps.api.CpsAdminService import org.onap.cps.api.CpsModuleService import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations +import org.onap.cps.ncmp.api.models.CmHandle import org.onap.cps.ncmp.api.models.PersistenceCmHandle import org.onap.cps.spi.model.ModuleReference import org.onap.cps.utils.JsonObjectMapper @@ -44,30 +45,29 @@ class NetworkCmProxyDataServiceImplModelSyncSpec extends Specification { def 'Sync model for a (new) cm handle with #scenario'() { given: 'persistence cm handle is given' - def cmHandleForModelSync = new PersistenceCmHandle(id:'some cm handle', dmiServiceName: 'some service name') - and: 'additional properties are set as required' - if (additionalProperties!=null) { - cmHandleForModelSync.asAdditionalProperties(additionalProperties) - } - and: 'dmi operations returns some module references' + def cmHandle = new CmHandle() + def dmiServiceName = 'some service name' + cmHandle.cmHandleID = 'cm handle id 1' + cmHandle.dmiProperties = dmiProperties + def persistenceCmHandle = PersistenceCmHandle.toPersistenceCmHandle(dmiServiceName, '' , '', cmHandle) + and: 'DMI operations returns some module references' def moduleReferences = [ new ModuleReference(moduleName:'module1',revision:'1'), new ModuleReference(moduleName:'module2',revision:'2') ] - mockDmiModelOperations.getModuleReferences(cmHandleForModelSync) >> moduleReferences + mockDmiModelOperations.getModuleReferences(persistenceCmHandle) >> moduleReferences and: 'CPS-Core returns list of existing module resources' mockCpsModuleService.getYangResourceModuleReferences(expectedDataspaceName) >> existingModuleResourcesInCps and: 'DMI-Plugin returns resource(s) for "new" module(s)' - mockDmiModelOperations.getNewYangResourcesFromDmi(cmHandleForModelSync, [new ModuleReference('module1', '1')]) >> yangResourceToContentMap + mockDmiModelOperations.getNewYangResourcesFromDmi(persistenceCmHandle, [new ModuleReference('module1', '1')]) >> yangResourceToContentMap when: 'module sync is triggered' - objectUnderTest.syncModulesAndCreateAnchor(cmHandleForModelSync) + objectUnderTest.syncModulesAndCreateAnchor(persistenceCmHandle) then: 'the CPS module service is called once with the correct parameters' - 1 * mockCpsModuleService.createSchemaSetFromModules(expectedDataspaceName, cmHandleForModelSync.getId(), yangResourceToContentMap, expectedKnownModules) + 1 * mockCpsModuleService.createSchemaSetFromModules(expectedDataspaceName, persistenceCmHandle.getId(), yangResourceToContentMap, expectedKnownModules) and: 'admin service create anchor method has been called with correct parameters' - 1 * mockCpsAdminService.createAnchor(expectedDataspaceName, cmHandleForModelSync.getId(), cmHandleForModelSync.getId()) + 1 * mockCpsAdminService.createAnchor(expectedDataspaceName, persistenceCmHandle.getId(), persistenceCmHandle.getId()) where: 'the following parameters are used' - 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')] | '{}' + scenario | dmiProperties | existingModuleResourcesInCps | yangResourceToContentMap || expectedKnownModules + 'one unknown module' | ['name1': 'value1'] | [new ModuleReference('module2', '2'), new ModuleReference('module3', '3')] | [module1: 'some yang source'] || [new ModuleReference('module2', '2')] + 'no add. properties' | [:] | [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/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy index b954b41ef..3ec6f3a00 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy @@ -60,11 +60,15 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { def objectUnderTest = getObjectUnderTestWithModelSyncDisabled() def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'my-server') persistenceCmHandle.cmHandleID = '123' - persistenceCmHandle.cmHandleProperties = [name1: 'value1', name2: 'value2'] + persistenceCmHandle.dmiProperties = [dmiProp1: 'dmiValue1', dmiProp2: 'dmiValue2'] + persistenceCmHandle.publicProperties = [publicProp1: 'publicValue1', publicProp2: 'publicValue2' ] dmiPluginRegistration.createdCmHandles = createdCmHandles dmiPluginRegistration.updatedCmHandles = updatedCmHandles dmiPluginRegistration.removedCmHandles = removedCmHandles - def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","dmi-data-service-name":null,"dmi-model-service-name":null,"additional-properties":[{"name":"name1","value":"value1"},{"name":"name2","value":"value2"}]}]}' + def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","dmi-data-service-name":null,"dmi-model-service-name":null,' + + '"additional-properties":[{"name":"dmiProp1","value":"dmiValue1"},{"name":"dmiProp2","value":"dmiValue2"}],' + + '"public-properties":[{"name":"publicProp1","value":"publicValue1"},{"name":"publicProp2","value":"publicValue2"}]' + + '}]}' when: 'registration is updated and modules are synced' objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'save list elements is invoked with the expected parameters' @@ -87,14 +91,15 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { 'no valid data' | null | null | null || 0 | 0 | 0 } - def 'Register a DMI Plugin for the given cm-handle(s) without additional properties.'() { + def 'Register a DMI Plugin for the given cm-handle(s) without DMI properties.'() { given: 'a registration without cm-handle properties' NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled() def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'my-server') persistenceCmHandle.cmHandleID = '123' - persistenceCmHandle.cmHandleProperties = null + persistenceCmHandle.dmiProperties = Collections.emptyMap() + persistenceCmHandle.publicProperties = Collections.emptyMap() dmiPluginRegistration.createdCmHandles = [persistenceCmHandle] - def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","dmi-data-service-name":null,"dmi-model-service-name":null,"additional-properties":[]}]}' + def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","dmi-data-service-name":null,"dmi-model-service-name":null,"additional-properties":[],"public-properties":[]}]}' when: 'registration is updated' objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'save list elements is invoked with the expected parameters' @@ -163,7 +168,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification { 'data & model using same service' | '' | 'service1' | 'service1' } - def 'Invalid dmi plugin registration with #scenario'() { + def 'Invalid DMI plugin registration with #scenario'() { given: 'a registration ' def objectUnderTest = getObjectUnderTestWithModelSyncDisabled() def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:dmiPlugin, dmiModelPlugin:dmiModelPlugin, 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 51af0f55e..7f127003d 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 @@ -57,34 +57,28 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']" + def dataNode = new DataNode(leaves: ['dmi-service-name': 'testDmiService']) - def 'Write resource data for pass-through running from dmi using POST #scenario cm handle properties.'() { - given: 'a data node' - def dataNode = getDataNode(includeCmHandleProperties) - and: 'cpsDataService returns valid datanode' + + def 'Write resource data for pass-through running from DMI using POST #scenario cm handle properties.'() { + given: 'cpsDataService returns valid datanode' mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode when: 'get resource data is called' objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle', 'testResourceId', CREATE, '{some-json}', 'application/json') - then: 'dmi called with correct data' + then: 'DMI called with correct data' 1 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId', CREATE, '{some-json}', 'application/json') >> { new ResponseEntity<>(HttpStatus.CREATED) } - where: - scenario | includeCmHandleProperties || expectedJsonForCmhandleProperties - 'with' | true || '{"testName":"testValue"}' - 'without' | false || '{}' } - def 'Write resource data for pass-through running from dmi using POST "not found" response (from DMI).'() { - given: 'a data node' - def dataNode = getDataNode(true) - and: 'cpsDataService returns valid dataNode' + def 'Write resource data for pass-through running from DMI using POST "not found" response (from DMI).'() { + given: 'cpsDataService returns valid dataNode' mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode - and: 'dmi returns a response with 404 status code' + and: 'DMI returns a response with 404 status code' mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId', CREATE, '{some-json}', 'application/json') @@ -100,13 +94,11 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { } - def 'Get resource data for pass-through operational from dmi.'() { - given: 'a data node' - def dataNode = getDataNode(true) - and: 'get data node is called' + def 'Get resource data for pass-through operational from DMI.'() { + given: 'get data node is called' mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode - and: 'get resource data from dmi is called' + and: 'get resource data from DMI is called' mockDmiDataOperations.getResourceDataFromDmi( 'testCmHandle', 'testResourceId', @@ -118,19 +110,17 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 'testResourceId', 'testAcceptParam', '(a=1,b=2)') - then: 'dmi returns a json response' + then: 'DMI returns a json response' response == 'result-json' } - def 'Get resource data for pass-through operational from dmi with Json Processing Exception.'() { - given: 'a data node' - def dataNode = getDataNode(true) - and: 'cps data service returns valid data node' + def 'Get resource data for pass-through operational from DMI with Json Processing Exception.'() { + given: 'cps data service returns valid data node' mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode and: 'objectMapper not able to parse object' spiedJsonObjectMapper.asJsonString(_) >> { throw new JsonProcessingException('testException') } - and: 'dmi returns NOK response' + and: 'DMI returns NOK response' mockDmiDataOperations.getResourceDataFromDmi(*_) >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND) when: 'get resource data is called' @@ -143,13 +133,11 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { exceptionThrown.details == 'DMI status code: 404, DMI response body: NOK-json' } - def 'Get resource data for pass-through operational from dmi return NOK response.'() { - given: 'a data node' - def dataNode = getDataNode(true) - and: 'cps data service returns valid data node' + def 'Get resource data for pass-through operational from DMI return NOK response.'() { + given: 'cps data service returns valid data node' mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode - and: 'dmi returns NOK response' + and: 'DMI returns NOK response' mockDmiDataOperations.getResourceDataFromDmi('testCmHandle', 'testResourceId', '(a=1,b=2)', @@ -167,13 +155,11 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { exceptionThrown.details.contains('NOK-json') } - def 'Get resource data for pass-through running from dmi.'() { - given: 'a data node' - def dataNode = getDataNode(true) - and: 'cpsDataService returns valid data node' + def 'Get resource data for pass-through running from DMI.'() { + given: 'cpsDataService returns valid data node' mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode - and: 'dmi returns valid response and data' + and: 'DMI returns valid response and data' mockDmiDataOperations.getResourceDataFromDmi('testCmHandle', 'testResourceId', '(a=1,b=2)', @@ -188,13 +174,11 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { response == '{result-json}' } - def 'Get resource data for pass-through running from dmi return NOK response.'() { - given: 'a data node' - def dataNode = getDataNode(true) - and: 'cpsDataService returns valid dataNode' + def 'Get resource data for pass-through running from DMI return NOK response.'() { + given: 'cpsDataService returns valid dataNode' mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode - and: 'dmi returns NOK response' + and: 'DMI returns NOK response' mockDmiDataOperations.getResourceDataFromDmi('testCmHandle', 'testResourceId', '(a=1,b=2)', @@ -226,25 +210,18 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 1 * mockCpsAdminService.queryAnchorNames('NFP-Operational', ['some-module-name']) } - - def 'Update resource data for pass-through running from dmi using POST #scenario cm handle properties.'() { - given: 'a data node' - def dataNode = getDataNode(includeCmHandleProperties) - and: 'cpsDataService returns valid datanode' + def 'Update resource data for pass-through running from dmi using POST #scenario DMI properties.'() { + given: 'cpsDataService returns valid datanode' mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode when: 'get resource data is called' objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle', 'testResourceId', UPDATE, '{some-json}', 'application/json') - then: 'dmi called with correct data' + then: 'DMI called with correct data' 1 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId', UPDATE, '{some-json}', 'application/json') >> { new ResponseEntity<>(HttpStatus.OK) } - where: - scenario | includeCmHandleProperties || expectedJsonForCmhandleProperties - 'with' | true || '{"testName":"testValue"}' - 'without' | false || '{}' } def 'Verify error message from handleResponse is correct for #scenario operation.'() { @@ -252,7 +229,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi(*_) >> new ResponseEntity<>(HttpStatus.NOT_FOUND) when: 'get resource data is called' - def response = objectUnderTest.writeResourceDataPassThroughRunningForCmHandle( + objectUnderTest.writeResourceDataPassThroughRunningForCmHandle( 'testCmHandle', 'testResourceId', givenOperation, @@ -267,15 +244,4 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 'READ' | READ || 'Not able to read resource data.' 'UPDATE' | UPDATE || 'Not able to update resource data.' } - - def getDataNode(boolean includeCmHandleProperties) { - def dataNode = new DataNode() - dataNode.leaves = ['dmi-service-name': 'testDmiService'] - if (includeCmHandleProperties) { - def cmHandlePropertyDataNode = new DataNode() - cmHandlePropertyDataNode.leaves = ['name': 'testName', 'value': 'testValue'] - dataNode.childDataNodes = [cmHandlePropertyDataNode] - } - return dataNode - } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy index 54ae0aa6f..7873f39bb 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy @@ -47,30 +47,29 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec { def 'call get resource data for #expectedDatastoreInUrl from DMI #scenario.'() { given: 'a persistence cm handle for #cmHandleId' - mockPersistenceCmHandleRetrieval(additionalProperties) - and: 'a positive response from dmi service when it is called with the expected parameters' + mockPersistenceCmHandleRetrieval(dmiProperties) + and: 'a positive response from DMI service when it is called with the expected parameters' def responseFromDmi = new ResponseEntity(HttpStatus.OK) mockDmiRestClient.postOperationWithJsonData( "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/data/ds/ncmp-datastore:${expectedDatastoreInUrl}?resourceIdentifier=${resourceIdentifier}${expectedOptionsInUrl}", expectedJson, [Accept:['sample accept header']]) >> responseFromDmi when: 'get resource data is invoked' def result = objectUnderTest.getResourceDataFromDmi(cmHandleId,resourceIdentifier, options,'sample accept header', dataStore) - then: 'the result is the response from the dmi service' + then: 'the result is the response from the DMI service' assert result == responseFromDmi where: 'the following parameters are used' - scenario | additionalProperties | dataStore | options || expectedJson | expectedDatastoreInUrl | expectedOptionsInUrl - 'without properties' | [] | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-operational' | '&options=(a=1,b=2)' - 'null properties' | null | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-operational' | '&options=(a=1,b=2)' - 'with properties' | [sampleAdditionalProperty] | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '&options=(a=1,b=2)' - 'null options' | [sampleAdditionalProperty] | PASSTHROUGH_OPERATIONAL | null || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '' - 'empty options' | [sampleAdditionalProperty] | PASSTHROUGH_OPERATIONAL | '' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '' - 'datastore running' | [] | PASSTHROUGH_RUNNING | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-running' | '&options=(a=1,b=2)' + scenario | dmiProperties | dataStore | options || expectedJson | expectedDatastoreInUrl | expectedOptionsInUrl + 'without properties' | [] | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-operational' | '&options=(a=1,b=2)' + 'with properties' | [dmiSampleProperty] | PASSTHROUGH_OPERATIONAL | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '&options=(a=1,b=2)' + 'null options' | [dmiSampleProperty] | PASSTHROUGH_OPERATIONAL | null || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '' + 'empty options' | [dmiSampleProperty] | PASSTHROUGH_OPERATIONAL | '' || '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}' | 'passthrough-operational' | '' + 'datastore running' | [] | PASSTHROUGH_RUNNING | '(a=1,b=2)' || '{"operation":"read","cmHandleProperties":{}}' | 'passthrough-running' | '&options=(a=1,b=2)' } def 'Write data for pass-through:running datastore in DMI.'() { given: 'a persistence cm handle for #cmHandleId' - mockPersistenceCmHandleRetrieval([sampleAdditionalProperty]) - and: 'a positive response from dmi service when it is called with the expected parameters' + mockPersistenceCmHandleRetrieval([dmiSampleProperty]) + and: 'a positive response from DMI service when it is called with the expected parameters' def expectedUrl = "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/data/ds" + "/ncmp-datastore:passthrough-running?resourceIdentifier=${resourceIdentifier}" def expectedJson = '{"operation":"' + expectedOperationInUrl + '","dataType":"some data type","data":"requestData","cmHandleProperties":{"prop1":"val1"}}' @@ -78,7 +77,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec { mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, [:]) >> responseFromDmi when: 'write resource method is invoked' def result = objectUnderTest.writeResourceDataPassThroughRunningFromDmi(cmHandleId,'parent/child', operation, 'requestData', 'some data type') - then: 'the result is the response from the dmi service' + then: 'the result is the response from the DMI service' assert result == responseFromDmi where: 'the following operation is performed' operation || expectedOperationInUrl 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 2efd6c2b3..bd5fe6f87 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 @@ -49,7 +49,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { 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' + 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", @@ -63,7 +63,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { 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' + 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 @@ -71,7 +71,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { def result = objectUnderTest.getModuleReferences(persistenceCmHandle) then: 'the result is empty' assert result == [] - where: 'the dmi response body has the following content' + where: 'the DMI response body has the following content' scenario | bodyAsMap 'no modules' | [schemas:[]] 'modules null' | [schemas:null] @@ -79,34 +79,33 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { 'no body' | null } - def 'Retrieving module references, additional property handling: #scenario.'() { + def 'Retrieving module references, DMI 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' + mockPersistenceCmHandleRetrieval(dmiProperties) + and: 'a positive response from DMI service when it is called with tha expected parameters' def responseFromDmi = new ResponseEntity(HttpStatus.OK) mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules", '{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', [:]) >> responseFromDmi when: 'a get module references is called' def result = objectUnderTest.getModuleReferences(persistenceCmHandle) - then: 'the result is the response from dmi service' + then: 'the result is the response from DMI service' assert result == [] - where: 'the following additional properties are used' - scenario | additionalPropertiesObject || expectedAdditionalPropertiesInRequest - 'with properties' | [sampleAdditionalProperty] || '{"prop1":"val1"}' - 'with null properties' | null || '{}' - 'without properties' | [] || '{}' + where: 'the following DMI properties are used' + scenario | dmiProperties || expectedAdditionalPropertiesInRequest + 'with properties' | [dmiSampleProperty] || '{"prop1":"val1"}' + 'without properties' | [] || '{}' } 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' + 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'], [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' + 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 @@ -117,43 +116,43 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { 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' + 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' + 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' + where: 'the DMI response body has the following content' scenario | responseFromDmiBody 'empty array' | [] 'null array' | null } - def 'Retrieving yang resources, additional property handling #scenario.'() { + def 'Retrieving yang resources, DMI 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' + mockPersistenceCmHandleRetrieval(dmiProperties) + 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' + when: 'get new yang resources from DMI service' def result = objectUnderTest.getNewYangResourcesFromDmi(persistenceCmHandle, unknownModuleReferences) - then: 'the result is the response from dmi service' + then: 'the result is the response from DMI service' 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"}' + where: 'the following DMI properties are used' + scenario | dmiProperties | unknownModuleReferences || expectedAdditionalPropertiesInRequest | expectedModuleReferencesInRequest + 'with module references and properties' | [dmiSampleProperty] | newModuleReferences || '{"prop1":"val1"}' | '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}' + 'without module references' | [dmiSampleProperty] | [] || '{"prop1":"val1"}' | '' + 'without properties' | [] | newModuleReferences || '{}' | '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}' } - def 'Retrieving yang resources from dmi with additional properties null.'() { + def 'Retrieving yang resources from DMI with null DMI properties.'() { given: 'a persistence cm handle' mockPersistenceCmHandleRetrieval(null) - when: 'a get new yang resources from dmi is called' + when: 'a get new yang resources from DMI is called' objectUnderTest.getNewYangResourcesFromDmi(persistenceCmHandle, []) then: 'a null pointer is thrown (we might need to address this later)' thrown(NullPointerException) @@ -164,7 +163,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec { mockPersistenceCmHandleRetrieval([]) and: 'a Json processing exception occurs' spiedJsonObjectMapper.asJsonString(_) >> {throw (new JsonProcessingException('parsing error'))} - when: 'a dmi operation is executed' + when: 'a DMI operation is executed' objectUnderTest.getModuleReferences(persistenceCmHandle) then: 'an ncmp exception is thrown' def exceptionThrown = thrown(JsonProcessingException) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy index 4bf7dad8b..7b295f68b 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy @@ -1,3 +1,23 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021-2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.api.impl.operations import com.fasterxml.jackson.databind.ObjectMapper @@ -10,7 +30,7 @@ import spock.lang.Specification abstract class DmiOperationsBaseSpec extends Specification { @Shared - def sampleAdditionalProperty = new PersistenceCmHandle.AdditionalProperty('prop1', 'val1') + def dmiSampleProperty = new PersistenceCmHandle.Property('prop1', 'val1') @SpringBean DmiRestClient mockDmiRestClient = Mock() @@ -26,11 +46,11 @@ abstract class DmiOperationsBaseSpec extends Specification { def static cmHandleId = 'some cm handle' def static resourceIdentifier = 'parent/child' - def mockPersistenceCmHandleRetrieval(additionalProperties) { + def mockPersistenceCmHandleRetrieval(dmiProperties) { persistenceCmHandle.dmiDataServiceName = dmiServiceName persistenceCmHandle.dmiServiceName = dmiServiceName - persistenceCmHandle.additionalProperties = additionalProperties + persistenceCmHandle.dmiProperties = dmiProperties persistenceCmHandle.id = cmHandleId - mockCmHandlePropertiesRetriever.retrieveCmHandleDmiServiceNameAndProperties(cmHandleId) >> persistenceCmHandle + mockCmHandlePropertiesRetriever.retrieveCmHandleDmiServiceNameAndDmiProperties(cmHandleId) >> persistenceCmHandle } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetrieverSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetrieverSpec.groovy index 3ab9266ba..c92234f9a 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetrieverSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/PersistenceCmHandleRetrieverSpec.groovy @@ -1,3 +1,23 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021-2022 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.api.impl.operations import org.onap.cps.api.CpsDataService @@ -19,26 +39,25 @@ class PersistenceCmHandleRetrieverSpec extends Specification { def xpath = "/dmi-registry/cm-handles[@id='some cm handle']" @Shared - def childDataNodesForCmHandleProperties = [new DataNode(leaves: ["name":"name1","value":"value1"]), - new DataNode(leaves: ["name":"name2","value":"value2"])] + def childDataNodesForCmHandleProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/additional-properties[@name='name1']", leaves: ["name":"name1","value":"value1"]), + new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])] def "Retrieve CmHandle using datanode #scenario."() { - given: 'the cps data service returns a data node from the dmi registry' + given: 'the cps data service returns a data node from the DMI registry' def dataNode = new DataNode(childDataNodes:childDataNodes, leaves: leaves) mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', xpath, INCLUDE_ALL_DESCENDANTS) >> dataNode when: 'retrieving the persisted cm handle' - def result = objectUnderTest.retrieveCmHandleDmiServiceNameAndProperties(cmHandleId) + def result = objectUnderTest.retrieveCmHandleDmiServiceNameAndDmiProperties(cmHandleId) then: 'the result has the correct id and service names' result.id == cmHandleId result.dmiServiceName == 'common service name' result.dmiDataServiceName == 'data service name' result.dmiModelServiceName == 'model service name' - and: 'the expected additional properties' - result.additionalProperties == expectedCmHandleProperties + and: 'the expected DMI properties' + result.dmiProperties == expectedCmHandleProperties where: 'the following parameters are used' - scenario | childDataNodes || expectedCmHandleProperties - 'without additional properties' | [] || [] - 'with additional properties' | childDataNodesForCmHandleProperties || [new PersistenceCmHandle.AdditionalProperty("name1", "value1"), - new PersistenceCmHandle.AdditionalProperty("name2", "value2")] + scenario | childDataNodes || expectedCmHandleProperties + 'without DMI properties' | [] || [] + 'with DMI properties' | childDataNodesForCmHandleProperties || [new PersistenceCmHandle.Property("name1", "value1")] } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/PersistenceCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/PersistenceCmHandleSpec.groovy index c66eaa9b4..49de4422e 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/PersistenceCmHandleSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/PersistenceCmHandleSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021-2022 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 * ============LICENSE_END========================================================= */ + package org.onap.cps.ncmp.api.models import spock.lang.Specification @@ -26,24 +27,26 @@ import static org.onap.cps.ncmp.api.impl.operations.RequiredDmiService.MODEL class PersistenceCmHandleSpec extends Specification { - def 'Setting and getting additional properties.'() { - given: 'a map of one property is added' - def objectUnderTest = new PersistenceCmHandle() - objectUnderTest.asAdditionalProperties([myProperty: 'some value']) - when: 'the additional properties are retrieved' - def result = objectUnderTest.getAdditionalProperties() + def 'Creating persistence cm handle from a cm handle.'() { + given: 'a cm handle with properties' + def cmHandle = new CmHandle() + cmHandle.dmiProperties = [myDmiProperty:'value1'] + cmHandle.publicProperties = [myPublicProperty:'value2'] + when: 'it is converted to a persistence cm handle' + def objectUnderTest = PersistenceCmHandle.toPersistenceCmHandle('','','', cmHandle) then: 'the result has the right size' - assert result.size() == 1 - and: 'the property in the result has the correct name and value' - def actualAdditionalProperty = result.get(0) - def expectedAdditionalProperty = new PersistenceCmHandle.AdditionalProperty('myProperty','some value') - assert actualAdditionalProperty.name == expectedAdditionalProperty.name - assert actualAdditionalProperty.value == expectedAdditionalProperty.value + assert objectUnderTest.dmiProperties.size() == 1 + and: 'the DMI property in the result has the correct name and value' + assert objectUnderTest.dmiProperties[0].name == 'myDmiProperty' + assert objectUnderTest.dmiProperties[0].value == 'value1' + and: 'the public property in the result has the correct name and value' + assert objectUnderTest.publicProperties[0].name == 'myPublicProperty' + assert objectUnderTest.publicProperties[0].value == 'value2' } - def 'Resolve dmi service name: #scenario and #requiredService service require.'() { + def 'Resolve DMI service name: #scenario and #requiredService service require.'() { given: 'a Persistence CM Handle' - def objectUnderTest = PersistenceCmHandle.toPersistenceCmHandle(dmiServiceName, dmiDataServiceName, dmiModelServiceName, new CmHandle('some id', null)) + def objectUnderTest = PersistenceCmHandle.toPersistenceCmHandle(dmiServiceName, dmiDataServiceName, dmiModelServiceName, new CmHandle()) expect: assert objectUnderTest.resolveDmiServiceName(requiredService) == expectedService where: diff --git a/cps-parent/pom.xml b/cps-parent/pom.xml index a51d6943a..2e0528e97 100755 --- a/cps-parent/pom.xml +++ b/cps-parent/pom.xml @@ -46,6 +46,31 @@ + + + Windows + + + Windows + + + + python + + + + unix + + + unix + + + + python3 + + + + @@ -377,6 +402,28 @@ org.sonarsource.scanner.maven sonar-maven-plugin + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + generate-csv + prepare-package + + exec + + + + + ${script.executor} + ../cps-ri/src/main/resources/ + + yangResourceCsvGenerator.py + dmi-registry@2021-12-13 + + + diff --git a/cps-ri/src/main/resources/changelog/db/changes/09-loadData-dmi-registry-schema-set.yaml b/cps-ri/src/main/resources/changelog/db/changes/09-loadData-dmi-registry-schema-set.yaml index fe2428e0c..723c2b9ec 100644 --- a/cps-ri/src/main/resources/changelog/db/changes/09-loadData-dmi-registry-schema-set.yaml +++ b/cps-ri/src/main/resources/changelog/db/changes/09-loadData-dmi-registry-schema-set.yaml @@ -1,5 +1,5 @@ # ============LICENSE_START======================================================= -# Copyright (C) 2021 Nordix Foundation. +# Copyright (C) 2021-2022 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -160,3 +160,51 @@ databaseChangeLog: delete from schema_set_yang_resources where schema_set_id = (select id from schema_set where name = 'ncmp-dmi-registry-model') and yang_resource_id = (select id from yang_resource where name = 'dmi-registry@2021-10-20.yang') + + - changeSet: + author: cps + label: dmi-registry-schema-preload + id: 9.7 + loadUpdateData: + encoding: UTF-8 + file: 'changelog/db/changes/data/dmi//generated-csv/generated_yang_resource_dmi-registry@2021-12-13.csv' + onlyUpdate: 'false' + primaryKey: 'id' + quotchar: '"' + separator: '|' + tableName: 'yang_resource' + columns: + - column: + header: name + name: name + type: STRING + - column: + header: content + name: content + type: STRING + - column: + header: checksum + name: checksum + type: STRING + rollback: + - sql: + sql: delete from yang_resource where name = 'dmi-registry@2021-12-13.yang' + + - changeSet: + author: cps + label: dmi-registry-schema-preload + id: 9.8 + loadUpdateData: + encoding: UTF-8 + file: 'changelog/db/changes/data/dmi/schema_set_yang_resources@2021-12-13.csv' + quotchar: '"' + primaryKey: 'schema_set_id,yang_resource_id' + separator: '|' + tableName: 'schema_set_yang_resources' + usePreparedStatements: true + rollback: + - sql: + sql: > + delete from schema_set_yang_resources + where schema_set_id = (select id from schema_set where name = 'ncmp-dmi-registry-model') + and yang_resource_id = (select id from yang_resource where name = 'dmi-registry@2021-12-13.yang') \ No newline at end of file diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md b/cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md new file mode 100644 index 000000000..212acb900 --- /dev/null +++ b/cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md @@ -0,0 +1,23 @@ + + +##Placeholder folder for generated CSV files as part of yang models. + +Do not remove this folder \ No newline at end of file diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/dmi/schema_set_yang_resources@2021-12-13.csv b/cps-ri/src/main/resources/changelog/db/changes/data/dmi/schema_set_yang_resources@2021-12-13.csv new file mode 100644 index 000000000..3e8afdd4e --- /dev/null +++ b/cps-ri/src/main/resources/changelog/db/changes/data/dmi/schema_set_yang_resources@2021-12-13.csv @@ -0,0 +1,3 @@ +schema_set_id|yang_resource_id +(select id from schema_set where name='ncmp-dmi-registry-model')|(select id from yang_resource where name='dmi-registry@2021-12-13.yang') + diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang b/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang new file mode 100644 index 000000000..ed3559bf6 --- /dev/null +++ b/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang @@ -0,0 +1,63 @@ +module dmi-registry { + + yang-version 1.1; + + namespace "org:onap:cps:ncmp"; + + prefix dmi-reg; + + contact "dylan.byrne@est.tech"; + + revision "2021-05-20" { + description + "Initial Version"; + } + + revision "2021-10-20" { + description + "Added dmi-data-service-name & dmi-model-service-name to allow separate DMI instances for each responsibility"; + } + + revision "2021-12-13" { + description + "Added new list of public additonal properties for a Cm-Handle which are exposed to clients of the NCMP interface"; + } + + container dmi-registry { + list cm-handles { + key "id"; + leaf id { + type string; + } + leaf dmi-service-name { + type string; + } + leaf dmi-data-service-name { + type string; + } + leaf dmi-model-service-name { + type string; + } + + list additional-properties { + key "name"; + leaf name { + type string; + } + leaf value { + type string; + } + } + + list public-properties { + key "name"; + leaf name { + type string; + } + leaf value { + type string; + } + } + } + } +} \ No newline at end of file diff --git a/cps-ri/src/main/resources/yangResourceCsvGenerator.py b/cps-ri/src/main/resources/yangResourceCsvGenerator.py new file mode 100644 index 000000000..9a4077bbd --- /dev/null +++ b/cps-ri/src/main/resources/yangResourceCsvGenerator.py @@ -0,0 +1,38 @@ +# ============LICENSE_START======================================================= +# Copyright (C) 2022 Nordix Foundation +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# 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========================================================= + + +import csv +import hashlib +import sys + +yang_source = '' +checksum = '' + +for yang_source in sys.argv[1:]: + checksum = hashlib.sha256(str(yang_source).encode()).hexdigest() + +with open('changelog/db/changes/data/yang-models/' + yang_source + '.yang') as content: + dmiRegistry = content.read() + +# open the file in the write mode +with open('changelog/db/changes/data/dmi/generated-csv/generated_yang_resource_' + yang_source + '.csv', 'w', newline='') \ + as file: + writer = csv.writer(file, delimiter='|') + writer.writerow(["name", "content", "checksum"]) + writer.writerow([yang_source + '.yang', dmiRegistry, checksum]) diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy index 6c899c793..a302eb5e7 100644 --- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2021-2022 Nordix Foundation * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2021-2022 Bell Canada. * ================================================================================ @@ -154,19 +154,19 @@ class CpsDataServiceImplSpec extends Specification { 'one leaf' | '{"name": "some-name"}' } - def 'Update cm-handle properties' () { - given: 'a dmi registry model' - setupSchemaSetMocks('dmi-registry.yang') + def 'Update Bookstore node leaves' () { + given: 'a DMI registry model' + setupSchemaSetMocks('bookstore.yang') and: 'the expected json string' - def jsonData = '{"cm-handles":[{"id":"cmHandle001", "additional-properties":[{"name":"P1"}]}]}' + def jsonData = '{"categories":[{"code":01,"name":"Romance"}]}' when: 'update data method is invoked with json data and parent node xpath' objectUnderTest.updateNodeLeavesAndExistingDescendantLeaves(dataspaceName, anchorName, - '/dmi-registry', jsonData, observedTimestamp) + '/bookstore', jsonData, observedTimestamp) then: 'the persistence service method is invoked with correct parameters' 1 * mockCpsDataPersistenceService.updateDataLeaves(dataspaceName, anchorName, - "/dmi-registry/cm-handles[@id='cmHandle001']", ['id': 'cmHandle001']) + "/bookstore/categories[@code='01']", ['name':'Romance', 'code': '01']) and: 'the data updated event is sent to the notification service' - 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/dmi-registry', Operation.UPDATE) + 1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, observedTimestamp, '/bookstore', Operation.UPDATE) } def 'Replace data node: #scenario.'() { diff --git a/cps-service/src/test/resources/dmi-registry.yang b/cps-service/src/test/resources/dmi-registry.yang deleted file mode 100644 index 3c2d893b2..000000000 --- a/cps-service/src/test/resources/dmi-registry.yang +++ /dev/null @@ -1,42 +0,0 @@ -module dmi-registry { - - yang-version 1.1; - - namespace "org:onap:cps:ncmp"; - - prefix dmi-reg; - - revision "2021-05-20" { - description - "Initial Version"; - } - - container dmi-registry { - - list cm-handles { - - key "id"; - - leaf id { - type string; - } - - leaf dmi-service-name { - type string; - } - - list additional-properties { - - key "name"; - - leaf name { - type string; - } - - leaf value { - type string; - } - } - } - } -} \ No newline at end of file diff --git a/docs/api/swagger/ncmp/openapi-inventory.yaml b/docs/api/swagger/ncmp/openapi-inventory.yaml index c4b6f4b73..67eae41c4 100644 --- a/docs/api/swagger/ncmp/openapi-inventory.yaml +++ b/docs/api/swagger/ncmp/openapi-inventory.yaml @@ -4,12 +4,12 @@ info: description: NCMP Inventory API version: "1.0" servers: - - url: /ncmpInventory +- url: /ncmpInventory paths: /v1/ch: post: tags: - - network-cm-proxy-inventory + - network-cm-proxy-inventory summary: DMI notifies NCMP of new CM Handles description: "Register a DMI Plugin with any new, updated or removed CM Handles." operationId: updateDmiPluginRegistration @@ -29,18 +29,30 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 400 BAD_REQUEST + message: Bad request error message + details: Bad request error details "401": description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 401 + message: Unauthorized error message + details: Unauthorized error details "403": description: Forbidden content: application/json: schema: $ref: '#/components/schemas/ErrorMessage' + example: + status: 403 + message: Forbidden error message + details: Forbidden error details components: schemas: RestDmiPluginRegistration: @@ -48,7 +60,13 @@ components: properties: dmiPlugin: type: string - example: onap-dmi-plugin + example: my-dmi-plugin + dmiDataPlugin: + type: string + example: my-dmi-data-plugin + dmiModelPlugin: + type: string + example: my-dmi-model-plugin createdCmHandles: type: array items: @@ -61,21 +79,24 @@ components: type: array items: type: string + example: "[\"my-cm-handle1\",\"my-cm-handle2\",\"my-cm-handle3\"]" RestCmHandle: required: - - cmHandle + - cmHandle type: object properties: cmHandle: type: string - example: cmHandle123 + example: my-cm-handle cmHandleProperties: - $ref: '#/components/schemas/RestCmHandleAdditionalProperties' - RestCmHandleAdditionalProperties: + $ref: '#/components/schemas/RestCmHandleProperties' + publicCmHandleProperties: + $ref: '#/components/schemas/RestCmHandleProperties' + RestCmHandleProperties: type: object additionalProperties: type: string - example: system-001 + example: my-property ErrorMessage: title: Error type: object -- 2.16.6