X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=catalog-be%2Fsrc%2Fmain%2Fjava%2Forg%2Fopenecomp%2Fsdc%2Fbe%2Fcomponents%2Fimpl%2FServiceImportBusinessLogic.java;h=bf27d030b5a82ec8e5a91cff9942965e4498859f;hb=fda41360dcb7e68c8e3003c73fdb98db2514bf5f;hp=d7e5d0b9c1c3bb51553357a6ee351e0765604159;hpb=5c9d068e66264be8db6018cb551db7c05e8e2596;p=sdc.git diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java index d7e5d0b9c1..bf27d030b5 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java @@ -13,91 +13,118 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.openecomp.sdc.be.components.impl; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static org.apache.commons.collections.CollectionUtils.isNotEmpty; +import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaMapElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaStringElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.getPropertyJsonStringValue; import static org.openecomp.sdc.be.tosca.CsarUtils.VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import fj.data.Either; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; +import java.util.stream.Collectors; import lombok.Getter; import lombok.Setter; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringEscapeUtils; +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.distribution.engine.IDistributionEngine; +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; +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.impl.model.ToscaTypeImportData; import org.openecomp.sdc.be.components.impl.utils.CINodeFilterUtils; import org.openecomp.sdc.be.components.impl.utils.CreateServiceFromYamlParameter; import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic; import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction; import org.openecomp.sdc.be.components.merge.resource.ResourceDataMergeBusinessLogic; -import org.openecomp.sdc.be.components.path.ForwardingPathValidator; -import org.openecomp.sdc.be.components.validation.NodeFilterValidator; -import org.openecomp.sdc.be.components.validation.ServiceDistributionValidation; -import org.openecomp.sdc.be.components.validation.component.ComponentContactIdValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentDescriptionValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentIconValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentNameValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentProjectCodeValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentTagsValidator; -import org.openecomp.sdc.be.components.validation.component.ComponentValidator; 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.CINodeFilterDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.CustomYamlFunction; 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.RequirementSubstitutionFilterPropertyDataDefinition; +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.SubPropertyToscaFunction; +import org.openecomp.sdc.be.datatypes.elements.SubstitutionFilterPropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ToscaGetFunctionDataDefinition; 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; +import org.openecomp.sdc.be.model.ArtifactTypeDefinition; import org.openecomp.sdc.be.model.AttributeDefinition; import org.openecomp.sdc.be.model.CapabilityDefinition; import org.openecomp.sdc.be.model.CapabilityRequirementRelationship; +import org.openecomp.sdc.be.model.CapabilityTypeDefinition; 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; 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.GroupTypeDefinition; 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; +import org.openecomp.sdc.be.model.PolicyDefinition; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.RelationshipImpl; import org.openecomp.sdc.be.model.RelationshipInfo; @@ -105,7 +132,9 @@ import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; import org.openecomp.sdc.be.model.RequirementDefinition; 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; @@ -113,21 +142,25 @@ import org.openecomp.sdc.be.model.UploadResourceInfo; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement; -import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; -import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; -import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeFilterOperation; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade; import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter; +import org.openecomp.sdc.be.model.normatives.ToscaTypeMetadata; import org.openecomp.sdc.be.model.operations.StorageException; -import org.openecomp.sdc.be.model.operations.api.IElementOperation; -import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation; -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.IGraphLockOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.ArtifactTypeOperation; +import org.openecomp.sdc.be.model.operations.impl.CapabilityTypeOperation; +import org.openecomp.sdc.be.model.operations.impl.GroupTypeOperation; 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.tosca.ToscaPropertyType; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.tosca.CsarUtils; +import org.openecomp.sdc.be.tosca.ToscaExportHandler; +import org.openecomp.sdc.be.ui.model.OperationUi; import org.openecomp.sdc.be.utils.TypeUtils; +import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; import org.openecomp.sdc.common.api.ArtifactTypeEnum; import org.openecomp.sdc.common.api.Constants; @@ -144,9 +177,9 @@ import org.yaml.snakeyaml.Yaml; @org.springframework.stereotype.Component("serviceImportBusinessLogic") public class ServiceImportBusinessLogic { + protected static final String CREATE_RESOURCE = "Create Resource"; private static final String INITIAL_VERSION = "0.1"; - private static final String CREATE_RESOURCE = "Create Resource"; - private static final String IN_RESOURCE = " in resource {} "; + private static final String IN_RESOURCE = " in resource {} "; private static final String COMPONENT_INSTANCE_WITH_NAME = "component instance with name "; private static final String COMPONENT_INSTANCE_WITH_NAME_IN_RESOURCE = "component instance with name {} in resource {} "; private static final String CERTIFICATION_ON_IMPORT = "certification on import"; @@ -155,102 +188,535 @@ public class ServiceImportBusinessLogic { private static final String CREATE_RESOURCE_VALIDATE_CAPABILITY_TYPES = "Create Resource - validateCapabilityTypesCreate"; private static final String CATEGORY_IS_EMPTY = "Resource category is empty"; private static final Logger log = Logger.getLogger(ServiceImportBusinessLogic.class); - private final UiComponentDataConverter uiComponentDataConverter; - private final ComponentInstanceBusinessLogic componentInstanceBusinessLogic; - @Autowired - protected ComponentsUtils componentsUtils; - @Autowired - protected ToscaOperationFacade toscaOperationFacade; - @Autowired - private ServiceBusinessLogic serviceBusinessLogic; - @Autowired - private CsarBusinessLogic csarBusinessLogic; - @Autowired - private CsarArtifactsAndGroupsBusinessLogic csarArtifactsAndGroupsBusinessLogic; - @Autowired - private LifecycleBusinessLogic lifecycleBusinessLogic; - @Autowired - private CompositionBusinessLogic compositionBusinessLogic; - @Autowired - private ResourceDataMergeBusinessLogic resourceDataMergeBusinessLogic; - @Autowired - private ServiceImportParseLogic serviceImportParseLogic; - @Autowired - private ComponentNodeFilterBusinessLogic componentNodeFilterBusinessLogic; - @Autowired - public ServiceImportBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation, - IGroupTypeOperation groupTypeOperation, GroupBusinessLogic groupBusinessLogic, - InterfaceOperation interfaceOperation, InterfaceLifecycleOperation interfaceLifecycleTypeOperation, - ArtifactsBusinessLogic artifactsBusinessLogic, IDistributionEngine distributionEngine, - ComponentInstanceBusinessLogic componentInstanceBusinessLogic, - ServiceDistributionValidation serviceDistributionValidation, ForwardingPathValidator forwardingPathValidator, - UiComponentDataConverter uiComponentDataConverter, NodeFilterOperation serviceFilterOperation, - NodeFilterValidator serviceFilterValidator, ArtifactsOperations artifactToscaOperation, - ComponentContactIdValidator componentContactIdValidator, ComponentNameValidator componentNameValidator, - ComponentTagsValidator componentTagsValidator, ComponentValidator componentValidator, - ComponentIconValidator componentIconValidator, ComponentProjectCodeValidator componentProjectCodeValidator, - ComponentDescriptionValidator componentDescriptionValidator) { - this.componentInstanceBusinessLogic = componentInstanceBusinessLogic; - this.uiComponentDataConverter = uiComponentDataConverter; - } - - public ServiceBusinessLogic getServiceBusinessLogic() { - return serviceBusinessLogic; - } - - public void setServiceBusinessLogic(ServiceBusinessLogic serviceBusinessLogic) { + private final ComponentsUtils componentsUtils; + private final ToscaOperationFacade toscaOperationFacade; + private final ServiceBusinessLogic serviceBusinessLogic; + private final CsarBusinessLogic csarBusinessLogic; + private final CsarArtifactsAndGroupsBusinessLogic csarArtifactsAndGroupsBusinessLogic; + private final LifecycleBusinessLogic lifecycleBusinessLogic; + private final CompositionBusinessLogic compositionBusinessLogic; + private final ResourceDataMergeBusinessLogic resourceDataMergeBusinessLogic; + private final ServiceImportParseLogic serviceImportParseLogic; + private final GroupBusinessLogic groupBusinessLogic; + private final PolicyBusinessLogic policyBusinessLogic; + private final ResourceImportManager resourceImportManager; + private final JanusGraphDao janusGraphDao; + private final ArtifactsBusinessLogic artifactsBusinessLogic; + private final ArtifactTypeImportManager artifactTypeImportManager; + private final IGraphLockOperation graphLockOperation; + private final ToscaFunctionService toscaFunctionService; + private final DataTypeBusinessLogic dataTypeBusinessLogic; + private final ArtifactTypeOperation artifactTypeOperation; + private final GroupTypeImportManager groupTypeImportManager; + private final GroupTypeOperation groupTypeOperation; + private final CapabilityTypeImportManager capabilityTypeImportManager; + private final CapabilityTypeOperation capabilityTypeOperation; + private ApplicationDataTypeCache applicationDataTypeCache; + private final InterfaceLifecycleOperation interfaceLifecycleTypeOperation; + private final InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager; + private final ModelOperation modelOperation; + + 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 PolicyBusinessLogic policyBusinessLogic, + final ResourceImportManager resourceImportManager, final JanusGraphDao janusGraphDao, + final IGraphLockOperation graphLockOperation, final ToscaFunctionService toscaFunctionService, + final DataTypeBusinessLogic dataTypeBusinessLogic, final ArtifactTypeOperation artifactTypeOperation, + final ArtifactTypeImportManager artifactTypeImportManager, final GroupTypeImportManager groupTypeImportManager, + final GroupTypeOperation groupTypeOperation, + final InterfaceLifecycleOperation interfaceLifecycleTypeOperation, + final InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager, + final CapabilityTypeImportManager capabilityTypeImportManager, + final CapabilityTypeOperation capabilityTypeOperation, + final ModelOperation modelOperation) { + this.componentsUtils = componentsUtils; + this.toscaOperationFacade = toscaOperationFacade; this.serviceBusinessLogic = serviceBusinessLogic; + this.csarBusinessLogic = csarBusinessLogic; + this.csarArtifactsAndGroupsBusinessLogic = csarArtifactsAndGroupsBusinessLogic; + this.lifecycleBusinessLogic = lifecycleBusinessLogic; + this.compositionBusinessLogic = compositionBusinessLogic; + this.resourceDataMergeBusinessLogic = resourceDataMergeBusinessLogic; + this.serviceImportParseLogic = serviceImportParseLogic; + this.groupBusinessLogic = groupBusinessLogic; + this.policyBusinessLogic = policyBusinessLogic; + this.resourceImportManager = resourceImportManager; + this.janusGraphDao = janusGraphDao; + this.artifactsBusinessLogic = artifactsBusinessLogic; + this.graphLockOperation = graphLockOperation; + this.toscaFunctionService = toscaFunctionService; + this.dataTypeBusinessLogic = dataTypeBusinessLogic; + this.artifactTypeOperation = artifactTypeOperation; + this.artifactTypeImportManager = artifactTypeImportManager; + this.groupTypeImportManager = groupTypeImportManager; + this.groupTypeOperation = groupTypeOperation; + this.interfaceLifecycleTypeOperation = interfaceLifecycleTypeOperation; + this.interfaceLifecycleTypeImportManager = interfaceLifecycleTypeImportManager; + this.capabilityTypeImportManager = capabilityTypeImportManager; + this.capabilityTypeOperation = capabilityTypeOperation; + this.modelOperation = modelOperation; + } + + @Autowired + public void setApplicationDataTypeCache(ApplicationDataTypeCache applicationDataTypeCache) { + this.applicationDataTypeCache = applicationDataTypeCache; + } + + public Service updateServiceFromToscaTemplate(final String serviceId, final User modifier, final String data) { + final Either serviceResponseFormatEither = serviceBusinessLogic.getService(serviceId, modifier); + if (serviceResponseFormatEither.isRight()) { + throw new ByActionStatusComponentException(ActionStatus.SERVICE_NOT_FOUND, serviceId); + } + final Service serviceOriginal = serviceResponseFormatEither.left().value(); + final Map metadata = (Map) new Yaml().loadAs(data, Map.class).get("metadata"); + validateServiceMetadataBeforeCreate(serviceOriginal, metadata); + + final Service newService = cloneServiceIdentifications(serviceOriginal); + final Map payload = new HashMap<>(); + payload.put("Definitions/service-" + metadata.get("name") + "-template.yml", data.getBytes()); + updateServiceMetadata(newService, metadata); + return createService(newService, AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE, modifier, payload, null); + } + + private Service cloneServiceIdentifications(final Service serviceOriginal) { + final Service newService = new Service(serviceOriginal.getComponentMetadataDefinition()); + newService.setCategories(serviceOriginal.getCategories()); + newService.setInvariantUUID(serviceOriginal.getInvariantUUID()); + newService.setUniqueId(serviceOriginal.getUniqueId()); + newService.setName(serviceOriginal.getName()); + newService.setUUID(serviceOriginal.getUUID()); + return newService; + } + + private void validateServiceMetadataBeforeCreate(final Service service, final Map metadata) { + if (MapUtils.isEmpty(metadata)) { + throw new ByActionStatusComponentException(ActionStatus.MISSING_SERVICE_METADATA); + } + final String uuid = metadata.get("UUID"); + if (!service.getUUID().equals(uuid)) { + throw new ByActionStatusComponentException(ActionStatus.UNCHANGEABLE_PROPERTY_ERROR, "UUID"); + } + final String invariantUUID = metadata.get("invariantUUID"); + if (!service.getInvariantUUID().equals(invariantUUID)) { + throw new ByActionStatusComponentException(ActionStatus.UNCHANGEABLE_PROPERTY_ERROR, "invariantUUID"); + } + final String name = metadata.get("name"); + if (!service.getName().equals(name)) { + throw new ByActionStatusComponentException(ActionStatus.UNCHANGEABLE_PROPERTY_ERROR, "name"); + } + final String version = metadata.get("template_version"); + if (!service.getVersion().equals(version)) { + throw new ByActionStatusComponentException(ActionStatus.UNCHANGEABLE_PROPERTY_ERROR, "template_version"); + } } public Service createService(Service service, AuditingActionEnum auditingAction, User user, Map csarUIPayload, String payloadName) { log.debug("enter createService"); - service.setCreatorUserId(user.getUserId()); - service.setState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); - service.setVersion(INITIAL_VERSION); - service.setConformanceLevel(ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel()); - service.setDistributionStatus(DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED); - service.setInstantiationType("A-la-carte"); - service.setEnvironmentContext("General_Revenue-Bearing"); - service.setEcompGeneratedNaming(true); + if (AuditingActionEnum.CREATE_SERVICE.equals(auditingAction)) { + service.setCreatorUserId(user.getUserId()); + service.setState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + service.setVersion(INITIAL_VERSION); + service.setConformanceLevel(ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel()); + service.setDistributionStatus(DistributionStatusEnum.DISTRIBUTION_NOT_APPROVED); + } try { - serviceBusinessLogic.validateServiceBeforeCreate(service, user, auditingAction); + final var serviceBeforeCreate = serviceBusinessLogic.validateServiceBeforeCreate(service, user, auditingAction); + if (serviceBeforeCreate.isRight()) { + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } log.debug("enter createService,validateServiceBeforeCreate success"); String csarUUID = payloadName == null ? service.getCsarUUID() : payloadName; - log.debug("enter createService,get csarUUID:{}", csarUUID); - csarBusinessLogic.validateCsarBeforeCreate(service, csarUUID); + if (AuditingActionEnum.CREATE_SERVICE.equals(auditingAction)) { + log.debug("enter createService,get csarUUID:{}", csarUUID); + csarBusinessLogic.validateCsarBeforeCreate(service, csarUUID); + } log.debug("CsarUUID is {} - going to create resource from CSAR", csarUUID); - return createServiceFromCsar(service, user, csarUIPayload, csarUUID); - } catch (Exception e) { - log.debug("Exception occured when createService,error is:{}", e.getMessage(), e); + return createServiceFromCsar(service, user, csarUIPayload, csarUUID, auditingAction); + } catch (final ComponentException e) { + log.debug("Exception occurred when createService: {}", e.getMessage(), e); + throw e; + } catch (final Exception e) { + log.debug("Exception occurred when createService: {}", e.getMessage(), e); throw new ComponentException(ActionStatus.GENERAL_ERROR); } } - protected Service createServiceFromCsar(Service service, User user, Map csarUIPayload, String csarUUID) { + private void updateServiceMetadata(final Service service, final Map metadata) { + metadata.entrySet().forEach(s -> { + final Optional find = + Arrays.stream(service.getClass().getMethods()).filter(method -> method.getName().equalsIgnoreCase("set" + s.getKey())).findAny(); + if (find.isPresent()) { + try { + find.get().invoke(service, s.getValue()); + } catch (final Exception e) { + log.warn("Unable to set '{}' with value '{}'", s.getKey(), s.getValue()); + } + } + }); + } + + protected Service createServiceFromCsar(Service service, User user, Map csarUIPayload, String csarUUID, + AuditingActionEnum auditingAction) { log.trace("************* created successfully from YAML, resource TOSCA "); try { - CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID); + final ServiceCsarInfo csarInfo; + if (AuditingActionEnum.UPDATE_SERVICE_TOSCA_TEMPLATE.equals(auditingAction)) { + csarInfo = new ServiceCsarInfo(user, csarUUID, csarUIPayload, service.getName(), service.getModel(), + csarUIPayload.keySet().iterator().next(), new String(csarUIPayload.values().iterator().next()), true, modelOperation); + } else { + csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID, auditingAction); + } + final String serviceModel = service.getModel(); + final Map dataTypesToCreate = getDatatypesToCreate(serviceModel, csarInfo); + if (MapUtils.isNotEmpty(dataTypesToCreate)) { + dataTypeBusinessLogic.createDataTypeFromYaml(new Yaml().dump(dataTypesToCreate), serviceModel, true); + dataTypesToCreate.keySet().forEach(key -> + applicationDataTypeCache.reload(serviceModel, UniqueIdBuilder.buildDataTypeUid(serviceModel, key)) + ); + } + + final Map artifactTypesToCreate = getArtifactTypesToCreate(serviceModel, csarInfo); + if (MapUtils.isNotEmpty(artifactTypesToCreate)) { + artifactTypeImportManager.createArtifactTypes(new Yaml().dump(artifactTypesToCreate), serviceModel, true); + } + + final List nodeTypesToCreate = getNodeTypesToCreate(serviceModel, csarInfo); + if (CollectionUtils.isNotEmpty(nodeTypesToCreate)) { + ParsedToscaYamlInfo parsedToscaYamlInfo = csarBusinessLogic.getParsedToscaYamlInfo(csarInfo, service); + createNodeTypes(nodeTypesToCreate, parsedToscaYamlInfo.getInstances(), serviceModel, csarInfo.getModifier()); + } + + final Map groupTypesToCreate = getGroupTypesToCreate(serviceModel, csarInfo); + if (MapUtils.isNotEmpty(groupTypesToCreate)) { + final Map toscaTypeMetadata = fillToscaTypeMetadata(groupTypesToCreate); + final ToscaTypeImportData toscaTypeImportData = new ToscaTypeImportData(new Yaml().dump(groupTypesToCreate), toscaTypeMetadata); + groupTypeImportManager.createGroupTypes(toscaTypeImportData, serviceModel, true); + } + + final Map interfaceTypesToCreate = getInterfaceTypesToCreate(serviceModel, csarInfo); + if (MapUtils.isNotEmpty(interfaceTypesToCreate)) { + interfaceLifecycleTypeImportManager.createLifecycleTypes(new Yaml().dump(interfaceTypesToCreate), serviceModel, true); + } + + final Map capabilityTypesToCreate = getCapabilityTypesToCreate(serviceModel, csarInfo); + if (MapUtils.isNotEmpty(capabilityTypesToCreate)) { + capabilityTypeImportManager.createCapabilityTypes(new Yaml().dump(capabilityTypesToCreate), serviceModel, true); + } + Map nodeTypesInfo = csarInfo.extractTypesInfo(); - Either>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = serviceImportParseLogic - .findNodeTypesArtifactsToHandle(nodeTypesInfo, csarInfo, service); + Either>>, ResponseFormat> findNodeTypesArtifactsToHandleRes + = serviceImportParseLogic.findNodeTypesArtifactsToHandle(nodeTypesInfo, csarInfo, service); if (findNodeTypesArtifactsToHandleRes.isRight()) { log.debug("failed to find node types for update with artifacts during import csar {}. ", csarInfo.getCsarUUID()); throw new ComponentException(findNodeTypesArtifactsToHandleRes.right().value()); } return createServiceFromYaml(service, csarInfo.getMainTemplateContent(), csarInfo.getMainTemplateName(), nodeTypesInfo, csarInfo, - findNodeTypesArtifactsToHandleRes.left().value(), true, false, null); - } catch (Exception e) { - log.debug("Exception occured when createServiceFromCsar,error is:{}", e.getMessage(), e); + findNodeTypesArtifactsToHandleRes.left().value(), true, false, null, user.getUserId(), auditingAction); + } catch (final ComponentException e) { + log.debug("Exception occurred when createServiceFromCsar,error is:{}", e.getMessage(), e); + throw e; + } catch (final Exception e) { + log.debug("Exception occurred when createServiceFromCsar,error is:{}", e.getMessage(), e); throw new ComponentException(ActionStatus.GENERAL_ERROR); } } + private Map fillToscaTypeMetadata(final Map groupTypesToCreate) { + final Map toscaTypeMetadata = new HashMap<>(); + groupTypesToCreate.entrySet().forEach(entry -> { + final ToscaTypeMetadata metadata = new ToscaTypeMetadata(); + metadata.setIcon(getIconFromGroupType(entry.getValue())); + metadata.setDisplayName(extractDisplayName(entry.getKey())); + toscaTypeMetadata.put(entry.getKey(), metadata); + }); + return toscaTypeMetadata; + } + + private String extractDisplayName(final String key) { + final String[] split = key.split("\\."); + return split[split.length - 1]; + } + + private String getIconFromGroupType(final Object value) { + final Either groupType = groupTypeOperation.getLatestGroupTypeByType( + (String) ((LinkedHashMap) value).get(ToscaTagNamesEnum.DERIVED_FROM.getElementName()), null); + if (groupType.isLeft()) { + return groupType.left().value().getIcon(); + } + return null; + } + + private Map getGroupTypesToCreate(final String model, final CsarInfo csarInfo) { + final Map groupTypesToCreate = new HashMap<>(); + final Map groupTypes = csarInfo.getGroupTypes(); + if (MapUtils.isNotEmpty(groupTypes)) { + for (final Entry entry : groupTypes.entrySet()) { + final Either result + = groupTypeOperation.getGroupTypeByUid(UniqueIdBuilder.buildGroupTypeUid(model, entry.getKey(), "1.0")); + if (result.isRight() && result.right().value().equals(StorageOperationStatus.NOT_FOUND)) { + groupTypesToCreate.put(entry.getKey(), entry.getValue()); + log.info("Deploying new group type {} to model {} from package {}", entry.getKey(), model, csarInfo.getCsarUUID()); + } + } + } + return groupTypesToCreate; + } + + private Map getCapabilityTypesToCreate(final String model, final CsarInfo csarInfo) { + final Map capabilityTypesToCreate = new HashMap<>(); + final Map capabilityTypes = csarInfo.getCapabilityTypes(); + if (MapUtils.isNotEmpty(capabilityTypes)) { + for (final Entry entry : capabilityTypes.entrySet()) { + final Either result + = capabilityTypeOperation.getCapabilityType(UniqueIdBuilder.buildCapabilityTypeUid(model, entry.getKey())); + if (result.isRight() && result.right().value().equals(StorageOperationStatus.NOT_FOUND)) { + capabilityTypesToCreate.put(entry.getKey(), entry.getValue()); + log.info("Deploying new capability type {} to model {} from package {}", entry.getKey(), model, csarInfo.getCsarUUID()); + } + } + } + return capabilityTypesToCreate; + } + + private Map getDatatypesToCreate(final String model, final CsarInfo csarInfo) { + final Map dataTypesToCreate = new HashMap<>(); + + for (final Entry dataTypeEntry : csarInfo.getDataTypes().entrySet()) { + final Either 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 {} to model {} from package {}", dataTypeEntry.getKey(), model, csarInfo.getCsarUUID()); + } + if (hasNewProperties(result, (Map>) dataTypeEntry.getValue())) { + dataTypesToCreate.put(dataTypeEntry.getKey(), dataTypeEntry.getValue()); + log.info("Deploying new version of type {} to model {} from package {}", dataTypeEntry.getKey(), model, csarInfo.getCsarUUID()); + } + } + return dataTypesToCreate; + } + + private Map getArtifactTypesToCreate(final String model, final CsarInfo csarInfo) { + final Map artifactTypesToCreate = new HashMap<>(); + final Map artifactTypesMap = csarInfo.getArtifactTypes(); + if (MapUtils.isNotEmpty(artifactTypesMap)) { + for (final Entry artifactTypeEntry : artifactTypesMap.entrySet()) { + final Either result = + artifactTypeOperation.getArtifactTypeByUid(UniqueIdBuilder.buildArtifactTypeUid(model, artifactTypeEntry.getKey())); + if (result.isRight() && StorageOperationStatus.NOT_FOUND.equals(result.right().value())) { + artifactTypesToCreate.put(artifactTypeEntry.getKey(), artifactTypeEntry.getValue()); + log.info("Deploying new artifact type={}, to model={}, from package={}", + artifactTypeEntry.getKey(), model, csarInfo.getCsarUUID()); + } + } + } + return artifactTypesToCreate; + } + + private Map getInterfaceTypesToCreate(final String model, final CsarInfo csarInfo) { + final Map interfaceTypesToCreate = new HashMap<>(); + Map interfacetypeMap = csarInfo.getInterfaceTypes(); + + interfacetypeMap.entrySet().forEach(interfacetypeDef -> { + Either interfaceDefinition = + interfaceLifecycleTypeOperation.getInterface(UniqueIdBuilder.buildInterfaceTypeUid(model, interfacetypeDef.getKey())); + if (interfaceDefinition.isRight() && interfaceDefinition.right().value().equals(StorageOperationStatus.NOT_FOUND)) { + interfaceTypesToCreate.put(interfacetypeDef.getKey(), interfacetypeDef.getValue()); + } + }); + return interfaceTypesToCreate; + } + + private boolean hasNewProperties(final Either result, + final Map> dataType) { + return result.isLeft() && dataType.containsKey("properties") && result.left().value().getProperties() != null + && result.left().value().getProperties().size() != dataType.get("properties").size(); + } + + private void createNodeTypes(List nodeTypesToCreate, Map instancesFromCsar, String model, + User user) { + NodeTypesMetadataList nodeTypesMetadataList = new NodeTypesMetadataList(); + List nodeTypeMetadataList = new ArrayList<>(); + final Map allTypesToCreate = new HashMap<>(); + nodeTypesToCreate.forEach(nodeType -> { + allTypesToCreate.put(nodeType.getMappedNodeType().getKey(), nodeType.getMappedNodeType().getValue()); + nodeTypeMetadataList.add(nodeType.getNodeTypeMetadata()); + }); + nodeTypesMetadataList.setNodeMetadataList(nodeTypeMetadataList); + resourceImportManager.importAllNormativeResource(allTypesToCreate, nodeTypesMetadataList, instancesFromCsar, user, model, true, false); + } + + private List getNodeTypesToCreate(final String model, final ServiceCsarInfo csarInfo) { + List namesOfNodeTypesToCreate = new ArrayList<>(); + + for (final NodeTypeDefinition nodeTypeDefinition : csarInfo.getNodeTypesUsed()) { + Either result = toscaOperationFacade + .getLatestByToscaResourceName(nodeTypeDefinition.getMappedNodeType().getKey(), model); + if (result.isRight() && result.right().value().equals(StorageOperationStatus.NOT_FOUND)) { + namesOfNodeTypesToCreate.add(nodeTypeDefinition); + } else if (result.isLeft()) { + Resource latestResource = (Resource) result.left().value(); + Entry existingMappedToscaTemplate = getResourceToscaTemplate(latestResource.getUniqueId(), + latestResource.getToscaArtifacts().get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE), csarInfo.getModifier().getUserId()); + Map newMappedToscaTemplate = (Map) nodeTypeDefinition.getMappedNodeType().getValue(); + Map combinedMappedToscaTemplate = + getNewChangesToToscaTemplate(newMappedToscaTemplate, (Map) existingMappedToscaTemplate.getValue()); + if (!combinedMappedToscaTemplate.equals(existingMappedToscaTemplate.getValue())) { + if (latestResource.getComponentMetadataDefinition().getMetadataDataDefinition().isNormative()) { + nodeTypeDefinition.getNodeTypeMetadata().setNormative(true); + } + existingMappedToscaTemplate.setValue(combinedMappedToscaTemplate); + nodeTypeDefinition.setMappedNodeType(existingMappedToscaTemplate); + namesOfNodeTypesToCreate.add(nodeTypeDefinition); + } + } + } + return namesOfNodeTypesToCreate; + } + + private Entry getResourceToscaTemplate(String uniqueId, ArtifactDefinition assetToscaTemplate, String userId) { + String assetToToscaTemplate = assetToscaTemplate.getUniqueId(); + ImmutablePair toscaTemplate = artifactsBusinessLogic. + handleDownloadRequestById(uniqueId, assetToToscaTemplate, userId, ComponentTypeEnum.RESOURCE, null, null); + Map mappedToscaTemplate = new Yaml().load(new String(toscaTemplate.right)); + Either, ImportUtils.ResultStatusEnum> eitherNodeTypes = + findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES); + if (eitherNodeTypes.isRight()) { + throw new ComponentException(ActionStatus.INVALID_TOSCA_TEMPLATE); + } + return eitherNodeTypes.left().value().entrySet().iterator().next(); + } + + private Map getNewChangesToToscaTemplate(Map newMappedToscaTemplate, + Map existingMappedToscaTemplate) { + Map combinedMappedToscaTemplate = new HashMap<>(existingMappedToscaTemplate); + combinePropertiesIntoToscaTemplate((Map) newMappedToscaTemplate.get("properties"), + (Map) existingMappedToscaTemplate.get("properties"), combinedMappedToscaTemplate); + combineAttributesIntoToscaTemplate((Map) newMappedToscaTemplate.get("attributes"), + (Map) existingMappedToscaTemplate.get("attributes"), combinedMappedToscaTemplate); + combineRequirementsIntoToscaTemplate((List>) newMappedToscaTemplate.get("requirements"), + (List>) existingMappedToscaTemplate.get("requirements"), combinedMappedToscaTemplate); + combineCapabilitiesIntoToscaTemplate((Map) newMappedToscaTemplate.get("capabilities"), + (Map) existingMappedToscaTemplate.get("capabilities"), combinedMappedToscaTemplate); + combineInterfacesIntoToscaTemplate((Map>) newMappedToscaTemplate.get("interfaces"), + (Map>) existingMappedToscaTemplate.get("interfaces"), combinedMappedToscaTemplate); + return combinedMappedToscaTemplate; + } + + private void combineInterfacesIntoToscaTemplate(Map> newInterfaces, + Map> existingInterfaces, + Map combinedMappedToscaTemplate) { + Map> combinedInterfaces = combineAdditionalInterfaces(newInterfaces, existingInterfaces); + if ((MapUtils.isEmpty(existingInterfaces) && MapUtils.isNotEmpty(combinedInterfaces)) + || (MapUtils.isNotEmpty(existingInterfaces) && !existingInterfaces.equals(combinedInterfaces))) { + combinedMappedToscaTemplate.put("interfaces", combinedInterfaces); + } + } + + private void combineCapabilitiesIntoToscaTemplate(Map newCapabilities, Map existingCapabilities, + Map combinedMappedToscaTemplate) { + Map combinedCapabilities = combineEntries(newCapabilities, existingCapabilities); + if ((MapUtils.isEmpty(existingCapabilities) && MapUtils.isNotEmpty(combinedCapabilities)) || + (MapUtils.isNotEmpty(existingCapabilities) && !combinedCapabilities.equals(existingCapabilities))) { + combinedMappedToscaTemplate.put("capabilities", combinedCapabilities); + } + } + + private void combineRequirementsIntoToscaTemplate(List> newRequirements, List> existingRequirements, + Map combinedMappedToscaTemplate) { + List> combinedRequirements = combineAdditionalRequirements(newRequirements, existingRequirements); + if ((CollectionUtils.isEmpty(existingRequirements) && CollectionUtils.isNotEmpty(combinedRequirements)) + || (CollectionUtils.isNotEmpty(existingRequirements) && !combinedRequirements.equals(existingRequirements))) { + combinedMappedToscaTemplate.put("requirements", combinedRequirements); + } + } + + private void combineAttributesIntoToscaTemplate(Map newAttributes, Map existingAttributes, + Map combinedMappedToscaTemplate) { + Map combinedAttributes = combineEntries(newAttributes, existingAttributes); + if ((MapUtils.isEmpty(existingAttributes) && MapUtils.isNotEmpty(combinedAttributes)) || + (MapUtils.isNotEmpty(existingAttributes) && !combinedAttributes.equals(existingAttributes))) { + combinedMappedToscaTemplate.put("attributes", combinedAttributes); + } + } + + private void combinePropertiesIntoToscaTemplate(Map newProperties, Map existingProperties, + Map combinedMappedToscaTemplate) { + Map combinedProperties = combineEntries(newProperties, existingProperties); + if ((MapUtils.isEmpty(existingProperties) && MapUtils.isNotEmpty(combinedProperties)) || + (MapUtils.isNotEmpty(existingProperties) && !combinedProperties.equals(existingProperties))) { + combinedMappedToscaTemplate.put("properties", combinedProperties); + } + } + + private Map> combineAdditionalInterfaces(Map> newInterfaces, + Map> existingInterfaces) { + if (MapUtils.isNotEmpty(newInterfaces) && MapUtils.isNotEmpty(existingInterfaces) && newInterfaces.equals(existingInterfaces)) { + return new HashMap<>(existingInterfaces); + } + if (MapUtils.isEmpty(newInterfaces)) { + newInterfaces = new HashMap<>(); + } + Map> combinedEntries = new HashMap<>(newInterfaces); + if (MapUtils.isEmpty(existingInterfaces)) { + return combinedEntries; + } + existingInterfaces.entrySet().forEach(interfaceDef -> { + combinedEntries.entrySet().stream().filter((interFace) -> interFace.getValue().get("type").equals((interfaceDef.getValue()).get("type"))) + .findFirst().ifPresentOrElse((interFace) -> { + interFace.getValue().putAll(interfaceDef.getValue()); + }, () -> { + combinedEntries.put(interfaceDef.getKey(), interfaceDef.getValue()); + }); + }); + return combinedEntries; + } + + private List> combineAdditionalRequirements(List> newReqs, + List> existingResourceReqs) { + if (CollectionUtils.isNotEmpty(newReqs) && CollectionUtils.isNotEmpty(existingResourceReqs) && newReqs.equals(existingResourceReqs)) { + return new ArrayList<>(existingResourceReqs); + } + if (CollectionUtils.isEmpty(existingResourceReqs)) { + existingResourceReqs = new ArrayList<>(); + } + Set> combinedReqs = new TreeSet<>((map1, map2) -> + map1.keySet().equals(map2.keySet()) ? 0 : map1.keySet().iterator().next().compareTo(map2.keySet().iterator().next())); + combinedReqs.addAll(existingResourceReqs); + if (CollectionUtils.isEmpty(newReqs)) { + return new ArrayList<>(combinedReqs); + } + combinedReqs.addAll(newReqs); + return new ArrayList<>(combinedReqs); + } + + private Map combineEntries(Map newMap, Map existingMap) { + if (MapUtils.isNotEmpty(newMap) && MapUtils.isNotEmpty(existingMap) && newMap.equals(existingMap)) { + return new HashMap<>(existingMap); + } + if (MapUtils.isEmpty(newMap)) { + newMap = new HashMap<>(); + } + Map combinedEntries = new HashMap<>(newMap); + if (MapUtils.isEmpty(existingMap)) { + return combinedEntries; + } + combinedEntries.putAll(existingMap); + return combinedEntries; + } + protected Service createServiceFromYaml(Service service, String topologyTemplateYaml, String yamlName, Map nodeTypesInfo, CsarInfo csarInfo, - Map>> nodeTypesArtifactsToCreate, - boolean shouldLock, boolean inTransaction, String nodeName) throws BusinessLogicException { + Map>> nodeTypesArtifactsToCreate, + boolean shouldLock, boolean inTransaction, String nodeName, final String userId, + AuditingActionEnum auditingAction) + throws BusinessLogicException { List createdArtifacts = new ArrayList<>(); Service createdService; CreateServiceFromYamlParameter csfyp = new CreateServiceFromYamlParameter(); @@ -265,7 +731,8 @@ public class ServiceImportBusinessLogic { csfyp.setNodeTypesInfo(nodeTypesInfo); csfyp.setCsarInfo(csarInfo); csfyp.setNodeName(nodeName); - createdService = createServiceAndRIsFromYaml(service, false, nodeTypesArtifactsToCreate, shouldLock, inTransaction, csfyp); + createdService = createServiceAndRIsFromYaml(service, false, nodeTypesArtifactsToCreate, shouldLock, inTransaction, csfyp, userId, + auditingAction); log.debug("#createResourceFromYaml - The resource {} has been created ", service.getName()); } catch (ComponentException | BusinessLogicException e) { log.debug("Create Service from yaml failed", e); @@ -278,9 +745,11 @@ public class ServiceImportBusinessLogic { } protected Service createServiceAndRIsFromYaml(Service service, boolean isNormative, - Map>> nodeTypesArtifactsToCreate, - boolean shouldLock, boolean inTransaction, CreateServiceFromYamlParameter csfyp) + Map>> nodeTypesArtifactsToCreate, + boolean shouldLock, boolean inTransaction, CreateServiceFromYamlParameter csfyp, + final String userId, AuditingActionEnum auditingAction) throws BusinessLogicException { + List nodeTypesNewCreatedArtifacts = new ArrayList<>(); String yamlName = csfyp.getYamlName(); ParsedToscaYamlInfo parsedToscaYamlInfo = csfyp.getParsedToscaYamlInfo(); @@ -292,11 +761,11 @@ public class ServiceImportBusinessLogic { if (shouldLock) { Either lockResult = serviceBusinessLogic.lockComponentByName(service.getSystemName(), service, CREATE_RESOURCE); if (lockResult.isRight()) { - serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ComponentException(lockResult.right().value()); } log.debug("name is locked {} status = {}", service.getSystemName(), lockResult); } + boolean rollback = false; try { log.trace("************* Adding properties to service from interface yaml {}", yamlName); Map properties = parsedToscaYamlInfo.getProperties(); @@ -309,12 +778,13 @@ public class ServiceImportBusinessLogic { service.setProperties(propertiesList); } log.trace("************* createResourceFromYaml before full create resource {}", yamlName); - service = serviceImportParseLogic.createServiceTransaction(service, csarInfo.getModifier(), isNormative); + service = serviceImportParseLogic.createServiceTransaction(service, csarInfo.getModifier(), isNormative, auditingAction); log.trace("************* Going to add inputs from yaml {}", yamlName); Map inputs = parsedToscaYamlInfo.getInputs(); service = serviceImportParseLogic.createInputsOnService(service, inputs); - log.trace("************* Finish to add inputs from yaml {}", yamlName); - ListDataDefinition substitutionFilterProperties = parsedToscaYamlInfo.getSubstitutionFilterProperties(); + log.trace("************* Finished to add inputs from yaml {}", yamlName); + ListDataDefinition substitutionFilterProperties = + parsedToscaYamlInfo.getSubstitutionFilterProperties(); service = serviceImportParseLogic.createSubstitutionFilterOnService(service, substitutionFilterProperties); log.trace("************* Added Substitution filter from interface yaml {}", yamlName); Map uploadComponentInstanceInfoMap = parsedToscaYamlInfo.getInstances(); @@ -322,10 +792,14 @@ public class ServiceImportBusinessLogic { service = createRIAndRelationsFromYaml(yamlName, service, uploadComponentInstanceInfoMap, topologyTemplateYaml, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeTypesArtifactsToCreate, nodeName); log.trace("************* Finished to create nodes, RI and Relation from yaml {}", yamlName); - Either, ResponseFormat> validateUpdateVfGroupNamesRes = serviceBusinessLogic.groupBusinessLogic - .validateUpdateVfGroupNames(parsedToscaYamlInfo.getGroups(), service.getSystemName()); + log.trace("************* Going to add outputs from yaml {}", yamlName); + Map outputs = parsedToscaYamlInfo.getOutputs(); + service = serviceImportParseLogic.createOutputsOnService(service, outputs, userId); + log.trace("************* Finished to add outputs from yaml {}", yamlName); + + Either, ResponseFormat> validateUpdateVfGroupNamesRes + = groupBusinessLogic.validateUpdateVfGroupNames(parsedToscaYamlInfo.getGroups(), service.getSystemName()); if (validateUpdateVfGroupNamesRes.isRight()) { - serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ComponentException(validateUpdateVfGroupNamesRes.right().value()); } Map groups; @@ -337,32 +811,186 @@ public class ServiceImportBusinessLogic { } Either createGroupsOnResource = createGroupsOnResource(service, groups); if (createGroupsOnResource.isRight()) { - serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ComponentException(createGroupsOnResource.right().value()); } service = createGroupsOnResource.left().value(); + + Either createPoliciesOnResource = createPoliciesOnResource(service, parsedToscaYamlInfo.getPolicies()); + if (createPoliciesOnResource.isRight()) { + throw new ComponentException(createPoliciesOnResource.right().value()); + } + service = createPoliciesOnResource.left().value(); log.trace("************* Going to add artifacts from yaml {}", yamlName); - NodeTypeInfoToUpdateArtifacts nodeTypeInfoToUpdateArtifacts = new NodeTypeInfoToUpdateArtifacts(nodeName, nodeTypesArtifactsToCreate); Either createArtifactsEither = createOrUpdateArtifacts(ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE, - createdArtifacts, yamlName, csarInfo, service, nodeTypeInfoToUpdateArtifacts, inTransaction, shouldLock); + createdArtifacts, yamlName, csarInfo, service, inTransaction, shouldLock); if (createArtifactsEither.isRight()) { - serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ComponentException(createArtifactsEither.right().value()); } service = serviceImportParseLogic.getServiceWithGroups(createArtifactsEither.left().value().getUniqueId()); + service = updateInputs(service, userId, parsedToscaYamlInfo.getSubstitutionMappingProperties()); + ASDCKpiApi.countCreatedResourcesKPI(); return service; - } catch (ComponentException | StorageException | BusinessLogicException e) { + } catch (Exception e) { + rollback = true; serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw e; } finally { if (!inTransaction) { - serviceBusinessLogic.janusGraphDao.commit(); + if (rollback) { + janusGraphDao.rollback(); + } else { + janusGraphDao.commit(); + } } if (shouldLock) { - serviceBusinessLogic.graphLockOperation.unlockComponentByName(service.getSystemName(), service.getUniqueId(), NodeTypeEnum.Resource); + graphLockOperation.unlockComponentByName(service.getSystemName(), service.getUniqueId(), NodeTypeEnum.Service); + } + } + } + + private Service updateInputs(final Service component, final String userId, final Map> substitutionMappingProperties) { + final List inputs = component.getInputs(); + if (CollectionUtils.isNotEmpty(inputs)) { + final List componentInstances = component.getComponentInstances(); + final String componentUniqueId = component.getUniqueId(); + List propertyMissingNames = new ArrayList<>(); + for (final InputDefinition input : inputs) { + boolean isSubMapProp = false; + if (substitutionMappingProperties != null && !substitutionMappingProperties.isEmpty()) { + isSubMapProp = substitutionMappingProperties.entrySet().stream() + .anyMatch(stringEntry -> stringEntry.getValue().get(0).equals(input.getName())); + } + if (!isSubMapProp && isInputFromComponentInstanceProperty(input.getName(), componentInstances)) { + associateInputToComponentInstanceProperty(userId, input, componentInstances, componentUniqueId); + } else { + String propertyName = associateInputToServiceProperty(userId, input, component, substitutionMappingProperties); + if (StringUtils.isNotBlank(propertyName)) { + propertyMissingNames.add(propertyName); + } + } + } + if (CollectionUtils.isNotEmpty(propertyMissingNames)) { + throw new ComponentException( + componentsUtils.getResponseFormat(ActionStatus.MISSING_PROPERTIES_ERROR, propertyMissingNames.toString())); + } + Either, 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 componentInstances) { + + if (CollectionUtils.isNotEmpty(componentInstances)) { + for (ComponentInstance instance : componentInstances) { + for (PropertyDefinition instanceProperty : instance.getProperties()) { + if (CollectionUtils.isNotEmpty(instanceProperty.getGetInputValues())) { + for (GetInputValueDataDefinition getInputValueDataDefinition : instanceProperty.getGetInputValues()) { + if (inputName.equals(getInputValueDataDefinition.getInputName())) { + return true; + } + } + } + } } } + return false; + } + + private void associateInputToComponentInstanceProperty(final String userId, final InputDefinition input, + final List componentInstances, + String componentUniqueId) { + + String componentInstanceId = null; + ComponentInstanceProperty componentInstanceProperty = new ComponentInstanceProperty(); + + outer: + for (ComponentInstance instance : componentInstances) { + for (PropertyDefinition instanceProperty : instance.getProperties()) { + if (CollectionUtils.isNotEmpty(instanceProperty.getGetInputValues())) { + for (GetInputValueDataDefinition getInputValueDataDefinition : instanceProperty.getGetInputValues()) { + if (input.getName().equals(getInputValueDataDefinition.getInputName())) { + componentInstanceId = instance.getUniqueId(); + componentInstanceProperty = new ComponentInstanceProperty(instanceProperty); + break outer; + } + } + } + } + } + + //unmapping instance property declared inputs from substitution mapping + input.setMappedToComponentProperty(false); + + // From Instance + updateInput(input, componentInstanceProperty, userId, componentInstanceId); + + final Either>, StorageOperationStatus> either = + toscaOperationFacade.updateComponentInstancePropsToComponent(Collections.singletonMap(componentInstanceId, + Collections.singletonList(componentInstanceProperty)), componentUniqueId); + if (either.isRight()) { + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + private String associateInputToServiceProperty(final String userId, + final InputDefinition input, final Service component, + final Map> substitutionMappingProperties) { + final List properties = component.getProperties(); + if (CollectionUtils.isNotEmpty(properties) && MapUtils.isNotEmpty(substitutionMappingProperties)) { + AtomicReference propertyNameFromInput = new AtomicReference<>(" "); + substitutionMappingProperties.entrySet().forEach(stringEntry -> { + if (stringEntry.getValue().get(0).equals(input.getName())) { + propertyNameFromInput.set(stringEntry.getKey()); + } + }); + + final Optional propDefOptional = + properties.stream().filter(prop -> prop.getName().equals(propertyNameFromInput.get())) + .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 either + = toscaOperationFacade.updatePropertyOfComponent(component, propertyDefinition); + if (either.isRight()) { + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } else { + input.setMappedToComponentProperty(false); + return propertyNameFromInput.get(); + } + } + return ""; + } + + 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()); } protected Either createOrUpdateArtifacts(ArtifactsBusinessLogic.ArtifactOperationEnum operation, @@ -372,8 +1000,9 @@ public class ServiceImportBusinessLogic { boolean inTransaction, boolean shouldLock) { String nodeName = nodeTypeInfoToUpdateArtifacts.getNodeName(); Resource resource = preparedResource; - Map>> nodeTypesArtifactsToHandle = nodeTypeInfoToUpdateArtifacts - .getNodeTypesArtifactsToHandle(); + Map>> nodeTypesArtifactsToHandle = + nodeTypeInfoToUpdateArtifacts + .getNodeTypesArtifactsToHandle(); if (preparedResource.getResourceType() == ResourceTypeEnum.VF) { if (nodeName != null && nodeTypesArtifactsToHandle.get(nodeName) != null && !nodeTypesArtifactsToHandle.get(nodeName).isEmpty()) { Either, ResponseFormat> handleNodeTypeArtifactsRes = handleNodeTypeArtifacts(preparedResource, @@ -449,11 +1078,11 @@ public class ServiceImportBusinessLogic { Constants.VF_LICENSE_DESCRIPTION, vfLicenseModelId, artifactOperation, null, true, shouldLock, inTransaction); } - protected Either getResourceResponseFormatEither(Resource resource, CsarInfo csarInfo, - List createdArtifacts, - ArtifactOperationInfo artifactOperation, boolean shouldLock, - boolean inTransaction, - Either, ResponseFormat> artifacsMetaCsarStatus) { + private Either getResourceResponseFormatEither(Resource resource, CsarInfo csarInfo, + List createdArtifacts, + ArtifactOperationInfo artifactOperation, boolean shouldLock, + boolean inTransaction, + Either, ResponseFormat> artifacsMetaCsarStatus) { try { String artifactsFileName = artifacsMetaCsarStatus.left().value().getKey(); String artifactsContents = artifacsMetaCsarStatus.left().value().getValue(); @@ -500,7 +1129,8 @@ public class ServiceImportBusinessLogic { vfCsarArtifactsToHandle = new EnumMap<>(ArtifactsBusinessLogic.ArtifactOperationEnum.class); vfCsarArtifactsToHandle.put(artifactOperation.getArtifactOperationEnum(), artifactPathAndNameList.left().value()); } else { - Either>, ResponseFormat> findVfCsarArtifactsToHandleRes = findVfCsarArtifactsToHandle( + Either>, ResponseFormat> + findVfCsarArtifactsToHandleRes = findVfCsarArtifactsToHandle( component, artifactPathAndNameList.left().value(), csarInfo.getModifier()); if (findVfCsarArtifactsToHandleRes.isRight()) { resStatus = Either.right(findVfCsarArtifactsToHandleRes.right().value()); @@ -565,7 +1195,7 @@ public class ServiceImportBusinessLogic { if (operation.getArtifactOperationEnum() == ArtifactsBusinessLogic.ArtifactOperationEnum.UPDATE || operation.getArtifactOperationEnum() == ArtifactsBusinessLogic.ArtifactOperationEnum.DELETE) { if (serviceImportParseLogic.isArtifactDeletionRequired(artifactId, artifactFileBytes, isFromCsar)) { - Either handleDelete = serviceBusinessLogic.artifactsBusinessLogic + Either handleDelete = artifactsBusinessLogic .handleDelete(component.getUniqueId(), artifactId, csarInfo.getModifier(), component, shouldLock, inTransaction); if (handleDelete.isRight()) { result = Either.right(handleDelete.right().value()); @@ -593,10 +1223,10 @@ public class ServiceImportBusinessLogic { return result; } - public Either, ResponseFormat> handleNodeTypeArtifacts(Resource nodeTypeResource, - Map> nodeTypeArtifactsToHandle, - List createdArtifacts, User user, - boolean inTransaction, boolean ignoreLifecycleState) { + private Either, ResponseFormat> handleNodeTypeArtifacts(Resource nodeTypeResource, + Map> nodeTypeArtifactsToHandle, + List createdArtifacts, User user, + boolean inTransaction, boolean ignoreLifecycleState) { List handleNodeTypeArtifactsRequestRes; Either, ResponseFormat> handleNodeTypeArtifactsRes = null; Either changeStateResponse; @@ -614,7 +1244,7 @@ public class ServiceImportBusinessLogic { List curArtifactsToHandle = curOperationEntry.getValue(); if (curArtifactsToHandle != null && !curArtifactsToHandle.isEmpty()) { log.debug("************* Going to {} artifact to vfc {}", curOperation.name(), nodeTypeResource.getName()); - handleNodeTypeArtifactsRequestRes = serviceBusinessLogic.artifactsBusinessLogic + handleNodeTypeArtifactsRequestRes = artifactsBusinessLogic .handleArtifactsRequestForInnerVfcComponent(curArtifactsToHandle, nodeTypeResource, user, createdArtifacts, new ArtifactOperationInfo(false, ignoreLifecycleState, curOperation), false, inTransaction); if (ArtifactsBusinessLogic.ArtifactOperationEnum.isCreateOrLink(curOperation)) { @@ -623,9 +1253,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); @@ -634,7 +1262,7 @@ public class ServiceImportBusinessLogic { return handleNodeTypeArtifactsRes; } - protected Either checkoutResource(Resource resource, User user, boolean inTransaction) { + private Either checkoutResource(Resource resource, User user, boolean inTransaction) { Either checkoutResourceRes; try { if (!resource.getComponentMetadataDefinition().getMetadataDataDefinition().getState() @@ -661,7 +1289,6 @@ public class ServiceImportBusinessLogic { protected Either createOrUpdateArtifacts(ArtifactOperationEnum operation, List createdArtifacts, String yamlFileName, CsarInfo csarInfo, Service preparedService, - NodeTypeInfoToUpdateArtifacts nodeTypeInfoToUpdateArtifacts, boolean inTransaction, boolean shouldLock) { Either createdCsarArtifactsEither = handleVfCsarArtifacts(preparedService, csarInfo, createdArtifacts, new ArtifactOperationInfo(false, false, operation), shouldLock, inTransaction); @@ -772,7 +1399,7 @@ public class ServiceImportBusinessLogic { return organizeVfCsarArtifactsByArtifactOperation(artifactPathAndNameList, existingArtifacts, component, user); } - protected boolean isNonMetaArtifact(ArtifactDefinition artifact) { + private boolean isNonMetaArtifact(ArtifactDefinition artifact) { boolean result = true; if (artifact.getMandatory() || artifact.getArtifactName() == null || !isValidArtifactType(artifact)) { result = false; @@ -781,12 +1408,10 @@ public class ServiceImportBusinessLogic { } private boolean isValidArtifactType(ArtifactDefinition artifact) { - boolean result = true; - if (artifact.getArtifactType() == null || ArtifactTypeEnum.findType(artifact.getArtifactType()).equals(ArtifactTypeEnum.VENDOR_LICENSE) - || ArtifactTypeEnum.findType(artifact.getArtifactType()).equals(ArtifactTypeEnum.VF_LICENSE)) { - result = false; - } - return result; + final String artifactType = artifact.getArtifactType(); + return artifactType != null + && !ArtifactTypeEnum.VENDOR_LICENSE.getType().equals(ArtifactTypeEnum.findType(artifactType)) + && !ArtifactTypeEnum.VF_LICENSE.getType().equals(ArtifactTypeEnum.findType(artifactType)); } protected Either>, ResponseFormat> organizeVfCsarArtifactsByArtifactOperation( @@ -795,7 +1420,8 @@ public class ServiceImportBusinessLogic { EnumMap> nodeTypeArtifactsToHandle = new EnumMap<>( ArtifactsBusinessLogic.ArtifactOperationEnum.class); Wrapper responseWrapper = new Wrapper<>(); - Either>, ResponseFormat> nodeTypeArtifactsToHandleRes = Either + Either>, ResponseFormat> + nodeTypeArtifactsToHandleRes = Either .left(nodeTypeArtifactsToHandle); try { List artifactsToUpload = new ArrayList<>(artifactPathAndNameList); @@ -819,12 +1445,11 @@ public class ServiceImportBusinessLogic { ResponseFormat responseFormat = ResponseFormatManager.getInstance() .getResponseFormat(ActionStatus.ARTIFACT_ALREADY_EXIST_IN_DIFFERENT_TYPE_IN_CSAR, currNewArtifact.getArtifactName(), currNewArtifact.getArtifactType(), foundArtifact.getArtifactType()); - AuditingActionEnum auditingAction = serviceBusinessLogic.artifactsBusinessLogic - .detectAuditingType(new ArtifactOperationInfo(false, false, ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE), - foundArtifact.getArtifactChecksum()); - serviceBusinessLogic.artifactsBusinessLogic - .handleAuditing(auditingAction, component, component.getUniqueId(), user, null, null, foundArtifact.getUniqueId(), - responseFormat, component.getComponentType(), null); + AuditingActionEnum auditingAction = artifactsBusinessLogic.detectAuditingType( + new ArtifactOperationInfo(false, false, ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE), + foundArtifact.getArtifactChecksum()); + artifactsBusinessLogic.handleAuditing(auditingAction, component, component.getUniqueId(), user, null, null, + foundArtifact.getUniqueId(), responseFormat, component.getComponentType(), null); responseWrapper.setInnerElement(responseFormat); break; } @@ -867,14 +1492,6 @@ public class ServiceImportBusinessLogic { return nodeTypeArtifactsToHandleRes; } - public ComponentsUtils getComponentsUtils() { - return this.componentsUtils; - } - - public void setComponentsUtils(ComponentsUtils componentsUtils) { - this.componentsUtils = componentsUtils; - } - protected Either, String> getValidArtifactNames(CsarInfo csarInfo, Map>> collectedWarningMessages) { List artifactPathAndNameList = csarInfo.getCsar().entrySet().stream() @@ -895,14 +1512,41 @@ public class ServiceImportBusinessLogic { List groupsAsList = updateGroupsMembersUsingResource(groups, service); serviceImportParseLogic.handleGroupsProperties(service, groups); serviceImportParseLogic.fillGroupsFinalFields(groupsAsList); - Either, ResponseFormat> createGroups = serviceBusinessLogic.groupBusinessLogic - .createGroups(service, groupsAsList, true); + Either, ResponseFormat> createGroups = groupBusinessLogic.createGroups(service, groupsAsList, true); if (createGroups.isRight()) { return Either.right(createGroups.right().value()); } } else { return Either.left(service); } + return getServiceResponseFormatEither(service); + } + + private Either createPoliciesOnResource(final Service service, + final Map policies) { + if (MapUtils.isEmpty(policies)) { + return Either.left(service); + } + Map> componentInstancesAttributes = service.getComponentInstancesAttributes(); + final Map> instanceAttributeMap = new HashMap<>(); + if (MapUtils.isNotEmpty(componentInstancesAttributes)) { + instanceAttributeMap.putAll(componentInstancesAttributes + .entrySet().stream() + .collect(toMap(Entry::getKey, entry -> entry.getValue().stream().map(AttributeDefinition.class::cast).collect(toList())))); + } + policies.values().stream() + .map(PolicyDataDefinition::getProperties) + .flatMap(Collection::stream) + .filter(PropertyDataDefinition::isToscaFunction) + .forEach(policyDefinition -> toscaFunctionService + .updateFunctionWithDataFromSelfComponent(policyDefinition.getToscaFunction(), service, service.getComponentInstancesProperties(), + instanceAttributeMap) + ); + policyBusinessLogic.createPolicies(service, policies); + return getServiceResponseFormatEither(service); + } + + private Either getServiceResponseFormatEither(Service service) { Either updatedResource = toscaOperationFacade.getToscaElement(service.getUniqueId()); if (updatedResource.isRight()) { ResponseFormat responseFormat = componentsUtils @@ -917,10 +1561,6 @@ public class ServiceImportBusinessLogic { List result = new ArrayList<>(); List componentInstances = component.getComponentInstances(); if (groups != null) { - Either validateCyclicGroupsDependencies = serviceImportParseLogic.validateCyclicGroupsDependencies(groups); - if (validateCyclicGroupsDependencies.isRight()) { - throw new ComponentException(validateCyclicGroupsDependencies.right().value()); - } for (Map.Entry entry : groups.entrySet()) { String groupName = entry.getKey(); GroupDefinition groupDefinition = entry.getValue(); @@ -982,7 +1622,7 @@ public class ServiceImportBusinessLogic { List relations = new ArrayList<>(); Map> instInputs = new HashMap<>(); Map instNodeFilter = new HashMap<>(); - + Map> instInterfaces = new HashMap<>(); log.debug("enter ServiceImportBusinessLogic createResourceInstancesRelations#createResourceInstancesRelations - Before get all datatypes. "); final ApplicationDataTypeCache applicationDataTypeCache = serviceBusinessLogic.applicationDataTypeCache; if (applicationDataTypeCache != null) { @@ -990,7 +1630,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); @@ -1012,7 +1653,7 @@ public class ServiceImportBusinessLogic { return eitherGetResource.left().value(); } - protected void processProperty(Resource resource, ComponentInstance currentCompInstance, Map allDataTypes, + protected void processProperty(Resource resource, Map allDataTypes, Map currPropertiesMap, List instPropList, List propertyList) { UploadPropInfo propertyInfo = propertyList.get(0); @@ -1240,11 +1881,11 @@ public class ServiceImportBusinessLogic { return result; } - public Map createResourcesFromYamlNodeTypesList(String yamlName, Resource resource, Map mappedToscaTemplate, - boolean needLock, - Map>> nodeTypesArtifactsToHandle, - List nodeTypesNewCreatedArtifacts, - Map nodeTypesInfo, CsarInfo csarInfo) { + private Map createResourcesFromYamlNodeTypesList(String yamlName, Resource resource, Map mappedToscaTemplate, + boolean needLock, + Map>> nodeTypesArtifactsToHandle, + List nodeTypesNewCreatedArtifacts, + Map nodeTypesInfo, CsarInfo csarInfo) { Either toscaVersion = findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION); if (toscaVersion.isRight()) { @@ -1296,10 +1937,13 @@ public class ServiceImportBusinessLogic { List 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); } @@ -1312,11 +1956,12 @@ public class ServiceImportBusinessLogic { log.debug("************* Going to create all nodes {}", yamlName); handleServiceNodeTypes(yamlName, service, topologyTemplateYaml, false, nodeTypesArtifactsToCreate, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeName); - if (!MapUtils.isEmpty(uploadComponentInstanceInfoMap)) { + List serviceProperties = null != service ? service.getProperties() : Collections.emptyList(); + if (MapUtils.isNotEmpty(uploadComponentInstanceInfoMap)) { log.debug("************* Going to create all resource instances {}", yamlName); service = createServiceInstances(yamlName, service, uploadComponentInstanceInfoMap, csarInfo.getCreatedNodes()); log.debug("************* Going to create all relations {}", yamlName); - service = createServiceInstancesRelations(csarInfo.getModifier(), yamlName, service, uploadComponentInstanceInfoMap); + service = createServiceInstancesRelations(csarInfo.getModifier(), yamlName, service, uploadComponentInstanceInfoMap, serviceProperties); log.debug("************* Going to create positions {}", yamlName); compositionBusinessLogic.setPositionsForComponentInstances(service, csarInfo.getModifier().getUserId()); log.debug("************* Finished to set positions {}", yamlName); @@ -1325,10 +1970,11 @@ public class ServiceImportBusinessLogic { } protected Service createServiceInstancesRelations(User user, String yamlName, Service service, - Map uploadResInstancesMap) { + Map uploadResInstancesMap, + List serviceProperties) { log.debug("#createResourceInstancesRelations - Going to create relations "); List componentInstancesList = service.getComponentInstances(); - if (((MapUtils.isEmpty(uploadResInstancesMap) || CollectionUtils.isEmpty(componentInstancesList)))) { // PNF can have no resource instances + if (MapUtils.isEmpty(uploadResInstancesMap) || CollectionUtils.isEmpty(componentInstancesList)) { // PNF can have no resource instances log.debug("#createResourceInstancesRelations - No instances found in the resource {} is empty, yaml template file name {}, ", service.getUniqueId(), yamlName); BeEcompErrorManager.getInstance() @@ -1346,16 +1992,28 @@ public class ServiceImportBusinessLogic { List relations = new ArrayList<>(); Map> instInputs = new HashMap<>(); Map instNodeFilter = new HashMap<>(); + Map> instInterfaces = new HashMap<>(); log.debug("enter ServiceImportBusinessLogic createServiceInstancesRelations#createResourceInstancesRelations - Before get all datatypes. "); final ApplicationDataTypeCache applicationDataTypeCache = serviceBusinessLogic.applicationDataTypeCache; if (applicationDataTypeCache != null) { - Service finalResource = service; + final Map allDataTypesMap = + componentsUtils.getAllDataTypes(applicationDataTypeCache, service.getModel()); + final Service service1 = service; + service1.setProperties(serviceProperties); uploadResInstancesMap.values().forEach( - i -> processComponentInstance(yamlName, finalResource, componentInstancesList, - componentsUtils.getAllDataTypes(applicationDataTypeCache, finalResource.getModel()), instProperties, - instCapabilities, instRequirements, instDeploymentArtifacts, instArtifacts, instAttributes, originCompMap, instInputs, instNodeFilter, i)); + i -> processComponentInstance(yamlName, service1, componentInstancesList, + allDataTypesMap, instProperties, + instCapabilities, instRequirements, instDeploymentArtifacts, instArtifacts, instAttributes, originCompMap, instInputs, + 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); @@ -1371,7 +2029,6 @@ public class ServiceImportBusinessLogic { service = getResourceAfterCreateRelations(service); addRelationsToRI(yamlName, service, uploadResInstancesMap, componentInstancesList, relations); serviceImportParseLogic.associateResourceInstances(yamlName, service, relations); - handleSubstitutionMappings(service, uploadResInstancesMap); log.debug("************* in create relations, getResource start"); Either eitherGetResource = toscaOperationFacade.getToscaElement(service.getUniqueId()); log.debug("************* in create relations, getResource end"); @@ -1383,6 +2040,29 @@ public class ServiceImportBusinessLogic { return eitherGetResource.left().value(); } + private void updatePropertyToscaFunctionData(final Component service, + final Map> instancePropertyMap, + final Map> instanceAttributeMap) { + final Component updatedService = + toscaOperationFacade.getToscaElement(service.getUniqueId()).left() + .on(storageOperationStatus -> { + final ActionStatus status = componentsUtils.convertFromStorageResponse(storageOperationStatus); + final ResponseFormat responseFormat = + componentsUtils.getResponseFormatByComponent(status, service, service.getComponentType()); + throw new ComponentException(responseFormat); + } + ); + instancePropertyMap.values().forEach(instancePropertyList -> + instancePropertyList.stream() + .filter(PropertyDataDefinition::isToscaFunction) + .forEach(instanceProperty -> { + toscaFunctionService.updateFunctionWithDataFromSelfComponent(instanceProperty.getToscaFunction(), + updatedService, instancePropertyMap, instanceAttributeMap); + instanceProperty.setValue(StringEscapeUtils.unescapeJava(instanceProperty.getToscaFunction().getValue())); + }) + ); + } + protected void processComponentInstance(String yamlName, Component component, List componentInstancesList, Map allDataTypes, Map> instProperties, @@ -1393,11 +2073,12 @@ public class ServiceImportBusinessLogic { Map> instAttributes, Map originCompMap, Map> instInputs, Map instNodeFilter, + Map> instInterfaces, UploadComponentInstanceInfo uploadComponentInstanceInfo) { log.debug("enter ServiceImportBusinessLogic processComponentInstance"); Optional currentCompInstanceOpt = componentInstancesList.stream() .filter(i -> i.getName().equals(uploadComponentInstanceInfo.getName())).findFirst(); - if (!currentCompInstanceOpt.isPresent()) { + if (currentCompInstanceOpt.isEmpty()) { log.debug(COMPONENT_INSTANCE_WITH_NAME_IN_RESOURCE, uploadComponentInstanceInfo.getName(), component.getUniqueId()); BeEcompErrorManager.getInstance() .logInternalDataError(COMPONENT_INSTANCE_WITH_NAME + uploadComponentInstanceInfo.getName() + IN_RESOURCE, component.getUniqueId(), @@ -1422,10 +2103,26 @@ public class ServiceImportBusinessLogic { } if (originResource.getAttributes() != null && !originResource.getAttributes().isEmpty()) { instAttributes.put(resourceInstanceId, originResource.getAttributes()); + addAttributeValueToResourceInstance(instAttributes, uploadComponentInstanceInfo.getAttributes()); } - if (uploadComponentInstanceInfo.getUploadNodeFilterInfo() != null) { + if (uploadComponentInstanceInfo.getUploadNodeFilterInfo() == null) { + instNodeFilter.put(resourceInstanceId, new UploadNodeFilterInfo()); + } else { 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); @@ -1451,7 +2148,7 @@ public class ServiceImportBusinessLogic { } originResource.getInputs().forEach(p -> serviceImportParseLogic.addInput(currPropertiesMap, p)); for (List 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); @@ -1462,7 +2159,7 @@ public class ServiceImportBusinessLogic { } } - protected void processProperty(Component component, ComponentInstance currentCompInstance, Map allDataTypes, + protected void processProperty(Component component, Map allDataTypes, Map currPropertiesMap, List instPropList, List propertyList) { UploadPropInfo propertyInfo = propertyList.get(0); @@ -1489,29 +2186,43 @@ public class ServiceImportBusinessLogic { } } + private void addAttributeValueToResourceInstance(Map> instAttributes, + Map attributeMap) { + if (attributeMap == null) { + return; + } + attributeMap.forEach((attributeName, attributeValue) -> instAttributes.values() + .forEach(value -> value.stream().filter(attr -> attr.getName().equals(attributeName)).forEach(attr -> { + if (attributeValue.getValue() instanceof Collection || attributeValue.getValue() instanceof Map) { + Gson gson = new Gson(); + String json = gson.toJson(attributeValue.getValue()); + attr.setValue(json); + } else { + attr.setValue(String.valueOf(attributeValue.getValue())); + } + }))); + } + protected ResponseFormat addPropertyValuesToRi(UploadComponentInstanceInfo uploadComponentInstanceInfo, Component component, Resource originResource, ComponentInstance currentCompInstance, Map> instProperties, Map allDataTypes) { Map> propMap = uploadComponentInstanceInfo.getProperties(); Map currPropertiesMap = new HashMap<>(); - List listFromMap = originResource.getProperties(); - if ((propMap != null && !propMap.isEmpty()) && (listFromMap == null || listFromMap.isEmpty())) { + List originalPropertyList = originResource.getProperties(); + if (MapUtils.isNotEmpty(propMap) && CollectionUtils.isEmpty(originalPropertyList)) { log.debug("failed to find properties "); return componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND); } - if (listFromMap == null || listFromMap.isEmpty()) { + if (CollectionUtils.isEmpty(originalPropertyList)) { return componentsUtils.getResponseFormat(ActionStatus.OK); } - for (PropertyDefinition prop : listFromMap) { - String propName = prop.getName(); - if (!currPropertiesMap.containsKey(propName)) { - currPropertiesMap.put(propName, prop); - } - } + originalPropertyList.stream() + .filter(property -> !currPropertiesMap.containsKey(property.getName())) + .forEach(property -> currPropertiesMap.put(property.getName(), property)); List instPropList = new ArrayList<>(); - if (propMap != null && propMap.size() > 0) { - for (List propertyList : propMap.values()) { + if (MapUtils.isNotEmpty(propMap)) { + for (final List propertyList : propMap.values()) { UploadPropInfo propertyInfo = propertyList.get(0); String propName = propertyInfo.getName(); if (!currPropertiesMap.containsKey(propName)) { @@ -1519,26 +2230,46 @@ public class ServiceImportBusinessLogic { return componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, propName); } PropertyDefinition curPropertyDef = currPropertiesMap.get(propName); - ComponentInstanceProperty property = null; String value = null; - List getInputs = null; + final List getInputs = new ArrayList<>(); boolean isValidate = true; if (propertyInfo.getValue() != null) { - getInputs = propertyInfo.getGet_input(); - isValidate = getInputs == null || getInputs.isEmpty(); + getInputs.addAll(propertyInfo.getGet_input()); + isValidate = getInputs.isEmpty(); if (isValidate) { value = getPropertyJsonStringValue(propertyInfo.getValue(), curPropertyDef.getType()); } else { value = getPropertyJsonStringValue(propertyInfo.getValue(), TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName()); } } - property = new ComponentInstanceProperty(curPropertyDef, value, null); - String validatePropValue = serviceBusinessLogic.validatePropValueBeforeCreate(property, value, isValidate, allDataTypes); - property.setValue(validatePropValue); - if (getInputs != null && !getInputs.isEmpty()) { - List getInputValues = new ArrayList<>(); - for (GetInputValueDataDefinition getInput : getInputs) { - List inputs = component.getInputs(); + final var property = new ComponentInstanceProperty(curPropertyDef, value, null); + String validatedPropValue = serviceBusinessLogic.validatePropValueBeforeCreate(property, value, true, allDataTypes); + + addSubPropertyYamlToscaFunctions(validatedPropValue, value, property.getType(), propertyInfo, allDataTypes); + + if (CollectionUtils.isNotEmpty(propertyInfo.getSubPropertyToscaFunctions())) { + validatedPropValue = value; + } + + property.setValue(validatedPropValue); + + if (tryHandlingAsYamlToscaFunction(validatedPropValue, value, propertyInfo)) { + try { + final Object yamlValue = new Yaml().loadAs(value, Object.class); + CustomYamlFunction toscaFunction = new CustomYamlFunction(); + toscaFunction.setYamlValue(yamlValue); + property.setToscaFunction(toscaFunction); + } catch (Exception exception) { + log.info("Cannot create YAML value for {}", propName); + } + } else { + property.setToscaFunction(propertyInfo.getToscaFunction()); + } + property.setSubPropertyToscaFunctions(propertyInfo.getSubPropertyToscaFunctions()); + if (!getInputs.isEmpty() && CollectionUtils.isEmpty(property.getSubPropertyToscaFunctions())) { + final List getInputValues = new ArrayList<>(); + for (final GetInputValueDataDefinition getInput : getInputs) { + final List inputs = component.getInputs(); if (inputs == null || inputs.isEmpty()) { log.debug("Failed to add property {} to instance. Inputs list is empty ", property); serviceBusinessLogic.rollbackWithException(ActionStatus.INPUTS_NOT_FOUND, @@ -1569,6 +2300,170 @@ public class ServiceImportBusinessLogic { return componentsUtils.getResponseFormat(ActionStatus.OK); } + private boolean tryHandlingAsYamlToscaFunction(String validatedPropValue, String value, UploadPropInfo propertyInfo) { + return StringUtils.isEmpty(validatedPropValue) && StringUtils.isNotEmpty(value) && propertyInfo.getToscaFunction() == null + && CollectionUtils.isEmpty(propertyInfo.getSubPropertyToscaFunctions()); + } + + private void addSubPropertyYamlToscaFunctions(final String validatedPropValue, final String value, final String propertyType, + final UploadPropInfo propertyInfo, final Map allDataTypes) { + if (StringUtils.isNotEmpty(validatedPropValue) || StringUtils.isEmpty(value) || ToscaPropertyType.isValidType(propertyType) != null) { + return; + } + try { + final JsonObject jsonObject = JsonParser.parseString(value).getAsJsonObject(); + + final DataTypeDefinition dataTypeDefinition = allDataTypes.get(propertyType); + final List propertyNames = + dataTypeDefinition.getProperties().stream().map(PropertyDataDefinition::getName).collect(Collectors.toList()); + + boolean hasSubPropertyValues = jsonObject.entrySet().stream().allMatch(entry -> propertyNames.contains(entry.getKey())); + + if (hasSubPropertyValues) { + for (final PropertyDefinition prop : dataTypeDefinition.getProperties()) { + if (propertyInfo.getSubPropertyToscaFunctions().stream() + .anyMatch(subPropertyToscaFunction -> subPropertyToscaFunction.getSubPropertyPath().get(0).equals(prop.getName()))) { + continue; + } + Optional subPropertyToscaFunction = createSubPropertyYamlToscaFunction(jsonObject, prop, allDataTypes); + if (subPropertyToscaFunction.isPresent()) { + propertyInfo.getSubPropertyToscaFunctions().add(subPropertyToscaFunction.get()); + } + } + } + } catch (Exception exception) { + log.info("Cannot create YAML value for {}", value); + } + } + + private Optional createSubPropertyYamlToscaFunction(final JsonObject jsonObject, final PropertyDefinition prop, + final Map allDataTypes) { + JsonElement propJsonElement = jsonObject.get(prop.getName()); + if (propJsonElement != null) { + final String subPropValue = propJsonElement.toString(); + final ComponentInstanceProperty subProperty = new ComponentInstanceProperty(prop, subPropValue, null); + final String validateSubPropValue = + serviceBusinessLogic.validatePropValueBeforeCreate(subProperty, subPropValue, true, allDataTypes); + + if (StringUtils.isEmpty(validateSubPropValue) && StringUtils.isNotEmpty(subPropValue)) { + try { + Object yamlValue = new Yaml().loadAs(subPropValue, Object.class); + SubPropertyToscaFunction subPropertyToscaFunction = new SubPropertyToscaFunction(); + CustomYamlFunction toscaFunction = new CustomYamlFunction(); + toscaFunction.setYamlValue(yamlValue); + subPropertyToscaFunction.setToscaFunction(toscaFunction); + subPropertyToscaFunction.setSubPropertyPath(Collections.singletonList(prop.getName())); + return Optional.of(subPropertyToscaFunction); + } catch (Exception exception) { + log.info("Cannot create YAML value for {}", subPropValue); + } + } + } + return Optional.empty(); + } + + protected ResponseFormat addInterfaceValuesToRi( + UploadComponentInstanceInfo uploadComponentInstanceInfo, + Component component, + Resource originResource, ComponentInstance currentCompInstance, + Map> instInterfaces + ) { + Map instanceInterfacesMap = uploadComponentInstanceInfo.getInterfaces(); + Map currInterfacesMap = new HashMap<>(); + Map 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 entryInstances : interfacesFromNodeType.entrySet()) { + String interfaceName = entryInstances.getKey().substring(entryInstances.getKey().lastIndexOf(".") + 1); + if (!currInterfacesMap.containsKey(interfaceName)) { + currInterfacesMap.put(interfaceName, entryInstances.getValue()); + } + } + + Map 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 operationsToAdd = new HashMap<>(); + + Map operations = uploadInterfaceInfo.getOperations(); + for (Map.Entry operation : operations.entrySet()) { + OperationDataDefinition instanceOperation = operation.getValue(); + OperationDataDefinition templateOperation = currentInterfaceDef.getOperationsMap() + .getOrDefault(operation.getKey(), new Operation(instanceOperation)); + //Inputs + ListDataDefinition instanceInputs = instanceOperation.getInputs(); + if (null != instanceInputs) { + mergeOperationInputDefinitions(templateOperation.getInputs(), instanceInputs); + component.getProperties() + .forEach(property -> instanceInputs.getListToscaDataDefinition().stream() + .filter(instanceInput -> + instanceInput.getToscaFunction() instanceof ToscaGetFunctionDataDefinition && + property.getName().equals(instanceInput.getToscaFunction() != null ? + ((ToscaGetFunctionDataDefinition) instanceInput.getToscaFunction()).getPropertyName() : null)) + .forEach(oldInput -> oldInput.setType(property.getType())) + ); + 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(currentInterfaceDef.getType(), 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 inputsFromNodeType, + ListDataDefinition instanceInputs) { + if (inputsFromNodeType == null || CollectionUtils.isEmpty(inputsFromNodeType.getListToscaDataDefinition()) || instanceInputs == null + || CollectionUtils.isEmpty(instanceInputs.getListToscaDataDefinition())) { + return; + } + 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 allDataTypes, Map>> instCapabilties, UploadComponentInstanceInfo uploadComponentInstanceInfo, @@ -1581,7 +2476,7 @@ public class ServiceImportBusinessLogic { originResource.getCapabilities().forEach((k, v) -> serviceImportParseLogic.addCapabilities(originCapabilities, k, v)); uploadComponentInstanceInfo.getCapabilities().values() .forEach(l -> serviceImportParseLogic.addCapabilitiesProperties(newPropertiesMap, l)); - updateCapabilityPropertiesValues(allDataTypes, originCapabilities, newPropertiesMap, originResource.getModel()); + updateCapabilityPropertiesValues(allDataTypes, originCapabilities, newPropertiesMap); } else { originCapabilities = originResource.getCapabilities(); } @@ -1590,7 +2485,7 @@ public class ServiceImportBusinessLogic { protected void updateCapabilityPropertiesValues(Map allDataTypes, Map> originCapabilities, - Map> newPropertiesMap, String model) { + Map> newPropertiesMap) { originCapabilities.values().stream().flatMap(Collection::stream).filter(c -> newPropertiesMap.containsKey(c.getName())) .forEach(c -> updatePropertyValues(c.getProperties(), newPropertiesMap.get(c.getName()), allDataTypes)); } @@ -1637,25 +2532,6 @@ public class ServiceImportBusinessLogic { return originResource; } - protected void handleSubstitutionMappings(Service service, Map uploadResInstancesMap) { - if (false) { - Either getResourceRes = toscaOperationFacade.getToscaFullElement(service.getUniqueId()); - if (getResourceRes.isRight()) { - ResponseFormat responseFormat = componentsUtils - .getResponseFormatByComponent(componentsUtils.convertFromStorageResponse(getResourceRes.right().value()), service, - ComponentTypeEnum.SERVICE); - throw new ComponentException(responseFormat); - } - getResourceRes = updateCalculatedCapReqWithSubstitutionMappings(getResourceRes.left().value(), uploadResInstancesMap); - if (getResourceRes.isRight()) { - ResponseFormat responseFormat = componentsUtils - .getResponseFormatByComponent(componentsUtils.convertFromStorageResponse(getResourceRes.right().value()), service, - ComponentTypeEnum.SERVICE); - throw new ComponentException(responseFormat); - } - } - } - protected Either updateCalculatedCapReqWithSubstitutionMappings(Resource resource, Map uploadResInstancesMap) { Either updateRes = null; @@ -1698,7 +2574,7 @@ public class ServiceImportBusinessLogic { if (MapUtils.isNotEmpty(capabilitiesNamesToUpdate)) { for (Map.Entry> requirements : instance.getCapabilities().entrySet()) { updatedCapabilities.put(requirements.getKey(), requirements.getValue().stream().filter( - c -> capabilitiesNamesToUpdate.containsKey(c.getName()) && !updatedCapNames.contains(capabilitiesNamesToUpdate.get(c.getName()))) + c -> capabilitiesNamesToUpdate.containsKey(c.getName()) && !updatedCapNames.contains(capabilitiesNamesToUpdate.get(c.getName()))) .map(c -> { c.setParentName(c.getName()); c.setName(capabilitiesNamesToUpdate.get(c.getName())); @@ -1719,7 +2595,7 @@ public class ServiceImportBusinessLogic { if (MapUtils.isNotEmpty(requirementsNamesToUpdate)) { for (Map.Entry> requirements : instance.getRequirements().entrySet()) { updatedRequirements.put(requirements.getKey(), requirements.getValue().stream().filter( - r -> requirementsNamesToUpdate.containsKey(r.getName()) && !updatedReqNames.contains(requirementsNamesToUpdate.get(r.getName()))) + r -> requirementsNamesToUpdate.containsKey(r.getName()) && !updatedReqNames.contains(requirementsNamesToUpdate.get(r.getName()))) .map(r -> { r.setParentName(r.getName()); r.setName(requirementsNamesToUpdate.get(r.getName())); @@ -1790,7 +2666,7 @@ public class ServiceImportBusinessLogic { regCapRelDef.setFromNode(resourceInstanceId); log.debug("try to find available requirement {} ", regName); Either eitherReqStatus = serviceImportParseLogic - .findAviableRequiremen(regName, yamlName, nodesInfoValue, currentCompInstance, uploadRegInfo.getCapabilityName()); + .findAvailableRequirement(regName, yamlName, nodesInfoValue, currentCompInstance, uploadRegInfo.getCapabilityName()); if (eitherReqStatus.isRight()) { log.debug("failed to find available requirement {} status is {}", regName, eitherReqStatus.right().value()); return eitherReqStatus.right().value(); @@ -1825,17 +2701,20 @@ public class ServiceImportBusinessLogic { log.debug("try to find aviable Capability req name is {} ", validReq.getName()); CapabilityDefinition aviableCapForRel = serviceImportParseLogic .findAvailableCapabilityByTypeOrName(validReq, currentCapCompInstance, uploadRegInfo); - reqAndRelationshipPair.setCapability(aviableCapForRel.getName()); - reqAndRelationshipPair.setCapabilityUid(aviableCapForRel.getUniqueId()); - reqAndRelationshipPair.setCapabilityOwnerId(aviableCapForRel.getOwnerId()); if (aviableCapForRel == null) { BeEcompErrorManager.getInstance().logInternalDataError( "aviable capability was not found. req name is " + validReq.getName() + " component instance is " + currentCapCompInstance .getUniqueId(), service.getUniqueId(), BeEcompErrorManager.ErrorSeverity.ERROR); return componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); } + reqAndRelationshipPair.setCapability(aviableCapForRel.getName()); + reqAndRelationshipPair.setCapabilityUid(aviableCapForRel.getUniqueId()); + reqAndRelationshipPair.setCapabilityOwnerId(aviableCapForRel.getOwnerId()); CapabilityRequirementRelationship capReqRel = new CapabilityRequirementRelationship(); capReqRel.setRelation(reqAndRelationshipPair); + if (StringUtils.isNotEmpty(uploadRegInfo.getRelationshipTemplate())) { + capReqRel.setOperations(getOperations(nodesInfoValue.getOperations(), uploadRegInfo.getRelationshipTemplate())); + } reqAndRelationshipPairList.add(capReqRel); regCapRelDef.setRelationships(reqAndRelationshipPairList); relations.add(regCapRelDef); @@ -1845,6 +2724,16 @@ public class ServiceImportBusinessLogic { return componentsUtils.getResponseFormat(ActionStatus.OK, yamlName); } + private List getOperations(final Map> operations, final String relationshipTemplate) { + final List operationUiList = new ArrayList<>(); + operations.forEach((operationKey, operationValues) -> { + if (operationKey.equals(relationshipTemplate)) { + operationUiList.addAll(operationValues); + } + }); + return operationUiList; + } + protected Service getResourceAfterCreateRelations(Service service) { ComponentParametersView parametersView = serviceImportParseLogic.getComponentFilterAfterCreateRelations(); Either eitherGetResource = toscaOperationFacade.getToscaElement(service.getUniqueId(), parametersView); @@ -1907,7 +2796,8 @@ public class ServiceImportBusinessLogic { if (nodeNamespaceMap.containsKey(uploadComponentInstanceInfo.getType())) { uploadComponentInstanceInfo.setType(nodeNamespaceMap.get(uploadComponentInstanceInfo.getType()).getToscaResourceName()); } - Resource refResource = validateResourceInstanceBeforeCreate(yamlName, uploadComponentInstanceInfo, existingnodeTypeMap); + Resource refResource = + validateResourceInstanceBeforeCreate(yamlName, component.getModel(), uploadComponentInstanceInfo, existingnodeTypeMap); ComponentInstance componentInstance = new ComponentInstance(); componentInstance.setComponentUid(refResource.getUniqueId()); Collection directives = uploadComponentInstanceInfo.getDirectives(); @@ -1938,27 +2828,32 @@ public class ServiceImportBusinessLogic { Resource origResource = existingnodeTypeMap.get(uploadComponentInstanceInfo.getType()); componentInstance.setName(uploadComponentInstanceInfo.getName()); componentInstance.setIcon(origResource.getIcon()); + componentInstance.setMinOccurrences(uploadComponentInstanceInfo.getMinOccurrences()); + componentInstance.setMaxOccurrences(uploadComponentInstanceInfo.getMaxOccurrences()); + componentInstance.setInstanceCount(uploadComponentInstanceInfo.getInstanceCount()); resourcesInstancesMap.put(componentInstance, origResource); - } catch (Exception e) { + } catch (final ComponentException e) { + throw e; + } catch (final Exception e) { throw new ComponentException(ActionStatus.GENERAL_ERROR, e.getMessage()); } } - protected Resource validateResourceInstanceBeforeCreate(String yamlName, UploadComponentInstanceInfo uploadComponentInstanceInfo, + protected Resource validateResourceInstanceBeforeCreate(String yamlName, String model, UploadComponentInstanceInfo uploadComponentInstanceInfo, Map nodeNamespaceMap) { Resource refResource; try { if (nodeNamespaceMap.containsKey(uploadComponentInstanceInfo.getType())) { refResource = nodeNamespaceMap.get(uploadComponentInstanceInfo.getType()); } else { - Either findResourceEither = toscaOperationFacade - .getLatestResourceByToscaResourceName(uploadComponentInstanceInfo.getType()); - if (findResourceEither.isRight()) { + final Either resourceEither = + toscaOperationFacade.getLatestByToscaResourceName(uploadComponentInstanceInfo.getType(), model); + if (resourceEither.isRight()) { ResponseFormat responseFormat = componentsUtils - .getResponseFormat(componentsUtils.convertFromStorageResponse(findResourceEither.right().value())); + .getResponseFormat(componentsUtils.convertFromStorageResponse(resourceEither.right().value())); throw new ComponentException(responseFormat); } - refResource = findResourceEither.left().value(); + refResource = (Resource) resourceEither.left().value(); nodeNamespaceMap.put(refResource.getToscaResourceName(), refResource); } String componentState = refResource.getComponentMetadataDefinition().getMetadataDataDefinition().getState(); @@ -1976,7 +2871,9 @@ public class ServiceImportBusinessLogic { throw new ComponentException(responseFormat); } return refResource; - } catch (Exception e) { + } catch (final ComponentException e) { + throw e; + } catch (final Exception e) { throw new ComponentException(ActionStatus.GENERAL_ERROR, e.getMessage()); } } @@ -2151,8 +3048,8 @@ public class ServiceImportBusinessLogic { .auditResource(responseFormat, csarInfo.getModifier(), preparedResource == null ? oldRresource : preparedResource, actionEnum); throw e; } - Either, ResponseFormat> validateUpdateVfGroupNamesRes = serviceBusinessLogic.groupBusinessLogic - .validateUpdateVfGroupNames(uploadComponentInstanceInfoMap.getGroups(), preparedResource.getSystemName()); + Either, ResponseFormat> validateUpdateVfGroupNamesRes = groupBusinessLogic.validateUpdateVfGroupNames( + uploadComponentInstanceInfoMap.getGroups(), preparedResource.getSystemName()); if (validateUpdateVfGroupNamesRes.isRight()) { throw new ComponentException(validateUpdateVfGroupNamesRes.right().value()); } @@ -2244,8 +3141,8 @@ public class ServiceImportBusinessLogic { nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeTypesArtifactsToCreate, nodeName); log.trace("************* Finished to create nodes, RI and Relation from yaml {}", yamlName); // validate update vf module group names - Either, ResponseFormat> validateUpdateVfGroupNamesRes = serviceBusinessLogic.groupBusinessLogic - .validateUpdateVfGroupNames(parsedToscaYamlInfo.getGroups(), resource.getSystemName()); + Either, ResponseFormat> validateUpdateVfGroupNamesRes = groupBusinessLogic.validateUpdateVfGroupNames( + parsedToscaYamlInfo.getGroups(), resource.getSystemName()); if (validateUpdateVfGroupNamesRes.isRight()) { serviceImportParseLogic.rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); throw new ComponentException(validateUpdateVfGroupNamesRes.right().value()); @@ -2281,11 +3178,10 @@ public class ServiceImportBusinessLogic { throw e; } finally { if (!inTransaction) { - serviceBusinessLogic.janusGraphDao.commit(); + janusGraphDao.commit(); } if (shouldLock) { - serviceBusinessLogic.graphLockOperation - .unlockComponentByName(resource.getSystemName(), resource.getUniqueId(), NodeTypeEnum.Resource); + graphLockOperation.unlockComponentByName(resource.getSystemName(), resource.getUniqueId(), NodeTypeEnum.Resource); } } } @@ -2295,8 +3191,7 @@ public class ServiceImportBusinessLogic { List groupsAsList = updateGroupsMembersUsingResource(groups, resource); serviceImportParseLogic.handleGroupsProperties(resource, groups); serviceImportParseLogic.fillGroupsFinalFields(groupsAsList); - Either, ResponseFormat> createGroups = serviceBusinessLogic.groupBusinessLogic - .createGroups(resource, groupsAsList, true); + Either, ResponseFormat> createGroups = groupBusinessLogic.createGroups(resource, groupsAsList, true); if (createGroups.isRight()) { return Either.right(createGroups.right().value()); } @@ -2316,10 +3211,6 @@ public class ServiceImportBusinessLogic { List result = new ArrayList<>(); List componentInstances = component.getComponentInstances(); if (groups != null) { - Either validateCyclicGroupsDependencies = serviceImportParseLogic.validateCyclicGroupsDependencies(groups); - if (validateCyclicGroupsDependencies.isRight()) { - throw new ComponentException(validateCyclicGroupsDependencies.right().value()); - } for (Map.Entry entry : groups.entrySet()) { String groupName = entry.getKey(); GroupDefinition groupDefinition = entry.getValue(); @@ -2372,7 +3263,7 @@ public class ServiceImportBusinessLogic { .getResponseFormat(componentsUtils.convertFromStorageResponse(eitherValidation.right().value())); throw new ComponentException(errorResponse); } - if (eitherValidation.left().value()) { + if (Boolean.TRUE.equals(eitherValidation.left().value())) { log.debug("resource with name: {}, already exists", resource.getName()); ResponseFormat errorResponse = componentsUtils .getResponseFormat(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, ComponentTypeEnum.RESOURCE.getValue(), resource.getName()); @@ -2418,13 +3309,13 @@ public class ServiceImportBusinessLogic { } finally { if (resourcePair == null) { BeEcompErrorManager.getInstance().logBeSystemError("Change LifecycleState - Certify"); - serviceBusinessLogic.janusGraphDao.rollback(); + janusGraphDao.rollback(); } else if (!inTransaction) { - serviceBusinessLogic.janusGraphDao.commit(); + janusGraphDao.commit(); } if (needLock) { log.debug("unlock resource {}", lockedResourceId); - serviceBusinessLogic.graphLockOperation.unlockComponent(lockedResourceId, NodeTypeEnum.Resource); + graphLockOperation.unlockComponent(lockedResourceId, NodeTypeEnum.Resource); } } } @@ -2502,23 +3393,24 @@ public class ServiceImportBusinessLogic { Resource vfcCreated = null; while (nodesNameValueIter.hasNext()) { Map.Entry nodeType = nodesNameValueIter.next(); + String nodeTypeKey = nodeType.getKey(); Map> nodeTypeArtifactsToHandle = - nodeTypesArtifactsToHandle == null || nodeTypesArtifactsToHandle.isEmpty() ? null : nodeTypesArtifactsToHandle.get(nodeType.getKey()); - if (nodeTypesInfo.containsKey(nodeType.getKey())) { + nodeTypesArtifactsToHandle == null || nodeTypesArtifactsToHandle.isEmpty() ? null : nodeTypesArtifactsToHandle.get(nodeTypeKey); + if (nodeTypesInfo.containsKey(nodeTypeKey)) { vfcCreated = handleNestedVfc(service, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, - nodeType.getKey()); - log.trace("************* Finished to handle nested vfc {}", nodeType.getKey()); + nodeTypeKey); + log.trace("************* Finished to handle nested vfc {}", nodeTypeKey); } else if (csarInfo.getCreatedNodesToscaResourceNames() != null && !csarInfo.getCreatedNodesToscaResourceNames() - .containsKey(nodeType.getKey())) { + .containsKey(nodeTypeKey)) { ImmutablePair resourceCreated = serviceImportParseLogic .createNodeTypeResourceFromYaml(yamlName, nodeType, csarInfo.getModifier(), mapToConvert, service, needLock, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts, true, csarInfo, true); - log.debug("************* Finished to create node {}", nodeType.getKey()); + log.debug("************* Finished to create node {}", nodeTypeKey); vfcCreated = resourceCreated.getLeft(); - csarInfo.getCreatedNodesToscaResourceNames().put(nodeType.getKey(), vfcCreated.getName()); + csarInfo.getCreatedNodesToscaResourceNames().put(nodeTypeKey, vfcCreated.getName()); } if (vfcCreated != null) { - csarInfo.getCreatedNodes().put(nodeType.getKey(), vfcCreated); + csarInfo.getCreatedNodes().put(nodeTypeKey, vfcCreated); } mapToConvert.remove(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName()); }