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=8671d9e27ac9239ee832a4e3f9c3ece705310072;hb=8d59b022d1b35a4549ff4a1f3aeea0c11214c6fb;hp=ca8a13dba37066338e1b45e1c0d7311c2aa3898e;hpb=9c696c0d1787d50a8481f7ccc66f30a3e0b6e197;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 ca8a13dba3..8671d9e27a 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,12 +13,15 @@ * 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.CsarValidationUtils.TOSCA_METADATA_PATH_PATTERN; +import static org.openecomp.sdc.be.components.impl.CsarValidationUtils.TOSCA_META_ENTRY_DEFINITIONS; 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; @@ -29,7 +32,12 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import fj.data.Either; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +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; @@ -41,16 +49,18 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Optional; +import java.util.Properties; import java.util.Set; import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; import java.util.stream.Collectors; +import javax.validation.constraints.NotNull; 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; @@ -61,6 +71,7 @@ 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; @@ -86,6 +97,7 @@ 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; @@ -147,6 +159,7 @@ 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; @@ -162,6 +175,8 @@ import org.openecomp.sdc.common.datastructure.Wrapper; import org.openecomp.sdc.common.kpi.api.ASDCKpiApi; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.common.util.ValidationUtils; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.beans.factory.annotation.Autowired; import org.yaml.snakeyaml.Yaml; @@ -201,16 +216,15 @@ public class ServiceImportBusinessLogic { private final IGraphLockOperation graphLockOperation; private final ToscaFunctionService toscaFunctionService; private final DataTypeBusinessLogic dataTypeBusinessLogic; - private ApplicationDataTypeCache applicationDataTypeCache; private final ArtifactTypeOperation artifactTypeOperation; - private final GroupTypeImportManager groupTypeImportManager; private final GroupTypeOperation groupTypeOperation; - private InterfaceLifecycleOperation interfaceLifecycleTypeOperation; - private InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager; - private final CapabilityTypeImportManager capabilityTypeImportManager; private final CapabilityTypeOperation capabilityTypeOperation; + private final InterfaceLifecycleOperation interfaceLifecycleTypeOperation; + private final InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager; + private final ModelOperation modelOperation; + private ApplicationDataTypeCache applicationDataTypeCache; public ServiceImportBusinessLogic(final GroupBusinessLogic groupBusinessLogic, final ArtifactsBusinessLogic artifactsBusinessLogic, final ComponentsUtils componentsUtils, final ToscaOperationFacade toscaOperationFacade, @@ -227,7 +241,8 @@ public class ServiceImportBusinessLogic { final InterfaceLifecycleOperation interfaceLifecycleTypeOperation, final InterfaceLifecycleTypeImportManager interfaceLifecycleTypeImportManager, final CapabilityTypeImportManager capabilityTypeImportManager, - final CapabilityTypeOperation capabilityTypeOperation) { + final CapabilityTypeOperation capabilityTypeOperation, + final ModelOperation modelOperation) { this.componentsUtils = componentsUtils; this.toscaOperationFacade = toscaOperationFacade; this.serviceBusinessLogic = serviceBusinessLogic; @@ -253,6 +268,7 @@ public class ServiceImportBusinessLogic { this.interfaceLifecycleTypeImportManager = interfaceLifecycleTypeImportManager; this.capabilityTypeImportManager = capabilityTypeImportManager; this.capabilityTypeOperation = capabilityTypeOperation; + this.modelOperation = modelOperation; } @Autowired @@ -260,14 +276,108 @@ public class ServiceImportBusinessLogic { 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); + } + + public Service updateServiceFromToscaModel(final String serviceId, final User modifier, final @NotNull InputStream fileToUpload) { + final Either serviceResponseFormatEither = serviceBusinessLogic.getService(serviceId, modifier); + if (serviceResponseFormatEither.isRight()) { + throw new ByActionStatusComponentException(ActionStatus.SERVICE_NOT_FOUND, serviceId); + } + final Service serviceOriginal = serviceResponseFormatEither.left().value(); + Map csar = null; + try { + csar = ZipUtils.readZip(fileToUpload.readAllBytes(), false); + } catch (final ZipException | IOException e) { + log.info("Failed to unzip received csar {}", serviceId, e); + } + if (csar == null) { + throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND); + } + final byte[] mainYamlBytes = readMainYamlFile(csar); + final Map metadata = (Map) new Yaml().loadAs(new String(mainYamlBytes), Map.class).get("metadata"); + validateServiceMetadataBeforeCreate(serviceOriginal, metadata); + final Service newService = cloneServiceIdentifications(serviceOriginal); + updateServiceMetadata(newService, metadata); + return createService(newService, AuditingActionEnum.UPDATE_SERVICE_TOSCA_MODEL, modifier, csar, null); + } + + private byte[] readMainYamlFile(final Map csar) { + final Pattern pattern = Pattern.compile(TOSCA_METADATA_PATH_PATTERN); + final Optional keyOp = csar.keySet().stream().filter(k -> pattern.matcher(k).matches()).findAny(); + if (keyOp.isEmpty()) { + throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND_IN_CSAR, TOSCA_METADATA_PATH_PATTERN, ""); + } + final Properties props = new Properties(); + try { + final String propStr = new String(csar.get(keyOp.get())); + props.load(new StringReader(propStr.replace("\\", "\\\\"))); + } catch (IOException e) { + throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND_IN_CSAR, TOSCA_META_ENTRY_DEFINITIONS, ""); + } + final String mainYamlFileName = props.getProperty(TOSCA_META_ENTRY_DEFINITIONS); + final byte[] mainYamlBytes = csar.get(mainYamlFileName); + if (mainYamlBytes == null) { + throw new ByActionStatusComponentException(ActionStatus.ARTIFACT_NOT_FOUND_IN_CSAR, mainYamlFileName, ""); + } + return mainYamlBytes; + } + + 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); + 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 { final var serviceBeforeCreate = serviceBusinessLogic.validateServiceBeforeCreate(service, user, auditingAction); if (serviceBeforeCreate.isRight()) { @@ -275,10 +385,12 @@ public class ServiceImportBusinessLogic { } 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); + return createServiceFromCsar(service, user, csarUIPayload, csarUUID, auditingAction); } catch (final ComponentException e) { log.debug("Exception occurred when createService: {}", e.getMessage(), e); throw e; @@ -288,10 +400,31 @@ public class ServiceImportBusinessLogic { } } - 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 { - final ServiceCsarInfo 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)) { @@ -308,7 +441,8 @@ public class ServiceImportBusinessLogic { final List nodeTypesToCreate = getNodeTypesToCreate(serviceModel, csarInfo); if (CollectionUtils.isNotEmpty(nodeTypesToCreate)) { - createNodeTypes(nodeTypesToCreate, serviceModel, csarInfo.getModifier()); + ParsedToscaYamlInfo parsedToscaYamlInfo = csarBusinessLogic.getParsedToscaYamlInfo(csarInfo, service); + createNodeTypes(nodeTypesToCreate, parsedToscaYamlInfo.getInstances(), serviceModel, csarInfo.getModifier()); } final Map groupTypesToCreate = getGroupTypesToCreate(serviceModel, csarInfo); @@ -324,7 +458,6 @@ public class ServiceImportBusinessLogic { } final Map capabilityTypesToCreate = getCapabilityTypesToCreate(serviceModel, csarInfo); - if (MapUtils.isNotEmpty(capabilityTypesToCreate)) { capabilityTypeImportManager.createCapabilityTypes(new Yaml().dump(capabilityTypesToCreate), serviceModel, true); } @@ -337,7 +470,7 @@ public class ServiceImportBusinessLogic { throw new ComponentException(findNodeTypesArtifactsToHandleRes.right().value()); } return createServiceFromYaml(service, csarInfo.getMainTemplateContent(), csarInfo.getMainTemplateName(), nodeTypesInfo, csarInfo, - findNodeTypesArtifactsToHandleRes.left().value(), true, false, null, user.getUserId()); + 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; @@ -459,7 +592,8 @@ public class ServiceImportBusinessLogic { && result.left().value().getProperties().size() != dataType.get("properties").size(); } - private void createNodeTypes(List nodeTypesToCreate, String model, User user) { + private void createNodeTypes(List nodeTypesToCreate, Map instancesFromCsar, String model, + User user) { NodeTypesMetadataList nodeTypesMetadataList = new NodeTypesMetadataList(); List nodeTypeMetadataList = new ArrayList<>(); final Map allTypesToCreate = new HashMap<>(); @@ -468,7 +602,7 @@ public class ServiceImportBusinessLogic { nodeTypeMetadataList.add(nodeType.getNodeTypeMetadata()); }); nodeTypesMetadataList.setNodeMetadataList(nodeTypeMetadataList); - resourceImportManager.importAllNormativeResource(allTypesToCreate, nodeTypesMetadataList, user, model, true, false); + resourceImportManager.importAllNormativeResource(allTypesToCreate, nodeTypesMetadataList, instancesFromCsar, user, model, true, false); } private List getNodeTypesToCreate(final String model, final ServiceCsarInfo csarInfo) { @@ -487,6 +621,9 @@ public class ServiceImportBusinessLogic { 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); @@ -528,7 +665,7 @@ public class ServiceImportBusinessLogic { private void combineInterfacesIntoToscaTemplate(Map> newInterfaces, Map> existingInterfaces, Map combinedMappedToscaTemplate) { - Map> combinedInterfaces = combineAdditionalInterfaces(existingInterfaces, newInterfaces); + Map> combinedInterfaces = combineAdditionalInterfaces(newInterfaces, existingInterfaces); if ((MapUtils.isEmpty(existingInterfaces) && MapUtils.isNotEmpty(combinedInterfaces)) || (MapUtils.isNotEmpty(existingInterfaces) && !existingInterfaces.equals(combinedInterfaces))) { combinedMappedToscaTemplate.put("interfaces", combinedInterfaces); @@ -571,8 +708,11 @@ public class ServiceImportBusinessLogic { } } - private Map> combineAdditionalInterfaces(Map> existingInterfaces, - Map> newInterfaces) { + 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<>(); } @@ -593,6 +733,9 @@ public class ServiceImportBusinessLogic { 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<>(); } @@ -607,6 +750,9 @@ public class ServiceImportBusinessLogic { } 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<>(); } @@ -620,8 +766,9 @@ public class ServiceImportBusinessLogic { protected Service createServiceFromYaml(Service service, String topologyTemplateYaml, String yamlName, Map nodeTypesInfo, CsarInfo csarInfo, - Map>> nodeTypesArtifactsToCreate, - boolean shouldLock, boolean inTransaction, String nodeName, final String userId) + Map>> nodeTypesArtifactsToCreate, + boolean shouldLock, boolean inTransaction, String nodeName, final String userId, + AuditingActionEnum auditingAction) throws BusinessLogicException { List createdArtifacts = new ArrayList<>(); Service createdService; @@ -637,7 +784,8 @@ public class ServiceImportBusinessLogic { csfyp.setNodeTypesInfo(nodeTypesInfo); csfyp.setCsarInfo(csarInfo); csfyp.setNodeName(nodeName); - createdService = createServiceAndRIsFromYaml(service, false, nodeTypesArtifactsToCreate, shouldLock, inTransaction, csfyp, userId); + 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); @@ -650,10 +798,11 @@ public class ServiceImportBusinessLogic { } protected Service createServiceAndRIsFromYaml(Service service, boolean isNormative, - Map>> nodeTypesArtifactsToCreate, + Map>> nodeTypesArtifactsToCreate, boolean shouldLock, boolean inTransaction, CreateServiceFromYamlParameter csfyp, - final String userId) + final String userId, AuditingActionEnum auditingAction) throws BusinessLogicException { + List nodeTypesNewCreatedArtifacts = new ArrayList<>(); String yamlName = csfyp.getYamlName(); ParsedToscaYamlInfo parsedToscaYamlInfo = csfyp.getParsedToscaYamlInfo(); @@ -665,7 +814,6 @@ 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); @@ -683,12 +831,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("************* Finished to add inputs from yaml {}", yamlName); - ListDataDefinition substitutionFilterProperties = parsedToscaYamlInfo.getSubstitutionFilterProperties(); + ListDataDefinition substitutionFilterProperties = + parsedToscaYamlInfo.getSubstitutionFilterProperties(); service = serviceImportParseLogic.createSubstitutionFilterOnService(service, substitutionFilterProperties); log.trace("************* Added Substitution filter from interface yaml {}", yamlName); Map uploadComponentInstanceInfoMap = parsedToscaYamlInfo.getInstances(); @@ -704,7 +853,6 @@ public class ServiceImportBusinessLogic { 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; @@ -716,23 +864,19 @@ 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()) { - serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); 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()); @@ -740,7 +884,7 @@ public class ServiceImportBusinessLogic { ASDCKpiApi.countCreatedResourcesKPI(); return service; - } catch (ComponentException | StorageException | BusinessLogicException e) { + } catch (Exception e) { rollback = true; serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); throw e; @@ -753,7 +897,7 @@ public class ServiceImportBusinessLogic { } } if (shouldLock) { - graphLockOperation.unlockComponentByName(service.getSystemName(), service.getUniqueId(), NodeTypeEnum.Resource); + graphLockOperation.unlockComponentByName(service.getSystemName(), service.getUniqueId(), NodeTypeEnum.Service); } } } @@ -763,14 +907,26 @@ public class ServiceImportBusinessLogic { if (CollectionUtils.isNotEmpty(inputs)) { final List componentInstances = component.getComponentInstances(); final String componentUniqueId = component.getUniqueId(); + List propertyMissingNames = new ArrayList<>(); for (final InputDefinition input : inputs) { - if (isInputFromComponentInstanceProperty(input.getName(), componentInstances)) { + 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 { - associateInputToServiceProperty(userId, input, component, substitutionMappingProperties); + 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); @@ -782,22 +938,20 @@ public class ServiceImportBusinessLogic { private boolean isInputFromComponentInstanceProperty(final String inputName, final List componentInstances) { - AtomicBoolean isInputFromCIProp = new AtomicBoolean(false); if (CollectionUtils.isNotEmpty(componentInstances)) { - outer: for (ComponentInstance instance : 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())) { - isInputFromCIProp.set(true); - break outer; + return true; } } } } } } - return isInputFromCIProp.get(); + return false; } private void associateInputToComponentInstanceProperty(final String userId, final InputDefinition input, @@ -807,7 +961,8 @@ public class ServiceImportBusinessLogic { String componentInstanceId = null; ComponentInstanceProperty componentInstanceProperty = new ComponentInstanceProperty(); - outer: for (ComponentInstance instance : componentInstances) { + outer: + for (ComponentInstance instance : componentInstances) { for (PropertyDefinition instanceProperty : instance.getProperties()) { if (CollectionUtils.isNotEmpty(instanceProperty.getGetInputValues())) { for (GetInputValueDataDefinition getInputValueDataDefinition : instanceProperty.getGetInputValues()) { @@ -835,9 +990,9 @@ public class ServiceImportBusinessLogic { } } - private void associateInputToServiceProperty(final String userId, - final InputDefinition input, final Service component, - final Map> substitutionMappingProperties) { + 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<>(" "); @@ -847,8 +1002,9 @@ public class ServiceImportBusinessLogic { } }); - final Optional propDefOptional = properties.stream().filter(prop -> prop.getName().equals(propertyNameFromInput.get())) - .findFirst(); + final Optional propDefOptional = + properties.stream().filter(prop -> prop.getName().equals(propertyNameFromInput.get())) + .findFirst(); if (propDefOptional.isPresent()) { // From SELF final String componentUniqueId = component.getUniqueId(); @@ -864,8 +1020,12 @@ public class ServiceImportBusinessLogic { 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) { @@ -893,8 +1053,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, @@ -1021,7 +1182,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()); @@ -1180,7 +1342,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); @@ -1312,7 +1473,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); @@ -1847,11 +2009,12 @@ public class ServiceImportBusinessLogic { log.debug("************* Going to create all nodes {}", yamlName); handleServiceNodeTypes(yamlName, service, topologyTemplateYaml, false, nodeTypesArtifactsToCreate, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeName); + 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); @@ -1860,7 +2023,8 @@ 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 @@ -1888,6 +2052,7 @@ public class ServiceImportBusinessLogic { final Map allDataTypesMap = componentsUtils.getAllDataTypes(applicationDataTypeCache, service.getModel()); final Service service1 = service; + service1.setProperties(serviceProperties); uploadResInstancesMap.values().forEach( i -> processComponentInstance(yamlName, service1, componentInstancesList, allDataTypesMap, instProperties, @@ -1946,7 +2111,7 @@ public class ServiceImportBusinessLogic { .forEach(instanceProperty -> { toscaFunctionService.updateFunctionWithDataFromSelfComponent(instanceProperty.getToscaFunction(), updatedService, instancePropertyMap, instanceAttributeMap); - instanceProperty.setValue(instanceProperty.getToscaFunction().getValue()); + instanceProperty.setValue(StringEscapeUtils.unescapeJava(instanceProperty.getToscaFunction().getValue())); }) ); } @@ -1992,8 +2157,11 @@ public class ServiceImportBusinessLogic { if (originResource.getAttributes() != null && !originResource.getAttributes().isEmpty()) { instAttributes.put(resourceInstanceId, originResource.getAttributes()); addAttributeValueToResourceInstance(instAttributes, uploadComponentInstanceInfo.getAttributes()); + instAttributes.get(resourceInstanceId).addAll(addImplicitAttributeValues(originResource, uploadComponentInstanceInfo)); } - if (uploadComponentInstanceInfo.getUploadNodeFilterInfo() != null) { + if (uploadComponentInstanceInfo.getUploadNodeFilterInfo() == null) { + instNodeFilter.put(resourceInstanceId, new UploadNodeFilterInfo()); + } else { instNodeFilter.put(resourceInstanceId, uploadComponentInstanceInfo.getUploadNodeFilterInfo()); } if (MapUtils.isNotEmpty(uploadComponentInstanceInfo.getInterfaces())) { @@ -2020,6 +2188,44 @@ public class ServiceImportBusinessLogic { } } + private List addImplicitAttributeValues(Resource originResource, UploadComponentInstanceInfo uploadComponentInstanceInfo) { + if (uploadComponentInstanceInfo.getAttributes() == null) { + return Collections.emptyList(); + } + List origAttributes = originResource.getAttributes().stream().map(AttributeDefinition::getName).collect(toList()); + Map uploadAttributes = uploadComponentInstanceInfo.getAttributes(); + List newAttributesToAdd = + uploadAttributes.keySet().stream().filter(newAttribute -> !origAttributes.contains(newAttribute)) + .collect(toList()); + List propsToAddAsAttributes = + originResource.getProperties().stream().filter(prop -> newAttributesToAdd.contains(prop.getName())).collect(toList()); + propsToAddAsAttributes.stream().forEach(prop -> { + Object value = uploadAttributes.get(prop.getName()).getValue(); + if (value instanceof Collection || value instanceof Map) { + Gson gson = new Gson(); + String json = gson.toJson(value); + prop.setValue(json); + } else { + prop.setValue(String.valueOf(value)); + } + }); + List attributesToAdd = new ArrayList<>(); + for (PropertyDefinition prop : propsToAddAsAttributes) { + attributesToAdd.add(getPropertyAsAttribute(prop)); + } + return attributesToAdd; + } + + private AttributeDefinition getPropertyAsAttribute(PropertyDefinition property) { + AttributeDefinition attribute = new AttributeDefinition(); + attribute.setName(property.getName()); + attribute.setType(property.getType()); + attribute.setSchema(property.getSchema()); + attribute.setValue(property.getValue()); + attribute.setDefaultValue(property.getDefaultValue()); + return attribute; + } + protected void addInputsValuesToRi(UploadComponentInstanceInfo uploadComponentInstanceInfo, Component component, Resource originResource, ComponentInstance currentCompInstance, Map> instInputs, Map allDataTypes) { @@ -2257,13 +2463,13 @@ public class ServiceImportBusinessLogic { Map instanceInterfacesMap = uploadComponentInstanceInfo.getInterfaces(); Map currInterfacesMap = new HashMap<>(); Map interfacesFromNodeType = originResource.getInterfaces(); - if ((MapUtils.isNotEmpty(instanceInterfacesMap)) && (MapUtils.isEmpty(interfacesFromNodeType))) { + if (interfacesFromNodeType == null) { + interfacesFromNodeType = new HashMap<>(); + } + if (MapUtils.isEmpty(instanceInterfacesMap) && MapUtils.isEmpty(instanceInterfacesMap)) { 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)) { @@ -2275,25 +2481,42 @@ public class ServiceImportBusinessLogic { if (MapUtils.isNotEmpty(instanceInterfacesMap)) { for (UploadInterfaceInfo uploadInterfaceInfo : instanceInterfacesMap.values()) { String interfaceName = uploadInterfaceInfo.getName(); + InterfaceDefinition currentInterfaceDef; if (!currInterfacesMap.containsKey(interfaceName)) { - log.debug("failed to find interface {} ", interfaceName); - return componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceName); + currentInterfaceDef = getInterfaceDef(interfaceName, component.getModel()); + if (currentInterfaceDef == null) { + log.debug("failed to find interface {} ", interfaceName); + return componentsUtils.getResponseFormat(ActionStatus.INTERFACE_NOT_FOUND_IN_COMPONENT, interfaceName); + } + } else { + currentInterfaceDef = currInterfacesMap.get(interfaceName); } - InterfaceDefinition currentInterfaceDef = currInterfacesMap.get(interfaceName); Map operationsToAdd = new HashMap<>(); Map operations = uploadInterfaceInfo.getOperations(); for (Map.Entry operation : operations.entrySet()) { - OperationDataDefinition templateOperation = currentInterfaceDef.getOperationsMap().get(operation.getKey()); OperationDataDefinition instanceOperation = operation.getValue(); + OperationDataDefinition templateOperation = currentInterfaceDef.getOperationsMap() + .getOrDefault(operation.getKey(), new Operation(instanceOperation)); //Inputs ListDataDefinition instanceInputs = instanceOperation.getInputs(); - mergeOperationInputDefinitions(templateOperation.getInputs(), instanceInputs); - templateOperation.setInputs(instanceInputs); + 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()); + templateOperation.setMilestones(instanceOperation.getMilestones()); operationsToAdd.put(operation.getKey(), templateOperation); } InterfaceDefinition interfaceDef = new InterfaceDefinition(); @@ -2315,6 +2538,21 @@ public class ServiceImportBusinessLogic { return componentsUtils.getResponseFormat(ActionStatus.OK); } + private InterfaceDefinition getInterfaceDef(String interfaceName, String model) { + Either, StorageOperationStatus> interfaceLifecycleTypesEither = + interfaceLifecycleTypeOperation.getAllInterfaceLifecycleTypes(model); + if (interfaceLifecycleTypesEither.isRight()) { + return null; + } + Map interfaceLifecycleTypes = interfaceLifecycleTypesEither.left().value(); + Optional interfaceType = + interfaceLifecycleTypes.values().stream().filter(interfaceDef -> interfaceDef.getUniqueId().contains(interfaceName)).findFirst(); + if (interfaceType.isEmpty()) { + return null; + } + return interfaceType.get(); + } + private void mergeOperationInputDefinitions(ListDataDefinition inputsFromNodeType, ListDataDefinition instanceInputs) { if (inputsFromNodeType == null || CollectionUtils.isEmpty(inputsFromNodeType.getListToscaDataDefinition()) || instanceInputs == null @@ -2703,6 +2941,9 @@ 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 (final ComponentException e) { throw e;