From 97b5fa431d5924d90e97adedf76f3ce5648cd938 Mon Sep 17 00:00:00 2001 From: MichaelMorris Date: Fri, 19 Aug 2022 09:36:41 +0100 Subject: [PATCH] Support updated data types in service import Signed-off-by: MichaelMorris Issue-ID: SDC-4140 Change-Id: Ib66d47a0f566b648722ce86cfc4e208880551a29 --- .../be/components/impl/CommonImportManager.java | 8 ++++ .../be/components/impl/DataTypeImportManager.java | 5 +- .../impl/ServiceImportBusinessLogic.java | 12 +++++ .../impl/ServiceImportBusinessLogicTest.java | 19 +++++++- .../resources/csars/service-Ser09080002-csar.csar | Bin 65020 -> 64137 bytes .../openecomp/sdc/be/model/DataTypeDefinition.java | 1 + .../be/model/cache/ApplicationDataTypeCache.java | 15 ++++++ .../be/model/operations/impl/ModelOperation.java | 51 +++++++++++++++++++++ .../model/operations/impl/PropertyOperation.java | 44 ++---------------- .../model/operations/impl/ModelOperationTest.java | 24 +++++++++- .../expected-additional_types-1.yaml | 3 ++ .../expected-additional_types-2-updated.yaml | 24 ++++++++++ .../expected-additional_types-2.yaml | 3 ++ .../modelOperation/input-data_types-updated.yaml | 12 +++++ .../resources/modelOperation/input-data_types.yaml | 3 ++ 15 files changed, 179 insertions(+), 45 deletions(-) create mode 100644 catalog-model/src/test/resources/modelOperation/expected-additional_types-2-updated.yaml create mode 100644 catalog-model/src/test/resources/modelOperation/input-data_types-updated.yaml diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java index f1582eecb1..6bbeed0dd0 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CommonImportManager.java @@ -538,9 +538,17 @@ public class CommonImportManager { public void addTypesToDefaultImports(final ElementTypeEnum elementTypeEnum, final String typesYaml, final String modelName) { modelOperation.addTypesToDefaultImports(elementTypeEnum, typesYaml, modelName); } + + public void updateTypesInAdditionalTypesImport(final ElementTypeEnum elementTypeEnum, final String dataTypeYml, final String modelName) { + modelOperation.updateTypesInAdditionalTypesImport(elementTypeEnum, dataTypeYml, modelName); + } public interface ICreateElementType { T3 createElement(T1 firstArg, T2 secondArg); } + + + + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeImportManager.java index 943edb1b95..d488c65b22 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeImportManager.java @@ -65,12 +65,15 @@ public class DataTypeImportManager { public Either>, ResponseFormat> createDataTypes(final String dataTypeYml, final String modelName, final boolean includeToModelDefaultImports) { - final var elementTypes = commonImportManager.createElementTypes( + final Either>, ResponseFormat> elementTypes = commonImportManager.createElementTypes( dataTypeYml, dataTypesFromYml -> createDataTypesFromYml(dataTypeYml, modelName), this::createDataTypesByDao, ElementTypeEnum.DATA_TYPE); if (includeToModelDefaultImports && StringUtils.isNotEmpty(modelName)) { commonImportManager.addTypesToDefaultImports(ElementTypeEnum.DATA_TYPE, dataTypeYml, modelName); } + if (!includeToModelDefaultImports && StringUtils.isNotEmpty(modelName) && elementTypes.isLeft()) { + commonImportManager.updateTypesInAdditionalTypesImport(ElementTypeEnum.DATA_TYPE, dataTypeYml, modelName); + } return elementTypes; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java index a3e3a6ba58..b4079ac0d2 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java @@ -250,6 +250,9 @@ public class ServiceImportBusinessLogic { final Map dataTypesToCreate = getDatatypesToCreate(service.getModel(), csarInfo); if (MapUtils.isNotEmpty(dataTypesToCreate)) { dataTypeBusinessLogic.createDataTypeFromYaml(new Yaml().dump(dataTypesToCreate), service.getModel(), true); + dataTypesToCreate.entrySet().stream().forEach(createdOrUpdatedDataType -> { + applicationDataTypeCache.reload(service.getModel(), UniqueIdBuilder.buildDataTypeUid(service.getModel(), createdOrUpdatedDataType.getKey())); + }); } final List nodeTypesToCreate = getNodeTypesToCreate(service.getModel(), csarInfo); if (CollectionUtils.isNotEmpty(nodeTypesToCreate)) { @@ -283,9 +286,18 @@ public class ServiceImportBusinessLogic { dataTypesToCreate.put(dataTypeEntry.getKey(), dataTypeEntry.getValue()); log.info("Deploying unknown type " + dataTypeEntry.getKey() + " to model " + model + " from package " + csarInfo.getCsarUUID()); } + if (hasNewProperties(result, (Map>) dataTypeEntry.getValue())) { + dataTypesToCreate.put(dataTypeEntry.getKey(), dataTypeEntry.getValue()); + log.info("Deploying new version of type " + dataTypeEntry.getKey() + " to model " + model + " from package " + csarInfo.getCsarUUID()); + } } return dataTypesToCreate; } + + private boolean hasNewProperties(final Either result, final Map> dataType) { + return result.isLeft() && dataType.containsKey("properties") && result.left().value().getProperties() != null + && result.left().value().getProperties().size() != dataType.get("properties").size(); + } private void createNodeTypes(List nodeTypesToCreate, ServiceCsarInfo csarInfo) { NodeTypesMetadataList nodeTypesMetadataList = new NodeTypesMetadataList(); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java index 07593a0cd7..3f8f9c382c 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java @@ -218,7 +218,21 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest when(toscaOperationFacade.updateInputsToComponent(anyList(), eq(newService.getUniqueId()))).thenReturn(Either.left(new ArrayList<>())); when(applicationDataTypeCache.get(any(), contains("tosca.datatypes.test_"))).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND)); - when(applicationDataTypeCache.get(any(), matches("^((?!tosca.datatypes.test_).)*$"))).thenReturn(Either.left(new DataTypeDefinition())); + DataTypeDefinition typeToBeUpdated = new DataTypeDefinition(); + List properties = new ArrayList<>(); + PropertyDefinition nameProperty = new PropertyDefinition(); + nameProperty.setName("name"); + nameProperty.setType("string"); + properties.add(nameProperty); + PropertyDefinition versionProperty = new PropertyDefinition(); + versionProperty.setName("version"); + versionProperty.setType("string"); + properties.add(versionProperty); + typeToBeUpdated.setProperties(properties); + when(applicationDataTypeCache.get(any(), eq("onap.datatypes.ToscaConceptIdentifier.datatype"))).thenReturn(Either.left(typeToBeUpdated)); + when(applicationDataTypeCache.get(any(), matches("^((?!(tosca.datatypes.test_|onap.datatypes.ToscaConceptIdentifier)).)*$"))).thenReturn(Either.left(new DataTypeDefinition())); + + when(toscaOperationFacade.getLatestByToscaResourceName(contains("org.openecomp.resource"), isNull())).thenReturn(Either.left(null)); when(toscaOperationFacade.getLatestByToscaResourceName(contains("tosca.nodes."), isNull())).thenReturn(Either.left(null)); @@ -240,9 +254,10 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest ArgumentCaptor yaml = ArgumentCaptor.forClass(String.class); verify(dataTypeBusinessLogic).createDataTypeFromYaml(yaml.capture(), isNull(), anyBoolean()); Map yamlMap = new Yaml().load(yaml.getValue()); - assertEquals(2, yamlMap.size()); + assertEquals(3, yamlMap.size()); assertNotNull(yamlMap.get("tosca.datatypes.test_a")); assertNotNull(yamlMap.get("tosca.datatypes.test_b")); + assertNotNull(yamlMap.get("onap.datatypes.ToscaConceptIdentifier")); } @Test diff --git a/catalog-be/src/test/resources/csars/service-Ser09080002-csar.csar b/catalog-be/src/test/resources/csars/service-Ser09080002-csar.csar index a65850469d2e2c5e067c2a9c12e9b6b744a1a556..00a6981272417da50820be5d0615ca2bce3b9ca2 100644 GIT binary patch delta 19443 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

&R_%KG2y_klXncd2Pb+ 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

|A?h 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 z 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 safeGetConstraints() { diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ApplicationDataTypeCache.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ApplicationDataTypeCache.java index 0b4d02a0ab..338bbe15a9 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ApplicationDataTypeCache.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/cache/ApplicationDataTypeCache.java @@ -198,6 +198,21 @@ public class ApplicationDataTypeCache implements ApplicationCache dataTypeDefEither = propertyOperation.getDataTypeByUid(uniqueId); + if (dataTypeDefEither.isLeft()) { + DataTypeDefinition dataTypeDef = dataTypeDefEither.left().value(); + if (getDataTypeDefinitionMapByModel(model).containsKey(dataTypeDef.getName())) { + try { + readWriteLock.readLock().lock(); + getDataTypeDefinitionMapByModel(model).put(dataTypeDef.getName(), dataTypeDef); + } finally { + readWriteLock.readLock().unlock(); + } + } + } + } private Map getDataTypeDefinitionMapByModel(final String model) { return dataTypesByModelCacheMap.containsKey(model) ? dataTypesByModelCacheMap.get(model) : new HashMap<>(); diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java index 01e5cdcd40..0d462c9874 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/ModelOperation.java @@ -26,12 +26,16 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.EnumMap; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -50,6 +54,7 @@ import org.openecomp.sdc.be.data.model.ToscaImportByModel; import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum; import org.openecomp.sdc.be.datatypes.enums.ModelTypeEnum; import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.Model; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException; @@ -379,4 +384,50 @@ public class ModelOperation { this.modelElementOperation = modelElementOperation; } + @SuppressWarnings("unchecked") + public void updateTypesInAdditionalTypesImport(final ElementTypeEnum elementTypeEnum, final String typesYaml, final String modelName) { + final Optional additionalTypeDefinitionsImportOptional = getAdditionalTypes(modelName); + + if (additionalTypeDefinitionsImportOptional.isPresent()) { + + final Map existingTypeContent = getExistingTypes(elementTypeEnum, additionalTypeDefinitionsImportOptional.get()); + final Set existingTypeNames = existingTypeContent.keySet(); + + final Map typesToUpate = new HashMap<>(); + + final Map newTypesYaml = new Yaml().load(typesYaml); + newTypesYaml.entrySet().stream().filter(entry -> existingTypeNames.contains(entry.getKey())).forEach(newTypeToUpdate -> { + + final Map propertiesInNewDef = (Map) ((Map) newTypeToUpdate.getValue()).get("properties"); + final Map existingProperties = + (Map) ((Map) existingTypeContent.get(newTypeToUpdate.getKey())).get("properties"); + + final List> propertiesMissingFromNewDef = MapUtils.isEmpty(existingProperties) ? Collections.emptyList() + : existingProperties.entrySet().stream() + .filter(existingPropEntry -> !propertiesInNewDef.keySet().contains(existingPropEntry.getKey())) + .collect(Collectors.toList()); + + if (CollectionUtils.isNotEmpty(propertiesMissingFromNewDef)) { + typesToUpate.put(newTypeToUpdate.getKey(), newTypeToUpdate.getValue()); + + propertiesMissingFromNewDef + .forEach(existingPropToAdd -> propertiesInNewDef.put(existingPropToAdd.getKey(), existingPropToAdd.getValue())); + } + }); + if (MapUtils.isNotEmpty(typesToUpate)) { + addTypesToDefaultImports(elementTypeEnum, new Yaml().dumpAsMap(typesToUpate), modelName); + } + } + } + + private Optional getAdditionalTypes(final String modelName) { + final List modelImportList = toscaModelImportCassandraDao.findAllByModel(modelName); + return modelImportList.stream().filter(t -> ADDITIONAL_TYPE_DEFINITIONS_PATH.equals(Path.of(t.getFullPath()))).findAny(); + } + + private Map getExistingTypes(final ElementTypeEnum elementTypeEnum, final ToscaImportByModel additionalTypeDefinitionsImport) { + final Map existingContent = new Yaml().load(additionalTypeDefinitionsImport.getContent()); + return (Map) existingContent.get(elementTypeEnum.getToscaEntryName()); + } + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java index 7546e90a82..b5215dc848 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/PropertyOperation.java @@ -1822,13 +1822,13 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe String oldDerivedFromName = oldDataTypeDefinition.getDerivedFromName(); String dataTypeName = newDataTypeDefinition.getName(); List propertiesToAdd = new ArrayList<>(); - if (isPropertyOmitted(newProperties, oldProperties, dataTypeName) || isPropertyTypeChanged(dataTypeName, newProperties, oldProperties, - propertiesToAdd) || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) { + if (isPropertyTypeChanged(dataTypeName, newProperties, oldProperties, propertiesToAdd) + || isDerivedFromNameChanged(dataTypeName, newDerivedFromName, oldDerivedFromName)) { log.debug("The new data type {} is invalid.", dataTypeName); result = Either.right(StorageOperationStatus.CANNOT_UPDATE_EXISTING_ENTITY); return result; } - if (propertiesToAdd == null || propertiesToAdd.isEmpty()) { + if (CollectionUtils.isEmpty(propertiesToAdd)) { log.debug("No new properties has been defined in the new data type {}", newDataTypeDefinition); result = Either.right(StorageOperationStatus.OK); return result; @@ -1935,44 +1935,6 @@ public class PropertyOperation extends AbstractOperation implements IPropertyOpe return entryType; } - private boolean isPropertyOmitted(List newProperties, List oldProperties, String dataTypeName) { - boolean isValid = validateChangeInCaseOfEmptyProperties(newProperties, oldProperties, dataTypeName); - if (!isValid) { - log.debug("At least one property is missing in the new data type {}", dataTypeName); - return false; - } - if (newProperties != null && oldProperties != null) { - List newProps = newProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList()); - List oldProps = oldProperties.stream().map(PropertyDataDefinition::getName).collect(Collectors.toList()); - if (!newProps.containsAll(oldProps)) { - StringJoiner joiner = new StringJoiner(",", "[", "]"); - newProps.forEach(joiner::add); - log.debug("Properties {} in data type {} are missing, but they already defined in the existing data type", joiner.toString(), - dataTypeName); - return true; - } - } - return false; - } - - private boolean validateChangeInCaseOfEmptyProperties(List newProperties, List oldProperties, - String dataTypeName) { - if (newProperties != null) { - if (newProperties.isEmpty()) { - newProperties = null; - } - } - if (oldProperties != null) { - if (oldProperties.isEmpty()) { - oldProperties = null; - } - } - if ((newProperties == null && oldProperties == null) || (newProperties != null && oldProperties != null)) { - return true; - } - return false; - } - private boolean isDerivedFromNameChanged(String dataTypeName, String newDerivedFromName, String oldDerivedFromName) { if (newDerivedFromName != null) { boolean isEqual = newDerivedFromName.equals(oldDerivedFromName); diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java index 42f52982a8..acff2a3aa2 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/operations/impl/ModelOperationTest.java @@ -31,6 +31,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.openecomp.sdc.be.model.operations.impl.ModelOperation.ADDITIONAL_TYPE_DEFINITIONS_PATH; @@ -503,7 +504,28 @@ class ModelOperationTest extends ModelTestBase { final ToscaImportByModel actualImport1 = actualImportList.stream().filter(expectedImport1::equals).findFirst().orElse(null); assertNotNull(actualImport1); assertEquals(expectedImport1.getContent(), actualImport1.getContent()); - + + // Update the added additional type + final var updatedDataTypesPath = testResourcePath.resolve(Path.of("input-data_types-updated.yaml")); + final var updatedDataTypes = Files.readString(updatedDataTypesPath); + modelOperation.updateTypesInAdditionalTypesImport(ElementTypeEnum.DATA_TYPE, updatedDataTypes, modelName); + + ArgumentCaptor> updatedImportListArgumentCaptor = ArgumentCaptor.forClass(List.class); + verify(toscaModelImportCassandraDao, times(2)).saveAll(eq(modelName), updatedImportListArgumentCaptor.capture()); + + final List updatedActualImportList = updatedImportListArgumentCaptor.getValue(); + assertEquals(2, updatedActualImportList.size()); + + var expectedUpdatedAdditionalTypesImport = new ToscaImportByModel(); + expectedUpdatedAdditionalTypesImport.setModelId(modelName); + expectedUpdatedAdditionalTypesImport.setFullPath(ADDITIONAL_TYPE_DEFINITIONS_PATH.toString()); + expectedUpdatedAdditionalTypesImport.setContent(Files.readString(testResourcePath.resolve(Path.of("expected-additional_types-2-updated.yaml")))); + final ToscaImportByModel actualUpdatedAdditionalTypesImport = + actualImportList.stream().filter(expectedUpdatedAdditionalTypesImport::equals).findFirst().orElse(null); + assertNotNull(actualUpdatedAdditionalTypesImport); + + assertTrue(actualUpdatedAdditionalTypesImport.getContent().contains("added_property_1")); + assertTrue(actualUpdatedAdditionalTypesImport.getContent().contains("added_property_2")); } @Test diff --git a/catalog-model/src/test/resources/modelOperation/expected-additional_types-1.yaml b/catalog-model/src/test/resources/modelOperation/expected-additional_types-1.yaml index c9e6741993..50d9babb60 100644 --- a/catalog-model/src/test/resources/modelOperation/expected-additional_types-1.yaml +++ b/catalog-model/src/test/resources/modelOperation/expected-additional_types-1.yaml @@ -5,6 +5,9 @@ data_types: tosca.datatypes.nfv.ServiceAvailability: derived_from: tosca.datatypes.Root description: additional type + properties: + added_property_1: + type: string tosca.datatypes.nfv.L2AddressData: derived_from: tosca.datatypes.Root description: additional type diff --git a/catalog-model/src/test/resources/modelOperation/expected-additional_types-2-updated.yaml b/catalog-model/src/test/resources/modelOperation/expected-additional_types-2-updated.yaml new file mode 100644 index 0000000000..ad3d0bfdd8 --- /dev/null +++ b/catalog-model/src/test/resources/modelOperation/expected-additional_types-2-updated.yaml @@ -0,0 +1,24 @@ +tosca_definitions_version: tosca_simple_yaml_1_3 +description: Auto-generated file that contains package custom types or types added + after system installation. +data_types: + tosca.datatypes.nfv.PreviouslyExistingType1: + derived_from: tosca.datatypes.Root + description: additional type + tosca.datatypes.nfv.PreviouslyExistingType2: + derived_from: tosca.datatypes.Root + description: additional type + tosca.datatypes.nfv.ServiceAvailability: + derived_from: tosca.datatypes.Root + description: additional type + properties: + added_property_1: + type: string + added_property_2: + type: string + tosca.datatypes.nfv.L2AddressData: + derived_from: tosca.datatypes.Root + description: additional type + tosca.datatypes.nfv.Unknown: + derived_from: tosca.datatypes.Root + description: additional type diff --git a/catalog-model/src/test/resources/modelOperation/expected-additional_types-2.yaml b/catalog-model/src/test/resources/modelOperation/expected-additional_types-2.yaml index 2d2c54206e..a36c828193 100644 --- a/catalog-model/src/test/resources/modelOperation/expected-additional_types-2.yaml +++ b/catalog-model/src/test/resources/modelOperation/expected-additional_types-2.yaml @@ -11,6 +11,9 @@ data_types: tosca.datatypes.nfv.ServiceAvailability: derived_from: tosca.datatypes.Root description: additional type + properties: + added_property_1: + type: string tosca.datatypes.nfv.L2AddressData: derived_from: tosca.datatypes.Root description: additional type diff --git a/catalog-model/src/test/resources/modelOperation/input-data_types-updated.yaml b/catalog-model/src/test/resources/modelOperation/input-data_types-updated.yaml new file mode 100644 index 0000000000..136585acb6 --- /dev/null +++ b/catalog-model/src/test/resources/modelOperation/input-data_types-updated.yaml @@ -0,0 +1,12 @@ +tosca.datatypes.nfv.ServiceAvailability: + derived_from: tosca.datatypes.Root + description: additional type + properties: + added_property_2: + type: string +tosca.datatypes.nfv.L2AddressData: + derived_from: tosca.datatypes.Root + description: additional type +tosca.datatypes.nfv.Unknown: + derived_from: tosca.datatypes.Root + description: additional type \ No newline at end of file diff --git a/catalog-model/src/test/resources/modelOperation/input-data_types.yaml b/catalog-model/src/test/resources/modelOperation/input-data_types.yaml index 77b7d977b0..0754631071 100644 --- a/catalog-model/src/test/resources/modelOperation/input-data_types.yaml +++ b/catalog-model/src/test/resources/modelOperation/input-data_types.yaml @@ -1,6 +1,9 @@ tosca.datatypes.nfv.ServiceAvailability: derived_from: tosca.datatypes.Root description: additional type + properties: + added_property_1: + type: string tosca.datatypes.nfv.L2AddressData: derived_from: tosca.datatypes.Root description: additional type -- 2.16.6