Import multiple node types in a single endpoint 43/124743/3
authorandre.schmid <andre.schmid@est.tech>
Fri, 1 Oct 2021 17:45:17 +0000 (18:45 +0100)
committerAndré Schmid <andre.schmid@est.tech>
Fri, 15 Oct 2021 14:26:03 +0000 (14:26 +0000)
Change-Id: I7aa914d459a083146b92ef82197c8df265b8c5b6
Issue-ID: SDC-3752
Signed-off-by: andre.schmid <andre.schmid@est.tech>
50 files changed:
catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Cp/Cp.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Cp/Cp.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NS/NS.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NS/NS.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NsVirtualLink/NsVirtualLink.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NsVirtualLink/NsVirtualLink.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Sap/Sap.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Sap/Sap.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/VNF/VNF.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/VNF/VNF.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/metadata.json [new file with mode: 0644]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/nodeTypes.yaml [new file with mode: 0644]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/root/root.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/root/root.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/types.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCompute/vduCompute.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCompute/vduCompute.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCp/vduCp.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCp/vduCp.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualBlockStorage/vduVirtualBlockStorage.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualBlockStorage/vduVirtualBlockStorage.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualFileStorage/vduVirtualFileStorage.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualFileStorage/vduVirtualFileStorage.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualObjectStorage/vduVirtualObjectStorage.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualObjectStorage/vduVirtualObjectStorage.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfExtCp/vnfExtCp.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfExtCp/vnfExtCp.yml [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfVirtualLink/vnfVirtualLink.json [deleted file]
catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfVirtualLink/vnfVirtualLink.yml [deleted file]
catalog-be/src/main/resources/scripts/sdcBePy/common/logger.py
catalog-be/src/main/resources/scripts/sdcBePy/common/normative/toscaTypes.py
catalog-be/src/main/resources/scripts/sdcBePy/tosca/imports/run.py
catalog-be/src/main/resources/scripts/sdcBePy/tosca/models/model_client.py
catalog-be/src/main/resources/scripts/sdcBePy/tosca/models/model_import_manager.py
catalog-be/src/main/resources/scripts/sdcBePy/tosca/models/node_type_client.py [new file with mode: 0644]
catalog-be/src/main/resources/scripts/sdcBePy/tosca/upgrade/run.py
catalog-be/src/test/java/org/openecomp/sdc/be/components/ResourceImportManagerTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ResourceUploadServletTest.java
catalog-be/src/test/resources/node-types/nodeTypes.yaml [new file with mode: 0644]
catalog-be/src/test/resources/node-types/payload.json [new file with mode: 0644]
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/NodeTypeMetadata.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/NodeTypesMetadataList.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadResourceInfo.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/NodeTypeMetadataMapper.java [new file with mode: 0644]
catalog-model/src/test/java/org/openecomp/sdc/be/model/mapper/NodeTypeMetadataMapperTest.java [new file with mode: 0644]

index 9d3204b..cfde6b4 100644 (file)
@@ -2611,4 +2611,10 @@ errors:
         code: 500,
         message: "Could not delete the model '%1' elements.",
         messageId: "SVC4160"
+    }
+    #---------SVC4161-----------------------------
+    INVALID_NODE_TYPES_YAML: {
+        code: 400,
+        message: "Invalid node_types TOSCA yaml",
+        messageId: "SVC4161"
     }
\ No newline at end of file
index 1503835..9980a96 100644 (file)
@@ -24,6 +24,7 @@ package org.openecomp.sdc.be.components.impl;
 import static org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaElementOperation.createDataType;
 import static org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaElementOperation.createDataTypeDefinitionWithName;
 
+import fj.data.Either;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -36,9 +37,7 @@ import java.util.Set;
 import java.util.function.Function;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
-
 import javax.servlet.ServletContext;
-
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -57,6 +56,7 @@ import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
 import org.openecomp.sdc.be.config.BeEcompErrorManager;
 import org.openecomp.sdc.be.config.BeEcompErrorManager.ErrorSeverity;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
@@ -72,6 +72,7 @@ import org.openecomp.sdc.be.model.ComponentInstanceProperty;
 import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.LifecycleStateEnum;
+import org.openecomp.sdc.be.model.NodeTypesMetadataList;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.RequirementDefinition;
 import org.openecomp.sdc.be.model.Resource;
@@ -80,6 +81,7 @@ import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.category.CategoryDefinition;
 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
+import org.openecomp.sdc.be.model.mapper.NodeTypeMetadataMapper;
 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.CapabilityTypeOperation;
@@ -89,6 +91,7 @@ import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo;
 import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo;
 import org.openecomp.sdc.be.utils.TypeUtils;
 import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.ThreadLocalsHolder;
 import org.openecomp.sdc.common.util.ValidationUtils;
@@ -98,8 +101,6 @@ import org.springframework.stereotype.Component;
 import org.springframework.web.context.WebApplicationContext;
 import org.yaml.snakeyaml.Yaml;
 
-import fj.data.Either;
-
 @Component("resourceImportManager")
 public class ResourceImportManager {
 
@@ -108,6 +109,7 @@ public class ResourceImportManager {
     private final InterfaceDefinitionHandler interfaceDefinitionHandler;
     private final ComponentsUtils componentsUtils;
     private final CapabilityTypeOperation capabilityTypeOperation;
+    private final JanusGraphDao janusGraphDao;
     private ServletContext servletContext;
     private AuditingManager auditingManager;
     private ResourceBusinessLogic resourceBusinessLogic;
@@ -118,11 +120,12 @@ public class ResourceImportManager {
     private ResponseFormatManager responseFormatManager;
 
     @Autowired
-    public ResourceImportManager(ComponentsUtils componentsUtils, CapabilityTypeOperation capabilityTypeOperation,
-                                 final InterfaceDefinitionHandler interfaceDefinitionHandler) {
+    public ResourceImportManager(final ComponentsUtils componentsUtils, final CapabilityTypeOperation capabilityTypeOperation,
+                                 final InterfaceDefinitionHandler interfaceDefinitionHandler, final JanusGraphDao janusGraphDao) {
         this.componentsUtils = componentsUtils;
         this.capabilityTypeOperation = capabilityTypeOperation;
         this.interfaceDefinitionHandler = interfaceDefinitionHandler;
+        this.janusGraphDao = janusGraphDao;
     }
 
     public ServiceBusinessLogic getServiceBusinessLogic() {
@@ -138,13 +141,51 @@ public class ResourceImportManager {
         this.toscaOperationFacade = toscaOperationFacade;
     }
 
-    public ImmutablePair<Resource, ActionStatus> importNormativeResource(String resourceYml, UploadResourceInfo resourceMetaData, User creator,
-                                                                         boolean createNewVersion, boolean needLock) {
+    public ImmutablePair<Resource, ActionStatus> importNormativeResource(final String resourceYml, final UploadResourceInfo resourceMetaData,
+                                                                         final User creator, final boolean createNewVersion, final boolean needLock,
+                                                                         final boolean isInTransaction) {
         LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction();
         lifecycleChangeInfo.setUserRemarks("certification on import");
         Function<Resource, Boolean> validator = resource -> resourceBusinessLogic.validatePropertiesDefaultValues(resource);
-        return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, false, createNewVersion, needLock,
-            null, null, false, null, null, false);
+        return importCertifiedResource(resourceYml, resourceMetaData, creator, validator, lifecycleChangeInfo, isInTransaction, createNewVersion,
+            needLock, null, null, false, null, null, false);
+    }
+
+    public void importAllNormativeResource(final String resourcesYaml, final NodeTypesMetadataList nodeTypesMetadataList, final User user,
+                                           final boolean createNewVersion, final boolean needLock) {
+        final Map<String, Object> nodeTypesYamlMap;
+        try {
+            nodeTypesYamlMap = new Yaml().load(resourcesYaml);
+        } catch (final Exception e) {
+            log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ResourceImportManager.class.getName(), "Could not parse node types YAML", e);
+            throw new ByActionStatusComponentException(ActionStatus.INVALID_NODE_TYPES_YAML);
+        }
+
+        if (!nodeTypesYamlMap.containsKey(ToscaTagNamesEnum.NODE_TYPES.getElementName())) {
+            return;
+        }
+        final Map<String, Object> nodeTypesMap = (Map<String, Object>) nodeTypesYamlMap.get(ToscaTagNamesEnum.NODE_TYPES.getElementName());
+        try {
+            nodeTypesMetadataList.getNodeMetadataList().forEach(nodeTypeMetadata -> {
+                final String nodeTypeToscaName = nodeTypeMetadata.getToscaName();
+                final Map<String, Object> nodeTypeMap = (Map<String, Object>) nodeTypesMap.get(nodeTypeToscaName);
+                if (nodeTypeMap == null) {
+                    log.warn(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ResourceImportManager.class.getName(),
+                        "Could not find given node type '{}'. The node will not be created.", new Object[]{nodeTypeToscaName});
+                } else {
+                    final Map<String, Map<String, Map<String, Object>>> nodeTypeDefinitionMap =
+                        Map.of(ToscaTagNamesEnum.NODE_TYPES.getElementName(),
+                            Map.of(nodeTypeToscaName, nodeTypeMap)
+                        );
+                    final String nodeTypeYaml = new Yaml().dump(nodeTypeDefinitionMap);
+                    importNormativeResource(nodeTypeYaml, NodeTypeMetadataMapper.mapTo(nodeTypeMetadata), user, createNewVersion, needLock, true);
+                }
+            });
+            janusGraphDao.commit();
+        } catch (final Exception e) {
+            janusGraphDao.rollback();
+            throw e;
+        }
     }
 
     public ImmutablePair<Resource, ActionStatus> importNormativeResourceFromCsar(String resourceYml, UploadResourceInfo resourceMetaData,
@@ -308,11 +349,11 @@ public class ResourceImportManager {
             Map<String, Object> toscaJsonAll = (Map<String, Object>) ymlObj;
             Map<String, Object> toscaJson = toscaJsonAll;
             // Checks if exist and builds the node_types map
-            if (toscaJsonAll.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName())
+            if (toscaJsonAll.containsKey(ToscaTagNamesEnum.NODE_TYPES.getElementName())
                 && resource.getResourceType() != ResourceTypeEnum.CVFC) {
                 toscaJson = new HashMap<>();
-                toscaJson.put(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName(),
-                    toscaJsonAll.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName()));
+                toscaJson.put(ToscaTagNamesEnum.NODE_TYPES.getElementName(),
+                    toscaJsonAll.get(ToscaTagNamesEnum.NODE_TYPES.getElementName()));
             }
             final List<Object> foundElements = new ArrayList<>();
             final Either<List<Object>, ResultStatusEnum> toscaElements = ImportUtils
@@ -340,8 +381,8 @@ public class ResourceImportManager {
 
     private void setToscaResourceName(Map<String, Object> toscaJson, Resource resource) {
         Either<Map<String, Object>, ResultStatusEnum> toscaElement = ImportUtils
-            .findFirstToscaMapElement(toscaJson, TypeUtils.ToscaTagNamesEnum.NODE_TYPES);
-        if (toscaElement.isLeft() || toscaElement.left().value().size() == 1) {
+            .findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.NODE_TYPES);
+        if (toscaElement.isLeft() && toscaElement.left().value().size() == 1) {
             String toscaResourceName = toscaElement.left().value().keySet().iterator().next();
             resource.setToscaResourceName(toscaResourceName);
         }
@@ -349,7 +390,7 @@ public class ResourceImportManager {
 
     private void setInterfaceLifecycle(Map<String, Object> toscaJson, Resource resource) {
         Either<Map<String, Object>, ResultStatusEnum> toscaInterfaces = ImportUtils
-            .findFirstToscaMapElement(toscaJson, TypeUtils.ToscaTagNamesEnum.INTERFACES);
+            .findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.INTERFACES);
         if (toscaInterfaces.isLeft()) {
             Map<String, Object> jsonInterfaces = toscaInterfaces.left().value();
             Map<String, InterfaceDefinition> moduleInterfaces = new HashMap<>();
@@ -391,7 +432,7 @@ public class ResourceImportManager {
     private void setRequirements(Map<String, Object> toscaJson, Resource resource,
                                  Resource parentResource) {// Note that parentResource can be null
         Either<List<Object>, ResultStatusEnum> toscaRequirements = ImportUtils
-            .findFirstToscaListElement(toscaJson, TypeUtils.ToscaTagNamesEnum.REQUIREMENTS);
+            .findFirstToscaListElement(toscaJson, ToscaTagNamesEnum.REQUIREMENTS);
         if (toscaRequirements.isLeft()) {
             List<Object> jsonRequirements = toscaRequirements.left().value();
             Map<String, List<RequirementDefinition>> moduleRequirements = new HashMap<>();
@@ -442,17 +483,17 @@ public class ResourceImportManager {
             requirement.setCapability(requirementJsonString);
         } else if (requirementJson instanceof Map) {
             Map<String, Object> requirementJsonMap = (Map<String, Object>) requirementJson;
-            if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.CAPABILITY.getElementName())) {
-                requirement.setCapability((String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.CAPABILITY.getElementName()));
+            if (requirementJsonMap.containsKey(ToscaTagNamesEnum.CAPABILITY.getElementName())) {
+                requirement.setCapability((String) requirementJsonMap.get(ToscaTagNamesEnum.CAPABILITY.getElementName()));
             }
-            if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.NODE.getElementName())) {
-                requirement.setNode((String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.NODE.getElementName()));
+            if (requirementJsonMap.containsKey(ToscaTagNamesEnum.NODE.getElementName())) {
+                requirement.setNode((String) requirementJsonMap.get(ToscaTagNamesEnum.NODE.getElementName()));
             }
-            if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.RELATIONSHIP.getElementName())) {
-                requirement.setRelationship((String) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.RELATIONSHIP.getElementName()));
+            if (requirementJsonMap.containsKey(ToscaTagNamesEnum.RELATIONSHIP.getElementName())) {
+                requirement.setRelationship((String) requirementJsonMap.get(ToscaTagNamesEnum.RELATIONSHIP.getElementName()));
             }
-            if (requirementJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName())) {
-                List<Object> occurrencesList = (List) requirementJsonMap.get(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName());
+            if (requirementJsonMap.containsKey(ToscaTagNamesEnum.OCCURRENCES.getElementName())) {
+                List<Object> occurrencesList = (List) requirementJsonMap.get(ToscaTagNamesEnum.OCCURRENCES.getElementName());
                 validateOccurrences(occurrencesList);
                 requirement.setMinOccurrences(occurrencesList.get(0).toString());
                 requirement.setMaxOccurrences(occurrencesList.get(1).toString());
@@ -522,7 +563,7 @@ public class ResourceImportManager {
 
     private Resource setDerivedFrom(Map<String, Object> toscaJson, Resource resource) {
         Either<String, ResultStatusEnum> toscaDerivedFromElement = ImportUtils
-            .findFirstToscaStringElement(toscaJson, TypeUtils.ToscaTagNamesEnum.DERIVED_FROM);
+            .findFirstToscaStringElement(toscaJson, ToscaTagNamesEnum.DERIVED_FROM);
         Resource derivedFromResource = null;
         if (toscaDerivedFromElement.isLeft()) {
             String derivedFrom = toscaDerivedFromElement.left().value();
@@ -547,7 +588,7 @@ public class ResourceImportManager {
     private void setCapabilities(Map<String, Object> toscaJson, Resource resource,
                                  Resource parentResource) {// Note that parentResource can be null
         Either<Map<String, Object>, ResultStatusEnum> toscaCapabilities = ImportUtils
-            .findFirstToscaMapElement(toscaJson, TypeUtils.ToscaTagNamesEnum.CAPABILITIES);
+            .findFirstToscaMapElement(toscaJson, ToscaTagNamesEnum.CAPABILITIES);
         if (toscaCapabilities.isLeft()) {
             Map<String, Object> jsonCapabilities = toscaCapabilities.left().value();
             Map<String, List<CapabilityDefinition>> moduleCapabilities = new HashMap<>();
@@ -674,25 +715,25 @@ public class ResourceImportManager {
         } else if (capabilityJson instanceof Map) {
             Map<String, Object> capabilityJsonMap = (Map<String, Object>) capabilityJson;
             // Type
-            if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())) {
-                capabilityDefinition.setType((String) capabilityJsonMap.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName()));
+            if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.TYPE.getElementName())) {
+                capabilityDefinition.setType((String) capabilityJsonMap.get(ToscaTagNamesEnum.TYPE.getElementName()));
             }
             // ValidSourceTypes
-            if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.VALID_SOURCE_TYPES.getElementName())) {
+            if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.VALID_SOURCE_TYPES.getElementName())) {
                 capabilityDefinition
-                    .setValidSourceTypes((List<String>) capabilityJsonMap.get(TypeUtils.ToscaTagNamesEnum.VALID_SOURCE_TYPES.getElementName()));
+                    .setValidSourceTypes((List<String>) capabilityJsonMap.get(ToscaTagNamesEnum.VALID_SOURCE_TYPES.getElementName()));
             }
             // ValidSourceTypes
-            if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.DESCRIPTION.getElementName())) {
-                capabilityDefinition.setDescription((String) capabilityJsonMap.get(TypeUtils.ToscaTagNamesEnum.DESCRIPTION.getElementName()));
+            if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.DESCRIPTION.getElementName())) {
+                capabilityDefinition.setDescription((String) capabilityJsonMap.get(ToscaTagNamesEnum.DESCRIPTION.getElementName()));
             }
-            if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName())) {
-                List<Object> occurrencesList = (List) capabilityJsonMap.get(TypeUtils.ToscaTagNamesEnum.OCCURRENCES.getElementName());
+            if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.OCCURRENCES.getElementName())) {
+                List<Object> occurrencesList = (List) capabilityJsonMap.get(ToscaTagNamesEnum.OCCURRENCES.getElementName());
                 validateOccurrences(occurrencesList);
                 capabilityDefinition.setMinOccurrences(occurrencesList.get(0).toString());
                 capabilityDefinition.setMaxOccurrences(occurrencesList.get(1).toString());
             }
-            if (capabilityJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.PROPERTIES.getElementName())) {
+            if (capabilityJsonMap.containsKey(ToscaTagNamesEnum.PROPERTIES.getElementName())) {
                 Either<Map<String, PropertyDefinition>, ResultStatusEnum> propertiesRes = ImportUtils.getProperties(capabilityJsonMap);
                 if (propertiesRes.isRight()) {
                     throw new ByActionStatusComponentException(ActionStatus.PROPERTY_NOT_FOUND);
@@ -771,7 +812,7 @@ public class ResourceImportManager {
     private String getToscaVersion(final String payloadData) {
         final Map<String, Object> mappedToscaTemplate = decodePayload(payloadData);
         final Either<String, ResultStatusEnum> findFirstToscaStringElement = ImportUtils
-            .findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION);
+            .findFirstToscaStringElement(mappedToscaTemplate, ToscaTagNamesEnum.TOSCA_VERSION);
         if (findFirstToscaStringElement.isLeft()) {
             return findFirstToscaStringElement.left().value();
         } else {
index beaa08c..02f96ad 100644 (file)
@@ -656,7 +656,8 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet {
             importedResourceStatus = importResourceFromUICsar(resourceInfoObject, user, resourceUniqueId);
         } else if (!authority.isUserTypeResource()) {
             log.debug("import normative type resource");
-            createOrUpdateResponse = resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true);
+            createOrUpdateResponse =
+                resourceImportManager.importNormativeResource(yamlAsString, resourceInfoObject, user, createNewVersion, true, false);
         } else {
             log.debug("import user resource (not normative type)");
             createOrUpdateResponse = resourceImportManager.importUserDefinedResource(yamlAsString, resourceInfoObject, user, false);
index e7966e0..b200b32 100644 (file)
@@ -20,6 +20,7 @@
 package org.openecomp.sdc.be.servlets;
 
 import com.jcabi.aspects.Loggable;
+import fj.data.Either;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.media.ArraySchema;
@@ -29,8 +30,12 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
 import io.swagger.v3.oas.annotations.servers.Server;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import javax.inject.Inject;
 import javax.servlet.http.HttpServletRequest;
+import javax.validation.constraints.NotNull;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DefaultValue;
 import javax.ws.rs.HeaderParam;
@@ -54,12 +59,15 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.exception.BusinessException;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.impl.ServletUtils;
+import org.openecomp.sdc.be.model.NodeTypesMetadataList;
 import org.openecomp.sdc.be.model.UploadResourceInfo;
 import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ModelOperationExceptionSupplier;
 import org.openecomp.sdc.be.user.UserBusinessLogic;
 import org.openecomp.sdc.common.api.Constants;
 import org.openecomp.sdc.common.datastructure.Wrapper;
+import org.openecomp.sdc.common.util.ValidationUtils;
+import org.openecomp.sdc.exception.ResponseFormat;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Controller;
@@ -80,7 +88,7 @@ public class ResourceUploadServlet extends AbstractValidationsServlet {
     public static final String USER_TYPE_RESOURCE_UI_IMPORT = "user-resource-ui-import";
     private static final Logger log = LoggerFactory.getLogger(ResourceUploadServlet.class);
 
-    private ModelBusinessLogic modelBusinessLogic;
+    private final ModelBusinessLogic modelBusinessLogic;
 
     @Inject
     public ResourceUploadServlet(UserBusinessLogic userBusinessLogic, ComponentInstanceBusinessLogic componentInstanceBL,
@@ -150,6 +158,59 @@ public class ResourceUploadServlet extends AbstractValidationsServlet {
         }
     }
 
+    @POST
+    @Path("/resource/import")
+    @Consumes(MediaType.MULTIPART_FORM_DATA)
+    @Produces(MediaType.APPLICATION_JSON)
+    @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
+    @Operation(description = "Import node types from a TOSCA yaml, along with the types metadata", method = "POST",
+        summary = "Creates node types from a TOSCA yaml file", responses = {
+        @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))),
+        @ApiResponse(responseCode = "201", description = "Resources created"),
+        @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
+        @ApiResponse(responseCode = "403", description = "Restricted operation"),
+        @ApiResponse(responseCode = "409", description = "One of the resources already exists")}
+    )
+    public Response bulkImport(@Parameter(description = "The nodes metadata JSON", required = true)
+                               @NotNull @FormDataParam("nodeTypeMetadataJson") final NodeTypesMetadataList nodeTypeMetadata,
+                               @Parameter(description = "The node types TOSCA definition yaml", required = true)
+                               @NotNull @FormDataParam("nodeTypesYaml") final InputStream nodeTypesYamlInputStream,
+                               @Parameter(description = "The model name to associate the node types to")
+                               @DefaultValue("true") @FormDataParam("createNewVersion") boolean createNewVersion,
+                               @HeaderParam(value = Constants.USER_ID_HEADER) String userId,
+                               @Context final HttpServletRequest request) {
+        userId = ValidationUtils.sanitizeInputString(userId);
+        final Either<User, ResponseFormat> userEither = getUser(request, userId);
+        if (userEither.isRight()) {
+            return buildErrorResponse(userEither.right().value());
+        }
+
+        final User user = userEither.left().value();
+
+        final String nodeTypesYamlString;
+        try {
+            nodeTypesYamlString = new String(nodeTypesYamlInputStream.readAllBytes(), StandardCharsets.UTF_8);
+        } catch (final IOException e) {
+            var errorMsg = "Could not read the given node types yaml";
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError(errorMsg);
+            log.error(errorMsg, e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.INVALID_NODE_TYPES_YAML));
+        }
+
+        try {
+            resourceImportManager
+                .importAllNormativeResource(nodeTypesYamlString, nodeTypeMetadata, user, createNewVersion, false);
+            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), null);
+        } catch (final BusinessException e) {
+            throw e;
+        } catch (final Exception e) {
+            var errorMsg = "Unexpected error while importing the node types";
+            BeEcompErrorManager.getInstance().logBeRestApiGeneralError(errorMsg);
+            log.error(errorMsg, e);
+            return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR));
+        }
+    }
+
     /**
      * The Model field is an optional entry when uploading a resource. If the field is present, it validates if the Model name exists.
      * @param modelName Model names declared on the resource json representation
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Cp/Cp.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Cp/Cp.json
deleted file mode 100644 (file)
index 123bc23..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "payloadName": "Cp.yml",
-       "contactId": "jh0003",
-       "name": "Cp",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "Cp",
-       "resourceIconPath": "compute",
-       "resourceType": "VFC",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Infrastructure"
-               }]
-       }],
-       "tags": ["Cp"]
-}
\ No newline at end of file
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Cp/Cp.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Cp/Cp.yml
deleted file mode 100644 (file)
index 1132735..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 Cp node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.Cp:
-    derived_from: tosca.nodes.Root
-    description: Provides information regarding the purpose of the connection point
-    properties:
-      layer_protocols:
-        type: list
-        description: Identifies which protocol the connection point uses for connectivity purposes
-        required: true
-        entry_schema:
-          type: string
-          constraints:
-            - valid_values: [ ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire ]
-      role: #Name in ETSI NFV IFA011 v0.7.3: cpRole
-        type: string
-        description: Identifies the role of the port in the context of the traffic flow patterns in the VNF or parent NS
-        required: false
-        constraints:
-          - valid_values: [ root, leaf ]
-      description:
-        type: string
-        description: Provides human-readable information on the purpose of the connection point
-        required: false
-      protocol:
-        type: list
-        description: Provides information on the addresses to be assigned to the connection point(s) instantiated from this Connection Point Descriptor
-        required: false
-        entry_schema:
-          type: tosca.datatypes.nfv.CpProtocolData
-      trunk_mode:
-        type: boolean
-        description: Provides information about whether the CP instantiated from this Cp is in Trunk mode (802.1Q or other), When operating in "trunk mode", the Cp is capable of carrying traffic for several VLANs. Absence of this property implies that trunkMode is not configured for the Cp i.e. It is equivalent to boolean value "false".
-        required: false
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NS/NS.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NS/NS.json
deleted file mode 100644 (file)
index 1e77b17..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "payloadName": "NS.yml",
-       "contactId": "jh0003",
-       "name": "NS",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "ETSI NS",
-       "resourceIconPath": "network",
-       "resourceType": "VFC",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Network Elements"
-               }]
-       }],
-       "tags": ["NS"]
-}
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NS/NS.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NS/NS.yml
deleted file mode 100644 (file)
index afa1351..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 NS node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.NS:
-    derived_from: tosca.nodes.Root
-    properties:
-      descriptor_id:
-        type: string # GUID
-        description: Identifier of this NS descriptor
-        required: true
-      designer:
-        type: string
-        description: Identifies the designer of the NSD.
-        required: true
-      version:
-        type: string
-        description: Identifies the version of the NSD.
-        required: true
-      name:
-        type: string
-        description: Provides the human readable name of the NSD.
-        required: true
-      invariant_id:
-        type: string
-        description: Identifies an NSD in a version independent manner. This attribute is invariant across versions of NSD.
-        required: true
-    requirements:
-      - virtual_link:
-          capability: tosca.capabilities.nfv.VirtualLinkable
-          relationship: tosca.relationships.nfv.VirtualLinksTo
-          node: tosca.nodes.nfv.NsVirtualLink
-          occurrences: [ 0, 1 ]
-    interfaces:
-      Nslcm:
-        type: tosca.interfaces.nfv.Nslcm
\ No newline at end of file
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NsVirtualLink/NsVirtualLink.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NsVirtualLink/NsVirtualLink.json
deleted file mode 100644 (file)
index a2c83b1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "payloadName": "NsVirtualLink.yml",
-       "contactId": "jh0003",
-       "name": "NsVirtualLink",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "ETSI NsVirtualLink",
-       "resourceIconPath": "network",
-       "resourceType": "VL",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Infrastructure"
-               }]
-       }],
-       "tags": ["NsVirtualLink"]
-}
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NsVirtualLink/NsVirtualLink.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/NsVirtualLink/NsVirtualLink.yml
deleted file mode 100644 (file)
index fa4f470..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 NsVirtualLink node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.NsVirtualLink:
-    derived_from: tosca.nodes.Root
-    description: node definition of Virtual Links
-    properties:
-      vl_profile:
-        type: tosca.datatypes.nfv.NsVlProfile # only covers min/max bitrate requirements
-        description: Specifies instantiation parameters for a virtual link of a particular NS deployment flavour.
-        required: true
-      connectivity_type:
-        type: tosca.datatypes.nfv.ConnectivityType
-        required: true
-      test_access:
-        type: list
-        description: Test access facilities available on the VL
-        required: false
-        entry_schema:
-          type: string
-          constraints:
-            - valid_values: [ passive_monitoring, active_loopback ]
-      description:
-        type: string
-        required: false
-        description: Human readable information on the purpose of the virtual link (e.g. VL for control plane traffic).
-    capabilities:
-      virtual_linkable:
-        type: tosca.capabilities.nfv.VirtualLinkable
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Sap/Sap.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Sap/Sap.json
deleted file mode 100644 (file)
index 1c8c3a0..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-       "payloadName": "Sap.yml",
-       "contactId": "jh0003",
-       "name": "Sap",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "Sap",
-       "resourceIconPath": "network",
-       "resourceType": "VFC",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Infrastructure"
-               }]
-       }],
-        "vendorName": "ETSI",
-        "vendorRelease": "2.5.1",
-       "tags": ["Sap"]
-}
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Sap/Sap.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/Sap/Sap.yml
deleted file mode 100644 (file)
index 818571c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 Sap node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.Sap:
-    derived_from: tosca.nodes.nfv.Cp
-    description: node definition of SAP.
-    requirements:
-      - external_virtual_link:
-          capability: tosca.capabilities.nfv.VirtualLinkable
-          relationship: tosca.relationships.nfv.VirtualLinksTo
-      - internal_virtual_link:
-          capability: tosca.capabilities.nfv.VirtualLinkable
-          relationship: tosca.relationships.nfv.VirtualLinksTo
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/VNF/VNF.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/VNF/VNF.json
deleted file mode 100644 (file)
index c260bb3..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "payloadName": "VNF.yml",
-       "contactId": "jh0003",
-       "name": "VNF",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "VNF",
-       "resourceIconPath": "compute",
-       "resourceType": "VFC",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Infrastructure"
-               }]
-       }],
-       "tags": ["VNF"]
-}
\ No newline at end of file
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/VNF/VNF.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/VNF/VNF.yml
deleted file mode 100644 (file)
index c5f7672..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 vnf node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.VNF:
-    derived_from: tosca.nodes.Root
-    description: The generic abstract type from which all VNF specific abstract node types shall be derived to form, together with other node types, the TOSCA service template(s) representing the VNFD
-    properties:
-      descriptor_id: # instead of vnfd_id
-        type: string # GUID
-        description: Globally unique identifier of the VNFD
-        required: true
-      descriptor_version: # instead of vnfd_version
-        type: string
-        description: Identifies the version of the VNFD
-        required: true
-      provider: # instead of vnf_provider
-        type: string
-        description: Provider of the VNF and of the VNFD
-        required: true
-      product_name: # instead of vnf_product_name
-        type: string
-        description: Human readable name for the VNF Product
-        required: true
-      software_version: # instead of vnf_software_version
-        type: string
-        description: Software version of the VNF
-        required: true
-      product_info_name: # instead of vnf_product_info_name
-        type: string
-        description: Human readable name for the VNF Product
-        required: false
-      product_info_description: # instead of vnf_product_info_description
-        type: string
-        description: Human readable description of the VNF Product
-        required: false
-      vnfm_info:
-        type: list
-        required: true
-        description: Identifies VNFM(s) compatible with the VNF
-        entry_schema:
-          type: string
-      localization_languages:
-        type: list
-        description: Information about localization languages of the VNF
-        required: false
-        entry_schema:
-          type: string #IETF RFC 5646 string
-      default_localization_language:
-        type: string #IETF RFC 5646 string
-        description: Default localization language that is instantiated if no information about selected localization language is available
-        required: false
-        #configurable_properties:
-        #type: tosca.datatypes.nfv.VnfConfigurableProperties
-        #description: Describes the configurable properties of the VNF
-        #required: false
-        # derived types are expected to introduce configurable_properties 
-        # with its type derived from 
-        # tosca.datatypes.nfv.VnfConfigurableProperties
-        #modifiable_attributes:
-        #type: tosca.datatypes.nfv.VnfInfoModifiableAttributes
-        #description: Describes the modifiable attributes of the VNF
-        #required: false 
-        # derived types are expected to introduce modifiable_attributes
-        # with its type derived from
-        # tosca.datatypes.nfv.VnfInfoModifiableAttributes
-      lcm_operations_configuration:
-        type: tosca.datatypes.nfv.VnfLcmOperationsConfiguration
-        description: Describes the configuration parameters for the VNF LCM operations
-        required: false
-      monitoring_parameters:
-        type: list
-        entry_schema:
-          type: tosca.datatypes.nfv.VnfMonitoringParameter
-        description: Describes monitoring parameters applicable to the VNF.
-        required: false
-      flavour_id:
-        type: string
-        description: Identifier of the Deployment Flavour within the VNFD
-        required: true
-      flavour_description:
-        type: string
-        description: Human readable description of the DF
-        required: true
-      #vnf_profile:
-      #  type: tosca.datatypes.nfv.VnfProfile
-      #  description: Describes a profile for instantiating VNFs of a particular NS DF according to a specific VNFD and VNF DF
-      #  required: false
-    requirements:
-      - virtual_link:
-          capability: tosca.capabilities.nfv.VirtualLinkable
-          relationship: tosca.relationships.nfv.VirtualLinksTo
-          occurrences: [ 0, 1 ]
-    # Additional requirements shall be defined in the VNF specific node type (deriving from tosca.nodes.nfv.VNF) corresponding to NS virtual links that need to connect to VnfExtCps
-    interfaces:
-      Vnflcm:
-        type: tosca.interfaces.nfv.Vnflcm
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/metadata.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/metadata.json
new file mode 100644 (file)
index 0000000..60c1943
--- /dev/null
@@ -0,0 +1,304 @@
+{
+  "nodeMetadataList": [
+    {
+      "contactId": "jh0003",
+      "toscaName": "tosca.nodes.Root",
+      "name": "Root",
+      "model": "ETSI SOL001 v2.5.1",
+      "description": "The TOSCA Node Type all other TOSCA base Node Types derive from",
+      "resourceIconPath": "defaulticon",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Abstract"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "Root",
+        "tosca.nodes.Root"
+      ]
+    },
+    {
+      "contactId": "jh0003",
+      "toscaName": "tosca.nodes.nfv.VNF",
+      "name": "VNF",
+      "model": "ETSI SOL001 v2.5.1",
+      "description": "The generic abstract type from which all VNF specific abstract node types shall be derived to form, together with other node types, the TOSCA service template(s) representing the VNFD",
+      "resourceIconPath": "compute",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VNF",
+        "tosca.nodes.nfv.VNF"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Cp",
+      "name": "Cp",
+      "model": "ETSI SOL001 v2.5.1",
+      "description": "Provides information regarding the purpose of the connection point",
+      "contactId": "jh0003",
+      "resourceIconPath": "compute",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "Cp",
+        "tosca.nodes.nfv.Cp"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.VnfExtCp",
+      "name": "VNF External CP",
+      "model": "ETSI SOL001 v2.5.1",
+      "description": "Describes a logical external connection point, exposed by the VNF enabling connection with an external Virtual Link",
+      "contactId": "jh0003",
+      "resourceIconPath": "network",
+      "resourceType": "CP",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VNF External CP",
+        "tosca.nodes.nfv.VnfExtCp"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.VnfVirtualLink",
+      "name": "VnfVirtualLink",
+      "model": "ETSI SOL001 v2.5.1",
+      "contactId": "jh0003",
+      "description": "Describes the information about an internal VNF VL",
+      "resourceIconPath": "network",
+      "resourceType": "VL",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VnfVirtualLink",
+        "tosca.nodes.nfv.VnfVirtualLink"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Vdu.VirtualObjectStorage",
+      "name": "VDU VirtualObjectStorage",
+      "description": "This node type describes the specifications of requirements related to virtual object storage resources",
+      "model": "ETSI SOL001 v2.5.1",
+      "contactId": "jh0003",
+      "resourceIconPath": "objectStorage",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VDU VirtualObjectStorage",
+        "tosca.nodes.nfv.Vdu.VirtualObjectStorage"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Vdu.VirtualFileStorage",
+      "name": "VDU VirtualFileStorage",
+      "description": "This node type describes the specifications of requirements related to virtual file storage resources",
+      "model": "ETSI SOL001 v2.5.1",
+      "contactId": "jh0003",
+      "resourceIconPath": "objectStorage",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VDU VirtualFileStorage",
+        "tosca.nodes.nfv.Vdu.VirtualFileStorage"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Vdu.VirtualBlockStorage",
+      "name": "VDU VirtualBlockStorage",
+      "description": "This node type describes the specifications of requirements related to virtual block storage resources",
+      "model": "ETSI SOL001 v2.5.1",
+      "contactId": "jh0003",
+      "resourceIconPath": "objectStorage",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VDU VirtualBlockStorage",
+        "tosca.nodes.nfv.Vdu.VirtualBlockStorage"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.NsVirtualLink",
+      "name": "NsVirtualLink",
+      "description": "Node definition of Virtual Links",
+      "model": "ETSI SOL001 v2.5.1",
+      "contactId": "jh0003",
+      "resourceIconPath": "network",
+      "resourceType": "VL",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "NsVirtualLink",
+        "tosca.nodes.nfv.NsVirtualLink"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.NS",
+      "name": "NS",
+      "contactId": "jh0003",
+      "description": "ETSI Network Service",
+      "model": "ETSI SOL001 v2.5.1",
+      "resourceIconPath": "network",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Network Elements"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "NS",
+        "tosca.nodes.nfv.NS"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Vdu.Compute",
+      "name": "VDU Compute",
+      "contactId": "jh0003",
+      "description": "Represents a real or virtual machine or server. Information specified on the Compute node will be used to find the machine that fits the given requirements in the cloud available machines. If no sizing information are specified the cloud provider default machine will be used. It is strongly recommended to specify the required CPUs and memory at least.",
+      "model": "ETSI SOL001 v2.5.1",
+      "resourceIconPath": "compute",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VDU Compute",
+        "tosca.nodes.nfv.Vdu.Compute"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Sap",
+      "name": "Sap",
+      "contactId": "jh0003",
+      "description": "Node definition of SAP",
+      "model": "ETSI SOL001 v2.5.1",
+      "resourceIconPath": "network",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "vendorName": "ETSI",
+      "vendorRelease": "2.5.1",
+      "tags": [
+        "Sap",
+        "tosca.nodes.nfv.Sap"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.VduCp",
+      "name": "VDU Cp",
+      "contactId": "jh0003",
+      "description": "Describes network connectivity between a VNFC instance based on this VDU and an internal VL",
+      "model": "ETSI SOL001 v2.5.1",
+      "resourceIconPath": "port",
+      "resourceType": "CP",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Network Elements"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VDU Cp",
+        "tosca.nodes.nfv.VduCp"
+      ]
+    }
+  ]
+}
+
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/nodeTypes.yaml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/nodeTypes.yaml
new file mode 100644 (file)
index 0000000..7f105c4
--- /dev/null
@@ -0,0 +1,408 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+description: ETSI NFV SOL 001 Root node type definitions version 2.5.1
+
+node_types:
+  tosca.nodes.Root:
+    description: The TOSCA Node Type all other TOSCA base Node Types derive from
+    attributes:
+      tosca_id:
+        type: string
+      tosca_name:
+        type: string
+      state:
+        type: string
+    capabilities:
+      feature:
+        type: tosca.capabilities.Node
+    requirements:
+      - dependency:
+          capability: tosca.capabilities.Node
+          node: tosca.nodes.Root
+          relationship: tosca.relationships.DependsOn
+          occurrences: [ 0, UNBOUNDED ]
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+  tosca.nodes.nfv.VNF:
+    derived_from: tosca.nodes.Root
+    description: The generic abstract type from which all VNF specific abstract node types shall be derived to form, together with other node types, the TOSCA service template(s) representing the VNFD
+    properties:
+      descriptor_id: # instead of vnfd_id
+        type: string # GUID
+        description: Globally unique identifier of the VNFD
+        required: true
+      descriptor_version: # instead of vnfd_version
+        type: string
+        description: Identifies the version of the VNFD
+        required: true
+      provider: # instead of vnf_provider
+        type: string
+        description: Provider of the VNF and of the VNFD
+        required: true
+      product_name: # instead of vnf_product_name
+        type: string
+        description: Human readable name for the VNF Product
+        required: true
+      software_version: # instead of vnf_software_version
+        type: string
+        description: Software version of the VNF
+        required: true
+      product_info_name: # instead of vnf_product_info_name
+        type: string
+        description: Human readable name for the VNF Product
+        required: false
+      product_info_description: # instead of vnf_product_info_description
+        type: string
+        description: Human readable description of the VNF Product
+        required: false
+      vnfm_info:
+        type: list
+        required: true
+        description: Identifies VNFM(s) compatible with the VNF
+        entry_schema:
+          type: string
+      localization_languages:
+        type: list
+        description: Information about localization languages of the VNF
+        required: false
+        entry_schema:
+          type: string #IETF RFC 5646 string
+      default_localization_language:
+        type: string #IETF RFC 5646 string
+        description: Default localization language that is instantiated if no information about selected localization language is available
+        required: false
+        #configurable_properties:
+        #type: tosca.datatypes.nfv.VnfConfigurableProperties
+        #description: Describes the configurable properties of the VNF
+        #required: false
+        # derived types are expected to introduce configurable_properties
+        # with its type derived from
+        # tosca.datatypes.nfv.VnfConfigurableProperties
+        #modifiable_attributes:
+        #type: tosca.datatypes.nfv.VnfInfoModifiableAttributes
+        #description: Describes the modifiable attributes of the VNF
+        #required: false
+        # derived types are expected to introduce modifiable_attributes
+        # with its type derived from
+        # tosca.datatypes.nfv.VnfInfoModifiableAttributes
+      lcm_operations_configuration:
+        type: tosca.datatypes.nfv.VnfLcmOperationsConfiguration
+        description: Describes the configuration parameters for the VNF LCM operations
+        required: false
+      monitoring_parameters:
+        type: list
+        entry_schema:
+          type: tosca.datatypes.nfv.VnfMonitoringParameter
+        description: Describes monitoring parameters applicable to the VNF.
+        required: false
+      flavour_id:
+        type: string
+        description: Identifier of the Deployment Flavour within the VNFD
+        required: true
+      flavour_description:
+        type: string
+        description: Human readable description of the DF
+        required: true
+      #vnf_profile:
+      #  type: tosca.datatypes.nfv.VnfProfile
+      #  description: Describes a profile for instantiating VNFs of a particular NS DF according to a specific VNFD and VNF DF
+      #  required: false
+    requirements:
+      - virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+          occurrences: [ 0, 1 ]
+    # Additional requirements shall be defined in the VNF specific node type (deriving from tosca.nodes.nfv.VNF) corresponding to NS virtual links that need to connect to VnfExtCps
+    interfaces:
+      Vnflcm:
+        type: tosca.interfaces.nfv.Vnflcm
+  tosca.nodes.nfv.Cp:
+    derived_from: tosca.nodes.Root
+    description: Provides information regarding the purpose of the connection point
+    properties:
+      layer_protocols:
+        type: list
+        description: Identifies which protocol the connection point uses for connectivity purposes
+        required: true
+        entry_schema:
+          type: string
+          constraints:
+            - valid_values: [ ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire ]
+      role: #Name in ETSI NFV IFA011 v0.7.3: cpRole
+        type: string
+        description: Identifies the role of the port in the context of the traffic flow patterns in the VNF or parent NS
+        required: false
+        constraints:
+          - valid_values: [ root, leaf ]
+      description:
+        type: string
+        description: Provides human-readable information on the purpose of the connection point
+        required: false
+      protocol:
+        type: list
+        description: Provides information on the addresses to be assigned to the connection point(s) instantiated from this Connection Point Descriptor
+        required: false
+        entry_schema:
+          type: tosca.datatypes.nfv.CpProtocolData
+      trunk_mode:
+        type: boolean
+        description: Provides information about whether the CP instantiated from this Cp is in Trunk mode (802.1Q or other), When operating in "trunk mode", the Cp is capable of carrying traffic for several VLANs. Absence of this property implies that trunkMode is not configured for the Cp i.e. It is equivalent to boolean value "false".
+        required: false
+  tosca.nodes.nfv.VnfExtCp:
+    derived_from: tosca.nodes.nfv.Cp
+    description: Describes a logical external connection point, exposed by the VNF enabling connection with an external Virtual Link
+    properties:
+      virtual_network_interface_requirements:
+        type: list
+        description: The actual virtual NIC requirements that is been assigned when instantiating the connection point
+        required: false
+        entry_schema:
+          type: tosca.datatypes.nfv.VirtualNetworkInterfaceRequirements
+    requirements:
+      - external_virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+      - internal_virtual_link: #name in ETSI NFV IFA011 v0.7.3: intVirtualLinkDesc
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+  tosca.nodes.nfv.VnfVirtualLink:
+    derived_from: tosca.nodes.Root
+    description: Describes the information about an internal VNF VL
+    properties:
+      connectivity_type:
+        type: tosca.datatypes.nfv.ConnectivityType
+        description: Specifies the protocol exposed by the VL and the flow pattern supported by the VL
+        required: true
+      description:
+        type: string
+        description: Provides human-readable information on the purpose of the VL
+        required: false
+      test_access:
+        type: list
+        description: Test access facilities available on the VL
+        required: false
+        entry_schema:
+          type: string
+          constraints:
+            - valid_values: [ passive_monitoring, active_loopback ]
+      vl_profile:
+        type: tosca.datatypes.nfv.VlProfile
+        description: Defines additional data for the VL
+        required: true
+      monitoring_parameters:
+        type: list
+        description: Describes monitoring parameters applicable to the VL
+        required: false
+        entry_schema:
+          type: tosca.datatypes.nfv.VirtualLinkMonitoringParameter
+    capabilities:
+      virtual_linkable:
+        type: tosca.capabilities.nfv.VirtualLinkable
+  tosca.nodes.nfv.Vdu.VirtualObjectStorage:
+    derived_from: tosca.nodes.Root
+    description: This node type describes the specifications of requirements related to virtual object storage resources
+    properties:
+      virtual_object_storage_data:
+        type: tosca.datatypes.nfv.VirtualObjectStorageData
+        description: Describes the object  storage characteristics.
+        required: true
+    capabilities:
+      virtual_storage:
+        type: tosca.capabilities.nfv.VirtualStorage
+        description: Defines the capabilities of virtual_storage.
+  tosca.nodes.nfv.Vdu.VirtualFileStorage:
+    derived_from: tosca.nodes.Root
+    description: This node type describes the specifications of requirements related to virtual file storage resources
+    properties:
+      virtual_file_storage_data:
+        type: tosca.datatypes.nfv.VirtualFileStorageData
+        description: Describes the file  storage characteristics.
+        required: true
+    capabilities:
+      virtual_storage:
+        type: tosca.capabilities.nfv.VirtualStorage
+        description: Defines the capabilities of virtual_storage.
+    requirements:
+      - virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+  tosca.nodes.nfv.Vdu.VirtualBlockStorage:
+    derived_from: tosca.nodes.Root
+    description: This node type describes the specifications of requirements related to virtual block storage resources
+    properties:
+      virtual_block_storage_data:
+        type: tosca.datatypes.nfv.VirtualBlockStorageData
+        description: Describes the block storage characteristics.
+        required: true
+      sw_image_data:
+        type: tosca.datatypes.nfv.SwImageData
+        description: Defines information related to a SwImage artifact used by this Vdu.Compute node.
+        required: false # property is required when the node template has an associated artifact of type tosca.artifacts.nfv.SwImage and not required otherwise
+    capabilities:
+      virtual_storage:
+        type: tosca.capabilities.nfv.VirtualStorage
+        description: Defines the capabilities of virtual_storage.
+  tosca.nodes.nfv.NsVirtualLink:
+    derived_from: tosca.nodes.Root
+    description: node definition of Virtual Links
+    properties:
+      vl_profile:
+        type: tosca.datatypes.nfv.NsVlProfile # only covers min/max bitrate requirements
+        description: Specifies instantiation parameters for a virtual link of a particular NS deployment flavour.
+        required: true
+      connectivity_type:
+        type: tosca.datatypes.nfv.ConnectivityType
+        required: true
+      test_access:
+        type: list
+        description: Test access facilities available on the VL
+        required: false
+        entry_schema:
+          type: string
+          constraints:
+            - valid_values: [ passive_monitoring, active_loopback ]
+      description:
+        type: string
+        required: false
+        description: Human readable information on the purpose of the virtual link (e.g. VL for control plane traffic).
+    capabilities:
+      virtual_linkable:
+        type: tosca.capabilities.nfv.VirtualLinkable
+  tosca.nodes.nfv.NS:
+    derived_from: tosca.nodes.Root
+    properties:
+      descriptor_id:
+        type: string # GUID
+        description: Identifier of this NS descriptor
+        required: true
+      designer:
+        type: string
+        description: Identifies the designer of the NSD.
+        required: true
+      version:
+        type: string
+        description: Identifies the version of the NSD.
+        required: true
+      name:
+        type: string
+        description: Provides the human readable name of the NSD.
+        required: true
+      invariant_id:
+        type: string
+        description: Identifies an NSD in a version independent manner. This attribute is invariant across versions of NSD.
+        required: true
+    requirements:
+      - virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+          node: tosca.nodes.nfv.NsVirtualLink
+          occurrences: [ 0, 1 ]
+    interfaces:
+      Nslcm:
+        type: tosca.interfaces.nfv.Nslcm
+  tosca.nodes.nfv.Vdu.Compute:
+    derived_from: tosca.nodes.Root
+    description: Describes the virtual compute part of a VDU which is a construct supporting the description of the deployment and operational behavior of a VNFC
+    properties:
+      name:
+        type: string
+        description: Human readable name of the VDU
+        required: true
+      description:
+        type: string
+        description: Human readable description of the VDU
+        required: true
+      boot_order:
+        type: list # explicit index (boot index) not necessary, contrary to IFA011
+        description: References a node template name from which a valid boot device is created
+        required: false
+        entry_schema:
+          type: string
+      nfvi_constraints:
+        type: list
+        description: Describes constraints on the NFVI for the VNFC instance(s) created from this VDU
+        required: false
+        entry_schema:
+          type: string
+      monitoring_parameters:
+        type: list
+        description: Describes monitoring parameters applicable to a VNFC instantiated from this VDU
+        required: false
+        entry_schema:
+          type: tosca.datatypes.nfv.VnfcMonitoringParameter
+          #configurable_properties:
+          #type: tosca.datatypes.nfv.VnfcConfigurableProperties
+          #required: false
+          # derived types are expected to introduce
+          # configurable_properties with its type derived from
+          # tosca.datatypes.nfv.VnfcConfigurableProperties
+      vdu_profile:
+        type: tosca.datatypes.nfv.VduProfile
+        description: Defines additional instantiation data for the VDU.Compute node
+        required: true
+      sw_image_data:
+        type: tosca.datatypes.nfv.SwImageData
+        description: Defines information related to a SwImage artifact used by this Vdu.Compute node
+        required: false # property is required when the node template has an associated artifact of type tosca.artifacts.nfv.SwImage and not required otherwise
+      boot_data:
+        type: string
+        description: Contains a string or a URL to a file contained in the VNF package used to customize a virtualised compute resource at boot time. The bootData may contain variable parts that are replaced by deployment specific values before being sent to the VIM.
+        required: false
+    capabilities:
+      virtual_compute:
+        type: tosca.capabilities.nfv.VirtualCompute
+        occurrences: [ 1, 1 ]
+      virtual_binding:
+        type: tosca.capabilities.nfv.VirtualBindable
+        occurrences: [ 1, UNBOUNDED ]
+    requirements:
+      - virtual_storage:
+          capability: tosca.capabilities.nfv.VirtualStorage
+          relationship: tosca.relationships.nfv.AttachesTo
+          occurrences: [ 0, UNBOUNDED ]
+  tosca.nodes.nfv.Sap:
+    derived_from: tosca.nodes.nfv.Cp
+    description: node definition of SAP.
+    requirements:
+      - external_virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+      - internal_virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+  tosca.nodes.nfv.VduCp:
+    derived_from: tosca.nodes.nfv.Cp
+    description: describes network connectivity between a VNFC instance based on this VDU and an internal VL
+    properties:
+      bitrate_requirement:
+        type: integer   # in bits per second
+        description: Bitrate requirement in bit per second on this connection point
+        required: false
+        constraints:
+          - greater_or_equal: 0
+      virtual_network_interface_requirements:
+        type: list
+        description: Specifies requirements on a virtual network interface realising the CPs instantiated from this CPD
+        required: false
+        entry_schema:
+          type: tosca.datatypes.nfv.VirtualNetworkInterfaceRequirements
+      order:
+        type: integer
+        description: The order of the NIC on the compute instance (e.g.eth2)
+        required: false
+        constraints:
+          - greater_or_equal: 0
+      vnic_type:
+        type: string
+        description: Describes the type of the virtual network interface realizing the CPs instantiated from this CPD
+        required: false
+        constraints:
+          - valid_values: [ normal, virtio, direct-physical ]
+    requirements:
+      - virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+      - virtual_binding:
+          capability: tosca.capabilities.nfv.VirtualBindable
+          relationship: tosca.relationships.nfv.VirtualBindsTo
+          node: tosca.nodes.nfv.Vdu.Compute
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/root/root.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/root/root.json
deleted file mode 100644 (file)
index 011bc18..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "payloadName": "root.yml",
-  "contactId": "jh0003",
-  "name": "Root",
-  "description": "Represents a generic software component that can be managed and run by a Compute Node Type.",
-  "resourceIconPath": "defaulticon",
-  "model": "ETSI SOL001 v2.5.1",
-  "categories": [
-  {
-    "name": "Generic",
-    "subcategories": [
-      {
-        "name": "Abstract"
-      }
-    ]
-  }
-],
-  "tags": [
-    "Root"
-  ]
-}
\ No newline at end of file
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/root/root.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/root/root.yml
deleted file mode 100644 (file)
index 5dedb78..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 Root node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.Root:
-    description: The TOSCA Node Type all other TOSCA base Node Types derive from
-    attributes:
-      tosca_id:
-        type: string
-      tosca_name:
-        type: string
-      state:
-        type: string
-    capabilities:
-      feature:
-        type: tosca.capabilities.Node
-    requirements:
-      - dependency:
-          capability: tosca.capabilities.Node
-          node: tosca.nodes.Root
-          relationship: tosca.relationships.DependsOn
-          occurrences: [ 0, UNBOUNDED ]
-    interfaces:
-      Standard:
-        type: tosca.interfaces.node.lifecycle.Standard
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/types.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/types.json
deleted file mode 100644 (file)
index fe26e1b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-[
-    "root",
-    "VNF",
-    "Cp",
-    "vnfExtCp",
-    "vnfVirtualLink",
-    "vduVirtualObjectStorage",
-    "vduVirtualFileStorage",
-    "vduVirtualBlockStorage",
-    "NsVirtualLink",
-    "NS",
-    "vduCompute",
-    "Sap",
-    "vduCp"
-]
\ No newline at end of file
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCompute/vduCompute.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCompute/vduCompute.json
deleted file mode 100644 (file)
index 572097d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "payloadName": "vduCompute.yml",
-  "contactId": "jh0003",
-  "name": "VDU Compute",
-  "model": "ETSI SOL001 v2.5.1",
-  "description": "Represents a real or virtual machine or server. Information specified on the Compute node will be used to find the machine that fits the given requirements in the cloud available machines. If no sizing information are specified the cloud provider default machine will be used. It is strongly recommended to specify the required  CPUs and memory at least.",
-  "resourceIconPath": "compute",
-  "categories": [
-  {
-    "name": "Generic",
-    "subcategories": [
-      {
-        "name": "Infrastructure"
-      }
-    ]
-  }
-],
-  "tags": [
-    "VDU Compute"
-  ]
-}
\ No newline at end of file
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCompute/vduCompute.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCompute/vduCompute.yml
deleted file mode 100644 (file)
index 8666e39..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 Vdu Compute node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.Vdu.Compute:
-    derived_from: tosca.nodes.Root
-    description: Describes the virtual compute part of a VDU which is a construct   supporting the description of the deployment and operational behavior of a VNFC
-    properties:
-      name:
-        type: string
-        description: Human readable name of the VDU
-        required: true
-      description:
-        type: string
-        description: Human readable description of the VDU
-        required: true
-      boot_order:
-        type: list # explicit index (boot index) not necessary, contrary to IFA011
-        description: References a node template name from which a valid boot device is created
-        required: false
-        entry_schema:
-          type: string
-      nfvi_constraints:
-        type: list
-        description: Describes constraints on the NFVI for the VNFC instance(s) created from this VDU
-        required: false
-        entry_schema:
-          type: string
-      monitoring_parameters:
-        type: list
-        description: Describes monitoring parameters applicable to a VNFC instantiated from this VDU
-        required: false
-        entry_schema:
-          type: tosca.datatypes.nfv.VnfcMonitoringParameter
-          #configurable_properties:
-          #type: tosca.datatypes.nfv.VnfcConfigurableProperties
-          #required: false
-          # derived types are expected to introduce
-          # configurable_properties with its type derived from
-          # tosca.datatypes.nfv.VnfcConfigurableProperties
-      vdu_profile:
-        type: tosca.datatypes.nfv.VduProfile
-        description: Defines additional instantiation data for the VDU.Compute node
-        required: true
-      sw_image_data:
-        type: tosca.datatypes.nfv.SwImageData
-        description: Defines information related to a SwImage artifact used by this Vdu.Compute node
-        required: false # property is required when the node template has an associated artifact of type tosca.artifacts.nfv.SwImage and not required otherwise
-      boot_data:
-        type: string
-        description: Contains a string or a URL to a file contained in the VNF package used to customize a virtualised compute resource at boot time. The bootData may contain variable parts that are replaced by deployment specific values before being sent to the VIM.
-        required: false
-    capabilities:
-      virtual_compute:
-        type: tosca.capabilities.nfv.VirtualCompute
-        occurrences: [ 1, 1 ]
-      virtual_binding:
-        type: tosca.capabilities.nfv.VirtualBindable
-        occurrences: [ 1, UNBOUNDED ]
-    requirements:
-      - virtual_storage:
-          capability: tosca.capabilities.nfv.VirtualStorage
-          relationship: tosca.relationships.nfv.AttachesTo
-          occurrences: [ 0, UNBOUNDED ]
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCp/vduCp.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCp/vduCp.json
deleted file mode 100644 (file)
index 7fab887..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "payloadName": "vduCp.yml",
-       "contactId": "jh0003",
-       "name": "VDU Cp",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "VDU Cp",
-       "resourceIconPath": "port",
-       "resourceType": "CP",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Network Elements"
-               }]
-       }],
-       "tags": ["VDU Cp"]
-}
\ No newline at end of file
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCp/vduCp.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduCp/vduCp.yml
deleted file mode 100644 (file)
index 51243d1..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 VduCp node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.VduCp:
-    derived_from: tosca.nodes.nfv.Cp
-    description: describes network connectivity between a VNFC instance based on this VDU and an internal VL
-    properties:
-      bitrate_requirement:
-        type: integer   # in bits per second
-        description: Bitrate requirement in bit per second on this connection point
-        required: false
-        constraints:
-          - greater_or_equal: 0
-      virtual_network_interface_requirements:
-        type: list
-        description: Specifies requirements on a virtual network interface realising the CPs instantiated from this CPD
-        required: false
-        entry_schema:
-          type: tosca.datatypes.nfv.VirtualNetworkInterfaceRequirements
-      order:
-        type: integer
-        description: The order of the NIC on the compute instance (e.g.eth2)
-        required: false
-        constraints:
-          - greater_or_equal: 0
-      vnic_type:
-        type: string
-        description: Describes the type of the virtual network interface realizing the CPs instantiated from this CPD
-        required: false
-        constraints:
-          - valid_values: [ normal, virtio, direct-physical ]
-    requirements:
-      - virtual_link:
-          capability: tosca.capabilities.nfv.VirtualLinkable
-          relationship: tosca.relationships.nfv.VirtualLinksTo
-      - virtual_binding:
-          capability: tosca.capabilities.nfv.VirtualBindable
-          relationship: tosca.relationships.nfv.VirtualBindsTo
-          node: tosca.nodes.nfv.Vdu.Compute
\ No newline at end of file
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualBlockStorage/vduVirtualBlockStorage.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualBlockStorage/vduVirtualBlockStorage.json
deleted file mode 100644 (file)
index dd630ee..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "payloadName": "vduVirtualBlockStorage.yml",
-       "contactId": "jh0003",
-       "name": "VDU VirtualBlockStorage",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "VDU VirtualBlockStorage",
-       "resourceIconPath": "objectStorage",
-       "resourceType": "VFC",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Infrastructure"
-               }]
-       }],
-       "tags": ["VDU VirtualBlockStorage"]
-}
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualBlockStorage/vduVirtualBlockStorage.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualBlockStorage/vduVirtualBlockStorage.yml
deleted file mode 100644 (file)
index 68f6b5d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 VirtualBlockStorage node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.Vdu.VirtualBlockStorage:
-    derived_from: tosca.nodes.Root
-    description: This node type describes the specifications of requirements related to virtual block storage resources
-    properties:
-      virtual_block_storage_data:
-        type: tosca.datatypes.nfv.VirtualBlockStorageData
-        description: Describes the block storage characteristics.
-        required: true
-      sw_image_data:
-        type: tosca.datatypes.nfv.SwImageData
-        description: Defines information related to a SwImage artifact used by this Vdu.Compute node.
-        required: false # property is required when the node template has an associated artifact of type tosca.artifacts.nfv.SwImage and not required otherwise
-    capabilities:
-      virtual_storage:
-        type: tosca.capabilities.nfv.VirtualStorage
-        description: Defines the capabilities of virtual_storage.
\ No newline at end of file
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualFileStorage/vduVirtualFileStorage.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualFileStorage/vduVirtualFileStorage.json
deleted file mode 100644 (file)
index 845db12..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "payloadName": "vduVirtualFileStorage.yml",
-       "contactId": "jh0003",
-       "name": "VDU VirtualFileStorage",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "VDU VirtualFileStorage",
-       "resourceIconPath": "objectStorage",
-       "resourceType": "VFC",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Infrastructure"
-               }]
-       }],
-       "tags": ["VDU VirtualFileStorage"]
-}
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualFileStorage/vduVirtualFileStorage.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualFileStorage/vduVirtualFileStorage.yml
deleted file mode 100644 (file)
index af3271a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 VirtualFileStorage node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.Vdu.VirtualFileStorage:
-    derived_from: tosca.nodes.Root
-    description: This node type describes the specifications of requirements related to virtual file storage resources
-    properties:
-      virtual_file_storage_data:
-        type: tosca.datatypes.nfv.VirtualFileStorageData
-        description: Describes the file  storage characteristics.
-        required: true
-    capabilities:
-      virtual_storage:
-        type: tosca.capabilities.nfv.VirtualStorage
-        description: Defines the capabilities of virtual_storage.
-    requirements:
-      - virtual_link:
-          capability: tosca.capabilities.nfv.VirtualLinkable
-          relationship: tosca.relationships.nfv.VirtualLinksTo
-          #description: Describes the requirements for linking to virtual link
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualObjectStorage/vduVirtualObjectStorage.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualObjectStorage/vduVirtualObjectStorage.json
deleted file mode 100644 (file)
index 6a8e20a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "payloadName": "vduVirtualObjectStorage.yml",
-       "contactId": "jh0003",
-       "name": "VDU VirtualObjectStorage",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "VDU VirtualObjectStorage",
-       "resourceIconPath": "objectStorage",
-       "resourceType": "VFC",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Infrastructure"
-               }]
-       }],
-       "tags": ["VDU VirtualObjectStorage"]
-}
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualObjectStorage/vduVirtualObjectStorage.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vduVirtualObjectStorage/vduVirtualObjectStorage.yml
deleted file mode 100644 (file)
index 60bec09..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 VirtualObjectStorage node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.Vdu.VirtualObjectStorage:
-    derived_from: tosca.nodes.Root
-    description: This node type describes the specifications of requirements related to virtual object storage resources
-    properties:
-      virtual_object_storage_data:
-        type: tosca.datatypes.nfv.VirtualObjectStorageData
-        description: Describes the object  storage characteristics.
-        required: true
-    capabilities:
-      virtual_storage:
-        type: tosca.capabilities.nfv.VirtualStorage
-        description: Defines the capabilities of virtual_storage.
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfExtCp/vnfExtCp.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfExtCp/vnfExtCp.json
deleted file mode 100644 (file)
index 2397c1e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "payloadName": "vnfExtCp.yml",
-       "contactId": "jh0003",
-       "name": "VNF External CP",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "VNF External CP",
-       "resourceIconPath": "network",
-       "resourceType": "CP",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Infrastructure"
-               }]
-       }],
-       "tags": ["VNF External CP"]
-}
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfExtCp/vnfExtCp.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfExtCp/vnfExtCp.yml
deleted file mode 100644 (file)
index 2fedc7a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 VnfExtCp node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.VnfExtCp:
-    derived_from: tosca.nodes.nfv.Cp
-    description: Describes a logical external connection point, exposed by the VNF enabling connection with an external Virtual Link
-    properties:
-      virtual_network_interface_requirements:
-        type: list
-        description: The actual virtual NIC requirements that is been assigned when instantiating the connection point
-        required: false
-        entry_schema:
-          type: tosca.datatypes.nfv.VirtualNetworkInterfaceRequirements
-    requirements:
-      - external_virtual_link:
-          capability: tosca.capabilities.nfv.VirtualLinkable
-          relationship: tosca.relationships.nfv.VirtualLinksTo
-      - internal_virtual_link: #name in ETSI NFV IFA011 v0.7.3: intVirtualLinkDesc
-          capability: tosca.capabilities.nfv.VirtualLinkable
-          relationship: tosca.relationships.nfv.VirtualLinksTo
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfVirtualLink/vnfVirtualLink.json b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfVirtualLink/vnfVirtualLink.json
deleted file mode 100644 (file)
index 3a56bff..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-       "payloadName": "vnfVirtualLink.yml",
-       "contactId": "jh0003",
-       "name": "VnfVirtualLink",
-       "model": "ETSI SOL001 v2.5.1",
-       "description": "VnfVirtualLink",
-       "resourceIconPath": "network",
-       "resourceType": "VL",
-       "categories": [{
-               "name": "Generic",
-               "subcategories": [{
-                       "name": "Infrastructure"
-               }]
-       }],
-       "tags": ["VnfVirtualLink"]
-}
\ No newline at end of file
diff --git a/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfVirtualLink/vnfVirtualLink.yml b/catalog-be/src/main/resources/import/tosca/models/init/etsi-SOL001-v2.5.1/tosca/node-types/vnfVirtualLink/vnfVirtualLink.yml
deleted file mode 100644 (file)
index 76addca..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_2
-description: ETSI NFV SOL 001 VnfVirtualLink node type definitions version 2.5.1
-
-node_types:
-  tosca.nodes.nfv.VnfVirtualLink:
-    derived_from: tosca.nodes.Root
-    description: Describes the information about an internal VNF VL
-    properties:
-      connectivity_type:
-        type: tosca.datatypes.nfv.ConnectivityType
-        description: Specifies the protocol exposed by the VL and the flow pattern supported by the VL
-        required: true
-      description:
-        type: string
-        description: Provides human-readable information on the purpose of the VL
-        required: false
-      test_access:
-        type: list
-        description: Test access facilities available on the VL
-        required: false
-        entry_schema:
-          type: string
-          constraints:
-            - valid_values: [ passive_monitoring, active_loopback ]
-      vl_profile:
-        type: tosca.datatypes.nfv.VlProfile
-        description: Defines additional data for the VL
-        required: true
-      monitoring_parameters:
-        type: list
-        description: Describes monitoring parameters applicable to the VL
-        required: false
-        entry_schema:
-          type: tosca.datatypes.nfv.VirtualLinkMonitoringParameter
-    capabilities:
-      virtual_linkable:
-        type: tosca.capabilities.nfv.VirtualLinkable
\ No newline at end of file
index 17ef9af..2508d9d 100644 (file)
@@ -12,8 +12,11 @@ def debug(desc, *args):
         print(desc, join_strings(args))
 
 
-def log(desc, arg):
-    print(desc, arg)
+def log(desc, arg=None):
+    if arg:
+        print(desc, arg)
+    else:
+        print(desc)
 
 
 def print_and_exit(error_code, error_desc):
index 56fe2b4..9304c88 100644 (file)
@@ -31,13 +31,13 @@ def print_and_check_results(results, update_version, exit_on_success=False):
         for result in results:
             print_name_and_return_code(result[0], result[1], with_line=False)
         print("----------------------------------------")
-        check_results_and_exit(results, update_version, exit_on_success)
+        check_results_and_exit(results, exit_on_success)
     else:
         raise ResourceCreationError("Results is none -> error occurred!!", 1)
 
 
-def check_results_and_exit(results, update_version, exit_on_success):
-    if not _results_ok(results, _get_response_code(update_version)):
+def check_results_and_exit(results, exit_on_success):
+    if not _results_ok(results, _get_response_code()):
         raise ResourceCreationError("Failed to create the normatives types !!", 1)
     else:
         if exit_on_success:
@@ -46,7 +46,7 @@ def check_results_and_exit(results, update_version, exit_on_success):
 
 def _create_normatives_type(file_dir, sdc_be_proxy, types, update_version):
     results = []
-    response_codes = _get_response_code(update_version)
+    response_codes = _get_response_code()
     for normative_type in types:
         result = _send_request(sdc_be_proxy, file_dir, normative_type, update_version)
         results.append(result)
@@ -113,7 +113,7 @@ def _results_ok(results, response_codes):
     return True
 
 
-def _get_response_code(update_version):
+def _get_response_code():
     response_codes = [200, 201, 409]
     return response_codes
 
index 39e802b..db6e914 100644 (file)
@@ -10,6 +10,7 @@ from sdcBePy.tosca.models import normativeElementsList
 from sdcBePy.tosca.models import normativeTypesList
 from sdcBePy.tosca.models.model_client import ModelClient
 from sdcBePy.tosca.models.model_import_manager import ModelImportManager
+from sdcBePy.tosca.models.node_type_client import NodeTypeClient
 
 
 def main(sdc_be_proxy, update_version):
@@ -24,7 +25,8 @@ def main(sdc_be_proxy, update_version):
         process_type_list(normativeTypesList.get_normative_type_candidate_list(base_file_location), sdc_be_proxy, update_version)
         process_element_list(normativeElementsList.get_normative_element_with_metadata_list(base_file_location), sdc_be_proxy)
         #Add model based normatives
-        model_import_manager = ModelImportManager(Path(base_file_location) / 'models', ModelClient(sdc_be_proxy))
+        model_import_manager = ModelImportManager(Path(base_file_location) / 'models', ModelClient(sdc_be_proxy),
+                                                  NodeTypeClient(sdc_be_proxy))
         model_import_manager.deploy_models()
     except Exception as ex:
         logger.log("An error has occurred while uploading elements and types: ", str(ex))
index 88128ea..8ba05f6 100644 (file)
@@ -23,7 +23,9 @@ import pycurl
 
 from sdcBePy.common import logger
 from sdcBePy.common.normative.main import process_element_list, process_type_list
-from sdcBePy.tosca.models.normativeElementsList import get_normative_element_candidate_list, get_normative_element_with_metadata_list
+from sdcBePy.tosca.models.normativeElementsList import get_normative_element_candidate_list, \
+    get_normative_element_with_metadata_list
+
 
 class ModelClient:
 
@@ -86,8 +88,7 @@ class ModelClient:
             process_element_list(get_normative_element_candidate_list(tosca_elements_import_path), self.__sdc_be_proxy, model=model_name)
         logger.log("Finished importing normative elements for model", model_name)
 
-    def import_model_types(self, model_payload_dict, types_list, upgrade):
-        model_name = model_payload_dict['name']
+    def import_model_types(self, model_name, types_list, upgrade):
         logger.debug("Starting import of normative types for model '{}'".format(model_name))
         process_type_list(types_list, self.__sdc_be_proxy, upgrade)
         logger.log("Finished importing normative types for model", model_name)
index 57b0f13..57ac06d 100644 (file)
@@ -19,6 +19,7 @@ import json
 import os
 import zipfile
 from sdcBePy.tosca.models.normativeTypeCandidate import NormativeTypeCandidate
+from sdcBePy.common import logger
 from pathlib import Path
 
 
@@ -32,37 +33,41 @@ class ModelImportManager:
     ACTION_INIT = 'init'
     TYPES_FOLDER = 'tosca'
     NODE_FOLDER = 'node-types'
+    NODE_TYPE_FILE = 'nodeTypes.yaml'
 
-    def __init__(self, model_imports_path, model_client):
+    def __init__(self, model_imports_path, model_client, node_type_client):
         self.__model_base_path = model_imports_path
         self.__model_init_path = self.__model_base_path / self.INIT_FOLDER_NAME
         self.__model_upgrade_path = self.__model_base_path / self.UPGRADE_FOLDER_NAME
         self.__model_client = model_client
+        self.__node_type_client = node_type_client
 
     def deploy_models(self):
         existing_models = self.__model_client.get_model_list()
         for model_folder_name in self.__get_model_init_list():
             model_payload_dict = self.__read_model_payload(model_folder_name, self.ACTION_INIT)
-            if (not existing_models or not any(m for m in existing_models if model_payload_dict['name'] == m['name'])):
+            if not existing_models or not any(m for m in existing_models if model_payload_dict['name'] == m['name']):
                 self.__create_models(model_folder_name, model_payload_dict)
 
         for model_folder_name in self.__get_model_upgrade_list():
             model_payload_dict = self.__read_model_payload(model_folder_name, self.ACTION_UPGRADE)
-            if (existing_models and any(m for m in existing_models if model_payload_dict['name'] == m['name'])):
+            if existing_models and any(m for m in existing_models if model_payload_dict['name'] == m['name']):
                 self.__update_models(model_folder_name, model_payload_dict)
 
     def __create_models(self, model_folder_name, model_payload_dict):
+        logger.log('Creating model {}, based on folder {}'.format(model_payload_dict['name'], model_folder_name))
         model_imports_zip_path = self.__zip_model_imports(model_folder_name, self.ACTION_INIT)
         self.__model_client.create_model(model_payload_dict, model_imports_zip_path)
         self.__init_model_non_node_types(model_folder_name, model_payload_dict)
-        self.__init_model_node_types(model_folder_name, model_payload_dict)
-        self.__init_model_non_node_types(model_folder_name, model_payload_dict, True);
+        self.__init_model_node_types(model_folder_name, model_payload_dict['name'])
+        self.__init_model_non_node_types(model_folder_name, model_payload_dict, True)
 
     def __update_models(self, model_folder_name, model_payload_dict):
+        logger.log('Updating model {}, based on folder {}'.format(model_payload_dict['name'], model_folder_name))
         model_imports_zip_path = self.__zip_model_imports(model_folder_name, self.ACTION_UPGRADE)
         self.__model_client.update_model_imports(model_payload_dict, model_imports_zip_path)
         self.__upgrade_model_non_node_types(model_folder_name, model_payload_dict)
-        self.__upgrade_model_node_types(model_folder_name, model_payload_dict)
+        self.__upgrade_model_node_types(model_folder_name, model_payload_dict['name'])
         self.__upgrade_model_non_node_types(model_folder_name, model_payload_dict, True)
 
     def __get_model_init_list(self):
@@ -118,6 +123,8 @@ class ModelImportManager:
         return self.__model_init_path if action_type == self.INIT_FOLDER_NAME else self.__model_upgrade_path
 
     def __get_tosca_path(self, action, model):
+        if action not in [self.ACTION_INIT, self.ACTION_UPGRADE]:
+            raise Exception("Invalid action {}. Expected {}".format(action, [self.ACTION_INIT, self.ACTION_UPGRADE]))
         return self.__get_base_action_path(action) / model / self.TYPES_FOLDER
 
     def __init_model_non_node_types(self, model, model_payload_dict, with_metadata=False):
@@ -130,12 +137,38 @@ class ModelImportManager:
         if os.path.isdir(path):
             self.__model_client.import_model_elements(model_payload_dict, str(os.path.join(path, '')), with_metadata)
 
-    def __init_model_node_types(self, model, model_payload_dict, upgrade=False):
-        path = self.__get_tosca_path(self.ACTION_INIT, model) / self.NODE_FOLDER
-        if os.path.isdir(path):
-            self.__model_client.import_model_types(model_payload_dict, self.__get_node_type_list(path), upgrade)
+    def __init_model_node_types(self, model_folder_name, model_name):
+        self.__import_model_node_types(model_folder_name, model_name, self.ACTION_INIT)
 
-    def __upgrade_model_node_types(self, model, model_payload_dict, upgrade=True):
-        path = self.__get_tosca_path(self.ACTION_UPGRADE, model) / self.NODE_FOLDER
-        if os.path.isdir(path):
-            self.__model_client.import_model_types(model_payload_dict, self.__get_node_type_list(path), upgrade)
+    def __upgrade_model_node_types(self, model_folder_name, model_name):
+        self.__import_model_node_types(model_folder_name, model_name, self.ACTION_UPGRADE)
+
+    def __import_model_node_types(self, model_folder_name, model_name, action):
+        path = self.__get_tosca_path(action, model_folder_name) / self.NODE_FOLDER
+        if not os.path.isdir(path):
+            return
+
+        payload_json_path = self.__get_node_types_metadata_file_path(model_name, path)
+        payload_json_str = json.dumps(json.load(open(payload_json_path)))
+
+        node_types_yaml_path = self.__get_node_types_yaml_file_path(model_name, path)
+
+        is_update = True if action == self.ACTION_UPGRADE else False
+
+        self.__node_type_client.import_all(node_types_yaml_path, payload_json_str, is_update)
+
+    def __get_node_types_metadata_file_path(self, model_name, node_types_folder):
+        metadata_json_path = node_types_folder / 'metadata.json'
+        if not os.path.isfile(metadata_json_path):
+            error_msg = "Missing metadata.json file for model '{}'. Expected path '{}'".format(model_name,
+                                                                                               metadata_json_path)
+            raise Exception(error_msg)
+        return metadata_json_path
+
+    def __get_node_types_yaml_file_path(self, model_name, node_types_folder):
+        node_types_yaml_path = node_types_folder / self.NODE_TYPE_FILE
+        if not os.path.isfile(node_types_yaml_path):
+            error_msg = "Missing {} file for model '{}'. Expected path '{}'".format(self.NODE_TYPE_FILE, model_name,
+                                                                                    node_types_yaml_path)
+            raise Exception(error_msg)
+        return node_types_yaml_path
diff --git a/catalog-be/src/main/resources/scripts/sdcBePy/tosca/models/node_type_client.py b/catalog-be/src/main/resources/scripts/sdcBePy/tosca/models/node_type_client.py
new file mode 100644 (file)
index 0000000..7937002
--- /dev/null
@@ -0,0 +1,75 @@
+#  -
+#   ============LICENSE_START=======================================================
+#   Copyright (C) 2021 Nordix Foundation.
+#   ================================================================================
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+#   SPDX-License-Identifier: Apache-2.0
+#   ============LICENSE_END=========================================================
+#
+#        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========================================================
+
+from io import BytesIO
+from pathlib import Path
+
+import pycurl
+
+from sdcBePy.common import logger
+
+
+class NodeTypeClient:
+
+    def __init__(self, sdc_be_proxy):
+        self.__base_path = Path('/sdc2/rest/v1/catalog/upload')
+        self.__import_all_path = self.__base_path / 'resource/import'
+        self.__sdc_be_proxy = sdc_be_proxy
+
+    def import_all(self, node_type_yaml_path, node_type_metadata_json_str, is_update=False):
+        logger.debug("Starting to import node types '{}'".format(node_type_yaml_path))
+
+        multi_part_form_data = []
+
+        node_type_yaml_param = ('nodeTypesYaml', (pycurl.FORM_FILE, str(node_type_yaml_path)))
+        multi_part_form_data.append(node_type_yaml_param)
+
+        node_type_metadata_json_param = ('nodeTypeMetadataJson', (
+            pycurl.FORM_CONTENTS, node_type_metadata_json_str,
+            pycurl.FORM_CONTENTTYPE, 'application/json'
+        ))
+        multi_part_form_data.append(node_type_metadata_json_param)
+
+        if is_update is not None:
+            create_new_version_param = ('createNewVersion', (
+                pycurl.FORM_CONTENTS, str(is_update).lower(),
+                pycurl.FORM_CONTENTTYPE, 'text/plain'
+            ))
+            multi_part_form_data.append(create_new_version_param)
+
+        response_buffer = BytesIO()
+        response_code = self.__sdc_be_proxy.post_file(str(self.__import_all_path), multi_part_form_data,
+                                                      response_buffer)
+        logger.debug("Import all node types response code '{}'".format(response_code))
+        if response_code != 201:
+            error_msg = "Failed to import node types '{}'".format(node_type_yaml_path)
+            logger.log(error_msg, response_buffer.getvalue())
+            raise Exception(error_msg)
+        logger.log("Failed to import node types '{}'".format(node_type_yaml_path))
+
index 663d27b..6af4492 100644 (file)
@@ -9,6 +9,7 @@ from sdcBePy.common.normative.main import process_element_list, process_type_lis
 from sdcBePy.tosca.main import parse_and_create_proxy
 from sdcBePy.tosca.models.model_client import ModelClient
 from sdcBePy.tosca.models.model_import_manager import ModelImportManager
+from sdcBePy.tosca.models.node_type_client import NodeTypeClient
 from sdcBePy.tosca.models.normativeElementsList import get_normative_element_candidate_list, \
     get_normative_element_with_metadata_list
 from sdcBePy.tosca.models.normativeToUpdateList import TypesToUpdate, get_heat_and_normative_to_update_list, \
@@ -25,7 +26,8 @@ def main(sdc_be_proxy):
     base_file_location = os.getcwd() + "/"
     logger.debug("working directory =" + base_file_location)
 
-    model_import_manager = ModelImportManager(Path(base_file_location) / 'models', ModelClient(sdc_be_proxy))
+    model_import_manager = ModelImportManager(Path(base_file_location) / 'models', ModelClient(sdc_be_proxy),
+                                              NodeTypeClient(sdc_be_proxy))
     try:
         model_import_manager.deploy_models()
     except Exception as ex:
index 1609299..40c9b43 100644 (file)
@@ -32,20 +32,23 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import fj.data.Either;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
-import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
 import org.mockito.stubbing.Answer;
 import org.openecomp.sdc.be.auditing.impl.AuditingManager;
 import org.openecomp.sdc.be.components.impl.ImportUtils;
@@ -61,6 +64,7 @@ import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction;
 import org.openecomp.sdc.be.config.Configuration;
 import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
 import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
@@ -68,6 +72,8 @@ import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.model.CapabilityDefinition;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.NodeTypeMetadata;
+import org.openecomp.sdc.be.model.NodeTypesMetadataList;
 import org.openecomp.sdc.be.model.PropertyConstraint;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.RequirementDefinition;
@@ -88,34 +94,23 @@ import org.openecomp.sdc.common.impl.FSConfigurationSource;
 import org.openecomp.sdc.exception.PolicyException;
 import org.openecomp.sdc.exception.ResponseFormat;
 
-import fj.data.Either;
-
 public class ResourceImportManagerTest {
 
-    static ResourceImportManager importManager;
-    static AuditingManager auditingManager = Mockito.mock(AuditingManager.class);
-    static ResponseFormatManager responseFormatManager = Mockito.mock(ResponseFormatManager.class);
-    static ResourceBusinessLogic resourceBusinessLogic = Mockito.mock(ResourceBusinessLogic.class);
-    static InterfaceOperationBusinessLogic interfaceOperationBusinessLogic = Mockito.mock(InterfaceOperationBusinessLogic.class);
-    static InterfaceDefinitionHandler interfaceDefinitionHandler =
-        new InterfaceDefinitionHandler(interfaceOperationBusinessLogic);
-
-    static UserBusinessLogic userAdmin = Mockito.mock(UserBusinessLogic.class);
-    static ToscaOperationFacade toscaOperationFacade =  Mockito.mock(ToscaOperationFacade.class);
+    private ResourceImportManager importManager;
 
-    protected static final ComponentsUtils componentsUtils = Mockito.mock(ComponentsUtils.class);
-    private static final CapabilityTypeOperation capabilityTypeOperation = Mockito.mock(CapabilityTypeOperation.class);
+    private final AuditingManager auditingManager = mock(AuditingManager.class);
+    private final ResponseFormatManager responseFormatManager = mock(ResponseFormatManager.class);
+    private final ResourceBusinessLogic resourceBusinessLogic = mock(ResourceBusinessLogic.class);
+    private final InterfaceOperationBusinessLogic interfaceOperationBusinessLogic = mock(InterfaceOperationBusinessLogic.class);
+    private final InterfaceDefinitionHandler interfaceDefinitionHandler = new InterfaceDefinitionHandler(interfaceOperationBusinessLogic);
+    private final JanusGraphDao janusGraphDao = mock(JanusGraphDao.class);
+    private final UserBusinessLogic userAdmin = mock(UserBusinessLogic.class);
+    private final ToscaOperationFacade toscaOperationFacade =  mock(ToscaOperationFacade.class);
+    private final ComponentsUtils componentsUtils = mock(ComponentsUtils.class);
+    private final CapabilityTypeOperation capabilityTypeOperation = mock(CapabilityTypeOperation.class);
 
     @BeforeAll
     public static void beforeClass() {
-        importManager = new ResourceImportManager(componentsUtils, capabilityTypeOperation, interfaceDefinitionHandler);
-        importManager.setAuditingManager(auditingManager);
-        when(toscaOperationFacade.getLatestByToscaResourceName(Mockito.anyString(), Mockito.any())).thenReturn(Either.left(null));
-        when(toscaOperationFacade.getLatestByToscaResourceNameAndModel(Mockito.anyString(), Mockito.any())).thenReturn(Either.left(null));
-        importManager.setResponseFormatManager(responseFormatManager);
-        importManager.setResourceBusinessLogic(resourceBusinessLogic);
-        importManager.setToscaOperationFacade(toscaOperationFacade);
-        
         String appConfigDir = "src/test/resources/config/catalog-be";
         ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
         final ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
@@ -127,7 +122,13 @@ public class ResourceImportManagerTest {
 
     @BeforeEach
     public void beforeTest() {
-        Mockito.reset(auditingManager, responseFormatManager, resourceBusinessLogic, userAdmin);
+        importManager = new ResourceImportManager(componentsUtils, capabilityTypeOperation, interfaceDefinitionHandler, janusGraphDao);
+        importManager.setAuditingManager(auditingManager);
+        when(toscaOperationFacade.getLatestByToscaResourceName(anyString(), any())).thenReturn(Either.left(null));
+        when(toscaOperationFacade.getLatestByToscaResourceNameAndModel(anyString(), any())).thenReturn(Either.left(null));
+        importManager.setResponseFormatManager(responseFormatManager);
+        importManager.setResourceBusinessLogic(resourceBusinessLogic);
+        importManager.setToscaOperationFacade(toscaOperationFacade);
         Either<Component, StorageOperationStatus> notFound = Either.right(StorageOperationStatus.NOT_FOUND);
         when(toscaOperationFacade.getComponentByNameAndVendorRelease(any(ComponentTypeEnum.class), anyString(), anyString(),
             any(JsonParseFlagEnum.class), any())).thenReturn(notFound);
@@ -142,13 +143,14 @@ public class ResourceImportManagerTest {
         user.setRole("ADMIN");
         user.setFirstName("Jhon");
         user.setLastName("Doh");
-        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+        when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
 
         setResourceBusinessLogicMock();
 
         String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-blockStorage.yml");
 
-        ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+        ImmutablePair<Resource, ActionStatus> createResource =
+            importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
         Resource resource = createResource.left;
 
         testSetConstantMetaData(resource);
@@ -157,15 +159,74 @@ public class ResourceImportManagerTest {
         testSetDerivedFrom(resource);
         testSetProperties(resource);
 
-        Mockito.verify(resourceBusinessLogic, Mockito.times(1)).propagateStateToCertified(eq(user), eq(resource), Mockito.any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
+        verify(resourceBusinessLogic).propagateStateToCertified(eq(user), eq(resource), any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
+    }
+
+    @Test
+    void importAllNormativeResourceSuccessTest() {
+        final List<NodeTypeMetadata> nodeMetadataList = new ArrayList<>();
+        var nodeTypeMetadata1 = new NodeTypeMetadata();
+        nodeTypeMetadata1.setToscaName("my.tosca.Type");
+        nodeMetadataList.add(nodeTypeMetadata1);
+        var nodeTypeMetadata2 = new NodeTypeMetadata();
+        nodeTypeMetadata2.setToscaName("my.tosca.not.in.the.Yaml");
+        nodeMetadataList.add(nodeTypeMetadata2);
+        var nodeTypesMetadataList = new NodeTypesMetadataList();
+        nodeTypesMetadataList.setNodeMetadataList(nodeMetadataList);
+        var user = new User();
+        var yaml = "node_types:\n"
+            + "  my.tosca.Type:\n"
+            + "    description: a description";
+
+        when(toscaOperationFacade.getLatestByName(any(), any())).thenReturn(Either.left(null));
+        when(resourceBusinessLogic
+            .createOrUpdateResourceByImport(any(Resource.class), any(User.class), eq(true), eq(true), eq(false), eq(null), eq(null), eq(false)))
+            .thenReturn(new ImmutablePair<>(new Resource(), ActionStatus.OK));
+
+        importManager.importAllNormativeResource(yaml, nodeTypesMetadataList, user, false, false);
+        verify(janusGraphDao).commit();
+    }
+
+    @Test
+    void importAllNormativeResourceTest_invalidYaml() {
+        var invalidYaml = "node_types: my.tosca.Type:";
+
+        final ByActionStatusComponentException actualException = assertThrows(ByActionStatusComponentException.class,
+            () -> importManager.importAllNormativeResource(invalidYaml, new NodeTypesMetadataList(), new User(), false, false));
+        assertEquals(ActionStatus.INVALID_NODE_TYPES_YAML, actualException.getActionStatus());
+    }
+
+    @Test
+    void importAllNormativeResourceTest_exceptionDuringImportShouldTriggerRolback() {
+        when(responseFormatManager.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(mock(ResponseFormat.class));
+        when(toscaOperationFacade.getLatestByName(any(), any())).thenThrow(new RuntimeException());
+
+        final List<NodeTypeMetadata> nodeMetadataList = new ArrayList<>();
+        var nodeTypeMetadata1 = new NodeTypeMetadata();
+        nodeTypeMetadata1.setToscaName("my.tosca.Type");
+        nodeMetadataList.add(nodeTypeMetadata1);
+        var nodeTypeMetadata2 = new NodeTypeMetadata();
+        nodeTypeMetadata2.setToscaName("my.tosca.not.in.the.Yaml");
+        nodeMetadataList.add(nodeTypeMetadata2);
+        var nodeTypesMetadataList = new NodeTypesMetadataList();
+        nodeTypesMetadataList.setNodeMetadataList(nodeMetadataList);
+        var user = new User();
+        var yaml = "node_types:\n"
+            + "  my.tosca.Type:\n"
+            + "    description: a description";
+
+        assertThrows(ComponentException.class,
+            () -> importManager.importAllNormativeResource(yaml, nodeTypesMetadataList, user, false, false));
+        verify(janusGraphDao).rollback();
     }
 
+
     @Test()
     void testResourceCreationFailed() {
         UploadResourceInfo resourceMD = createDummyResourceMD();
         User user = new User();
         user.setUserId(resourceMD.getContactId());
-        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+        when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
         ResponseFormat dummyResponseFormat = createGeneralErrorInfo();
 
         when(responseFormatManager.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(dummyResponseFormat);
@@ -174,15 +235,17 @@ public class ResourceImportManagerTest {
         String jsonContent = "this is an invalid yml!";
         ComponentException errorInfoFromTest = null;
         try {
-            importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+            importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
         }catch (ComponentException e){
             errorInfoFromTest = e;
         }
         assertNotNull(errorInfoFromTest);
         assertEquals(ActionStatus.GENERAL_ERROR, errorInfoFromTest.getActionStatus());
 
-        Mockito.verify(resourceBusinessLogic, Mockito.times(0)).createOrUpdateResourceByImport(Mockito.any(Resource.class), eq(user), eq(true), eq(false), eq(true), eq(null), eq(null), eq(false));
-        Mockito.verify(resourceBusinessLogic, Mockito.times(0)).propagateStateToCertified(eq(user), Mockito.any(Resource.class), Mockito.any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
+        verify(resourceBusinessLogic, times(0))
+            .createOrUpdateResourceByImport(any(Resource.class), eq(user), eq(true), eq(false), eq(true), eq(null), eq(null), eq(false));
+        verify(resourceBusinessLogic, times(0))
+            .propagateStateToCertified(eq(user), any(Resource.class), any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
     }
 
     @Test
@@ -190,34 +253,37 @@ public class ResourceImportManagerTest {
         UploadResourceInfo resourceMD = createDummyResourceMD();
         User user = new User();
         user.setUserId(resourceMD.getContactId());
-        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+        when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
 
         setResourceBusinessLogicMock();
 
         String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-webServer.yml");
 
-        ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+        ImmutablePair<Resource, ActionStatus> createResource =
+            importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
         Resource resource = createResource.left;
         testSetCapabilities(resource);
 
-        Mockito.verify(resourceBusinessLogic, Mockito.times(1)).propagateStateToCertified(eq(user), eq(resource), Mockito.any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
-        Mockito.verify(resourceBusinessLogic, Mockito.times(1)).createOrUpdateResourceByImport(resource, user, true, false, true, null, null, false);
+        verify(resourceBusinessLogic)
+            .propagateStateToCertified(eq(user), eq(resource), any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false));
+        verify(resourceBusinessLogic).createOrUpdateResourceByImport(resource, user, true, false, true, null, null, false);
 
     }
 
     @Test
-    void testResourceCreationWithRequirments() throws IOException {
+    void testResourceCreationWithRequirements() throws IOException {
         UploadResourceInfo resourceMD = createDummyResourceMD();
         User user = new User();
         user.setUserId(resourceMD.getContactId());
-        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+        when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
 
         setResourceBusinessLogicMock();
 
         String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-port.yml");
 
-        ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
-        testSetRequirments(createResource.left);
+        ImmutablePair<Resource, ActionStatus> createResource =
+            importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
+        testSetRequirements(createResource.left);
 
     }
 
@@ -226,7 +292,7 @@ public class ResourceImportManagerTest {
         UploadResourceInfo resourceMD = createDummyResourceMD();
         User user = new User();
         user.setUserId(resourceMD.getContactId());
-        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+        when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
 
         setResourceBusinessLogicMock();
 
@@ -241,8 +307,8 @@ public class ResourceImportManagerTest {
         interfaceTypes.put("tosca.interfaces.node.lifecycle.standard", interfaceDefinition);
                when(interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes(any())).thenReturn(Either.left(interfaceTypes));
 
-        final ImmutablePair<Resource, ActionStatus> createResource = importManager
-            .importNormativeResource(jsonContent, resourceMD, user, true, true);
+        final ImmutablePair<Resource, ActionStatus> createResource =
+            importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
         assertSetInterfaceImplementation(createResource.left);
     }
 
@@ -251,7 +317,7 @@ public class ResourceImportManagerTest {
         UploadResourceInfo resourceMD = createDummyResourceMD();
         User user = new User();
         user.setUserId(resourceMD.getContactId());
-        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+        when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
 
         setResourceBusinessLogicMock();
 
@@ -266,7 +332,8 @@ public class ResourceImportManagerTest {
         interfaceTypes.put("tosca.interfaces.node.lifecycle.standard", interfaceDefinition);
                when(interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes(any())).thenReturn(Either.left(interfaceTypes));
 
-        ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+        ImmutablePair<Resource, ActionStatus> createResource =
+            importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
         assertNull(createResource.left.getInterfaces());
     }
 
@@ -275,7 +342,7 @@ public class ResourceImportManagerTest {
         UploadResourceInfo resourceMD = createDummyResourceMD();
         User user = new User();
         user.setUserId(resourceMD.getContactId());
-        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+        when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
 
         setResourceBusinessLogicMock();
 
@@ -290,7 +357,8 @@ public class ResourceImportManagerTest {
         interfaceTypes.put("tosca.interfaces.node.lifecycle.standard", interfaceDefinition);
                when(interfaceOperationBusinessLogic.getAllInterfaceLifecycleTypes(any())).thenReturn(Either.left(interfaceTypes));
                
-        ImmutablePair<Resource, ActionStatus> createResource = importManager.importNormativeResource(jsonContent, resourceMD, user, true, true);
+        ImmutablePair<Resource, ActionStatus> createResource =
+            importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false);
         assertNull(createResource.left.getInterfaces());
     }
     
@@ -303,10 +371,10 @@ public class ResourceImportManagerTest {
         user.setRole("ADMIN");
         user.setFirstName("Jhon");
         user.setLastName("Doh");
-        when(userAdmin.getUser(Mockito.anyString(), Mockito.anyBoolean())).thenReturn(user);
+        when(userAdmin.getUser(anyString(), anyBoolean())).thenReturn(user);
 
         setResourceBusinessLogicMock();
-        final Either<Component, StorageOperationStatus> foundResourceEither = Either.left(Mockito.mock(Resource.class));
+        final Either<Component, StorageOperationStatus> foundResourceEither = Either.left(mock(Resource.class));
         when(toscaOperationFacade.getComponentByNameAndVendorRelease(any(ComponentTypeEnum.class), anyString(), anyString(),
             any(JsonParseFlagEnum.class), any())).thenReturn(foundResourceEither);
         when(toscaOperationFacade.isNodeAssociatedToModel(eq(null), any(Resource.class))).thenReturn(true);
@@ -314,37 +382,38 @@ public class ResourceImportManagerTest {
         String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-blockStorage.yml");
 
         var actualException = assertThrows(ByActionStatusComponentException.class,
-            () -> importManager.importNormativeResource(jsonContent, resourceMD, user, true, true));
+            () -> importManager.importNormativeResource(jsonContent, resourceMD, user, true, true, false));
         assertEquals(ActionStatus.COMPONENT_WITH_VENDOR_RELEASE_ALREADY_EXISTS, actualException.getActionStatus());
     }
 
     private void setResourceBusinessLogicMock() {
         when(resourceBusinessLogic.getUserAdmin()).thenReturn(userAdmin);
-        when(resourceBusinessLogic.createOrUpdateResourceByImport(Mockito.any(Resource.class), Mockito.any(User.class), Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.anyBoolean(), eq(null), eq(null), eq(false)))
+        when(resourceBusinessLogic.createOrUpdateResourceByImport(any(Resource.class), any(User.class), anyBoolean(), anyBoolean(), anyBoolean(), eq(null), eq(null), eq(false)))
                 .thenAnswer((Answer<ImmutablePair<Resource, ActionStatus>>) invocation -> {
                     Object[] args = invocation.getArguments();
                     return new ImmutablePair<>((Resource) args[0], ActionStatus.CREATED);
 
                 });
-        when(resourceBusinessLogic.propagateStateToCertified(Mockito.any(User.class), Mockito.any(Resource.class), Mockito.any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false)))
+        when(resourceBusinessLogic.propagateStateToCertified(any(User.class), any(Resource.class), any(LifecycleChangeInfoWithAction.class), eq(false), eq(true), eq(false)))
                 .thenAnswer((Answer<Resource>) invocation -> {
                     Object[] args = invocation.getArguments();
                     return (Resource) args[1];
 
                 });
-        when(resourceBusinessLogic.createResourceByDao(Mockito.any(Resource.class), Mockito.any(User.class), Mockito.any(AuditingActionEnum.class), Mockito.anyBoolean(), Mockito.anyBoolean())).thenAnswer((Answer<Either<Resource, ResponseFormat>>) invocation -> {
+        when(resourceBusinessLogic.createResourceByDao(
+            any(Resource.class), any(User.class), any(AuditingActionEnum.class), anyBoolean(), anyBoolean())).thenAnswer((Answer<Either<Resource, ResponseFormat>>) invocation -> {
             Object[] args = invocation.getArguments();
             return Either.left((Resource) args[0]);
 
         });
-        when(resourceBusinessLogic.validateResourceBeforeCreate(Mockito.any(Resource.class), Mockito.any(User.class), Mockito.any(AuditingActionEnum.class), eq(false), eq(null))).thenAnswer((Answer<Either<Resource, ResponseFormat>>) invocation -> {
+        when(resourceBusinessLogic.validateResourceBeforeCreate(
+            any(Resource.class), any(User.class), any(AuditingActionEnum.class), eq(false), eq(null))).thenAnswer((Answer<Either<Resource, ResponseFormat>>) invocation -> {
             Object[] args = invocation.getArguments();
             return Either.left((Resource) args[0]);
 
         });
 
-        Boolean either = true;
-        when(resourceBusinessLogic.validatePropertiesDefaultValues(Mockito.any(Resource.class))).thenReturn(either);
+        when(resourceBusinessLogic.validatePropertiesDefaultValues(any(Resource.class))).thenReturn(true);
     }
 
     private ResponseFormat createGeneralErrorInfo() {
@@ -421,7 +490,7 @@ public class ResourceImportManagerTest {
 
     }
 
-    private void testSetRequirments(Resource resource) {
+    private void testSetRequirements(Resource resource) {
         Map<String, List<RequirementDefinition>> requirements = resource.getRequirements();
         assertEquals(2, requirements.size());
 
index 9d0966b..7a7b07f 100644 (file)
@@ -22,6 +22,9 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.io.File;
@@ -29,6 +32,7 @@ import java.io.FileReader;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.nio.file.Path;
 import java.util.Optional;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
@@ -50,11 +54,8 @@ import org.json.simple.JSONObject;
 import org.json.simple.parser.JSONParser;
 import org.json.simple.parser.ParseException;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.api.TestInstance.Lifecycle;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic;
@@ -62,7 +63,8 @@ import org.openecomp.sdc.be.components.impl.ModelBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic;
 import org.openecomp.sdc.be.components.impl.ResourceImportManager;
 import org.openecomp.sdc.be.components.impl.ResponseFormatManager;
-import org.openecomp.sdc.be.components.validation.UserValidations;
+import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
+import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
 import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.config.SpringConfig;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
@@ -85,9 +87,9 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 import org.springframework.web.context.WebApplicationContext;
 
-@TestInstance(Lifecycle.PER_CLASS)
 class ResourceUploadServletTest extends JerseyTest {
     private static final String USER_ID = "cs0008";
+    private static final User USER = new User(USER_ID);
 
     @Mock
     private HttpServletRequest request;
@@ -114,39 +116,21 @@ class ResourceUploadServletTest extends JerseyTest {
     @Mock
     private ResponseFormat responseFormat;
     @Mock
-    private UserValidations userValidations;
-    @Mock
     private ModelBusinessLogic modelBusinessLogic;
     @Mock
     private ResponseFormatManager responseFormatManager;
     private final String modelName = "ETSI-SOL001-331";
 
-    private final String rootPath = "/v1/catalog/upload/multipart";
+    private final Path rootPath = Path.of("/v1/catalog/upload");
+    private final Path bulkImportPath = rootPath.resolve("resource/import");
+    private final String multipartPath = "/v1/catalog/upload/multipart";
     private User user;
 
-    @BeforeAll
-    public void initClass() {
-        when(request.getSession()).thenReturn(session);
-        when(session.getServletContext()).thenReturn(servletContext);
-        when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR))
-            .thenReturn(webAppContextWrapper);
-        when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext);
-        when(webApplicationContext.getBean(ModelBusinessLogic.class)).thenReturn(modelBusinessLogic);
-        when(request.getHeader(Constants.USER_ID_HEADER)).thenReturn(USER_ID);
-        when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
-        when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils);
-        final String appConfigDir = "src/test/resources/config/catalog-be";
-        final ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
-        final ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
-        final org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
-        configuration.setJanusGraphInMemoryGraph(true);
-        configurationManager.setConfiguration(configuration);
-        ExternalConfiguration.setAppName("catalog-be");
-    }
-
     @BeforeEach
     void resetMock() throws Exception {
         super.setUp();
+        initMocks();
+        initConfig();
         initTestData();
     }
 
@@ -155,13 +139,6 @@ class ResourceUploadServletTest extends JerseyTest {
         super.tearDown();
     }
 
-    private void initTestData() {
-        user = new User();
-        user.setUserId(USER_ID);
-        user.setRole(Role.ADMIN.name());
-        when(userBusinessLogic.getUser(USER_ID)).thenReturn(user);
-    }
-
     @Override
     protected ResourceConfig configure() {
         MockitoAnnotations.openMocks(this);
@@ -179,7 +156,6 @@ class ResourceUploadServletTest extends JerseyTest {
                     bind(resourceImportManager).to(ResourceImportManager.class);
                     bind(resourceBusinessLogic).to(ResourceBusinessLogic.class);
                     bind(modelBusinessLogic).to(ModelBusinessLogic.class);
-                    bind(userValidations).to(UserValidations.class);
                 }
             })
             .register(new OperationExceptionMapper(new ServletResponseBuilder(), responseFormatManager))
@@ -192,6 +168,37 @@ class ResourceUploadServletTest extends JerseyTest {
         config.register(MultiPartFeature.class);
     }
 
+    void initMocks() {
+        when(request.getSession()).thenReturn(session);
+        when(session.getServletContext()).thenReturn(servletContext);
+        when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR))
+            .thenReturn(webAppContextWrapper);
+        when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext);
+        when(webApplicationContext.getBean(ModelBusinessLogic.class)).thenReturn(modelBusinessLogic);
+        when(webApplicationContext.getBean(UserBusinessLogic.class)).thenReturn(userBusinessLogic);
+        when(userBusinessLogic.getUser(USER_ID, false)).thenReturn(USER);
+        when(request.getHeader(Constants.USER_ID_HEADER)).thenReturn(USER_ID);
+        when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
+        when(servletUtils.getComponentsUtils()).thenReturn(componentsUtils);
+    }
+
+    void initConfig() {
+        final String appConfigDir = "src/test/resources/config/catalog-be";
+        final ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
+        final ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
+        final org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
+        configuration.setJanusGraphInMemoryGraph(true);
+        configurationManager.setConfiguration(configuration);
+        ExternalConfiguration.setAppName("catalog-be");
+    }
+
+    private void initTestData() {
+        user = new User();
+        user.setUserId(USER_ID);
+        user.setRole(Role.ADMIN.name());
+        when(userBusinessLogic.getUser(USER_ID)).thenReturn(user);
+    }
+
     @Test
     void uploadMultipartWithModelSuccessTest() throws IOException, ParseException, URISyntaxException {
         when(responseFormat.getStatus()).thenReturn(HttpStatus.OK_200);
@@ -199,10 +206,10 @@ class ResourceUploadServletTest extends JerseyTest {
         when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic);
         when(userBusinessLogic.getUser(anyString())).thenReturn(user);
         when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true);
-        when(resourceImportManager.importNormativeResource(anyString(), any(), any(), anyBoolean(), anyBoolean()))
+        when(resourceImportManager.importNormativeResource(anyString(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()))
             .thenReturn(new ImmutablePair<>(new Resource(), ActionStatus.CREATED));
         when(modelBusinessLogic.findModel(modelName)).thenReturn(Optional.of(new Model(modelName)));
-        final var response = target().path(rootPath).request(MediaType.APPLICATION_JSON)
+        final var response = target().path(multipartPath).request(MediaType.APPLICATION_JSON)
             .header(Constants.USER_ID_HEADER, USER_ID)
             .post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType001.zip",
                 "src/test/resources/node-types/nodeTypeWithModelsField.json"), MediaType.MULTIPART_FORM_DATA), Response.class);
@@ -216,9 +223,9 @@ class ResourceUploadServletTest extends JerseyTest {
         when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic);
         when(userBusinessLogic.getUser(anyString())).thenReturn(user);
         when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true);
-        when(resourceImportManager.importNormativeResource(anyString(), any(), any(), anyBoolean(), anyBoolean()))
+        when(resourceImportManager.importNormativeResource(anyString(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()))
             .thenReturn(new ImmutablePair<>(new Resource(), ActionStatus.CREATED));
-        final var response = target().path(rootPath).request(MediaType.APPLICATION_JSON)
+        final var response = target().path(multipartPath).request(MediaType.APPLICATION_JSON)
             .header(Constants.USER_ID_HEADER, USER_ID)
             .post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType002.zip",
                 "src/test/resources/node-types/nodeTypeWithoutModelsField.json"), MediaType.MULTIPART_FORM_DATA), Response.class);
@@ -233,7 +240,7 @@ class ResourceUploadServletTest extends JerseyTest {
         when(userBusinessLogic.getUser(anyString())).thenReturn(user);
         when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true);
         when(modelBusinessLogic.findModel("")).thenReturn(Optional.empty());
-        final Response response = target().path(rootPath).request(MediaType.APPLICATION_JSON)
+        final Response response = target().path(multipartPath).request(MediaType.APPLICATION_JSON)
             .header(Constants.USER_ID_HEADER, USER_ID)
             .post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType002.zip",
                 "src/test/resources/node-types/nodeTypeWithEmptyModels.json"), MediaType.MULTIPART_FORM_DATA), Response.class);
@@ -246,7 +253,7 @@ class ResourceUploadServletTest extends JerseyTest {
         when(userBusinessLogic.getUser(anyString())).thenReturn(user);
         when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true);
         when(modelBusinessLogic.findModel(modelName)).thenReturn(Optional.empty());
-        final var response = target().path(rootPath).request(MediaType.APPLICATION_JSON)
+        final var response = target().path(multipartPath).request(MediaType.APPLICATION_JSON)
             .header(Constants.USER_ID_HEADER, USER_ID)
             .post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType001.zip",
                 "src/test/resources/node-types/nodeTypeWithModelsField.json"), MediaType.MULTIPART_FORM_DATA), Response.class);
@@ -260,16 +267,75 @@ class ResourceUploadServletTest extends JerseyTest {
         when(servletUtils.getUserAdmin()).thenReturn(userBusinessLogic);
         when(userBusinessLogic.getUser(anyString())).thenReturn(user);
         when(resourceBusinessLogic.validatePropertiesDefaultValues(any())).thenReturn(true);
-        final var response = target().path(rootPath).request(MediaType.APPLICATION_JSON)
+        final var response = target().path(multipartPath).request(MediaType.APPLICATION_JSON)
             .header(Constants.USER_ID_HEADER, USER_ID)
             .post(Entity.entity(buildFormDataMultiPart("node-types/TestNodeType001.zip",
                 "src/test/resources/node-types/invalid.json"), MediaType.MULTIPART_FORM_DATA), Response.class);
         assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
     }
 
-    private String getInputData(final String jsonFilename) throws IOException, ParseException {
+    @Test
+    void bulkImportSuccessTest() throws IOException, ParseException {
+        when(responseFormat.getStatus()).thenReturn(HttpStatus.CREATED_201);
+        when(componentsUtils.getResponseFormat(ActionStatus.CREATED)).thenReturn(responseFormat);
+
+        final Response response = doValidCallToBulkImport(USER_ID);
+
+        verify(resourceImportManager).importAllNormativeResource(anyString(), any(), eq(USER), eq(false), eq(false));
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.CREATED_201);
+    }
+
+    @Test
+    void bulkImportFailTest_businessException() throws IOException, ParseException {
+        doThrow(new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR))
+            .when(resourceImportManager)
+            .importAllNormativeResource(anyString(), any(), eq(USER), eq(false), eq(false));
+
+        final Response response = doValidCallToBulkImport(USER_ID);
+
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
+    }
+
+    @Test
+    void bulkImportFailTest_unexpectedException() throws IOException, ParseException {
+        when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
+        when(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)).thenReturn(responseFormat);
+
+        doThrow(RuntimeException.class)
+            .when(resourceImportManager)
+            .importAllNormativeResource(anyString(), any(), eq(USER), eq(false), eq(false));
+
+        final Response response = doValidCallToBulkImport(USER_ID);
+
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
+    }
+
+    @Test
+    void bulkImportFailTest_invalidUser() throws IOException, ParseException {
+        var userId = "userId";
+        when(userBusinessLogic.getUser(userId, false)).thenThrow(ComponentException.class);
+        when(responseFormat.getStatus()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR_500);
+        when(componentsUtils.getResponseFormat(any(ComponentException.class))).thenReturn(responseFormat);
+
+        final Response response = doValidCallToBulkImport(userId);
+
+        assertThat(response.getStatus()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR_500);
+    }
+
+    private Response doValidCallToBulkImport(final String userId) throws IOException, ParseException {
+        final Path nodeTypesYamlPath = Path.of("src/test/resources/node-types/nodeTypes.yaml");
+        final Path nodeTypeMetadataJsonPath = Path.of("src/test/resources/node-types/payload.json");
+        return target().path(bulkImportPath.toString()).request(MediaType.APPLICATION_JSON)
+            .header(Constants.USER_ID_HEADER, userId)
+            .post(
+                Entity.entity(buildBulkImportMultiPartData(nodeTypesYamlPath, nodeTypeMetadataJsonPath), MediaType.MULTIPART_FORM_DATA),
+                Response.class
+            );
+    }
+
+    private String parseFileToJsonString(final Path jsonFilePath) throws IOException, ParseException {
         final JSONObject inputData = (JSONObject) new JSONParser().parse(
-            new FileReader(jsonFilename));
+            new FileReader(jsonFilePath.toString()));
         return inputData.toJSONString();
     }
 
@@ -286,7 +352,17 @@ class ResourceUploadServletTest extends JerseyTest {
         final FileDataBodyPart filePart = new FileDataBodyPart("resourceZip", getFile(zipFilePath));
         final FormDataMultiPart multipartEntity = new FormDataMultiPart();
         multipartEntity.bodyPart(filePart);
-        multipartEntity.field("resourceMetadata", getInputData(inputJsonData));
+        multipartEntity.field("resourceMetadata", parseFileToJsonString(Path.of(inputJsonData)));
         return  multipartEntity;
     }
+
+    private FormDataMultiPart buildBulkImportMultiPartData(final Path nodeTypesYamlPath, final Path payloadJsonPath)
+        throws IOException, ParseException {
+        final FileDataBodyPart formDataBodyPart = new FileDataBodyPart("nodeTypesYaml", nodeTypesYamlPath.toFile());
+        final FormDataMultiPart multipartEntity = new FormDataMultiPart();
+        multipartEntity.bodyPart(formDataBodyPart);
+        multipartEntity.field("nodeTypeMetadataJson", parseFileToJsonString(payloadJsonPath), MediaType.APPLICATION_JSON_TYPE);
+        multipartEntity.field("createNewVersion", String.valueOf(false), MediaType.TEXT_PLAIN_TYPE);
+        return multipartEntity;
+    }
 }
diff --git a/catalog-be/src/test/resources/node-types/nodeTypes.yaml b/catalog-be/src/test/resources/node-types/nodeTypes.yaml
new file mode 100644 (file)
index 0000000..7f105c4
--- /dev/null
@@ -0,0 +1,408 @@
+tosca_definitions_version: tosca_simple_yaml_1_2
+description: ETSI NFV SOL 001 Root node type definitions version 2.5.1
+
+node_types:
+  tosca.nodes.Root:
+    description: The TOSCA Node Type all other TOSCA base Node Types derive from
+    attributes:
+      tosca_id:
+        type: string
+      tosca_name:
+        type: string
+      state:
+        type: string
+    capabilities:
+      feature:
+        type: tosca.capabilities.Node
+    requirements:
+      - dependency:
+          capability: tosca.capabilities.Node
+          node: tosca.nodes.Root
+          relationship: tosca.relationships.DependsOn
+          occurrences: [ 0, UNBOUNDED ]
+    interfaces:
+      Standard:
+        type: tosca.interfaces.node.lifecycle.Standard
+  tosca.nodes.nfv.VNF:
+    derived_from: tosca.nodes.Root
+    description: The generic abstract type from which all VNF specific abstract node types shall be derived to form, together with other node types, the TOSCA service template(s) representing the VNFD
+    properties:
+      descriptor_id: # instead of vnfd_id
+        type: string # GUID
+        description: Globally unique identifier of the VNFD
+        required: true
+      descriptor_version: # instead of vnfd_version
+        type: string
+        description: Identifies the version of the VNFD
+        required: true
+      provider: # instead of vnf_provider
+        type: string
+        description: Provider of the VNF and of the VNFD
+        required: true
+      product_name: # instead of vnf_product_name
+        type: string
+        description: Human readable name for the VNF Product
+        required: true
+      software_version: # instead of vnf_software_version
+        type: string
+        description: Software version of the VNF
+        required: true
+      product_info_name: # instead of vnf_product_info_name
+        type: string
+        description: Human readable name for the VNF Product
+        required: false
+      product_info_description: # instead of vnf_product_info_description
+        type: string
+        description: Human readable description of the VNF Product
+        required: false
+      vnfm_info:
+        type: list
+        required: true
+        description: Identifies VNFM(s) compatible with the VNF
+        entry_schema:
+          type: string
+      localization_languages:
+        type: list
+        description: Information about localization languages of the VNF
+        required: false
+        entry_schema:
+          type: string #IETF RFC 5646 string
+      default_localization_language:
+        type: string #IETF RFC 5646 string
+        description: Default localization language that is instantiated if no information about selected localization language is available
+        required: false
+        #configurable_properties:
+        #type: tosca.datatypes.nfv.VnfConfigurableProperties
+        #description: Describes the configurable properties of the VNF
+        #required: false
+        # derived types are expected to introduce configurable_properties
+        # with its type derived from
+        # tosca.datatypes.nfv.VnfConfigurableProperties
+        #modifiable_attributes:
+        #type: tosca.datatypes.nfv.VnfInfoModifiableAttributes
+        #description: Describes the modifiable attributes of the VNF
+        #required: false
+        # derived types are expected to introduce modifiable_attributes
+        # with its type derived from
+        # tosca.datatypes.nfv.VnfInfoModifiableAttributes
+      lcm_operations_configuration:
+        type: tosca.datatypes.nfv.VnfLcmOperationsConfiguration
+        description: Describes the configuration parameters for the VNF LCM operations
+        required: false
+      monitoring_parameters:
+        type: list
+        entry_schema:
+          type: tosca.datatypes.nfv.VnfMonitoringParameter
+        description: Describes monitoring parameters applicable to the VNF.
+        required: false
+      flavour_id:
+        type: string
+        description: Identifier of the Deployment Flavour within the VNFD
+        required: true
+      flavour_description:
+        type: string
+        description: Human readable description of the DF
+        required: true
+      #vnf_profile:
+      #  type: tosca.datatypes.nfv.VnfProfile
+      #  description: Describes a profile for instantiating VNFs of a particular NS DF according to a specific VNFD and VNF DF
+      #  required: false
+    requirements:
+      - virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+          occurrences: [ 0, 1 ]
+    # Additional requirements shall be defined in the VNF specific node type (deriving from tosca.nodes.nfv.VNF) corresponding to NS virtual links that need to connect to VnfExtCps
+    interfaces:
+      Vnflcm:
+        type: tosca.interfaces.nfv.Vnflcm
+  tosca.nodes.nfv.Cp:
+    derived_from: tosca.nodes.Root
+    description: Provides information regarding the purpose of the connection point
+    properties:
+      layer_protocols:
+        type: list
+        description: Identifies which protocol the connection point uses for connectivity purposes
+        required: true
+        entry_schema:
+          type: string
+          constraints:
+            - valid_values: [ ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire ]
+      role: #Name in ETSI NFV IFA011 v0.7.3: cpRole
+        type: string
+        description: Identifies the role of the port in the context of the traffic flow patterns in the VNF or parent NS
+        required: false
+        constraints:
+          - valid_values: [ root, leaf ]
+      description:
+        type: string
+        description: Provides human-readable information on the purpose of the connection point
+        required: false
+      protocol:
+        type: list
+        description: Provides information on the addresses to be assigned to the connection point(s) instantiated from this Connection Point Descriptor
+        required: false
+        entry_schema:
+          type: tosca.datatypes.nfv.CpProtocolData
+      trunk_mode:
+        type: boolean
+        description: Provides information about whether the CP instantiated from this Cp is in Trunk mode (802.1Q or other), When operating in "trunk mode", the Cp is capable of carrying traffic for several VLANs. Absence of this property implies that trunkMode is not configured for the Cp i.e. It is equivalent to boolean value "false".
+        required: false
+  tosca.nodes.nfv.VnfExtCp:
+    derived_from: tosca.nodes.nfv.Cp
+    description: Describes a logical external connection point, exposed by the VNF enabling connection with an external Virtual Link
+    properties:
+      virtual_network_interface_requirements:
+        type: list
+        description: The actual virtual NIC requirements that is been assigned when instantiating the connection point
+        required: false
+        entry_schema:
+          type: tosca.datatypes.nfv.VirtualNetworkInterfaceRequirements
+    requirements:
+      - external_virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+      - internal_virtual_link: #name in ETSI NFV IFA011 v0.7.3: intVirtualLinkDesc
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+  tosca.nodes.nfv.VnfVirtualLink:
+    derived_from: tosca.nodes.Root
+    description: Describes the information about an internal VNF VL
+    properties:
+      connectivity_type:
+        type: tosca.datatypes.nfv.ConnectivityType
+        description: Specifies the protocol exposed by the VL and the flow pattern supported by the VL
+        required: true
+      description:
+        type: string
+        description: Provides human-readable information on the purpose of the VL
+        required: false
+      test_access:
+        type: list
+        description: Test access facilities available on the VL
+        required: false
+        entry_schema:
+          type: string
+          constraints:
+            - valid_values: [ passive_monitoring, active_loopback ]
+      vl_profile:
+        type: tosca.datatypes.nfv.VlProfile
+        description: Defines additional data for the VL
+        required: true
+      monitoring_parameters:
+        type: list
+        description: Describes monitoring parameters applicable to the VL
+        required: false
+        entry_schema:
+          type: tosca.datatypes.nfv.VirtualLinkMonitoringParameter
+    capabilities:
+      virtual_linkable:
+        type: tosca.capabilities.nfv.VirtualLinkable
+  tosca.nodes.nfv.Vdu.VirtualObjectStorage:
+    derived_from: tosca.nodes.Root
+    description: This node type describes the specifications of requirements related to virtual object storage resources
+    properties:
+      virtual_object_storage_data:
+        type: tosca.datatypes.nfv.VirtualObjectStorageData
+        description: Describes the object  storage characteristics.
+        required: true
+    capabilities:
+      virtual_storage:
+        type: tosca.capabilities.nfv.VirtualStorage
+        description: Defines the capabilities of virtual_storage.
+  tosca.nodes.nfv.Vdu.VirtualFileStorage:
+    derived_from: tosca.nodes.Root
+    description: This node type describes the specifications of requirements related to virtual file storage resources
+    properties:
+      virtual_file_storage_data:
+        type: tosca.datatypes.nfv.VirtualFileStorageData
+        description: Describes the file  storage characteristics.
+        required: true
+    capabilities:
+      virtual_storage:
+        type: tosca.capabilities.nfv.VirtualStorage
+        description: Defines the capabilities of virtual_storage.
+    requirements:
+      - virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+  tosca.nodes.nfv.Vdu.VirtualBlockStorage:
+    derived_from: tosca.nodes.Root
+    description: This node type describes the specifications of requirements related to virtual block storage resources
+    properties:
+      virtual_block_storage_data:
+        type: tosca.datatypes.nfv.VirtualBlockStorageData
+        description: Describes the block storage characteristics.
+        required: true
+      sw_image_data:
+        type: tosca.datatypes.nfv.SwImageData
+        description: Defines information related to a SwImage artifact used by this Vdu.Compute node.
+        required: false # property is required when the node template has an associated artifact of type tosca.artifacts.nfv.SwImage and not required otherwise
+    capabilities:
+      virtual_storage:
+        type: tosca.capabilities.nfv.VirtualStorage
+        description: Defines the capabilities of virtual_storage.
+  tosca.nodes.nfv.NsVirtualLink:
+    derived_from: tosca.nodes.Root
+    description: node definition of Virtual Links
+    properties:
+      vl_profile:
+        type: tosca.datatypes.nfv.NsVlProfile # only covers min/max bitrate requirements
+        description: Specifies instantiation parameters for a virtual link of a particular NS deployment flavour.
+        required: true
+      connectivity_type:
+        type: tosca.datatypes.nfv.ConnectivityType
+        required: true
+      test_access:
+        type: list
+        description: Test access facilities available on the VL
+        required: false
+        entry_schema:
+          type: string
+          constraints:
+            - valid_values: [ passive_monitoring, active_loopback ]
+      description:
+        type: string
+        required: false
+        description: Human readable information on the purpose of the virtual link (e.g. VL for control plane traffic).
+    capabilities:
+      virtual_linkable:
+        type: tosca.capabilities.nfv.VirtualLinkable
+  tosca.nodes.nfv.NS:
+    derived_from: tosca.nodes.Root
+    properties:
+      descriptor_id:
+        type: string # GUID
+        description: Identifier of this NS descriptor
+        required: true
+      designer:
+        type: string
+        description: Identifies the designer of the NSD.
+        required: true
+      version:
+        type: string
+        description: Identifies the version of the NSD.
+        required: true
+      name:
+        type: string
+        description: Provides the human readable name of the NSD.
+        required: true
+      invariant_id:
+        type: string
+        description: Identifies an NSD in a version independent manner. This attribute is invariant across versions of NSD.
+        required: true
+    requirements:
+      - virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+          node: tosca.nodes.nfv.NsVirtualLink
+          occurrences: [ 0, 1 ]
+    interfaces:
+      Nslcm:
+        type: tosca.interfaces.nfv.Nslcm
+  tosca.nodes.nfv.Vdu.Compute:
+    derived_from: tosca.nodes.Root
+    description: Describes the virtual compute part of a VDU which is a construct supporting the description of the deployment and operational behavior of a VNFC
+    properties:
+      name:
+        type: string
+        description: Human readable name of the VDU
+        required: true
+      description:
+        type: string
+        description: Human readable description of the VDU
+        required: true
+      boot_order:
+        type: list # explicit index (boot index) not necessary, contrary to IFA011
+        description: References a node template name from which a valid boot device is created
+        required: false
+        entry_schema:
+          type: string
+      nfvi_constraints:
+        type: list
+        description: Describes constraints on the NFVI for the VNFC instance(s) created from this VDU
+        required: false
+        entry_schema:
+          type: string
+      monitoring_parameters:
+        type: list
+        description: Describes monitoring parameters applicable to a VNFC instantiated from this VDU
+        required: false
+        entry_schema:
+          type: tosca.datatypes.nfv.VnfcMonitoringParameter
+          #configurable_properties:
+          #type: tosca.datatypes.nfv.VnfcConfigurableProperties
+          #required: false
+          # derived types are expected to introduce
+          # configurable_properties with its type derived from
+          # tosca.datatypes.nfv.VnfcConfigurableProperties
+      vdu_profile:
+        type: tosca.datatypes.nfv.VduProfile
+        description: Defines additional instantiation data for the VDU.Compute node
+        required: true
+      sw_image_data:
+        type: tosca.datatypes.nfv.SwImageData
+        description: Defines information related to a SwImage artifact used by this Vdu.Compute node
+        required: false # property is required when the node template has an associated artifact of type tosca.artifacts.nfv.SwImage and not required otherwise
+      boot_data:
+        type: string
+        description: Contains a string or a URL to a file contained in the VNF package used to customize a virtualised compute resource at boot time. The bootData may contain variable parts that are replaced by deployment specific values before being sent to the VIM.
+        required: false
+    capabilities:
+      virtual_compute:
+        type: tosca.capabilities.nfv.VirtualCompute
+        occurrences: [ 1, 1 ]
+      virtual_binding:
+        type: tosca.capabilities.nfv.VirtualBindable
+        occurrences: [ 1, UNBOUNDED ]
+    requirements:
+      - virtual_storage:
+          capability: tosca.capabilities.nfv.VirtualStorage
+          relationship: tosca.relationships.nfv.AttachesTo
+          occurrences: [ 0, UNBOUNDED ]
+  tosca.nodes.nfv.Sap:
+    derived_from: tosca.nodes.nfv.Cp
+    description: node definition of SAP.
+    requirements:
+      - external_virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+      - internal_virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+  tosca.nodes.nfv.VduCp:
+    derived_from: tosca.nodes.nfv.Cp
+    description: describes network connectivity between a VNFC instance based on this VDU and an internal VL
+    properties:
+      bitrate_requirement:
+        type: integer   # in bits per second
+        description: Bitrate requirement in bit per second on this connection point
+        required: false
+        constraints:
+          - greater_or_equal: 0
+      virtual_network_interface_requirements:
+        type: list
+        description: Specifies requirements on a virtual network interface realising the CPs instantiated from this CPD
+        required: false
+        entry_schema:
+          type: tosca.datatypes.nfv.VirtualNetworkInterfaceRequirements
+      order:
+        type: integer
+        description: The order of the NIC on the compute instance (e.g.eth2)
+        required: false
+        constraints:
+          - greater_or_equal: 0
+      vnic_type:
+        type: string
+        description: Describes the type of the virtual network interface realizing the CPs instantiated from this CPD
+        required: false
+        constraints:
+          - valid_values: [ normal, virtio, direct-physical ]
+    requirements:
+      - virtual_link:
+          capability: tosca.capabilities.nfv.VirtualLinkable
+          relationship: tosca.relationships.nfv.VirtualLinksTo
+      - virtual_binding:
+          capability: tosca.capabilities.nfv.VirtualBindable
+          relationship: tosca.relationships.nfv.VirtualBindsTo
+          node: tosca.nodes.nfv.Vdu.Compute
diff --git a/catalog-be/src/test/resources/node-types/payload.json b/catalog-be/src/test/resources/node-types/payload.json
new file mode 100644 (file)
index 0000000..2930855
--- /dev/null
@@ -0,0 +1,304 @@
+{
+  "nodeMetadataList": [
+    {
+      "contactId": "jh0003",
+      "toscaName": "tosca.nodes.Root",
+      "name": "Root",
+      "model": "ETSI SOL001 v2.5.3",
+      "description": "The TOSCA Node Type all other TOSCA base Node Types derive from",
+      "resourceIconPath": "defaulticon",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Abstract"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "Root",
+        "tosca.nodes.Root"
+      ]
+    },
+    {
+      "contactId": "jh0003",
+      "toscaName": "tosca.nodes.nfv.VNF",
+      "name": "VNF",
+      "model": "ETSI SOL001 v2.5.3",
+      "description": "The generic abstract type from which all VNF specific abstract node types shall be derived to form, together with other node types, the TOSCA service template(s) representing the VNFD",
+      "resourceIconPath": "compute",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VNF",
+        "tosca.nodes.nfv.VNF"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Cp",
+      "name": "Cp",
+      "model": "ETSI SOL001 v2.5.3",
+      "description": "Provides information regarding the purpose of the connection point",
+      "contactId": "jh0003",
+      "resourceIconPath": "compute",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "Cp",
+        "tosca.nodes.nfv.Cp"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.VnfExtCp",
+      "name": "VNF External CP",
+      "model": "ETSI SOL001 v2.5.3",
+      "description": "Describes a logical external connection point, exposed by the VNF enabling connection with an external Virtual Link",
+      "contactId": "jh0003",
+      "resourceIconPath": "network",
+      "resourceType": "CP",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VNF External CP",
+        "tosca.nodes.nfv.VnfExtCp"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.VnfVirtualLink",
+      "name": "VnfVirtualLink",
+      "model": "ETSI SOL001 v2.5.3",
+      "contactId": "jh0003",
+      "description": "Describes the information about an internal VNF VL",
+      "resourceIconPath": "network",
+      "resourceType": "VL",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VnfVirtualLink",
+        "tosca.nodes.nfv.VnfVirtualLink"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Vdu.VirtualObjectStorage",
+      "name": "VDU VirtualObjectStorage",
+      "description": "This node type describes the specifications of requirements related to virtual object storage resources",
+      "model": "ETSI SOL001 v2.5.3",
+      "contactId": "jh0003",
+      "resourceIconPath": "objectStorage",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VDU VirtualObjectStorage",
+        "tosca.nodes.nfv.Vdu.VirtualObjectStorage"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Vdu.VirtualFileStorage",
+      "name": "VDU VirtualFileStorage",
+      "description": "This node type describes the specifications of requirements related to virtual file storage resources",
+      "model": "ETSI SOL001 v2.5.3",
+      "contactId": "jh0003",
+      "resourceIconPath": "objectStorage",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VDU VirtualFileStorage",
+        "tosca.nodes.nfv.Vdu.VirtualFileStorage"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Vdu.VirtualBlockStorage",
+      "name": "VDU VirtualBlockStorage",
+      "description": "This node type describes the specifications of requirements related to virtual block storage resources",
+      "model": "ETSI SOL001 v2.5.3",
+      "contactId": "jh0003",
+      "resourceIconPath": "objectStorage",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VDU VirtualBlockStorage",
+        "tosca.nodes.nfv.Vdu.VirtualBlockStorage"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.NsVirtualLink",
+      "name": "NsVirtualLink",
+      "description": "Node definition of Virtual Links",
+      "model": "ETSI SOL001 v2.5.3",
+      "contactId": "jh0003",
+      "resourceIconPath": "network",
+      "resourceType": "VL",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "NsVirtualLink",
+        "tosca.nodes.nfv.NsVirtualLink"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.NS",
+      "name": "NS",
+      "contactId": "jh0003",
+      "description": "ETSI Network Service",
+      "model": "ETSI SOL001 v2.5.3",
+      "resourceIconPath": "network",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Network Elements"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "NS",
+        "tosca.nodes.nfv.NS"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Vdu.Compute",
+      "name": "VDU Compute",
+      "contactId": "jh0003",
+      "description": "Represents a real or virtual machine or server. Information specified on the Compute node will be used to find the machine that fits the given requirements in the cloud available machines. If no sizing information are specified the cloud provider default machine will be used. It is strongly recommended to specify the required CPUs and memory at least.",
+      "model": "ETSI SOL001 v2.5.3",
+      "resourceIconPath": "compute",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VDU Compute",
+        "tosca.nodes.nfv.Vdu.Compute"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.Sap",
+      "name": "Sap",
+      "contactId": "jh0003",
+      "description": "Node definition of SAP",
+      "model": "ETSI SOL001 v2.5.3",
+      "resourceIconPath": "network",
+      "resourceType": "VFC",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Infrastructure"
+            }
+          ]
+        }
+      ],
+      "vendorName": "ETSI",
+      "vendorRelease": "2.5.1",
+      "tags": [
+        "Sap",
+        "tosca.nodes.nfv.Sap"
+      ]
+    },
+    {
+      "toscaName": "tosca.nodes.nfv.VduCp",
+      "name": "VDU Cp",
+      "contactId": "jh0003",
+      "description": "Describes network connectivity between a VNFC instance based on this VDU and an internal VL",
+      "model": "ETSI SOL001 v2.5.3",
+      "resourceIconPath": "port",
+      "resourceType": "CP",
+      "categories": [
+        {
+          "name": "Generic",
+          "subcategories": [
+            {
+              "name": "Network Elements"
+            }
+          ]
+        }
+      ],
+      "tags": [
+        "VDU Cp",
+        "tosca.nodes.nfv.VduCp"
+      ]
+    }
+  ]
+}
+
index 2a71089..800fc67 100644 (file)
@@ -125,5 +125,8 @@ public enum ActionStatus {
     //Abstract template related
     ABSTRACT, NORMAL,
     //including default imports in CSAR related
-    CSAR_TOSCA_IMPORTS_ERROR
+    CSAR_TOSCA_IMPORTS_ERROR,
+    //TOSCA node types
+    INVALID_NODE_TYPES_YAML
+
 }
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/NodeTypeMetadata.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/NodeTypeMetadata.java
new file mode 100644 (file)
index 0000000..da83b8f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * -
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.model;
+
+import java.util.List;
+import lombok.Data;
+import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
+import org.openecomp.sdc.be.model.category.CategoryDefinition;
+
+/**
+ * Holds metadata information about a TOSCA node_type.
+ */
+@Data
+public class NodeTypeMetadata {
+
+    private String name;
+    private String toscaName;
+    private String description;
+    private String contactId;
+    private String resourceIconPath;
+    private String model;
+    private String icon;
+    private String vendorName;
+    private String vendorRelease;
+    private String resourceVendorModelNumber;
+    private String resourceType = ResourceTypeEnum.VFC.getValue();
+    private List<String> tags;
+    private List<CategoryDefinition> categories;
+
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/NodeTypesMetadataList.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/NodeTypesMetadataList.java
new file mode 100644 (file)
index 0000000..25b9616
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * -
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.model;
+
+import java.util.List;
+import lombok.Data;
+
+/**
+ * Dto to hold a list of TOSCA node type metadata.
+ */
+@Data
+public class NodeTypesMetadataList {
+
+    private List<NodeTypeMetadata> nodeMetadataList;
+
+}
index 752fad2..dcb0116 100644 (file)
@@ -21,10 +21,12 @@ package org.openecomp.sdc.be.model;
 
 import java.util.ArrayList;
 import java.util.List;
+import lombok.NoArgsConstructor;
 import org.openecomp.sdc.be.model.category.CategoryDefinition;
 import org.openecomp.sdc.be.model.category.SubCategoryDefinition;
 import org.openecomp.sdc.common.api.UploadArtifactInfo;
 
+@NoArgsConstructor
 public class UploadResourceInfo {
 
     private String payloadData;
@@ -39,7 +41,6 @@ public class UploadResourceInfo {
 
     public UploadResourceInfo(String payload, String payloadName, String description, String category, List<String> tags,
                               List<UploadArtifactInfo> artifactsList, String modelName) {
-        super();
         this.payloadData = payload;
         this.payloadName = payloadName;
         this.description = description;
@@ -60,9 +61,6 @@ public class UploadResourceInfo {
         }
     }
 
-    public UploadResourceInfo() {
-    }
-
     public String getPayloadData() {
         return payloadData;
     }
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/NodeTypeMetadataMapper.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/mapper/NodeTypeMetadataMapper.java
new file mode 100644 (file)
index 0000000..feef044
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * -
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.model.mapper;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.openecomp.sdc.be.model.NodeTypeMetadata;
+import org.openecomp.sdc.be.model.UploadResourceInfo;
+
+/**
+ * Responsible to map the {@code NodeTypeMetadata} to and from other classes.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class NodeTypeMetadataMapper {
+
+    public static UploadResourceInfo mapTo(final NodeTypeMetadata nodeTypeMetadata) {
+        var uploadResourceInfo = new UploadResourceInfo();
+        uploadResourceInfo.setName(nodeTypeMetadata.getName());
+        uploadResourceInfo.setDescription(nodeTypeMetadata.getDescription());
+        uploadResourceInfo.setContactId(nodeTypeMetadata.getContactId());
+        uploadResourceInfo.setIcon(nodeTypeMetadata.getIcon());
+        uploadResourceInfo.setResourceIconPath(nodeTypeMetadata.getResourceIconPath());
+        uploadResourceInfo.setVendorName(nodeTypeMetadata.getVendorName());
+        uploadResourceInfo.setModel(nodeTypeMetadata.getModel());
+        uploadResourceInfo.setVendorRelease(nodeTypeMetadata.getVendorRelease());
+        uploadResourceInfo.setResourceVendorModelNumber(nodeTypeMetadata.getResourceVendorModelNumber());
+        uploadResourceInfo.setResourceType(nodeTypeMetadata.getResourceType());
+        uploadResourceInfo.setTags(nodeTypeMetadata.getTags());
+        uploadResourceInfo.setCategories(nodeTypeMetadata.getCategories());
+        return uploadResourceInfo;
+    }
+
+}
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/mapper/NodeTypeMetadataMapperTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/mapper/NodeTypeMetadataMapperTest.java
new file mode 100644 (file)
index 0000000..1121503
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * -
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2021 Nordix Foundation.
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.openecomp.sdc.be.model.mapper;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.model.NodeTypeMetadata;
+import org.openecomp.sdc.be.model.UploadResourceInfo;
+import org.openecomp.sdc.be.model.category.CategoryDefinition;
+
+class NodeTypeMetadataMapperTest {
+
+    @Test
+    void mapToUploadResourceInfoTest() {
+        final var nodeTypeMetadata = new NodeTypeMetadata();
+        nodeTypeMetadata.setName("name");
+        nodeTypeMetadata.setDescription("description");
+        nodeTypeMetadata.setContactId("contactId");
+        nodeTypeMetadata.setIcon("icon");
+        nodeTypeMetadata.setResourceIconPath("resourceIconPath");
+        nodeTypeMetadata.setVendorName("vendorName");
+        nodeTypeMetadata.setModel("model");
+        nodeTypeMetadata.setVendorRelease("vendorRelease");
+        nodeTypeMetadata.setResourceVendorModelNumber("resourceVendorModelNumber");
+        nodeTypeMetadata.setResourceType("resourceType");
+        nodeTypeMetadata.setTags(List.of("tag1", "tag2"));
+        nodeTypeMetadata.setCategories(List.of(new CategoryDefinition()));
+
+        final UploadResourceInfo uploadResourceInfo = NodeTypeMetadataMapper.mapTo(nodeTypeMetadata);
+        assertEquals(nodeTypeMetadata.getName(), uploadResourceInfo.getName());
+        assertEquals(nodeTypeMetadata.getDescription(), uploadResourceInfo.getDescription());
+        assertEquals(nodeTypeMetadata.getContactId(), uploadResourceInfo.getContactId());
+        assertEquals(nodeTypeMetadata.getResourceIconPath(), uploadResourceInfo.getResourceIconPath());
+        assertEquals(nodeTypeMetadata.getVendorName(), uploadResourceInfo.getVendorName());
+        assertEquals(nodeTypeMetadata.getModel(), uploadResourceInfo.getModel());
+        assertEquals(nodeTypeMetadata.getVendorRelease(), uploadResourceInfo.getVendorRelease());
+        assertEquals(nodeTypeMetadata.getResourceVendorModelNumber(), uploadResourceInfo.getResourceVendorModelNumber());
+        assertEquals(nodeTypeMetadata.getResourceType(), uploadResourceInfo.getResourceType());
+        assertEquals(nodeTypeMetadata.getTags(), uploadResourceInfo.getTags());
+        assertEquals(nodeTypeMetadata.getCategories(), uploadResourceInfo.getCategories());
+
+        final var nodeTypeMetadata1 = new NodeTypeMetadata();
+        nodeTypeMetadata1.setIcon("icon");
+        final UploadResourceInfo uploadResourceInfo1 = NodeTypeMetadataMapper.mapTo(nodeTypeMetadata1);
+        assertEquals(nodeTypeMetadata1.getIcon(), uploadResourceInfo1.getResourceIconPath());
+    }
+
+}
\ No newline at end of file