Support updated data types in service import
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ServiceImportBusinessLogic.java
index 7e15a52..b4079ac 100644 (file)
@@ -27,6 +27,7 @@ import com.google.gson.Gson;
 import fj.data.Either;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -36,18 +37,19 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 import lombok.Getter;
 import lombok.Setter;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.json.simple.JSONObject;
 import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic;
 import org.openecomp.sdc.be.components.csar.CsarBusinessLogic;
 import org.openecomp.sdc.be.components.csar.CsarInfo;
+import org.openecomp.sdc.be.components.csar.ServiceCsarInfo;
 import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum;
 import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo;
 import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException;
@@ -62,18 +64,22 @@ import org.openecomp.sdc.be.config.BeEcompErrorManager;
 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.janusgraph.JanusGraphOperationStatus;
 import org.openecomp.sdc.be.datamodel.utils.ArtifactUtils;
-import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter;
+import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PolicyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.RequirementSubstitutionFilterPropertyDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
+import org.openecomp.sdc.be.datatypes.tosca.ToscaGetFunctionType;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
 import org.openecomp.sdc.be.info.NodeTypeInfoToUpdateArtifacts;
 import org.openecomp.sdc.be.model.ArtifactDefinition;
@@ -82,7 +88,6 @@ import org.openecomp.sdc.be.model.CapabilityDefinition;
 import org.openecomp.sdc.be.model.CapabilityRequirementRelationship;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.ComponentInstance;
-import org.openecomp.sdc.be.model.ComponentInstanceAttribute;
 import org.openecomp.sdc.be.model.ComponentInstanceInput;
 import org.openecomp.sdc.be.model.ComponentInstanceProperty;
 import org.openecomp.sdc.be.model.ComponentParametersView;
@@ -90,9 +95,13 @@ import org.openecomp.sdc.be.model.DataTypeDefinition;
 import org.openecomp.sdc.be.model.DistributionStatusEnum;
 import org.openecomp.sdc.be.model.GroupDefinition;
 import org.openecomp.sdc.be.model.InputDefinition;
+import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.LifeCycleTransitionEnum;
 import org.openecomp.sdc.be.model.LifecycleStateEnum;
+import org.openecomp.sdc.be.model.NodeTypeDefinition;
 import org.openecomp.sdc.be.model.NodeTypeInfo;
+import org.openecomp.sdc.be.model.NodeTypeMetadata;
+import org.openecomp.sdc.be.model.NodeTypesMetadataList;
 import org.openecomp.sdc.be.model.Operation;
 import org.openecomp.sdc.be.model.OutputDefinition;
 import org.openecomp.sdc.be.model.ParsedToscaYamlInfo;
@@ -106,6 +115,7 @@ import org.openecomp.sdc.be.model.Resource;
 import org.openecomp.sdc.be.model.Service;
 import org.openecomp.sdc.be.model.UploadAttributeInfo;
 import org.openecomp.sdc.be.model.UploadComponentInstanceInfo;
+import org.openecomp.sdc.be.model.UploadInterfaceInfo;
 import org.openecomp.sdc.be.model.UploadNodeFilterInfo;
 import org.openecomp.sdc.be.model.UploadPropInfo;
 import org.openecomp.sdc.be.model.UploadReqInfo;
@@ -118,6 +128,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
 import org.openecomp.sdc.be.model.operations.StorageException;
 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.UniqueIdBuilder;
 import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
 import org.openecomp.sdc.be.tosca.CsarUtils;
 import org.openecomp.sdc.be.ui.model.OperationUi;
@@ -130,6 +141,7 @@ import org.openecomp.sdc.common.kpi.api.ASDCKpiApi;
 import org.openecomp.sdc.common.log.wrappers.Logger;
 import org.openecomp.sdc.common.util.ValidationUtils;
 import org.openecomp.sdc.exception.ResponseFormat;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.yaml.snakeyaml.Yaml;
 
 @Getter
@@ -151,8 +163,6 @@ public class ServiceImportBusinessLogic {
 
     private final ComponentsUtils componentsUtils;
     private final ToscaOperationFacade toscaOperationFacade;
-    private final UiComponentDataConverter uiComponentDataConverter;
-    private final ComponentInstanceBusinessLogic componentInstanceBusinessLogic;
     private final ServiceBusinessLogic serviceBusinessLogic;
     private final CsarBusinessLogic csarBusinessLogic;
     private final CsarArtifactsAndGroupsBusinessLogic csarArtifactsAndGroupsBusinessLogic;
@@ -160,29 +170,26 @@ public class ServiceImportBusinessLogic {
     private final CompositionBusinessLogic compositionBusinessLogic;
     private final ResourceDataMergeBusinessLogic resourceDataMergeBusinessLogic;
     private final ServiceImportParseLogic serviceImportParseLogic;
-    private final ComponentNodeFilterBusinessLogic componentNodeFilterBusinessLogic;
     private final GroupBusinessLogic groupBusinessLogic;
     private final PolicyBusinessLogic policyBusinessLogic;
+    private final ResourceImportManager resourceImportManager;
     private final JanusGraphDao janusGraphDao;
     private final ArtifactsBusinessLogic artifactsBusinessLogic;
     private final IGraphLockOperation graphLockOperation;
     private final ToscaFunctionService toscaFunctionService;
+    private final DataTypeBusinessLogic dataTypeBusinessLogic;
+    private ApplicationDataTypeCache applicationDataTypeCache;
 
-    public ServiceImportBusinessLogic(final GroupBusinessLogic groupBusinessLogic,
-                                      final ArtifactsBusinessLogic artifactsBusinessLogic,
-                                      final ComponentInstanceBusinessLogic componentInstanceBusinessLogic,
-                                      final UiComponentDataConverter uiComponentDataConverter, final ComponentsUtils componentsUtils,
-                                      final ToscaOperationFacade toscaOperationFacade, final ServiceBusinessLogic serviceBusinessLogic,
-                                      final CsarBusinessLogic csarBusinessLogic,
+    public ServiceImportBusinessLogic(final GroupBusinessLogic groupBusinessLogic, final ArtifactsBusinessLogic artifactsBusinessLogic,
+                                      final ComponentsUtils componentsUtils, final ToscaOperationFacade toscaOperationFacade,
+                                      final ServiceBusinessLogic serviceBusinessLogic, final CsarBusinessLogic csarBusinessLogic,
                                       final CsarArtifactsAndGroupsBusinessLogic csarArtifactsAndGroupsBusinessLogic,
                                       final LifecycleBusinessLogic lifecycleBusinessLogic, final CompositionBusinessLogic compositionBusinessLogic,
                                       final ResourceDataMergeBusinessLogic resourceDataMergeBusinessLogic,
-                                      final ServiceImportParseLogic serviceImportParseLogic,
-                                      final ComponentNodeFilterBusinessLogic componentNodeFilterBusinessLogic,
-                                      final PolicyBusinessLogic policyBusinessLogic, final JanusGraphDao janusGraphDao,
-                                      final IGraphLockOperation graphLockOperation, final ToscaFunctionService toscaFunctionService) {
-        this.componentInstanceBusinessLogic = componentInstanceBusinessLogic;
-        this.uiComponentDataConverter = uiComponentDataConverter;
+                                      final ServiceImportParseLogic serviceImportParseLogic, final PolicyBusinessLogic policyBusinessLogic,
+                                      final ResourceImportManager resourceImportManager, final JanusGraphDao janusGraphDao,
+                                      final IGraphLockOperation graphLockOperation, final ToscaFunctionService toscaFunctionService,
+                                      final DataTypeBusinessLogic dataTypeBusinessLogic) {
         this.componentsUtils = componentsUtils;
         this.toscaOperationFacade = toscaOperationFacade;
         this.serviceBusinessLogic = serviceBusinessLogic;
@@ -192,13 +199,19 @@ public class ServiceImportBusinessLogic {
         this.compositionBusinessLogic = compositionBusinessLogic;
         this.resourceDataMergeBusinessLogic = resourceDataMergeBusinessLogic;
         this.serviceImportParseLogic = serviceImportParseLogic;
-        this.componentNodeFilterBusinessLogic = componentNodeFilterBusinessLogic;
         this.groupBusinessLogic = groupBusinessLogic;
         this.policyBusinessLogic = policyBusinessLogic;
+        this.resourceImportManager = resourceImportManager;
         this.janusGraphDao = janusGraphDao;
         this.artifactsBusinessLogic = artifactsBusinessLogic;
         this.graphLockOperation = graphLockOperation;
         this.toscaFunctionService = toscaFunctionService;
+        this.dataTypeBusinessLogic = dataTypeBusinessLogic;
+    }
+
+    @Autowired
+    public void setApplicationDataTypeCache(ApplicationDataTypeCache applicationDataTypeCache) {
+        this.applicationDataTypeCache = applicationDataTypeCache;
     }
 
     public Service createService(Service service, AuditingActionEnum auditingAction, User user, Map<String, byte[]> csarUIPayload,
@@ -232,7 +245,19 @@ public class ServiceImportBusinessLogic {
     protected Service createServiceFromCsar(Service service, User user, Map<String, byte[]> csarUIPayload, String csarUUID) {
         log.trace("************* created successfully from YAML, resource TOSCA ");
         try {
-            CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID);
+            ServiceCsarInfo csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID);
+
+            final Map<String, Object> dataTypesToCreate = getDatatypesToCreate(service.getModel(), csarInfo);
+            if (MapUtils.isNotEmpty(dataTypesToCreate)) {
+                dataTypeBusinessLogic.createDataTypeFromYaml(new Yaml().dump(dataTypesToCreate), service.getModel(), true);
+                dataTypesToCreate.entrySet().stream().forEach(createdOrUpdatedDataType -> {
+                    applicationDataTypeCache.reload(service.getModel(), UniqueIdBuilder.buildDataTypeUid(service.getModel(), createdOrUpdatedDataType.getKey()));
+                });
+            }
+            final List<NodeTypeDefinition> nodeTypesToCreate = getNodeTypesToCreate(service.getModel(), csarInfo);
+            if (CollectionUtils.isNotEmpty(nodeTypesToCreate)) {
+                createNodeTypes(nodeTypesToCreate, csarInfo);
+            }
             Map<String, NodeTypeInfo> nodeTypesInfo = csarInfo.extractTypesInfo();
             Either<Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = serviceImportParseLogic
                 .findNodeTypesArtifactsToHandle(nodeTypesInfo, csarInfo, service);
@@ -251,6 +276,56 @@ public class ServiceImportBusinessLogic {
         }
     }
 
+    private Map<String, Object> getDatatypesToCreate(final String model, final CsarInfo csarInfo) {
+        final Map<String, Object> dataTypesToCreate = new HashMap<>();
+
+        for (final Entry<String, Object> dataTypeEntry : csarInfo.getDataTypes().entrySet()) {
+            final Either<DataTypeDefinition, JanusGraphOperationStatus> result = applicationDataTypeCache.get(model,
+                UniqueIdBuilder.buildDataTypeUid(model, dataTypeEntry.getKey()));
+            if (result.isRight() && result.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) {
+                dataTypesToCreate.put(dataTypeEntry.getKey(), dataTypeEntry.getValue());
+                log.info("Deploying unknown type " + dataTypeEntry.getKey() + " to model " + model + " from package " + csarInfo.getCsarUUID());
+            }
+            if (hasNewProperties(result, (Map<String, Map<String, Object>>) dataTypeEntry.getValue())) {
+                dataTypesToCreate.put(dataTypeEntry.getKey(), dataTypeEntry.getValue());
+                log.info("Deploying new version of type " + dataTypeEntry.getKey() + " to model " + model + " from package " + csarInfo.getCsarUUID());
+            }
+        }
+        return dataTypesToCreate;
+    }
+    
+    private boolean hasNewProperties(final Either<DataTypeDefinition, JanusGraphOperationStatus> result, final Map<String, Map<String, Object>> dataType) {
+        return result.isLeft() && dataType.containsKey("properties") && result.left().value().getProperties() != null
+                && result.left().value().getProperties().size() != dataType.get("properties").size();
+    }
+
+    private void createNodeTypes(List<NodeTypeDefinition> nodeTypesToCreate, ServiceCsarInfo csarInfo) {
+        NodeTypesMetadataList nodeTypesMetadataList = new NodeTypesMetadataList();
+        List<NodeTypeMetadata> nodeTypeMetadataList = new ArrayList<>();
+
+        final Map<String, Object> allTypesToCreate = new HashMap<>();
+        nodeTypesToCreate.stream().forEach(nodeType -> {
+            allTypesToCreate.put(nodeType.getMappedNodeType().getKey(), nodeType.getMappedNodeType().getValue());
+            nodeTypeMetadataList.add(nodeType.getNodeTypeMetadata());
+        });
+
+        nodeTypesMetadataList.setNodeMetadataList(nodeTypeMetadataList);
+        resourceImportManager.importAllNormativeResource(allTypesToCreate, nodeTypesMetadataList, csarInfo.getModifier(), true, false);
+    }
+
+    private List<NodeTypeDefinition> getNodeTypesToCreate(final String model, final ServiceCsarInfo csarInfo) {
+        List<NodeTypeDefinition> namesOfNodeTypesToCreate = new ArrayList<>();
+
+        for (final NodeTypeDefinition nodeTypeDefinition : csarInfo.getNodeTypesUsed()) {
+            Either<Component, StorageOperationStatus> result = toscaOperationFacade
+                .getLatestByToscaResourceName(nodeTypeDefinition.getMappedNodeType().getKey(), model);
+            if (result.isRight() && result.right().value().equals(StorageOperationStatus.NOT_FOUND)) {
+                namesOfNodeTypesToCreate.add(nodeTypeDefinition);
+            }
+        }
+        return namesOfNodeTypesToCreate;
+    }
+
     protected Service createServiceFromYaml(Service service, String topologyTemplateYaml, String yamlName, Map<String, NodeTypeInfo> nodeTypesInfo,
                                             CsarInfo csarInfo,
                                             Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate,
@@ -303,6 +378,7 @@ public class ServiceImportBusinessLogic {
             }
             log.debug("name is locked {} status = {}", service.getSystemName(), lockResult);
         }
+        boolean rollback = false;
         try {
             log.trace("************* Adding properties to service from interface yaml {}", yamlName);
             Map<String, PropertyDefinition> properties = parsedToscaYamlInfo.getProperties();
@@ -368,14 +444,21 @@ public class ServiceImportBusinessLogic {
                 throw new ComponentException(createArtifactsEither.right().value());
             }
             service = serviceImportParseLogic.getServiceWithGroups(createArtifactsEither.left().value().getUniqueId());
+            service = updateInputs(service, userId);
+
             ASDCKpiApi.countCreatedResourcesKPI();
             return service;
         } catch (ComponentException | StorageException | BusinessLogicException e) {
+            rollback = true;
             serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts);
             throw e;
         } finally {
             if (!inTransaction) {
-                janusGraphDao.commit();
+                if (rollback) {
+                    janusGraphDao.rollback();
+                } else {
+                    janusGraphDao.commit();
+                }
             }
             if (shouldLock) {
                 graphLockOperation.unlockComponentByName(service.getSystemName(), service.getUniqueId(), NodeTypeEnum.Resource);
@@ -383,6 +466,136 @@ public class ServiceImportBusinessLogic {
         }
     }
 
+    private Service updateInputs(final Service component, final String userId) {
+        final List<InputDefinition> inputs = component.getInputs();
+        final List<ComponentInstance> componentInstances = component.getComponentInstances();
+        final String componentUniqueId = component.getUniqueId();
+        final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties = component.getComponentInstancesProperties();
+        for (final InputDefinition input : inputs) {
+            if (isInputFromComponentInstanceProperty(input.getName(), componentInstances, componentInstancesProperties)) {
+                associateInputToComponentInstanceProperty(userId, input, componentInstances, componentInstancesProperties,
+                    componentUniqueId);
+            } else {
+                associateInputToServiceProperty(userId, input, component);
+            }
+
+        }
+
+        final Either<List<InputDefinition>, StorageOperationStatus> either
+            = toscaOperationFacade.updateInputsToComponent(inputs, componentUniqueId);
+        if (either.isRight()) {
+            throw new ComponentException(ActionStatus.GENERAL_ERROR);
+        }
+
+        return component;
+    }
+
+    private boolean isInputFromComponentInstanceProperty(final String inputName, final List<ComponentInstance> componentInstances,
+                                                         final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties) {
+        if (CollectionUtils.isNotEmpty(componentInstances)) {
+            // get instance's names
+            final List<String> componentInstancesNames = componentInstances.stream().map(ComponentInstanceDataDefinition::getNormalizedName)
+                .collect(toList());
+            final Optional<String> componentInstancesNameOptional = componentInstancesNames.stream()
+                .filter(cin -> inputName.startsWith(cin + "_")).findFirst();
+            if (componentInstancesNameOptional.isPresent() && MapUtils.isNotEmpty(componentInstancesProperties)) {
+                final Optional<String> componentInstanceIdOptional = componentInstancesProperties.keySet().stream()
+                    .filter(key -> key.endsWith("." + componentInstancesNameOptional.get())).findFirst();
+                if (componentInstanceIdOptional.isPresent()) {
+                    // get property's name
+                    final String propertyNameFromInput = extractPropertyNameFromInputName(inputName, componentInstancesNames);
+                    return componentInstancesProperties.get(componentInstanceIdOptional.get()).stream()
+                        .anyMatch(prop -> prop.getName().equals(propertyNameFromInput) && prop.getValue() != null
+                            && prop.getValue().contains(ToscaGetFunctionType.GET_INPUT.getFunctionName()));
+                }
+            }
+        }
+        return false;
+    }
+
+    private void associateInputToComponentInstanceProperty(final String userId, final InputDefinition input,
+                                                           final List<ComponentInstance> componentInstances,
+                                                           final Map<String, List<ComponentInstanceProperty>> componentInstancesProperties,
+                                                           String componentUniqueId) {
+        // From Instance
+        final List<String> componentInstancesNames = componentInstances.stream().map(ComponentInstanceDataDefinition::getNormalizedName)
+            .collect(toList());
+        final String propertyNameFromInput = extractPropertyNameFromInputName(input.getName(), componentInstancesNames);
+
+        final Optional<String> componentInstancesNameOptional = componentInstancesNames.stream()
+            .filter(cin -> input.getName().startsWith(cin + "_")).findFirst();
+
+        final Optional<String> componentInstanceIdOptional = componentInstancesProperties.keySet().stream()
+            .filter(key -> key.endsWith("." + componentInstancesNameOptional.get())).findFirst();
+
+        final String componentInstanceId = componentInstanceIdOptional.get();
+        final List<ComponentInstanceProperty> componentInstanceProperties = componentInstancesProperties.get(componentInstanceId);
+
+        final ComponentInstanceProperty componentInstanceProperty = componentInstanceProperties.stream()
+            .filter(prop -> prop.getName().equals(propertyNameFromInput) && prop.getValue() != null
+                && prop.getValue().contains(ToscaGetFunctionType.GET_INPUT.getFunctionName())).findFirst().get();
+
+        // From Instance
+        updateInput(input, componentInstanceProperty, userId, componentInstanceId);
+
+        final Either<Map<String, List<ComponentInstanceProperty>>, StorageOperationStatus> either =
+            toscaOperationFacade.updateComponentInstancePropsToComponent(Collections.singletonMap(componentInstanceId,
+                Collections.singletonList(componentInstanceProperty)), componentUniqueId);
+        if (either.isRight()) {
+            throw new ComponentException(ActionStatus.GENERAL_ERROR);
+        }
+    }
+
+    private void associateInputToServiceProperty(final String userId,
+                                                 final InputDefinition input, final Service component) {
+        final List<PropertyDefinition> properties = component.getProperties();
+        if (CollectionUtils.isNotEmpty(properties)) {
+            final String propertyNameFromInput = input.getName();
+            final Optional<PropertyDefinition> propDefOptional = properties.stream().filter(prop -> prop.getName().equals(propertyNameFromInput))
+                .findFirst();
+            if (propDefOptional.isPresent()) {
+                // From SELF
+                final String componentUniqueId = component.getUniqueId();
+                final PropertyDefinition propertyDefinition = propDefOptional.get();
+                updateProperty(propertyDefinition, input, componentUniqueId);
+                final JSONObject jsonObject = new JSONObject();
+                jsonObject.put(ToscaGetFunctionType.GET_INPUT.getFunctionName(), input.getName());
+                propertyDefinition.setValue(jsonObject.toJSONString());
+                updateInput(input, propertyDefinition, userId, componentUniqueId);
+
+                final Either<PropertyDefinition, StorageOperationStatus> either
+                    = toscaOperationFacade.updatePropertyOfComponent(component, propertyDefinition);
+                if (either.isRight()) {
+                    throw new ComponentException(ActionStatus.GENERAL_ERROR);
+                }
+            }
+        }
+    }
+
+    private void updateProperty(final PropertyDefinition propertyDefinition, final InputDefinition input, final String componentUniqueId) {
+        propertyDefinition.setParentUniqueId(componentUniqueId);
+        final GetInputValueDataDefinition getInputValueDataDefinition = new GetInputValueDataDefinition();
+        getInputValueDataDefinition.setInputId(input.getUniqueId());
+        getInputValueDataDefinition.setInputName(input.getName());
+        getInputValueDataDefinition.setPropName(propertyDefinition.getName());
+        propertyDefinition.setGetInputValues(Collections.singletonList(getInputValueDataDefinition));
+    }
+
+    private void updateInput(final InputDefinition input, final PropertyDefinition propertyDefinition,
+                             final String userId, final String componentUniqueId) {
+        input.setProperties(Collections.singletonList(new ComponentInstanceProperty(propertyDefinition)));
+        input.setInstanceUniqueId(componentUniqueId);
+        input.setOwnerId(userId);
+        input.setPropertyId(propertyDefinition.getUniqueId());
+        input.setParentPropertyType(propertyDefinition.getType());
+    }
+
+    private String extractPropertyNameFromInputName(final String inputName, final List<String> componentInstancesNames) {
+        final AtomicReference<String> result = new AtomicReference<>(inputName);
+        componentInstancesNames.forEach(cin -> result.set(result.get().replace(cin + "_", "")));
+        return result.get();
+    }
+
     protected Either<Resource, ResponseFormat> createOrUpdateArtifacts(ArtifactsBusinessLogic.ArtifactOperationEnum operation,
                                                                        List<ArtifactDefinition> createdArtifacts, String yamlFileName,
                                                                        CsarInfo csarInfo, Resource preparedResource,
@@ -641,9 +854,7 @@ public class ServiceImportBusinessLogic {
                     handledNodeTypeArtifacts.addAll(handleNodeTypeArtifactsRequestRes);
                 }
             }
-            if (handleNodeTypeArtifactsRes == null) {
-                handleNodeTypeArtifactsRes = Either.left(handledNodeTypeArtifacts);
-            }
+            handleNodeTypeArtifactsRes = Either.left(handledNodeTypeArtifacts);
         } catch (Exception e) {
             ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
             handleNodeTypeArtifactsRes = Either.right(responseFormat);
@@ -930,7 +1141,8 @@ public class ServiceImportBusinessLogic {
             .filter(PropertyDataDefinition::isToscaFunction)
             .forEach(policyDefinition ->
                 toscaFunctionService
-                    .updateFunctionWithDataFromSelfComponent(policyDefinition.getToscaFunction(), service, service.getComponentInstancesProperties(), instanceAttributeMap)
+                    .updateFunctionWithDataFromSelfComponent(policyDefinition.getToscaFunction(), service, service.getComponentInstancesProperties(),
+                        instanceAttributeMap)
             );
         policyBusinessLogic.createPolicies(service, policies);
         return getServiceResponseFormatEither(service);
@@ -1012,7 +1224,7 @@ public class ServiceImportBusinessLogic {
         List<RequirementCapabilityRelDef> relations = new ArrayList<>();
         Map<String, List<ComponentInstanceInput>> instInputs = new HashMap<>();
         Map<String, UploadNodeFilterInfo> instNodeFilter = new HashMap<>();
-
+        Map<String, Map<String, InterfaceDefinition>> instInterfaces = new HashMap<>();
         log.debug("enter ServiceImportBusinessLogic createResourceInstancesRelations#createResourceInstancesRelations - Before get all datatypes. ");
         final ApplicationDataTypeCache applicationDataTypeCache = serviceBusinessLogic.applicationDataTypeCache;
         if (applicationDataTypeCache != null) {
@@ -1020,7 +1232,8 @@ public class ServiceImportBusinessLogic {
             uploadResInstancesMap.values().forEach(
                 i -> processComponentInstance(yamlName, finalResource, componentInstancesList,
                     componentsUtils.getAllDataTypes(applicationDataTypeCache, finalResource.getModel()), instProperties, instCapabilities,
-                    instRequirements, instDeploymentArtifacts, instArtifacts, instAttributes, originCompMap, instInputs, instNodeFilter, i));
+                    instRequirements, instDeploymentArtifacts, instArtifacts, instAttributes, originCompMap, instInputs, instNodeFilter,
+                    instInterfaces, i));
         }
         serviceImportParseLogic.associateComponentInstancePropertiesToComponent(yamlName, resource, instProperties);
         serviceImportParseLogic.associateComponentInstanceInputsToComponent(yamlName, resource, instInputs);
@@ -1042,7 +1255,7 @@ public class ServiceImportBusinessLogic {
         return eitherGetResource.left().value();
     }
 
-    protected void processProperty(Resource resource, ComponentInstance currentCompInstance, Map<String, DataTypeDefinition> allDataTypes,
+    protected void processProperty(Resource resource, Map<String, DataTypeDefinition> allDataTypes,
                                    Map<String, InputDefinition> currPropertiesMap, List<ComponentInstanceInput> instPropList,
                                    List<UploadPropInfo> propertyList) {
         UploadPropInfo propertyInfo = propertyList.get(0);
@@ -1326,10 +1539,13 @@ public class ServiceImportBusinessLogic {
                                                                                    List<ArtifactDefinition> nodeTypesNewCreatedArtifacts,
                                                                                    boolean forceCertificationAllowed, CsarInfo csarInfo,
                                                                                    boolean isNested) {
-        UploadResourceInfo resourceMetaData = serviceImportParseLogic.fillResourceMetadata(yamlName, resourceVf, nodeNameValue.getKey(), user);
+        final var validatedUser = serviceBusinessLogic.validateUser(user, "CheckIn Resource", resourceVf, AuditingActionEnum.CHECKIN_RESOURCE,
+            true);
+        UploadResourceInfo resourceMetaData = serviceImportParseLogic.fillResourceMetadata(yamlName, resourceVf, nodeNameValue.getKey(),
+            validatedUser);
         String singleVfcYaml = serviceImportParseLogic.buildNodeTypeYaml(nodeNameValue, mapToConvert, resourceMetaData.getResourceType(), csarInfo);
-        user = serviceBusinessLogic.validateUser(user, "CheckIn Resource", resourceVf, AuditingActionEnum.CHECKIN_RESOURCE, true);
-        return serviceImportParseLogic.createResourceFromNodeType(singleVfcYaml, resourceMetaData, user, true, needLock, nodeTypeArtifactsToHandle,
+        return serviceImportParseLogic.createResourceFromNodeType(singleVfcYaml, resourceMetaData, validatedUser, true, needLock,
+            nodeTypeArtifactsToHandle,
             nodeTypesNewCreatedArtifacts, forceCertificationAllowed, csarInfo, nodeNameValue.getKey(), isNested);
     }
 
@@ -1376,6 +1592,7 @@ public class ServiceImportBusinessLogic {
         List<RequirementCapabilityRelDef> relations = new ArrayList<>();
         Map<String, List<ComponentInstanceInput>> instInputs = new HashMap<>();
         Map<String, UploadNodeFilterInfo> instNodeFilter = new HashMap<>();
+        Map<String, Map<String, InterfaceDefinition>> instInterfaces = new HashMap<>();
         log.debug("enter ServiceImportBusinessLogic  createServiceInstancesRelations#createResourceInstancesRelations - Before get all datatypes. ");
         final ApplicationDataTypeCache applicationDataTypeCache = serviceBusinessLogic.applicationDataTypeCache;
         if (applicationDataTypeCache != null) {
@@ -1386,10 +1603,16 @@ public class ServiceImportBusinessLogic {
                 i -> processComponentInstance(yamlName, service1, componentInstancesList,
                     allDataTypesMap, instProperties,
                     instCapabilities, instRequirements, instDeploymentArtifacts, instArtifacts, instAttributes, originCompMap, instInputs,
-                    instNodeFilter, i));
+                    instNodeFilter, instInterfaces, i)
+            );
         }
         updatePropertyToscaFunctionData(service, instProperties, instAttributes);
         serviceImportParseLogic.associateComponentInstancePropertiesToComponent(yamlName, service, instProperties);
+        serviceImportParseLogic.associateComponentInstanceInterfacesToComponent(
+            yamlName,
+            service,
+            instInterfaces
+        );
         serviceImportParseLogic.associateComponentInstanceInputsToComponent(yamlName, service, instInputs);
         serviceImportParseLogic.associateCINodeFilterToComponent(yamlName, service, instNodeFilter);
         serviceImportParseLogic.associateDeploymentArtifactsToInstances(user, yamlName, service, instDeploymentArtifacts);
@@ -1449,6 +1672,7 @@ public class ServiceImportBusinessLogic {
                                             Map<String, List<AttributeDefinition>> instAttributes, Map<String, Resource> originCompMap,
                                             Map<String, List<ComponentInstanceInput>> instInputs,
                                             Map<String, UploadNodeFilterInfo> instNodeFilter,
+                                            Map<String, Map<String, InterfaceDefinition>> instInterfaces,
                                             UploadComponentInstanceInfo uploadComponentInstanceInfo) {
         log.debug("enter ServiceImportBusinessLogic processComponentInstance");
         Optional<ComponentInstance> currentCompInstanceOpt = componentInstancesList.stream()
@@ -1483,6 +1707,19 @@ public class ServiceImportBusinessLogic {
         if (uploadComponentInstanceInfo.getUploadNodeFilterInfo() != null) {
             instNodeFilter.put(resourceInstanceId, uploadComponentInstanceInfo.getUploadNodeFilterInfo());
         }
+        if (MapUtils.isNotEmpty(uploadComponentInstanceInfo.getInterfaces())) {
+
+            ResponseFormat addInterfacesToRiRes = addInterfaceValuesToRi(
+                uploadComponentInstanceInfo,
+                component,
+                originResource,
+                currentCompInstance,
+                instInterfaces
+            );
+            if (addInterfacesToRiRes.getStatus() != 200) {
+                throw new ComponentException(addInterfacesToRiRes);
+            }
+        }
         if (originResource.getResourceType() != ResourceTypeEnum.VF) {
             ResponseFormat addPropertiesValueToRiRes = addPropertyValuesToRi(uploadComponentInstanceInfo, component, originResource,
                 currentCompInstance, instProperties, allDataTypes);
@@ -1508,7 +1745,7 @@ public class ServiceImportBusinessLogic {
                 }
                 originResource.getInputs().forEach(p -> serviceImportParseLogic.addInput(currPropertiesMap, p));
                 for (List<UploadPropInfo> propertyList : propMap.values()) {
-                    processProperty(component, currentCompInstance, allDataTypes, currPropertiesMap, instPropList, propertyList);
+                    processProperty(component, allDataTypes, currPropertiesMap, instPropList, propertyList);
                 }
                 currPropertiesMap.values().forEach(p -> instPropList.add(new ComponentInstanceInput(p)));
                 instInputs.put(currentCompInstance.getUniqueId(), instPropList);
@@ -1519,7 +1756,7 @@ public class ServiceImportBusinessLogic {
         }
     }
 
-    protected void processProperty(Component component, ComponentInstance currentCompInstance, Map<String, DataTypeDefinition> allDataTypes,
+    protected void processProperty(Component component, Map<String, DataTypeDefinition> allDataTypes,
                                    Map<String, InputDefinition> currPropertiesMap, List<ComponentInstanceInput> instPropList,
                                    List<UploadPropInfo> propertyList) {
         UploadPropInfo propertyInfo = propertyList.get(0);
@@ -1640,6 +1877,93 @@ public class ServiceImportBusinessLogic {
         return componentsUtils.getResponseFormat(ActionStatus.OK);
     }
 
+    protected ResponseFormat addInterfaceValuesToRi(
+        UploadComponentInstanceInfo uploadComponentInstanceInfo,
+        Component component,
+        Resource originResource, ComponentInstance currentCompInstance,
+        Map<String, Map<String, InterfaceDefinition>> instInterfaces
+    ) {
+        Map<String, UploadInterfaceInfo> instanceInterfacesMap = uploadComponentInstanceInfo.getInterfaces();
+        Map<String, InterfaceDefinition> currInterfacesMap = new HashMap<>();
+        Map<String, InterfaceDefinition> interfacesFromNodeType = originResource.getInterfaces();
+        if ((MapUtils.isNotEmpty(instanceInterfacesMap)) && (MapUtils.isEmpty(interfacesFromNodeType))) {
+            log.debug("failed to find interfaces ");
+            return componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT);
+        }
+        if (interfacesFromNodeType == null || interfacesFromNodeType.isEmpty()) {
+            return componentsUtils.getResponseFormat(ActionStatus.OK);
+        }
+        for (Map.Entry<String, InterfaceDefinition> entryInstances : interfacesFromNodeType.entrySet()) {
+            String interfaceName = entryInstances.getKey().substring(entryInstances.getKey().lastIndexOf(".") + 1);
+            if (!currInterfacesMap.containsKey(interfaceName)) {
+                currInterfacesMap.put(interfaceName, entryInstances.getValue());
+            }
+        }
+
+        Map<String, InterfaceDefinition> instInterfacesMap = new HashMap<>();
+        if (MapUtils.isNotEmpty(instanceInterfacesMap)) {
+            for (UploadInterfaceInfo uploadInterfaceInfo : instanceInterfacesMap.values()) {
+                String interfaceName = uploadInterfaceInfo.getName();
+                if (!currInterfacesMap.containsKey(interfaceName)) {
+                    log.debug("failed to find interface {} ", interfaceName);
+                    return componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceName);
+                }
+                InterfaceDefinition currentInterfaceDef = currInterfacesMap.get(interfaceName);
+                Map<String, OperationDataDefinition> operationsToAdd = new HashMap<>();
+
+                Map<String, OperationDataDefinition> operations = uploadInterfaceInfo.getOperations();
+                for (Map.Entry<String, OperationDataDefinition> operation : operations.entrySet()) {
+                    OperationDataDefinition templateOperation = currentInterfaceDef.getOperationsMap().get(operation.getKey());
+                    OperationDataDefinition instanceOperation = operation.getValue();
+                    //Inputs
+                    ListDataDefinition<OperationInputDefinition> instanceInputs = instanceOperation.getInputs();
+                    mergeOperationInputDefinitions(templateOperation.getInputs(), instanceInputs);
+                    templateOperation.setInputs(instanceInputs);
+                    //Implementation
+                    templateOperation.setImplementation(instanceOperation.getImplementation());
+                    //Description
+                    templateOperation.setDescription(instanceOperation.getDescription());
+                    operationsToAdd.put(operation.getKey(), templateOperation);
+                }
+                InterfaceDefinition interfaceDef = new InterfaceDefinition();
+                interfaceDef.setModel(component.getModel());
+                interfaceDef.setType(currentInterfaceDef.getType());
+                interfaceDef.setUniqueId(currentInterfaceDef.getType());
+                interfaceDef.setDescription(uploadInterfaceInfo.getDescription());
+                interfaceDef.setOperations(operationsToAdd);
+                instInterfacesMap.put(interfaceName, interfaceDef);
+                currInterfacesMap.remove(interfaceName);
+            }
+        }
+        if (!currInterfacesMap.isEmpty()) {
+            for (InterfaceDefinition value : currInterfacesMap.values()) {
+                instInterfacesMap.put(value.getUniqueId(), value);
+            }
+        }
+        instInterfaces.put(currentCompInstance.getUniqueId(), instInterfacesMap);
+        return componentsUtils.getResponseFormat(ActionStatus.OK);
+    }
+
+    private void mergeOperationInputDefinitions(ListDataDefinition<OperationInputDefinition> inputsFromNodeType,
+                                                ListDataDefinition<OperationInputDefinition> instanceInputs) {
+        instanceInputs.getListToscaDataDefinition().forEach(
+            instanceInput -> inputsFromNodeType.getListToscaDataDefinition().stream().filter(
+                templateInput -> templateInput.getName().equals(instanceInput.getName())
+            ).forEach(
+                newInstanceInput -> {
+                    instanceInput.setSourceProperty(newInstanceInput.getSourceProperty());
+                    instanceInput.setSource(newInstanceInput.getSource());
+                    instanceInput.setType(newInstanceInput.getType());
+                }
+            )
+        );
+        instanceInputs.getListToscaDataDefinition().stream()
+            .filter(instanceInput -> inputsFromNodeType.getListToscaDataDefinition().stream().noneMatch(
+                inputFromNodeType -> inputFromNodeType.getName().equals(instanceInput.getName())
+            ))
+            .forEach(oldInput -> oldInput.setType("string"));
+    }
+
     protected void processComponentInstanceCapabilities(Map<String, DataTypeDefinition> allDataTypes,
                                                         Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> instCapabilties,
                                                         UploadComponentInstanceInfo uploadComponentInstanceInfo,