Implement 'Update Service by importing Tosca Template'-story
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / impl / ServiceBusinessLogic.java
index aa011e9..9874020 100644 (file)
@@ -19,6 +19,7 @@
  * Modifications copyright (c) 2019 Nokia
  * ================================================================================
  */
+
 package org.openecomp.sdc.be.components.impl;
 
 import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
@@ -45,6 +46,7 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
@@ -53,6 +55,8 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
 import lombok.Getter;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
@@ -67,6 +71,7 @@ import org.openecomp.sdc.be.components.health.HealthCheckBusinessLogic;
 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
+import org.openecomp.sdc.be.components.kafka.KafkaHandler;
 import org.openecomp.sdc.be.components.path.ForwardingPathValidator;
 import org.openecomp.sdc.be.components.utils.InterfaceOperationUtils;
 import org.openecomp.sdc.be.components.utils.PropertiesUtils;
@@ -97,9 +102,14 @@ import org.openecomp.sdc.be.datatypes.elements.InterfaceDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationInputDefinition;
 import org.openecomp.sdc.be.datatypes.elements.OperationOutputDefinition;
+import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.ToscaFunction;
+import org.openecomp.sdc.be.datatypes.elements.ToscaFunctionType;
+import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition;
 import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
+import org.openecomp.sdc.be.datatypes.enums.ModelTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
 import org.openecomp.sdc.be.externalapi.servlet.representation.ServiceDistributionReqInfo;
@@ -118,6 +128,7 @@ import org.openecomp.sdc.be.model.GroupInstanceProperty;
 import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.InterfaceDefinition;
 import org.openecomp.sdc.be.model.LifecycleStateEnum;
+import org.openecomp.sdc.be.model.Model;
 import org.openecomp.sdc.be.model.Operation;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.Resource;
@@ -133,6 +144,7 @@ import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
 import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
+import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
 import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
 import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
 import org.openecomp.sdc.be.plugins.ServiceCreationPlugin;
@@ -167,7 +179,7 @@ import org.springframework.web.context.WebApplicationContext;
 @org.springframework.stereotype.Component("serviceBusinessLogic")
 public class ServiceBusinessLogic extends ComponentBusinessLogic {
 
-    static final String IS_VALID = "isValid";
+    private static final String IS_VALID = "isValid";
     private static final String THE_SERVICE_WITH_SYSTEM_NAME_LOCKED = "The service with system name {} locked. ";
     private static final String FAILED_TO_LOCK_SERVICE_RESPONSE_IS = "Failed to lock service {}. Response is {}. ";
     private static final String AUDIT_BEFORE_SENDING_RESPONSE = "audit before sending response";
@@ -181,21 +193,19 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
     private final ServiceDistributionValidation serviceDistributionValidation;
     private final ForwardingPathValidator forwardingPathValidator;
     private final UiComponentDataConverter uiComponentDataConverter;
+    private final ModelOperation modelOperation;
+    private final ServiceRoleValidator serviceRoleValidator;
+    private final ServiceInstantiationTypeValidator serviceInstantiationTypeValidator;
+    private final ServiceCategoryValidator serviceCategoryValidator;
+    private final ServiceValidator serviceValidator;
+    private final GroupBusinessLogic groupBusinessLogic;
+    private final KafkaHandler kafkaHandler;
     private ForwardingPathOperation forwardingPathOperation;
     private AuditCassandraDao auditCassandraDao;
     private ServiceTypeValidator serviceTypeValidator;
     private List<ServiceCreationPlugin> serviceCreationPluginList;
     private ServiceFunctionValidator serviceFunctionValidator;
-    @Autowired
-    private ServiceRoleValidator serviceRoleValidator;
-    @Autowired
-    private ServiceInstantiationTypeValidator serviceInstantiationTypeValidator;
-    @Autowired
-    private ServiceCategoryValidator serviceCategoryValidator;
-    @Autowired
-    private ServiceValidator serviceValidator;
 
-    @Autowired
     public ServiceBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
                                 IGroupTypeOperation groupTypeOperation, GroupBusinessLogic groupBusinessLogic, InterfaceOperation interfaceOperation,
                                 InterfaceLifecycleOperation interfaceLifecycleTypeOperation, ArtifactsBusinessLogic artifactsBusinessLogic,
@@ -205,7 +215,11 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
                                 ComponentContactIdValidator componentContactIdValidator, ComponentNameValidator componentNameValidator,
                                 ComponentTagsValidator componentTagsValidator, ComponentValidator componentValidator,
                                 ComponentIconValidator componentIconValidator, ComponentProjectCodeValidator componentProjectCodeValidator,
-                                ComponentDescriptionValidator componentDescriptionValidator) {
+                                ComponentDescriptionValidator componentDescriptionValidator, ModelOperation modelOperation,
+                                final ServiceRoleValidator serviceRoleValidator,
+                                final ServiceInstantiationTypeValidator serviceInstantiationTypeValidator,
+                                final ServiceCategoryValidator serviceCategoryValidator, final ServiceValidator serviceValidator,
+                                KafkaHandler kafkaHandler) {
         super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, groupBusinessLogic, interfaceOperation,
             interfaceLifecycleTypeOperation, artifactsBusinessLogic, artifactToscaOperation, componentContactIdValidator, componentNameValidator,
             componentTagsValidator, componentValidator, componentIconValidator, componentProjectCodeValidator, componentDescriptionValidator);
@@ -214,6 +228,13 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
         this.serviceDistributionValidation = serviceDistributionValidation;
         this.forwardingPathValidator = forwardingPathValidator;
         this.uiComponentDataConverter = uiComponentDataConverter;
+        this.modelOperation = modelOperation;
+        this.serviceRoleValidator = serviceRoleValidator;
+        this.serviceInstantiationTypeValidator = serviceInstantiationTypeValidator;
+        this.serviceCategoryValidator = serviceCategoryValidator;
+        this.serviceValidator = serviceValidator;
+        this.groupBusinessLogic = groupBusinessLogic;
+        this.kafkaHandler = kafkaHandler;
     }
 
     @Autowired
@@ -632,16 +653,6 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
         return Either.left(archiveAudit);
     }
 
-    @VisibleForTesting
-    public void setServiceValidator(ServiceValidator serviceValidator) {
-        this.serviceValidator = serviceValidator;
-    }
-
-    @VisibleForTesting
-    public void setServiceCategoryValidator(ServiceCategoryValidator serviceCategoryValidator) {
-        this.serviceCategoryValidator = serviceCategoryValidator;
-    }
-
     private List<Map<String, Object>> getAuditingFieldsList(List<? extends AuditingGenericEvent> prevVerAuditList) {
         List<Map<String, Object>> prevVerAudit = new ArrayList<>();
         for (AuditingGenericEvent auditEvent : prevVerAuditList) {
@@ -661,12 +672,12 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
     public Either<Service, ResponseFormat> createService(Service service, User user) {
         // get user details
         user = validateUser(user, "Create Service", service, AuditingActionEnum.CREATE_RESOURCE, false);
-        log.debug("User returned from validation: " + user.toString());
+        log.debug("User returned from validation: {}", user);
         // validate user role
         validateUserRole(user, service, new ArrayList<>(), AuditingActionEnum.CREATE_RESOURCE, null);
         service.setCreatorUserId(user.getUserId());
         // warn on overridden fields
-        checkFieldsForOverideAttampt(service);
+        checkFieldsForOverideAttempt(service);
         // enrich object
         log.debug("enrich service with version and state");
         service.setState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
@@ -678,10 +689,10 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
         if (createServiceResponse.isRight()) {
             return createServiceResponse;
         }
-        return createServiceByDao(service, user).left().bind(c -> updateCatalog(c, ChangeTypeEnum.LIFECYCLE).left().map(r -> (Service) r));
+        return createServiceByDao(service, user).left().bind(c -> updateCatalog(c, ChangeTypeEnum.LIFECYCLE).left().map(Service.class::cast));
     }
 
-    private void checkFieldsForOverideAttampt(Service service) {
+    private void checkFieldsForOverideAttempt(Service service) {
         checkComponentFieldsForOverrideAttempt(service);
         if (service.getDistributionStatus() != null) {
             log.info("Distribution Status cannot be defined by user. This field will be overridden by the application");
@@ -705,7 +716,9 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
             if (service.isSubstituteCandidate() || genericTypeBusinessLogic.hasMandatorySubstitutionType(service)) {
                 final Resource genericType = fetchAndSetDerivedFromGenericType(service);
                 generatePropertiesFromGenericType(service, genericType);
-                generateAndAddInputsFromGenericTypeProperties(service, genericType);
+                if (Constants.DEFAULT_MODEL_NAME.equals(service.getModel()) || service.getModel() == null) {
+                    generateAndAddInputsFromGenericTypeProperties(service, genericType);
+                }
             }
             beforeCreate(service);
             Either<Service, StorageOperationStatus> dataModelResponse = toscaOperationFacade.createToscaComponent(service);
@@ -716,6 +729,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
                 ASDCKpiApi.countCreatedServicesKPI();
                 return Either.left(dataModelResponse.left().value());
             }
+            janusGraphDao.rollback();
             ResponseFormat responseFormat = componentsUtils
                 .getResponseFormatByComponent(componentsUtils.convertFromStorageResponse(dataModelResponse.right().value()), service,
                     ComponentTypeEnum.SERVICE);
@@ -786,13 +800,13 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
             componentsUtils.auditComponentAdmin(responseFormat, user, service, AuditingActionEnum.CREATE_SERVICE, ComponentTypeEnum.SERVICE);
             throw exp;
         }
-        service.setCreatorFullName(user.getFirstName() + " " + user.getLastName());
-        service.setContactId(service.getContactId().toLowerCase());
-        // Generate invariant UUID - must be here and not in operation since it
-
-        // should stay constant during clone
-        String invariantUUID = UniqueIdBuilder.buildInvariantUUID();
-        service.setInvariantUUID(invariantUUID);
+        if (!AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(actionEnum) &&
+            !AuditingActionEnum.UPDATE_SERVICE_TOSCA_MODEL.equals(actionEnum)) {
+            service.setCreatorFullName(user.getFirstName() + " " + user.getLastName());
+            service.setContactId(service.getContactId().toLowerCase());
+            // Generate invariant UUID - must be here and not in operation since it should stay constant during clone
+            service.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID());
+        }
         return Either.left(service);
     }
 
@@ -844,28 +858,49 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
             log.info("Restricted operation for user: {}, on service: {}", user.getUserId(), currentService.getCreatorUserId());
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION));
         }
-        Either<Service, ResponseFormat> validationRsponse = validateAndUpdateServiceMetadata(user, currentService, serviceUpdate);
-        if (validationRsponse.isRight()) {
+        List<String> subNodePropsToBeRemoved = getSubstitutionNodePropertiesToBeRemoved(currentService, serviceUpdate);
+        List<PropertyDefinition> subNodePropsToBeAdded = getSubstitutionNodePropertiesToBeAdded(currentService, serviceUpdate);
+        boolean subNodeChanged = isSubstitutionNodeChanged(currentService, serviceUpdate);
+        Either<Service, ResponseFormat> validationResponse =
+            validateAndUpdateServiceMetadata(user, currentService, serviceUpdate, subNodeChanged, ListUtils.emptyIfNull(subNodePropsToBeRemoved));
+        if (validationResponse.isRight()) {
             log.info("service update metadata: validations field.");
-            return validationRsponse;
+            return validationResponse;
         }
-        Service serviceToUpdate = validationRsponse.left().value();
+        Service serviceToUpdate = validationResponse.left().value();
         // lock resource
         lockComponent(serviceId, currentService, "Update Service Metadata");
         try {
+            if (subNodeChanged) {
+                if (!subNodePropsToBeRemoved.isEmpty()) {
+                    removePropertiesFromService(currentService, subNodePropsToBeRemoved);
+                    removeInputsFromService(currentService, subNodePropsToBeRemoved);
+                }
+                if (!subNodePropsToBeAdded.isEmpty()) {
+                    addPropertiesToService(currentService, subNodePropsToBeAdded);
+                    if (Constants.DEFAULT_MODEL_NAME.equals(currentService.getModel()) || currentService.getModel() == null) {
+                        addInputsToService(currentService, subNodePropsToBeAdded);
+                    }
+                }
+            }
             return toscaOperationFacade.updateToscaElement(serviceToUpdate).right().map(rf -> {
                 janusGraphDao.rollback();
                 BeEcompErrorManager.getInstance().logBeSystemError("Update Service Metadata");
                 log.debug("failed to update sevice {}", serviceToUpdate.getUniqueId());
                 return (componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
-            }).left().bind(c -> updateCatalogAndCommit(c));
+            }).left().bind(this::updateCatalogAndCommit);
+        } catch (ComponentException e) {
+            janusGraphDao.rollback();
+            BeEcompErrorManager.getInstance().logBeSystemError("Update Service Metadata");
+            log.debug("failed to update sevice {}", serviceToUpdate.getUniqueId());
+            return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
         } finally {
             graphLockOperation.unlockComponent(serviceId, NodeTypeEnum.Service);
         }
     }
 
     private Either<Service, ResponseFormat> updateCatalogAndCommit(Service service) {
-        Either<Service, ResponseFormat> res = updateCatalog(service, ChangeTypeEnum.LIFECYCLE).left().map(s -> (Service) s);
+        Either<Service, ResponseFormat> res = updateCatalog(service, ChangeTypeEnum.LIFECYCLE).left().map(Service.class::cast);
         janusGraphDao.commit();
         return res;
     }
@@ -1029,9 +1064,18 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
     }
 
     @VisibleForTesting
-    Either<Service, ResponseFormat> validateAndUpdateServiceMetadata(User user, Service currentService, Service serviceUpdate) {
+    Either<Service, ResponseFormat> validateAndUpdateServiceMetadata(User user, Service currentService, Service serviceUpdate, boolean subNodeChanged,
+                                                                     List<String> subNodePropsToBeRemoved) {
         try {
             boolean hasBeenCertified = ValidationUtils.hasBeenCertified(currentService.getVersion());
+            if (subNodeChanged) {
+                if (!subNodePropsToBeRemoved.isEmpty()) {
+                    areSubstitutionNodePropertiesInUse(currentService, subNodePropsToBeRemoved);
+                }
+                currentService.setDerivedFromGenericVersion(serviceUpdate.getDerivedFromGenericVersion());
+                currentService.setDerivedFromGenericType(serviceUpdate.getDerivedFromGenericType());
+            }
+
             Either<Boolean, ResponseFormat> response = validateAndUpdateCategory(user, currentService, serviceUpdate, hasBeenCertified,
                 UPDATE_SERVICE_METADATA);
             if (response.isRight()) {
@@ -1098,6 +1142,168 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
         }
     }
 
+    private void addPropertiesToService(Service currentService, List<PropertyDefinition> subNodePropsToBeAdded) {
+        ListUtils.emptyIfNull(subNodePropsToBeAdded).forEach(prop -> {
+            Either<PropertyDefinition, StorageOperationStatus> addPropertyEither =
+                toscaOperationFacade.addPropertyToComponent(prop, currentService);
+            if (addPropertyEither.isRight()) {
+                throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
+            }
+        });
+    }
+
+    private void addInputsToService(Service currentService, List<PropertyDefinition> subNodePropsToBeAdded) {
+        ListUtils.emptyIfNull(subNodePropsToBeAdded).forEach(prop -> {
+            InputDefinition inputDef = new InputDefinition(prop);
+            Either<InputDefinition, StorageOperationStatus> status =
+                toscaOperationFacade.addInputToComponent(prop.getName(), inputDef, currentService);
+            if (status.isRight()) {
+                throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
+            }
+        });
+    }
+
+    private void removePropertiesFromService(Service currentService, List<String> subNodePropsToBeRemoved) {
+        List<PropertyDefinition> props = currentService.getProperties();
+        List<String> propsUniqueIdsToBeRemoved =
+            props.stream().filter(prop -> subNodePropsToBeRemoved.contains(prop.getName())).map(PropertyDefinition::getUniqueId)
+                .collect(Collectors.toList());
+        ListUtils.emptyIfNull(props).stream().filter(prop -> propsUniqueIdsToBeRemoved.contains(prop.getUniqueId())).forEach(prop -> {
+            StorageOperationStatus status = toscaOperationFacade.deletePropertyOfComponent(currentService, prop.getName());
+            if (status != StorageOperationStatus.OK) {
+                throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
+            }
+        });
+    }
+
+    private void removeInputsFromService(Service currentService, List<String> subNodePropsToBeRemoved) {
+        List<PropertyDefinition> props = currentService.getProperties();
+        List<InputDefinition> inputs = currentService.getInputs();
+        List<String> propsUniqueIdsToBeRemoved =
+            props.stream().filter(prop -> subNodePropsToBeRemoved.contains(prop.getName())).map(PropertyDefinition::getUniqueId)
+                .collect(Collectors.toList());
+        ListUtils.emptyIfNull(inputs).stream().filter(input -> input.isMappedToComponentProperty() &&
+            (propsUniqueIdsToBeRemoved.contains(input.getPropertyId()) || subNodePropsToBeRemoved.contains(input.getName()))).forEach(input -> {
+            StorageOperationStatus status = toscaOperationFacade.deleteInputOfResource(currentService, input.getName());
+            if (status != StorageOperationStatus.OK) {
+                throw new ByActionStatusComponentException(ActionStatus.GENERAL_ERROR);
+            }
+        });
+    }
+
+    private void areSubstitutionNodePropertiesInUse(Service service, List<String> subNodePropsToBeRemoved) {
+        Map<String, List<ComponentInstanceProperty>> componentInstancesProps = service.getComponentInstancesProperties();
+        List<String> propsUniqueIdsToBeRemoved =
+            ListUtils.emptyIfNull(service.getProperties()).stream().filter(prop -> subNodePropsToBeRemoved.contains(prop.getName()))
+                .map(PropertyDefinition::getUniqueId)
+                .collect(Collectors.toList());
+        List<String> inputsUniqueIdsToBeRemoved = ListUtils.emptyIfNull(service.getInputs()).stream()
+            .filter(input -> propsUniqueIdsToBeRemoved.contains(input.getPropertyId()) || subNodePropsToBeRemoved.contains(input.getName()))
+            .map(PropertyDefinition::getUniqueId)
+            .collect(Collectors.toList());
+        Map<String, List<String>> inUse = new HashMap<>();
+        if (componentInstancesProps != null && !componentInstancesProps.isEmpty()) {
+            componentInstancesProps.forEach((compInstanceId, listOfProps) -> {
+                List<String> propsInUse = new ArrayList<>();
+                listOfProps.stream()
+                    .filter(PropertyDataDefinition::isToscaFunction)
+                    .filter(compProp -> ToscaFunctionType.isGetFunction(compProp.getToscaFunction().getType()))
+                    .forEach(compProp -> {
+                        ToscaFunction toscaFunction = compProp.getToscaFunction();
+                        ToscaGetFunctionDataDefinition toscaGetFunction = (ToscaGetFunctionDataDefinition) toscaFunction;
+                        String propName = toscaGetFunction.getPropertyName();
+                        String propUniqueId = toscaGetFunction.getPropertyUniqueId();
+                        if (inputsUniqueIdsToBeRemoved.contains(propUniqueId) || propsUniqueIdsToBeRemoved.contains(propUniqueId) ||
+                            subNodePropsToBeRemoved.contains(propName)) {
+                            propsInUse.add(compProp.getName());
+                        }
+                    });
+                if (!propsInUse.isEmpty()) {
+                    Optional<ComponentInstance> componentInstance = service.getComponentInstanceById(compInstanceId);
+                    componentInstance.ifPresent(instance -> inUse.put(instance.getName(), propsInUse));
+                }
+
+            });
+        }
+        if (!inUse.isEmpty()) {
+            String propsInUse = inUse.entrySet().stream().map(entry -> {
+                String properties = entry.getValue().stream().map(Object::toString).collect(Collectors.joining(", "));
+                return properties + " on " + entry.getKey();
+            }).collect(Collectors.joining(", properties "));
+            throw new ByActionStatusComponentException(ActionStatus.SUBSTITUTION_NODE_TYPE_PROPERTY_IN_USE, propsInUse);
+        }
+    }
+
+
+    private boolean isSubstitutionNodeChanged(Service currentService, Service updatedService) {
+        String currentServiceType = currentService.getDerivedFromGenericType();
+        String updatedServiceType = updatedService.getDerivedFromGenericType();
+        String currentServiceVersion = currentService.getDerivedFromGenericVersion();
+        String updatedServiceVersion = updatedService.getDerivedFromGenericVersion();
+        return !(StringUtils.equals(currentServiceType, updatedServiceType) && StringUtils.equals(currentServiceVersion, updatedServiceVersion));
+    }
+
+    private List<String> getSubstitutionNodePropertiesToBeRemoved(Service currentService, Service serviceUpdate) {
+        List<PropertyDefinition> currentProps = ListUtils.emptyIfNull(fetchDerivedFromGenericType(currentService, null).getProperties());
+        List<PropertyDefinition> updatedProps = ListUtils.emptyIfNull(fetchDerivedFromGenericType(serviceUpdate, null).getProperties());
+        if (!StringUtils.equals(currentService.getDerivedFromGenericType(), serviceUpdate.getDerivedFromGenericType())) {
+            return currentProps.stream().map(PropertyDefinition::getName).collect(Collectors.toList());
+        }
+
+        Map<String, PropertyDefinition> currentPropsMap = currentProps.stream().collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
+        Map<String, PropertyDefinition> updatedPropsMap = updatedProps.stream().collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
+
+        List<String> propNamesToBeRemoved = new ArrayList<>();
+        for (String currentPropertyName : currentPropsMap.keySet()) {
+            if (updatedPropsMap.containsKey(currentPropertyName)) {
+                if (!haveSameType(currentPropsMap.get(currentPropertyName), updatedPropsMap.get(currentPropertyName))) {
+                    propNamesToBeRemoved.add(currentPropertyName);
+                }
+            } else {
+                propNamesToBeRemoved.add(currentPropertyName);
+            }
+        }
+
+        return propNamesToBeRemoved;
+    }
+
+    private boolean haveSameType(final PropertyDefinition property1, final PropertyDefinition property2) {
+        if (property1.getType().equals("list")) {
+            return property2.getType().equals("list") && property1.getSchema().equals(property2.getSchema());
+        }
+        if (property1.getType().equals("map")) {
+            return property2.getType().equals("map") && property1.getSchema().equals(property2.getSchema());
+        }
+        return property1.getType().equals(property2.getType());
+    }
+
+    private List<PropertyDefinition> getSubstitutionNodePropertiesToBeAdded(Service currentService, Service serviceUpdate) {
+        List<PropertyDefinition> propsInCurrentVersion = ListUtils.emptyIfNull(fetchDerivedFromGenericType(currentService, null).getProperties());
+        List<PropertyDefinition> propsInUpdatedVersion = ListUtils.emptyIfNull(fetchDerivedFromGenericType(serviceUpdate, null).getProperties());
+        if (!StringUtils.equals(currentService.getDerivedFromGenericType(), serviceUpdate.getDerivedFromGenericType())) {
+            return propsInUpdatedVersion;
+        }
+
+        Map<String, PropertyDefinition> mapOfPropsInCurrentVersion = propsInCurrentVersion.stream()
+            .collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
+        Map<String, PropertyDefinition> mapOfPropsInUpdatedVersion = propsInUpdatedVersion.stream()
+            .collect(Collectors.toMap(prop -> prop.getName(), prop -> prop));
+
+        List<PropertyDefinition> propsToBeAdded = new ArrayList<>();
+        for (Entry<String, PropertyDefinition> propertyInUpdatedVersion : mapOfPropsInUpdatedVersion.entrySet()) {
+            if (mapOfPropsInCurrentVersion.containsKey(propertyInUpdatedVersion.getKey())) {
+                if (!haveSameType(mapOfPropsInCurrentVersion.get(propertyInUpdatedVersion.getKey()), propertyInUpdatedVersion.getValue())) {
+                    propsToBeAdded.add(propertyInUpdatedVersion.getValue());
+                }
+            } else {
+                propsToBeAdded.add(propertyInUpdatedVersion.getValue());
+            }
+        }
+
+        return propsToBeAdded;
+    }
+
+
     private void verifyValuesAreIdentical(Object updatedValue, Object originalValue, String fieldName) {
         if (updatedValue != null && !updatedValue.equals(originalValue)) {
             log.info("update service: received request to update {} to {} the field is not updatable ignoring.", fieldName, updatedValue);
@@ -1301,7 +1507,39 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
         return Either.left(serviceRelations);
     }
 
-    public ResponseFormat deleteService(String serviceId, User user) {
+    public void deleteServiceAllVersions(String serviceId, User user) {
+        validateUserExists(user);
+        Either<Service, StorageOperationStatus> serviceStatus = toscaOperationFacade.getToscaElement(serviceId);
+        if (serviceStatus.isRight()) {
+            log.debug("Failed to get service {}", serviceId);
+            componentException(serviceStatus.right().value());
+        }
+        Service service = serviceStatus.left().value();
+        if (Boolean.FALSE.equals(service.isArchived())) {
+            log.debug("The service, {}, requested for delete has not been archived.", serviceId);
+            throw new ComponentException(ActionStatus.COMPONENT_NOT_ARCHIVED, serviceId);
+        }
+        List<String> deletedServiceList = new ArrayList<>();
+        try {
+            String model = service.getModel();
+            final Optional<Model> modelOptional = modelOperation.findModelByName(model);
+            deletedServiceList = toscaOperationFacade.deleteService(service.getInvariantUUID(), true);
+            if (log.isDebugEnabled()) {
+                deletedServiceList.forEach(deletedS -> log.debug("Component {} was deleted.", deletedS));
+            }
+            if (modelOptional.isPresent() && modelOptional.get().getModelType() == ModelTypeEnum.NORMATIVE_EXTENSION) {
+                modelOperation.deleteModel(modelOptional.get(), false);
+            }
+            toscaOperationFacade.commitAndCheck(service.getUniqueId());
+            updateCatalog(service, ChangeTypeEnum.DELETE);
+        } catch (ComponentException exception) {
+            log.debug("Failed to delete service, {}, in ServiceServlet", serviceId);
+            janusGraphDao.rollback();
+            throw exception;
+        }
+    }
+
+    public ResponseFormat markServiceForDeletion(String serviceId, User user) {
         ResponseFormat responseFormat;
         validateUserExists(user);
         Either<Service, StorageOperationStatus> serviceStatus = toscaOperationFacade.getToscaElement(serviceId);
@@ -1446,7 +1684,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
                                                         Boolean isServiceApi) {
         ArtifactDefinition artifactInfo = artifactsBusinessLogic
             .createArtifactPlaceHolderInfo(serviceId, logicalName, artifactInfoMap, user, ArtifactGroupTypeEnum.INFORMATIONAL);
-        if (isServiceApi) {
+        if (Boolean.TRUE.equals(isServiceApi)) {
             artifactInfo.setMandatory(false);
             artifactInfo.setServiceApi(true);
         }
@@ -1500,14 +1738,16 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
             log.trace("Update environment name to be {} instead of {}", configuredEnvName, envName);
             envName = configuredEnvName;
         }
-        // DE194021
-        ServletContext servletContext = request.getSession().getServletContext();
-        boolean isDistributionEngineUp = getHealthCheckBL(servletContext).isDistributionEngineUp(); // DE
-        if (!isDistributionEngineUp) {
-            BeEcompErrorManager.getInstance().logBeSystemError("Distribution Engine is DOWN");
-            log.debug("Distribution Engine is DOWN");
-            response = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
-            return Either.right(response);
+        if (!kafkaHandler.isKafkaActive()) {
+            // DE194021
+            ServletContext servletContext = request.getSession().getServletContext();
+            boolean isDistributionEngineUp = getHealthCheckBL(servletContext).isDistributionEngineUp(); // DE
+            if (!isDistributionEngineUp) {
+                BeEcompErrorManager.getInstance().logBeSystemError("Distribution Engine is DOWN");
+                log.debug("Distribution Engine is DOWN");
+                response = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
+                return Either.right(response);
+            }
         }
         Either<Service, StorageOperationStatus> serviceRes = toscaOperationFacade.getToscaElement(serviceId);
         if (serviceRes.isRight()) {
@@ -1519,7 +1759,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
             return Either.right(response);
         }
         Service service = serviceRes.left().value();
-        if (service.isArchived()) {
+        if (Boolean.TRUE.equals(service.isArchived())) {
             log.info("Component is archived. Component id: {}", serviceId);
             return Either.right(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_IS_ARCHIVED, service.getName()));
         }
@@ -1621,123 +1861,6 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
         return asList;
     }
 
-    private List<GroupInstance> collectGroupsInstanceForCompInstance(ComponentInstance currVF) {
-        Map<String, ArtifactDefinition> deploymentArtifacts = currVF.getDeploymentArtifacts();
-        if (currVF.getGroupInstances() != null) {
-            currVF.getGroupInstances().forEach(gi -> gi.alignArtifactsUuid(deploymentArtifacts));
-        }
-        return currVF.getGroupInstances();
-    }
-
-    private ArtifactDefinition getVfModuleInstArtifactForCompInstance(ComponentInstance currVF, Service service, Wrapper<String> payloadWrapper,
-                                                                      Wrapper<ResponseFormat> responseWrapper) {
-        ArtifactDefinition vfModuleAertifact = null;
-        if (MapUtils.isNotEmpty(currVF.getDeploymentArtifacts())) {
-            final Optional<ArtifactDefinition> optionalVfModuleArtifact = currVF.getDeploymentArtifacts().values().stream()
-                .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.VF_MODULES_METADATA.getType())).findAny();
-            if (optionalVfModuleArtifact.isPresent()) {
-                vfModuleAertifact = optionalVfModuleArtifact.get();
-            }
-        }
-        if (vfModuleAertifact == null) {
-            Either<ArtifactDefinition, ResponseFormat> createVfModuleArtifact = createVfModuleArtifact(currVF, service,
-                payloadWrapper.getInnerElement());
-            if (createVfModuleArtifact.isLeft()) {
-                vfModuleAertifact = createVfModuleArtifact.left().value();
-            } else {
-                responseWrapper.setInnerElement(createVfModuleArtifact.right().value());
-            }
-        }
-        return vfModuleAertifact;
-    }
-
-    private void fillVfModuleInstHeatEnvPayload(List<GroupInstance> groupsForCurrVF, Wrapper<String> payloadWrapper) {
-        List<VfModuleArtifactPayload> vfModulePayloads = new ArrayList<>();
-        if (groupsForCurrVF != null) {
-            for (GroupInstance groupInstance : groupsForCurrVF) {
-                VfModuleArtifactPayload modulePayload = new VfModuleArtifactPayload(groupInstance);
-                vfModulePayloads.add(modulePayload);
-            }
-            vfModulePayloads.sort(VfModuleArtifactPayload::compareByGroupName);
-            final Gson gson = new GsonBuilder().setPrettyPrinting().create();
-            String vfModulePayloadString = gson.toJson(vfModulePayloads);
-            payloadWrapper.setInnerElement(vfModulePayloadString);
-        }
-    }
-
-    private Either<ArtifactDefinition, ResponseFormat> generateVfModuleInstanceArtifact(User modifier, ComponentInstance currVFInstance,
-                                                                                        Service service, boolean shouldLock, boolean inTransaction) {
-        ArtifactDefinition vfModuleArtifact = null;
-        Wrapper<ResponseFormat> responseWrapper = new Wrapper<>();
-        Wrapper<String> payloadWrapper = new Wrapper<>();
-        List<GroupInstance> groupsForCurrVF = collectGroupsInstanceForCompInstance(currVFInstance);
-        if (responseWrapper.isEmpty()) {
-            fillVfModuleInstHeatEnvPayload(groupsForCurrVF, payloadWrapper);
-        }
-        if (responseWrapper.isEmpty() && payloadWrapper.getInnerElement() != null) {
-            vfModuleArtifact = getVfModuleInstArtifactForCompInstance(currVFInstance, service, payloadWrapper, responseWrapper);
-        }
-        if (responseWrapper.isEmpty() && vfModuleArtifact != null) {
-            vfModuleArtifact = fillVfModulePayload(modifier, currVFInstance, vfModuleArtifact, shouldLock, inTransaction, payloadWrapper,
-                responseWrapper, service);
-        }
-        Either<ArtifactDefinition, ResponseFormat> result;
-        if (responseWrapper.isEmpty()) {
-            result = Either.left(vfModuleArtifact);
-        } else {
-            result = Either.right(responseWrapper.getInnerElement());
-        }
-        return result;
-    }
-
-    private ArtifactDefinition fillVfModulePayload(User modifier, ComponentInstance currVF, ArtifactDefinition vfModuleArtifact, boolean shouldLock,
-                                                   boolean inTransaction, Wrapper<String> payloadWrapper, Wrapper<ResponseFormat> responseWrapper,
-                                                   Service service) {
-        ArtifactDefinition result = null;
-        Either<ArtifactDefinition, ResponseFormat> eitherPayload = artifactsBusinessLogic
-            .generateArtifactPayload(vfModuleArtifact, ComponentTypeEnum.RESOURCE_INSTANCE, service, currVF.getName(), modifier, shouldLock,
-                inTransaction, System::currentTimeMillis, () -> Either.left(
-                    artifactsBusinessLogic.createEsArtifactData(vfModuleArtifact, payloadWrapper.getInnerElement().getBytes(StandardCharsets.UTF_8))),
-                currVF.getUniqueId());
-        if (eitherPayload.isLeft()) {
-            result = eitherPayload.left().value();
-        } else {
-            responseWrapper.setInnerElement(eitherPayload.right().value());
-        }
-        if (result == null) {
-            result = vfModuleArtifact;
-        }
-        return result;
-    }
-
-    private Either<ArtifactDefinition, ResponseFormat> createVfModuleArtifact(ComponentInstance currVF, Service service,
-                                                                              String vfModulePayloadString) {
-        ArtifactDefinition vfModuleArtifactDefinition = new ArtifactDefinition();
-        String newCheckSum = null;
-        vfModuleArtifactDefinition.setDescription("Auto-generated VF Modules information artifact");
-        vfModuleArtifactDefinition.setArtifactDisplayName("Vf Modules Metadata");
-        vfModuleArtifactDefinition.setArtifactType(ArtifactTypeEnum.VF_MODULES_METADATA.getType());
-        vfModuleArtifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.DEPLOYMENT);
-        vfModuleArtifactDefinition.setArtifactLabel("vfModulesMetadata");
-        vfModuleArtifactDefinition.setTimeout(0);
-        vfModuleArtifactDefinition.setArtifactName(currVF.getNormalizedName() + "_modules.json");
-        vfModuleArtifactDefinition.setPayloadData(vfModulePayloadString);
-        if (vfModulePayloadString != null) {
-            newCheckSum = GeneralUtility.calculateMD5Base64EncodedByByteArray(vfModulePayloadString.getBytes());
-        }
-        vfModuleArtifactDefinition.setArtifactChecksum(newCheckSum);
-        Either<ArtifactDefinition, StorageOperationStatus> addArtifactToComponent = artifactToscaOperation
-            .addArtifactToComponent(vfModuleArtifactDefinition, service, NodeTypeEnum.ResourceInstance, true, currVF.getUniqueId());
-        Either<ArtifactDefinition, ResponseFormat> result;
-        if (addArtifactToComponent.isLeft()) {
-            result = Either.left(addArtifactToComponent.left().value());
-        } else {
-            result = Either
-                .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(addArtifactToComponent.right().value())));
-        }
-        return result;
-    }
-
     public Either<Service, ResponseFormat> generateHeatEnvArtifacts(Service service, User modifier, boolean shouldLock, boolean inTransaction) {
         Function<ComponentInstance, List<ArtifactGenerator<ArtifactDefinition>>> artifactTaskGeneratorCreator = resourceInstance ->
             // Get All Deployment Artifacts
@@ -2026,7 +2149,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
             log.error("Exception occured during update Group Instance property values: {}", e.getMessage(), e);
             actionResult = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
         } finally {
-            if (lockResult != null && lockResult.isLeft() && lockResult.left().value()) {
+            if (lockResult != null && lockResult.isLeft() && Boolean.TRUE.equals(lockResult.left().value())) {
                 graphLockOperation.unlockComponentByName(component.getSystemName(), component.getUniqueId(), NodeTypeEnum.Service);
             }
         }
@@ -2196,7 +2319,8 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
         }
         Service service = serviceResultEither.left().value();
         if (dataParamsToReturn.contains(ComponentFieldsEnum.INPUTS.getValue())) {
-            ListUtils.emptyIfNull(service.getInputs()).forEach(input -> input.setConstraints(setInputConstraint(input)));
+            ListUtils.emptyIfNull(service.getInputs()).stream().filter(input -> CollectionUtils.isEmpty(input.getConstraints()))
+                .forEach(input -> input.setConstraints(setInputConstraint(input)));
         }
         UiComponentDataTransfer dataTransfer = uiComponentDataConverter.getUiDataTransferFromServiceByParams(service, dataParamsToReturn);
         return Either.left(dataTransfer);
@@ -2208,35 +2332,24 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
     }
 
     public boolean isServiceExist(String serviceName) {
-        Either<Service, StorageOperationStatus> latestByName = toscaOperationFacade.getLatestByServiceName(serviceName);
-        return latestByName.isLeft();
+        return toscaOperationFacade.getLatestByServiceName(serviceName).isLeft();
     }
 
-    abstract class ArtifactGenerator<CallVal> implements Callable<Either<CallVal, ResponseFormat>> {
+    interface ArtifactGenerator<CallVal> extends Callable<Either<CallVal, ResponseFormat>> {
 
     }
 
     @Getter
-    class HeatEnvArtifactGenerator extends ArtifactGenerator<ArtifactDefinition> {
+    @AllArgsConstructor(access = AccessLevel.PRIVATE)
+    class HeatEnvArtifactGenerator implements ArtifactGenerator<ArtifactDefinition> {
 
         private ArtifactDefinition artifactDefinition;
         private Service service;
         private String resourceInstanceName;
         private User modifier;
-        private String instanceId;
         private boolean shouldLock;
         private boolean inTransaction;
-
-        HeatEnvArtifactGenerator(ArtifactDefinition artifactDefinition, Service service, String resourceInstanceName, User modifier,
-                                 boolean shouldLock, boolean inTransaction, String instanceId) {
-            this.artifactDefinition = artifactDefinition;
-            this.service = service;
-            this.resourceInstanceName = resourceInstanceName;
-            this.modifier = modifier;
-            this.shouldLock = shouldLock;
-            this.instanceId = instanceId;
-            this.inTransaction = inTransaction;
-        }
+        private String instanceId;
 
         @Override
         public Either<ArtifactDefinition, ResponseFormat> call() throws Exception {
@@ -2246,22 +2359,128 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
         }
     }
 
-    class VfModuleArtifactGenerator extends ArtifactGenerator<ArtifactDefinition> {
+    @AllArgsConstructor(access = AccessLevel.PRIVATE)
+    class VfModuleArtifactGenerator implements ArtifactGenerator<ArtifactDefinition> {
 
-        boolean shouldLock;
-        boolean inTransaction;
         private User user;
         private ComponentInstance componentInstance;
         private Service service;
+        private boolean shouldLock;
+        private boolean inTransaction;
+
+        private Either<ArtifactDefinition, ResponseFormat> generateVfModuleInstanceArtifact(User modifier, ComponentInstance currVFInstance,
+                                                                                            Service service, boolean shouldLock,
+                                                                                            boolean inTransaction) {
+            ArtifactDefinition vfModuleArtifact = null;
+            Wrapper<ResponseFormat> responseWrapper = new Wrapper<>();
+            Wrapper<String> payloadWrapper = new Wrapper<>();
+            List<GroupInstance> groupsForCurrVF = collectGroupsInstanceForCompInstance(currVFInstance);
+            if (responseWrapper.isEmpty()) {
+                fillVfModuleInstHeatEnvPayload(groupsForCurrVF, payloadWrapper);
+            }
+            if (responseWrapper.isEmpty() && payloadWrapper.getInnerElement() != null) {
+                vfModuleArtifact = getVfModuleInstArtifactForCompInstance(currVFInstance, service, payloadWrapper, responseWrapper);
+            }
+            if (responseWrapper.isEmpty() && vfModuleArtifact != null) {
+                vfModuleArtifact = fillVfModulePayload(modifier, currVFInstance, vfModuleArtifact, shouldLock, inTransaction, payloadWrapper,
+                    responseWrapper, service);
+            }
+            if (responseWrapper.isEmpty()) {
+                return Either.left(vfModuleArtifact);
+            } else {
+                return Either.right(responseWrapper.getInnerElement());
+            }
+        }
+
+        private void fillVfModuleInstHeatEnvPayload(List<GroupInstance> groupsForCurrVF, Wrapper<String> payloadWrapper) {
+            List<VfModuleArtifactPayload> vfModulePayloads = new ArrayList<>();
+            if (groupsForCurrVF != null) {
+                for (GroupInstance groupInstance : groupsForCurrVF) {
+                    VfModuleArtifactPayload modulePayload = new VfModuleArtifactPayload(groupInstance);
+                    vfModulePayloads.add(modulePayload);
+                }
+                vfModulePayloads.sort(VfModuleArtifactPayload::compareByGroupName);
+                final Gson gson = new GsonBuilder().setPrettyPrinting().create();
+                String vfModulePayloadString = gson.toJson(vfModulePayloads);
+                payloadWrapper.setInnerElement(vfModulePayloadString);
+            }
+        }
+
+        private ArtifactDefinition getVfModuleInstArtifactForCompInstance(ComponentInstance currVF, Service service, Wrapper<String> payloadWrapper,
+                                                                          Wrapper<ResponseFormat> responseWrapper) {
+            ArtifactDefinition vfModuleAertifact = null;
+            if (MapUtils.isNotEmpty(currVF.getDeploymentArtifacts())) {
+                final Optional<ArtifactDefinition> optionalVfModuleArtifact = currVF.getDeploymentArtifacts().values().stream()
+                    .filter(p -> p.getArtifactType().equals(ArtifactTypeEnum.VF_MODULES_METADATA.getType())).findAny();
+                if (optionalVfModuleArtifact.isPresent()) {
+                    vfModuleAertifact = optionalVfModuleArtifact.get();
+                }
+            }
+            if (vfModuleAertifact == null) {
+                Either<ArtifactDefinition, ResponseFormat> createVfModuleArtifact = createVfModuleArtifact(currVF, service,
+                    payloadWrapper.getInnerElement());
+                if (createVfModuleArtifact.isLeft()) {
+                    vfModuleAertifact = createVfModuleArtifact.left().value();
+                } else {
+                    responseWrapper.setInnerElement(createVfModuleArtifact.right().value());
+                }
+            }
+            return vfModuleAertifact;
+        }
+
+        private List<GroupInstance> collectGroupsInstanceForCompInstance(ComponentInstance currVF) {
+            if (currVF.getGroupInstances() != null) {
+                currVF.getGroupInstances().forEach(gi -> gi.alignArtifactsUuid(currVF.getDeploymentArtifacts()));
+            }
+            return currVF.getGroupInstances();
+        }
 
-        private VfModuleArtifactGenerator(User user, ComponentInstance componentInstance, Service service, boolean shouldLock,
-                                          boolean inTransaction) {
-            super();
-            this.user = user;
-            this.componentInstance = componentInstance;
-            this.service = service;
-            this.shouldLock = shouldLock;
-            this.inTransaction = inTransaction;
+        private Either<ArtifactDefinition, ResponseFormat> createVfModuleArtifact(ComponentInstance currVF, Service service,
+                                                                                  String vfModulePayloadString) {
+            ArtifactDefinition vfModuleArtifactDefinition = new ArtifactDefinition();
+            String newCheckSum = null;
+            vfModuleArtifactDefinition.setDescription("Auto-generated VF Modules information artifact");
+            vfModuleArtifactDefinition.setArtifactDisplayName("Vf Modules Metadata");
+            vfModuleArtifactDefinition.setArtifactType(ArtifactTypeEnum.VF_MODULES_METADATA.getType());
+            vfModuleArtifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.DEPLOYMENT);
+            vfModuleArtifactDefinition.setArtifactLabel("vfModulesMetadata");
+            vfModuleArtifactDefinition.setTimeout(0);
+            vfModuleArtifactDefinition.setArtifactName(currVF.getNormalizedName() + "_modules.json");
+            vfModuleArtifactDefinition.setPayloadData(vfModulePayloadString);
+            if (vfModulePayloadString != null) {
+                newCheckSum = GeneralUtility.calculateMD5Base64EncodedByByteArray(vfModulePayloadString.getBytes());
+            }
+            vfModuleArtifactDefinition.setArtifactChecksum(newCheckSum);
+            Either<ArtifactDefinition, StorageOperationStatus> addArtifactToComponent = artifactToscaOperation
+                .addArtifactToComponent(vfModuleArtifactDefinition, service, NodeTypeEnum.ResourceInstance, true, currVF.getUniqueId());
+            if (addArtifactToComponent.isLeft()) {
+                return Either.left(addArtifactToComponent.left().value());
+            } else {
+                return Either
+                    .right(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(addArtifactToComponent.right().value())));
+            }
+        }
+
+        private ArtifactDefinition fillVfModulePayload(User modifier, ComponentInstance currVF, ArtifactDefinition vfModuleArtifact,
+                                                       boolean shouldLock,
+                                                       boolean inTransaction, Wrapper<String> payloadWrapper, Wrapper<ResponseFormat> responseWrapper,
+                                                       Service service) {
+            ArtifactDefinition result = null;
+            Either<ArtifactDefinition, ResponseFormat> eitherPayload = artifactsBusinessLogic
+                .generateArtifactPayload(vfModuleArtifact, ComponentTypeEnum.RESOURCE_INSTANCE, service, currVF.getName(), modifier, shouldLock,
+                    inTransaction, System::currentTimeMillis, () -> Either.left(
+                        artifactsBusinessLogic.createEsArtifactData(vfModuleArtifact,
+                            payloadWrapper.getInnerElement().getBytes(StandardCharsets.UTF_8))),
+                    currVF.getUniqueId());
+            if (eitherPayload.isLeft()) {
+                result = eitherPayload.left().value();
+            } else {
+                responseWrapper.setInnerElement(eitherPayload.right().value());
+            }
+            if (result == null) {
+                result = vfModuleArtifact;
+            }
+            return result;
         }
 
         @Override