Fix changed instance attribute value not visible in generated tosca
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / csar / YamlTemplateParsingHandler.java
index e04a401..940363b 100644 (file)
@@ -19,6 +19,7 @@
  * Modifications copyright (c) 2019 Nokia
  * ================================================================================
  */
+
 package org.openecomp.sdc.be.components.csar;
 
 import static java.util.stream.Collectors.toList;
@@ -29,6 +30,7 @@ import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaMap
 import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement;
 import static org.openecomp.sdc.be.components.impl.ImportUtils.loadYamlAsStrictMap;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.ARTIFACTS;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.ATTRIBUTES;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.CAPABILITIES;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.CAPABILITY;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DEFAULT_VALUE;
@@ -36,13 +38,17 @@ import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DESCRIPTION
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.FILE;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.GET_INPUT;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.GROUPS;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.INPUTS;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.IS_PASSWORD;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.MEMBERS;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE_TYPE;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.OUTPUTS;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.POLICIES;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.PROPERTIES;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIREMENTS;
+import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_FILTERS;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TARGETS;
 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE;
@@ -76,22 +82,27 @@ import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentEx
 import org.openecomp.sdc.be.components.utils.PropertiesUtils;
 import org.openecomp.sdc.be.config.BeEcompErrorManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
-import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao;
 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PolicyTargetType;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
 import org.openecomp.sdc.be.model.CapabilityDefinition;
+import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
 import org.openecomp.sdc.be.model.GroupDefinition;
 import org.openecomp.sdc.be.model.GroupTypeDefinition;
 import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.NodeTypeInfo;
+import org.openecomp.sdc.be.model.OutputDefinition;
 import org.openecomp.sdc.be.model.ParsedToscaYamlInfo;
 import org.openecomp.sdc.be.model.PolicyDefinition;
 import org.openecomp.sdc.be.model.PolicyTypeDefinition;
-import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.UploadArtifactInfo;
+import org.openecomp.sdc.be.model.UploadAttributeInfo;
 import org.openecomp.sdc.be.model.UploadCapInfo;
 import org.openecomp.sdc.be.model.UploadComponentInstanceInfo;
 import org.openecomp.sdc.be.model.UploadPropInfo;
@@ -99,13 +110,12 @@ import org.openecomp.sdc.be.model.UploadReqInfo;
 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
 import org.openecomp.sdc.be.utils.TypeUtils;
 import org.openecomp.sdc.common.log.wrappers.Logger;
-import org.springframework.stereotype.Component;
 import org.yaml.snakeyaml.parser.ParserException;
 
 /**
  * A handler class designed to parse the YAML file of the service template for a JAVA object
  */
-@Component
+@org.springframework.stereotype.Component
 public class YamlTemplateParsingHandler {
 
     private static final Pattern propertyValuePattern = Pattern.compile("[ ]*\\{[ ]*(str_replace=|token=|get_property=|concat=|get_attribute=)+");
@@ -128,16 +138,28 @@ public class YamlTemplateParsingHandler {
 
     public ParsedToscaYamlInfo parseResourceInfoFromYAML(String fileName, String resourceYml, Map<String, String> createdNodesToscaResourceNames,
                                                          Map<String, NodeTypeInfo> nodeTypesInfo, String nodeName,
-                                                         org.openecomp.sdc.be.model.Component component) {
+                                                         Component component, String interfaceTemplateYaml) {
         log.debug("#parseResourceInfoFromYAML - Going to parse yaml {} ", fileName);
-        Map<String, Object> mappedToscaTemplate = getMappedToscaTemplate(fileName, resourceYml, nodeTypesInfo, nodeName);
-        ParsedToscaYamlInfo parsedToscaYamlInfo = new ParsedToscaYamlInfo();
-        findToscaElement(mappedToscaTemplate, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL).left().on(err -> failIfNotTopologyTemplate(fileName));
-        parsedToscaYamlInfo.setInputs(getInputs(mappedToscaTemplate));
-        parsedToscaYamlInfo.setInstances(getInstances(fileName, mappedToscaTemplate, createdNodesToscaResourceNames));
-        parsedToscaYamlInfo.setGroups(getGroups(fileName, mappedToscaTemplate));
-        if (component instanceof Resource) {
-            parsedToscaYamlInfo.setPolicies(getPolicies(fileName, mappedToscaTemplate));
+        final Map<String, Object> mappedToscaTemplate = getMappedToscaTemplate(fileName, resourceYml, nodeTypesInfo, nodeName);
+        final ParsedToscaYamlInfo parsedToscaYamlInfo = new ParsedToscaYamlInfo();
+        final Map<String, Object> mappedTopologyTemplate = (Map<String, Object>) findToscaElement(mappedToscaTemplate, TOPOLOGY_TEMPLATE,
+            ToscaElementTypeEnum.ALL).left().on(err -> failIfNotTopologyTemplate(fileName));
+        final Map<String, Object> mappedTopologyTemplateInputs = mappedTopologyTemplate.entrySet().stream()
+            .filter(entry -> entry.getKey().equals(INPUTS.getElementName())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+        final Map<String, Object> mappedTopologyTemplateOutputs = mappedTopologyTemplate.entrySet().stream()
+            .filter(entry -> entry.getKey().equals(OUTPUTS.getElementName())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+        parsedToscaYamlInfo.setInputs(getInputs(mappedTopologyTemplateInputs));
+        parsedToscaYamlInfo.setOutputs(getOutputs(mappedTopologyTemplateOutputs));
+        parsedToscaYamlInfo.setInstances(getInstances(mappedToscaTemplate, createdNodesToscaResourceNames));
+        parsedToscaYamlInfo.setGroups(getGroups(mappedToscaTemplate, component.getModel()));
+        parsedToscaYamlInfo.setPolicies(getPolicies(mappedToscaTemplate, component.getModel()));
+        Map<String, Object> substitutionMappings = getSubstitutionMappings(mappedToscaTemplate);
+        if (substitutionMappings != null) {
+            if (component.isService() && !interfaceTemplateYaml.isEmpty()) {
+                parsedToscaYamlInfo.setProperties(getProperties(loadYamlAsStrictMap(interfaceTemplateYaml)));
+                parsedToscaYamlInfo.setSubstitutionFilterProperties(getSubstitutionFilterProperties(mappedToscaTemplate));
+            }
+            parsedToscaYamlInfo.setSubstitutionMappingNodeType((String) substitutionMappings.get(NODE_TYPE.getElementName()));
         }
         log.debug("#parseResourceInfoFromYAML - The yaml {} has been parsed ", fileName);
         return parsedToscaYamlInfo;
@@ -176,15 +198,60 @@ public class YamlTemplateParsingHandler {
         return inputs;
     }
 
-    private Map<String, PolicyDefinition> getPolicies(String fileName, Map<String, Object> toscaJson) {
-        Map<String, Object> foundPolicies = findFirstToscaMapElement(toscaJson, POLICIES).left().on(err -> logPoliciesNotFound(fileName));
+    private Map<String, OutputDefinition> getOutputs(Map<String, Object> toscaJson) {
+        return ImportUtils.getOutputs(toscaJson).left().on(err -> new HashMap<>());
+    }
+
+    private Map<String, PropertyDefinition> getProperties(Map<String, Object> toscaJson) {
+        return ImportUtils.getProperties(toscaJson).left().on(err -> new HashMap<>());
+    }
+
+    private ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> getSubstitutionFilterProperties(Map<String, Object> toscaJson) {
+        ListDataDefinition<RequirementSubstitutionFilterPropertyDataDefinition> propertyList = new ListDataDefinition<>();
+        Map<String, Object> substitutionFilters = findFirstToscaMapElement(toscaJson, SUBSTITUTION_FILTERS).left().on(err -> new HashMap<>());
+        if (MapUtils.isEmpty(substitutionFilters)) {
+            return propertyList;
+        }
+        ArrayList<Map<String, List<Map<String, Object>>>> substitutionFilterProperties =
+            (ArrayList<Map<String, List<Map<String, Object>>>>) substitutionFilters.get("properties");
+        if (CollectionUtils.isEmpty(substitutionFilterProperties)) {
+            return propertyList;
+        }
+        for (Map<String, List<Map<String, Object>>> filterProps : substitutionFilterProperties) {
+            for (Map.Entry<String, List<Map<String, Object>>> filterPropsMap : filterProps.entrySet()) {
+                for (Map<String, Object> mapValue : filterPropsMap.getValue()) {
+                    RequirementSubstitutionFilterPropertyDataDefinition requirementSubstitutionFilterPropertyDataDefinition =
+                        new RequirementSubstitutionFilterPropertyDataDefinition();
+                    requirementSubstitutionFilterPropertyDataDefinition.setName(filterPropsMap.getKey());
+                    requirementSubstitutionFilterPropertyDataDefinition.setConstraints(
+                        getSubstitutionFilterConstraints(filterPropsMap.getKey(), mapValue));
+                    propertyList.add(requirementSubstitutionFilterPropertyDataDefinition);
+                }
+            }
+        }
+        return propertyList;
+    }
+
+    private List<String> getSubstitutionFilterConstraints(String name, Map<String, Object> value) {
+        List<String> constraints = new ArrayList<>();
+        for (Map.Entry<String, Object> valueMap : value.entrySet()) {
+            constraints.add(name + ": {" + valueMap.getKey() + ": " + valueMap.getValue() + "}");
+        }
+        return constraints;
+    }
+
+    private Map<String, PolicyDefinition> getPolicies(Map<String, Object> toscaJson, String model) {
+        Map<String, Object> mappedTopologyTemplate = (Map<String, Object>) findToscaElement(toscaJson, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL)
+            .left().on(err -> new HashMap<>());
+        Map<String, Object> foundPolicies = (Map<String, Object>) mappedTopologyTemplate.get(POLICIES.getElementName());
         if (MapUtils.isNotEmpty(foundPolicies)) {
-            return foundPolicies.entrySet().stream().map(this::createPolicy).collect(Collectors.toMap(PolicyDefinition::getName, p -> p));
+            return foundPolicies.entrySet().stream().map(policyToCreate -> createPolicy(policyToCreate, model))
+                .collect(Collectors.toMap(PolicyDefinition::getName, p -> p));
         }
         return Collections.emptyMap();
     }
 
-    private PolicyDefinition createPolicy(Map.Entry<String, Object> policyNameValue) {
+    private PolicyDefinition createPolicy(Map.Entry<String, Object> policyNameValue, String model) {
         PolicyDefinition emptyPolicyDef = new PolicyDefinition();
         String policyName = policyNameValue.getKey();
         emptyPolicyDef.setName(policyName);
@@ -192,7 +259,7 @@ public class YamlTemplateParsingHandler {
             // There's no need to null test in conjunction with an instanceof test. null is not an instanceof anything, so a null check is redundant.
             if (policyNameValue.getValue() instanceof Map) {
                 Map<String, Object> policyTemplateJsonMap = (Map<String, Object>) policyNameValue.getValue();
-                validateAndFillPolicy(emptyPolicyDef, policyTemplateJsonMap);
+                validateAndFillPolicy(emptyPolicyDef, policyTemplateJsonMap, model);
             } else {
                 rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE);
             }
@@ -203,12 +270,7 @@ public class YamlTemplateParsingHandler {
         return emptyPolicyDef;
     }
 
-    private Map<String, Object> logPoliciesNotFound(String fileName) {
-        log.debug("#logPoliciesNotFound - Policies were not found in the yaml template {}.", fileName);
-        return Collections.emptyMap();
-    }
-
-    private void validateAndFillPolicy(PolicyDefinition emptyPolicyDefinition, Map<String, Object> policyTemplateJsonMap) {
+    private void validateAndFillPolicy(PolicyDefinition emptyPolicyDefinition, Map<String, Object> policyTemplateJsonMap, String model) {
         String policyTypeName = (String) policyTemplateJsonMap.get(TYPE.getElementName());
         if (StringUtils.isEmpty(policyTypeName)) {
             log.debug("#validateAndFillPolicy - The 'type' member is not found under policy {}", emptyPolicyDefinition.getName());
@@ -217,13 +279,13 @@ public class YamlTemplateParsingHandler {
         emptyPolicyDefinition.setType(policyTypeName);
         // set policy targets
         emptyPolicyDefinition.setTargets(validateFillPolicyTargets(policyTemplateJsonMap));
-        PolicyTypeDefinition policyTypeDefinition = validateGetPolicyTypeDefinition(policyTypeName);
+        PolicyTypeDefinition policyTypeDefinition = validateGetPolicyTypeDefinition(policyTypeName, model);
         // set policy properties
         emptyPolicyDefinition.setProperties(validateFillPolicyProperties(policyTypeDefinition, policyTemplateJsonMap));
     }
 
-    private PolicyTypeDefinition validateGetPolicyTypeDefinition(String policyType) {
-        PolicyTypeDefinition policyTypeDefinition = policyTypeBusinessLogic.getLatestPolicyTypeByType(policyType);
+    private PolicyTypeDefinition validateGetPolicyTypeDefinition(String policyType, String modelName) {
+        PolicyTypeDefinition policyTypeDefinition = policyTypeBusinessLogic.getLatestPolicyTypeByType(policyType, modelName);
         if (policyTypeDefinition == null) {
             log.debug("#validateAndFillPolicy - The policy type {} not found", policyType);
             rollbackWithException(ActionStatus.POLICY_TYPE_IS_INVALID, policyType);
@@ -267,36 +329,38 @@ public class YamlTemplateParsingHandler {
         return targets;
     }
 
-    private Map<String, UploadComponentInstanceInfo> getInstances(String yamlName, Map<String, Object> toscaJson,
+    private Map<String, UploadComponentInstanceInfo> getInstances(Map<String, Object> toscaJson,
                                                                   Map<String, String> createdNodesToscaResourceNames) {
-        Map<String, Object> nodeTemlates = findFirstToscaMapElement(toscaJson, NODE_TEMPLATES).left().on(err -> failIfNoNodeTemplates(yamlName));
-        return getInstances(toscaJson, createdNodesToscaResourceNames, nodeTemlates);
+        Map<String, Object> nodeTemplates = findFirstToscaMapElement(toscaJson, NODE_TEMPLATES).left().on(err -> new HashMap<>());
+        if (nodeTemplates.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        return getInstances(toscaJson, createdNodesToscaResourceNames, nodeTemplates);
     }
 
     private Map<String, UploadComponentInstanceInfo> getInstances(Map<String, Object> toscaJson, Map<String, String> createdNodesToscaResourceNames,
-                                                                  Map<String, Object> nodeTemlates) {
-        Map<String, UploadComponentInstanceInfo> moduleComponentInstances;
+                                                                  Map<String, Object> nodeTemplates) {
         Map<String, Object> substitutionMappings = getSubstitutionMappings(toscaJson);
-        moduleComponentInstances = nodeTemlates.entrySet().stream()
+        return nodeTemplates.entrySet().stream()
             .map(node -> buildModuleComponentInstanceInfo(node, substitutionMappings, createdNodesToscaResourceNames))
             .collect(Collectors.toMap(UploadComponentInstanceInfo::getName, i -> i));
-        return moduleComponentInstances;
     }
 
     private Map<String, Object> getSubstitutionMappings(Map<String, Object> toscaJson) {
-        Map<String, Object> substitutionMappings = null;
         Either<Map<String, Object>, ResultStatusEnum> eitherSubstitutionMappings = findFirstToscaMapElement(toscaJson, SUBSTITUTION_MAPPINGS);
         if (eitherSubstitutionMappings.isLeft()) {
-            substitutionMappings = eitherSubstitutionMappings.left().value();
+            return eitherSubstitutionMappings.left().value();
         }
-        return substitutionMappings;
+        return null;
     }
 
     @SuppressWarnings("unchecked")
-    private Map<String, GroupDefinition> getGroups(String fileName, Map<String, Object> toscaJson) {
-        Map<String, Object> foundGroups = findFirstToscaMapElement(toscaJson, GROUPS).left().on(err -> logGroupsNotFound(fileName));
-        if (MapUtils.isNotEmpty(foundGroups) && matcheKey(foundGroups)) {
-            Map<String, GroupDefinition> groups = foundGroups.entrySet().stream().map(this::createGroup)
+    private Map<String, GroupDefinition> getGroups(Map<String, Object> toscaJson, String model) {
+        Map<String, Object> mappedTopologyTemplate = (Map<String, Object>) findToscaElement(toscaJson, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL)
+            .left().on(err -> new HashMap<>());
+        Map<String, Object> foundGroups = (Map<String, Object>) mappedTopologyTemplate.get(GROUPS.getElementName());
+        if (MapUtils.isNotEmpty(foundGroups)) {
+            Map<String, GroupDefinition> groups = foundGroups.entrySet().stream().map(groupToCreate -> createGroup(groupToCreate, model))
                 .collect(Collectors.toMap(GroupDefinition::getName, g -> g));
             Map<String, Object> substitutionMappings = getSubstitutionMappings(toscaJson);
             if (capabilitiesSubstitutionMappingsExist(substitutionMappings)) {
@@ -308,25 +372,6 @@ public class YamlTemplateParsingHandler {
         return new HashMap<>();
     }
 
-    private boolean matcheKey(Map<String, Object> foundGroups) {
-        if (foundGroups != null && !foundGroups.isEmpty()) {
-            for (Map.Entry<String, Object> stringObjectEntry : foundGroups.entrySet()) {
-                String key = stringObjectEntry.getKey();
-                if (key.contains("group")) {
-                    if (foundGroups.get(key) instanceof Map) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-    private Map<String, Object> logGroupsNotFound(String fileName) {
-        log.debug("#logGroupsNotFound - Groups were not found in the yaml template {}.", fileName);
-        return new HashMap<>();
-    }
-
     private void updateCapabilitiesNames(GroupDefinition group, Map<String, String> capabilityNames) {
         if (MapUtils.isNotEmpty(group.getCapabilities())) {
             group.getCapabilities().values().stream().flatMap(Collection::stream).filter(cap -> capabilityNames.containsKey(cap.getName()))
@@ -343,20 +388,20 @@ public class YamlTemplateParsingHandler {
         return substitutionMappings != null && substitutionMappings.containsKey(CAPABILITIES.getElementName());
     }
 
-    private GroupDefinition createGroup(Map.Entry<String, Object> groupNameValue) {
+    private GroupDefinition createGroup(Map.Entry<String, Object> groupNameValue, String model) {
         GroupDefinition group = new GroupDefinition();
         group.setName(groupNameValue.getKey());
         try {
             if (groupNameValue.getValue() instanceof Map) {
                 Map<String, Object> groupTemplateJsonMap = (Map<String, Object>) groupNameValue.getValue();
-                validateAndFillGroup(group, groupTemplateJsonMap);
+                validateAndFillGroup(group, groupTemplateJsonMap, model);
                 validateUpdateGroupProperties(group, groupTemplateJsonMap);
                 validateUpdateGroupCapabilities(group, groupTemplateJsonMap);
             } else {
                 rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE);
             }
         } catch (ClassCastException e) {
-            log.debug("#createGroup - Failed to create the group {}. The exception occure", groupNameValue.getKey(), e);
+            log.debug("#createGroup - Failed to create the group {}. The exception occurres", groupNameValue.getKey(), e);
             rollbackWithException(ActionStatus.INVALID_YAML);
         }
         return group;
@@ -443,14 +488,14 @@ public class YamlTemplateParsingHandler {
         }
     }
 
-    private void validateAndFillGroup(GroupDefinition groupInfo, Map<String, Object> groupTemplateJsonMap) {
+    private void validateAndFillGroup(GroupDefinition groupInfo, Map<String, Object> groupTemplateJsonMap, String model) {
         String type = (String) groupTemplateJsonMap.get(TYPE.getElementName());
         if (StringUtils.isEmpty(type)) {
             log.debug("#validateAndFillGroup - The 'type' member is not found under group {}", groupInfo.getName());
             rollbackWithException(ActionStatus.GROUP_MISSING_GROUP_TYPE, groupInfo.getName());
         }
         groupInfo.setType(type);
-        GroupTypeDefinition groupType = groupTypeBusinessLogic.getLatestGroupTypeByType(type);
+        GroupTypeDefinition groupType = groupTypeBusinessLogic.getLatestGroupTypeByType(type, model);
         if (groupType == null) {
             log.debug("#validateAndFillGroup - The group type {} not found", groupInfo.getName());
             rollbackWithException(ActionStatus.GROUP_TYPE_IS_INVALID, type);
@@ -537,7 +582,7 @@ public class YamlTemplateParsingHandler {
         if (CollectionUtils.isNotEmpty(missingProperties)) {
             if (log.isDebugEnabled()) {
                 log.debug("#validateProperties - Failed to validate properties. The properties {} are missing on {} of the type {}. ",
-                        missingProperties.toString(), name, type);
+                    missingProperties.toString(), name, type);
             }
             rollbackWithException(actionStatus, missingProperties.toString(), missingProperties.toString(), name, type);
         }
@@ -603,6 +648,7 @@ public class YamlTemplateParsingHandler {
                 setCapabilities(nodeTemplateInfo, nodeTemplateJsonMap);
                 setArtifacts(nodeTemplateInfo, nodeTemplateJsonMap);
                 updateProperties(nodeTemplateInfo, nodeTemplateJsonMap);
+                updateAttributes(nodeTemplateInfo, nodeTemplateJsonMap);
                 setDirectives(nodeTemplateInfo, nodeTemplateJsonMap);
                 setNodeFilter(nodeTemplateInfo, nodeTemplateJsonMap);
                 setSubstitutions(substitutionMappings, nodeTemplateInfo);
@@ -640,6 +686,15 @@ public class YamlTemplateParsingHandler {
         }
     }
 
+    private void updateAttributes(UploadComponentInstanceInfo nodeTemplateInfo, Map<String, Object> nodeTemplateJsonMap) {
+        if (nodeTemplateJsonMap.containsKey(ATTRIBUTES.getElementName())) {
+            Map<String, UploadAttributeInfo> attributes = buildAttributeModuleFromYaml(nodeTemplateJsonMap);
+            if (!attributes.isEmpty()) {
+                nodeTemplateInfo.setAttributes(attributes);
+            }
+        }
+    }
+
     private void setCapabilities(UploadComponentInstanceInfo nodeTemplateInfo, Map<String, Object> nodeTemplateJsonMap) {
         if (nodeTemplateJsonMap.containsKey(CAPABILITIES.getElementName())) {
             Map<String, List<UploadCapInfo>> eitherCapRes = createCapModuleFromYaml(nodeTemplateJsonMap);
@@ -777,6 +832,13 @@ public class YamlTemplateParsingHandler {
         if (nodeTemplateJsonMap.containsKey(FILE.getElementName())) {
             artifactTemplateInfo.setFile((String) nodeTemplateJsonMap.get(FILE.getElementName()));
         }
+        if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) {
+            Map<String, List<UploadPropInfo>> props = buildPropModuleFromYaml(nodeTemplateJsonMap);
+            if (!props.isEmpty()) {
+                List<UploadPropInfo> properties = props.values().stream().flatMap(Collection::stream).collect(toList());
+                artifactTemplateInfo.setProperties(properties);
+            }
+        }
     }
 
     @SuppressWarnings("unchecked")
@@ -866,6 +928,26 @@ public class YamlTemplateParsingHandler {
         return regTemplateInfo;
     }
 
+    private Map<String, UploadAttributeInfo> buildAttributeModuleFromYaml(Map<String, Object> nodeTemplateJsonMap) {
+        Map<String, UploadAttributeInfo> moduleAttribute = new HashMap<>();
+        Either<Map<String, Object>, ResultStatusEnum> toscaAttributes = findFirstToscaMapElement(nodeTemplateJsonMap, ATTRIBUTES);
+        if (toscaAttributes.isLeft()) {
+            Map<String, Object> jsonAttributes = toscaAttributes.left().value();
+            for (Map.Entry<String, Object> jsonAttributeObj : jsonAttributes.entrySet()) {
+                UploadAttributeInfo attributeDef = buildAttribute(jsonAttributeObj.getKey(), jsonAttributeObj.getValue());
+                moduleAttribute.put(attributeDef.getName(), attributeDef);
+            }
+        }
+        return moduleAttribute;
+    }
+
+    private UploadAttributeInfo buildAttribute(String attributeName, Object attributeValue) {
+        UploadAttributeInfo attributeDef = new UploadAttributeInfo();
+        attributeDef.setValue(attributeValue);
+        attributeDef.setName(attributeName);
+        return attributeDef;
+    }
+
     private Map<String, List<UploadPropInfo>> buildPropModuleFromYaml(Map<String, Object> nodeTemplateJsonMap) {
         Map<String, List<UploadPropInfo>> moduleProp = new HashMap<>();
         Either<Map<String, Object>, ResultStatusEnum> toscaProperties = findFirstToscaMapElement(nodeTemplateJsonMap, PROPERTIES);
@@ -982,7 +1064,7 @@ public class YamlTemplateParsingHandler {
 
     @SuppressWarnings("unchecked")
     private void findAndFillInputRecursively(Map<String, Object> propValue, UploadPropInfo propertyDef) {
-        for (Map.Entry<String,Object> entry : propValue.entrySet()) {
+        for (Map.Entry<String, Object> entry : propValue.entrySet()) {
             String propName = entry.getKey();
             Object value = entry.getValue();
             if (value instanceof Map) {
@@ -994,9 +1076,7 @@ public class YamlTemplateParsingHandler {
     }
 
     private void fillInputsRecursively(UploadPropInfo propertyDef, String propName, List<Object> inputs) {
-        inputs.stream()
-                .filter(Map.class::isInstance)
-                .forEach(o -> fillInputRecursively(propName, (Map<String, Object>) o, propertyDef));
+        inputs.stream().filter(Map.class::isInstance).forEach(o -> fillInputRecursively(propName, (Map<String, Object>) o, propertyDef));
     }
 
     @SuppressWarnings("unchecked")
@@ -1026,11 +1106,6 @@ public class YamlTemplateParsingHandler {
         return propValue == null || !pattern.matcher(propValue.toString()).find();
     }
 
-    private Map<String, Object> failIfNoNodeTemplates(String fileName) {
-        janusGraphDao.rollback();
-        throw new ByActionStatusComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, fileName);
-    }
-
     private Object failIfNotTopologyTemplate(String fileName) {
         janusGraphDao.rollback();
         throw new ByActionStatusComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, fileName);
@@ -1044,8 +1119,8 @@ public class YamlTemplateParsingHandler {
     private void failOnMissingCapabilityTypes(GroupDefinition groupDefinition, List<String> missingCapTypes) {
         if (log.isDebugEnabled()) {
             log.debug(
-                    "#failOnMissingCapabilityTypes - Failed to validate the capabilities of the group {}. The capability types {} are missing on the group type {}. ",
-                    groupDefinition.getName(), missingCapTypes.toString(), groupDefinition.getType());
+                "#failOnMissingCapabilityTypes - Failed to validate the capabilities of the group {}. The capability types {} are missing on the group type {}. ",
+                groupDefinition.getName(), missingCapTypes.toString(), groupDefinition.getType());
         }
         if (CollectionUtils.isNotEmpty(missingCapTypes)) {
             rollbackWithException(ActionStatus.MISSING_CAPABILITY_TYPE, missingCapTypes.toString());
@@ -1055,8 +1130,8 @@ public class YamlTemplateParsingHandler {
     private void failOnMissingCapabilityNames(GroupDefinition groupDefinition, List<String> missingCapNames) {
         if (log.isDebugEnabled()) {
             log.debug(
-                    "#failOnMissingCapabilityNames - Failed to validate the capabilities of the group {}. The capabilities with the names {} are missing on the group type {}. ",
-                    groupDefinition.getName(), missingCapNames.toString(), groupDefinition.getType());
+                "#failOnMissingCapabilityNames - Failed to validate the capabilities of the group {}. The capabilities with the names {} are missing on the group type {}. ",
+                groupDefinition.getName(), missingCapNames.toString(), groupDefinition.getType());
         }
         rollbackWithException(ActionStatus.MISSING_CAPABILITIES, missingCapNames.toString(), CapabilityDataDefinition.OwnerType.GROUP.getValue(),
             groupDefinition.getName());