diff options
Diffstat (limited to 'catalog-be/src/main/java')
31 files changed, 8205 insertions, 106 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarArtifactsAndGroupsBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarArtifactsAndGroupsBusinessLogic.java index 697d6faecb..c34a006b6c 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarArtifactsAndGroupsBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarArtifactsAndGroupsBusinessLogic.java @@ -71,6 +71,7 @@ import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.info.ArtifactTemplateInfo; import org.openecomp.sdc.be.info.MergedArtifactInfo; import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.GroupDefinition; import org.openecomp.sdc.be.model.GroupProperty; @@ -79,6 +80,7 @@ import org.openecomp.sdc.be.model.HeatParameterDefinition; import org.openecomp.sdc.be.model.Operation; import org.openecomp.sdc.be.model.PropertyDefinition; import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.heat.HeatParameterType; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; @@ -137,21 +139,48 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { .right() .map(rf -> { componentsUtils.auditResource(rf, csarInfo.getModifier(), resource, AuditingActionEnum.IMPORT_RESOURCE); return rf;}) .left() - .bind(this::getResourcetFromGraph); + .bind(c -> checkoutRes(c)); } + private Either<Resource, ResponseFormat> checkoutRes(Component component) { + Either<? extends Component, ResponseFormat> checkoutRes = getResourcetFromGraph(component); + Resource resource1 = (Resource) checkoutRes.left().value(); + Either<Resource, ResponseFormat> checkoutRes1 = Either.left(resource1); + return checkoutRes1; + } + + public Either<Service, ResponseFormat> createResourceArtifactsFromCsar(CsarInfo csarInfo, Service resource, + String artifactsMetaFile, String artifactsMetaFileName, List<ArtifactDefinition> createdArtifacts + ) { - public Either<Resource, ResponseFormat> updateResourceArtifactsFromCsar(CsarInfo csarInfo, Resource resource, + log.debug("parseResourceArtifactsInfoFromFile start"); + return parseResourceArtifactsInfoFromFile(resource, artifactsMetaFile, artifactsMetaFileName) + .left() + .bind(p -> createResourceArtifacts(csarInfo, resource, p, createdArtifacts)) + .right() + .map(rf -> rf) + .left() + .bind(c -> { + Either<? extends Component, ResponseFormat> checkoutRes = getResourcetFromGraph(c); + Service resource1 = (Service) checkoutRes.left().value(); + Either<Service, ResponseFormat> checkoutRes1 = Either.left(resource1); + return checkoutRes1; + }); + } + + public Either<Component, ResponseFormat> updateResourceArtifactsFromCsar(CsarInfo csarInfo, Component resource, String artifactsMetaFile, String artifactsMetaFileName, List<ArtifactDefinition> createdNewArtifacts, boolean shouldLock, boolean inTransaction){ - Resource updatedResource = resource; + Component updatedResource = resource; Either<Map<String, List<ArtifactTemplateInfo>>, ResponseFormat> parseResourceInfoFromYamlEither = parseResourceArtifactsInfoFromFile( updatedResource, artifactsMetaFile, artifactsMetaFileName); if (parseResourceInfoFromYamlEither.isRight()) { ResponseFormat responseFormat = parseResourceInfoFromYamlEither.right().value(); - componentsUtils.auditResource(responseFormat, csarInfo.getModifier(), resource, AuditingActionEnum.IMPORT_RESOURCE); + if (resource instanceof Resource) { + componentsUtils.auditResource(responseFormat, csarInfo.getModifier(), (Resource) resource, AuditingActionEnum.IMPORT_RESOURCE); + } return Either.right(responseFormat); } @@ -183,8 +212,8 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { Collection<List<ArtifactTemplateInfo>> parsedArifactsCollection = parsedArtifactsMap.values(); Either<Map<ArtifactTemplateInfo, Set<ArtifactTemplateInfo>>, ResponseFormat> parsedArtifactsPerGroupEither = createArtifactsTemplateCollection(csarInfo, updatedResource, createdNewArtifacts, - createdDeploymentArtifactsAfterDelete, labelCounter, parsedArifactsCollection); - if(parsedArtifactsPerGroupEither.isRight()){ + createdDeploymentArtifactsAfterDelete, labelCounter, parsedArifactsCollection); + if (parsedArtifactsPerGroupEither.isRight()) { log.error("Failed to parse artifacts. Status is {} ", parsedArtifactsPerGroupEither.right().value()); return Either.right(parsedArtifactsPerGroupEither.right().value()); } @@ -207,7 +236,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { artifactsToDelete, groupToDelete, jsonMasterArtifacts, createdDeploymentArtifactsAfterDelete); List<ArtifactDefinition> deletedArtifacts = new ArrayList<>(); - Either<Resource, ResponseFormat> deletedArtifactsEither = deleteArtifactsInUpdateCsarFlow( + Either<Component, ResponseFormat> deletedArtifactsEither = deleteArtifactsInUpdateCsarFlow( updatedResource, csarInfo.getModifier(), shouldLock, inTransaction, artifactsToDelete, groupToDelete, deletedArtifacts); if (deletedArtifactsEither.isRight()) { log.debug("Failed to delete artifacts. Status is {} ", deletedArtifactsEither.right().value()); @@ -222,7 +251,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { ////////////// dissociate, associate or create ////////////// artifacts//////////////////////////// - Either<Resource, ResponseFormat> assDissotiateEither = associateAndDissociateArtifactsToGroup(csarInfo, + Either<Component, ResponseFormat> assDissotiateEither = associateAndDissociateArtifactsToGroup(csarInfo, updatedResource, createdNewArtifacts, labelCounter, createdDeploymentArtifactsAfterDelete, mergedgroup, deletedArtifacts); groups = updatedResource.getGroups(); @@ -239,37 +268,37 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { // update vfModule names Set<GroupDefinition> groupForAssociateWithMembers = mergedgroup.keySet(); - Either<Resource, ResponseFormat> validateUpdateVfGroupNamesRes = updateVfModuleNames(createdNewArtifacts, + Either<Component, ResponseFormat> validateUpdateVfGroupNamesRes = updateVfModuleNames(createdNewArtifacts, updatedResource, groups, createdDeploymentArtifactsAfterDelete, groupForAssociateWithMembers); if (validateUpdateVfGroupNamesRes != null) return validateUpdateVfGroupNamesRes; //////////////// create new artifacts in update //////////////// flow//////////////////////////// List<ArtifactTemplateInfo> newArtifactsGroup = createNewArtifcats(parsedGroup, groupArtifact); - Either<Resource, ResponseFormat> validateGroupNamesRes = handleArtifactsInGroup(csarInfo, createdNewArtifacts, + Either<Component, ResponseFormat> validateGroupNamesRes = handleArtifactsInGroup(csarInfo, createdNewArtifacts, updatedResource, groups, createdDeploymentArtifactsAfterDelete, labelCounter, newArtifactsGroup); if (validateGroupNamesRes != null) return validateGroupNamesRes; // updatedGroup - Either<Resource, ResponseFormat> updateVersionEither = updateGroupVersion(updatedResource, groupForAssociateWithMembers); + Either<Component, ResponseFormat> updateVersionEither = updateGroupVersion(updatedResource, groupForAssociateWithMembers); if (updateVersionEither != null) return updateVersionEither; if (!CollectionUtils.isEmpty(artifactsWithoutGroups)) { for (ArtifactTemplateInfo t : artifactsWithoutGroups) { List<ArtifactTemplateInfo> artifacts = new ArrayList<>(); artifacts.add(t); - Either<Resource, ResponseFormat> resStatus = createGroupDeploymentArtifactsFromCsar(csarInfo, updatedResource, + Either<Component, ResponseFormat> resStatus = createGroupDeploymentArtifactsFromCsar(csarInfo, updatedResource, artifacts, createdNewArtifacts, createdDeploymentArtifactsAfterDelete, labelCounter); if (checkResponse(resStatus)) return resStatus; } } - Either<Resource, StorageOperationStatus> eitherGetResource = toscaOperationFacade.getToscaElement(updatedResource.getUniqueId()); + Either<Component, StorageOperationStatus> eitherGetResource = toscaOperationFacade.getToscaElement(updatedResource.getUniqueId()); return mapResult(eitherGetResource, updatedResource); } - private Either<Resource, ResponseFormat> handleArtifactsInGroup(CsarInfo csarInfo, List<ArtifactDefinition> createdNewArtifacts, - Resource updatedResource, List<GroupDefinition> groups, + private Either<Component, ResponseFormat> handleArtifactsInGroup(CsarInfo csarInfo, List<ArtifactDefinition> createdNewArtifacts, + Component updatedResource, List<GroupDefinition> groups, List<ArtifactDefinition> createdDeploymentArtifactsAfterDelete, int labelCounter, List<ArtifactTemplateInfo> newArtifactsGroup) { if (!newArtifactsGroup.isEmpty()) { @@ -280,18 +309,18 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { if (validateGroupNamesRes.isRight()) { return Either.right(validateGroupNamesRes.right().value()); } - Either<Resource, ResponseFormat> resStatus = createGroupDeploymentArtifactsFromCsar(csarInfo, updatedResource, + Either<Component, ResponseFormat> resStatus = createGroupDeploymentArtifactsFromCsar(csarInfo, updatedResource, newArtifactsGroup, createdNewArtifacts, createdDeploymentArtifactsAfterDelete, labelCounter); checkResponse(resStatus); } return null; } - private boolean checkResponse(Either<Resource, ResponseFormat> resStatus) { + private boolean checkResponse(Either<Component, ResponseFormat> resStatus) { return (resStatus.isRight()); } - private Either<Resource, ResponseFormat> updateVfModuleNames(List<ArtifactDefinition> createdNewArtifacts, Resource updatedResource, List<GroupDefinition> groups, List<ArtifactDefinition> createdDeploymentArtifactsAfterDelete, Set<GroupDefinition> groupForAssociateWithMembers) { + private Either<Component, ResponseFormat> updateVfModuleNames(List<ArtifactDefinition> createdNewArtifacts, Component updatedResource, List<GroupDefinition> groups, List<ArtifactDefinition> createdDeploymentArtifactsAfterDelete, Set<GroupDefinition> groupForAssociateWithMembers) { if (!CollectionUtils.isEmpty(groups)) { Either<List<GroupDefinition>, ResponseFormat> validateUpdateVfGroupNamesRes = groupBusinessLogic .validateUpdateVfGroupNamesOnGraph(groups, updatedResource); @@ -303,7 +332,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { return null; } - private Either<Resource, ResponseFormat> updateGroupVersion(Resource updatedResource, Set<GroupDefinition> groupForAssociateWithMembers) { + private Either<Component, ResponseFormat> updateGroupVersion(Component updatedResource, Set<GroupDefinition> groupForAssociateWithMembers) { if (!groupForAssociateWithMembers.isEmpty()) { List<GroupDefinition> groupsId = groupForAssociateWithMembers.stream() @@ -341,7 +370,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { return Character.isDigit(artifactLabel.charAt(artifactLabel.length()-1)); } - private Either<Resource, ResponseFormat> mapResult(Either<Resource, StorageOperationStatus> result, Resource resource) { + private Either<Component, ResponseFormat> mapResult(Either<Component, StorageOperationStatus> result, Component resource) { return result.right() .map(status -> componentsUtils.getResponseFormatByResource( componentsUtils.convertFromStorageResponse(status), resource)); @@ -396,7 +425,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { } - private void deleteGroupsByType(List<GroupDefinition> groups, String groupType, Resource resource) { + private void deleteGroupsByType(List<GroupDefinition> groups, String groupType, Component resource) { if(groups != null){ List<GroupDefinition> listToDelete = groups.stream() .filter(g -> g.getType().equals(groupType)) @@ -452,11 +481,11 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { } - private Either<Resource, ResponseFormat> createResourceArtifacts(CsarInfo csarInfo, Resource resource, + private Either<Component, ResponseFormat> createResourceArtifacts(CsarInfo csarInfo, Component resource, Map<String, List<ArtifactTemplateInfo>> artifactsMap, List<ArtifactDefinition> createdArtifacts) { - Either<Resource, ResponseFormat> resStatus = Either.left(resource); + Either<Component, ResponseFormat> resStatus = Either.left(resource); Collection<List<ArtifactTemplateInfo>> arifactsCollection = artifactsMap.values(); @@ -476,7 +505,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { private Either<Map<ArtifactTemplateInfo, Set<ArtifactTemplateInfo>>, ResponseFormat> createArtifactsTemplateCollection( - CsarInfo csarInfo, Resource resource, + CsarInfo csarInfo, Component resource, List<ArtifactDefinition> createdNewArtifacts, List<ArtifactDefinition> createdDeploymentArtifactsAfterDelete, int labelCounter, Collection<List<ArtifactTemplateInfo>> parsedArifactsCollection) { @@ -498,7 +527,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { } else { List<ArtifactTemplateInfo> arrtifacts = new ArrayList<>(); arrtifacts.add(parsedGroupTemplate); - Either<Resource, ResponseFormat> resStatus = createGroupDeploymentArtifactsFromCsar(csarInfo, + Either<Component, ResponseFormat> resStatus = createGroupDeploymentArtifactsFromCsar(csarInfo, resource, arrtifacts, createdNewArtifacts, createdDeploymentArtifactsAfterDelete, labelCounter); if (resStatus.isRight()) { @@ -514,7 +543,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { @SuppressWarnings({ "unchecked", "static-access" }) public Either<Map<String, List<ArtifactTemplateInfo>>, ResponseFormat> parseResourceArtifactsInfoFromFile( - Resource resource, String artifactsMetaFile, String artifactFileName) { + Component resource, String artifactsMetaFile, String artifactFileName) { try { JsonObject jsonElement = new JsonObject(); @@ -622,8 +651,8 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { - private Either<Resource, ResponseFormat> createGroupDeploymentArtifactsFromCsar(CsarInfo csarInfo, - Resource resource, List<ArtifactTemplateInfo> artifactsTemplateList, + private Either<Component, ResponseFormat> createGroupDeploymentArtifactsFromCsar(CsarInfo csarInfo, + Component resource, List<ArtifactTemplateInfo> artifactsTemplateList, List<ArtifactDefinition> createdArtifacts, int labelCounter) { List<GroupDefinition> createdGroups = resource.getGroups(); List<GroupDefinition> heatGroups = null; @@ -637,7 +666,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { Set<String> artifactsUUIDGroup = new HashSet<>(); log.debug("createDeploymentArtifactsFromCsar start"); - Either<Resource, ResponseFormat> resStatus = createDeploymentArtifactFromCsar(csarInfo, ARTIFACTS_PATH, resource, artifactsGroup, + Either<Component, ResponseFormat> resStatus = createDeploymentArtifactFromCsar(csarInfo, ARTIFACTS_PATH, resource, artifactsGroup, artifactsUUIDGroup, groupTemplateInfo, createdArtifacts, labelCounter); log.debug("createDeploymentArtifactsFromCsar end"); if (resStatus.isRight()) { @@ -707,10 +736,10 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { return Either.left(groupDefinition); } - private Either<Resource, ResponseFormat> createDeploymentArtifactFromCsar(CsarInfo csarInfo, String artifactPath, - Resource resource, Set<String> artifactsGroup, Set<String> artifactsUUIDGroup, + private Either<Component, ResponseFormat> createDeploymentArtifactFromCsar(CsarInfo csarInfo, String artifactPath, + Component resource, Set<String> artifactsGroup, Set<String> artifactsUUIDGroup, ArtifactTemplateInfo artifactTemplateInfo, List<ArtifactDefinition> createdArtifacts, int labelCounter) { - Either<Resource, ResponseFormat> resStatus = Either.left(resource); + Either<Component, ResponseFormat> resStatus = Either.left(resource); String artifactUid = ""; String artifactEnvUid = ""; @@ -801,7 +830,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { } - private Either<ArtifactDefinition, ResponseFormat> createDeploymentArtifact(CsarInfo csarInfo, Resource resource, + private Either<ArtifactDefinition, ResponseFormat> createDeploymentArtifact(CsarInfo csarInfo, Component resource, String artifactPath, ArtifactTemplateInfo artifactTemplateInfo, List<ArtifactDefinition> createdArtifacts, int label) { int updatedlabel = label; @@ -847,10 +876,10 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { - private Either<ArtifactDefinition, ResponseFormat> updateHeatParamsFromCsar(Resource resource, CsarInfo csarInfo, + private Either<ArtifactDefinition, ResponseFormat> updateHeatParamsFromCsar(Component resource, CsarInfo csarInfo, ArtifactTemplateInfo artifactTemplateInfo, ArtifactDefinition currentInfo, boolean isUpdateEnv) { - Resource updatedResource = resource; + Component updatedResource = resource; Either<ArtifactDefinition, ResponseFormat> resStatus = Either.left(currentInfo); if (artifactTemplateInfo.getEnv() != null && !artifactTemplateInfo.getEnv().isEmpty()) { @@ -920,7 +949,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { } - private Either<ArtifactDefinition, ResponseFormat> updateHeatParams(Resource resource, + private Either<ArtifactDefinition, ResponseFormat> updateHeatParams(Component resource, ArtifactDefinition currentInfo, List<HeatParameterDefinition> updatedHeatEnvParams) { Either<ArtifactDefinition, ResponseFormat> resStatus = Either.left(currentInfo); @@ -973,7 +1002,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { } public Either<Either<ArtifactDefinition, Operation>, ResponseFormat> createOrUpdateCsarArtifactFromJson( - Resource resource, User user, Map<String, Object> json, ArtifactOperationInfo operation) { + Component resource, User user, Map<String, Object> json, ArtifactOperationInfo operation) { String jsonStr = gson.toJson(json); ArtifactDefinition artifactDefinitionFromJson = RepresentationUtils.convertJsonToArtifactDefinition(jsonStr, @@ -1231,11 +1260,11 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { return groupArtifact; } - private Either<Resource, ResponseFormat> deleteArtifactsInUpdateCsarFlow(Resource resource, + private Either<Component, ResponseFormat> deleteArtifactsInUpdateCsarFlow(Component resource, User user, boolean shouldLock, boolean inTransaction, Set<ArtifactDefinition> artifactsToDelete, Map<String, List<ArtifactDefinition>> groupToDelete, List<ArtifactDefinition> deletedArtifacts) { - Resource updatedResource = resource; + Component updatedResource = resource; String resourceId = updatedResource.getUniqueId(); if (!artifactsToDelete.isEmpty()) { @@ -1279,8 +1308,8 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { Either<Resource, StorageOperationStatus> eitherGerResource = toscaOperationFacade .getToscaElement(updatedResource.getUniqueId()); if (eitherGerResource.isRight()) { - ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource( - componentsUtils.convertFromStorageResponse(eitherGerResource.right().value()), updatedResource); + ResponseFormat responseFormat = componentsUtils.getResponseFormatByComponent( + componentsUtils.convertFromStorageResponse(eitherGerResource.right().value()), updatedResource, resource.getComponentType()); return Either.right(responseFormat); @@ -1302,14 +1331,14 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { } } - private Either<Resource, ResponseFormat> createGroupDeploymentArtifactsFromCsar(CsarInfo csarInfo, - Resource resource, List<ArtifactTemplateInfo> artifactsTemplateList, + private Either<Component, ResponseFormat> createGroupDeploymentArtifactsFromCsar(CsarInfo csarInfo, + Component resource, List<ArtifactTemplateInfo> artifactsTemplateList, List<ArtifactDefinition> createdNewArtifacts, List<ArtifactDefinition> artifactsFromResource, int labelCounter) { - Resource updatedResource = resource; + Component updatedResource = resource; - Either<Resource, ResponseFormat> resStatus = Either.left(updatedResource); + Either<Component, ResponseFormat> resStatus = Either.left(updatedResource); List<GroupDefinition> createdGroups = updatedResource.getGroups(); List<GroupDefinition> heatGroups = null; if (createdGroups != null && !createdGroups.isEmpty()) { @@ -1388,10 +1417,10 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { return resStatus; } - private Either<Resource, ResponseFormat> createDeploymentArtifactsFromCsar(CsarInfo csarInfo, Resource resource, + private Either<Component, ResponseFormat> createDeploymentArtifactsFromCsar(CsarInfo csarInfo, Component resource, Set<String> artifactsGroup, Set<String> artifactsUUIDGroup, ArtifactTemplateInfo artifactTemplateInfo, List<ArtifactDefinition> createdArtifacts, List<ArtifactDefinition> artifactsFromResource, int labelCounter) { - Either<Resource, ResponseFormat> resStatus = Either.left(resource); + Either<Component, ResponseFormat> resStatus = Either.left(resource); String artifactFileName = artifactTemplateInfo.getFileName(); String artifactUid = ""; String artifactUUID = ""; @@ -1487,13 +1516,13 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { return resStatus; } - private Either<Resource, ResponseFormat> associateAndDissociateArtifactsToGroup(CsarInfo csarInfo, - Resource resource, List<ArtifactDefinition> createdNewArtifacts, int labelCounter, + private Either<Component, ResponseFormat> associateAndDissociateArtifactsToGroup(CsarInfo csarInfo, + Component resource, List<ArtifactDefinition> createdNewArtifacts, int labelCounter, List<ArtifactDefinition> createdDeploymentArtifactsAfterDelete, Map<GroupDefinition, MergedArtifactInfo> mergedgroup, List<ArtifactDefinition> deletedArtifacts) { Map<GroupDefinition, List<ArtifactTemplateInfo>> artifactsToAssotiate = new HashMap<>(); Map<GroupDefinition, List<ImmutablePair<ArtifactDefinition, ArtifactTemplateInfo>>> artifactsToUpdateMap = new HashMap<>(); - Either<Resource, ResponseFormat> resEither; + Either<Component, ResponseFormat> resEither; for (Entry<GroupDefinition, MergedArtifactInfo> entry : mergedgroup.entrySet()) { List<ArtifactDefinition> dissArtifactsInGroup = entry.getValue() .getListToDissotiateArtifactFromGroup(deletedArtifacts); @@ -1649,8 +1678,8 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { .getToscaElement(resource.getUniqueId(), parametersView); if (eitherGerResource.isRight()) { - ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource( - componentsUtils.convertFromStorageResponse(eitherGerResource.right().value()), resource); + ResponseFormat responseFormat = componentsUtils.getResponseFormatByComponent( + componentsUtils.convertFromStorageResponse(eitherGerResource.right().value()), resource, resource.getComponentType()); resEither = Either.right(responseFormat); return resEither; @@ -1661,7 +1690,7 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { } private Either<ArtifactDefinition, ResponseFormat> updateDeploymentArtifactsFromCsar(CsarInfo csarInfo, - Resource resource, ArtifactDefinition oldArtifact, ArtifactTemplateInfo artifactTemplateInfo, + Component resource, ArtifactDefinition oldArtifact, ArtifactTemplateInfo artifactTemplateInfo, List<ArtifactDefinition> updatedArtifacts, List<ArtifactTemplateInfo> updatedRequiredArtifacts) { Either<ArtifactDefinition, ResponseFormat> resStatus = null; @@ -1763,15 +1792,57 @@ public class CsarArtifactsAndGroupsBusinessLogic extends BaseBusinessLogic { return Either.left(updatedResource); } - private Either<Resource, ResponseFormat> getResourcetFromGraph(Resource component){ + public Either<Service, ResponseFormat> deleteVFModules(Service resource, CsarInfo csarInfo, boolean shouldLock, boolean inTransaction) { + Service updatedResource = resource; + List<GroupDefinition> groupsToDelete = updatedResource.getGroups(); + if (groupsToDelete != null && !groupsToDelete.isEmpty()) { + List<GroupDefinition> vfGroupsToDelete = groupsToDelete.stream().filter(g -> g.getType().equals(Constants.DEFAULT_GROUP_VF_MODULE)).collect(Collectors.toList()); + Either<Service, ResponseFormat> eitherGetResource = deleteVfGroups(vfGroupsToDelete, updatedResource, csarInfo, shouldLock, inTransaction); + if (eitherGetResource.isRight()) { + return Either.right(eitherGetResource.right().value()); + } + updatedResource = eitherGetResource.left().value(); + } + return Either.left(updatedResource); + } + + private Either<Service, ResponseFormat> deleteVfGroups(List<GroupDefinition> vfGroupsToDelete, Service resource, CsarInfo csarInfo, boolean shouldLock, boolean inTransaction) { + ResponseFormat responseFormat; + if (vfGroupsToDelete != null && !vfGroupsToDelete.isEmpty()) { + for (GroupDefinition gr : vfGroupsToDelete) { + List<String> artifacts = gr.getArtifacts(); + for (String artifactId : artifacts) { + Either<ArtifactDefinition, ResponseFormat> handleDelete = artifactsBusinessLogic.handleDelete(resource.getUniqueId(), artifactId, csarInfo.getModifier(), + resource, shouldLock, inTransaction); + if (handleDelete.isRight()) { + log.debug("Couldn't delete artifact {}", artifactId); + return Either.right(handleDelete.right().value()); + } + } + } + groupBusinessLogic.deleteGroups(resource, vfGroupsToDelete); + + Either<Service, StorageOperationStatus> eitherGetResource = toscaOperationFacade.getToscaElement(resource.getUniqueId()); + if (eitherGetResource.isRight()) { + responseFormat = componentsUtils.getResponseFormatByComponent(componentsUtils.convertFromStorageResponse(eitherGetResource.right().value()), resource, resource.getComponentType()); + + return Either.right(responseFormat); + } + resource = eitherGetResource.left().value(); + return Either.left(resource); + } + responseFormat = componentsUtils.getResponseFormatByComponent(ActionStatus.INVALID_CONTENT, resource, resource.getComponentType()); + return Either.right(responseFormat); + } + + + private Either<? extends Component, ResponseFormat> getResourcetFromGraph(Component component) { log.debug("getResource start"); return toscaOperationFacade.getToscaElement(component.getUniqueId()) .right() - .map(rf -> componentsUtils.getResponseFormatByResource(componentsUtils.convertFromStorageResponse(rf), component)) + .map(rf -> componentsUtils.getResponseFormatByComponent(componentsUtils.convertFromStorageResponse(rf), component, component.getComponentType())) .left() - .map (c -> (Resource) c); - - + .map(c -> c); } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java index e16f08b859..15cde435ed 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java @@ -28,11 +28,14 @@ import org.openecomp.sdc.be.components.impl.CsarValidationUtils; import org.openecomp.sdc.be.components.impl.GroupBusinessLogic; 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.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.NodeTypeInfo; import org.openecomp.sdc.be.model.ParsedToscaYamlInfo; import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; @@ -98,6 +101,21 @@ public class CsarBusinessLogic extends BaseBusinessLogic { } } + public void validateCsarBeforeCreate(Service resource, String csarUUID) { + // check if VF with the same Csar UUID or with he same name already + // exists + StorageOperationStatus status = toscaOperationFacade.validateCsarUuidUniqueness(csarUUID); + log.debug("enter validateCsarBeforeCreate,get status:{}", status); + if (status == StorageOperationStatus.ENTITY_ALREADY_EXISTS) { + log.debug("Failed to create resource {}, csarUUID {} already exist for a different VF ", + resource.getSystemName(), csarUUID); + } else if (status != StorageOperationStatus.OK) { + log.debug("Failed to validate uniqueness of CsarUUID {} for resource", csarUUID, + resource.getSystemName()); + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(status)); + } + } + public CsarInfo getCsarInfo(Resource resource, Resource oldResource,User user, Map<String, byte[]> payload, String csarUUID){ Map<String, byte[]> csar = getCsar(resource, user, payload, csarUUID); ImmutablePair<String, String> toscaYamlCsarStatus = validateAndParseCsar(resource, @@ -120,11 +138,32 @@ public class CsarBusinessLogic extends BaseBusinessLogic { toscaYamlCsarStatus.getKey(), toscaYamlCsarStatus.getValue(), true); } + public CsarInfo getCsarInfo(Service service, Service oldResource,User user, Map<String, byte[]> payload, String csarUUID){ + Map<String, byte[]> csar = getCsar(service, user, payload, csarUUID); + ImmutablePair<String, String> toscaYamlCsarStatus = validateAndParseCsar(service, + user, csar, csarUUID) + .left().on(this::throwComponentException); - public ParsedToscaYamlInfo getParsedToscaYamlInfo(String topologyTemplateYaml, String yamlName, Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, String nodeName) { + String checksum = CsarValidationUtils.getToscaYamlChecksum(csar, + csarUUID, componentsUtils).left().on(r->logAndThrowComponentException(r, "Failed to calculate checksum for casrUUID {} error {} ", csarUUID)); + if (oldResource!=null && !checksum.equals( + oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().getImportedToscaChecksum())) { + log.debug("The checksum of main template yaml of csar with csarUUID {} is not equal to the previous one, existing checksum is {}, new one is {}.", csarUUID, + oldResource.getComponentMetadataDefinition().getMetadataDataDefinition() + .getImportedToscaChecksum(), + checksum); + oldResource.getComponentMetadataDefinition().getMetadataDataDefinition() + .setImportedToscaChecksum(checksum); + } + + return new CsarInfo(user, csarUUID, csar, service.getName(), + toscaYamlCsarStatus.getKey(), toscaYamlCsarStatus.getValue(), true); + } + + public ParsedToscaYamlInfo getParsedToscaYamlInfo(String topologyTemplateYaml, String yamlName, Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, String nodeName, Component component) { return yamlHandler.parseResourceInfoFromYAML( yamlName, topologyTemplateYaml, csarInfo.getCreatedNodesToscaResourceNames(), nodeTypesInfo, - nodeName); + nodeName, component); } private String logAndThrowComponentException(ResponseFormat responseFormat, String logMessage, String ...params) { @@ -136,9 +175,9 @@ public class CsarBusinessLogic extends BaseBusinessLogic { throw new ByResponseFormatComponentException(responseFormat); } - private Either<ImmutablePair<String, String>, ResponseFormat> validateAndParseCsar(Resource resource, User user, + private Either<ImmutablePair<String, String>, ResponseFormat> validateAndParseCsar(Component component, User user, Map<String, byte[]> payload, String csarUUID) { - Map<String, byte[]> csar = getCsar(resource, user, payload, csarUUID); + Map<String, byte[]> csar = getCsar(component, user, payload, csarUUID); Either<Boolean, ResponseFormat> validateCsarStatus = CsarValidationUtils.validateCsar(csar, csarUUID, componentsUtils); if (validateCsarStatus.isRight()) { @@ -146,7 +185,10 @@ public class CsarBusinessLogic extends BaseBusinessLogic { log.debug("Error when validate csar with ID {}, error: {}", csarUUID, responseFormat); BeEcompErrorManager.getInstance() .logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED); - componentsUtils.auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE); + if(component instanceof Resource){ + componentsUtils.auditResource(responseFormat, user, (Resource)component, AuditingActionEnum.CREATE_RESOURCE); + } + return Either.right(responseFormat); } @@ -158,13 +200,15 @@ public class CsarBusinessLogic extends BaseBusinessLogic { log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat); BeEcompErrorManager.getInstance() .logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED); - componentsUtils.auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE); + if(component instanceof Resource) { + componentsUtils.auditResource(responseFormat, user, (Resource)component, AuditingActionEnum.CREATE_RESOURCE); + } return Either.right(responseFormat); } return toscaYamlCsarStatus; } - private Map<String, byte[]> getCsar(Resource resource, User user, Map<String, byte[]> payload, String csarUUID) { + private Map<String, byte[]> getCsar(Component component, User user, Map<String, byte[]> payload, String csarUUID) { if (payload != null) { return payload; } @@ -176,7 +220,11 @@ public class CsarBusinessLogic extends BaseBusinessLogic { .logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED); ResponseFormat responseFormat = componentsUtils .getResponseFormat(componentsUtils.convertFromStorageResponse(value), csarUUID); - componentsUtils.auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE); + if(component instanceof Resource){ + Resource newResource = (Resource) component; + componentsUtils.auditResource(responseFormat, user, newResource, AuditingActionEnum.CREATE_RESOURCE); + } + throw new StorageException(csar.right().value()); } return csar.left().value(); @@ -187,4 +235,44 @@ public class CsarBusinessLogic extends BaseBusinessLogic { componentsUtils.auditResource(errorResponse, user, resource, auditingAction); throw new ByResponseFormatComponentException(errorResponse, params); } + + private Map<String, byte[]> getCsar(User user, Map<String, byte[]> payload, String csarUUID) { + if (payload != null) { + return payload; + } + Either<Map<String, byte[]>, StorageOperationStatus> csar = csarOperation.getCsar(csarUUID, user); + if (csar.isRight()) { + StorageOperationStatus value = csar.right().value(); + log.debug("#getCsar - failed to fetch csar with ID {}, error: {}", csarUUID, value); + throw new StorageException(value); + } + return csar.left().value(); + } + + private Either<ImmutablePair<String, String>, ResponseFormat> validateAndParseCsar(Service service, User user, + Map<String, byte[]> payload, String csarUUID) { + Map<String, byte[]> csar = getCsar(service, user, payload, csarUUID); + Either<Boolean, ResponseFormat> validateCsarStatus = CsarValidationUtils.validateCsar(csar, + csarUUID, componentsUtils); + if (validateCsarStatus.isRight()) { + ResponseFormat responseFormat = validateCsarStatus.right().value(); + log.debug("Error when validate csar with ID {}, error: {}", csarUUID, responseFormat); + BeEcompErrorManager.getInstance() + .logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED); + + return Either.right(responseFormat); + } + + Either<ImmutablePair<String, String>, ResponseFormat> toscaYamlCsarStatus = CsarValidationUtils + .getToscaYaml(csar, csarUUID, componentsUtils); + + if (toscaYamlCsarStatus.isRight()) { + ResponseFormat responseFormat = toscaYamlCsarStatus.right().value(); + log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat); + BeEcompErrorManager.getInstance() + .logBeDaoSystemError(CREATING_RESOURCE_FROM_CSAR_FETCHING_CSAR_WITH_ID + csarUUID + FAILED); + return Either.right(responseFormat); + } + return toscaYamlCsarStatus; + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java index 41dc3a6db3..9636885190 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java @@ -54,6 +54,7 @@ import org.openecomp.sdc.be.model.NodeTypeInfo; import org.openecomp.sdc.be.model.ParsedToscaYamlInfo; import org.openecomp.sdc.be.model.PolicyDefinition; import org.openecomp.sdc.be.model.PolicyTypeDefinition; +import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.UploadArtifactInfo; import org.openecomp.sdc.be.model.UploadCapInfo; import org.openecomp.sdc.be.model.UploadComponentInstanceInfo; @@ -129,7 +130,7 @@ public class YamlTemplateParsingHandler { } public ParsedToscaYamlInfo parseResourceInfoFromYAML(String fileName, String resourceYml, Map<String, String> createdNodesToscaResourceNames, - Map<String, NodeTypeInfo> nodeTypesInfo, String nodeName) { + Map<String, NodeTypeInfo> nodeTypesInfo, String nodeName, org.openecomp.sdc.be.model.Component component) { log.debug("#parseResourceInfoFromYAML - Going to parse yaml {} ", fileName); Map<String, Object> mappedToscaTemplate = getMappedToscaTemplate(fileName, resourceYml, nodeTypesInfo, nodeName); ParsedToscaYamlInfo parsedToscaYamlInfo = new ParsedToscaYamlInfo(); @@ -140,7 +141,9 @@ public class YamlTemplateParsingHandler { parsedToscaYamlInfo.setInputs(getInputs(mappedToscaTemplate)); parsedToscaYamlInfo.setInstances(getInstances(fileName, mappedToscaTemplate, createdNodesToscaResourceNames)); parsedToscaYamlInfo.setGroups(getGroups(fileName, mappedToscaTemplate)); - parsedToscaYamlInfo.setPolicies(getPolicies(fileName, mappedToscaTemplate)); + if(component instanceof Resource){ + parsedToscaYamlInfo.setPolicies(getPolicies(fileName, mappedToscaTemplate)); + } log.debug("#parseResourceInfoFromYAML - The yaml {} has been parsed ", fileName); return parsedToscaYamlInfo; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/AbstractTemplateBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/AbstractTemplateBusinessLogic.java new file mode 100644 index 0000000000..95422f4cfc --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/AbstractTemplateBusinessLogic.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2020 CMCC, Inc. and others. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.components.impl; + +import fj.data.Either; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.openecomp.sdc.be.components.validation.ServiceDistributionValidation; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; +import org.openecomp.sdc.be.externalapi.servlet.representation.AbstractResourceInfo; +import org.openecomp.sdc.be.externalapi.servlet.representation.AbstractTemplateInfo; +import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.category.CategoryDefinition; +import org.openecomp.sdc.be.model.category.SubCategoryDefinition; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; +import org.openecomp.sdc.be.model.operations.api.*; +import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; +import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; +import org.openecomp.sdc.common.log.wrappers.Logger; +import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@org.springframework.stereotype.Component("abstractTemplateBusinessLogic") +public class AbstractTemplateBusinessLogic extends BaseBusinessLogic { + + private static final String INITIAL_VERSION = "0.1"; + + private static final Logger log = Logger.getLogger(AbstractTemplateBusinessLogic.class); + + @Autowired + ServiceDistributionValidation serviceDistributionValidation; + + @Autowired + protected ServiceImportManager serviceImportManager; + + @Autowired + protected ServiceBusinessLogic serviceBusinessLogic; + + @Autowired + public AbstractTemplateBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, + IGroupInstanceOperation groupInstanceOperation, IGroupTypeOperation groupTypeOperation, + InterfaceOperation interfaceOperation, + InterfaceLifecycleOperation interfaceLifecycleTypeOperation, ArtifactsOperations artifactToscaOperation) { + super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, + interfaceOperation, interfaceLifecycleTypeOperation, artifactToscaOperation); + } + + public Either<AbstractTemplateInfo, ResponseFormat> getServiceAbstractStatus(List<? extends Component> componentList) { + AbstractTemplateInfo abstractTemplateInfo = new AbstractTemplateInfo(); + if (componentList == null || componentList.isEmpty()) { + return Either.left(abstractTemplateInfo); + } + + for (Component curr : componentList) { + Service service = (Service) curr; + List<ComponentInstance> componentInstances = service.getComponentInstances(); + List<RequirementCapabilityRelDef> componentInstancesRelations = service.getComponentInstancesRelations(); + abstractTemplateInfo.setServiceUniqueId(service.getUniqueId()); + String serviceUniqueId = abstractTemplateInfo.getServiceUniqueId(); + Either<Boolean, ResponseFormat> isAbstractResourceData = getEveryServiceAbstractStatus(componentInstances, abstractTemplateInfo, componentInstancesRelations, serviceUniqueId); + if (isAbstractResourceData.isRight()) { + return Either.right(isAbstractResourceData.right().value()); + } + } + + return Either.left(abstractTemplateInfo); + } + + private Either<Boolean, ResponseFormat> getEveryServiceAbstractStatus(List<ComponentInstance> componentInstances, AbstractTemplateInfo abstractTemplateInfo, + List<RequirementCapabilityRelDef> componentInstancesRelations, String serviceUniqueId) { + Map<String, ImmutablePair<String, String>> uuidDuplicatesMap = new HashMap<>(); + List<AbstractResourceInfo> abstractResourceInfoList = new ArrayList<>(); + Boolean isContainAbstractResource = false; + + for (ComponentInstance componentInstance : componentInstances) { + String componentUid = componentInstance.getComponentUid(); + String invariantUUID, resourceUUID; + if (!uuidDuplicatesMap.containsKey(componentUid)) { + Either<Resource, StorageOperationStatus> eitherResource = toscaOperationFacade + .getToscaElement(componentInstance.getComponentUid()); + if (eitherResource.isRight()) { + log.debug("getEveryServiceAbstractStatus: Failed getting resource with UUid: {}", + componentInstance.getComponentUid()); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(eitherResource.right().value()); + return Either.right(responseFormat); + } else { + final Resource resource = eitherResource.left().value(); + invariantUUID = resource.getInvariantUUID(); + resourceUUID = resource.getUUID(); + ImmutablePair<String, String> uuidInvariantUUIDPair = new ImmutablePair<>(resourceUUID, + invariantUUID); + uuidDuplicatesMap.put(componentUid, uuidInvariantUUIDPair); + + Either<List<AbstractResourceInfo>, ResponseFormat> abstractResourceEither = getAbstractResourceInfoList(resource, componentInstancesRelations, serviceUniqueId); + if (abstractResourceEither.isRight()) { + return Either.right(abstractResourceEither.right().value()); + } + abstractResourceInfoList = abstractResourceEither.left().value(); + isContainAbstractResource = true; + } + } + } + abstractTemplateInfo.setIsAbstractTemplate(isContainAbstractResource); + abstractTemplateInfo.setAbstractResourceInfoList(abstractResourceInfoList); + return Either.left(isContainAbstractResource); + } + + private Either<List<AbstractResourceInfo>, ResponseFormat> getAbstractResourceInfoList(Resource resource, List<RequirementCapabilityRelDef> componentInstancesRelations, String serviceUniqueId) { + List<AbstractResourceInfo> abstractResourceInfoList = new ArrayList<>(); + boolean isAbstract = getIsAbstract(resource.getCategories()); + log.debug("before if isAbstract,get resource:{}", resource); + if (!isAbstract) { + log.debug("getAbstractResourceInfoList:Resource is not Abstract"); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(JanusGraphOperationStatus.NOT_FOUND)); + return Either.right(responseFormat); + } + log.debug("getAbstractResourceInfoList:Resource is Abstract"); + + AbstractResourceInfo abstractResourceInfo = getAbstractResourceInfo(resource, componentInstancesRelations, serviceUniqueId); + abstractResourceInfoList.add(abstractResourceInfo); + return Either.left(abstractResourceInfoList); + } + + private AbstractResourceInfo getAbstractResourceInfo(Resource resource,List<RequirementCapabilityRelDef> componentInstancesRelations,String serviceUniqueId){ + AbstractResourceInfo abstractResourceInfo = new AbstractResourceInfo(); + abstractResourceInfo.setAbstractResourceUUid(resource.getUUID()); + abstractResourceInfo.setAbstractResourceName(resource.getName()); + abstractResourceInfo.setAbstractResourceUniqueId(resource.getUniqueId()); + String uniqueId = serviceUniqueId + "." + resource.getUniqueId() + "." + resource.getNormalizedName(); + + List<RequirementCapabilityRelDef> resourceComponentInstancesRelations = new ArrayList<>(); + log.debug("get serviceUniqueId:{},get UniqueId:{},get NormalizedName:{}", + serviceUniqueId, resource.getUniqueId(), resource.getNormalizedName()); + log.debug("get is Abstract,componentInstancesRelations:{}", componentInstancesRelations); + for (RequirementCapabilityRelDef componentInstancesRelation : componentInstancesRelations) { + log.debug("for componentInstancesRelation,get componentInstancesRelation:{}", componentInstancesRelation); + String fromNode = componentInstancesRelation.getFromNode(); + log.debug("for componentInstancesRelation,get fromNode:{},uniqueId:{}", fromNode,uniqueId); + if (fromNode.toUpperCase().contains(uniqueId.toUpperCase())) { + RequirementCapabilityRelDef resourceComponentInstancesRelation = new RequirementCapabilityRelDef(); + log.debug("fromNode contains name,get componentInstancesRelation:{}", componentInstancesRelation); + resourceComponentInstancesRelation.setFromNode(componentInstancesRelation.getFromNode()); + resourceComponentInstancesRelation.setOriginUI(componentInstancesRelation.isOriginUI()); + resourceComponentInstancesRelation.setRelationships(componentInstancesRelation.getRelationships()); + resourceComponentInstancesRelation.setToNode(componentInstancesRelation.getToNode()); + resourceComponentInstancesRelation.setUid(componentInstancesRelation.getUid()); + resourceComponentInstancesRelations.add(resourceComponentInstancesRelation); + } + } + abstractResourceInfo.setComponentInstancesRelations(resourceComponentInstancesRelations); + return abstractResourceInfo; + } + + private boolean getIsAbstract(List<CategoryDefinition> categories) { + boolean anAbstract = false; + if (categories != null && !categories.isEmpty()) { + CategoryDefinition categoryDef = categories.get(0); + if (categoryDef != null && categoryDef.getName() != null && categoryDef.getName() + .equals(ImportUtils.Constants.ABSTRACT_CATEGORY_NAME)) { + SubCategoryDefinition subCategoryDef = categoryDef.getSubcategories().get(0); + if (subCategoryDef != null && subCategoryDef.getName().equals(ImportUtils.Constants.ABSTRACT_SUBCATEGORY)) { + anAbstract = true; + } + } + } + return anAbstract; + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java index cac36cbe0e..c9e0a44999 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogic.java @@ -4491,7 +4491,7 @@ public class ArtifactsBusinessLogic extends BaseBusinessLogic { return uploadedArtifacts; } - public Either<ArtifactDefinition, Operation> handleLoadedArtifact(Resource component, User user, ArtifactOperationInfo operation, boolean shouldLock, boolean inTransaction, + public Either<ArtifactDefinition, Operation> handleLoadedArtifact(Component component, User user, ArtifactOperationInfo operation, boolean shouldLock, boolean inTransaction, ComponentTypeEnum componentType, ArtifactDefinition artifactDefinition) { AuditingActionEnum auditingAction = detectAuditingType(operation, ""); String componentId = component.getUniqueId(); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java index ba1500c9be..34236eb644 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java @@ -296,6 +296,39 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { return Either.left(result); } + protected void validateIcon(User user, Component component, AuditingActionEnum actionEnum) { + log.debug("validate Icon"); + ComponentTypeEnum type = component.getComponentType(); + String icon = component.getIcon(); + if (!ValidationUtils.validateStringNotEmpty(icon)) { + log.info("icon is missing."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_ICON, type.getValue()); + componentsUtils.auditComponentAdmin(errorResponse, user, component, actionEnum, type); + throw new ComponentException(ActionStatus.COMPONENT_MISSING_ICON, type.getValue()); + } + try { + validateIcon(icon, type); + } catch(ComponentException e){ + ResponseFormat responseFormat = e.getResponseFormat() != null ? e.getResponseFormat() + : componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams()); + componentsUtils.auditComponentAdmin(responseFormat, user, component, actionEnum, type); + throw e; + } + } + + private void validateIcon(String icon, ComponentTypeEnum type) { + if (icon != null) { + if (!ValidationUtils.validateIconLength(icon)) { + log.debug("icon exceeds max length"); + throw new ComponentException(ActionStatus.COMPONENT_ICON_EXCEEDS_LIMIT, type.getValue(), "" + ValidationUtils.ICON_MAX_LENGTH); + } + + if (!ValidationUtils.validateIcon(icon)) { + log.info("icon is invalid."); + throw new ComponentException(ActionStatus.COMPONENT_INVALID_ICON, type.getValue()); + } + } + } protected void checkComponentFieldsForOverrideAttempt(Component component) { if (component.getLifecycleState() != null) { @@ -331,6 +364,24 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { } } + protected void validateComponentFieldsBeforeCreate(User user, Component component, AuditingActionEnum actionEnum) { + // validate component name uniqueness + log.debug("validate component name "); + componentNameValidator.validateAndCorrectField(user, component, actionEnum); + // validate description + log.debug("validate description"); + componentDescriptionValidator.validateAndCorrectField(user, component, actionEnum); + // validate tags + log.debug("validate tags"); + componentTagsValidator.validateAndCorrectField(user, component, actionEnum); + // validate contact info + log.debug("validate contact info"); + componentContactIdValidator.validateAndCorrectField(user, component, actionEnum); + // validate icon + log.debug("validate icon"); + validateIcon(user, component, actionEnum); + } + public CapReqDef getRequirementsAndCapabilities(String componentId, ComponentTypeEnum componentTypeEnum, String userId) { validateUserExists(userId); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java index e7d8dd56f5..ffccc978db 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java @@ -421,6 +421,138 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } } + /** + * Try using either to make a judgment + * @param containerComponentParam + * @param containerComponentId + * @param userId + * @param resourceInstance + * @return + */ + + public Either<ComponentInstance, ResponseFormat> createRealComponentInstance(String containerComponentParam, String containerComponentId, String userId, ComponentInstance resourceInstance) { + log.debug("enter createRealComponentInstance"); + return createRealComponentInstance(containerComponentParam, containerComponentId, userId, resourceInstance, false, true); + } + /** + * Try using either to make a judgment + * + * @param inTransaction + * @param needLock + * @param containerComponentParam + * @param containerComponentId + * @param userId + * @param resourceInstance + * @return + */ + public Either<ComponentInstance, ResponseFormat> createRealComponentInstance(String containerComponentParam, String containerComponentId, String userId, ComponentInstance resourceInstance, boolean inTransaction, boolean needLock) { + + log.debug("enter createRealComponentInstance"); + Component origComponent = null; + User user; + org.openecomp.sdc.be.model.Component containerComponent = null; + ComponentTypeEnum containerComponentType; + try { + user = validateUserExists(userId); + validateUserNotEmpty(user, "Create component instance"); + validateJsonBody(resourceInstance, ComponentInstance.class); + containerComponentType = validateComponentType(containerComponentParam); + containerComponent = validateComponentExists(containerComponentId, containerComponentType, null); + + log.debug("enter createRealComponentInstance,validate user json success"); + if (ModelConverter.isAtomicComponent(containerComponent)) { + log.debug("Cannot attach resource instances to container resource of type {}", containerComponent.assetType()); + throw new ByActionStatusComponentException(ActionStatus.RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES, containerComponent.assetType()); + } + + validateCanWorkOnComponent(containerComponent, userId); + log.debug("enter createRealComponentInstance,validateCanWorkOnComponent success"); + + if (resourceInstance != null && containerComponentType != null) { + log.debug("enter createRealComponentInstance,start create ComponentInstance"); + OriginTypeEnum originType = resourceInstance.getOriginType(); + validateInstanceName(resourceInstance); + if (originType == OriginTypeEnum.ServiceProxy) { + + log.debug("enter createRealComponentInstance,originType equals ServiceProxy"); + Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade.getLatestByName("serviceProxy"); + if (isServiceProxyOrigin(serviceProxyOrigin)) { + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value())); + } + origComponent = serviceProxyOrigin.left().value(); + + StorageOperationStatus fillProxyRes = fillInstanceData(resourceInstance, origComponent); + if (isFillProxyRes(fillProxyRes)) { + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(fillProxyRes)); + } + } else { + log.debug("enter createRealComponentInstance,originType is not ServiceProxy"); + origComponent = getAndValidateOriginComponentOfComponentInstance(containerComponent, resourceInstance); + } + validateOriginAndResourceInstanceTypes(containerComponent, origComponent, originType); + validateResourceInstanceState(containerComponent, origComponent); + overrideFields(origComponent, resourceInstance); + compositionBusinessLogic.validateAndSetDefaultCoordinates(resourceInstance); + log.debug("enter createRealComponentInstance,final validate success"); + } + return createRealComponent(needLock, containerComponent, origComponent, resourceInstance, user); + + } catch (ComponentException e) { + log.debug("create Real Component Instance failed"); + throw e; + } + } + + private Either<ComponentInstance, ResponseFormat> createRealComponent(boolean needLock, Component containerComponent, Component origComponent, ComponentInstance resourceInstance, User user) { + + log.debug("enter createRealComponent"); + boolean failed = false; + try { + + ComponentInstance lockComponent = isNeedLock(needLock, containerComponent); + if (lockComponent != null) { + return Either.left(lockComponent); + } + log.debug(TRY_TO_CREATE_ENTRY_ON_GRAPH); + return createRealComponentInstanceOnGraph(containerComponent, origComponent, resourceInstance, user); + } catch (ComponentException e) { + failed = true; + throw e; + } finally { + if (needLock) + unlockComponent(failed, containerComponent); + } + } + + private Either<ComponentInstance, ResponseFormat> createRealComponentInstanceOnGraph(org.openecomp.sdc.be.model.Component containerComponent, Component originComponent, ComponentInstance componentInstance, User user) { + Either<ComponentInstance, ResponseFormat> resultOp; + log.debug("enter createRealComponentInstanceOnGraph"); + + Either<ImmutablePair<Component, String>, StorageOperationStatus> result = toscaOperationFacade.addComponentInstanceToTopologyTemplate(containerComponent, originComponent, componentInstance, false, user); + + if (result.isRight()) { + log.debug("enter createRealComponentInstanceOnGraph,result is right"); + ActionStatus status = componentsUtils.convertFromStorageResponse(result.right().value()); + log.debug(FAILED_TO_CREATE_ENTRY_ON_GRAPH_FOR_COMPONENT_INSTANCE, componentInstance.getName()); + return Either.right(componentsUtils.getResponseFormat(status)); + } + + log.debug(ENTITY_ON_GRAPH_IS_CREATED); + log.debug("enter createRealComponentInstanceOnGraph,Entity on graph is created."); + Component updatedComponent = result.left().value().getLeft(); + Map<String, String> existingEnvVersions = new HashMap<>(); + // TODO existingEnvVersions ?? + addComponentInstanceArtifacts(updatedComponent, componentInstance, originComponent, user, existingEnvVersions); + + Optional<ComponentInstance> updatedInstanceOptional = updatedComponent.getComponentInstances().stream().filter(ci -> ci.getUniqueId().equals(result.left().value().getRight())).findFirst(); + if (!updatedInstanceOptional.isPresent()) { + log.debug("Failed to fetch new added component instance {} from component {}", componentInstance.getName(), containerComponent.getName()); + throw new ByActionStatusComponentException(ActionStatus.COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, componentInstance.getName()); + } + log.debug("enter createRealComponentInstanceOnGraph,and final success"); + return Either.left(updatedInstanceOptional.get()); + } + private void overrideFields(Component origComponent, ComponentInstance resourceInstance) { resourceInstance.setComponentVersion(origComponent.getVersion()); resourceInstance.setIcon(origComponent.getIcon()); @@ -1158,6 +1290,67 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } return componentInstance; } + + /** + * Try to modify the delete and return two cases + * + * @param containerComponentParam + * @param containerComponentId + * @param componentInstanceId + * @param userId + * @return + */ + public Either<ComponentInstance, ResponseFormat> deleteAbstractComponentInstance(String containerComponentParam, String containerComponentId, String componentInstanceId, String userId) { + log.debug("enter deleteAbstractComponentInstance"); + validateUserExists(userId); + + final ComponentTypeEnum containerComponentType = validateComponentType(containerComponentParam); + + org.openecomp.sdc.be.model.Component containerComponent = validateComponentExists(containerComponentId, containerComponentType, null); + validateCanWorkOnComponent(containerComponent, userId); + + boolean failed = false; + ComponentInstance deletedRelatedInst; + try { + if (containerComponent instanceof Service) { + ComponentInstance componentInstance = containerComponent.getComponentInstanceById(componentInstanceId).get(); + Either<String, StorageOperationStatus> deleteServiceFilterEither = + nodeFilterOperation.deleteNodeFilter((Service) containerComponent, componentInstanceId); + if (deleteServiceFilterEither.isRight()) { + log.debug("enter deleteAbstractComponentInstance:deleteServiceFilterEither is right, filed"); + ActionStatus status = componentsUtils.convertFromStorageResponse(deleteServiceFilterEither.right().value(), + containerComponentType); + janusGraphDao.rollback(); + return Either.right(componentsUtils.getResponseFormat(status, componentInstance.getName())); + } + Either<ComponentInstance, ResponseFormat> resultOp = deleteNodeFiltersFromComponentInstance((Service) containerComponent, + componentInstance, ComponentTypeEnum.SERVICE, userId); + if (resultOp.isRight()) { + log.debug("enter deleteAbstractComponentInstance:resultOp is right, filed"); + janusGraphDao.rollback(); + return resultOp; + } + } + log.debug("enter deleteAbstractComponentInstance:"); + lockComponent(containerComponent, "deleteComponentInstance"); + ComponentInstance deletedCompInstance = deleteComponentInstance(containerComponent, componentInstanceId, containerComponentType); + + deletedRelatedInst = deleteForwardingPathsRelatedTobeDeletedComponentInstance(containerComponentId, + containerComponentType, deletedCompInstance); + ActionStatus onDeleteOperationsStatus = onChangeInstanceOperationOrchestrator.doOnDeleteInstanceOperations(containerComponent, componentInstanceId); + log.debug("enter deleteAbstractComponentInstance,get onDeleteOperationsStatus:{}",onDeleteOperationsStatus); + if (ActionStatus.OK != onDeleteOperationsStatus) { + throw new ByActionStatusComponentException(onDeleteOperationsStatus); + } + } catch (ComponentException e) { + failed = true; + throw e; + } finally { + unlockComponent(failed, containerComponent); + } + log.debug("enter deleteAbstractComponentInstance,deleted RelatedInst success"); + return Either.left(deletedRelatedInst); + } public Either<ComponentInstance, ResponseFormat> deleteNodeFiltersFromComponentInstance( final Component component, diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CompositionBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CompositionBusinessLogic.java index 0790c4b8bf..20e796e1fa 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CompositionBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CompositionBusinessLogic.java @@ -29,6 +29,7 @@ import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum; import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -83,6 +84,20 @@ public class CompositionBusinessLogic { userId, resource.getComponentInstances(), false); } } + + protected void setPositionsForComponentInstances(Service service, String userId) { + boolean isNotAllPositionsCalculated = service.getComponentInstances() == null + || service.getComponentInstances().stream().anyMatch(p -> (p.getPosX() == null || p.getPosX().isEmpty()) || (p.getPosY() == null || p.getPosY().isEmpty())); + if (isNotAllPositionsCalculated && service.getComponentInstances() != null) { + // Arrange Icons In Spiral Pattern + Map<ImmutablePair<Double, Double>, ComponentInstance> componentInstanceLocations = buildSpiralPatternPositioningForComponentInstances(service); + // Set Relative Locations According to Canvas Size + componentInstanceLocations.entrySet().forEach(this::setRelativePosition); + // Update in DB + componentInstanceBusinessLogic.updateComponentInstance(ComponentTypeEnum.SERVICE_PARAM_NAME, service, service.getUniqueId(), + userId, service.getComponentInstances(), false); + } + } private void setRelativePosition(Entry<ImmutablePair<Double, Double>, ComponentInstance> entry) { int xCenter = CANVAS_WIDTH / 2; @@ -120,13 +135,23 @@ public class CompositionBusinessLogic { return String.valueOf(offsetedCanvasPosition); } - protected Map<ImmutablePair<Double, Double>, ComponentInstance> buildSpiralPatternPositioningForComponentInstances(Resource resource) { + protected Map<ImmutablePair<Double, Double>, ComponentInstance> buildSpiralPatternPositioningForComponentInstances( + org.openecomp.sdc.be.model.Component component) { Map<ImmutablePair<Double, Double>, ComponentInstance> componentInstanceLocations = new HashMap<>(); List<ComponentInstance> componentInstances = new ArrayList<>(); - componentInstances.addAll(resource.getComponentInstances()); - Map<ComponentInstance, List<ComponentInstance>> connectededCps = getCpsConnectedToVFC(componentInstances, resource); + if (component instanceof Resource){ + Resource resource = (Resource) component; + List<ComponentInstance> componentInstanceList = resource.getComponentInstances(); + componentInstances.addAll(componentInstanceList); + }else if (component instanceof Service){ + Service service = (Service) component; + List<ComponentInstance> componentInstanceList = service.getComponentInstances(); + componentInstances.addAll(componentInstanceList); + } + + Map<ComponentInstance, List<ComponentInstance>> connectededCps = getCpsConnectedToVFC(componentInstances, component); // Remove all cp that are connected from the list componentInstances.removeAll(connectededCps.values().stream().flatMap(Collection::stream).collect(Collectors.toList())); @@ -186,9 +211,17 @@ public class CompositionBusinessLogic { } } - protected Map<ComponentInstance, List<ComponentInstance>> getCpsConnectedToVFC(List<ComponentInstance> allComponentInstances, Resource vf) { + protected Map<ComponentInstance, List<ComponentInstance>> getCpsConnectedToVFC(List<ComponentInstance> allComponentInstances, org.openecomp.sdc.be.model.Component component) { Map<ComponentInstance, List<ComponentInstance>> vfcWithItsCps = new HashMap<>(); - List<RequirementCapabilityRelDef> allRelations = vf.getComponentInstancesRelations(); + List<RequirementCapabilityRelDef> allRelations = new ArrayList<>(); + if (component instanceof Resource){ + Resource vf = (Resource) component; + allRelations = vf.getComponentInstancesRelations(); + }else if (component instanceof Service){ + Service sv = (Service) component; + allRelations = sv.getComponentInstancesRelations(); + } + for (ComponentInstance curr : allComponentInstances) { // Filters Only CPs if (curr.getOriginType() == OriginTypeEnum.CP) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java index 4db44d3a76..f04eca1744 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ImportUtils.java @@ -182,6 +182,7 @@ public final class ImportUtils { public static final String CVFC_DESCRIPTION = "Complex node type that is used as nested type in VF"; public static final String ESCAPED_DOUBLE_QUOTE = "\""; public static final String QUOTE = "'"; + public static final String VF_DESCRIPTION = "Nested VF in service"; private Constants() { } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java index ffac13bdb5..50b2941f1b 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java @@ -603,7 +603,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { ParsedToscaYamlInfo uploadComponentInstanceInfoMap; try { uploadComponentInstanceInfoMap = csarBusinessLogic.getParsedToscaYamlInfo(yamlFileContent, yamlFileName, - nodeTypesInfo, csarInfo, nodeName); + nodeTypesInfo, csarInfo, nodeName, oldResource); Map<String, UploadComponentInstanceInfo> instances = uploadComponentInstanceInfoMap.getInstances(); if (MapUtils.isEmpty(instances) && newResource.getResourceType() != ResourceTypeEnum.PNF) { throw new ByActionStatusComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlFileName); @@ -1193,7 +1193,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { List<ArtifactDefinition> createdArtifacts = new ArrayList<>(); Resource createdResource; try { - ParsedToscaYamlInfo parsedToscaYamlInfo = csarBusinessLogic.getParsedToscaYamlInfo(topologyTemplateYaml, yamlName, nodeTypesInfo, csarInfo, nodeName); + ParsedToscaYamlInfo parsedToscaYamlInfo = csarBusinessLogic.getParsedToscaYamlInfo(topologyTemplateYaml, yamlName, nodeTypesInfo, csarInfo, nodeName, resource); if (MapUtils.isEmpty(parsedToscaYamlInfo.getInstances()) && resource.getResourceType() != ResourceTypeEnum.PNF) { throw new ByActionStatusComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); } @@ -2317,9 +2317,15 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { createArtifactsFromCsar = csarArtifactsAndGroupsBusinessLogic.createResourceArtifactsFromCsar( csarInfo, resource, artifactsContents, artifactsFileName, createdArtifacts); } else { - createArtifactsFromCsar = csarArtifactsAndGroupsBusinessLogic.updateResourceArtifactsFromCsar( + Either<Component, ResponseFormat> result = csarArtifactsAndGroupsBusinessLogic.updateResourceArtifactsFromCsar( csarInfo, resource, artifactsContents, artifactsFileName, createdArtifacts, shouldLock, inTransaction); + if ((result.left().value() instanceof Resource) && result.isLeft()) { + Resource service1 = (Resource) result.left().value(); + createArtifactsFromCsar = Either.left(service1); + } else { + createArtifactsFromCsar = Either.right(result.right().value()); + } } if (createArtifactsFromCsar.isRight()) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java index dbcaee4d30..4e6628c8dd 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceImportManager.java @@ -128,6 +128,16 @@ public class ResourceImportManager { private AuditingManager auditingManager; private ResourceBusinessLogic resourceBusinessLogic; + public ServiceBusinessLogic getServiceBusinessLogic() { + return serviceBusinessLogic; + } + + public void setServiceBusinessLogic(ServiceBusinessLogic serviceBusinessLogic) { + this.serviceBusinessLogic = serviceBusinessLogic; + } + + @Autowired + private ServiceBusinessLogic serviceBusinessLogic; private InterfaceOperationBusinessLogic interfaceOperationBusinessLogic; private IGraphLockOperation graphLockOperation; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java index 552fbb0b16..a38ffe9ee0 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java @@ -179,6 +179,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { private static final String STATUS_SUCCESS_200 = "200"; private static final String STATUS_DEPLOYED = "DEPLOYED"; static final String IS_VALID = "isValid"; + private static final String PLACE_HOLDER_RESOURCE_TYPES = "validForResourceTypes"; private ForwardingPathOperation forwardingPathOperation; private AuditCassandraDao auditCassandraDao; @@ -2271,12 +2272,51 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { @Override public void setDeploymentArtifactsPlaceHolder(Component component, User user) { - Service service = (Service) component; - Map<String, ArtifactDefinition> artifactMap = service.getDeploymentArtifacts(); - if (artifactMap == null) { - artifactMap = new HashMap<>(); + if(component instanceof Service){ + Service service = (Service) component; + Map<String, ArtifactDefinition> artifactMap = service.getDeploymentArtifacts(); + if (artifactMap == null) { + artifactMap = new HashMap<>(); + } + service.setDeploymentArtifacts(artifactMap); + }else if(component instanceof Resource){ + Resource resource = (Resource) component; + Map<String, ArtifactDefinition> artifactMap = resource.getDeploymentArtifacts(); + if (artifactMap == null) { + artifactMap = new HashMap<>(); + } + Map<String, Object> deploymentResourceArtifacts = ConfigurationManager.getConfigurationManager() + .getConfiguration().getDeploymentResourceArtifacts(); + if (deploymentResourceArtifacts != null) { + Map<String, ArtifactDefinition> finalArtifactMap = artifactMap; + deploymentResourceArtifacts.forEach((k, v)->processDeploymentResourceArtifacts(user, resource, finalArtifactMap, k,v)); + } + resource.setDeploymentArtifacts(artifactMap); + } + + } + + private void processDeploymentResourceArtifacts(User user, Resource resource, Map<String, ArtifactDefinition> artifactMap, String k, Object v) { + Map<String, Object> artifactDetails = (Map<String, Object>) v; + Object object = artifactDetails.get(PLACE_HOLDER_RESOURCE_TYPES); + if (object != null) { + List<String> artifactTypes = (List<String>) object; + if (!artifactTypes.contains(resource.getResourceType().name())) { + return; + } + } else { + log.info("resource types for artifact placeholder {} were not defined. default is all resources", + k); + } + if (artifactsBusinessLogic != null) { + ArtifactDefinition artifactDefinition = artifactsBusinessLogic.createArtifactPlaceHolderInfo( + resource.getUniqueId(), k, (Map<String, Object>) v, + user, ArtifactGroupTypeEnum.DEPLOYMENT); + if (artifactDefinition != null + && !artifactMap.containsKey(artifactDefinition.getArtifactLabel())) { + artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition); + } } - service.setDeploymentArtifacts(artifactMap); } @Override @@ -2520,4 +2560,9 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { public void setServiceCreationPluginList(List<ServiceCreationPlugin> serviceCreationPluginList) { this.serviceCreationPluginList = serviceCreationPluginList; } + + public boolean isServiceExist(String serviceName) { + Either<Service, StorageOperationStatus> latestByName = toscaOperationFacade.getLatestByServiceName(serviceName); + return latestByName.isLeft(); + } } 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 new file mode 100644 index 0000000000..857c5e32b7 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java @@ -0,0 +1,3141 @@ +/* + * Copyright (C) 2020 CMCC, Inc. and others. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * 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.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 fj.data.Either; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.regex.Pattern; + +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.collections4.ListUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +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.impl.ArtifactsBusinessLogic.ArtifactOperationEnum; +import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo; +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.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.JanusGraphOperationStatus; +import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum; +import org.openecomp.sdc.be.datamodel.utils.ArtifactUtils; +import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter; +import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListCapabilityDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.ListRequirementDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition; +import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition; +import org.openecomp.sdc.be.datatypes.enums.ComponentFieldsEnum; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.CreatedFrom; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +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.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.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.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.NodeTypeInfo; +import org.openecomp.sdc.be.model.Operation; +import org.openecomp.sdc.be.model.ParsedToscaYamlInfo; +import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.RelationshipImpl; +import org.openecomp.sdc.be.model.RelationshipInfo; +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.UploadCapInfo; +import org.openecomp.sdc.be.model.UploadComponentInstanceInfo; +import org.openecomp.sdc.be.model.UploadInfo; +import org.openecomp.sdc.be.model.UploadNodeFilterInfo; +import org.openecomp.sdc.be.model.UploadPropInfo; +import org.openecomp.sdc.be.model.UploadReqInfo; +import org.openecomp.sdc.be.model.UploadResourceInfo; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.category.CategoryDefinition; +import org.openecomp.sdc.be.model.category.SubCategoryDefinition; +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.operations.StorageException; +import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation; +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.IInterfaceLifecycleOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter; +import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; +import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; +import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo; +import org.openecomp.sdc.be.tosca.CsarUtils; +import org.openecomp.sdc.be.utils.CommonBeUtils; +import org.openecomp.sdc.be.utils.TypeUtils; +import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; +import org.openecomp.sdc.common.api.ArtifactTypeEnum; +import org.openecomp.sdc.common.api.Constants; +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.GeneralUtility; +import org.openecomp.sdc.common.util.ValidationUtils; +import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.beans.factory.annotation.Autowired; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; + +@Getter +@Setter +@org.springframework.stereotype.Component("serviceImportBusinessLogic") +public class ServiceImportBusinessLogic{ + + private final UiComponentDataConverter uiComponentDataConverter; + 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 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"; + private static final String VALIDATE_DERIVED_BEFORE_UPDATE = "validate derived before update"; + private static final String PLACE_HOLDER_RESOURCE_TYPES = "validForResourceTypes"; + private static final String CREATE_RESOURCE_VALIDATE_CAPABILITY_TYPES = "Create Resource - validateCapabilityTypesCreate"; + private static final String CATEGORY_IS_EMPTY = "Resource category is empty"; + + + @Autowired + private ServiceBusinessLogic serviceBusinessLogic; + public ServiceBusinessLogic getServiceBusinessLogic() { + return serviceBusinessLogic; + } + + public void setServiceBusinessLogic( + ServiceBusinessLogic serviceBusinessLogic) { + this.serviceBusinessLogic = serviceBusinessLogic; + } + + @Autowired + private CsarBusinessLogic csarBusinessLogic; + @Autowired + protected ComponentsUtils componentsUtils; + @Autowired + protected ToscaOperationFacade toscaOperationFacade; + @Autowired + private CsarArtifactsAndGroupsBusinessLogic csarArtifactsAndGroupsBusinessLogic; + @Autowired + private LifecycleBusinessLogic lifecycleBusinessLogic; + @Autowired + private CompositionBusinessLogic compositionBusinessLogic; + @Autowired + private ResourceDataMergeBusinessLogic resourceDataMergeBusinessLogic; + @Autowired + private ServiceImportParseLogic serviceImportParseLogic; + + private static final Logger log = Logger.getLogger(ServiceImportBusinessLogic.class); + @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; + } + + private final ComponentInstanceBusinessLogic componentInstanceBusinessLogic; + + public Service createService(Service service, AuditingActionEnum auditingAction, User user, Map<String, byte[]> 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); + + try { + serviceBusinessLogic.validateServiceBeforeCreate(service, user, auditingAction); + + log.debug("enter createService,validateServiceBeforeCreate success"); + String csarUUID = payloadName == null ? service.getCsarUUID() : payloadName; + + 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); + //ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected Service createServiceFromCsar(Service service, User user, Map<String, byte[]> csarUIPayload, String csarUUID) { + log.trace("************* created successfully from YAML, resource TOSCA "); + try { + CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID); + + Map<String, NodeTypeInfo> nodeTypesInfo = csarInfo.extractNodeTypesInfo(); + Either<Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>>, 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()); + } + Service cService = createServiceFromYaml(service, csarInfo.getMainTemplateContent(), csarInfo.getMainTemplateName(), + nodeTypesInfo, csarInfo, findNodeTypesArtifactsToHandleRes.left().value(), true, false, + null); + return cService; + }catch (Exception e){ + log.debug("Exception occured when createServiceFromCsar,error is:{}",e.getMessage(),e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected Service createServiceFromYaml(Service service, String topologyTemplateYaml, + String yamlName, Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate, + boolean shouldLock, boolean inTransaction, String nodeName) { + + List<ArtifactDefinition> createdArtifacts = new ArrayList<>(); + Service createdService; + CreateServiceFromYamlParameter csfyp = new CreateServiceFromYamlParameter(); + try { + ParsedToscaYamlInfo + parsedToscaYamlInfo = csarBusinessLogic.getParsedToscaYamlInfo(topologyTemplateYaml, yamlName, nodeTypesInfo, csarInfo, nodeName, service); + if (MapUtils.isEmpty(parsedToscaYamlInfo.getInstances())) { + throw new ComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + } + log.debug("#createResourceFromYaml - Going to create resource {} and RIs ", service.getName()); + csfyp.setYamlName(yamlName); + csfyp.setParsedToscaYamlInfo(parsedToscaYamlInfo); + csfyp.setCreatedArtifacts(createdArtifacts); + csfyp.setTopologyTemplateYaml(topologyTemplateYaml); + csfyp.setNodeTypesInfo(nodeTypesInfo); + csfyp.setCsarInfo(csarInfo); + csfyp.setNodeName(nodeName); + + createdService = createServiceAndRIsFromYaml(service, false, nodeTypesArtifactsToCreate, shouldLock, inTransaction, csfyp); + log.debug("#createResourceFromYaml - The resource {} has been created ", service.getName()); + } catch (ComponentException e) { + log.debug("create Service From Yaml failed,get ComponentException:{}", e); + throw e; + } catch (StorageException e) { + log.debug("create Service From Yaml failed,get StorageException:{}", e); + throw e; + } + return createdService; + } + + protected Service createServiceAndRIsFromYaml(Service service, boolean isNormative, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate, + boolean shouldLock, boolean inTransaction, CreateServiceFromYamlParameter csfyp) { + + List<ArtifactDefinition> nodeTypesNewCreatedArtifacts = new ArrayList<>(); + String yamlName = csfyp.getYamlName(); + ParsedToscaYamlInfo parsedToscaYamlInfo = csfyp.getParsedToscaYamlInfo(); + List<ArtifactDefinition> createdArtifacts = csfyp.getCreatedArtifacts(); + String topologyTemplateYaml = csfyp.getTopologyTemplateYaml(); + Map<String, NodeTypeInfo> nodeTypesInfo = csfyp.getNodeTypesInfo(); + CsarInfo csarInfo = csfyp.getCsarInfo(); + String nodeName = csfyp.getNodeName(); + + if (shouldLock) { + Either<Boolean, ResponseFormat> 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); + } + try { + log.trace("************* createResourceFromYaml before full create resource {}", yamlName); + service = serviceImportParseLogic.createServiceTransaction(service, csarInfo.getModifier(), isNormative); + log.trace("************* Going to add inputs from yaml {}", yamlName); + + Map<String, InputDefinition> inputs = parsedToscaYamlInfo.getInputs(); + service = serviceImportParseLogic.createInputsOnService(service, inputs); + log.trace("************* Finish to add inputs from yaml {}", yamlName); + + Map<String, UploadComponentInstanceInfo> uploadComponentInstanceInfoMap = parsedToscaYamlInfo + .getInstances(); + log.trace("************* Going to create nodes, RI's and Relations from yaml {}", yamlName); + + service = createRIAndRelationsFromYaml(yamlName, service, uploadComponentInstanceInfoMap, + topologyTemplateYaml, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, + nodeTypesArtifactsToCreate, nodeName); + log.trace("************* Finished to create nodes, RI and Relation from yaml {}", yamlName); + Either<Map<String, GroupDefinition>, ResponseFormat> validateUpdateVfGroupNamesRes = serviceBusinessLogic.groupBusinessLogic + .validateUpdateVfGroupNames(parsedToscaYamlInfo.getGroups(), service.getSystemName()); + if (validateUpdateVfGroupNamesRes.isRight()) { + serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw new ComponentException(validateUpdateVfGroupNamesRes.right().value()); + } + Map<String, GroupDefinition> groups; + log.trace("************* Going to add groups from yaml {}", yamlName); + + if (!validateUpdateVfGroupNamesRes.left().value().isEmpty()) { + groups = validateUpdateVfGroupNamesRes.left().value(); + } else { + groups = parsedToscaYamlInfo.getGroups(); + } + + Either<Service, ResponseFormat> createGroupsOnResource = createGroupsOnResource(service, groups); + if (createGroupsOnResource.isRight()) { + serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw new ComponentException(createGroupsOnResource.right().value()); + } + service = createGroupsOnResource.left().value(); + log.trace("************* Going to add artifacts from yaml {}", yamlName); + + NodeTypeInfoToUpdateArtifacts nodeTypeInfoToUpdateArtifacts = new NodeTypeInfoToUpdateArtifacts(nodeName, + nodeTypesArtifactsToCreate); + + Either<Service, ResponseFormat> createArtifactsEither = createOrUpdateArtifacts( + ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE, createdArtifacts, yamlName, + csarInfo, service, nodeTypeInfoToUpdateArtifacts, inTransaction, shouldLock); + if (createArtifactsEither.isRight()) { + serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw new ComponentException(createArtifactsEither.right().value()); + } + service = serviceImportParseLogic.getServiceWithGroups(createArtifactsEither.left().value().getUniqueId()); + ASDCKpiApi.countCreatedResourcesKPI(); + return service; + } catch (ComponentException | StorageException e) { + serviceImportParseLogic.rollback(inTransaction, service, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw e; + } finally { + if (!inTransaction) { + serviceBusinessLogic.janusGraphDao.commit(); + } + if (shouldLock) { + serviceBusinessLogic.graphLockOperation.unlockComponentByName(service.getSystemName(), service.getUniqueId(), + NodeTypeEnum.Resource); + } + } + } + + protected Either<Resource, ResponseFormat> createOrUpdateArtifacts( + ArtifactsBusinessLogic.ArtifactOperationEnum operation, List<ArtifactDefinition> createdArtifacts, + String yamlFileName, CsarInfo csarInfo, Resource preparedResource, + NodeTypeInfoToUpdateArtifacts nodeTypeInfoToUpdateArtifacts, boolean inTransaction, boolean shouldLock) { + + String nodeName = nodeTypeInfoToUpdateArtifacts.getNodeName(); + Resource resource = preparedResource; + + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle = nodeTypeInfoToUpdateArtifacts + .getNodeTypesArtifactsToHandle(); + if (preparedResource.getResourceType() == ResourceTypeEnum.VF) { + if (nodeName != null && nodeTypesArtifactsToHandle.get(nodeName) != null && !nodeTypesArtifactsToHandle.get(nodeName).isEmpty()) { + Either<List<ArtifactDefinition>, ResponseFormat> handleNodeTypeArtifactsRes = + handleNodeTypeArtifacts(preparedResource, nodeTypesArtifactsToHandle.get(nodeName), createdArtifacts, csarInfo.getModifier(), inTransaction, true); + if (handleNodeTypeArtifactsRes.isRight()) { + return Either.right(handleNodeTypeArtifactsRes.right().value()); + } + } + } else { + Either<Resource, ResponseFormat> createdCsarArtifactsEither = handleVfCsarArtifacts(preparedResource, csarInfo, createdArtifacts, + new ArtifactOperationInfo(false, false, operation), shouldLock, inTransaction); + log.trace("************* Finished to add artifacts from yaml {}", yamlFileName); + if (createdCsarArtifactsEither.isRight()) { + return createdCsarArtifactsEither; + } + resource = createdCsarArtifactsEither.left().value(); + } + return Either.left(resource); + } + + protected Either<Resource, ResponseFormat> handleVfCsarArtifacts(Resource resource, CsarInfo csarInfo, + List<ArtifactDefinition> createdArtifacts, ArtifactOperationInfo artifactOperation, boolean shouldLock, + boolean inTransaction) { + if (csarInfo.getCsar() != null) { + createOrUpdateSingleNonMetaArtifactToComstants(resource, csarInfo, artifactOperation, shouldLock, inTransaction); + + Either<Resource, ResponseFormat> eitherCreateResult = createOrUpdateNonMetaArtifacts(csarInfo, resource, + createdArtifacts, shouldLock, inTransaction, artifactOperation); + if (eitherCreateResult.isRight()) { + return Either.right(eitherCreateResult.right().value()); + } + Either<Resource, StorageOperationStatus> eitherGerResource = toscaOperationFacade.getToscaElement(resource.getUniqueId()); + if (eitherGerResource.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(eitherGerResource.right().value()), resource); + return Either.right(responseFormat); + } + resource = eitherGerResource.left().value(); + Either<ImmutablePair<String, String>, ResponseFormat> artifacsMetaCsarStatus = CsarValidationUtils.getArtifactsMeta(csarInfo.getCsar(), csarInfo.getCsarUUID(), componentsUtils); + + if (artifacsMetaCsarStatus.isLeft()) { + return getResourceResponseFormatEither(resource, csarInfo, createdArtifacts, artifactOperation, shouldLock, inTransaction, artifacsMetaCsarStatus); + } else { + return csarArtifactsAndGroupsBusinessLogic.deleteVFModules(resource, csarInfo, shouldLock, inTransaction); + } + } + return Either.left(resource); + } + + protected void createOrUpdateSingleNonMetaArtifactToComstants(Resource resource, CsarInfo csarInfo, ArtifactOperationInfo artifactOperation, boolean shouldLock, boolean inTransaction) { + String vendorLicenseModelId = null; + String vfLicenseModelId = null; + if (artifactOperation.getArtifactOperationEnum() == ArtifactOperationEnum.UPDATE) { + Map<String, ArtifactDefinition> deploymentArtifactsMap = resource.getDeploymentArtifacts(); + if (deploymentArtifactsMap != null && !deploymentArtifactsMap.isEmpty()) { + for (Map.Entry<String, ArtifactDefinition> artifactEntry : deploymentArtifactsMap.entrySet()) { + if (artifactEntry.getValue().getArtifactName().equalsIgnoreCase(Constants.VENDOR_LICENSE_MODEL)) { + vendorLicenseModelId = artifactEntry.getValue().getUniqueId(); + } + if (artifactEntry.getValue().getArtifactName().equalsIgnoreCase(Constants.VF_LICENSE_MODEL)) { + vfLicenseModelId = artifactEntry.getValue().getUniqueId(); + } + } + } + } + createOrUpdateSingleNonMetaArtifact(resource, csarInfo, + CsarUtils.ARTIFACTS_PATH + Constants.VENDOR_LICENSE_MODEL, Constants.VENDOR_LICENSE_MODEL, + ArtifactTypeEnum.VENDOR_LICENSE.getType(), ArtifactGroupTypeEnum.DEPLOYMENT, + Constants.VENDOR_LICENSE_LABEL, Constants.VENDOR_LICENSE_DISPLAY_NAME, + Constants.VENDOR_LICENSE_DESCRIPTION, vendorLicenseModelId, artifactOperation, null, true, shouldLock, + inTransaction); + createOrUpdateSingleNonMetaArtifact(resource, csarInfo, + CsarUtils.ARTIFACTS_PATH + Constants.VF_LICENSE_MODEL, Constants.VF_LICENSE_MODEL, + ArtifactTypeEnum.VF_LICENSE.getType(), ArtifactGroupTypeEnum.DEPLOYMENT, Constants.VF_LICENSE_LABEL, + Constants.VF_LICENSE_DISPLAY_NAME, Constants.VF_LICENSE_DESCRIPTION, vfLicenseModelId, + artifactOperation, null, true, shouldLock, inTransaction); + } + + protected Either<Resource, ResponseFormat> getResourceResponseFormatEither(Resource resource, CsarInfo csarInfo, List<ArtifactDefinition> createdArtifacts, ArtifactOperationInfo artifactOperation, boolean shouldLock, boolean inTransaction, Either<ImmutablePair<String, String>, ResponseFormat> artifacsMetaCsarStatus) { + try { + String artifactsFileName = artifacsMetaCsarStatus.left().value().getKey(); + String artifactsContents = artifacsMetaCsarStatus.left().value().getValue(); + Either<Resource, ResponseFormat> createArtifactsFromCsar; + if (ArtifactOperationEnum.isCreateOrLink(artifactOperation.getArtifactOperationEnum())) { + createArtifactsFromCsar = csarArtifactsAndGroupsBusinessLogic + .createResourceArtifactsFromCsar(csarInfo, resource, artifactsContents, artifactsFileName, + createdArtifacts); + } else { + Either<Component, ResponseFormat> result = csarArtifactsAndGroupsBusinessLogic + .updateResourceArtifactsFromCsar(csarInfo, resource, artifactsContents, artifactsFileName, + createdArtifacts, shouldLock, inTransaction); + if ((result.left().value() instanceof Resource) && result.isLeft()) { + Resource service1 = (Resource) result.left().value(); + createArtifactsFromCsar = Either.left(service1); + } else { + createArtifactsFromCsar = Either.right(result.right().value()); + } + } + if (createArtifactsFromCsar.isRight()) { + log.debug("Couldn't create artifacts from artifacts.meta"); + return Either.right(createArtifactsFromCsar.right().value()); + } + return Either.left(createArtifactsFromCsar.left().value()); + }catch(Exception e) + { + log.debug("Exception occured in getResourceResponseFormatEither, message:{}", e.getMessage(), e); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + protected Either<Resource, ResponseFormat> createOrUpdateNonMetaArtifacts(CsarInfo csarInfo, Resource resource, + List<ArtifactDefinition> createdArtifacts, boolean shouldLock, boolean inTransaction, + ArtifactOperationInfo artifactOperation) { + Either<Resource, ResponseFormat> resStatus = null; + Map<String, Set<List<String>>> collectedWarningMessages = new HashMap<>(); + try { + Either<List<CsarUtils.NonMetaArtifactInfo>, String> artifactPathAndNameList = getValidArtifactNames(csarInfo, collectedWarningMessages); + if (artifactPathAndNameList.isRight()) { + return Either.right(getComponentsUtils().getResponseFormatByArtifactId( + ActionStatus.ARTIFACT_NAME_INVALID, artifactPathAndNameList.right().value())); + } + EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>> vfCsarArtifactsToHandle = null; + + if (ArtifactsBusinessLogic.ArtifactOperationEnum.isCreateOrLink(artifactOperation.getArtifactOperationEnum())) { + vfCsarArtifactsToHandle = new EnumMap<>(ArtifactsBusinessLogic.ArtifactOperationEnum.class); + vfCsarArtifactsToHandle.put(artifactOperation.getArtifactOperationEnum(), artifactPathAndNameList.left().value()); + } else { + Either<EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>>, ResponseFormat> findVfCsarArtifactsToHandleRes = findVfCsarArtifactsToHandle( + resource, artifactPathAndNameList.left().value(), csarInfo.getModifier()); + if (findVfCsarArtifactsToHandleRes.isRight()) { + resStatus = Either.right(findVfCsarArtifactsToHandleRes.right().value()); + } + if (resStatus == null) { + vfCsarArtifactsToHandle = findVfCsarArtifactsToHandleRes.left().value(); + } + } + if (resStatus == null && vfCsarArtifactsToHandle != null) { + resStatus = processCsarArtifacts(csarInfo, resource, createdArtifacts, shouldLock, inTransaction, resStatus, vfCsarArtifactsToHandle); + } + if (resStatus == null) { + resStatus = Either.left(resource); + } + } catch (Exception e) { + resStatus = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + log.debug("Exception occured in createNonMetaArtifacts, message:{}", e.getMessage(), e); + } finally { + CsarUtils.handleWarningMessages(collectedWarningMessages); + } + return resStatus; + } + + protected Either<EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>>, ResponseFormat> findVfCsarArtifactsToHandle( + Resource resource, List<CsarUtils.NonMetaArtifactInfo> artifactPathAndNameList, User user) { + + List<ArtifactDefinition> existingArtifacts = new ArrayList<>(); + if (resource.getDeploymentArtifacts() != null && !resource.getDeploymentArtifacts().isEmpty()) { + existingArtifacts.addAll(resource.getDeploymentArtifacts().values()); + } + if (resource.getArtifacts() != null && !resource.getArtifacts().isEmpty()) { + existingArtifacts.addAll(resource.getArtifacts().values()); + } + existingArtifacts = existingArtifacts.stream() + .filter(this::isNonMetaArtifact).collect(toList()); + + List<String> artifactsToIgnore = new ArrayList<>(); + if (resource.getGroups() != null) { + resource.getGroups().stream().forEach(g -> { + if (g.getArtifacts() != null && !g.getArtifacts().isEmpty()) { + artifactsToIgnore.addAll(g.getArtifacts()); + } + }); + } + existingArtifacts = existingArtifacts.stream() + .filter(a -> !artifactsToIgnore.contains(a.getUniqueId())).collect(toList()); + return organizeVfCsarArtifactsByArtifactOperation(artifactPathAndNameList, existingArtifacts, resource, user); + } + + protected boolean isNonMetaArtifact(ArtifactDefinition artifact) { + boolean result = true; + if (artifact.getMandatory() || artifact.getArtifactName() == null || !isValidArtifactType(artifact)) { + result = false; + } + return result; + } + + 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; + } + + protected Either<EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>>, ResponseFormat> organizeVfCsarArtifactsByArtifactOperation( + List<CsarUtils.NonMetaArtifactInfo> artifactPathAndNameList, List<ArtifactDefinition> existingArtifactsToHandle, + Resource resource, User user) { + + EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>> nodeTypeArtifactsToHandle = new EnumMap<>( + ArtifactsBusinessLogic.ArtifactOperationEnum.class); + Wrapper<ResponseFormat> responseWrapper = new Wrapper<>(); + Either<EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>>, ResponseFormat> nodeTypeArtifactsToHandleRes = Either + .left(nodeTypeArtifactsToHandle); + try { + // add all found Csar artifacts to list to upload + List<CsarUtils.NonMetaArtifactInfo> artifactsToUpload = new ArrayList<>(artifactPathAndNameList); + List<CsarUtils.NonMetaArtifactInfo> artifactsToUpdate = new ArrayList<>(); + List<CsarUtils.NonMetaArtifactInfo> artifactsToDelete = new ArrayList<>(); + for (CsarUtils.NonMetaArtifactInfo currNewArtifact : artifactPathAndNameList) { + ArtifactDefinition foundArtifact; + if (!existingArtifactsToHandle.isEmpty()) { + foundArtifact = existingArtifactsToHandle.stream() + .filter(a -> a.getArtifactName().equals(currNewArtifact.getArtifactName())).findFirst() + .orElse(null); + if (foundArtifact != null) { + if (ArtifactTypeEnum.findType(foundArtifact.getArtifactType()).equals(currNewArtifact + .getArtifactType())) { + if (!foundArtifact.getArtifactChecksum().equals(currNewArtifact.getArtifactChecksum())) { + currNewArtifact.setArtifactUniqueId(foundArtifact.getUniqueId()); + artifactsToUpdate.add(currNewArtifact); + } + existingArtifactsToHandle.remove(foundArtifact); + artifactsToUpload.remove(currNewArtifact); + } else { + log.debug("Can't upload two artifact with the same name {}.", + currNewArtifact.getArtifactName()); + 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, resource, resource.getUniqueId(), + user, null, null, foundArtifact.getUniqueId(), responseFormat, + resource.getComponentType(), null); + responseWrapper.setInnerElement(responseFormat); + break; + } + } + } + } + if (responseWrapper.isEmpty()) { + for (ArtifactDefinition currArtifact : existingArtifactsToHandle) { + if (currArtifact.getIsFromCsar()) { + artifactsToDelete.add(new CsarUtils.NonMetaArtifactInfo(currArtifact.getArtifactName(), null, ArtifactTypeEnum.findType(currArtifact.getArtifactType()), currArtifact.getArtifactGroupType(), null, currArtifact.getUniqueId(), currArtifact.getIsFromCsar())); + } else { + artifactsToUpdate.add(new CsarUtils.NonMetaArtifactInfo(currArtifact.getArtifactName(), null, ArtifactTypeEnum.findType(currArtifact.getArtifactType()), currArtifact.getArtifactGroupType(), null, currArtifact.getUniqueId(), currArtifact.getIsFromCsar())); + + } + } + } + if (responseWrapper.isEmpty()) { + if (!artifactsToUpload.isEmpty()) { + nodeTypeArtifactsToHandle.put(ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE, artifactsToUpload); + } + if (!artifactsToUpdate.isEmpty()) { + nodeTypeArtifactsToHandle.put(ArtifactsBusinessLogic.ArtifactOperationEnum.UPDATE, artifactsToUpdate); + } + if (!artifactsToDelete.isEmpty()) { + nodeTypeArtifactsToHandle.put(ArtifactsBusinessLogic.ArtifactOperationEnum.DELETE, artifactsToDelete); + } + } + if (!responseWrapper.isEmpty()) { + nodeTypeArtifactsToHandleRes = Either.right(responseWrapper.getInnerElement()); + } + } catch (Exception e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR); + responseWrapper.setInnerElement(responseFormat); + log.debug("Exception occured when findNodeTypeArtifactsToHandle, error is:{}", e.getMessage(), e); + nodeTypeArtifactsToHandleRes = Either.right(responseWrapper.getInnerElement()); + } + return nodeTypeArtifactsToHandleRes; + } + + protected Either<Resource, ResponseFormat> processCsarArtifacts(CsarInfo csarInfo, Resource resource, List<ArtifactDefinition> createdArtifacts, boolean shouldLock, boolean inTransaction, Either<Resource, ResponseFormat> resStatus, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>> vfCsarArtifactsToHandle) { + for (Map.Entry<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>> currArtifactOperationPair : vfCsarArtifactsToHandle + .entrySet()) { + Optional<ResponseFormat> optionalCreateInDBError = + currArtifactOperationPair.getValue().stream() + .map(e -> createOrUpdateSingleNonMetaArtifact(resource, csarInfo, e.getPath(), + e.getArtifactName(), e.getArtifactType(), + e.getArtifactGroupType(), e.getArtifactLabel(), e.getDisplayName(), + CsarUtils.ARTIFACT_CREATED_FROM_CSAR, e.getArtifactUniqueId(), + new ArtifactOperationInfo(false, false, + currArtifactOperationPair.getKey()), + createdArtifacts, e.isFromCsar(), shouldLock, inTransaction)) + .filter(Either::isRight). + map(e -> e.right().value()). + findAny(); + if (optionalCreateInDBError.isPresent()) { + resStatus = Either.right(optionalCreateInDBError.get()); + break; + } + } + return resStatus; + } + + protected Either<Boolean, ResponseFormat> createOrUpdateSingleNonMetaArtifact(Resource resource, CsarInfo csarInfo, + String artifactPath, String artifactFileName, String artifactType, ArtifactGroupTypeEnum artifactGroupType, + String artifactLabel, String artifactDisplayName, String artifactDescription, String artifactId, + ArtifactOperationInfo operation, List<ArtifactDefinition> createdArtifacts, boolean isFromCsar, boolean shouldLock, + boolean inTransaction) { + byte[] artifactFileBytes = null; + + if (csarInfo.getCsar().containsKey(artifactPath)) { + artifactFileBytes = csarInfo.getCsar().get(artifactPath); + } + Either<Boolean, ResponseFormat> result = Either.left(true); + if (operation.getArtifactOperationEnum() == ArtifactsBusinessLogic.ArtifactOperationEnum.UPDATE || operation.getArtifactOperationEnum() == ArtifactsBusinessLogic.ArtifactOperationEnum.DELETE) { + if (serviceImportParseLogic.isArtifactDeletionRequired(artifactId, artifactFileBytes, isFromCsar)) { + Either<ArtifactDefinition, ResponseFormat> handleDelete = serviceBusinessLogic.artifactsBusinessLogic.handleDelete(resource.getUniqueId(), artifactId, csarInfo.getModifier(), resource, + shouldLock, inTransaction); + if (handleDelete.isRight()) { + result = Either.right(handleDelete.right().value()); + } + return result; + } + if (org.apache.commons.lang.StringUtils.isEmpty(artifactId) && artifactFileBytes != null) { + operation = new ArtifactOperationInfo(false, false, + ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE); + } + } + if (artifactFileBytes != null) { + Map<String, Object> vendorLicenseModelJson = ArtifactUtils + .buildJsonForUpdateArtifact(artifactId, artifactFileName, + artifactType, artifactGroupType, artifactLabel, artifactDisplayName, artifactDescription, + artifactFileBytes, null, isFromCsar); + Either<Either<ArtifactDefinition, Operation>, ResponseFormat> eitherNonMetaArtifacts = csarArtifactsAndGroupsBusinessLogic.createOrUpdateCsarArtifactFromJson( + resource, csarInfo.getModifier(), vendorLicenseModelJson, operation); + serviceImportParseLogic + .addNonMetaCreatedArtifactsToSupportRollback(operation, createdArtifacts, eitherNonMetaArtifacts); + if (eitherNonMetaArtifacts.isRight()) { + BeEcompErrorManager.getInstance() + .logInternalFlowError("UploadLicenseArtifact", "Failed to upload license artifact: " + + artifactFileName + "With csar uuid: " + csarInfo.getCsarUUID(), + BeEcompErrorManager.ErrorSeverity.WARNING); + return Either.right(eitherNonMetaArtifacts.right().value()); + } + } + return result; + } + + public Either<List<ArtifactDefinition>, ResponseFormat> handleNodeTypeArtifacts(Resource nodeTypeResource, + Map<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> nodeTypeArtifactsToHandle, + List<ArtifactDefinition> createdArtifacts, User user, boolean inTransaction, boolean ignoreLifecycleState) { + List<ArtifactDefinition> handleNodeTypeArtifactsRequestRes; + Either<List<ArtifactDefinition>, ResponseFormat> handleNodeTypeArtifactsRes = null; + Either<Resource, ResponseFormat> changeStateResponse; + try { + changeStateResponse = checkoutResource(nodeTypeResource, user, inTransaction); + if (changeStateResponse.isRight()) { + return Either.right(changeStateResponse.right().value()); + } + nodeTypeResource = changeStateResponse.left().value(); + + List<ArtifactDefinition> handledNodeTypeArtifacts = new ArrayList<>(); + log.debug("************* Going to handle artifacts of node type resource {}. ", nodeTypeResource.getName()); + for (Map.Entry<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> curOperationEntry : nodeTypeArtifactsToHandle + .entrySet()) { + ArtifactsBusinessLogic.ArtifactOperationEnum curOperation = curOperationEntry.getKey(); + List<ArtifactDefinition> curArtifactsToHandle = curOperationEntry.getValue(); + if (curArtifactsToHandle != null && !curArtifactsToHandle.isEmpty()) { + log.debug("************* Going to {} artifact to vfc {}", curOperation.name(), + nodeTypeResource.getName()); + handleNodeTypeArtifactsRequestRes = serviceBusinessLogic.artifactsBusinessLogic + .handleArtifactsRequestForInnerVfcComponent(curArtifactsToHandle, nodeTypeResource, user, + createdArtifacts, new ArtifactOperationInfo(false, + ignoreLifecycleState, curOperation), + false, inTransaction); + if (ArtifactsBusinessLogic.ArtifactOperationEnum.isCreateOrLink(curOperation)) { + createdArtifacts.addAll(handleNodeTypeArtifactsRequestRes); + } + handledNodeTypeArtifacts.addAll(handleNodeTypeArtifactsRequestRes); + } + } + if (handleNodeTypeArtifactsRes == null) { + handleNodeTypeArtifactsRes = Either.left(handledNodeTypeArtifacts); + } + } catch (Exception e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR); + handleNodeTypeArtifactsRes = Either.right(responseFormat); + log.debug("Exception occured when handleVfcArtifacts, error is:{}", e.getMessage(), e); + } + return handleNodeTypeArtifactsRes; + } + + protected Either<Resource, ResponseFormat> checkoutResource(Resource resource, User user, boolean inTransaction) { + Either<Resource, ResponseFormat> checkoutResourceRes; + try { + if (!resource.getComponentMetadataDefinition().getMetadataDataDefinition().getState() + .equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) { + Either<? extends Component, ResponseFormat> checkoutRes = lifecycleBusinessLogic.changeComponentState( + resource.getComponentType(), resource.getUniqueId(), user, LifeCycleTransitionEnum.CHECKOUT, + new LifecycleChangeInfoWithAction(CERTIFICATION_ON_IMPORT, + LifecycleChangeInfoWithAction.LifecycleChanceActionEnum.CREATE_FROM_CSAR), + inTransaction, true); + if (checkoutRes.isRight()) { + checkoutResourceRes = Either.right(checkoutRes.right().value()); + } else { + checkoutResourceRes = Either.left((Resource) checkoutRes.left().value()); + } + } else { + checkoutResourceRes = Either.left(resource); + } + } catch (Exception e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR); + checkoutResourceRes = Either.right(responseFormat); + log.debug("Exception occured when checkoutResource {} , error is:{}", resource.getName(), e.getMessage(), + e); + } + return checkoutResourceRes; + } + + protected Either<Service, ResponseFormat> createOrUpdateArtifacts( + ArtifactsBusinessLogic.ArtifactOperationEnum operation, List<ArtifactDefinition> createdArtifacts, + String yamlFileName, CsarInfo csarInfo, Service preparedService, + NodeTypeInfoToUpdateArtifacts nodeTypeInfoToUpdateArtifacts, boolean inTransaction, boolean shouldLock) { + + String nodeName = nodeTypeInfoToUpdateArtifacts.getNodeName(); + Service resource = preparedService; + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle = nodeTypeInfoToUpdateArtifacts + .getNodeTypesArtifactsToHandle(); + + Either<Service, ResponseFormat> createdCsarArtifactsEither = handleVfCsarArtifacts(preparedService, csarInfo, createdArtifacts, + new ArtifactOperationInfo(false, false, operation), shouldLock, inTransaction); + log.trace("************* Finished to add artifacts from yaml {}", yamlFileName); + if (createdCsarArtifactsEither.isRight()) { + return createdCsarArtifactsEither; + } + resource = createdCsarArtifactsEither.left().value(); + return Either.left(resource); + } + + protected Either<Service, ResponseFormat> handleVfCsarArtifacts(Service service, CsarInfo csarInfo, + List<ArtifactDefinition> createdArtifacts, ArtifactOperationInfo artifactOperation, boolean shouldLock, + boolean inTransaction) { + + if (csarInfo.getCsar() != null) { + String vendorLicenseModelId = null; + String vfLicenseModelId = null; + if (artifactOperation.getArtifactOperationEnum() == ArtifactsBusinessLogic.ArtifactOperationEnum.UPDATE) { + Map<String, ArtifactDefinition> deploymentArtifactsMap = service.getDeploymentArtifacts(); + if (deploymentArtifactsMap != null && !deploymentArtifactsMap.isEmpty()) { + for (Map.Entry<String, ArtifactDefinition> artifactEntry : deploymentArtifactsMap.entrySet()) { + if (artifactEntry.getValue().getArtifactName().equalsIgnoreCase(Constants.VENDOR_LICENSE_MODEL)) { + vendorLicenseModelId = artifactEntry.getValue().getUniqueId(); + } + if (artifactEntry.getValue().getArtifactName().equalsIgnoreCase(Constants.VF_LICENSE_MODEL)) { + vfLicenseModelId = artifactEntry.getValue().getUniqueId(); + } + } + } + } + createOrUpdateSingleNonMetaArtifact(service, csarInfo, + CsarUtils.ARTIFACTS_PATH + Constants.VENDOR_LICENSE_MODEL, Constants.VENDOR_LICENSE_MODEL, + ArtifactTypeEnum.VENDOR_LICENSE.getType(), ArtifactGroupTypeEnum.DEPLOYMENT, + Constants.VENDOR_LICENSE_LABEL, Constants.VENDOR_LICENSE_DISPLAY_NAME, + Constants.VENDOR_LICENSE_DESCRIPTION, vendorLicenseModelId, artifactOperation, null, true, shouldLock, + inTransaction); + createOrUpdateSingleNonMetaArtifact(service, csarInfo, + CsarUtils.ARTIFACTS_PATH + Constants.VF_LICENSE_MODEL, Constants.VF_LICENSE_MODEL, + ArtifactTypeEnum.VF_LICENSE.getType(), ArtifactGroupTypeEnum.DEPLOYMENT, Constants.VF_LICENSE_LABEL, + Constants.VF_LICENSE_DISPLAY_NAME, Constants.VF_LICENSE_DESCRIPTION, vfLicenseModelId, + artifactOperation, null, true, shouldLock, inTransaction); + + Either<Service, ResponseFormat> eitherCreateResult = createOrUpdateNonMetaArtifacts(csarInfo, service, + createdArtifacts, shouldLock, inTransaction, artifactOperation); + if (eitherCreateResult.isRight()) { + return Either.right(eitherCreateResult.right().value()); + } + Either<Service, StorageOperationStatus> eitherGerResource = toscaOperationFacade + .getToscaElement(service.getUniqueId()); + if (eitherGerResource.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByComponent( + componentsUtils.convertFromStorageResponse(eitherGerResource.right().value()), service, ComponentTypeEnum.SERVICE); + return Either.right(responseFormat); + } + service = eitherGerResource.left().value(); + Either<ImmutablePair<String, String>, ResponseFormat> artifacsMetaCsarStatus = CsarValidationUtils.getArtifactsMeta(csarInfo.getCsar(), csarInfo.getCsarUUID(), componentsUtils); + + if (artifacsMetaCsarStatus.isLeft()) { + String artifactsFileName = artifacsMetaCsarStatus.left().value().getKey(); + String artifactsContents = artifacsMetaCsarStatus.left().value().getValue(); + Either<Service, ResponseFormat> createArtifactsFromCsar; + if (ArtifactsBusinessLogic.ArtifactOperationEnum.isCreateOrLink(artifactOperation.getArtifactOperationEnum())) { + createArtifactsFromCsar = csarArtifactsAndGroupsBusinessLogic.createResourceArtifactsFromCsar(csarInfo, service, artifactsContents, artifactsFileName, createdArtifacts); + } else { + Either<Component, ResponseFormat> result = csarArtifactsAndGroupsBusinessLogic.updateResourceArtifactsFromCsar(csarInfo, service, artifactsContents, artifactsFileName, createdArtifacts, shouldLock, inTransaction); + if ((result.left().value() instanceof Service) && result.isLeft()) { + Service service1 = (Service) result.left().value(); + createArtifactsFromCsar = Either.left(service1); + } else { + createArtifactsFromCsar = Either.right(result.right().value()); + } + } + if (createArtifactsFromCsar.isRight()) { + log.debug("Couldn't create artifacts from artifacts.meta"); + return Either.right(createArtifactsFromCsar.right().value()); + } + return Either.left(createArtifactsFromCsar.left().value()); + } else { + return csarArtifactsAndGroupsBusinessLogic.deleteVFModules(service, csarInfo, shouldLock, inTransaction); + } + } + return Either.left(service); + } + + protected Either<Service, ResponseFormat> createOrUpdateNonMetaArtifacts(CsarInfo csarInfo, Service resource, + List<ArtifactDefinition> createdArtifacts, boolean shouldLock, boolean inTransaction, + ArtifactOperationInfo artifactOperation) { + Either<Service, ResponseFormat> resStatus = null; + Map<String, Set<List<String>>> collectedWarningMessages = new HashMap<>(); + + try { + Either<List<CsarUtils.NonMetaArtifactInfo>, String> artifactPathAndNameList = getValidArtifactNames(csarInfo, collectedWarningMessages); + if (artifactPathAndNameList.isRight()) { + return Either.right(getComponentsUtils().getResponseFormatByArtifactId( + ActionStatus.ARTIFACT_NAME_INVALID, artifactPathAndNameList.right().value())); + } + EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>> vfCsarArtifactsToHandle = null; + + if (ArtifactsBusinessLogic.ArtifactOperationEnum.isCreateOrLink(artifactOperation.getArtifactOperationEnum())) { + vfCsarArtifactsToHandle = new EnumMap<>(ArtifactsBusinessLogic.ArtifactOperationEnum.class); + vfCsarArtifactsToHandle.put(artifactOperation.getArtifactOperationEnum(), artifactPathAndNameList.left().value()); + } else { + Either<EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>>, ResponseFormat> findVfCsarArtifactsToHandleRes = findVfCsarArtifactsToHandle( + resource, artifactPathAndNameList.left().value(), csarInfo.getModifier()); + + if (findVfCsarArtifactsToHandleRes.isRight()) { + resStatus = Either.right(findVfCsarArtifactsToHandleRes.right().value()); + } + if (resStatus == null) { + vfCsarArtifactsToHandle = findVfCsarArtifactsToHandleRes.left().value(); + } + } + if (resStatus == null && vfCsarArtifactsToHandle != null) { + resStatus = processCsarArtifacts(csarInfo, resource, createdArtifacts, shouldLock, inTransaction, resStatus, vfCsarArtifactsToHandle); + } + if (resStatus == null) { + resStatus = Either.left(resource); + } + } catch (Exception e) { + resStatus = Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR)); + log.debug("Exception occured in createNonMetaArtifacts, message:{}", e.getMessage(), e); + } finally { + CsarUtils.handleWarningMessages(collectedWarningMessages); + } + return resStatus; + } + + protected Either<EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>>, ResponseFormat> findVfCsarArtifactsToHandle( + Service resource, List<CsarUtils.NonMetaArtifactInfo> artifactPathAndNameList, User user) { + List<ArtifactDefinition> existingArtifacts = new ArrayList<>(); + if (resource.getDeploymentArtifacts() != null && !resource.getDeploymentArtifacts().isEmpty()) { + existingArtifacts.addAll(resource.getDeploymentArtifacts().values()); + } + if (resource.getArtifacts() != null && !resource.getArtifacts().isEmpty()) { + existingArtifacts.addAll(resource.getArtifacts().values()); + } + existingArtifacts = existingArtifacts.stream().filter(this::isNonMetaArtifact).collect(toList()); + + List<String> artifactsToIgnore = new ArrayList<>(); + if (resource.getGroups() != null) { + resource.getGroups().stream().forEach(g -> { + if (g.getArtifacts() != null && !g.getArtifacts().isEmpty()) { + artifactsToIgnore.addAll(g.getArtifacts()); + } + }); + } + existingArtifacts = existingArtifacts.stream() + .filter(a -> !artifactsToIgnore.contains(a.getUniqueId())).collect(toList()); + return organizeVfCsarArtifactsByArtifactOperation(artifactPathAndNameList, existingArtifacts, resource, user); + } + + protected Either<EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>>, ResponseFormat> organizeVfCsarArtifactsByArtifactOperation( + List<CsarUtils.NonMetaArtifactInfo> artifactPathAndNameList, List<ArtifactDefinition> existingArtifactsToHandle, + Service resource, User user) { + EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>> nodeTypeArtifactsToHandle = new EnumMap<>( + ArtifactsBusinessLogic.ArtifactOperationEnum.class); + Wrapper<ResponseFormat> responseWrapper = new Wrapper<>(); + Either<EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>>, ResponseFormat> nodeTypeArtifactsToHandleRes = Either + .left(nodeTypeArtifactsToHandle); + try { + List<CsarUtils.NonMetaArtifactInfo> artifactsToUpload = new ArrayList<>(artifactPathAndNameList); + List<CsarUtils.NonMetaArtifactInfo> artifactsToUpdate = new ArrayList<>(); + List<CsarUtils.NonMetaArtifactInfo> artifactsToDelete = new ArrayList<>(); + for (CsarUtils.NonMetaArtifactInfo currNewArtifact : artifactPathAndNameList) { + ArtifactDefinition foundArtifact; + + if (!existingArtifactsToHandle.isEmpty()) { + foundArtifact = existingArtifactsToHandle.stream() + .filter(a -> a.getArtifactName().equals(currNewArtifact.getArtifactName())).findFirst() + .orElse(null); + if (foundArtifact != null) { + if (ArtifactTypeEnum.findType(foundArtifact.getArtifactType()).equals(currNewArtifact + .getArtifactType())) { + if (!foundArtifact.getArtifactChecksum().equals(currNewArtifact.getArtifactChecksum())) { + currNewArtifact.setArtifactUniqueId(foundArtifact.getUniqueId()); + artifactsToUpdate.add(currNewArtifact); + } + existingArtifactsToHandle.remove(foundArtifact); + artifactsToUpload.remove(currNewArtifact); + } else { + log.debug("Can't upload two artifact with the same name {}.", + currNewArtifact.getArtifactName()); + 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, resource, resource.getUniqueId(), + user, null, null, foundArtifact.getUniqueId(), responseFormat, + resource.getComponentType(), null); + responseWrapper.setInnerElement(responseFormat); + break; + } + } + } + } + if (responseWrapper.isEmpty()) { + for (ArtifactDefinition currArtifact : existingArtifactsToHandle) { + if (currArtifact.getIsFromCsar()) { + artifactsToDelete.add(new CsarUtils.NonMetaArtifactInfo(currArtifact.getArtifactName(), null, ArtifactTypeEnum.findType(currArtifact.getArtifactType()), currArtifact.getArtifactGroupType(), null, currArtifact.getUniqueId(), currArtifact.getIsFromCsar())); + } else { + artifactsToUpdate.add(new CsarUtils.NonMetaArtifactInfo(currArtifact.getArtifactName(), null, ArtifactTypeEnum.findType(currArtifact.getArtifactType()), currArtifact.getArtifactGroupType(), null, currArtifact.getUniqueId(), currArtifact.getIsFromCsar())); + } + } + } + if (responseWrapper.isEmpty()) { + if (!artifactsToUpload.isEmpty()) { + nodeTypeArtifactsToHandle.put(ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE, artifactsToUpload); + } + if (!artifactsToUpdate.isEmpty()) { + nodeTypeArtifactsToHandle.put(ArtifactsBusinessLogic.ArtifactOperationEnum.UPDATE, artifactsToUpdate); + } + if (!artifactsToDelete.isEmpty()) { + nodeTypeArtifactsToHandle.put(ArtifactsBusinessLogic.ArtifactOperationEnum.DELETE, artifactsToDelete); + } + } + if (!responseWrapper.isEmpty()) { + nodeTypeArtifactsToHandleRes = Either.right(responseWrapper.getInnerElement()); + } + } catch (Exception e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR); + responseWrapper.setInnerElement(responseFormat); + log.debug("Exception occured when findNodeTypeArtifactsToHandle, error is:{}", e.getMessage(), e); + nodeTypeArtifactsToHandleRes = Either.right(responseWrapper.getInnerElement()); + } + return nodeTypeArtifactsToHandleRes; + } + + protected Either<Service, ResponseFormat> processCsarArtifacts(CsarInfo csarInfo, Service resource, List<ArtifactDefinition> createdArtifacts, boolean shouldLock, boolean inTransaction, Either<Service, ResponseFormat> resStatus, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>> vfCsarArtifactsToHandle) { + for (Map.Entry<ArtifactsBusinessLogic.ArtifactOperationEnum, List<CsarUtils.NonMetaArtifactInfo>> currArtifactOperationPair : vfCsarArtifactsToHandle + .entrySet()) { + Optional<ResponseFormat> optionalCreateInDBError = + currArtifactOperationPair.getValue().stream() + .map(e -> createOrUpdateSingleNonMetaArtifact(resource, csarInfo, e.getPath(), + e.getArtifactName(), e.getArtifactType(), + e.getArtifactGroupType(), e.getArtifactLabel(), e.getDisplayName(), + CsarUtils.ARTIFACT_CREATED_FROM_CSAR, e.getArtifactUniqueId(), + new ArtifactOperationInfo(false, false, + currArtifactOperationPair.getKey()), + createdArtifacts, e.isFromCsar(), shouldLock, inTransaction)) + .filter(Either::isRight). + map(e -> e.right().value()). + findAny(); + if (optionalCreateInDBError.isPresent()) { + resStatus = Either.right(optionalCreateInDBError.get()); + break; + } + } + return resStatus; + } + + public ComponentsUtils getComponentsUtils() { + return this.componentsUtils; + } + + public void setComponentsUtils(ComponentsUtils componentsUtils) { + this.componentsUtils = componentsUtils; + } + + protected Either<List<CsarUtils.NonMetaArtifactInfo>, String> getValidArtifactNames(CsarInfo csarInfo, Map<String, Set<List<String>>> collectedWarningMessages) { + List<CsarUtils.NonMetaArtifactInfo> artifactPathAndNameList = + csarInfo.getCsar().entrySet().stream() + .filter(e -> Pattern.compile(VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN).matcher(e.getKey()) + .matches()) + .map(e -> CsarUtils.validateNonMetaArtifact(e.getKey(), e.getValue(), + collectedWarningMessages)) + .filter(Either::isLeft) + .map(e -> e.left().value()) + .collect(toList()); + Pattern englishNumbersAndUnderScoresOnly = Pattern.compile(CsarUtils.VALID_ENGLISH_ARTIFACT_NAME); + for (CsarUtils.NonMetaArtifactInfo nonMetaArtifactInfo : artifactPathAndNameList) { + if (!englishNumbersAndUnderScoresOnly.matcher(nonMetaArtifactInfo.getDisplayName()).matches()) { + return Either.right(nonMetaArtifactInfo.getArtifactName()); + } + } + return Either.left(artifactPathAndNameList); + } + + protected Either<Boolean, ResponseFormat> createOrUpdateSingleNonMetaArtifact(Service service, CsarInfo csarInfo, + String artifactPath, String artifactFileName, String artifactType, ArtifactGroupTypeEnum artifactGroupType, + String artifactLabel, String artifactDisplayName, String artifactDescription, String artifactId, + ArtifactOperationInfo operation, List<ArtifactDefinition> createdArtifacts, boolean isFromCsar, boolean shouldLock, + boolean inTransaction) { + byte[] artifactFileBytes = null; + if (csarInfo.getCsar().containsKey(artifactPath)) { + artifactFileBytes = csarInfo.getCsar().get(artifactPath); + } + Either<Boolean, ResponseFormat> result = Either.left(true); + if (operation.getArtifactOperationEnum() == ArtifactsBusinessLogic.ArtifactOperationEnum.UPDATE || operation.getArtifactOperationEnum() == ArtifactsBusinessLogic.ArtifactOperationEnum.DELETE) { + if (serviceImportParseLogic.isArtifactDeletionRequired(artifactId, artifactFileBytes, isFromCsar)) { + Either<ArtifactDefinition, ResponseFormat> handleDelete = serviceBusinessLogic.artifactsBusinessLogic.handleDelete(service.getUniqueId(), artifactId, csarInfo.getModifier(), service, + shouldLock, inTransaction); + if (handleDelete.isRight()) { + result = Either.right(handleDelete.right().value()); + } + return result; + } + if (org.apache.commons.lang.StringUtils.isEmpty(artifactId) && artifactFileBytes != null) { + operation = new ArtifactOperationInfo(false, false, + ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE); + } + } + if (artifactFileBytes != null) { + Map<String, Object> vendorLicenseModelJson = ArtifactUtils.buildJsonForUpdateArtifact(artifactId, artifactFileName, + artifactType, artifactGroupType, artifactLabel, artifactDisplayName, artifactDescription, + artifactFileBytes, null, isFromCsar); + Either<Either<ArtifactDefinition, Operation>, ResponseFormat> eitherNonMetaArtifacts = csarArtifactsAndGroupsBusinessLogic.createOrUpdateCsarArtifactFromJson( + service, csarInfo.getModifier(), vendorLicenseModelJson, operation); + serviceImportParseLogic + .addNonMetaCreatedArtifactsToSupportRollback(operation, createdArtifacts, eitherNonMetaArtifacts); + if (eitherNonMetaArtifacts.isRight()) { + BeEcompErrorManager.getInstance() + .logInternalFlowError("UploadLicenseArtifact", "Failed to upload license artifact: " + + artifactFileName + "With csar uuid: " + csarInfo.getCsarUUID(), + BeEcompErrorManager.ErrorSeverity.WARNING); + return Either.right(eitherNonMetaArtifacts.right().value()); + } + } + return result; + } + + protected Either<Service, ResponseFormat> createGroupsOnResource(Service service, + Map<String, GroupDefinition> groups) { + if (groups != null && !groups.isEmpty()) { + List<GroupDefinition> groupsAsList = updateGroupsMembersUsingResource(groups, service); + serviceImportParseLogic.handleGroupsProperties(service, groups); + serviceImportParseLogic.fillGroupsFinalFields(groupsAsList); + Either<List<GroupDefinition>, ResponseFormat> createGroups = serviceBusinessLogic.groupBusinessLogic.createGroups(service, + groupsAsList, true); + if (createGroups.isRight()) { + return Either.right(createGroups.right().value()); + } + } else { + return Either.left(service); + } + Either<Service, StorageOperationStatus> updatedResource = toscaOperationFacade + .getToscaElement(service.getUniqueId()); + if (updatedResource.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByComponent( + componentsUtils.convertFromStorageResponse(updatedResource.right().value()), service, ComponentTypeEnum.SERVICE); + return Either.right(responseFormat); + } + return Either.left(updatedResource.left().value()); + } + + protected List<GroupDefinition> updateGroupsMembersUsingResource(Map<String, GroupDefinition> groups, Service component) { + List<GroupDefinition> result = new ArrayList<>(); + List<ComponentInstance> componentInstances = component.getComponentInstances(); + if (groups != null) { + Either<Boolean, ResponseFormat> validateCyclicGroupsDependencies = serviceImportParseLogic.validateCyclicGroupsDependencies(groups); + if (validateCyclicGroupsDependencies.isRight()) { + throw new ComponentException(validateCyclicGroupsDependencies.right().value()); + } + for (Map.Entry<String, GroupDefinition> entry : groups.entrySet()) { + String groupName = entry.getKey(); + GroupDefinition groupDefinition = entry.getValue(); + GroupDefinition updatedGroupDefinition = new GroupDefinition(groupDefinition); + updatedGroupDefinition.setMembers(null); + Map<String, String> members = groupDefinition.getMembers(); + if (members != null) { + serviceImportParseLogic + .updateGroupMembers(groups, updatedGroupDefinition, component, componentInstances, groupName, members); + } + result.add(updatedGroupDefinition); + } + } + return result; + } + + + protected Resource createRIAndRelationsFromYaml(String yamlName, Resource resource, + Map<String, UploadComponentInstanceInfo> uploadComponentInstanceInfoMap, + String topologyTemplateYaml, List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, + Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate, + String nodeName) { + try { + log.debug("************* Going to create all nodes {}", yamlName); + handleNodeTypes(yamlName, resource, topologyTemplateYaml, false, nodeTypesArtifactsToCreate, nodeTypesNewCreatedArtifacts, + nodeTypesInfo, csarInfo, nodeName); + log.debug("************* Going to create all resource instances {}", yamlName); + resource = createResourceInstances(yamlName, resource, + uploadComponentInstanceInfoMap, csarInfo.getCreatedNodes()); + log.debug("************* Finished to create all resource instances {}", yamlName); + resource = createResourceInstancesRelations(csarInfo.getModifier(), yamlName, resource, uploadComponentInstanceInfoMap); + log.debug("************* Going to create positions {}", yamlName); + compositionBusinessLogic.setPositionsForComponentInstances(resource, csarInfo.getModifier().getUserId()); + log.debug("************* Finished to set positions {}", yamlName); + return resource; + } catch (Exception e) { + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected Resource createResourceInstancesRelations(User user, String yamlName, Resource resource, + Map<String, UploadComponentInstanceInfo> uploadResInstancesMap) { + log.debug("#createResourceInstancesRelations - Going to create relations "); + List<ComponentInstance> componentInstancesList = resource.getComponentInstances(); + if (((MapUtils.isEmpty(uploadResInstancesMap) || CollectionUtils.isEmpty(componentInstancesList)) && + resource.getResourceType() != ResourceTypeEnum.PNF)) { // PNF can have no resource instances + log.debug("#createResourceInstancesRelations - No instances found in the resource {} is empty, yaml template file name {}, ", resource.getUniqueId(), yamlName); + BeEcompErrorManager.getInstance().logInternalDataError("createResourceInstancesRelations", "No instances found in a resource or nn yaml template. ", BeEcompErrorManager.ErrorSeverity.ERROR); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName)); + } + Map<String, List<ComponentInstanceProperty>> instProperties = new HashMap<>(); + Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> instCapabilities = new HashMap<>(); + Map<ComponentInstance, Map<String, List<RequirementDefinition>>> instRequirements = new HashMap<>(); + Map<String, Map<String, ArtifactDefinition>> instDeploymentArtifacts = new HashMap<>(); + Map<String, Map<String, ArtifactDefinition>> instArtifacts = new HashMap<>(); + Map<String, List<AttributeDataDefinition>> instAttributes = new HashMap<>(); + Map<String, Resource> originCompMap = new HashMap<>(); + List<RequirementCapabilityRelDef> relations = new ArrayList<>(); + Map<String, List<ComponentInstanceInput>> instInputs = new HashMap<>(); + + log.debug("enter ServiceImportBusinessLogic createResourceInstancesRelations#createResourceInstancesRelations - Before get all datatypes. "); + Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes = serviceBusinessLogic.dataTypeCache.getAll(); + if (allDataTypes.isRight()) { + JanusGraphOperationStatus status = allDataTypes.right().value(); + BeEcompErrorManager.getInstance().logInternalFlowError("UpdatePropertyValueOnComponentInstance", + "Failed to update property value on instance. Status is " + status, BeEcompErrorManager.ErrorSeverity.ERROR); + throw new ComponentException(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse( + DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status)), yamlName)); + } + Resource finalResource = resource; + uploadResInstancesMap + .values() + .forEach(i -> processComponentInstance(yamlName, finalResource, componentInstancesList, allDataTypes, + instProperties, instCapabilities, instRequirements, instDeploymentArtifacts, + instArtifacts, instAttributes, originCompMap, instInputs, i)); + serviceImportParseLogic.associateComponentInstancePropertiesToComponent(yamlName, resource, instProperties); + serviceImportParseLogic.associateComponentInstanceInputsToComponent(yamlName, resource, instInputs); + serviceImportParseLogic + .associateDeploymentArtifactsToInstances(user, yamlName, resource, instDeploymentArtifacts); + serviceImportParseLogic.associateArtifactsToInstances(yamlName, resource, instArtifacts); + serviceImportParseLogic.associateOrAddCalculatedCapReq(yamlName, resource, instCapabilities, instRequirements); + serviceImportParseLogic.associateInstAttributeToComponentToInstances(yamlName, resource, instAttributes); + resource = serviceImportParseLogic.getResourceAfterCreateRelations(resource); + + serviceImportParseLogic + .addRelationsToRI(yamlName, resource, uploadResInstancesMap, componentInstancesList, relations); + serviceImportParseLogic.associateResourceInstances(yamlName, resource, relations); + handleSubstitutionMappings(resource, uploadResInstancesMap); + log.debug("************* in create relations, getResource start"); + Either<Resource, StorageOperationStatus> eitherGetResource = toscaOperationFacade.getToscaElement(resource.getUniqueId()); + log.debug("************* in create relations, getResource end"); + if (eitherGetResource.isRight()) { + throw new ComponentException(componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(eitherGetResource.right().value()), resource)); + } + return eitherGetResource.left().value(); + } + + protected void processComponentInstance(String yamlName, Resource resource, List<ComponentInstance> componentInstancesList, Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes, Map<String, List<ComponentInstanceProperty>> instProperties, Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> instCapabilties, Map<ComponentInstance, Map<String, List<RequirementDefinition>>> instRequirements, Map<String, Map<String, ArtifactDefinition>> instDeploymentArtifacts, Map<String, Map<String, ArtifactDefinition>> instArtifacts, Map<String, List<AttributeDataDefinition>> instAttributes, Map<String, Resource> originCompMap, Map<String, List<ComponentInstanceInput>> instInputs, UploadComponentInstanceInfo uploadComponentInstanceInfo) { + Optional<ComponentInstance> currentCompInstanceOpt = componentInstancesList.stream() + .filter(i -> i.getName().equals(uploadComponentInstanceInfo.getName())) + .findFirst(); + if (!currentCompInstanceOpt.isPresent()) { + log.debug(COMPONENT_INSTANCE_WITH_NAME_IN_RESOURCE, uploadComponentInstanceInfo.getName(), + resource.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError( + COMPONENT_INSTANCE_WITH_NAME + uploadComponentInstanceInfo.getName() + IN_RESOURCE, + resource.getUniqueId(), BeEcompErrorManager.ErrorSeverity.ERROR); + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + throw new ComponentException(responseFormat); + } + ComponentInstance currentCompInstance = currentCompInstanceOpt.get(); + String resourceInstanceId = currentCompInstance.getUniqueId(); + Resource originResource = getOriginResource(yamlName, originCompMap, currentCompInstance); + log.debug("enter processComponentInstance,get originResource Requirements:{}", + originResource.getRequirements()); + if (MapUtils.isNotEmpty(originResource.getRequirements())) { + instRequirements.put(currentCompInstance, originResource.getRequirements()); + } + if (MapUtils.isNotEmpty(originResource.getCapabilities())) { + processComponentInstanceCapabilities(allDataTypes, instCapabilties, uploadComponentInstanceInfo, + currentCompInstance, originResource); + } + if (originResource.getDeploymentArtifacts() != null && !originResource.getDeploymentArtifacts().isEmpty()) { + instDeploymentArtifacts.put(resourceInstanceId, originResource.getDeploymentArtifacts()); + } + if (originResource.getArtifacts() != null && !originResource.getArtifacts().isEmpty()) { + instArtifacts.put(resourceInstanceId, originResource.getArtifacts()); + } + if (originResource.getAttributes() != null && !originResource.getAttributes().isEmpty()) { + instAttributes.put(resourceInstanceId, originResource.getAttributes()); + } + if (originResource.getResourceType() != ResourceTypeEnum.VF) { + ResponseFormat addPropertiesValueToRiRes = addPropertyValuesToRi(uploadComponentInstanceInfo, resource, + originResource, currentCompInstance, instProperties, allDataTypes.left().value()); + if (addPropertiesValueToRiRes.getStatus() != 200) { + throw new ComponentException(addPropertiesValueToRiRes); + } + } else { + addInputsValuesToRi(uploadComponentInstanceInfo, resource, + originResource, currentCompInstance, instInputs, allDataTypes.left().value()); + } + } + + protected void addInputsValuesToRi(UploadComponentInstanceInfo uploadComponentInstanceInfo, + Resource resource, Resource originResource, ComponentInstance currentCompInstance, + Map<String, List<ComponentInstanceInput>> instInputs, Map<String, DataTypeDefinition> allDataTypes) { + Map<String, List<UploadPropInfo>> propMap = uploadComponentInstanceInfo.getProperties(); + try { + if (MapUtils.isNotEmpty(propMap)) { + Map<String, InputDefinition> currPropertiesMap = new HashMap<>(); + List<ComponentInstanceInput> instPropList = new ArrayList<>(); + + if (CollectionUtils.isEmpty(originResource.getInputs())) { + log.debug("failed to find properties "); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND)); + } + originResource.getInputs().forEach(p -> serviceImportParseLogic.addInput(currPropertiesMap, p)); + for (List<UploadPropInfo> propertyList : propMap.values()) { + processProperty(resource, currentCompInstance, allDataTypes, currPropertiesMap, instPropList, propertyList); + } + currPropertiesMap.values().forEach(p -> instPropList.add(new ComponentInstanceInput(p))); + instInputs.put(currentCompInstance.getUniqueId(), instPropList); + } + } catch (Exception e) { + log.debug("failed to add Inputs Values To Ri"); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected void processProperty(Resource resource, ComponentInstance currentCompInstance, Map<String, DataTypeDefinition> allDataTypes, Map<String, InputDefinition> currPropertiesMap, List<ComponentInstanceInput> instPropList, List<UploadPropInfo> propertyList) { + UploadPropInfo propertyInfo = propertyList.get(0); + String propName = propertyInfo.getName(); + if (!currPropertiesMap.containsKey(propName)) { + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, + propName)); + } + InputDefinition curPropertyDef = currPropertiesMap.get(propName); + ComponentInstanceInput property = null; + + String value = null; + List<GetInputValueDataDefinition> getInputs = null; + boolean isValidate = true; + if (propertyInfo.getValue() != null) { + getInputs = propertyInfo.getGet_input(); + isValidate = getInputs == null || getInputs.isEmpty(); + if (isValidate) { + value = getPropertyJsonStringValue(propertyInfo.getValue(), + curPropertyDef.getType()); + } else { + value = getPropertyJsonStringValue(propertyInfo.getValue(), + TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName()); + } + } + String innerType = null; + property = new ComponentInstanceInput(curPropertyDef, value, null); + String validPropertyVAlue = serviceBusinessLogic.validatePropValueBeforeCreate(property, value, isValidate, allDataTypes); + property.setValue(validPropertyVAlue); + + if (isNotEmpty(getInputs)) { + List<GetInputValueDataDefinition> getInputValues = new ArrayList<>(); + for (GetInputValueDataDefinition getInput : getInputs) { + List<InputDefinition> inputs = resource.getInputs(); + if (CollectionUtils.isEmpty(inputs)) { + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + + Optional<InputDefinition> optional = inputs.stream() + .filter(p -> p.getName().equals(getInput.getInputName())).findAny(); + if (!optional.isPresent()) { + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + InputDefinition input = optional.get(); + getInput.setInputId(input.getUniqueId()); + getInputValues.add(getInput); + + GetInputValueDataDefinition getInputIndex = getInput.getGetInputIndex(); + processGetInput(getInputValues, inputs, getInputIndex); + } + property.setGetInputValues(getInputValues); + } + instPropList.add(property); + currPropertiesMap.remove(property.getName()); + } + + protected void handleSubstitutionMappings(Resource resource, Map<String, UploadComponentInstanceInfo> uploadResInstancesMap) { + if (resource.getResourceType() == ResourceTypeEnum.VF) { + Either<Resource, StorageOperationStatus> getResourceRes = toscaOperationFacade.getToscaFullElement(resource.getUniqueId()); + if (getResourceRes.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(getResourceRes.right().value()), resource); + throw new ComponentException(responseFormat); + } + getResourceRes = updateCalculatedCapReqWithSubstitutionMappings(getResourceRes.left().value(), + uploadResInstancesMap); + if (getResourceRes.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(getResourceRes.right().value()), resource); + throw new ComponentException(responseFormat); + } + } + } + + protected Resource createResourceInstances(String yamlName, Resource resource, + Map<String, UploadComponentInstanceInfo> uploadResInstancesMap, + Map<String, Resource> nodeNamespaceMap) { + Either<Resource, ResponseFormat> eitherResource = null; + log.debug("createResourceInstances is {} - going to create resource instanse from CSAR", yamlName); + if (MapUtils.isEmpty(uploadResInstancesMap) && resource.getResourceType() != ResourceTypeEnum.PNF) { // PNF can have no resource instances + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); + throw new ComponentException(responseFormat); + } + Map<String, Resource> existingNodeTypeMap = new HashMap<>(); + if (MapUtils.isNotEmpty(nodeNamespaceMap)) { + nodeNamespaceMap.forEach((k, v) -> existingNodeTypeMap.put(v.getToscaResourceName(), v)); + } + Map<ComponentInstance, Resource> resourcesInstancesMap = new HashMap<>(); + uploadResInstancesMap + .values() + .forEach(i -> createAndAddResourceInstance(i, yamlName, resource, nodeNamespaceMap, existingNodeTypeMap, resourcesInstancesMap)); + + if (MapUtils.isNotEmpty(resourcesInstancesMap)) { + try { + toscaOperationFacade.associateComponentInstancesToComponent(resource, + resourcesInstancesMap, false, false); + } catch (StorageException exp) { + if (exp.getStorageOperationStatus() != null && exp.getStorageOperationStatus() != StorageOperationStatus.OK) { + log.debug("Failed to add component instances to container component {}", resource.getName()); + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(exp.getStorageOperationStatus())); + eitherResource = Either.right(responseFormat); + throw new ByResponseFormatComponentException(eitherResource.right().value()); + } + } + } + log.debug("*************Going to get resource {}", resource.getUniqueId()); + Either<Resource, StorageOperationStatus> eitherGetResource = toscaOperationFacade + .getToscaElement(resource.getUniqueId(), serviceImportParseLogic.getComponentWithInstancesFilter()); + log.debug("*************finished to get resource {}", resource.getUniqueId()); + if (eitherGetResource.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(eitherGetResource.right().value()), resource); + throw new ComponentException(responseFormat); + } + if (CollectionUtils.isEmpty(eitherGetResource.left().value().getComponentInstances()) && + resource.getResourceType() != ResourceTypeEnum.PNF) { // PNF can have no resource instances + log.debug("Error when create resource instance from csar. ComponentInstances list empty"); + BeEcompErrorManager.getInstance().logBeDaoSystemError( + "Error when create resource instance from csar. ComponentInstances list empty"); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE)); + } + return eitherGetResource.left().value(); + } + + protected void handleNodeTypes(String yamlName, Resource resource, + String topologyTemplateYaml, boolean needLock, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle, + List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, Map<String, NodeTypeInfo> nodeTypesInfo, + CsarInfo csarInfo, String nodeName) { + try { + for (Map.Entry<String, NodeTypeInfo> nodeTypeEntry : nodeTypesInfo.entrySet()) { + if (nodeTypeEntry.getValue().isNested()) { + + handleNestedVfc(resource, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, + nodeTypesInfo, csarInfo, nodeTypeEntry.getKey()); + log.trace("************* finished to create node {}", nodeTypeEntry.getKey()); + } + } + Map<String, Object> mappedToscaTemplate = null; + if (org.apache.commons.lang.StringUtils.isNotEmpty(nodeName) && MapUtils.isNotEmpty(nodeTypesInfo) + && nodeTypesInfo.containsKey(nodeName)) { + mappedToscaTemplate = nodeTypesInfo.get(nodeName).getMappedToscaTemplate(); + } + if (MapUtils.isEmpty(mappedToscaTemplate)) { + mappedToscaTemplate = (Map<String, Object>) new Yaml().load(topologyTemplateYaml); + } + createResourcesFromYamlNodeTypesList(yamlName, resource, mappedToscaTemplate, needLock, nodeTypesArtifactsToHandle, + nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo); + } catch (ComponentException e) { + ResponseFormat responseFormat = e.getResponseFormat() != null ? e.getResponseFormat() + : componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams()); + componentsUtils.auditResource(responseFormat, csarInfo.getModifier(), resource, AuditingActionEnum.IMPORT_RESOURCE); + throw e; + } catch (StorageException e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(e.getStorageOperationStatus())); + componentsUtils.auditResource(responseFormat, csarInfo.getModifier(), resource, AuditingActionEnum.IMPORT_RESOURCE); + throw e; + }catch (Exception e){ + log.debug("Exception occured when handleNodeTypes, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected Resource handleNestedVfc(Resource resource, Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodesArtifactsToHandle, + List<ArtifactDefinition> createdArtifacts, Map<String, NodeTypeInfo> nodesInfo, CsarInfo csarInfo, + String nodeName) { + String yamlName = nodesInfo.get(nodeName).getTemplateFileName(); + Map<String, Object> nestedVfcJsonMap = nodesInfo.get(nodeName).getMappedToscaTemplate(); + + log.debug("************* Going to create node types from yaml {}", yamlName); + createResourcesFromYamlNodeTypesList(yamlName, resource, nestedVfcJsonMap, false, + nodesArtifactsToHandle, createdArtifacts, nodesInfo, csarInfo); + + if (nestedVfcJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE.getElementName())) { + log.debug("************* Going to handle complex VFC from yaml {}", yamlName); + resource = handleComplexVfc(resource, nodesArtifactsToHandle, createdArtifacts, nodesInfo, + csarInfo, nodeName, yamlName); + } + return resource; + } + + protected Resource handleComplexVfc(Resource resource, Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodesArtifactsToHandle, + List<ArtifactDefinition> createdArtifacts, Map<String, NodeTypeInfo> nodesInfo, CsarInfo csarInfo, + String nodeName, String yamlName) { + Resource oldComplexVfc = null; + Resource newComplexVfc = serviceImportParseLogic.buildValidComplexVfc(resource, csarInfo, nodeName, nodesInfo); + Either<Resource, StorageOperationStatus> oldComplexVfcRes = toscaOperationFacade + .getFullLatestComponentByToscaResourceName(newComplexVfc.getToscaResourceName()); + if (oldComplexVfcRes.isRight() && oldComplexVfcRes.right().value() == StorageOperationStatus.NOT_FOUND) { + oldComplexVfcRes = toscaOperationFacade.getFullLatestComponentByToscaResourceName( + serviceImportParseLogic.buildNestedToscaResourceName(ResourceTypeEnum.VF.name(), csarInfo.getVfResourceName(), + nodeName).getRight()); + } + if (oldComplexVfcRes.isRight() && oldComplexVfcRes.right().value() != StorageOperationStatus.NOT_FOUND) { + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } else if (oldComplexVfcRes.isLeft()) { + log.debug(VALIDATE_DERIVED_BEFORE_UPDATE); + Either<Boolean, ResponseFormat> eitherValidation = serviceImportParseLogic.validateNestedDerivedFromDuringUpdate( + oldComplexVfcRes.left().value(), newComplexVfc, + ValidationUtils.hasBeenCertified(oldComplexVfcRes.left().value().getVersion())); + if (eitherValidation.isLeft()) { + oldComplexVfc = oldComplexVfcRes.left().value(); + } + } + newComplexVfc = handleComplexVfc(nodesArtifactsToHandle, createdArtifacts, nodesInfo, csarInfo, nodeName, yamlName, + oldComplexVfc, newComplexVfc); + csarInfo.getCreatedNodesToscaResourceNames().put(nodeName, newComplexVfc.getToscaResourceName()); + LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction( + CERTIFICATION_ON_IMPORT, LifecycleChangeInfoWithAction.LifecycleChanceActionEnum.CREATE_FROM_CSAR); + log.debug("Going to certify cvfc {}. ", newComplexVfc.getName()); + final Resource result = serviceImportParseLogic + .propagateStateToCertified(csarInfo.getModifier(), newComplexVfc, lifecycleChangeInfo, true, false, + true); + csarInfo.getCreatedNodes().put(nodeName, result); + csarInfo.removeNodeFromQueue(); + return result; + } + + public Map<String, Resource> createResourcesFromYamlNodeTypesList(String yamlName, Resource resource, Map<String, Object> mappedToscaTemplate, boolean needLock, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle, + List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, Map<String, NodeTypeInfo> nodeTypesInfo, + CsarInfo csarInfo) { + Either<String, ImportUtils.ResultStatusEnum> toscaVersion = findFirstToscaStringElement(mappedToscaTemplate, + TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION); + if (toscaVersion.isRight()) { + throw new ComponentException(ActionStatus.INVALID_TOSCA_TEMPLATE); + } + Map<String, Object> mapToConvert = new HashMap<>(); + mapToConvert.put(TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION.getElementName(), toscaVersion.left().value()); + Map<String, Object> nodeTypes = serviceImportParseLogic.getNodeTypesFromTemplate(mappedToscaTemplate); + createNodeTypes(yamlName, resource, needLock, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, mapToConvert, nodeTypes); + return csarInfo.getCreatedNodes(); + } + + protected void createNodeTypes(String yamlName, Resource resource, boolean needLock, Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle, List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, Map<String, Object> mapToConvert, Map<String, Object> nodeTypes) { + Iterator<Map.Entry<String, Object>> nodesNameValueIter = nodeTypes.entrySet().iterator(); + Resource vfcCreated = null; + while (nodesNameValueIter.hasNext()) { + Map.Entry<String, Object> nodeType = nodesNameValueIter.next(); + Map<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> nodeTypeArtifactsToHandle = nodeTypesArtifactsToHandle == null + || nodeTypesArtifactsToHandle.isEmpty() ? null + : nodeTypesArtifactsToHandle.get(nodeType.getKey()); + + if (nodeTypesInfo.containsKey(nodeType.getKey())) { + log.trace("************* Going to handle nested vfc {}", nodeType.getKey()); + vfcCreated = handleNestedVfc(resource, + nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, + nodeType.getKey()); + log.trace("************* Finished to handle nested vfc {}", nodeType.getKey()); + } else if (csarInfo.getCreatedNodesToscaResourceNames() != null + && !csarInfo.getCreatedNodesToscaResourceNames().containsKey(nodeType.getKey())) { + log.trace("************* Going to create node {}", nodeType.getKey()); + ImmutablePair<Resource, ActionStatus> resourceCreated = createNodeTypeResourceFromYaml(yamlName, nodeType, csarInfo.getModifier(), mapToConvert, + resource, needLock, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts, true, + csarInfo, true); + log.debug("************* Finished to create node {}", nodeType.getKey()); + + vfcCreated = resourceCreated.getLeft(); + csarInfo.getCreatedNodesToscaResourceNames().put(nodeType.getKey(), + vfcCreated.getToscaResourceName()); + } + if (vfcCreated != null) { + csarInfo.getCreatedNodes().put(nodeType.getKey(), vfcCreated); + } + mapToConvert.remove(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName()); + } + } + + protected ImmutablePair<Resource, ActionStatus> createNodeTypeResourceFromYaml( + String yamlName, Map.Entry<String, Object> nodeNameValue, User user, Map<String, Object> mapToConvert, + Resource resourceVf, boolean needLock, + Map<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> nodeTypeArtifactsToHandle, + List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, boolean forceCertificationAllowed, CsarInfo csarInfo, + boolean isNested) { + UploadResourceInfo resourceMetaData = serviceImportParseLogic + .fillResourceMetadata(yamlName, resourceVf, nodeNameValue.getKey(), user); + + 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, nodeTypesNewCreatedArtifacts, forceCertificationAllowed, csarInfo, + nodeNameValue.getKey(), isNested); + } + + protected Service createRIAndRelationsFromYaml(String yamlName, Service service, + Map<String, UploadComponentInstanceInfo> uploadComponentInstanceInfoMap, + String topologyTemplateYaml, List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, + Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate, + String nodeName) { + log.debug("************* Going to create all nodes {}", yamlName); + handleServiceNodeTypes(yamlName, service, topologyTemplateYaml, false, nodeTypesArtifactsToCreate, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeName); + 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); + log.debug("************* Going to create positions {}", yamlName); + compositionBusinessLogic.setPositionsForComponentInstances(service, csarInfo.getModifier().getUserId()); + log.debug("************* Finished to set positions {}", yamlName); + return service; + } + + protected Service createServiceInstancesRelations(User user, String yamlName, Service service, + Map<String, UploadComponentInstanceInfo> uploadResInstancesMap) { + log.debug("#createResourceInstancesRelations - Going to create relations "); + List<ComponentInstance> componentInstancesList = service.getComponentInstances(); + 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().logInternalDataError("createResourceInstancesRelations", "No instances found in a resource or nn yaml template. ", BeEcompErrorManager.ErrorSeverity.ERROR); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName)); + } + Map<String, List<ComponentInstanceProperty>> instProperties = new HashMap<>(); + Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> instCapabilities = new HashMap<>(); + Map<ComponentInstance, Map<String, List<RequirementDefinition>>> instRequirements = new HashMap<>(); + Map<String, Map<String, ArtifactDefinition>> instDeploymentArtifacts = new HashMap<>(); + Map<String, Map<String, ArtifactDefinition>> instArtifacts = new HashMap<>(); + Map<String, List<AttributeDataDefinition>> instAttributes = new HashMap<>(); + Map<String, Resource> originCompMap = new HashMap<>(); + List<RequirementCapabilityRelDef> relations = new ArrayList<>(); + Map<String, List<ComponentInstanceInput>> instInputs = new HashMap<>(); + + log.debug("enter ServiceImportBusinessLogic createServiceInstancesRelations#createResourceInstancesRelations - Before get all datatypes. "); + Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes = serviceBusinessLogic.dataTypeCache.getAll(); + if (allDataTypes.isRight()) { + JanusGraphOperationStatus status = allDataTypes.right().value(); + BeEcompErrorManager.getInstance().logInternalFlowError("UpdatePropertyValueOnComponentInstance", + "Failed to update property value on instance. Status is " + status, BeEcompErrorManager.ErrorSeverity.ERROR); + throw new ComponentException(componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse( + DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status)), yamlName)); + } + Service finalResource = service; + uploadResInstancesMap + .values() + .forEach(i -> processComponentInstance(yamlName, finalResource, componentInstancesList, allDataTypes, + instProperties, instCapabilities, instRequirements, instDeploymentArtifacts, + instArtifacts, instAttributes, originCompMap, instInputs, i)); + serviceImportParseLogic.associateComponentInstancePropertiesToComponent(yamlName, service, instProperties); + serviceImportParseLogic.associateComponentInstanceInputsToComponent(yamlName, service, instInputs); + serviceImportParseLogic.associateDeploymentArtifactsToInstances(user, yamlName, service, instDeploymentArtifacts); + serviceImportParseLogic.associateArtifactsToInstances(yamlName, service, instArtifacts); + serviceImportParseLogic.associateOrAddCalculatedCapReq(yamlName, service, instCapabilities, instRequirements); + log.debug("enter createServiceInstancesRelations test,instRequirements:{},instCapabilities:{}", + instRequirements, instCapabilities); + serviceImportParseLogic.associateInstAttributeToComponentToInstances(yamlName, service, instAttributes); + ToscaElement serviceTemplate = ModelConverter.convertToToscaElement(service); + Map<String, ListCapabilityDataDefinition> capabilities = serviceTemplate.getCapabilities(); + Map<String, ListRequirementDataDefinition> requirements = serviceTemplate.getRequirements(); + + serviceImportParseLogic.associateCapabilitiesToService(yamlName, service, capabilities); + serviceImportParseLogic.associateRequirementsToService(yamlName, service, requirements); + 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<Service, StorageOperationStatus> eitherGetResource = toscaOperationFacade.getToscaElement(service.getUniqueId()); + log.debug("************* in create relations, getResource end"); + if (eitherGetResource.isRight()) { + throw new ComponentException(componentsUtils.getResponseFormatByComponent( + componentsUtils.convertFromStorageResponse(eitherGetResource.right().value()), service, service.getComponentType())); + } + return eitherGetResource.left().value(); + } + + protected void processComponentInstance(String yamlName, Service service, List<ComponentInstance> componentInstancesList, Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes, Map<String, List<ComponentInstanceProperty>> instProperties, Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> instCapabilties, Map<ComponentInstance, Map<String, List<RequirementDefinition>>> instRequirements, Map<String, Map<String, ArtifactDefinition>> instDeploymentArtifacts, Map<String, Map<String, ArtifactDefinition>> instArtifacts, Map<String, List<AttributeDataDefinition>> instAttributes, Map<String, Resource> originCompMap, Map<String, List<ComponentInstanceInput>> instInputs, UploadComponentInstanceInfo uploadComponentInstanceInfo) { + log.debug("enter ServiceImportBusinessLogic processComponentInstance"); + Optional<ComponentInstance> currentCompInstanceOpt = componentInstancesList.stream() + .filter(i -> i.getName().equals(uploadComponentInstanceInfo.getName())) + .findFirst(); + if (!currentCompInstanceOpt.isPresent()) { + log.debug(COMPONENT_INSTANCE_WITH_NAME_IN_RESOURCE, uploadComponentInstanceInfo.getName(), + service.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError( + COMPONENT_INSTANCE_WITH_NAME + uploadComponentInstanceInfo.getName() + IN_RESOURCE, + service.getUniqueId(), BeEcompErrorManager.ErrorSeverity.ERROR); + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + throw new ComponentException(responseFormat); + } + ComponentInstance currentCompInstance = currentCompInstanceOpt.get(); + String resourceInstanceId = currentCompInstance.getUniqueId(); + Resource originResource = getOriginResource(yamlName, originCompMap, currentCompInstance); + + if (MapUtils.isNotEmpty(originResource.getRequirements())) { + instRequirements.put(currentCompInstance, originResource.getRequirements()); + } + if (MapUtils.isNotEmpty(originResource.getCapabilities())) { + processComponentInstanceCapabilities(allDataTypes, instCapabilties, uploadComponentInstanceInfo, + currentCompInstance, originResource); + } + if (originResource.getDeploymentArtifacts() != null && !originResource.getDeploymentArtifacts().isEmpty()) { + instDeploymentArtifacts.put(resourceInstanceId, originResource.getDeploymentArtifacts()); + } + if (originResource.getArtifacts() != null && !originResource.getArtifacts().isEmpty()) { + instArtifacts.put(resourceInstanceId, originResource.getArtifacts()); + } + if (originResource.getAttributes() != null && !originResource.getAttributes().isEmpty()) { + instAttributes.put(resourceInstanceId, originResource.getAttributes()); + } + if (originResource.getResourceType() != ResourceTypeEnum.VF) { + ResponseFormat addPropertiesValueToRiRes = addPropertyValuesToRi(uploadComponentInstanceInfo, service, + originResource, currentCompInstance, instProperties, allDataTypes.left().value()); + if (addPropertiesValueToRiRes.getStatus() != 200) { + throw new ComponentException(addPropertiesValueToRiRes); + } + } else { + addInputsValuesToRi(uploadComponentInstanceInfo, service, + originResource, currentCompInstance, instInputs, allDataTypes.left().value()); + } + } + + protected void addInputsValuesToRi(UploadComponentInstanceInfo uploadComponentInstanceInfo, + Service resource, Resource originResource, ComponentInstance currentCompInstance, + Map<String, List<ComponentInstanceInput>> instInputs, Map<String, DataTypeDefinition> allDataTypes) { + Map<String, List<UploadPropInfo>> propMap = uploadComponentInstanceInfo.getProperties(); + if (MapUtils.isNotEmpty(propMap)) { + Map<String, InputDefinition> currPropertiesMap = new HashMap<>(); + List<ComponentInstanceInput> instPropList = new ArrayList<>(); + + if (CollectionUtils.isEmpty(originResource.getInputs())) { + log.debug("failed to find properties "); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND)); + } + originResource.getInputs().forEach(p -> serviceImportParseLogic.addInput(currPropertiesMap, p)); + for (List<UploadPropInfo> propertyList : propMap.values()) { + processProperty(resource, currentCompInstance, allDataTypes, currPropertiesMap, instPropList, propertyList); + } + currPropertiesMap.values().forEach(p -> instPropList.add(new ComponentInstanceInput(p))); + instInputs.put(currentCompInstance.getUniqueId(), instPropList); + } + } + + protected void processProperty(Service resource, ComponentInstance currentCompInstance, Map<String, DataTypeDefinition> allDataTypes, Map<String, InputDefinition> currPropertiesMap, List<ComponentInstanceInput> instPropList, List<UploadPropInfo> propertyList) { + UploadPropInfo propertyInfo = propertyList.get(0); + String propName = propertyInfo.getName(); + if (!currPropertiesMap.containsKey(propName)) { + log.debug("failed to find property {} ", propName); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, + propName)); + } + InputDefinition curPropertyDef = currPropertiesMap.get(propName); + ComponentInstanceInput property = null; + + String value = null; + List<GetInputValueDataDefinition> getInputs = null; + boolean isValidate = true; + if (propertyInfo.getValue() != null) { + getInputs = propertyInfo.getGet_input(); + isValidate = getInputs == null || getInputs.isEmpty(); + if (isValidate) { + value = getPropertyJsonStringValue(propertyInfo.getValue(), + curPropertyDef.getType()); + } else { + value = getPropertyJsonStringValue(propertyInfo.getValue(), + TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName()); + } + } + String innerType = null; + property = new ComponentInstanceInput(curPropertyDef, value, null); + String validPropertyVAlue = serviceBusinessLogic.validatePropValueBeforeCreate(property, value, isValidate, allDataTypes); + property.setValue(validPropertyVAlue); + + if (isNotEmpty(getInputs)) { + List<GetInputValueDataDefinition> getInputValues = new ArrayList<>(); + for (GetInputValueDataDefinition getInput : getInputs) { + List<InputDefinition> inputs = resource.getInputs(); + if (CollectionUtils.isEmpty(inputs)) { + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + Optional<InputDefinition> optional = inputs.stream() + .filter(p -> p.getName().equals(getInput.getInputName())).findAny(); + if (!optional.isPresent()) { + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + InputDefinition input = optional.get(); + getInput.setInputId(input.getUniqueId()); + getInputValues.add(getInput); + + GetInputValueDataDefinition getInputIndex = getInput.getGetInputIndex(); + processGetInput(getInputValues, inputs, getInputIndex); + } + property.setGetInputValues(getInputValues); + } + instPropList.add(property); + currPropertiesMap.remove(property.getName()); + } + + protected void processGetInput(List<GetInputValueDataDefinition> getInputValues, List<InputDefinition> inputs, GetInputValueDataDefinition getInputIndex) { + Optional<InputDefinition> optional; + if (getInputIndex != null) { + optional = inputs.stream().filter(p -> p.getName().equals(getInputIndex.getInputName())) + .findAny(); + if (!optional.isPresent()) { + log.debug("Failed to find input {} ", getInputIndex.getInputName()); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT)); + } + InputDefinition inputIndex = optional.get(); + getInputIndex.setInputId(inputIndex.getUniqueId()); + getInputValues.add(getInputIndex); + } + } + + protected ResponseFormat addPropertyValuesToRi(UploadComponentInstanceInfo uploadComponentInstanceInfo, + Resource resource, Resource originResource, ComponentInstance currentCompInstance, + Map<String, List<ComponentInstanceProperty>> instProperties, Map<String, DataTypeDefinition> allDataTypes) { + Map<String, List<UploadPropInfo>> propMap = uploadComponentInstanceInfo.getProperties(); + Map<String, PropertyDefinition> currPropertiesMap = new HashMap<>(); + + List<PropertyDefinition> listFromMap = originResource.getProperties(); + if ((propMap != null && !propMap.isEmpty()) && (listFromMap == null || listFromMap.isEmpty())) { + log.debug("failed to find properties "); + return componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND); + } + if (listFromMap == null || listFromMap.isEmpty()) { + return componentsUtils.getResponseFormat(ActionStatus.OK); + } + for (PropertyDefinition prop : listFromMap) { + String propName = prop.getName(); + if (!currPropertiesMap.containsKey(propName)) { + currPropertiesMap.put(propName, prop); + } + } + List<ComponentInstanceProperty> instPropList = new ArrayList<>(); + if (propMap != null && propMap.size() > 0) { + for (List<UploadPropInfo> propertyList : propMap.values()) { + UploadPropInfo propertyInfo = propertyList.get(0); + String propName = propertyInfo.getName(); + if (!currPropertiesMap.containsKey(propName)) { + log.debug("failed to find property {} ", propName); + return componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, + propName); + } + PropertyDefinition curPropertyDef = currPropertiesMap.get(propName); + ComponentInstanceProperty property = null; + + String value = null; + List<GetInputValueDataDefinition> getInputs = null; + boolean isValidate = true; + if (propertyInfo.getValue() != null) { + getInputs = propertyInfo.getGet_input(); + isValidate = getInputs == null || getInputs.isEmpty(); + if (isValidate) { + value = getPropertyJsonStringValue(propertyInfo.getValue(), + curPropertyDef.getType()); + } else { + value = getPropertyJsonStringValue(propertyInfo.getValue(), + TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName()); + } + } + String innerType = null; + property = new ComponentInstanceProperty(curPropertyDef, value, null); + + String validatePropValue = serviceBusinessLogic.validatePropValueBeforeCreate(property, value, isValidate, allDataTypes); + property.setValue(validatePropValue); + + if (getInputs != null && !getInputs.isEmpty()) { + List<GetInputValueDataDefinition> getInputValues = new ArrayList<>(); + for (GetInputValueDataDefinition getInput : getInputs) { + List<InputDefinition> inputs = resource.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, property.getGetInputValues() + .stream() + .map(GetInputValueDataDefinition::getInputName) + .collect(toList()).toString()); + } + InputDefinition input = serviceImportParseLogic.findInputByName(inputs, getInput); + getInput.setInputId(input.getUniqueId()); + getInputValues.add(getInput); + + GetInputValueDataDefinition getInputIndex = getInput.getGetInputIndex(); + if (getInputIndex != null) { + input = serviceImportParseLogic.findInputByName(inputs, getInputIndex); + getInputIndex.setInputId(input.getUniqueId()); + getInputValues.add(getInputIndex); + } + } + property.setGetInputValues(getInputValues); + } + instPropList.add(property); + currPropertiesMap.remove(property.getName()); + } + } + if (!currPropertiesMap.isEmpty()) { + for (PropertyDefinition value : currPropertiesMap.values()) { + instPropList.add(new ComponentInstanceProperty(value)); + } + } + instProperties.put(currentCompInstance.getUniqueId(), instPropList); + return componentsUtils.getResponseFormat(ActionStatus.OK); + } + + protected ResponseFormat addPropertyValuesToRi(UploadComponentInstanceInfo uploadComponentInstanceInfo, + Service service, Resource originResource, ComponentInstance currentCompInstance, + Map<String, List<ComponentInstanceProperty>> instProperties, Map<String, DataTypeDefinition> allDataTypes) { + Map<String, List<UploadPropInfo>> propMap = uploadComponentInstanceInfo.getProperties(); + Map<String, PropertyDefinition> currPropertiesMap = new HashMap<>(); + + List<PropertyDefinition> listFromMap = originResource.getProperties(); + if ((propMap != null && !propMap.isEmpty()) && (listFromMap == null || listFromMap.isEmpty())) { + log.debug("failed to find properties "); + return componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND); + } + if (listFromMap == null || listFromMap.isEmpty()) { + return componentsUtils.getResponseFormat(ActionStatus.OK); + } + for (PropertyDefinition prop : listFromMap) { + String propName = prop.getName(); + if (!currPropertiesMap.containsKey(propName)) { + currPropertiesMap.put(propName, prop); + } + } + List<ComponentInstanceProperty> instPropList = new ArrayList<>(); + if (propMap != null && propMap.size() > 0) { + for (List<UploadPropInfo> propertyList : propMap.values()) { + + UploadPropInfo propertyInfo = propertyList.get(0); + String propName = propertyInfo.getName(); + if (!currPropertiesMap.containsKey(propName)) { + log.debug("failed to find property {} ", propName); + return componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, + propName); + } + PropertyDefinition curPropertyDef = currPropertiesMap.get(propName); + ComponentInstanceProperty property = null; + + String value = null; + List<GetInputValueDataDefinition> getInputs = null; + boolean isValidate = true; + if (propertyInfo.getValue() != null) { + getInputs = propertyInfo.getGet_input(); + isValidate = getInputs == null || getInputs.isEmpty(); + if (isValidate) { + value = getPropertyJsonStringValue(propertyInfo.getValue(), + curPropertyDef.getType()); + } else { + value = getPropertyJsonStringValue(propertyInfo.getValue(), + TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName()); + } + } + String innerType = null; + property = new ComponentInstanceProperty(curPropertyDef, value, null); + + String validatePropValue = serviceBusinessLogic.validatePropValueBeforeCreate(property, value, isValidate, allDataTypes); + property.setValue(validatePropValue); + + if (getInputs != null && !getInputs.isEmpty()) { + List<GetInputValueDataDefinition> getInputValues = new ArrayList<>(); + for (GetInputValueDataDefinition getInput : getInputs) { + List<InputDefinition> inputs = service.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, property.getGetInputValues() + .stream() + .map(GetInputValueDataDefinition::getInputName) + .collect(toList()).toString()); + } + InputDefinition input = serviceImportParseLogic.findInputByName(inputs, getInput); + getInput.setInputId(input.getUniqueId()); + getInputValues.add(getInput); + + GetInputValueDataDefinition getInputIndex = getInput.getGetInputIndex(); + if (getInputIndex != null) { + input = serviceImportParseLogic.findInputByName(inputs, getInputIndex); + getInputIndex.setInputId(input.getUniqueId()); + getInputValues.add(getInputIndex); + } + } + property.setGetInputValues(getInputValues); + } + instPropList.add(property); + currPropertiesMap.remove(property.getName()); + } + } + if (!currPropertiesMap.isEmpty()) { + for (PropertyDefinition value : currPropertiesMap.values()) { + instPropList.add(new ComponentInstanceProperty(value)); + } + } + instProperties.put(currentCompInstance.getUniqueId(), instPropList); + return componentsUtils.getResponseFormat(ActionStatus.OK); + } + + protected void processComponentInstanceCapabilities(Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes, Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> instCapabilties, UploadComponentInstanceInfo uploadComponentInstanceInfo, ComponentInstance currentCompInstance, Resource originResource) { + log.debug("enter processComponentInstanceCapabilities"); + Map<String, List<CapabilityDefinition>> originCapabilities; + if (MapUtils.isNotEmpty(uploadComponentInstanceInfo.getCapabilities())) { + originCapabilities = new HashMap<>(); + Map<String, Map<String, UploadPropInfo>> newPropertiesMap = new HashMap<>(); + originResource.getCapabilities().forEach((k, v) -> serviceImportParseLogic + .addCapabilities(originCapabilities, k, v)); + uploadComponentInstanceInfo.getCapabilities().values().forEach(l -> serviceImportParseLogic + .addCapabilitiesProperties(newPropertiesMap, l)); + updateCapabilityPropertiesValues(allDataTypes, originCapabilities, newPropertiesMap); + } else { + originCapabilities = originResource.getCapabilities(); + } + instCapabilties.put(currentCompInstance, originCapabilities); + } + + protected void updateCapabilityPropertiesValues(Either<Map<String, DataTypeDefinition>, JanusGraphOperationStatus> allDataTypes, Map<String, List<CapabilityDefinition>> originCapabilities, Map<String, Map<String, UploadPropInfo>> newPropertiesMap) { + originCapabilities.values().stream() + .flatMap(Collection::stream) + .filter(c -> newPropertiesMap.containsKey(c.getName())) + .forEach(c -> updatePropertyValues(c.getProperties(), newPropertiesMap.get(c.getName()), allDataTypes.left().value())); + } + + protected void updatePropertyValues(List<ComponentInstanceProperty> properties, Map<String, UploadPropInfo> newProperties, + Map<String, DataTypeDefinition> allDataTypes) { + properties.forEach(p -> updatePropertyValue(p, newProperties.get(p.getName()), allDataTypes)); + } + + protected String updatePropertyValue(ComponentInstanceProperty property, UploadPropInfo propertyInfo, + Map<String, DataTypeDefinition> allDataTypes) { + String value = null; + List<GetInputValueDataDefinition> getInputs = null; + boolean isValidate = true; + if (null != propertyInfo && propertyInfo.getValue() != null) { + getInputs = propertyInfo.getGet_input(); + isValidate = getInputs == null || getInputs.isEmpty(); + if (isValidate) { + value = getPropertyJsonStringValue(propertyInfo.getValue(), property.getType()); + } else { + value = getPropertyJsonStringValue(propertyInfo.getValue(), + TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName()); + } + } + property.setValue(value); + return serviceBusinessLogic.validatePropValueBeforeCreate(property, value, isValidate, allDataTypes); + } + + protected Resource getOriginResource(String yamlName, Map<String, Resource> originCompMap, ComponentInstance currentCompInstance) { + Resource originResource; + log.debug("after enter ServiceImportBusinessLogic processComponentInstance, enter getOriginResource"); + if (!originCompMap.containsKey(currentCompInstance.getComponentUid())) { + Either<Resource, StorageOperationStatus> getOriginResourceRes = toscaOperationFacade + .getToscaFullElement(currentCompInstance.getComponentUid()); + if (getOriginResourceRes.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(getOriginResourceRes.right().value()), yamlName); + throw new ComponentException(responseFormat); + } + originResource = getOriginResourceRes.left().value(); + originCompMap.put(originResource.getUniqueId(), originResource); + } else { + originResource = originCompMap.get(currentCompInstance.getComponentUid()); + } + return originResource; + } + + protected void handleSubstitutionMappings(Service service, Map<String, UploadComponentInstanceInfo> uploadResInstancesMap) { + if (false) { + Either<Resource, StorageOperationStatus> 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<Resource, StorageOperationStatus> updateCalculatedCapReqWithSubstitutionMappings(Resource resource, + Map<String, UploadComponentInstanceInfo> uploadResInstancesMap) { + Either<Resource, StorageOperationStatus> updateRes = null; + Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> updatedInstCapabilities = new HashMap<>(); + Map<ComponentInstance, Map<String, List<RequirementDefinition>>> updatedInstRequirements = new HashMap<>(); + StorageOperationStatus status = toscaOperationFacade + .deleteAllCalculatedCapabilitiesRequirements(resource.getUniqueId()); + if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) { + log.debug( + "Failed to delete all calculated capabilities and requirements of resource {} upon update. Status is {}", + resource.getUniqueId(), status); + updateRes = Either.right(status); + } + if (updateRes == null) { + fillUpdatedInstCapabilitiesRequirements(resource.getComponentInstances(), uploadResInstancesMap, + updatedInstCapabilities, updatedInstRequirements); + status = toscaOperationFacade.associateOrAddCalculatedCapReq(updatedInstCapabilities, updatedInstRequirements, + resource); + if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) { + updateRes = Either.right(status); + } + } + if (updateRes == null) { + updateRes = Either.left(resource); + } + return updateRes; + } + + protected void fillUpdatedInstCapabilitiesRequirements(List<ComponentInstance> componentInstances, + Map<String, UploadComponentInstanceInfo> uploadResInstancesMap, + Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> updatedInstCapabilities, + Map<ComponentInstance, Map<String, List<RequirementDefinition>>> updatedInstRequirements) { + componentInstances.stream().forEach(i -> { + fillUpdatedInstCapabilities(updatedInstCapabilities, i, + uploadResInstancesMap.get(i.getName()).getCapabilitiesNamesToUpdate()); + fillUpdatedInstRequirements(updatedInstRequirements, i, + uploadResInstancesMap.get(i.getName()).getRequirementsNamesToUpdate()); + }); + } + + protected void fillUpdatedInstCapabilities( + Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> updatedInstCapabilties, + ComponentInstance instance, Map<String, String> capabilitiesNamesToUpdate) { + Map<String, List<CapabilityDefinition>> updatedCapabilities = new HashMap<>(); + Set<String> updatedCapNames = new HashSet<>(); + if (MapUtils.isNotEmpty(capabilitiesNamesToUpdate)) { + for (Map.Entry<String, List<CapabilityDefinition>> requirements : instance.getCapabilities().entrySet()) { + updatedCapabilities.put(requirements.getKey(), + requirements.getValue().stream() + .filter(c -> capabilitiesNamesToUpdate.containsKey(c.getName()) + && !updatedCapNames.contains(capabilitiesNamesToUpdate.get(c.getName()))) + .map(c -> { + c.setParentName(c.getName()); + c.setName(capabilitiesNamesToUpdate.get(c.getName())); + updatedCapNames.add(c.getName()); + return c; + }).collect(toList())); + } + } + if (MapUtils.isNotEmpty(updatedCapabilities)) { + updatedInstCapabilties.put(instance, updatedCapabilities); + } + } + + protected void fillUpdatedInstRequirements( + Map<ComponentInstance, Map<String, List<RequirementDefinition>>> updatedInstRequirements, + ComponentInstance instance, Map<String, String> requirementsNamesToUpdate) { + Map<String, List<RequirementDefinition>> updatedRequirements = new HashMap<>(); + Set<String> updatedReqNames = new HashSet<>(); + if (MapUtils.isNotEmpty(requirementsNamesToUpdate)) { + for (Map.Entry<String, List<RequirementDefinition>> requirements : instance.getRequirements().entrySet()) { + updatedRequirements.put(requirements.getKey(), + requirements.getValue().stream() + .filter(r -> requirementsNamesToUpdate.containsKey(r.getName()) + && !updatedReqNames.contains(requirementsNamesToUpdate.get(r.getName()))) + .map(r -> { + r.setParentName(r.getName()); + r.setName(requirementsNamesToUpdate.get(r.getName())); + updatedReqNames.add(r.getName()); + return r; + }).collect(toList())); + } + } + if (MapUtils.isNotEmpty(updatedRequirements)) { + updatedInstRequirements.put(instance, updatedRequirements); + } + } + + protected void addRelationsToRI(String yamlName, Service service, Map<String, UploadComponentInstanceInfo> uploadResInstancesMap, List<ComponentInstance> componentInstancesList, List<RequirementCapabilityRelDef> relations) { + for (Map.Entry<String, UploadComponentInstanceInfo> entry : uploadResInstancesMap.entrySet()) { + UploadComponentInstanceInfo uploadComponentInstanceInfo = entry.getValue(); + ComponentInstance currentCompInstance = null; + for (ComponentInstance compInstance : componentInstancesList) { + if (compInstance.getName().equals(uploadComponentInstanceInfo.getName())) { + currentCompInstance = compInstance; + break; + } + } + if (currentCompInstance == null) { + log.debug(COMPONENT_INSTANCE_WITH_NAME_IN_RESOURCE, uploadComponentInstanceInfo.getName(), + service.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError( + COMPONENT_INSTANCE_WITH_NAME + uploadComponentInstanceInfo.getName() + IN_RESOURCE, + service.getUniqueId(), BeEcompErrorManager.ErrorSeverity.ERROR); + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + throw new ComponentException(responseFormat); + } + + ResponseFormat addRelationToRiRes = addRelationToRI(yamlName, service, entry.getValue(), relations); + if (addRelationToRiRes.getStatus() != 200) { + throw new ComponentException(addRelationToRiRes); + } + } + } + + protected ResponseFormat addRelationToRI(String yamlName, Service service, + UploadComponentInstanceInfo nodesInfoValue, List<RequirementCapabilityRelDef> relations) { + List<ComponentInstance> componentInstancesList = service.getComponentInstances(); + ComponentInstance currentCompInstance = null; + for (ComponentInstance compInstance : componentInstancesList) { + if (compInstance.getName().equals(nodesInfoValue.getName())) { + currentCompInstance = compInstance; + break; + } + } + if (currentCompInstance == null) { + log.debug(COMPONENT_INSTANCE_WITH_NAME_IN_RESOURCE, nodesInfoValue.getName(), + service.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError( + COMPONENT_INSTANCE_WITH_NAME + nodesInfoValue.getName() + IN_RESOURCE, + service.getUniqueId(), BeEcompErrorManager.ErrorSeverity.ERROR); + return componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, + yamlName); + } + String resourceInstanceId = currentCompInstance.getUniqueId(); + Map<String, List<UploadReqInfo>> regMap = nodesInfoValue.getRequirements(); + + if (regMap != null) { + Iterator<Map.Entry<String, List<UploadReqInfo>>> nodesRegValue = regMap.entrySet().iterator(); + while (nodesRegValue.hasNext()) { + Map.Entry<String, List<UploadReqInfo>> nodesRegInfoEntry = nodesRegValue.next(); + List<UploadReqInfo> uploadRegInfoList = nodesRegInfoEntry.getValue(); + for (UploadReqInfo uploadRegInfo : uploadRegInfoList) { + log.debug("Going to create relation {}", uploadRegInfo.getName()); + String regName = uploadRegInfo.getName(); + RequirementCapabilityRelDef regCapRelDef = new RequirementCapabilityRelDef(); + regCapRelDef.setFromNode(resourceInstanceId); + log.debug("try to find available requirement {} ", regName); + Either<RequirementDefinition, ResponseFormat> eitherReqStatus = serviceImportParseLogic.findAviableRequiremen(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(); + } + + RequirementDefinition validReq = eitherReqStatus.left().value(); + List<CapabilityRequirementRelationship> reqAndRelationshipPairList = regCapRelDef + .getRelationships(); + if (reqAndRelationshipPairList == null) { + reqAndRelationshipPairList = new ArrayList<>(); + } + RelationshipInfo reqAndRelationshipPair = new RelationshipInfo(); + reqAndRelationshipPair.setRequirement(regName); + reqAndRelationshipPair.setRequirementOwnerId(validReq.getOwnerId()); + reqAndRelationshipPair.setRequirementUid(validReq.getUniqueId()); + RelationshipImpl relationship = new RelationshipImpl(); + relationship.setType(validReq.getCapability()); + reqAndRelationshipPair.setRelationships(relationship); + + ComponentInstance currentCapCompInstance = null; + for (ComponentInstance compInstance : componentInstancesList) { + if (compInstance.getName().equals(uploadRegInfo.getNode())) { + currentCapCompInstance = compInstance; + break; + } + } + if (currentCapCompInstance == null) { + log.debug("The component instance with name {} not found on resource {} ", + uploadRegInfo.getNode(), service.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError( + COMPONENT_INSTANCE_WITH_NAME + uploadRegInfo.getNode() + IN_RESOURCE, + service.getUniqueId(), BeEcompErrorManager.ErrorSeverity.ERROR); + return componentsUtils + .getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + } + regCapRelDef.setToNode(currentCapCompInstance.getUniqueId()); + 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); + } + CapabilityRequirementRelationship capReqRel = new CapabilityRequirementRelationship(); + capReqRel.setRelation(reqAndRelationshipPair); + reqAndRelationshipPairList.add(capReqRel); + regCapRelDef.setRelationships(reqAndRelationshipPairList); + relations.add(regCapRelDef); + } + } + } + return componentsUtils.getResponseFormat(ActionStatus.OK, yamlName); + } + + protected Service getResourceAfterCreateRelations(Service service) { + ComponentParametersView parametersView = serviceImportParseLogic.getComponentFilterAfterCreateRelations(); + Either<Service, StorageOperationStatus> eitherGetResource = toscaOperationFacade + .getToscaElement(service.getUniqueId(), parametersView); + if (eitherGetResource.isRight()) { + serviceImportParseLogic.throwComponentExceptionByResource(eitherGetResource.right().value(), service); + } + return eitherGetResource.left().value(); + } + + protected Service createServiceInstances(String yamlName, Service service, + Map<String, UploadComponentInstanceInfo> uploadResInstancesMap, + Map<String, Resource> nodeNamespaceMap) { + Either<Resource, ResponseFormat> eitherResource = null; + log.debug("createResourceInstances is {} - going to create resource instanse from CSAR", yamlName); + if (MapUtils.isEmpty(uploadResInstancesMap)) { // PNF can have no resource instances + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE); + throw new ComponentException(responseFormat); + } + Map<String, Resource> existingNodeTypeMap = new HashMap<>(); + if (MapUtils.isNotEmpty(nodeNamespaceMap)) { + nodeNamespaceMap.forEach((k, v) -> existingNodeTypeMap.put(v.getToscaResourceName(), v)); + } + Map<ComponentInstance, Resource> resourcesInstancesMap = new HashMap<>(); + uploadResInstancesMap + .values() + .forEach(i -> createAndAddResourceInstance(i, yamlName, service, nodeNamespaceMap, existingNodeTypeMap, resourcesInstancesMap)); + + if (MapUtils.isNotEmpty(resourcesInstancesMap)) { + try { + toscaOperationFacade.associateComponentInstancesToComponent(service, + resourcesInstancesMap, false, false); + } catch (StorageException exp) { + if (exp.getStorageOperationStatus() != null && exp.getStorageOperationStatus() != StorageOperationStatus.OK) { + log.debug("Failed to add component instances to container component {}", service.getName()); + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(exp.getStorageOperationStatus())); + eitherResource = Either.right(responseFormat); + throw new ComponentException(eitherResource.right().value()); + } + } + } + Either<Service, StorageOperationStatus> eitherGetResource = toscaOperationFacade + .getToscaElement(service.getUniqueId(), serviceImportParseLogic.getComponentWithInstancesFilter()); + log.debug("*************finished to get resource {}", service.getUniqueId()); + if (eitherGetResource.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByComponent( + componentsUtils.convertFromStorageResponse(eitherGetResource.right().value()), service, ComponentTypeEnum.SERVICE); + throw new ComponentException(responseFormat); + } + if (CollectionUtils.isEmpty(eitherGetResource.left().value().getComponentInstances())) { // PNF can have no resource instances + log.debug("Error when create resource instance from csar. ComponentInstances list empty"); + BeEcompErrorManager.getInstance().logBeDaoSystemError( + "Error when create resource instance from csar. ComponentInstances list empty"); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE)); + } + return eitherGetResource.left().value(); + } + + protected void createAndAddResourceInstance(UploadComponentInstanceInfo uploadComponentInstanceInfo, String yamlName, + Resource resource, Map<String, Resource> nodeNamespaceMap, Map<String, Resource> existingnodeTypeMap, Map<ComponentInstance, Resource> resourcesInstancesMap) { + Either<Resource, ResponseFormat> eitherResource; + log.debug("*************Going to create resource instances {}", uploadComponentInstanceInfo.getName()); + try { + if (nodeNamespaceMap.containsKey(uploadComponentInstanceInfo.getType())) { + uploadComponentInstanceInfo + .setType(nodeNamespaceMap.get(uploadComponentInstanceInfo.getType()).getToscaResourceName()); + } + Resource refResource = validateResourceInstanceBeforeCreate(yamlName, uploadComponentInstanceInfo, + existingnodeTypeMap); + + ComponentInstance componentInstance = new ComponentInstance(); + componentInstance.setComponentUid(refResource.getUniqueId()); + + Collection<String> directives = uploadComponentInstanceInfo.getDirectives(); + if (directives != null && !directives.isEmpty()) { + componentInstance.setDirectives(new ArrayList<>(directives)); + } + UploadNodeFilterInfo uploadNodeFilterInfo = uploadComponentInstanceInfo.getUploadNodeFilterInfo(); + if (uploadNodeFilterInfo != null) { + componentInstance.setNodeFilter(new CINodeFilterUtils().getNodeFilterDataDefinition(uploadNodeFilterInfo, + componentInstance.getUniqueId())); + } + + ComponentTypeEnum containerComponentType = resource.getComponentType(); + NodeTypeEnum containerNodeType = containerComponentType.getNodeType(); + if (containerNodeType.equals(NodeTypeEnum.Resource) + && MapUtils.isNotEmpty(uploadComponentInstanceInfo.getCapabilities()) + && MapUtils.isNotEmpty(refResource.getCapabilities())) { + serviceImportParseLogic.setCapabilityNamesTypes(refResource.getCapabilities(), uploadComponentInstanceInfo.getCapabilities()); + Map<String, List<CapabilityDefinition>> validComponentInstanceCapabilities = serviceImportParseLogic.getValidComponentInstanceCapabilities( + refResource.getUniqueId(), refResource.getCapabilities(), + uploadComponentInstanceInfo.getCapabilities()); + componentInstance.setCapabilities(validComponentInstanceCapabilities); + } + if (!existingnodeTypeMap.containsKey(uploadComponentInstanceInfo.getType())) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_NODE_TEMPLATE, + yamlName, uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); + throw new ComponentException(responseFormat); + } + Resource origResource = existingnodeTypeMap.get(uploadComponentInstanceInfo.getType()); + componentInstance.setName(uploadComponentInstanceInfo.getName()); + componentInstance.setIcon(origResource.getIcon()); + resourcesInstancesMap.put(componentInstance, origResource); + } catch (Exception e) { + throw new ComponentException(ActionStatus.GENERAL_ERROR,e.getMessage()); + } + } + + protected void createAndAddResourceInstance(UploadComponentInstanceInfo uploadComponentInstanceInfo, String yamlName, + Service service, Map<String, Resource> nodeNamespaceMap, Map<String, Resource> existingnodeTypeMap, Map<ComponentInstance, Resource> resourcesInstancesMap) { + Either<Resource, ResponseFormat> eitherResource; + log.debug("*************Going to create resource instances {}", uploadComponentInstanceInfo.getName()); + try { + if (nodeNamespaceMap.containsKey(uploadComponentInstanceInfo.getType())) { + uploadComponentInstanceInfo + .setType(nodeNamespaceMap.get(uploadComponentInstanceInfo.getType()).getToscaResourceName()); + } + Resource refResource = validateResourceInstanceBeforeCreate(yamlName, uploadComponentInstanceInfo, + existingnodeTypeMap); + + ComponentInstance componentInstance = new ComponentInstance(); + componentInstance.setComponentUid(refResource.getUniqueId()); + Collection<String> directives = uploadComponentInstanceInfo.getDirectives(); + if (directives != null && !directives.isEmpty()) { + componentInstance.setDirectives(new ArrayList<>(directives)); + } + UploadNodeFilterInfo uploadNodeFilterInfo = uploadComponentInstanceInfo.getUploadNodeFilterInfo(); + if (uploadNodeFilterInfo != null) { + componentInstance.setNodeFilter(new CINodeFilterUtils().getNodeFilterDataDefinition(uploadNodeFilterInfo, + componentInstance.getUniqueId())); + } + + ComponentTypeEnum containerComponentType = service.getComponentType(); + NodeTypeEnum containerNodeType = containerComponentType.getNodeType(); + if (containerNodeType.equals(NodeTypeEnum.Resource) + && MapUtils.isNotEmpty(uploadComponentInstanceInfo.getCapabilities()) + && MapUtils.isNotEmpty(refResource.getCapabilities())) { + serviceImportParseLogic.setCapabilityNamesTypes(refResource.getCapabilities(), uploadComponentInstanceInfo.getCapabilities()); + Map<String, List<CapabilityDefinition>> validComponentInstanceCapabilities = serviceImportParseLogic.getValidComponentInstanceCapabilities( + refResource.getUniqueId(), refResource.getCapabilities(), + uploadComponentInstanceInfo.getCapabilities()); + componentInstance.setCapabilities(validComponentInstanceCapabilities); + } + if (!existingnodeTypeMap.containsKey(uploadComponentInstanceInfo.getType())) { + log.debug( + "createResourceInstances - not found lates version for resource instance with name {} and type ", + uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_NODE_TEMPLATE, + yamlName, uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); + throw new ComponentException(responseFormat); + } + Resource origResource = existingnodeTypeMap.get(uploadComponentInstanceInfo.getType()); + componentInstance.setName(uploadComponentInstanceInfo.getName()); + componentInstance.setIcon(origResource.getIcon()); + resourcesInstancesMap.put(componentInstance, origResource); + } catch (Exception e) { + throw new ComponentException(ActionStatus.GENERAL_ERROR,e.getMessage()); + } + } + + protected Resource validateResourceInstanceBeforeCreate(String yamlName, UploadComponentInstanceInfo uploadComponentInstanceInfo, + Map<String, Resource> nodeNamespaceMap) { + Resource refResource; + try { + if (nodeNamespaceMap.containsKey(uploadComponentInstanceInfo.getType())) { + refResource = nodeNamespaceMap.get(uploadComponentInstanceInfo.getType()); + } else { + Either<Resource, StorageOperationStatus> findResourceEither = toscaOperationFacade + .getLatestResourceByToscaResourceName(uploadComponentInstanceInfo.getType()); + if (findResourceEither.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(findResourceEither.right().value())); + throw new ComponentException(responseFormat); + } + refResource = findResourceEither.left().value(); + nodeNamespaceMap.put(refResource.getToscaResourceName(), refResource); + } + String componentState = refResource.getComponentMetadataDefinition().getMetadataDataDefinition().getState(); + if (componentState.equals(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name())) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.ILLEGAL_COMPONENT_STATE, + refResource.getComponentType().getValue(), refResource.getName(), componentState); + throw new ComponentException(responseFormat); + } + if (!ModelConverter.isAtomicComponent(refResource) && refResource.getResourceType() != ResourceTypeEnum.VF) { + log.debug("validateResourceInstanceBeforeCreate - ref resource type is ", refResource.getResourceType()); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_NODE_TEMPLATE, + yamlName, uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); + throw new ComponentException(responseFormat); + } + return refResource; + } catch (Exception e) { + throw new ComponentException(ActionStatus.GENERAL_ERROR,e.getMessage()); + } + } + + protected void handleServiceNodeTypes(String yamlName, Service service, + String topologyTemplateYaml, boolean needLock, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle, + List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, Map<String, NodeTypeInfo> nodeTypesInfo, + CsarInfo csarInfo, String nodeName) { + try { + for (Map.Entry<String, NodeTypeInfo> nodeTypeEntry : nodeTypesInfo.entrySet()) { + boolean isResourceNotExisted = validateResourceNotExisted(nodeTypeEntry.getKey()); + if (nodeTypeEntry.getValue().isNested() && isResourceNotExisted) { + handleNestedVF(service, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, + nodeTypesInfo, csarInfo, nodeTypeEntry.getKey()); + log.trace("************* finished to create node {}", nodeTypeEntry.getKey()); + } + } + Map<String, Object> mappedToscaTemplate = null; + if (org.apache.commons.lang.StringUtils.isNotEmpty(nodeName) && MapUtils.isNotEmpty(nodeTypesInfo) + && nodeTypesInfo.containsKey(nodeName)) { + mappedToscaTemplate = nodeTypesInfo.get(nodeName).getMappedToscaTemplate(); + } + if (MapUtils.isEmpty(mappedToscaTemplate)) { + mappedToscaTemplate = (Map<String, Object>) new Yaml().load(topologyTemplateYaml); + } + createResourcesFromYamlNodeTypesList(yamlName, service, mappedToscaTemplate, needLock, nodeTypesArtifactsToHandle, + nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo); + } catch (ComponentException e) { + throw e; + } catch (StorageException e) { + throw e; + }catch (Exception e){ + log.debug("Exception occured when handleServiceNodeTypes, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected boolean validateResourceNotExisted(String type) { + try { + Either<Resource, StorageOperationStatus> latestResource = toscaOperationFacade.getLatestResourceByToscaResourceName(type); + return latestResource.isRight() ? true : false; + } catch (Exception e) { + log.debug("Exception occured when validateResourceNotExisted, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected Resource handleNestedVF(Service service, Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodesArtifactsToHandle, + List<ArtifactDefinition> createdArtifacts, Map<String, NodeTypeInfo> nodesInfo, CsarInfo csarInfo, + String nodeName) { + try { + String yamlName = nodesInfo.get(nodeName).getTemplateFileName(); + Map<String, Object> nestedVfcJsonMap = nodesInfo.get(nodeName).getMappedToscaTemplate(); + + createResourcesFromYamlNodeTypesList(yamlName, service, nestedVfcJsonMap, false, + nodesArtifactsToHandle, createdArtifacts, nodesInfo, csarInfo); + log.debug("************* Finished to create node types from yaml {}", yamlName); + + if (nestedVfcJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE.getElementName())) { + log.debug("************* Going to handle complex VFC from yaml {}", yamlName); + Resource resource = handleComplexVfc(nodesArtifactsToHandle, createdArtifacts, nodesInfo, + csarInfo, nodeName, yamlName); + return resource; + } + return new Resource(); + } catch (Exception e) { + log.debug("Exception occured when handleNestedVF, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected Resource handleNestedVfc(Service service, Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodesArtifactsToHandle, + List<ArtifactDefinition> createdArtifacts, Map<String, NodeTypeInfo> nodesInfo, CsarInfo csarInfo, + String nodeName) { + try { + String yamlName = nodesInfo.get(nodeName).getTemplateFileName(); + Map<String, Object> nestedVfcJsonMap = nodesInfo.get(nodeName).getMappedToscaTemplate(); + createResourcesFromYamlNodeTypesList(yamlName, service, nestedVfcJsonMap, false, + nodesArtifactsToHandle, createdArtifacts, nodesInfo, csarInfo); + log.debug("************* Finished to create node types from yaml {}", yamlName); + + if (nestedVfcJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE.getElementName())) { + log.debug("************* Going to handle complex VFC from yaml {}", yamlName); + Resource resource = handleComplexVfc(nodesArtifactsToHandle, createdArtifacts, nodesInfo, + csarInfo, nodeName, yamlName); + return resource; + } + return new Resource(); + } catch (Exception e) { + log.debug("Exception occured when handleNestedVFc, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected Resource handleComplexVfc(Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodesArtifactsToHandle, + List<ArtifactDefinition> createdArtifacts, Map<String, NodeTypeInfo> nodesInfo, CsarInfo csarInfo, + String nodeName, String yamlName) { + try { + Resource oldComplexVfc = null; + Resource newComplexVfc = serviceImportParseLogic.buildValidComplexVfc(csarInfo, nodeName, nodesInfo); + Either<Resource, StorageOperationStatus> oldComplexVfcRes = toscaOperationFacade + .getFullLatestComponentByToscaResourceName(newComplexVfc.getToscaResourceName()); + if (oldComplexVfcRes.isRight() && oldComplexVfcRes.right().value() == StorageOperationStatus.NOT_FOUND) { + oldComplexVfcRes = toscaOperationFacade.getFullLatestComponentByToscaResourceName( + serviceImportParseLogic.buildNestedToscaResourceName(ResourceTypeEnum.VF.name(), csarInfo.getVfResourceName(), + nodeName).getRight()); + } + if (oldComplexVfcRes.isRight() && oldComplexVfcRes.right().value() != StorageOperationStatus.NOT_FOUND) { + log.debug("Failed to fetch previous complex VFC by tosca resource name {}. Status is {}. ", + newComplexVfc.getToscaResourceName(), oldComplexVfcRes.right().value()); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } else if (oldComplexVfcRes.isLeft()) { + log.debug(VALIDATE_DERIVED_BEFORE_UPDATE); + Either<Boolean, ResponseFormat> eitherValidation = serviceImportParseLogic.validateNestedDerivedFromDuringUpdate( + oldComplexVfcRes.left().value(), newComplexVfc, + ValidationUtils.hasBeenCertified(oldComplexVfcRes.left().value().getVersion())); + if (eitherValidation.isLeft()) { + oldComplexVfc = oldComplexVfcRes.left().value(); + } + } + newComplexVfc = handleComplexVfc(nodesArtifactsToHandle, createdArtifacts, nodesInfo, csarInfo, nodeName, yamlName, + oldComplexVfc, newComplexVfc); + csarInfo.getCreatedNodesToscaResourceNames().put(nodeName, newComplexVfc.getToscaResourceName()); + LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction( + CERTIFICATION_ON_IMPORT, LifecycleChangeInfoWithAction.LifecycleChanceActionEnum.CREATE_FROM_CSAR); + log.debug("Going to certify cvfc {}. ", newComplexVfc.getName()); + final Resource result = serviceImportParseLogic + .propagateStateToCertified(csarInfo.getModifier(), newComplexVfc, lifecycleChangeInfo, true, false, + true); + csarInfo.getCreatedNodes().put(nodeName, result); + csarInfo.removeNodeFromQueue(); + return result; + } catch (Exception e) { + log.debug("Exception occured when handleComplexVfc, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected Resource handleComplexVfc(Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodesArtifactsToHandle, + List<ArtifactDefinition> createdArtifacts, Map<String, NodeTypeInfo> nodesInfo, CsarInfo csarInfo, + String nodeName, String yamlName, Resource oldComplexVfc, Resource newComplexVfc) { + Resource handleComplexVfcRes; + try { + Map<String, Object> mappedToscaTemplate = nodesInfo.get(nodeName).getMappedToscaTemplate(); + String yamlContent = new String(csarInfo.getCsar().get(yamlName)); + Map<String, NodeTypeInfo> newNodeTypesInfo = nodesInfo.entrySet().stream() + .collect(toMap(Map.Entry::getKey, e -> e.getValue().getUnmarkedCopy())); + CsarInfo.markNestedVfc(mappedToscaTemplate, newNodeTypesInfo); + if (oldComplexVfc == null) { + handleComplexVfcRes = createResourceFromYaml(newComplexVfc, yamlContent, yamlName, newNodeTypesInfo, + csarInfo, nodesArtifactsToHandle, false, true, nodeName); + } else { + handleComplexVfcRes = updateResourceFromYaml(oldComplexVfc, newComplexVfc, + AuditingActionEnum.UPDATE_RESOURCE_METADATA, createdArtifacts, yamlContent, yamlName, csarInfo, + newNodeTypesInfo, nodesArtifactsToHandle, nodeName, true); + } + return handleComplexVfcRes; + } catch (Exception e) { + log.debug("Exception occured when handleComplexVfc, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected Resource updateResourceFromYaml(Resource oldRresource, Resource newRresource, + AuditingActionEnum actionEnum, List<ArtifactDefinition> createdArtifacts, + String yamlFileName, String yamlFileContent, CsarInfo csarInfo, Map<String, NodeTypeInfo> nodeTypesInfo, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle, + String nodeName, boolean isNested) { + boolean inTransaction = true; + boolean shouldLock = false; + Resource preparedResource = null; + ParsedToscaYamlInfo uploadComponentInstanceInfoMap = null; + try { + uploadComponentInstanceInfoMap = csarBusinessLogic.getParsedToscaYamlInfo(yamlFileContent, yamlFileName, nodeTypesInfo, csarInfo, nodeName, oldRresource); + Map<String, UploadComponentInstanceInfo> instances = uploadComponentInstanceInfoMap.getInstances(); + if (MapUtils.isEmpty(instances) && newRresource.getResourceType() != ResourceTypeEnum.PNF) { + throw new ComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlFileName); + } + preparedResource = updateExistingResourceByImport(newRresource, oldRresource, csarInfo.getModifier(), + inTransaction, shouldLock, isNested).left; + log.trace("YAML topology file found in CSAR, file name: {}, contents: {}", yamlFileName, yamlFileContent); + serviceImportParseLogic.handleResourceGenericType(preparedResource); + handleNodeTypes(yamlFileName, preparedResource, yamlFileContent, + shouldLock, nodeTypesArtifactsToHandle, createdArtifacts, nodeTypesInfo, csarInfo, nodeName); + preparedResource = serviceImportParseLogic + .createInputsOnResource(preparedResource, uploadComponentInstanceInfoMap.getInputs()); + preparedResource = createResourceInstances(yamlFileName, preparedResource, instances, csarInfo.getCreatedNodes()); + preparedResource = createResourceInstancesRelations(csarInfo.getModifier(), yamlFileName, preparedResource, instances); + } catch (ComponentException e) { + ResponseFormat responseFormat = e.getResponseFormat() == null ? componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams()) : e.getResponseFormat(); + log.debug("#updateResourceFromYaml - failed to update resource from yaml {} .The error is {}", yamlFileName, responseFormat); + componentsUtils.auditResource(responseFormat, csarInfo.getModifier(), preparedResource == null ? oldRresource : preparedResource, actionEnum); + throw e; + } catch (StorageException e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(e.getStorageOperationStatus())); + log.debug("#updateResourceFromYaml - failed to update resource from yaml {} .The error is {}", yamlFileName, responseFormat); + componentsUtils.auditResource(responseFormat, csarInfo.getModifier(), preparedResource == null ? oldRresource : preparedResource, actionEnum); + throw e; + } + Either<Map<String, GroupDefinition>, ResponseFormat> validateUpdateVfGroupNamesRes = serviceBusinessLogic.groupBusinessLogic + .validateUpdateVfGroupNames(uploadComponentInstanceInfoMap.getGroups(), + preparedResource.getSystemName()); + if (validateUpdateVfGroupNamesRes.isRight()) { + throw new ComponentException(validateUpdateVfGroupNamesRes.right().value()); + } + Map<String, GroupDefinition> groups; + if (!validateUpdateVfGroupNamesRes.left().value().isEmpty()) { + groups = validateUpdateVfGroupNamesRes.left().value(); + } else { + groups = uploadComponentInstanceInfoMap.getGroups(); + } + serviceImportParseLogic.handleGroupsProperties(preparedResource, groups); + preparedResource = serviceImportParseLogic.updateGroupsOnResource(preparedResource, groups); + NodeTypeInfoToUpdateArtifacts nodeTypeInfoToUpdateArtifacts = new NodeTypeInfoToUpdateArtifacts(nodeName, + nodeTypesArtifactsToHandle); + + Either<Resource, ResponseFormat> updateArtifactsEither = createOrUpdateArtifacts( + ArtifactsBusinessLogic.ArtifactOperationEnum.UPDATE, createdArtifacts, yamlFileName, + csarInfo, preparedResource, nodeTypeInfoToUpdateArtifacts, inTransaction, shouldLock); + if (updateArtifactsEither.isRight()) { + log.debug("failed to update artifacts {}", updateArtifactsEither.right().value()); + throw new ComponentException(updateArtifactsEither.right().value()); + } + preparedResource = serviceImportParseLogic.getResourceWithGroups(updateArtifactsEither.left().value().getUniqueId()); + + ActionStatus mergingPropsAndInputsStatus = resourceDataMergeBusinessLogic.mergeResourceEntities(oldRresource, preparedResource); + if (mergingPropsAndInputsStatus != ActionStatus.OK) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource(mergingPropsAndInputsStatus, + preparedResource); + throw new ComponentException(responseFormat); + } + compositionBusinessLogic.setPositionsForComponentInstances(preparedResource, csarInfo.getModifier().getUserId()); + return preparedResource; + } + + protected Resource createResourceFromYaml(Resource resource, String topologyTemplateYaml, + String yamlName, Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate, + boolean shouldLock, boolean inTransaction, String nodeName) { + List<ArtifactDefinition> createdArtifacts = new ArrayList<>(); + Resource createdResource; + try { + ParsedToscaYamlInfo parsedToscaYamlInfo = csarBusinessLogic.getParsedToscaYamlInfo(topologyTemplateYaml, yamlName, nodeTypesInfo, csarInfo, nodeName, resource); + if (MapUtils.isEmpty(parsedToscaYamlInfo.getInstances()) && resource.getResourceType() != ResourceTypeEnum.PNF) { + throw new ComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + } + log.debug("#createResourceFromYaml - Going to create resource {} and RIs ", resource.getName()); + createdResource = createResourceAndRIsFromYaml(yamlName, resource, + parsedToscaYamlInfo, AuditingActionEnum.IMPORT_RESOURCE, false, createdArtifacts, topologyTemplateYaml, + nodeTypesInfo, csarInfo, nodeTypesArtifactsToCreate, shouldLock, inTransaction, nodeName); + log.debug("#createResourceFromYaml - The resource {} has been created ", resource.getName()); + } catch (ComponentException e) { + ResponseFormat responseFormat = e.getResponseFormat() == null ? componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams()) : e.getResponseFormat(); + componentsUtils.auditResource(responseFormat, csarInfo.getModifier(), resource, AuditingActionEnum.IMPORT_RESOURCE); + throw e; + } catch (StorageException e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(e.getStorageOperationStatus())); + componentsUtils.auditResource(responseFormat, csarInfo.getModifier(), resource, AuditingActionEnum.IMPORT_RESOURCE); + throw e; + } + return createdResource; + } + + protected Resource createResourceAndRIsFromYaml(String yamlName, Resource resource, + ParsedToscaYamlInfo parsedToscaYamlInfo, AuditingActionEnum actionEnum, boolean isNormative, + List<ArtifactDefinition> createdArtifacts, String topologyTemplateYaml, + Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToCreate, + boolean shouldLock, boolean inTransaction, String nodeName) { + List<ArtifactDefinition> nodeTypesNewCreatedArtifacts = new ArrayList<>(); + if (shouldLock) { + Either<Boolean, ResponseFormat> lockResult = serviceBusinessLogic.lockComponentByName(resource.getSystemName(), resource, + CREATE_RESOURCE); + if (lockResult.isRight()) { + serviceImportParseLogic.rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw new ComponentException(lockResult.right().value()); + } + log.debug("name is locked {} status = {}", resource.getSystemName(), lockResult); + } + try { + log.trace("************* createResourceFromYaml before full create resource {}", yamlName); + Resource genericResource = serviceBusinessLogic.fetchAndSetDerivedFromGenericType(resource); + resource = createResourceTransaction(resource, + csarInfo.getModifier(), isNormative); + log.trace("************* Going to add inputs from yaml {}", yamlName); + + Map<String, Object> yamlMap = ImportUtils.loadYamlAsStrictMap(csarInfo.getMainTemplateContent()); + Map<String, Object> metadata = (Map<String, Object>) yamlMap.get("metadata"); + String type = (String) metadata.get("type"); + if (resource.shouldGenerateInputs() && !"Service".equalsIgnoreCase(type)) + serviceBusinessLogic.generateAndAddInputsFromGenericTypeProperties(resource, genericResource); + Map<String, InputDefinition> inputs = parsedToscaYamlInfo.getInputs(); + resource = serviceImportParseLogic.createInputsOnResource(resource, inputs); + Map<String, UploadComponentInstanceInfo> uploadComponentInstanceInfoMap = parsedToscaYamlInfo + .getInstances(); + resource = createRIAndRelationsFromYaml(yamlName, resource, uploadComponentInstanceInfoMap, + topologyTemplateYaml, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, + nodeTypesArtifactsToCreate, nodeName); + log.trace("************* Finished to create nodes, RI and Relation from yaml {}", yamlName); + // validate update vf module group names + Either<Map<String, GroupDefinition>, ResponseFormat> validateUpdateVfGroupNamesRes = serviceBusinessLogic.groupBusinessLogic + .validateUpdateVfGroupNames(parsedToscaYamlInfo.getGroups(), resource.getSystemName()); + if (validateUpdateVfGroupNamesRes.isRight()) { + serviceImportParseLogic.rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw new ComponentException(validateUpdateVfGroupNamesRes.right().value()); + } + Map<String, GroupDefinition> groups; + log.trace("************* Going to add groups from yaml {}", yamlName); + + if (!validateUpdateVfGroupNamesRes.left().value().isEmpty()) { + groups = validateUpdateVfGroupNamesRes.left().value(); + } else { + groups = parsedToscaYamlInfo.getGroups(); + } + + Either<Resource, ResponseFormat> createGroupsOnResource = createGroupsOnResource(resource, + groups); + if (createGroupsOnResource.isRight()) { + serviceImportParseLogic.rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw new ComponentException(createGroupsOnResource.right().value()); + } + resource = createGroupsOnResource.left().value(); + log.trace("************* Going to add artifacts from yaml {}", yamlName); + + NodeTypeInfoToUpdateArtifacts nodeTypeInfoToUpdateArtifacts = new NodeTypeInfoToUpdateArtifacts(nodeName, nodeTypesArtifactsToCreate); + + Either<Resource, ResponseFormat> createArtifactsEither = createOrUpdateArtifacts( + ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE, createdArtifacts, yamlName, + csarInfo, resource, nodeTypeInfoToUpdateArtifacts, inTransaction, shouldLock); + if (createArtifactsEither.isRight()) { + serviceImportParseLogic.rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw new ComponentException(createArtifactsEither.right().value()); + } + + resource = serviceImportParseLogic.getResourceWithGroups(createArtifactsEither.left().value().getUniqueId()); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.CREATED); + componentsUtils.auditResource(responseFormat, csarInfo.getModifier(), resource, actionEnum); + ASDCKpiApi.countCreatedResourcesKPI(); + return resource; + } catch (ComponentException | StorageException e) { + serviceImportParseLogic.rollback(inTransaction, resource, createdArtifacts, nodeTypesNewCreatedArtifacts); + throw e; + } finally { + if (!inTransaction) { + serviceBusinessLogic.janusGraphDao.commit(); + } + if (shouldLock) { + serviceBusinessLogic.graphLockOperation.unlockComponentByName(resource.getSystemName(), resource.getUniqueId(), NodeTypeEnum.Resource); + } + } + } + + protected Either<Resource, ResponseFormat> createGroupsOnResource(Resource resource, + Map<String, GroupDefinition> groups) { + if (groups != null && !groups.isEmpty()) { + List<GroupDefinition> groupsAsList = updateGroupsMembersUsingResource( + groups, resource); + serviceImportParseLogic.handleGroupsProperties(resource, groups); + serviceImportParseLogic.fillGroupsFinalFields(groupsAsList); + Either<List<GroupDefinition>, ResponseFormat> createGroups = serviceBusinessLogic.groupBusinessLogic.createGroups(resource, + groupsAsList, true); + if (createGroups.isRight()) { + return Either.right(createGroups.right().value()); + } + } else { + return Either.left(resource); + } + Either<Resource, StorageOperationStatus> updatedResource = toscaOperationFacade + .getToscaElement(resource.getUniqueId()); + if (updatedResource.isRight()) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(updatedResource.right().value()), resource); + return Either.right(responseFormat); + } + return Either.left(updatedResource.left().value()); + } + + protected List<GroupDefinition> updateGroupsMembersUsingResource(Map<String, GroupDefinition> groups, Resource component) { + List<GroupDefinition> result = new ArrayList<>(); + List<ComponentInstance> componentInstances = component.getComponentInstances(); + + if (groups != null) { + Either<Boolean, ResponseFormat> validateCyclicGroupsDependencies = serviceImportParseLogic.validateCyclicGroupsDependencies(groups); + if (validateCyclicGroupsDependencies.isRight()) { + throw new ComponentException(validateCyclicGroupsDependencies.right().value()); + } + for (Map.Entry<String, GroupDefinition> entry : groups.entrySet()) { + String groupName = entry.getKey(); + GroupDefinition groupDefinition = entry.getValue(); + GroupDefinition updatedGroupDefinition = new GroupDefinition(groupDefinition); + updatedGroupDefinition.setMembers(null); + Map<String, String> members = groupDefinition.getMembers(); + if (members != null) { + updateGroupMembers(groups, updatedGroupDefinition, component, componentInstances, groupName, members); + } + result.add(updatedGroupDefinition); + } + } + return result; + } + + protected void updateGroupMembers(Map<String, GroupDefinition> groups, GroupDefinition updatedGroupDefinition, Resource component, List<ComponentInstance> componentInstances, String groupName, Map<String, String> members) { + Set<String> compInstancesNames = members.keySet(); + if (CollectionUtils.isEmpty(componentInstances)) { + String membersAstString = compInstancesNames.stream().collect(joining(",")); + log.debug("The members: {}, in group: {}, cannot be found in component {}. There are no component instances.", + membersAstString, groupName, component.getNormalizedName()); + throw new ComponentException(componentsUtils.getResponseFormat( + ActionStatus.GROUP_INVALID_COMPONENT_INSTANCE, membersAstString, groupName, + component.getNormalizedName(), serviceImportParseLogic.getComponentTypeForResponse(component))); + } + Map<String, String> memberNames = componentInstances.stream() + .collect(toMap(ComponentInstance::getName, ComponentInstance::getUniqueId)); + memberNames.putAll(groups.keySet().stream().collect(toMap(g -> g, g -> ""))); + Map<String, String> relevantInstances = memberNames.entrySet().stream() + .filter(n -> compInstancesNames.contains(n.getKey())) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); + + if (relevantInstances == null || relevantInstances.size() != compInstancesNames.size()) { + List<String> foundMembers = new ArrayList<>(); + if (relevantInstances != null) { + foundMembers = relevantInstances.keySet().stream().collect(toList()); + } + compInstancesNames.removeAll(foundMembers); + String membersAstString = compInstancesNames.stream().collect(joining(",")); + throw new ComponentException(componentsUtils.getResponseFormat( + ActionStatus.GROUP_INVALID_COMPONENT_INSTANCE, membersAstString, groupName, + component.getNormalizedName(), serviceImportParseLogic.getComponentTypeForResponse(component))); + } + updatedGroupDefinition.setMembers(relevantInstances); + } + + protected Resource createResourceTransaction(Resource resource, User user, + boolean isNormative) { + Either<Boolean, StorageOperationStatus> eitherValidation = toscaOperationFacade.validateComponentNameExists( + resource.getName(), resource.getResourceType(), resource.getComponentType()); + if (eitherValidation.isRight()) { + ResponseFormat errorResponse = componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(eitherValidation.right().value())); + throw new ComponentException(errorResponse); + } + if (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()); + throw new ComponentException(errorResponse); + } + log.debug("send resource {} to dao for create", resource.getName()); + serviceImportParseLogic.createArtifactsPlaceHolderData(resource, user); + if (!isNormative) { + log.debug("enrich resource with creator, version and state"); + resource.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + resource.setVersion(INITIAL_VERSION); + resource.setHighestVersion(true); + if (resource.getResourceType() != null && resource.getResourceType() != ResourceTypeEnum.VF) { + resource.setAbstract(false); + } + } + return toscaOperationFacade.createToscaComponent(resource) + .left() + .on(r -> serviceImportParseLogic.throwComponentExceptionByResource(r, resource)); + } + + protected ImmutablePair<Resource, ActionStatus> updateExistingResourceByImport( + Resource newResource, Resource oldResource, User user, boolean inTransaction, boolean needLock, + boolean isNested) { + String lockedResourceId = oldResource.getUniqueId(); + log.debug("found resource: name={}, id={}, version={}, state={}", oldResource.getName(), lockedResourceId, + oldResource.getVersion(), oldResource.getLifecycleState()); + ImmutablePair<Resource, ActionStatus> resourcePair = null; + try { + serviceBusinessLogic.lockComponent(lockedResourceId, oldResource, needLock, "Update Resource by Import"); + oldResource = serviceImportParseLogic + .prepareResourceForUpdate(oldResource, newResource, user, inTransaction, false); + serviceImportParseLogic.mergeOldResourceMetadataWithNew(oldResource, newResource); + serviceImportParseLogic.validateResourceFieldsBeforeUpdate(oldResource, newResource, inTransaction, isNested); + serviceImportParseLogic + .validateCapabilityTypesCreate(user, serviceImportParseLogic.getCapabilityTypeOperation(), newResource, AuditingActionEnum.IMPORT_RESOURCE, inTransaction); + newResource.setContactId(newResource.getContactId().toLowerCase()); + newResource.setCreatorUserId(user.getUserId()); + newResource.setCreatorFullName(user.getFullName()); + newResource.setLastUpdaterUserId(user.getUserId()); + newResource.setLastUpdaterFullName(user.getFullName()); + newResource.setUniqueId(oldResource.getUniqueId()); + newResource.setVersion(oldResource.getVersion()); + newResource.setInvariantUUID(oldResource.getInvariantUUID()); + newResource.setLifecycleState(oldResource.getLifecycleState()); + newResource.setUUID(oldResource.getUUID()); + newResource.setNormalizedName(oldResource.getNormalizedName()); + newResource.setSystemName(oldResource.getSystemName()); + if (oldResource.getCsarUUID() != null) { + newResource.setCsarUUID(oldResource.getCsarUUID()); + } + if (oldResource.getImportedToscaChecksum() != null) { + newResource.setImportedToscaChecksum(oldResource.getImportedToscaChecksum()); + } + if (newResource.getDerivedFromGenericType() == null || newResource.getDerivedFromGenericType().isEmpty()) { + newResource.setDerivedFromGenericType(oldResource.getDerivedFromGenericType()); + } + if (newResource.getDerivedFromGenericVersion() == null || newResource.getDerivedFromGenericVersion().isEmpty()) { + newResource.setDerivedFromGenericVersion(oldResource.getDerivedFromGenericVersion()); + } + if (newResource.getToscaArtifacts() == null || newResource.getToscaArtifacts().isEmpty()) { + serviceBusinessLogic.setToscaArtifactsPlaceHolders(newResource, user); + } + if (newResource.getInterfaces() == null || newResource.getInterfaces().isEmpty()) { + newResource.setInterfaces(oldResource.getInterfaces()); + } + if (CollectionUtils.isEmpty(newResource.getProperties())) { + newResource.setProperties(oldResource.getProperties()); + } + + Either<Resource, StorageOperationStatus> overrideResource = toscaOperationFacade + .overrideComponent(newResource, oldResource); + if (overrideResource.isRight()) { + ResponseFormat responseFormat = new ResponseFormat(); + serviceBusinessLogic.throwComponentException(responseFormat); + } + log.debug("Resource updated successfully!!!"); + resourcePair = new ImmutablePair<>(overrideResource.left().value(), + ActionStatus.OK); + return resourcePair; + } finally { + if (resourcePair == null) { + BeEcompErrorManager.getInstance().logBeSystemError("Change LifecycleState - Certify"); + serviceBusinessLogic.janusGraphDao.rollback(); + } else if (!inTransaction) { + serviceBusinessLogic.janusGraphDao.commit(); + } + if (needLock) { + log.debug("unlock resource {}", lockedResourceId); + serviceBusinessLogic.graphLockOperation.unlockComponent(lockedResourceId, NodeTypeEnum.Resource); + } + } + } + + protected Map<String, Resource> createResourcesFromYamlNodeTypesList(String yamlName, Service service, Map<String, Object> mappedToscaTemplate, boolean needLock, + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle, + List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, Map<String, NodeTypeInfo> nodeTypesInfo, + CsarInfo csarInfo) { + try { + Either<String, ImportUtils.ResultStatusEnum> toscaVersion = findFirstToscaStringElement(mappedToscaTemplate, + TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION); + if (toscaVersion.isRight()) { + throw new ComponentException(ActionStatus.INVALID_TOSCA_TEMPLATE); + } + Map<String, Object> mapToConvert = new HashMap<>(); + mapToConvert.put(TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION.getElementName(), toscaVersion.left().value()); + Map<String, Object> nodeTypes = serviceImportParseLogic.getNodeTypesFromTemplate(mappedToscaTemplate); + createNodeTypes(yamlName, service, needLock, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, mapToConvert, nodeTypes); + return csarInfo.getCreatedNodes(); + } catch (Exception e) { + log.debug("Exception occured when createResourcesFromYamlNodeTypesList,error is:{}",e.getMessage(),e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected void createNodeTypes(String yamlName, Service service, boolean needLock, Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle, List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, Map<String, Object> mapToConvert, Map<String, Object> nodeTypes) { + Iterator<Map.Entry<String, Object>> nodesNameValueIter = nodeTypes.entrySet().iterator(); + Resource vfcCreated = null; + while (nodesNameValueIter.hasNext()) { + Map.Entry<String, Object> nodeType = nodesNameValueIter.next(); + Map<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> nodeTypeArtifactsToHandle = nodeTypesArtifactsToHandle == null + || nodeTypesArtifactsToHandle.isEmpty() ? null + : nodeTypesArtifactsToHandle.get(nodeType.getKey()); + + if (nodeTypesInfo.containsKey(nodeType.getKey())) { + vfcCreated = handleNestedVfc(service, + nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, + nodeType.getKey()); + log.trace("************* Finished to handle nested vfc {}", nodeType.getKey()); + } else if (csarInfo.getCreatedNodesToscaResourceNames() != null + && !csarInfo.getCreatedNodesToscaResourceNames().containsKey(nodeType.getKey())) { + ImmutablePair<Resource, ActionStatus> resourceCreated = serviceImportParseLogic + .createNodeTypeResourceFromYaml(yamlName, nodeType, csarInfo.getModifier(), mapToConvert, + service, needLock, nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts, true, + csarInfo, true); + log.debug("************* Finished to create node {}", nodeType.getKey()); + + vfcCreated = resourceCreated.getLeft(); + csarInfo.getCreatedNodesToscaResourceNames().put(nodeType.getKey(), + vfcCreated.getName()); + } + if (vfcCreated != null) { + csarInfo.getCreatedNodes().put(nodeType.getKey(), vfcCreated); + } + mapToConvert.remove(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName()); + } + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java new file mode 100644 index 0000000000..8e7c1e852c --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportManager.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2020 CMCC Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl; + + +import javax.servlet.ServletContext; +import org.openecomp.sdc.be.datatypes.components.ServiceMetadataDataDefinition; +import org.openecomp.sdc.be.impl.WebAppContextWrapper; +import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.UploadServiceInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.WebApplicationContext; + + +//upload Service model by Shiyong1989@hotmail.com +@Component("ServiceImportManager") +public class ServiceImportManager { + + private ServletContext servletContext; + + private ResponseFormatManager responseFormatManager; + + @Autowired + private ServiceBusinessLogic serviceBusinessLogic; + + public ServiceImportBusinessLogic getServiceImportBusinessLogic() { + return serviceImportBusinessLogic; + } + + public void setServiceImportBusinessLogic( + ServiceImportBusinessLogic serviceImportBusinessLogic) { + this.serviceImportBusinessLogic = serviceImportBusinessLogic; + } + + @Autowired + private ServiceImportBusinessLogic serviceImportBusinessLogic; + + public boolean isServiceExist(String serviceName) { + return serviceBusinessLogic.isServiceExist(serviceName); + } + + + public ServiceBusinessLogic getServiceBusinessLogic() { + return serviceBusinessLogic; + } + + public void setServiceBusinessLogic( + ServiceBusinessLogic serviceBusinessLogic) { + this.serviceBusinessLogic = serviceBusinessLogic; + } + + + public void populateServiceMetadata(UploadServiceInfo serviceMetaData, Service service) { + if (service != null && serviceMetaData != null) { + service.setDescription(serviceMetaData.getDescription()); + service.setTags(serviceMetaData.getTags()); + service.setCategories(serviceMetaData.getCategories()); + service.setContactId(serviceMetaData.getContactId()); + service.setName(serviceMetaData.getName()); + service.setIcon(serviceMetaData.getServiceIconPath()); + service.setServiceVendorModelNumber(serviceMetaData.getServiceVendorModelNumber()); + ServiceMetadataDataDefinition serviceMetadataDataDefinition = (ServiceMetadataDataDefinition) service + .getComponentMetadataDefinition().getMetadataDataDefinition(); + serviceMetadataDataDefinition.getServiceVendorModelNumber(); + service.setServiceType(""); + service.setProjectCode(serviceMetaData.getProjectCode()); + if (serviceMetaData.getVendorName() != null) { + service.setVendorName(serviceMetaData.getVendorName()); + } + if (serviceMetaData.getVendorRelease() != null) { + service.setVendorRelease(serviceMetaData.getVendorRelease()); + } + } + } + + public void populateRealServiceMetadata(UploadServiceInfo serviceMetaData, Service service) { + if (service != null && serviceMetaData != null) { + service.setTags(serviceMetaData.getTags()); + service.setContactId(serviceMetaData.getContactId()); + service.setName(serviceMetaData.getName()); + } + } + + public synchronized void init(ServletContext servletContext) { + if (this.servletContext == null) { + this.servletContext = servletContext; + responseFormatManager = ResponseFormatManager.getInstance(); + serviceBusinessLogic = getServiceBL(servletContext); + } + } + + private ServiceBusinessLogic getServiceBL(ServletContext context) { + WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context.getAttribute(org.openecomp.sdc.common.api.Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); + WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); + return webApplicationContext.getBean(ServiceBusinessLogic.class); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java new file mode 100644 index 0000000000..65576d1567 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogic.java @@ -0,0 +1,2602 @@ +/* + * Copyright (C) 2020 CMCC, Inc. and others. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.be.components.impl; + + +import fj.data.Either; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.openecomp.sdc.be.components.csar.CsarInfo; +import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo; +import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException; +import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; +import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic; +import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction; +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.datatypes.elements.*; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.CreatedFrom; +import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum; +import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.model.category.CategoryDefinition; +import org.openecomp.sdc.be.model.category.SubCategoryDefinition; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade; +import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter; +import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation; +import org.openecomp.sdc.be.model.operations.api.IInterfaceLifecycleOperation; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; +import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.resources.data.auditing.model.ResourceVersionInfo; +import org.openecomp.sdc.be.tosca.CsarUtils; +import org.openecomp.sdc.be.utils.CommonBeUtils; +import org.openecomp.sdc.be.utils.TypeUtils; +import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; +import org.openecomp.sdc.common.api.ArtifactTypeEnum; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.log.wrappers.Logger; +import org.openecomp.sdc.common.util.GeneralUtility; +import org.openecomp.sdc.common.util.ValidationUtils; +import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.beans.factory.annotation.Autowired; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; + +import java.util.*; +import java.util.function.Function; + +import static java.util.stream.Collectors.*; +import static org.apache.commons.collections.CollectionUtils.isNotEmpty; + +@Getter +@Setter +@org.springframework.stereotype.Component +public class ServiceImportParseLogic { + + 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 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"; + private static final String VALIDATE_DERIVED_BEFORE_UPDATE = "validate derived before update"; + private static final String PLACE_HOLDER_RESOURCE_TYPES = "validForResourceTypes"; + private static final String CREATE_RESOURCE_VALIDATE_CAPABILITY_TYPES = "Create Resource - validateCapabilityTypesCreate"; + private static final String CATEGORY_IS_EMPTY = "Resource category is empty"; + + + @Autowired + private ServiceBusinessLogic serviceBusinessLogic; + public ServiceBusinessLogic getServiceBusinessLogic() { + return serviceBusinessLogic; + } + + public void setServiceBusinessLogic( + ServiceBusinessLogic serviceBusinessLogic) { + this.serviceBusinessLogic = serviceBusinessLogic; + } + + @Autowired + protected ComponentsUtils componentsUtils; + @Autowired + protected ToscaOperationFacade toscaOperationFacade; + @Autowired + private LifecycleBusinessLogic lifecycleBusinessLogic; + @Autowired + private InputsBusinessLogic inputsBusinessLogic; + @Autowired + private ResourceImportManager resourceImportManager; + @Autowired + private IInterfaceLifecycleOperation interfaceTypeOperation = null; + private static final Logger log = Logger.getLogger(ServiceImportParseLogic.class); + + @Autowired + private ICapabilityTypeOperation capabilityTypeOperation = null; + + public ICapabilityTypeOperation getCapabilityTypeOperation() { + return capabilityTypeOperation; + } + + public void setCapabilityTypeOperation(ICapabilityTypeOperation capabilityTypeOperation) { + this.capabilityTypeOperation = capabilityTypeOperation; + } + + public Either<Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>>, ResponseFormat> findNodeTypesArtifactsToHandle( + Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, Service oldResource) { + + Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle = new HashMap<>(); + Either<Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>>, ResponseFormat> nodeTypesArtifactsToHandleRes + = Either.left(nodeTypesArtifactsToHandle); + + try { + Map<String, List<ArtifactDefinition>> extractedVfcsArtifacts = CsarUtils.extractVfcsArtifactsFromCsar(csarInfo.getCsar()); + Map<String, ImmutablePair<String, String>> extractedVfcToscaNames = + extractVfcToscaNames(nodeTypesInfo, oldResource.getName(), csarInfo); + log.debug("Going to fetch node types for resource with name {} during import csar with UUID {}. ", + oldResource.getName(), csarInfo.getCsarUUID()); + extractedVfcToscaNames.forEach((namespace, vfcToscaNames) -> findAddNodeTypeArtifactsToHandle(csarInfo, nodeTypesArtifactsToHandle, oldResource, + extractedVfcsArtifacts, + namespace, vfcToscaNames)); + } catch (Exception e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR); + nodeTypesArtifactsToHandleRes = Either.right(responseFormat); + log.debug("Exception occured when findNodeTypesUpdatedArtifacts, error is:{}", e.getMessage(), e); + } + return nodeTypesArtifactsToHandleRes; + } + + private Map<String, ImmutablePair<String, String>> extractVfcToscaNames(Map<String, NodeTypeInfo> nodeTypesInfo, + String vfResourceName, CsarInfo csarInfo) { + Map<String, ImmutablePair<String, String>> vfcToscaNames = new HashMap<>(); + + Map<String, Object> nodes = extractAllNodes(nodeTypesInfo, csarInfo); + if (!nodes.isEmpty()) { + Iterator<Map.Entry<String, Object>> nodesNameEntry = nodes.entrySet().iterator(); + while (nodesNameEntry.hasNext()) { + Map.Entry<String, Object> nodeType = nodesNameEntry.next(); + ImmutablePair<String, String> toscaResourceName = buildNestedToscaResourceName( + ResourceTypeEnum.VFC.name(), vfResourceName, nodeType.getKey()); + vfcToscaNames.put(nodeType.getKey(), toscaResourceName); + } + } + for (NodeTypeInfo cvfc : nodeTypesInfo.values()) { + vfcToscaNames.put(cvfc.getType(), + buildNestedToscaResourceName(ResourceTypeEnum.VF.name(), vfResourceName, cvfc.getType())); + } + return vfcToscaNames; + } + + public String buildNodeTypeYaml(Map.Entry<String, Object> nodeNameValue, Map<String, Object> mapToConvert, + String nodeResourceType, CsarInfo csarInfo) { + // We need to create a Yaml from each node_types in order to create + // resource from each node type using import normative flow. + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + Yaml yaml = new Yaml(options); + + Map<String, Object> node = new HashMap<>(); + node.put(buildNestedToscaResourceName(nodeResourceType, csarInfo.getVfResourceName(), nodeNameValue.getKey()) + .getLeft(), nodeNameValue.getValue()); + mapToConvert.put(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName(), node); + + return yaml.dumpAsMap(mapToConvert); + } + + ImmutablePair<String, String> buildNestedToscaResourceName(String nodeResourceType, String vfResourceName, + String nodeTypeFullName) { + String actualType; + String actualVfName; + if (ResourceTypeEnum.CVFC.name().equals(nodeResourceType)) { + actualVfName = vfResourceName + ResourceTypeEnum.CVFC.name(); + actualType = ResourceTypeEnum.VFC.name(); + } else { + actualVfName = vfResourceName; + actualType = nodeResourceType; + } + String nameWithouNamespacePrefix; + try { + StringBuilder toscaResourceName = new StringBuilder(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX); + if (!nodeTypeFullName.contains(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX)){ + nameWithouNamespacePrefix = nodeTypeFullName; + } else { + nameWithouNamespacePrefix = nodeTypeFullName + .substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length()); + } + String[] findTypes = nameWithouNamespacePrefix.split("\\."); + String resourceType = findTypes[0]; + String actualName = nameWithouNamespacePrefix.substring(resourceType.length()); + + if (actualName.startsWith(Constants.ABSTRACT)) { + toscaResourceName.append(resourceType.toLowerCase()).append('.') + .append(ValidationUtils.convertToSystemName(actualVfName)); + } else { + toscaResourceName.append(actualType.toLowerCase()).append('.').append(ValidationUtils.convertToSystemName(actualVfName)); + //toscaResourceName.append(actualType.toLowerCase()); + } + StringBuilder previousToscaResourceName = new StringBuilder(toscaResourceName); + return new ImmutablePair<>(toscaResourceName.append(actualName.toLowerCase()).toString(), + previousToscaResourceName + .append(actualName.substring(actualName.split("\\.")[1].length() + 1).toLowerCase()) + .toString()); + } catch (Exception e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE); + log.debug("Exception occured when buildNestedToscaResourceName, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.INVALID_TOSCA_TEMPLATE, vfResourceName); + } + } + + private Map<String, Object> extractAllNodes(Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo) { + Map<String, Object> nodes = new HashMap<>(); + for (NodeTypeInfo nodeTypeInfo : nodeTypesInfo.values()) { + extractNodeTypes(nodes, nodeTypeInfo.getMappedToscaTemplate()); + } + extractNodeTypes(nodes, csarInfo.getMappedToscaMainTemplate()); + return nodes; + } + + private void extractNodeTypes(Map<String, Object> nodes, Map<String, Object> mappedToscaTemplate) { + Either<Map<String, Object>, ImportUtils.ResultStatusEnum> eitherNodeTypes = ImportUtils + .findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES); + if (eitherNodeTypes.isLeft()) { + nodes.putAll(eitherNodeTypes.left().value()); + } + } + + protected void findAddNodeTypeArtifactsToHandle(CsarInfo csarInfo, Map<String, EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle, + Service resource, Map<String, List<ArtifactDefinition>> extractedVfcsArtifacts, String namespace, ImmutablePair<String, String> vfcToscaNames){ + + EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> curNodeTypeArtifactsToHandle = null; + log.debug("Going to fetch node type with tosca name {}. ", vfcToscaNames.getLeft()); + Resource curNodeType = findVfcResource(csarInfo, resource, vfcToscaNames.getLeft(), vfcToscaNames.getRight(), null); + if (!MapUtils.isEmpty(extractedVfcsArtifacts)) { + List<ArtifactDefinition> currArtifacts = new ArrayList<>(); + if (extractedVfcsArtifacts.containsKey(namespace)) { + handleAndAddExtractedVfcsArtifacts(currArtifacts, extractedVfcsArtifacts.get(namespace)); + } + curNodeTypeArtifactsToHandle = findNodeTypeArtifactsToHandle(curNodeType, currArtifacts); + } else if (curNodeType != null) { + // delete all artifacts if have not received artifacts from + // csar + try { + curNodeTypeArtifactsToHandle = new EnumMap<>(ArtifactsBusinessLogic.ArtifactOperationEnum.class); + List<ArtifactDefinition> artifactsToDelete = new ArrayList<>(); + // delete all informational artifacts + artifactsToDelete.addAll(curNodeType.getArtifacts().values().stream() + .filter(a -> a.getArtifactGroupType() == ArtifactGroupTypeEnum.INFORMATIONAL) + .collect(toList())); + // delete all deployment artifacts + artifactsToDelete.addAll(curNodeType.getDeploymentArtifacts().values()); + if (!artifactsToDelete.isEmpty()) { + curNodeTypeArtifactsToHandle + .put(ArtifactsBusinessLogic.ArtifactOperationEnum.DELETE, artifactsToDelete); + } + } catch (Exception e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE); + log.debug("Exception occured when findAddNodeTypeArtifactsToHandle, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.INVALID_TOSCA_TEMPLATE, vfcToscaNames.getLeft()); + } + } + if (MapUtils.isNotEmpty(curNodeTypeArtifactsToHandle)) { + nodeTypesArtifactsToHandle.put(namespace, curNodeTypeArtifactsToHandle); + } + } + + protected void handleAndAddExtractedVfcsArtifacts(List<ArtifactDefinition> vfcArtifacts, + List<ArtifactDefinition> artifactsToAdd) { + List<String> vfcArtifactNames = vfcArtifacts.stream().map(ArtifactDataDefinition::getArtifactName) + .collect(toList()); + artifactsToAdd.stream().forEach(a -> { + if (!vfcArtifactNames.contains(a.getArtifactName())) { + vfcArtifacts.add(a); + } else { + log.debug("Can't upload two artifact with the same name {}. ", a.getArtifactName()); + } + }); + } + + protected Resource findVfcResource(CsarInfo csarInfo, Service resource, String currVfcToscaName, String previousVfcToscaName, StorageOperationStatus status) { + if (status != null && status != StorageOperationStatus.NOT_FOUND) { + log.debug("Error occured during fetching node type with tosca name {}, error: {}", currVfcToscaName, status); + throw new ComponentException(componentsUtils.convertFromStorageResponse(status), csarInfo.getCsarUUID()); + } else if (org.apache.commons.lang.StringUtils.isNotEmpty(currVfcToscaName)) { + return (Resource)toscaOperationFacade.getLatestByToscaResourceName(currVfcToscaName) + .left() + .on(st -> findVfcResource(csarInfo, resource, previousVfcToscaName, null, st)); + } + return null; + } + + protected EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> findNodeTypeArtifactsToHandle( + Resource curNodeType, List<ArtifactDefinition> extractedArtifacts) { + + EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> nodeTypeArtifactsToHandle = null; + try { + List<ArtifactDefinition> artifactsToUpload = new ArrayList<>(extractedArtifacts); + List<ArtifactDefinition> artifactsToUpdate = new ArrayList<>(); + List<ArtifactDefinition> artifactsToDelete = new ArrayList<>(); + processExistingNodeTypeArtifacts(extractedArtifacts, artifactsToUpload, artifactsToUpdate, artifactsToDelete, + collectExistingArtifacts(curNodeType)); + nodeTypeArtifactsToHandle = putFoundArtifacts(artifactsToUpload, artifactsToUpdate, artifactsToDelete); + } catch (Exception e) { + log.debug("Exception occured when findNodeTypeArtifactsToHandle, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + return nodeTypeArtifactsToHandle; + } + + protected Map<String, ArtifactDefinition> collectExistingArtifacts(Resource curNodeType) { + Map<String, ArtifactDefinition> existingArtifacts = new HashMap<>(); + if (curNodeType == null) { + return existingArtifacts; + } + if (MapUtils.isNotEmpty(curNodeType.getDeploymentArtifacts())) { + existingArtifacts.putAll(curNodeType.getDeploymentArtifacts()); + } + if (MapUtils.isNotEmpty(curNodeType.getArtifacts())) { + existingArtifacts + .putAll(curNodeType.getArtifacts().entrySet() + .stream() + .filter(e -> e.getValue().getArtifactGroupType() == ArtifactGroupTypeEnum.INFORMATIONAL) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue))); + } + return existingArtifacts; + } + + protected EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> putFoundArtifacts(List<ArtifactDefinition> artifactsToUpload, List<ArtifactDefinition> artifactsToUpdate, List<ArtifactDefinition> artifactsToDelete) { + EnumMap<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> nodeTypeArtifactsToHandle = null; + if (!artifactsToUpload.isEmpty() || !artifactsToUpdate.isEmpty() || !artifactsToDelete.isEmpty()) { + nodeTypeArtifactsToHandle = new EnumMap<>(ArtifactsBusinessLogic.ArtifactOperationEnum.class); + if (!artifactsToUpload.isEmpty()) { + nodeTypeArtifactsToHandle.put(ArtifactsBusinessLogic.ArtifactOperationEnum.CREATE, artifactsToUpload); + } + if (!artifactsToUpdate.isEmpty()) { + nodeTypeArtifactsToHandle.put(ArtifactsBusinessLogic.ArtifactOperationEnum.UPDATE, artifactsToUpdate); + } + if (!artifactsToDelete.isEmpty()) { + nodeTypeArtifactsToHandle.put(ArtifactsBusinessLogic.ArtifactOperationEnum.DELETE, artifactsToDelete); + } + } + return nodeTypeArtifactsToHandle; + } + + protected void processExistingNodeTypeArtifacts(List<ArtifactDefinition> extractedArtifacts, List<ArtifactDefinition> artifactsToUpload, + List<ArtifactDefinition> artifactsToUpdate, List<ArtifactDefinition> artifactsToDelete, + Map<String, ArtifactDefinition> existingArtifacts) { + try { + if (!existingArtifacts.isEmpty()) { + extractedArtifacts.stream() + .forEach(a -> processNodeTypeArtifact(artifactsToUpload, artifactsToUpdate, existingArtifacts, a)); + artifactsToDelete.addAll(existingArtifacts.values()); + } + } catch (Exception e) { + log.debug("Exception occured when processExistingNodeTypeArtifacts, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + + } + + protected void processNodeTypeArtifact(List<ArtifactDefinition> artifactsToUpload, List<ArtifactDefinition> artifactsToUpdate, Map<String, ArtifactDefinition> existingArtifacts, ArtifactDefinition currNewArtifact) { + Optional<ArtifactDefinition> foundArtifact = existingArtifacts.values() + .stream() + .filter(a -> a.getArtifactName().equals(currNewArtifact.getArtifactName())) + .findFirst(); + if (foundArtifact.isPresent()) { + if (foundArtifact.get().getArtifactType().equals(currNewArtifact.getArtifactType())) { + updateFoundArtifact(artifactsToUpdate, currNewArtifact, foundArtifact.get()); + existingArtifacts.remove(foundArtifact.get().getArtifactLabel()); + artifactsToUpload.remove(currNewArtifact); + } else { + log.debug("Can't upload two artifact with the same name {}.", currNewArtifact.getArtifactName()); + throw new ComponentException(ActionStatus.ARTIFACT_ALREADY_EXIST_IN_DIFFERENT_TYPE_IN_CSAR, + currNewArtifact.getArtifactName(), currNewArtifact.getArtifactType(), + foundArtifact.get().getArtifactType()); + } + } + } + + protected void updateFoundArtifact(List<ArtifactDefinition> artifactsToUpdate, ArtifactDefinition currNewArtifact, ArtifactDefinition foundArtifact) { + if (!foundArtifact.getArtifactChecksum().equals(currNewArtifact.getArtifactChecksum())) { + foundArtifact.setPayload(currNewArtifact.getPayloadData()); + foundArtifact.setPayloadData( + Base64.encodeBase64String(currNewArtifact.getPayloadData())); + foundArtifact.setArtifactChecksum(GeneralUtility + .calculateMD5Base64EncodedByByteArray(currNewArtifact.getPayloadData())); + artifactsToUpdate.add(foundArtifact); + } + } + + public void addNonMetaCreatedArtifactsToSupportRollback(ArtifactOperationInfo operation, + List<ArtifactDefinition> createdArtifacts, + Either<Either<ArtifactDefinition, Operation>, ResponseFormat> eitherNonMetaArtifacts) { + if (ArtifactsBusinessLogic.ArtifactOperationEnum.isCreateOrLink(operation.getArtifactOperationEnum()) && createdArtifacts != null + && eitherNonMetaArtifacts.isLeft()) { + Either<ArtifactDefinition, Operation> eitherResult = eitherNonMetaArtifacts.left().value(); + if (eitherResult.isLeft()) { + createdArtifacts.add(eitherResult.left().value()); + } + } + } + + public boolean isArtifactDeletionRequired(String artifactId, byte[] artifactFileBytes, boolean isFromCsar) { + return !org.apache.commons.lang.StringUtils.isEmpty(artifactId) && artifactFileBytes == null && isFromCsar; + } + + public void fillGroupsFinalFields(List<GroupDefinition> groupsAsList) { + groupsAsList.forEach(groupDefinition -> { + groupDefinition.setInvariantName(groupDefinition.getName()); + groupDefinition.setCreatedFrom(CreatedFrom.CSAR); + }); + } + + public String getComponentTypeForResponse(Component component) { + String componentTypeForResponse = "SERVICE"; + if (component instanceof Resource) { + componentTypeForResponse = ((Resource) component).getResourceType().name(); + } + return componentTypeForResponse; + } + + protected boolean isfillGroupMemebersRecursivlyStopCondition(String groupName, Map<String, GroupDefinition> allGroups, + Set<String> allGroupMembers) { + + boolean stop = false; + // In Case Not Group Stop + if (!allGroups.containsKey(groupName)) { + stop = true; + } + // In Case Group Has no members stop + if (!stop) { + GroupDefinition groupDefinition = allGroups.get(groupName); + stop = MapUtils.isEmpty(groupDefinition.getMembers()); + + } + // In Case all group members already contained stop + if (!stop) { + final Set<String> allMembers = allGroups.get(groupName).getMembers().keySet(); + Set<String> membersOfTypeGroup = allMembers.stream(). + // Filter In Only Group members + filter(allGroups::containsKey). + // Collect + collect(toSet()); + stop = allGroupMembers.containsAll(membersOfTypeGroup); + } + return stop; + } + + public Resource buildValidComplexVfc(Resource resource, CsarInfo csarInfo, String nodeName, + Map<String, NodeTypeInfo> nodesInfo) { + + Resource complexVfc = buildComplexVfcMetadata(resource, csarInfo, nodeName, nodesInfo); + log.debug("************* Going to validate complex VFC from yaml {}", complexVfc.getName()); + csarInfo.addNodeToQueue(nodeName); + return validateResourceBeforeCreate(complexVfc, csarInfo.getModifier(), + AuditingActionEnum.IMPORT_RESOURCE, true, csarInfo); + } + + public Resource validateResourceBeforeCreate(Resource resource, User user, AuditingActionEnum actionEnum, boolean inTransaction, CsarInfo csarInfo) { + + validateResourceFieldsBeforeCreate(user, resource, actionEnum, inTransaction); + validateCapabilityTypesCreate(user, getCapabilityTypeOperation(), resource, actionEnum, inTransaction); + validateLifecycleTypesCreate(user, resource, actionEnum); + validateResourceType(user, resource, actionEnum); + resource.setCreatorUserId(user.getUserId()); + resource.setCreatorFullName(user.getFirstName() + " " + user.getLastName()); + resource.setContactId(resource.getContactId().toLowerCase()); + if (org.apache.commons.lang.StringUtils.isEmpty(resource.getToscaResourceName()) && !ModelConverter.isAtomicComponent(resource)) { + String resourceSystemName; + if (csarInfo != null && org.apache.commons.lang.StringUtils.isNotEmpty(csarInfo.getVfResourceName())) { + resourceSystemName = ValidationUtils.convertToSystemName(csarInfo.getVfResourceName()); + } else { + resourceSystemName = resource.getSystemName(); + } + resource.setToscaResourceName(CommonBeUtils + .generateToscaResourceName(resource.getResourceType().name().toLowerCase(), resourceSystemName)); + } + + // Generate invariant UUID - must be here and not in operation since it + // should stay constant during clone + // TODO + String invariantUUID = UniqueIdBuilder.buildInvariantUUID(); + resource.setInvariantUUID(invariantUUID); + + return resource; + } + + protected Either<Boolean, ResponseFormat> validateResourceType(User user, Resource resource, + AuditingActionEnum actionEnum) { + Either<Boolean, ResponseFormat> eitherResult = Either.left(true); + if (resource.getResourceType() == null) { + log.debug("Invalid resource type for resource"); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT); + eitherResult = Either.right(errorResponse); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + } + return eitherResult; + } + + protected Either<Boolean, ResponseFormat> validateLifecycleTypesCreate(User user, Resource resource, + AuditingActionEnum actionEnum) { + Either<Boolean, ResponseFormat> eitherResult = Either.left(true); + if (resource.getInterfaces() != null && resource.getInterfaces().size() > 0) { + log.debug("validate interface lifecycle Types Exist"); + Iterator<InterfaceDefinition> intItr = resource.getInterfaces().values().iterator(); + while (intItr.hasNext() && eitherResult.isLeft()) { + InterfaceDefinition interfaceDefinition = intItr.next(); + String intType = interfaceDefinition.getUniqueId(); + Either<InterfaceDefinition, StorageOperationStatus> eitherCapTypeFound = interfaceTypeOperation + .getInterface(intType); + if (eitherCapTypeFound.isRight()) { + if (eitherCapTypeFound.right().value() == StorageOperationStatus.NOT_FOUND) { + BeEcompErrorManager.getInstance().logBeGraphObjectMissingError( + "Create Resource - validateLifecycleTypesCreate", "Interface", intType); + log.debug("Lifecycle Type: {} is required by resource: {} but does not exist in the DB", + intType, resource.getName()); + BeEcompErrorManager.getInstance() + .logBeDaoSystemError("Create Resource - validateLifecycleTypesCreate"); + log.debug("request to data model failed with error: {}", + eitherCapTypeFound.right().value().name()); + } + ResponseFormat errorResponse = componentsUtils + .getResponseFormat(ActionStatus.MISSING_LIFECYCLE_TYPE, intType); + eitherResult = Either.right(errorResponse); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + } + } + } + return eitherResult; + } + + public Either<Boolean, ResponseFormat> validateCapabilityTypesCreate(User user, + ICapabilityTypeOperation capabilityTypeOperation, Resource resource, AuditingActionEnum actionEnum, + boolean inTransaction) { + + Either<Boolean, ResponseFormat> eitherResult = Either.left(true); + if (resource.getCapabilities() != null && resource.getCapabilities().size() > 0) { + log.debug("validate capability Types Exist - capabilities section"); + + for (Map.Entry<String, List<CapabilityDefinition>> typeEntry : resource.getCapabilities().entrySet()) { + + eitherResult = validateCapabilityTypeExists(user, capabilityTypeOperation, resource, actionEnum, + eitherResult, typeEntry, inTransaction); + if (eitherResult.isRight()) { + return Either.right(eitherResult.right().value()); + } + } + } + if (resource.getRequirements() != null && resource.getRequirements().size() > 0) { + log.debug("validate capability Types Exist - requirements section"); + for (String type : resource.getRequirements().keySet()) { + eitherResult = validateCapabilityTypeExists(user, capabilityTypeOperation, resource, + resource.getRequirements().get(type), actionEnum, eitherResult, type, inTransaction); + if (eitherResult.isRight()) { + return Either.right(eitherResult.right().value()); + } + } + } + return eitherResult; + } + + protected Either<Boolean, ResponseFormat> validateCapabilityTypeExists(User user, + ICapabilityTypeOperation capabilityTypeOperation, Resource resource, AuditingActionEnum actionEnum, + Either<Boolean, ResponseFormat> eitherResult, Map.Entry<String, List<CapabilityDefinition>> typeEntry, + boolean inTransaction) { + Either<CapabilityTypeDefinition, StorageOperationStatus> eitherCapTypeFound = capabilityTypeOperation + .getCapabilityType(typeEntry.getKey(), inTransaction); + if (eitherCapTypeFound.isRight()) { + if (eitherCapTypeFound.right().value() == StorageOperationStatus.NOT_FOUND) { + BeEcompErrorManager.getInstance().logBeGraphObjectMissingError( + CREATE_RESOURCE_VALIDATE_CAPABILITY_TYPES, "Capability Type", typeEntry.getKey()); + log.debug("Capability Type: {} is required by resource: {} but does not exist in the DB", + typeEntry.getKey(), resource.getName()); + BeEcompErrorManager.getInstance() + .logBeDaoSystemError(CREATE_RESOURCE_VALIDATE_CAPABILITY_TYPES); + } + log.debug("Trying to get capability type {} failed with error: {}", typeEntry.getKey(), + eitherCapTypeFound.right().value().name()); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.MISSING_CAPABILITY_TYPE, + typeEntry.getKey()); + eitherResult = Either.right(errorResponse); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + return Either.right(eitherResult.right().value()); + } + CapabilityTypeDefinition capabilityTypeDefinition = eitherCapTypeFound.left().value(); + if (capabilityTypeDefinition.getProperties() != null) { + for (CapabilityDefinition capDef : typeEntry.getValue()) { + List<ComponentInstanceProperty> properties = capDef.getProperties(); + if (properties == null || properties.isEmpty()) { + properties = new ArrayList<>(); + for (Map.Entry<String, PropertyDefinition> prop : capabilityTypeDefinition.getProperties().entrySet()) { + ComponentInstanceProperty newProp = new ComponentInstanceProperty(prop.getValue()); + properties.add(newProp); + } + } else { + for (Map.Entry<String, PropertyDefinition> prop : capabilityTypeDefinition.getProperties().entrySet()) { + PropertyDefinition porpFromDef = prop.getValue(); + List<ComponentInstanceProperty> propsToAdd = new ArrayList<>(); + for (ComponentInstanceProperty cip : properties) { + if (!cip.getName().equals(porpFromDef.getName())) { + ComponentInstanceProperty newProp = new ComponentInstanceProperty(porpFromDef); + propsToAdd.add(newProp); + } + } + if (!propsToAdd.isEmpty()) { + properties.addAll(propsToAdd); + } + } + } + capDef.setProperties(properties); + } + } + return eitherResult; + } + + protected Either<Boolean, ResponseFormat> validateCapabilityTypeExists(User user, + ICapabilityTypeOperation capabilityTypeOperation, Resource resource, List<?> validationObjects, + AuditingActionEnum actionEnum, Either<Boolean, ResponseFormat> eitherResult, String type, + boolean inTransaction) { + try { + Either<CapabilityTypeDefinition, StorageOperationStatus> eitherCapTypeFound = capabilityTypeOperation + .getCapabilityType(type, inTransaction); + if (eitherCapTypeFound.isRight()) { + if (eitherCapTypeFound.right().value() == StorageOperationStatus.NOT_FOUND) { + BeEcompErrorManager.getInstance().logBeGraphObjectMissingError( + CREATE_RESOURCE_VALIDATE_CAPABILITY_TYPES, "Capability Type", type); + log.debug("Capability Type: {} is required by resource: {} but does not exist in the DB", type, + resource.getName()); + BeEcompErrorManager.getInstance() + .logBeDaoSystemError(CREATE_RESOURCE_VALIDATE_CAPABILITY_TYPES); + } + log.debug("Trying to get capability type {} failed with error: {}", type, + eitherCapTypeFound.right().value().name()); + ResponseFormat errorResponse = null; + if (type != null) { + errorResponse = componentsUtils.getResponseFormat(ActionStatus.MISSING_CAPABILITY_TYPE, type); + } else { + errorResponse = componentsUtils.getResponseFormatByElement(ActionStatus.MISSING_CAPABILITY_TYPE, + validationObjects); + } + eitherResult = Either.right(errorResponse); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + } + + } catch (Exception e) { + log.debug("Exception occured when validateCapabilityTypeExists, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.INVALID_TOSCA_TEMPLATE, resource.getName()); + } + return eitherResult; + } + + protected Either<Boolean, ResponseFormat> validateResourceFieldsBeforeCreate(User user, Resource resource, + AuditingActionEnum actionEnum, boolean inTransaction) { + serviceBusinessLogic.validateComponentFieldsBeforeCreate(user, resource, actionEnum); + // validate category + log.debug("validate category"); + validateCategory(user, resource, actionEnum, inTransaction); + // validate vendor name & release & model number + log.debug("validate vendor name"); + validateVendorName(user, resource, actionEnum); + log.debug("validate vendor release"); + validateVendorReleaseName(user, resource, actionEnum); + log.debug("validate resource vendor model number"); + validateResourceVendorModelNumber(user, resource, actionEnum); + // validate cost + log.debug("validate cost"); + validateCost(resource); + // validate licenseType + log.debug("validate licenseType"); + validateLicenseType(user, resource, actionEnum); + // validate template (derived from) + log.debug("validate derived from"); + if (!ModelConverter.isAtomicComponent(resource) && resource.getResourceType() != ResourceTypeEnum.VF) { + resource.setDerivedFrom(null); + } + validateDerivedFromExist(user, resource, actionEnum); + serviceBusinessLogic.checkComponentFieldsForOverrideAttempt(resource); + String currentCreatorFullName = resource.getCreatorFullName(); + if (currentCreatorFullName != null) { + log.debug("Resource Creator fullname is automatically set and cannot be updated"); + } + + String currentLastUpdaterFullName = resource.getLastUpdaterFullName(); + if (currentLastUpdaterFullName != null) { + log.debug("Resource LastUpdater fullname is automatically set and cannot be updated"); + } + + Long currentLastUpdateDate = resource.getLastUpdateDate(); + if (currentLastUpdateDate != null) { + log.debug("Resource last update date is automatically set and cannot be updated"); + } + + Boolean currentAbstract = resource.isAbstract(); + if (currentAbstract != null) { + log.debug("Resource abstract is automatically set and cannot be updated"); + } + + return Either.left(true); + } + + protected void validateDerivedFromExist(User user, Resource resource, AuditingActionEnum actionEnum) { + if (resource.getDerivedFrom() == null || resource.getDerivedFrom().isEmpty()) { + return; + } + String templateName = resource.getDerivedFrom().get(0); + Either<Boolean, StorageOperationStatus> dataModelResponse = toscaOperationFacade + .validateToscaResourceNameExists(templateName); + if (dataModelResponse.isRight()) { + StorageOperationStatus storageStatus = dataModelResponse.right().value(); + BeEcompErrorManager.getInstance().logBeDaoSystemError("Create Resource - validateDerivedFromExist"); + log.debug("request to data model failed with error: {}", storageStatus); + ResponseFormat responseFormat = componentsUtils + .getResponseFormatByResource(componentsUtils.convertFromStorageResponse(storageStatus), resource); + log.trace("audit before sending response"); + componentsUtils.auditResource(responseFormat, user, resource, actionEnum); + throw new ComponentException(componentsUtils.convertFromStorageResponse(storageStatus)); + } else if (!dataModelResponse.left().value()) { + log.info("resource template with name: {}, does not exists", templateName); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.PARENT_RESOURCE_NOT_FOUND); + componentsUtils.auditResource(responseFormat, user, resource, actionEnum); + throw new ComponentException(ActionStatus.PARENT_RESOURCE_NOT_FOUND); + } + } + + protected void validateLicenseType(User user, Resource resource, + AuditingActionEnum actionEnum) { + log.debug("validate licenseType"); + String licenseType = resource.getLicenseType(); + if (licenseType != null) { + List<String> licenseTypes = ConfigurationManager.getConfigurationManager().getConfiguration() + .getLicenseTypes(); + if (!licenseTypes.contains(licenseType)) { + log.debug("License type {} isn't configured", licenseType); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_CONTENT); + if (actionEnum != null) { + // In update case, no audit is required + componentsUtils.auditResource(responseFormat, user, resource, actionEnum); + } + throw new ComponentException(ActionStatus.INVALID_CONTENT); + } + } + } + + protected void validateCost(Resource resource) { + String cost = resource.getCost(); + if (cost != null) { + if (!ValidationUtils.validateCost(cost)) { + log.debug("resource cost is invalid."); + throw new ComponentException(ActionStatus.INVALID_CONTENT); + } + } + } + + protected void validateResourceVendorModelNumber(User user, Resource resource, AuditingActionEnum actionEnum) { + String resourceVendorModelNumber = resource.getResourceVendorModelNumber(); + if (org.apache.commons.lang.StringUtils.isNotEmpty(resourceVendorModelNumber)) { + if (!ValidationUtils.validateResourceVendorModelNumberLength(resourceVendorModelNumber)) { + log.info("resource vendor model number exceeds limit."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat( + ActionStatus.RESOURCE_VENDOR_MODEL_NUMBER_EXCEEDS_LIMIT, + "" + ValidationUtils.RESOURCE_VENDOR_MODEL_NUMBER_MAX_LENGTH); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + throw new ComponentException(ActionStatus.RESOURCE_VENDOR_MODEL_NUMBER_EXCEEDS_LIMIT, + "" + ValidationUtils.RESOURCE_VENDOR_MODEL_NUMBER_MAX_LENGTH); + } + // resource vendor model number is currently validated as vendor + // name + if (!ValidationUtils.validateVendorName(resourceVendorModelNumber)) { + log.info("resource vendor model number is not valid."); + ResponseFormat errorResponse = componentsUtils + .getResponseFormat(ActionStatus.INVALID_RESOURCE_VENDOR_MODEL_NUMBER); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + throw new ComponentException(ActionStatus.INVALID_RESOURCE_VENDOR_MODEL_NUMBER); + } + } + } + + public void validateVendorReleaseName(User user, Resource resource, AuditingActionEnum actionEnum) { + String vendorRelease = resource.getVendorRelease(); + log.debug("validate vendor relese name"); + if (!ValidationUtils.validateStringNotEmpty(vendorRelease)) { + log.info("vendor relese name is missing."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.MISSING_VENDOR_RELEASE); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + throw new ComponentException(ActionStatus.MISSING_VENDOR_RELEASE); + } + + validateVendorReleaseName(vendorRelease, user, resource, actionEnum); + } + + public void validateVendorReleaseName(String vendorRelease, User user, Resource resource, AuditingActionEnum actionEnum) { + if (vendorRelease != null) { + if (!ValidationUtils.validateVendorReleaseLength(vendorRelease)) { + log.info("vendor release exceds limit."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat( + ActionStatus.VENDOR_RELEASE_EXCEEDS_LIMIT, "" + ValidationUtils.VENDOR_RELEASE_MAX_LENGTH); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + throw new ComponentException(ActionStatus.VENDOR_RELEASE_EXCEEDS_LIMIT, "" + ValidationUtils.VENDOR_RELEASE_MAX_LENGTH); + } + + if (!ValidationUtils.validateVendorRelease(vendorRelease)) { + log.info("vendor release is not valid."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_VENDOR_RELEASE); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + throw new ComponentException(ActionStatus.INVALID_VENDOR_RELEASE); + } + } + } + + protected void validateCategory(User user, Resource resource, + AuditingActionEnum actionEnum, boolean inTransaction) { + + List<CategoryDefinition> categories = resource.getCategories(); + if (CollectionUtils.isEmpty(categories)) { + log.debug(CATEGORY_IS_EMPTY); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_CATEGORY, + ComponentTypeEnum.RESOURCE.getValue()); + componentsUtils.auditResource(responseFormat, user, resource, actionEnum); + throw new ComponentException(ActionStatus.COMPONENT_MISSING_CATEGORY, + ComponentTypeEnum.RESOURCE.getValue()); + } + if (categories.size() > 1) { + log.debug("Must be only one category for resource"); + throw new ComponentException(ActionStatus.COMPONENT_TOO_MUCH_CATEGORIES, ComponentTypeEnum.RESOURCE.getValue()); + } + CategoryDefinition category = categories.get(0); + List<SubCategoryDefinition> subcategories = category.getSubcategories(); + if (CollectionUtils.isEmpty(subcategories)) { + log.debug("Missinig subcategory for resource"); + throw new ComponentException(ActionStatus.COMPONENT_MISSING_SUBCATEGORY); + } + if (subcategories.size() > 1) { + log.debug("Must be only one sub category for resource"); + throw new ComponentException(ActionStatus.RESOURCE_TOO_MUCH_SUBCATEGORIES); + } + + SubCategoryDefinition subcategory = subcategories.get(0); + + if (!ValidationUtils.validateStringNotEmpty(category.getName())) { + log.debug(CATEGORY_IS_EMPTY); + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_MISSING_CATEGORY, + ComponentTypeEnum.RESOURCE.getValue()); + componentsUtils.auditResource(responseFormat, user, resource, actionEnum); + throw new ComponentException(ActionStatus.COMPONENT_MISSING_CATEGORY, + ComponentTypeEnum.RESOURCE.getValue()); + } + if (!ValidationUtils.validateStringNotEmpty(subcategory.getName())) { + log.debug(CATEGORY_IS_EMPTY); + ResponseFormat responseFormat = componentsUtils.getResponseFormat( + ActionStatus.COMPONENT_MISSING_SUBCATEGORY, ComponentTypeEnum.RESOURCE.getValue()); + componentsUtils.auditResource(responseFormat, user, resource, actionEnum); + throw new ComponentException(ActionStatus.COMPONENT_MISSING_SUBCATEGORY, ComponentTypeEnum.RESOURCE.getValue()); + } + + validateCategoryListed(category, subcategory, user, resource, actionEnum, inTransaction); + } + + protected void validateCategoryListed(CategoryDefinition category, SubCategoryDefinition subcategory, + User user, Resource resource, AuditingActionEnum actionEnum, boolean inTransaction) { + ResponseFormat responseFormat; + if (category != null && subcategory != null) { + try { + log.debug("validating resource category {} against valid categories list", category); + Either<List<CategoryDefinition>, ActionStatus> categories = serviceBusinessLogic.elementDao + .getAllCategories(NodeTypeEnum.ResourceNewCategory, inTransaction); + if (categories.isRight()) { + log.debug("failed to retrieve resource categories from Titan"); + responseFormat = componentsUtils.getResponseFormat(categories.right().value()); + componentsUtils.auditResource(responseFormat, user, resource, actionEnum); + throw new ComponentException(categories.right().value()); + } + List<CategoryDefinition> categoryList = categories.left().value(); + Optional<CategoryDefinition> foundCategory = categoryList.stream() + .filter(cat -> cat.getName().equals(category.getName())) + .findFirst(); + if (!foundCategory.isPresent()) { + log.debug( + "Category {} is not part of resource category group. Resource category valid values are {}", + category, categoryList); + failOnInvalidCategory(user, resource, actionEnum); + } + Optional<SubCategoryDefinition> foundSubcategory = foundCategory.get() + .getSubcategories() + .stream() + .filter(subcat -> subcat.getName().equals(subcategory.getName())) + .findFirst(); + if (!foundSubcategory.isPresent()) { + log.debug( + "SubCategory {} is not part of resource category group. Resource subcategory valid values are {}", + subcategory, foundCategory.get().getSubcategories()); + failOnInvalidCategory(user, resource, actionEnum); + } + }catch(Exception e){ + log.debug("Exception occured when validateCategoryListed, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + } + + protected void failOnInvalidCategory(User user, Resource resource, AuditingActionEnum actionEnum) { + ResponseFormat responseFormat; + responseFormat = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_INVALID_CATEGORY, + ComponentTypeEnum.RESOURCE.getValue()); + componentsUtils.auditResource(responseFormat, user, resource, actionEnum); + throw new ComponentException(ActionStatus.COMPONENT_INVALID_CATEGORY, + ComponentTypeEnum.RESOURCE.getValue()); + } + + protected void validateVendorName(User user, Resource resource, + AuditingActionEnum actionEnum) { + String vendorName = resource.getVendorName(); + if (!ValidationUtils.validateStringNotEmpty(vendorName)) { + log.info("vendor name is missing."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.MISSING_VENDOR_NAME); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + throw new ComponentException(ActionStatus.MISSING_VENDOR_NAME); + } + validateVendorName(vendorName, user, resource, actionEnum); + } + + protected void validateVendorName(String vendorName, User user, Resource resource, + AuditingActionEnum actionEnum) { + if (vendorName != null) { + if (!ValidationUtils.validateVendorNameLength(vendorName)) { + log.info("vendor name exceds limit."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.VENDOR_NAME_EXCEEDS_LIMIT, + "" + ValidationUtils.VENDOR_NAME_MAX_LENGTH); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + throw new ComponentException(ActionStatus.VENDOR_NAME_EXCEEDS_LIMIT, + "" + ValidationUtils.VENDOR_NAME_MAX_LENGTH); + } + + if (!ValidationUtils.validateVendorName(vendorName)) { + log.info("vendor name is not valid."); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.INVALID_VENDOR_NAME); + componentsUtils.auditResource(errorResponse, user, resource, actionEnum); + throw new ComponentException(ActionStatus.INVALID_VENDOR_NAME); + } + } + } + + private Resource buildComplexVfcMetadata(Resource resourceVf, CsarInfo csarInfo, String nodeName, + Map<String, NodeTypeInfo> nodesInfo) { + Resource cvfc = new Resource(); + NodeTypeInfo nodeTypeInfo = nodesInfo.get(nodeName); + cvfc.setName(buildCvfcName(csarInfo.getVfResourceName(), nodeName)); + cvfc.setNormalizedName(ValidationUtils.normaliseComponentName(cvfc.getName())); + cvfc.setSystemName(ValidationUtils.convertToSystemName(cvfc.getName())); + cvfc.setResourceType(ResourceTypeEnum.VF); + cvfc.setAbstract(true); + cvfc.setDerivedFrom(nodeTypeInfo.getDerivedFrom()); + cvfc.setDescription(ImportUtils.Constants.CVFC_DESCRIPTION); + cvfc.setIcon(ImportUtils.Constants.DEFAULT_ICON); + cvfc.setContactId(csarInfo.getModifier().getUserId()); + cvfc.setCreatorUserId(csarInfo.getModifier().getUserId()); + cvfc.setVendorName(resourceVf.getVendorName()); + cvfc.setVendorRelease(resourceVf.getVendorRelease()); + cvfc.setResourceVendorModelNumber(resourceVf.getResourceVendorModelNumber()); + cvfc.setToscaResourceName( + buildNestedToscaResourceName(ResourceTypeEnum.VF.name(), csarInfo.getVfResourceName(), nodeName) + .getLeft()); + cvfc.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID()); + + List<String> tags = new ArrayList<>(); + tags.add(cvfc.getName()); + cvfc.setTags(tags); + + CategoryDefinition category = new CategoryDefinition(); + category.setName(ImportUtils.Constants.ABSTRACT_CATEGORY_NAME); + SubCategoryDefinition subCategory = new SubCategoryDefinition(); + subCategory.setName(ImportUtils.Constants.ABSTRACT_SUBCATEGORY); + category.addSubCategory(subCategory); + List<CategoryDefinition> categories = new ArrayList<>(); + categories.add(category); + cvfc.setCategories(categories); + + cvfc.setVersion(ImportUtils.Constants.FIRST_NON_CERTIFIED_VERSION); + cvfc.setLifecycleState(ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT); + cvfc.setHighestVersion(ImportUtils.Constants.NORMATIVE_TYPE_HIGHEST_VERSION); + + return cvfc; + } + + private String buildCvfcName(String resourceVfName, String nodeName) { + String nameWithouNamespacePrefix = nodeName + .substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length()); + String[] findTypes = nameWithouNamespacePrefix.split("\\."); + String resourceType = findTypes[0]; + String resourceName = resourceVfName + "-" + nameWithouNamespacePrefix.substring(resourceType.length() + 1); + return addCvfcSuffixToResourceName(resourceName); + } + + private String addCvfcSuffixToResourceName(String resourceName) { + return resourceName + "VF"; + } + + public UploadResourceInfo fillResourceMetadata(String yamlName, Resource resourceVf, + String nodeName, User user) { + UploadResourceInfo resourceMetaData = new UploadResourceInfo(); + + // validate nodetype name prefix + if (!nodeName.startsWith(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX)) { + log.debug("invalid nodeName:{} does not start with {}.", nodeName, + Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX); + throw new ComponentException(ActionStatus.INVALID_NODE_TEMPLATE, + yamlName, resourceMetaData.getName(), nodeName); + } + + String actualName = this.getNodeTypeActualName(nodeName); + String namePrefix = nodeName.replace(actualName, ""); + String resourceType = namePrefix.substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length()); + + // if we import from csar, the node_type name can be + // org.openecomp.resource.abstract.node_name - in this case we always + // create a vfc + if (resourceType.equals(Constants.ABSTRACT)) { + resourceType = ResourceTypeEnum.VFC.name().toLowerCase(); + } + // validating type + if (!ResourceTypeEnum.containsName(resourceType.toUpperCase())) { + log.debug("invalid resourceType:{} the type is not one of the valide types:{}.", resourceType.toUpperCase(), + ResourceTypeEnum.values()); + throw new ComponentException(ActionStatus.INVALID_NODE_TEMPLATE, + yamlName, resourceMetaData.getName(), nodeName); + } + + // Setting name + resourceMetaData.setName(resourceVf.getSystemName() + actualName); + + // Setting type from name + String type = resourceType.toUpperCase(); + resourceMetaData.setResourceType(type); + + resourceMetaData.setDescription(ImportUtils.Constants.INNER_VFC_DESCRIPTION); + resourceMetaData.setIcon(ImportUtils.Constants.DEFAULT_ICON); + resourceMetaData.setContactId(user.getUserId()); + resourceMetaData.setVendorName(resourceVf.getVendorName()); + resourceMetaData.setVendorRelease(resourceVf.getVendorRelease()); + + // Setting tag + List<String> tags = new ArrayList<>(); + tags.add(resourceMetaData.getName()); + resourceMetaData.setTags(tags); + + // Setting category + CategoryDefinition category = new CategoryDefinition(); + category.setName(ImportUtils.Constants.ABSTRACT_CATEGORY_NAME); + SubCategoryDefinition subCategory = new SubCategoryDefinition(); + subCategory.setName(ImportUtils.Constants.ABSTRACT_SUBCATEGORY); + category.addSubCategory(subCategory); + List<CategoryDefinition> categories = new ArrayList<>(); + categories.add(category); + resourceMetaData.setCategories(categories); + + return resourceMetaData; + } + + protected String getNodeTypeActualName(String fullName) { + String nameWithouNamespacePrefix = fullName + .substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length()); + String[] findTypes = nameWithouNamespacePrefix.split("\\."); + String resourceType = findTypes[0]; + return nameWithouNamespacePrefix.substring(resourceType.length()); + } + + public void addInput(Map<String, InputDefinition> currPropertiesMap, InputDefinition prop) { + String propName = prop.getName(); + if (!currPropertiesMap.containsKey(propName)) { + currPropertiesMap.put(propName, prop); + } + } + + public Either<RequirementDefinition, ResponseFormat> findAviableRequiremen(String regName, String yamlName, + UploadComponentInstanceInfo uploadComponentInstanceInfo, ComponentInstance currentCompInstance, + String capName) { + Map<String, List<RequirementDefinition>> comInstRegDefMap = currentCompInstance.getRequirements(); + List<RequirementDefinition> list = comInstRegDefMap.get(capName); + RequirementDefinition validRegDef = null; + if (list == null) { + for (Map.Entry<String, List<RequirementDefinition>> entry : comInstRegDefMap.entrySet()) { + for (RequirementDefinition reqDef : entry.getValue()) { + if (reqDef.getName().equals(regName)) { + if (reqDef.getMaxOccurrences() != null + && !reqDef.getMaxOccurrences().equals(RequirementDataDefinition.MAX_OCCURRENCES)) { + String leftOccurrences = reqDef.getLeftOccurrences(); + if (leftOccurrences == null) { + leftOccurrences = reqDef.getMaxOccurrences(); + } + int left = Integer.parseInt(leftOccurrences); + if (left > 0) { + --left; + reqDef.setLeftOccurrences(String.valueOf(left)); + validRegDef = reqDef; + break; + } else { + continue; + } + } else { + validRegDef = reqDef; + break; + } + + } + } + if (validRegDef != null) { + break; + } + } + } else { + for (RequirementDefinition reqDef : list) { + if (reqDef.getName().equals(regName)) { + if (reqDef.getMaxOccurrences() != null + && !reqDef.getMaxOccurrences().equals(RequirementDataDefinition.MAX_OCCURRENCES)) { + String leftOccurrences = reqDef.getLeftOccurrences(); + if (leftOccurrences == null) { + leftOccurrences = reqDef.getMaxOccurrences(); + } + int left = Integer.parseInt(leftOccurrences); + if (left > 0) { + --left; + reqDef.setLeftOccurrences(String.valueOf(left)); + validRegDef = reqDef; + break; + } else { + continue; + } + } else { + validRegDef = reqDef; + break; + } + } + } + } + if (validRegDef == null) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.INVALID_NODE_TEMPLATE, + yamlName, uploadComponentInstanceInfo.getName(), uploadComponentInstanceInfo.getType()); + return Either.right(responseFormat); + } + return Either.left(validRegDef); + } + + public CapabilityDefinition findAvailableCapabilityByTypeOrName(RequirementDefinition validReq, + ComponentInstance currentCapCompInstance, UploadReqInfo uploadReqInfo) { + try { + if (null == uploadReqInfo.getCapabilityName() + || validReq.getCapability().equals(uploadReqInfo.getCapabilityName())) { + // get by capability type + return findAvailableCapability(validReq, currentCapCompInstance); + } + return findAvailableCapability(validReq, currentCapCompInstance, uploadReqInfo); + }catch (Exception e){ + log.debug("Exception occured when findAvailableCapabilityByTypeOrName, error is:{}", e.getMessage(), e); + throw new ComponentException(ActionStatus.GENERAL_ERROR); + } + } + + protected CapabilityDefinition findAvailableCapability(RequirementDefinition validReq, ComponentInstance instance) { + Map<String, List<CapabilityDefinition>> capMap = instance.getCapabilities(); + if (capMap.containsKey(validReq.getCapability())) { + List<CapabilityDefinition> capList = capMap.get(validReq.getCapability()); + + for (CapabilityDefinition cap : capList) { + if (isBoundedByOccurrences(cap)) { + String leftOccurrences = cap.getLeftOccurrences() != null ? + cap.getLeftOccurrences() : cap.getMaxOccurrences(); + int left = Integer.parseInt(leftOccurrences); + if (left > 0) { + --left; + cap.setLeftOccurrences(String.valueOf(left)); + return cap; + } + } else { + return cap; + } + } + } + return null; + } + + protected CapabilityDefinition findAvailableCapability(RequirementDefinition validReq, + ComponentInstance currentCapCompInstance, UploadReqInfo uploadReqInfo) { + CapabilityDefinition cap = null; + Map<String, List<CapabilityDefinition>> capMap = currentCapCompInstance.getCapabilities(); + if (!capMap.containsKey(validReq.getCapability())) { + return null; + } + Optional<CapabilityDefinition> capByName = capMap.get(validReq.getCapability()).stream() + .filter(p -> p.getName().equals(uploadReqInfo.getCapabilityName())).findAny(); + if (!capByName.isPresent()) { + return null; + } + cap = capByName.get(); + + if (isBoundedByOccurrences(cap)) { + String leftOccurrences = cap.getLeftOccurrences(); + int left = Integer.parseInt(leftOccurrences); + if (left > 0) { + --left; + cap.setLeftOccurrences(String.valueOf(left)); + + } + + } + return cap; + } + + private boolean isBoundedByOccurrences(CapabilityDefinition cap) { + return cap.getMaxOccurrences() != null && !cap.getMaxOccurrences().equals(CapabilityDataDefinition.MAX_OCCURRENCES); + } + + public ComponentParametersView getComponentFilterAfterCreateRelations() { + ComponentParametersView parametersView = new ComponentParametersView(); + parametersView.disableAll(); + parametersView.setIgnoreComponentInstances(false); + parametersView.setIgnoreComponentInstancesProperties(false); + parametersView.setIgnoreCapabilities(false); + parametersView.setIgnoreRequirements(false); + parametersView.setIgnoreGroups(false); + return parametersView; + } + + public ComponentParametersView getComponentWithInstancesFilter() { + ComponentParametersView parametersView = new ComponentParametersView(); + parametersView.disableAll(); + parametersView.setIgnoreComponentInstances(false); + parametersView.setIgnoreInputs(false); + // inputs are read when creating + // property values on instances + parametersView.setIgnoreUsers(false); + return parametersView; + } + + protected void addValidComponentInstanceCapabilities(String key, List<UploadCapInfo> capabilities, String resourceId, Map<String, List<CapabilityDefinition>> defaultCapabilities, Map<String, List<CapabilityDefinition>> validCapabilitiesMap){ + String capabilityType = capabilities.get(0).getType(); + if (defaultCapabilities.containsKey(capabilityType)) { + CapabilityDefinition defaultCapability = getCapability(resourceId, defaultCapabilities, capabilityType); + validateCapabilityProperties(capabilities, resourceId, defaultCapability); + List<CapabilityDefinition> validCapabilityList = new ArrayList<>(); + validCapabilityList.add(defaultCapability); + validCapabilitiesMap.put(key, validCapabilityList); + } else { + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.MISSING_CAPABILITY_TYPE, capabilityType)); + } + } + + protected CapabilityDefinition getCapability(String resourceId, Map<String, List<CapabilityDefinition>> defaultCapabilities, String capabilityType) { + CapabilityDefinition defaultCapability; + if (isNotEmpty(defaultCapabilities.get(capabilityType).get(0).getProperties())) { + defaultCapability = defaultCapabilities.get(capabilityType).get(0); + } else { + Either<Component, StorageOperationStatus> getFullComponentRes = toscaOperationFacade + .getToscaFullElement(resourceId); + if (getFullComponentRes.isRight()) { + log.debug("Failed to get full component {}. Status is {}. ", resourceId, + getFullComponentRes.right().value()); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.COMPONENT_NOT_FOUND, + resourceId)); + } + defaultCapability = getFullComponentRes.left().value().getCapabilities().get(capabilityType).get(0); + } + return defaultCapability; + } + + protected void validateCapabilityProperties(List<UploadCapInfo> capabilities, String resourceId, CapabilityDefinition defaultCapability) { + if (CollectionUtils.isEmpty(defaultCapability.getProperties()) + && isNotEmpty(capabilities.get(0).getProperties())) { + log.debug("Failed to validate capability {} of component {}. Property list is empty. ", + defaultCapability.getName(), resourceId); + log.debug( + "Failed to update capability property values. Property list of fetched capability {} is empty. ", + defaultCapability.getName()); + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NOT_FOUND, resourceId)); + } else if (isNotEmpty(capabilities.get(0).getProperties())) { + validateUniquenessUpdateUploadedComponentInstanceCapability(defaultCapability, capabilities.get(0)); + } + } + + protected void validateUniquenessUpdateUploadedComponentInstanceCapability( + CapabilityDefinition defaultCapability, UploadCapInfo uploadedCapability) { + List<ComponentInstanceProperty> validProperties = new ArrayList<>(); + Map<String, PropertyDefinition> defaultProperties = defaultCapability.getProperties().stream() + .collect(toMap(PropertyDefinition::getName, Function + .identity())); + List<UploadPropInfo> uploadedProperties = uploadedCapability.getProperties(); + for (UploadPropInfo property : uploadedProperties) { + String propertyName = property.getName().toLowerCase(); + String propertyType = property.getType(); + ComponentInstanceProperty validProperty; + if (defaultProperties.containsKey(propertyName) && propertTypeEqualsTo(defaultProperties, propertyName, propertyType)) { + throw new ComponentException(componentsUtils.getResponseFormat(ActionStatus.PROPERTY_NAME_ALREADY_EXISTS, + propertyName)); + } + validProperty = new ComponentInstanceProperty(); + validProperty.setName(propertyName); + if (property.getValue() != null) { + validProperty.setValue(property.getValue().toString()); + } + validProperty.setDescription(property.getDescription()); + validProperty.setPassword(property.isPassword()); + validProperties.add(validProperty); + } + defaultCapability.setProperties(validProperties); + } + + private boolean propertTypeEqualsTo(Map<String, PropertyDefinition> defaultProperties, String propertyName, String propertyType) { + return propertyType != null && !defaultProperties.get(propertyName).getType().equals(propertyType); + } + + public void setDeploymentArtifactsPlaceHolder(Component component, User user) { + if(component instanceof Service){ + Service service = (Service) component; + Map<String, ArtifactDefinition> artifactMap = service.getDeploymentArtifacts(); + if (artifactMap == null) { + artifactMap = new HashMap<>(); + } + service.setDeploymentArtifacts(artifactMap); + }else if(component instanceof Resource){ + Resource resource = (Resource) component; + Map<String, ArtifactDefinition> artifactMap = resource.getDeploymentArtifacts(); + if (artifactMap == null) { + artifactMap = new HashMap<>(); + } + Map<String, Object> deploymentResourceArtifacts = ConfigurationManager.getConfigurationManager() + .getConfiguration().getDeploymentResourceArtifacts(); + if (deploymentResourceArtifacts != null) { + Map<String, ArtifactDefinition> finalArtifactMap = artifactMap; + deploymentResourceArtifacts.forEach((k, v)->processDeploymentResourceArtifacts(user, resource, finalArtifactMap, k,v)); + } + resource.setDeploymentArtifacts(artifactMap); + } + + } + + protected void processDeploymentResourceArtifacts(User user, Resource resource, Map<String, ArtifactDefinition> artifactMap, String k, Object v) { + boolean shouldCreateArtifact = true; + Map<String, Object> artifactDetails = (Map<String, Object>) v; + Object object = artifactDetails.get(PLACE_HOLDER_RESOURCE_TYPES); + if (object != null) { + List<String> artifactTypes = (List<String>) object; + if (!artifactTypes.contains(resource.getResourceType().name())) { + shouldCreateArtifact = false; + return; + } + } else { + log.info("resource types for artifact placeholder {} were not defined. default is all resources", + k); + } + if (shouldCreateArtifact) { + if (serviceBusinessLogic.artifactsBusinessLogic != null) { + ArtifactDefinition artifactDefinition = serviceBusinessLogic.artifactsBusinessLogic.createArtifactPlaceHolderInfo( + resource.getUniqueId(), k, (Map<String, Object>) v, + user, ArtifactGroupTypeEnum.DEPLOYMENT); + if (artifactDefinition != null + && !artifactMap.containsKey(artifactDefinition.getArtifactLabel())) { + artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition); + } + } + } + } + + public void mergeOldResourceMetadataWithNew(Resource oldResource, Resource newResource) { + + if (newResource.getTags() == null || newResource.getTags().isEmpty()) { + newResource.setTags(oldResource.getTags()); + } + + if (newResource.getDescription() == null) { + newResource.setDescription(oldResource.getDescription()); + } + + + if (newResource.getContactId() == null) { + newResource.setContactId(oldResource.getContactId()); + } + + newResource.setCategories(oldResource.getCategories()); + + } + + protected Resource buildComplexVfcMetadata(CsarInfo csarInfo, String nodeName, + Map<String, NodeTypeInfo> nodesInfo) { + Resource cvfc = new Resource(); + NodeTypeInfo nodeTypeInfo = nodesInfo.get(nodeName); + cvfc.setName(buildCvfcName(csarInfo.getVfResourceName(), nodeName)); + cvfc.setNormalizedName(ValidationUtils.normaliseComponentName(cvfc.getName())); + cvfc.setSystemName(ValidationUtils.convertToSystemName(cvfc.getName())); + cvfc.setResourceType(ResourceTypeEnum.VF); + cvfc.setAbstract(true); + cvfc.setDerivedFrom(nodeTypeInfo.getDerivedFrom()); + cvfc.setDescription(ImportUtils.Constants.VF_DESCRIPTION); + cvfc.setIcon(ImportUtils.Constants.DEFAULT_ICON); + cvfc.setContactId(csarInfo.getModifier().getUserId()); + cvfc.setCreatorUserId(csarInfo.getModifier().getUserId()); + cvfc.setVendorName("cmri"); + cvfc.setVendorRelease("1.0"); + cvfc.setResourceVendorModelNumber(""); + cvfc.setToscaResourceName( + buildNestedToscaResourceName(ResourceTypeEnum.VF.name(), csarInfo.getVfResourceName(), nodeName) + .getLeft()); + cvfc.setInvariantUUID(UniqueIdBuilder.buildInvariantUUID()); + + List<String> tags = new ArrayList<>(); + tags.add(cvfc.getName()); + cvfc.setTags(tags); + + CategoryDefinition category = new CategoryDefinition(); + category.setName(ImportUtils.Constants.ABSTRACT_CATEGORY_NAME); + SubCategoryDefinition subCategory = new SubCategoryDefinition(); + subCategory.setName(ImportUtils.Constants.ABSTRACT_SUBCATEGORY); + category.addSubCategory(subCategory); + List<CategoryDefinition> categories = new ArrayList<>(); + categories.add(category); + cvfc.setCategories(categories); + + cvfc.setVersion(ImportUtils.Constants.FIRST_NON_CERTIFIED_VERSION); + cvfc.setLifecycleState(ImportUtils.Constants.NORMATIVE_TYPE_LIFE_CYCLE_NOT_CERTIFIED_CHECKOUT); + cvfc.setHighestVersion(ImportUtils.Constants.NORMATIVE_TYPE_HIGHEST_VERSION); + + return cvfc; + } + + public Boolean validateResourceCreationFromNodeType(Resource resource, User creator) { + validateDerivedFromNotEmpty(creator, resource, AuditingActionEnum.CREATE_RESOURCE); + return true; + } + + private void validateDerivedFromNotEmpty(User user, Resource resource, AuditingActionEnum actionEnum) { + log.debug("validate resource derivedFrom field"); + if ((resource.getDerivedFrom() == null) || (resource.getDerivedFrom().isEmpty()) + || (resource.getDerivedFrom().get(0)) == null || (resource.getDerivedFrom().get(0).trim().isEmpty())) { + log.info("derived from (template) field is missing for the resource"); + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(ActionStatus.MISSING_DERIVED_FROM_TEMPLATE); + componentsUtils.auditResource(responseFormat, user, resource, actionEnum); + + throw new ComponentException(ActionStatus.MISSING_DERIVED_FROM_TEMPLATE); + } + } + + public Service createInputsOnService(Service service, Map<String, InputDefinition> inputs) { + List<InputDefinition> resourceProperties = service.getInputs(); + if (MapUtils.isNotEmpty(inputs)|| isNotEmpty(resourceProperties)) { + + Either<List<InputDefinition>, ResponseFormat> createInputs = inputsBusinessLogic.createInputsInGraph(inputs, + service); + if (createInputs.isRight()) { + throw new ComponentException(createInputs.right().value()); + } + } else { + return service; + } + Either<Service, StorageOperationStatus> updatedResource = toscaOperationFacade + .getToscaElement(service.getUniqueId()); + if (updatedResource.isRight()) { + throw new ComponentException(componentsUtils.getResponseFormatByComponent( + componentsUtils.convertFromStorageResponse(updatedResource.right().value()), service, ComponentTypeEnum.SERVICE)); + } + return updatedResource.left().value(); + } + + + public Service createServiceTransaction(Service service, User user, boolean isNormative) { + // validate resource name uniqueness + log.debug("validate resource name"); + Either<Boolean, StorageOperationStatus> eitherValidation = toscaOperationFacade.validateComponentNameExists( + service.getName(), null, service.getComponentType()); + if (eitherValidation.isRight()) { + log.debug("Failed to validate component name {}. Status is {}. ", service.getName(), + eitherValidation.right().value()); + ResponseFormat errorResponse = componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(eitherValidation.right().value())); + throw new ComponentException(errorResponse); + } + if (eitherValidation.left().value()) { + log.debug("resource with name: {}, already exists", service.getName()); + ResponseFormat errorResponse = componentsUtils.getResponseFormat(ActionStatus.COMPONENT_NAME_ALREADY_EXIST, + ComponentTypeEnum.RESOURCE.getValue(), service.getName()); + throw new ComponentException(errorResponse); + } + + log.debug("send resource {} to dao for create", service.getName()); + + createArtifactsPlaceHolderData(service, user); + // enrich object + if (!isNormative) { + log.debug("enrich resource with creator, version and state"); + service.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + service.setVersion(INITIAL_VERSION); + service.setHighestVersion(true); + } + return toscaOperationFacade.createToscaComponent(service) + .left() + .on(r->throwComponentExceptionByResource(r, service)); + } + + public Service throwComponentExceptionByResource(StorageOperationStatus status, Service service) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByComponent( + componentsUtils.convertFromStorageResponse(status), service, ComponentTypeEnum.SERVICE); + throw new ComponentException(responseFormat); + } + + + protected void createArtifactsPlaceHolderData(Service service, User user) { + setInformationalArtifactsPlaceHolder(service, user); + serviceBusinessLogic.setDeploymentArtifactsPlaceHolder(service, user); + serviceBusinessLogic.setToscaArtifactsPlaceHolders(service, user); + } + + @SuppressWarnings("unchecked") + protected void setInformationalArtifactsPlaceHolder(Service service, User user) { + Map<String, ArtifactDefinition> artifactMap = service.getArtifacts(); + if (artifactMap == null) { + artifactMap = new HashMap<>(); + } + String resourceUniqueId = service.getUniqueId(); + List<String> exludeResourceCategory = ConfigurationManager.getConfigurationManager().getConfiguration() + .getExcludeResourceCategory(); + List<String> exludeResourceType = ConfigurationManager.getConfigurationManager().getConfiguration() + .getExcludeResourceType(); + Map<String, Object> informationalResourceArtifacts = ConfigurationManager.getConfigurationManager() + .getConfiguration().getInformationalResourceArtifacts(); + List<CategoryDefinition> categories = service.getCategories(); + boolean isCreateArtifact = true; + if (exludeResourceCategory != null) { + String category = categories.get(0).getName(); + isCreateArtifact = exludeResourceCategory.stream().noneMatch(e->e.equalsIgnoreCase(category)); + } + + if (informationalResourceArtifacts != null && isCreateArtifact) { + Set<String> keys = informationalResourceArtifacts.keySet(); + for (String informationalResourceArtifactName : keys) { + Map<String, Object> artifactInfoMap = (Map<String, Object>) informationalResourceArtifacts + .get(informationalResourceArtifactName); + ArtifactDefinition artifactDefinition = serviceBusinessLogic.artifactsBusinessLogic.createArtifactPlaceHolderInfo( + resourceUniqueId, informationalResourceArtifactName, artifactInfoMap, user, + ArtifactGroupTypeEnum.INFORMATIONAL); + artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition); + + } + } + service.setArtifacts(artifactMap); + } + + public void rollback(boolean inTransaction, Service service, List<ArtifactDefinition> createdArtifacts, List<ArtifactDefinition> nodeTypesNewCreatedArtifacts) { + if(!inTransaction) { + serviceBusinessLogic.janusGraphDao.rollback(); + } + if (isNotEmpty(createdArtifacts) && isNotEmpty(nodeTypesNewCreatedArtifacts)) { + createdArtifacts.addAll(nodeTypesNewCreatedArtifacts); + log.debug("Found {} newly created artifacts to deleted, the component name: {}",createdArtifacts.size(), service.getName()); + } + } + + public Map<String,Object> getNodeTypesFromTemplate(Map<String, Object> mappedToscaTemplate) { + return ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES) + .left().orValue(HashMap::new); + } + + private Resource nodeForceCertification(Resource resource, User user, + LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean inTransaction, boolean needLock) { + return lifecycleBusinessLogic.forceResourceCertification(resource, user, lifecycleChangeInfo, inTransaction, + needLock); + } + + private Resource nodeFullCertification(String uniqueId, User user, + LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean inTransaction, boolean needLock) { + Either<Resource, ResponseFormat> resourceResponse = lifecycleBusinessLogic.changeState(uniqueId, user, LifeCycleTransitionEnum.CERTIFY, lifecycleChangeInfo, + inTransaction, needLock); + if(resourceResponse.isRight()){ + throw new ByResponseFormatComponentException(resourceResponse.right().value()); + } + return resourceResponse.left().value(); + } + + public Either<Boolean, ResponseFormat> validateNestedDerivedFromDuringUpdate(Resource currentResource, + Resource updateInfoResource, boolean hasBeenCertified) { + + List<String> currentDerivedFrom = currentResource.getDerivedFrom(); + List<String> updatedDerivedFrom = updateInfoResource.getDerivedFrom(); + if (currentDerivedFrom == null || currentDerivedFrom.isEmpty() || updatedDerivedFrom == null + || updatedDerivedFrom.isEmpty()) { + log.trace("Update normative types"); + return Either.left(true); + } + + String derivedFromCurrent = currentDerivedFrom.get(0); + String derivedFromUpdated = updatedDerivedFrom.get(0); + + if (!derivedFromCurrent.equals(derivedFromUpdated)) { + if (!hasBeenCertified) { + validateDerivedFromExist(null, updateInfoResource, null); + } else { + Either<Boolean, ResponseFormat> validateDerivedFromExtending = validateDerivedFromExtending(null, + currentResource, updateInfoResource, null); + + if (validateDerivedFromExtending.isRight() || !validateDerivedFromExtending.left().value()) { + log.debug("Derived from cannot be updated if it doesnt inherits directly or extends inheritance"); + return validateDerivedFromExtending; + } + } + } + return Either.left(true); + } + + protected Either<Boolean, ResponseFormat> validateDerivedFromExtending(User user, Resource currentResource, + Resource updateInfoResource, AuditingActionEnum actionEnum) { + String currentTemplateName = currentResource.getDerivedFrom().get(0); + String updatedTemplateName = updateInfoResource.getDerivedFrom().get(0); + + Either<Boolean, StorageOperationStatus> dataModelResponse = toscaOperationFacade + .validateToscaResourceNameExtends(currentTemplateName, updatedTemplateName); + if (dataModelResponse.isRight()) { + StorageOperationStatus storageStatus = dataModelResponse.right().value(); + BeEcompErrorManager.getInstance() + .logBeDaoSystemError("Create/Update Resource - validateDerivingFromExtendingType"); + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(storageStatus), currentResource); + log.trace("audit before sending response"); + componentsUtils.auditResource(responseFormat, user, currentResource, actionEnum); + return Either.right(responseFormat); + } + + if (!dataModelResponse.left().value()) { + log.info("resource template with name {} does not inherit as original {}", updatedTemplateName, + currentTemplateName); + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(ActionStatus.PARENT_RESOURCE_DOES_NOT_EXTEND); + componentsUtils.auditResource(responseFormat, user, currentResource, actionEnum); + + return Either.right(responseFormat); + + } + return Either.left(true); + } + + public void validateResourceFieldsBeforeUpdate(Resource currentResource, Resource updateInfoResource, + boolean inTransaction, boolean isNested) { + validateFields(currentResource, updateInfoResource, inTransaction, isNested); + } + + + private void validateFields(Resource currentResource, Resource updateInfoResource, boolean inTransaction, boolean isNested) { + boolean hasBeenCertified = ValidationUtils.hasBeenCertified(currentResource.getVersion()); + log.debug("validate resource name before update"); + validateResourceName(currentResource, updateInfoResource, hasBeenCertified, isNested); + log.debug("validate description before update"); + serviceBusinessLogic.componentDescriptionValidator.validateAndCorrectField(null, updateInfoResource, null); + log.debug("validate icon before update"); + log.debug("validate tags before update"); + serviceBusinessLogic.componentTagsValidator.validateAndCorrectField(null, updateInfoResource, null); + log.debug("validate vendor name before update"); + log.debug("validate resource vendor model number before update"); + log.debug("validate vendor release before update"); + log.debug("validate contact info before update"); + serviceBusinessLogic.componentContactIdValidator.validateAndCorrectField(null, updateInfoResource, null); + log.debug(VALIDATE_DERIVED_BEFORE_UPDATE); + log.debug("validate category before update"); + } + + + protected void validateResourceName(Resource currentResource, Resource updateInfoResource, + boolean hasBeenCertified, boolean isNested) { + String resourceNameUpdated = updateInfoResource.getName(); + if (!isResourceNameEquals(currentResource, updateInfoResource)) { + if (isNested || !hasBeenCertified) { + serviceBusinessLogic.componentNameValidator.validateAndCorrectField(null, updateInfoResource, null); + currentResource.setName(resourceNameUpdated); + currentResource.setNormalizedName(ValidationUtils.normaliseComponentName(resourceNameUpdated)); + currentResource.setSystemName(ValidationUtils.convertToSystemName(resourceNameUpdated)); + + } else { + log.info("Resource name: {}, cannot be updated once the resource has been certified once.", + resourceNameUpdated); + throw new ComponentException(ActionStatus.RESOURCE_NAME_CANNOT_BE_CHANGED); + } + } + } + + protected boolean isResourceNameEquals(Resource currentResource, Resource updateInfoResource) { + String resourceNameUpdated = updateInfoResource.getName(); + String resourceNameCurrent = currentResource.getName(); + if (resourceNameCurrent.equals(resourceNameUpdated)) { + return true; + } + return currentResource.getResourceType().equals(ResourceTypeEnum.VF) && + resourceNameUpdated.equals(addCvfcSuffixToResourceName(resourceNameCurrent)); + } + + public Resource prepareResourceForUpdate(Resource oldResource, Resource newResource, User user, + boolean inTransaction, boolean needLock) { + + if (!ComponentValidationUtils.canWorkOnResource(oldResource, user.getUserId())) { + // checkout + return lifecycleBusinessLogic.changeState( + oldResource.getUniqueId(), user, LifeCycleTransitionEnum.CHECKOUT, + new LifecycleChangeInfoWithAction("update by import"), inTransaction, needLock) + .left() + .on(response -> failOnChangeState(response, user, oldResource, newResource)); + } + return oldResource; + } + + protected Resource failOnChangeState(ResponseFormat response, User user, Resource oldResource, Resource newResource) { + log.info("resource {} cannot be updated. reason={}", oldResource.getUniqueId(), + response.getFormattedMessage()); + componentsUtils.auditResource(response, user, newResource, AuditingActionEnum.IMPORT_RESOURCE, + ResourceVersionInfo.newBuilder() + .state(oldResource.getLifecycleState().name()) + .version(oldResource.getVersion()) + .build()); + throw new ComponentException(response); + } + + public Resource handleResourceGenericType(Resource resource) { + Resource genericResource = serviceBusinessLogic.fetchAndSetDerivedFromGenericType(resource); + if (resource.shouldGenerateInputs()) { + serviceBusinessLogic.generateAndAddInputsFromGenericTypeProperties(resource, genericResource); + } + return genericResource; + } + + public Resource createInputsOnResource(Resource resource, Map<String, InputDefinition> inputs) { + List<InputDefinition> resourceProperties = resource.getInputs(); + if (MapUtils.isNotEmpty(inputs)|| isNotEmpty(resourceProperties)) { + + Either<List<InputDefinition>, ResponseFormat> createInputs = inputsBusinessLogic.createInputsInGraph(inputs, + resource); + if (createInputs.isRight()) { + throw new ComponentException(createInputs.right().value()); + } + } else { + return resource; + } + Either<Resource, StorageOperationStatus> updatedResource = toscaOperationFacade + .getToscaElement(resource.getUniqueId()); + if (updatedResource.isRight()) { + throw new ComponentException(componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(updatedResource.right().value()), resource)); + } + return updatedResource.left().value(); + } + + protected void updateOrCreateGroups(Resource resource, Map<String, GroupDefinition> groups) { + List<GroupDefinition> groupsFromResource = resource.getGroups(); + List<GroupDefinition> groupsAsList = updateGroupsMembersUsingResource(groups, new Service()); + List<GroupDefinition> groupsToUpdate = new ArrayList<>(); + List<GroupDefinition> groupsToDelete = new ArrayList<>(); + List<GroupDefinition> groupsToCreate = new ArrayList<>(); + if (isNotEmpty(groupsFromResource)) { + addGroupsToCreateOrUpdate(groupsFromResource, groupsAsList, groupsToUpdate, groupsToCreate); + addGroupsToDelete(groupsFromResource, groupsAsList, groupsToDelete); + } else { + groupsToCreate.addAll(groupsAsList); + } + if (isNotEmpty(groupsToCreate)) { + fillGroupsFinalFields(groupsToCreate); + if (isNotEmpty(groupsFromResource)) { + serviceBusinessLogic.groupBusinessLogic.addGroups(resource, + groupsToCreate, true) + .left() + .on(serviceBusinessLogic::throwComponentException); + } else { + serviceBusinessLogic.groupBusinessLogic.createGroups(resource, + groupsToCreate, true) + .left() + .on(serviceBusinessLogic::throwComponentException); + } + } + if (isNotEmpty(groupsToDelete)) { + serviceBusinessLogic.groupBusinessLogic.deleteGroups(resource, groupsToDelete) + .left() + .on(serviceBusinessLogic::throwComponentException); + } + if (isNotEmpty(groupsToUpdate)) { + serviceBusinessLogic.groupBusinessLogic.updateGroups(resource, groupsToUpdate, true) + .left() + .on(serviceBusinessLogic::throwComponentException); + } + } + + protected void addGroupsToCreateOrUpdate(List<GroupDefinition> groupsFromResource, List<GroupDefinition> groupsAsList, List<GroupDefinition> groupsToUpdate, List<GroupDefinition> groupsToCreate) { + for (GroupDefinition group : groupsAsList) { + Optional<GroupDefinition> op = groupsFromResource.stream() + .filter(p -> p.getInvariantName().equalsIgnoreCase(group.getInvariantName())).findAny(); + if (op.isPresent()) { + GroupDefinition groupToUpdate = op.get(); + groupToUpdate.setMembers(group.getMembers()); + groupToUpdate.setCapabilities(group.getCapabilities()); + groupToUpdate.setProperties(group.getProperties()); + groupsToUpdate.add(groupToUpdate); + } else { + groupsToCreate.add(group); + } + } + } + + protected void addGroupsToDelete(List<GroupDefinition> groupsFromResource, List<GroupDefinition> groupsAsList, List<GroupDefinition> groupsToDelete) { + for (GroupDefinition group : groupsFromResource) { + Optional<GroupDefinition> op = groupsAsList.stream() + .filter(p -> p.getName().equalsIgnoreCase(group.getName())).findAny(); + if (!op.isPresent() && (group.getArtifacts() == null || group.getArtifacts().isEmpty())) { + groupsToDelete.add(group); + } + } + } + + protected List<GroupDefinition> updateGroupsMembersUsingResource(Map<String, GroupDefinition> groups, Service component) { + + List<GroupDefinition> result = new ArrayList<>(); + List<ComponentInstance> componentInstances = component.getComponentInstances(); + + if (groups != null) { + Either<Boolean, ResponseFormat> validateCyclicGroupsDependencies = validateCyclicGroupsDependencies(groups); + if (validateCyclicGroupsDependencies.isRight()) { + throw new ComponentException(validateCyclicGroupsDependencies.right().value()); + } + for (Map.Entry<String, GroupDefinition> entry : groups.entrySet()) { + String groupName = entry.getKey(); + GroupDefinition groupDefinition = entry.getValue(); + GroupDefinition updatedGroupDefinition = new GroupDefinition(groupDefinition); + updatedGroupDefinition.setMembers(null); + Map<String, String> members = groupDefinition.getMembers(); + if (members != null) { + updateGroupMembers(groups, updatedGroupDefinition, component, componentInstances, groupName, members); + } + result.add(updatedGroupDefinition); + } + } + return result; + } + + public void updateGroupMembers(Map<String, GroupDefinition> groups, GroupDefinition updatedGroupDefinition, Service component, List<ComponentInstance> componentInstances, String groupName, Map<String, String> members) { + Set<String> compInstancesNames = members.keySet(); + + if (CollectionUtils.isEmpty(componentInstances)) { + String membersAstString = compInstancesNames.stream().collect(joining(",")); + log.debug("The members: {}, in group: {}, cannot be found in component {}. There are no component instances.", + membersAstString, groupName, component.getNormalizedName()); + throw new ComponentException(componentsUtils.getResponseFormat( + ActionStatus.GROUP_INVALID_COMPONENT_INSTANCE, membersAstString, groupName, + component.getNormalizedName(), getComponentTypeForResponse(component))); + } + // Find all component instances with the member names + Map<String, String> memberNames = componentInstances.stream() + .collect(toMap(ComponentInstance::getName, ComponentInstance::getUniqueId)); + memberNames.putAll(groups.keySet().stream().collect(toMap(g -> g, g -> ""))); + Map<String, String> relevantInstances = memberNames.entrySet().stream() + .filter(n -> compInstancesNames.contains(n.getKey())) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); + + if (relevantInstances == null || relevantInstances.size() != compInstancesNames.size()) { + + List<String> foundMembers = new ArrayList<>(); + if (relevantInstances != null) { + foundMembers = relevantInstances.keySet().stream().collect(toList()); + } + compInstancesNames.removeAll(foundMembers); + String membersAstString = compInstancesNames.stream().collect(joining(",")); + log.debug("The members: {}, in group: {}, cannot be found in component: {}", membersAstString, + groupName, component.getNormalizedName()); + throw new ComponentException(componentsUtils.getResponseFormat( + ActionStatus.GROUP_INVALID_COMPONENT_INSTANCE, membersAstString, groupName, + component.getNormalizedName(), getComponentTypeForResponse(component))); + } + updatedGroupDefinition.setMembers(relevantInstances); + } + + public Either<Boolean, ResponseFormat> validateCyclicGroupsDependencies(Map<String, GroupDefinition> allGroups) { + + Either<Boolean, ResponseFormat> result = Either.left(true); + try { + Iterator<Map.Entry<String, GroupDefinition>> allGroupsItr = allGroups.entrySet().iterator(); + while (allGroupsItr.hasNext() && result.isLeft()) { + Map.Entry<String, GroupDefinition> groupAEntry = allGroupsItr.next(); + // Fetches a group member A + String groupAName = groupAEntry.getKey(); + // Finds all group members in group A + Set<String> allGroupAMembersNames = new HashSet<>(); + fillAllGroupMemebersRecursivly(groupAEntry.getKey(), allGroups, allGroupAMembersNames); + // If A is a group member of itself found cyclic dependency + if (allGroupAMembersNames.contains(groupAName)) { + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(ActionStatus.GROUP_HAS_CYCLIC_DEPENDENCY, groupAName); + result = Either.right(responseFormat); + } + } + } catch (Exception e) { + ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR); + result = Either.right(responseFormat); + log.debug("Exception occured when validateCyclicGroupsDependencies, error is:{}", e.getMessage(), e); + } + return result; + } + + protected void fillAllGroupMemebersRecursivly(String groupName, Map<String, GroupDefinition> allGroups, + Set<String> allGroupMembers) { + + // Found Cyclic dependency + if (isfillGroupMemebersRecursivlyStopCondition(groupName, allGroups, allGroupMembers)) { + return; + } + GroupDefinition groupDefinition = allGroups.get(groupName); + // All Members Of Current Group Resource Instances & Other Groups + Set<String> currGroupMembers = groupDefinition.getMembers().keySet(); + // Filtered Members Of Current Group containing only members which + // are groups + List<String> currGroupFilteredMembers = currGroupMembers.stream(). + // Keep Only Elements of type group and not Resource Instances + filter(allGroups::containsKey). + // Add Filtered Elements to main Set + peek(allGroupMembers::add). + // Collect results + collect(toList()); + + // Recursively call the method for all the filtered group members + for (String innerGroupName : currGroupFilteredMembers) { + fillAllGroupMemebersRecursivly(innerGroupName, allGroups, allGroupMembers); + } + } + + public ImmutablePair<Resource, ActionStatus> createResourceFromNodeType(String nodeTypeYaml, UploadResourceInfo resourceMetaData, User creator, boolean isInTransaction, boolean needLock, + Map<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> nodeTypeArtifactsToHandle, + List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, boolean forceCertificationAllowed, CsarInfo csarInfo, + String nodeName, boolean isNested) { + + LifecycleChangeInfoWithAction lifecycleChangeInfo = new LifecycleChangeInfoWithAction(CERTIFICATION_ON_IMPORT, + LifecycleChangeInfoWithAction.LifecycleChanceActionEnum.CREATE_FROM_CSAR); + + Function<Resource, Boolean> validator = resource -> validateResourceCreationFromNodeType( + resource, creator); + + return resourceImportManager.importCertifiedResource(nodeTypeYaml, resourceMetaData, creator, validator, + lifecycleChangeInfo, isInTransaction, true, needLock, nodeTypeArtifactsToHandle, + nodeTypesNewCreatedArtifacts, forceCertificationAllowed, csarInfo, nodeName, isNested); + } + + public ImmutablePair<Resource, ActionStatus> createNodeTypeResourceFromYaml( + String yamlName, Map.Entry<String, Object> nodeNameValue, User user, Map<String, Object> mapToConvert, + Service resourceVf, boolean needLock, + Map<ArtifactsBusinessLogic.ArtifactOperationEnum, List<ArtifactDefinition>> nodeTypeArtifactsToHandle, + List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, boolean forceCertificationAllowed, CsarInfo csarInfo, + boolean isNested) { + + UploadResourceInfo resourceMetaData = fillResourceMetadata(yamlName, resourceVf, nodeNameValue.getKey(), user); + + String singleVfcYaml = buildNodeTypeYaml(nodeNameValue, mapToConvert, + resourceMetaData.getResourceType(), csarInfo); + user = serviceBusinessLogic.validateUser(user, "CheckIn Resource", resourceVf, AuditingActionEnum.CHECKIN_RESOURCE, true); + return createResourceFromNodeType(singleVfcYaml, resourceMetaData, user, true, needLock, + nodeTypeArtifactsToHandle, nodeTypesNewCreatedArtifacts, forceCertificationAllowed, csarInfo, + nodeNameValue.getKey(), isNested); + } + + protected UploadResourceInfo fillResourceMetadata(String yamlName, Service resourceVf, + String nodeName, User user) { + UploadResourceInfo resourceMetaData = new UploadResourceInfo(); + + // validate nodetype name prefix + if (!nodeName.startsWith(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX)) { + log.debug("invalid nodeName:{} does not start with {}.", nodeName, + Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX); + throw new ComponentException(ActionStatus.INVALID_NODE_TEMPLATE, + yamlName, resourceMetaData.getName(), nodeName); + } + + String actualName = this.getNodeTypeActualName(nodeName); + String namePrefix = nodeName.replace(actualName, ""); + String resourceType = namePrefix.substring(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX.length()); + + // if we import from csar, the node_type name can be + // org.openecomp.resource.abstract.node_name - in this case we always + // create a vfc + if (resourceType.equals(Constants.ABSTRACT)) { + resourceType = ResourceTypeEnum.VFC.name().toLowerCase(); + } + // validating type + if (!ResourceTypeEnum.containsName(resourceType.toUpperCase())) { + log.debug("invalid resourceType:{} the type is not one of the valide types:{}.", resourceType.toUpperCase(), + ResourceTypeEnum.values()); + throw new ComponentException(ActionStatus.INVALID_NODE_TEMPLATE, + yamlName, resourceMetaData.getName(), nodeName); + } + + // Setting name + resourceMetaData.setName(resourceVf.getSystemName() + actualName); + + // Setting type from name + String type = resourceType.toUpperCase(); + resourceMetaData.setResourceType(type); + + resourceMetaData.setDescription(ImportUtils.Constants.INNER_VFC_DESCRIPTION); + resourceMetaData.setIcon(ImportUtils.Constants.DEFAULT_ICON); + resourceMetaData.setContactId(user.getUserId()); + + // Setting tag + List<String> tags = new ArrayList<>(); + tags.add(resourceMetaData.getName()); + resourceMetaData.setTags(tags); + + // Setting category + CategoryDefinition category = new CategoryDefinition(); + category.setName(ImportUtils.Constants.ABSTRACT_CATEGORY_NAME); + SubCategoryDefinition subCategory = new SubCategoryDefinition(); + subCategory.setName(ImportUtils.Constants.ABSTRACT_SUBCATEGORY); + category.addSubCategory(subCategory); + List<CategoryDefinition> categories = new ArrayList<>(); + categories.add(category); + resourceMetaData.setCategories(categories); + + return resourceMetaData; + } + + + public Resource propagateStateToCertified(User user, Resource resource, + LifecycleChangeInfoWithAction lifecycleChangeInfo, boolean inTransaction, boolean needLock, + boolean forceCertificationAllowed) { + + Either<Resource, ResponseFormat> result = null; + try { + if (resource.getLifecycleState() != LifecycleStateEnum.CERTIFIED && forceCertificationAllowed + && lifecycleBusinessLogic.isFirstCertification(resource.getVersion())) { + nodeForceCertification(resource, user, lifecycleChangeInfo, inTransaction, needLock); + } + if (resource.getLifecycleState() == LifecycleStateEnum.CERTIFIED) { + Either<ArtifactDefinition, Operation> eitherPopulated = serviceBusinessLogic.populateToscaArtifacts( + resource, user, false, inTransaction, needLock); + return resource; + } + return nodeFullCertification(resource.getUniqueId(), user, lifecycleChangeInfo, inTransaction, needLock); + } catch (Exception e) { + log.debug("The exception has occurred upon certification of resource {}. ", resource.getName(), e); + throw e; + } finally { + if (result == null || result.isRight()) { + BeEcompErrorManager.getInstance().logBeSystemError("Change LifecycleState - Certify"); + if (!inTransaction) { + serviceBusinessLogic.janusGraphDao.rollback(); + } + } else if (!inTransaction) { + serviceBusinessLogic.janusGraphDao.commit(); + } + } + } + + public Resource buildValidComplexVfc(CsarInfo csarInfo, String nodeName, + Map<String, NodeTypeInfo> nodesInfo) { + + Resource complexVfc = buildComplexVfcMetadata(csarInfo, nodeName, nodesInfo); + log.debug("************* Going to validate complex VFC from yaml {}", complexVfc.getName()); + csarInfo.addNodeToQueue(nodeName); + return validateResourceBeforeCreate(complexVfc, csarInfo.getModifier(), + AuditingActionEnum.IMPORT_RESOURCE, true, csarInfo); + } + + public Resource updateGroupsOnResource(Resource resource, Map<String, GroupDefinition> groups) { + if (MapUtils.isEmpty(groups)) { + return resource; + } else { + updateOrCreateGroups(resource, groups); + } + Either<Resource, StorageOperationStatus> updatedResource = toscaOperationFacade + .getToscaElement(resource.getUniqueId()); + if (updatedResource.isRight()) { + throw new ComponentException(componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(updatedResource.right().value()), resource)); + } + return updatedResource.left().value(); + } + + protected void setInformationalArtifactsPlaceHolder(Resource resource, User user) { + Map<String, ArtifactDefinition> artifactMap = resource.getArtifacts(); + if (artifactMap == null) { + artifactMap = new HashMap<>(); + } + String resourceUniqueId = resource.getUniqueId(); + List<String> exludeResourceCategory = ConfigurationManager.getConfigurationManager().getConfiguration() + .getExcludeResourceCategory(); + List<String> exludeResourceType = ConfigurationManager.getConfigurationManager().getConfiguration() + .getExcludeResourceType(); + Map<String, Object> informationalResourceArtifacts = ConfigurationManager.getConfigurationManager() + .getConfiguration().getInformationalResourceArtifacts(); + List<CategoryDefinition> categories = resource.getCategories(); + boolean isCreateArtifact = true; + if (exludeResourceCategory != null) { + String category = categories.get(0).getName(); + isCreateArtifact = exludeResourceCategory.stream().noneMatch(e->e.equalsIgnoreCase(category)); + } + if (isCreateArtifact && exludeResourceType != null) { + String resourceType = resource.getResourceType().name(); + isCreateArtifact = exludeResourceType.stream().noneMatch(e->e.equalsIgnoreCase(resourceType)); + } + if (informationalResourceArtifacts != null && isCreateArtifact) { + Set<String> keys = informationalResourceArtifacts.keySet(); + for (String informationalResourceArtifactName : keys) { + Map<String, Object> artifactInfoMap = (Map<String, Object>) informationalResourceArtifacts + .get(informationalResourceArtifactName); + ArtifactDefinition artifactDefinition = serviceBusinessLogic.artifactsBusinessLogic.createArtifactPlaceHolderInfo( + resourceUniqueId, informationalResourceArtifactName, artifactInfoMap, user, + ArtifactGroupTypeEnum.INFORMATIONAL); + artifactMap.put(artifactDefinition.getArtifactLabel(), artifactDefinition); + + } + } + resource.setArtifacts(artifactMap); + } + + public void rollback(boolean inTransaction, Resource resource, List<ArtifactDefinition> createdArtifacts, List<ArtifactDefinition> nodeTypesNewCreatedArtifacts) { + if(!inTransaction) { + serviceBusinessLogic.janusGraphDao.rollback(); + } + if (isNotEmpty(createdArtifacts) && isNotEmpty(nodeTypesNewCreatedArtifacts)) { + createdArtifacts.addAll(nodeTypesNewCreatedArtifacts); + log.debug("Found {} newly created artifacts to deleted, the component name: {}",createdArtifacts.size(), resource.getName()); + } + } + + public void createArtifactsPlaceHolderData(Resource resource, User user) { + setInformationalArtifactsPlaceHolder(resource, user); + setDeploymentArtifactsPlaceHolder(resource, user); + serviceBusinessLogic.setToscaArtifactsPlaceHolders(resource, user); + } + + public void handleGroupsProperties(Service service, Map<String, GroupDefinition> groups) { + List<InputDefinition> inputs = service.getInputs(); + if (MapUtils.isNotEmpty(groups)) { + groups.values() + .stream() + .filter(g -> isNotEmpty(g.getProperties())) + .flatMap(g -> g.getProperties().stream()) + .forEach(p -> handleGetInputs(p, inputs)); + } + } + + public void handleGroupsProperties(Resource resource, Map<String, GroupDefinition> groups) { + List<InputDefinition> inputs = resource.getInputs(); + if (MapUtils.isNotEmpty(groups)) { + groups.values() + .stream() + .filter(g -> isNotEmpty(g.getProperties())) + .flatMap(g -> g.getProperties().stream()) + .forEach(p -> handleGetInputs(p, inputs)); + } + } + + protected void handleGetInputs(PropertyDataDefinition property, List<InputDefinition> inputs) { + if (isNotEmpty(property.getGetInputValues())) { + if (inputs == null || inputs.isEmpty()) { + log.debug("Failed to add property {} to group. Inputs list is empty ", property); + serviceBusinessLogic.rollbackWithException(ActionStatus.INPUTS_NOT_FOUND, property.getGetInputValues() + .stream() + .map(GetInputValueDataDefinition::getInputName) + .collect(toList()).toString()); + } + ListIterator<GetInputValueDataDefinition> getInputValuesIter = property.getGetInputValues().listIterator(); + while (getInputValuesIter.hasNext()) { + GetInputValueDataDefinition getInput = getInputValuesIter.next(); + InputDefinition input = findInputByName(inputs, getInput); + getInput.setInputId(input.getUniqueId()); + if (getInput.getGetInputIndex() != null) { + GetInputValueDataDefinition getInputIndex = getInput.getGetInputIndex(); + input = findInputByName(inputs, getInputIndex); + getInputIndex.setInputId(input.getUniqueId()); + getInputValuesIter.add(getInputIndex); + } + } + } + } + + public InputDefinition findInputByName(List<InputDefinition> inputs, GetInputValueDataDefinition getInput) { + Optional<InputDefinition> inputOpt = inputs.stream() + .filter(p -> p.getName().equals(getInput.getInputName())) + .findFirst(); + if (!inputOpt.isPresent()) { + log.debug("#findInputByName - Failed to find the input {} ", getInput.getInputName()); + serviceBusinessLogic.rollbackWithException(ActionStatus.INPUTS_NOT_FOUND, getInput.getInputName()); + } + return inputOpt.get(); + } + + public void associateComponentInstancePropertiesToComponent(String yamlName, Resource resource, Map<String, List<ComponentInstanceProperty>> instProperties) { + Either<Map<String, List<ComponentInstanceProperty>>, StorageOperationStatus> addPropToInst = toscaOperationFacade + .associateComponentInstancePropertiesToComponent(instProperties, resource.getUniqueId()); + if (addPropToInst.isRight()) { + log.debug("failed to associate properties of resource {} status is {}", resource.getUniqueId(), + addPropToInst.right().value()); + throw new ComponentException(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(addPropToInst.right().value()), yamlName)); + } + } + + public void associateComponentInstanceInputsToComponent(String yamlName, Resource resource, Map<String, List<ComponentInstanceInput>> instInputs) { + if (MapUtils.isNotEmpty(instInputs)) { + Either<Map<String, List<ComponentInstanceInput>>, StorageOperationStatus> addInputToInst = toscaOperationFacade + .associateComponentInstanceInputsToComponent(instInputs, resource.getUniqueId()); + if (addInputToInst.isRight()) { + log.debug("failed to associate inputs value of resource {} status is {}", resource.getUniqueId(), + addInputToInst.right().value()); + throw new ComponentException(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(addInputToInst.right().value()), yamlName)); + } + } + } + + public void associateDeploymentArtifactsToInstances(User user, String yamlName, Resource resource, Map<String, Map<String, ArtifactDefinition>> instDeploymentArtifacts) { + StorageOperationStatus addArtToInst = toscaOperationFacade + .associateDeploymentArtifactsToInstances(instDeploymentArtifacts, resource, user); + if (addArtToInst != StorageOperationStatus.OK && addArtToInst != StorageOperationStatus.NOT_FOUND) { + log.debug("failed to associate artifact of resource {} status is {}", resource.getUniqueId(), addArtToInst); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(addArtToInst), yamlName)); + } + } + + public void associateArtifactsToInstances(String yamlName, Resource resource, Map<String, Map<String, ArtifactDefinition>> instArtifacts) { + + StorageOperationStatus addArtToInst; + + addArtToInst = toscaOperationFacade.associateArtifactsToInstances(instArtifacts, resource); + if (addArtToInst != StorageOperationStatus.OK && addArtToInst != StorageOperationStatus.NOT_FOUND) { + log.debug("failed to associate artifact of resource {} status is {}", resource.getUniqueId(), addArtToInst); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(addArtToInst), yamlName)); + } + } + + public void associateOrAddCalculatedCapReq(String yamlName, Resource resource, Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> instCapabilities, Map<ComponentInstance, Map<String, List<RequirementDefinition>>> instRequirements) { + + StorageOperationStatus addArtToInst; + addArtToInst = toscaOperationFacade.associateOrAddCalculatedCapReq(instCapabilities, instRequirements, + resource); + if (addArtToInst != StorageOperationStatus.OK && addArtToInst != StorageOperationStatus.NOT_FOUND) { + log.debug("failed to associate cap and req of resource {} status is {}", resource.getUniqueId(), + addArtToInst); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(addArtToInst), yamlName)); + } + } + + public void associateInstAttributeToComponentToInstances(String yamlName, Resource resource, Map<String, List<AttributeDataDefinition>> instAttributes) { + + StorageOperationStatus addArtToInst; + addArtToInst = toscaOperationFacade.associateInstAttributeToComponentToInstances(instAttributes, + resource); + if (addArtToInst != StorageOperationStatus.OK && addArtToInst != StorageOperationStatus.NOT_FOUND) { + log.debug("failed to associate attributes of resource {} status is {}", resource.getUniqueId(), + addArtToInst); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(addArtToInst), yamlName)); + } + } + + public Resource getResourceAfterCreateRelations(Resource resource) { + ComponentParametersView parametersView = getComponentFilterAfterCreateRelations(); + Either<Resource, StorageOperationStatus> eitherGetResource = toscaOperationFacade + .getToscaElement(resource.getUniqueId(), parametersView); + + if (eitherGetResource.isRight()) { + throwComponentExceptionByResource(eitherGetResource.right().value(),resource); + } + return eitherGetResource.left().value(); + } + + public Resource throwComponentExceptionByResource(StorageOperationStatus status, Resource resource) { + ResponseFormat responseFormat = componentsUtils.getResponseFormatByResource( + componentsUtils.convertFromStorageResponse(status), resource); + throw new ComponentException(responseFormat); + } + + public void setCapabilityNamesTypes(Map<String, List<CapabilityDefinition>> originCapabilities, + Map<String, List<UploadCapInfo>> uploadedCapabilities) { + for (Map.Entry<String, List<UploadCapInfo>> currEntry : uploadedCapabilities.entrySet()) { + if (originCapabilities.containsKey(currEntry.getKey())) { + currEntry.getValue().stream().forEach(cap -> cap.setType(currEntry.getKey())); + } + } + for (Map.Entry<String, List<CapabilityDefinition>> capabilities : originCapabilities.entrySet()) { + capabilities.getValue().stream().forEach(cap -> { + if (uploadedCapabilities.containsKey(cap.getName())) { + uploadedCapabilities.get(cap.getName()).stream().forEach(c -> { + c.setName(cap.getName()); + c.setType(cap.getType()); + }); + } + }); + } + } + + public Map<String, List<CapabilityDefinition>> getValidComponentInstanceCapabilities( + String resourceId, Map<String, List<CapabilityDefinition>> defaultCapabilities, + Map<String, List<UploadCapInfo>> uploadedCapabilities) { + + Map<String, List<CapabilityDefinition>> validCapabilitiesMap = new HashMap<>(); + uploadedCapabilities.forEach((k,v)->addValidComponentInstanceCapabilities(k,v,resourceId,defaultCapabilities,validCapabilitiesMap)); + return validCapabilitiesMap; + } + + public void associateComponentInstanceInputsToComponent(String yamlName, Service service, Map<String, List<ComponentInstanceInput>> instInputs) { + if (MapUtils.isNotEmpty(instInputs)) { + Either<Map<String, List<ComponentInstanceInput>>, StorageOperationStatus> addInputToInst = toscaOperationFacade + .associateComponentInstanceInputsToComponent(instInputs, service.getUniqueId()); + if (addInputToInst.isRight()) { + log.debug("failed to associate inputs value of resource {} status is {}", service.getUniqueId(), + addInputToInst.right().value()); + throw new ComponentException(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(addInputToInst.right().value()), yamlName)); + } + } + } + + public void associateComponentInstancePropertiesToComponent(String yamlName, Service service, Map<String, List<ComponentInstanceProperty>> instProperties) { + Either<Map<String, List<ComponentInstanceProperty>>, StorageOperationStatus> addPropToInst = toscaOperationFacade + .associateComponentInstancePropertiesToComponent(instProperties, service.getUniqueId()); + if (addPropToInst.isRight()) { + throw new ComponentException(componentsUtils.getResponseFormat( + componentsUtils.convertFromStorageResponse(addPropToInst.right().value()), yamlName)); + } + } + + public void associateDeploymentArtifactsToInstances(User user, String yamlName, Service resource, Map<String, Map<String, ArtifactDefinition>> instDeploymentArtifacts) { + StorageOperationStatus addArtToInst = toscaOperationFacade + .associateDeploymentArtifactsToInstances(instDeploymentArtifacts, resource, user); + if (addArtToInst != StorageOperationStatus.OK && addArtToInst != StorageOperationStatus.NOT_FOUND) { + log.debug("failed to associate artifact of resource {} status is {}", resource.getUniqueId(), addArtToInst); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(addArtToInst), yamlName)); + } + } + + public void associateArtifactsToInstances(String yamlName, Service resource, Map<String, Map<String, ArtifactDefinition>> instArtifacts) { + StorageOperationStatus addArtToInst; + + addArtToInst = toscaOperationFacade.associateArtifactsToInstances(instArtifacts, resource); + if (addArtToInst != StorageOperationStatus.OK && addArtToInst != StorageOperationStatus.NOT_FOUND) { + log.debug("failed to associate artifact of resource {} status is {}", resource.getUniqueId(), addArtToInst); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(addArtToInst), yamlName)); + } + } + + public void associateOrAddCalculatedCapReq(String yamlName, Service resource, Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> instCapabilities, Map<ComponentInstance, Map<String, List<RequirementDefinition>>> instRequirements) { + StorageOperationStatus addArtToInst; + addArtToInst = toscaOperationFacade.associateOrAddCalculatedCapReq(instCapabilities, instRequirements, + resource); + log.debug("enter associateOrAddCalculatedCapReq,get instCapabilities:{},get instRequirements:{}", + instCapabilities, instRequirements); + if (addArtToInst != StorageOperationStatus.OK && addArtToInst != StorageOperationStatus.NOT_FOUND) { + log.debug("failed to associate cap and req of resource {} status is {}", resource.getUniqueId(), + addArtToInst); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(addArtToInst), yamlName)); + } + } + + public void associateInstAttributeToComponentToInstances(String yamlName, Service resource, Map<String, List<AttributeDataDefinition>> instAttributes) { + StorageOperationStatus addArtToInst; + + addArtToInst = toscaOperationFacade.associateInstAttributeToComponentToInstances(instAttributes, + resource); + if (addArtToInst != StorageOperationStatus.OK && addArtToInst != StorageOperationStatus.NOT_FOUND) { + log.debug("failed to associate attributes of resource {} status is {}", resource.getUniqueId(), + addArtToInst); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(addArtToInst), yamlName)); + } + } + + public void associateRequirementsToService(String yamlName, Service resource, Map<String, ListRequirementDataDefinition> requirements) { + StorageOperationStatus addReqToService; + addReqToService = toscaOperationFacade.associateRequirementsToService(requirements, + resource.getUniqueId()); + if (addReqToService != StorageOperationStatus.OK && addReqToService != StorageOperationStatus.NOT_FOUND) { + log.debug("failed to associate attributes of resource {} status is {}", resource.getUniqueId(), + addReqToService); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(addReqToService), yamlName)); + } + } + + public void associateCapabilitiesToService(String yamlName, Service resource, Map<String,ListCapabilityDataDefinition> capabilities) { + StorageOperationStatus addCapToService; + addCapToService = toscaOperationFacade.associateCapabilitiesToService(capabilities, + resource.getUniqueId()); + if (addCapToService != StorageOperationStatus.OK && addCapToService != StorageOperationStatus.NOT_FOUND) { + log.debug("failed to associate attributes of resource {} status is {}", resource.getUniqueId(), + addCapToService); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(addCapToService), yamlName)); + } + } + + public void associateResourceInstances(String yamlName, Service service, List<RequirementCapabilityRelDef> relations) { + Either<List<RequirementCapabilityRelDef>, StorageOperationStatus> relationsEither = toscaOperationFacade.associateResourceInstances(service, service.getUniqueId(), relations); + + if (relationsEither.isRight() && relationsEither.right().value() != StorageOperationStatus.NOT_FOUND) { + StorageOperationStatus status = relationsEither.right().value(); + log.debug("failed to associate instances of service {} status is {}", service.getUniqueId(), + status); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(status), yamlName)); + } + } + + public void addCapabilities(Map<String, List<CapabilityDefinition>> originCapabilities, String type, List<CapabilityDefinition> capabilities) { + List<CapabilityDefinition> list = capabilities.stream().map(CapabilityDefinition::new) + .collect(toList()); + originCapabilities.put(type, list); + } + + public void addCapabilitiesProperties(Map<String, Map<String, UploadPropInfo>> newPropertiesMap, List<UploadCapInfo> capabilities) { + for (UploadCapInfo capability : capabilities) { + if (isNotEmpty(capability.getProperties())) { + newPropertiesMap.put(capability.getName(), capability.getProperties().stream() + .collect(toMap(UploadInfo::getName, p -> p))); + } + } + } + + public Service getServiceWithGroups(String resourceId) { + + ComponentParametersView filter = new ComponentParametersView(); + filter.setIgnoreGroups(false); + Either<Service, StorageOperationStatus> updatedResource = toscaOperationFacade.getToscaElement(resourceId, filter); + if (updatedResource.isRight()) { + serviceBusinessLogic.rollbackWithException(componentsUtils.convertFromStorageResponse(updatedResource.right().value()), resourceId); + } + return updatedResource.left().value(); + } + + public Resource getResourceWithGroups(String resourceId) { + + ComponentParametersView filter = new ComponentParametersView(); + filter.setIgnoreGroups(false); + Either<Resource, StorageOperationStatus> updatedResource = toscaOperationFacade.getToscaElement(resourceId, filter); + if (updatedResource.isRight()) { + serviceBusinessLogic.rollbackWithException(componentsUtils.convertFromStorageResponse(updatedResource.right().value()), resourceId); + } + return updatedResource.left().value(); + } + + public void associateResourceInstances(String yamlName, Resource resource, List<RequirementCapabilityRelDef> relations) { + + Either<List<RequirementCapabilityRelDef>, StorageOperationStatus> relationsEither = toscaOperationFacade.associateResourceInstances(resource, resource.getUniqueId(), relations); + if (relationsEither.isRight() && relationsEither.right().value() != StorageOperationStatus.NOT_FOUND) { + StorageOperationStatus status = relationsEither.right().value(); + log.debug("failed to associate instances of resource {} status is {}", resource.getUniqueId(), + status); + throw new ComponentException(componentsUtils + .getResponseFormat(componentsUtils.convertFromStorageResponse(status), yamlName)); + } + } + + public void addRelationsToRI(String yamlName, Resource resource, Map<String, UploadComponentInstanceInfo> uploadResInstancesMap, List<ComponentInstance> componentInstancesList, List<RequirementCapabilityRelDef> relations) { + for (Map.Entry<String, UploadComponentInstanceInfo> entry : uploadResInstancesMap.entrySet()) { + UploadComponentInstanceInfo uploadComponentInstanceInfo = entry.getValue(); + ComponentInstance currentCompInstance = null; + for (ComponentInstance compInstance : componentInstancesList) { + + if (compInstance.getName().equals(uploadComponentInstanceInfo.getName())) { + currentCompInstance = compInstance; + break; + } + } + if (currentCompInstance == null) { + log.debug(COMPONENT_INSTANCE_WITH_NAME_IN_RESOURCE, uploadComponentInstanceInfo.getName(), + resource.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError( + COMPONENT_INSTANCE_WITH_NAME + uploadComponentInstanceInfo.getName() + IN_RESOURCE, + resource.getUniqueId(), BeEcompErrorManager.ErrorSeverity.ERROR); + ResponseFormat responseFormat = componentsUtils + .getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + throw new ComponentException(responseFormat); + } + + ResponseFormat addRelationToRiRes = addRelationToRI(yamlName, resource, entry.getValue(), relations); + if (addRelationToRiRes.getStatus() != 200) { + throw new ComponentException(addRelationToRiRes); + } + } + } + + protected ResponseFormat addRelationToRI(String yamlName, Resource resource, + UploadComponentInstanceInfo nodesInfoValue, List<RequirementCapabilityRelDef> relations) { + List<ComponentInstance> componentInstancesList = resource.getComponentInstances(); + ComponentInstance currentCompInstance = null; + + for (ComponentInstance compInstance : componentInstancesList) { + + if (compInstance.getName().equals(nodesInfoValue.getName())) { + currentCompInstance = compInstance; + break; + } + } + if (currentCompInstance == null) { + log.debug(COMPONENT_INSTANCE_WITH_NAME_IN_RESOURCE, nodesInfoValue.getName(), + resource.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError( + COMPONENT_INSTANCE_WITH_NAME + nodesInfoValue.getName() + IN_RESOURCE, + resource.getUniqueId(), BeEcompErrorManager.ErrorSeverity.ERROR); + return componentsUtils.getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, + yamlName); + } + String resourceInstanceId = currentCompInstance.getUniqueId(); + Map<String, List<UploadReqInfo>> regMap = nodesInfoValue.getRequirements(); + + if (regMap != null) { + Iterator<Map.Entry<String, List<UploadReqInfo>>> nodesRegValue = regMap.entrySet().iterator(); + while (nodesRegValue.hasNext()) { + Map.Entry<String, List<UploadReqInfo>> nodesRegInfoEntry = nodesRegValue.next(); + List<UploadReqInfo> uploadRegInfoList = nodesRegInfoEntry.getValue(); + for (UploadReqInfo uploadRegInfo : uploadRegInfoList) { + log.debug("Going to create relation {}", uploadRegInfo.getName()); + String regName = uploadRegInfo.getName(); + RequirementCapabilityRelDef regCapRelDef = new RequirementCapabilityRelDef(); + regCapRelDef.setFromNode(resourceInstanceId); + log.debug("try to find available requirement {} ", regName); + Either<RequirementDefinition, ResponseFormat> eitherReqStatus = findAviableRequiremen(regName, + yamlName, nodesInfoValue, currentCompInstance, + uploadRegInfo.getCapabilityName()); + if (eitherReqStatus.isRight()) { + return eitherReqStatus.right().value(); + } + + RequirementDefinition validReq = eitherReqStatus.left().value(); + List<CapabilityRequirementRelationship> reqAndRelationshipPairList = regCapRelDef + .getRelationships(); + if (reqAndRelationshipPairList == null) { + reqAndRelationshipPairList = new ArrayList<>(); + } + RelationshipInfo reqAndRelationshipPair = new RelationshipInfo(); + reqAndRelationshipPair.setRequirement(regName); + reqAndRelationshipPair.setRequirementOwnerId(validReq.getOwnerId()); + reqAndRelationshipPair.setRequirementUid(validReq.getUniqueId()); + RelationshipImpl relationship = new RelationshipImpl(); + relationship.setType(validReq.getCapability()); + reqAndRelationshipPair.setRelationships(relationship); + + ComponentInstance currentCapCompInstance = null; + for (ComponentInstance compInstance : componentInstancesList) { + if (compInstance.getName().equals(uploadRegInfo.getNode())) { + currentCapCompInstance = compInstance; + break; + } + } + + if (currentCapCompInstance == null) { + log.debug("The component instance with name {} not found on resource {} ", + uploadRegInfo.getNode(), resource.getUniqueId()); + BeEcompErrorManager.getInstance().logInternalDataError( + COMPONENT_INSTANCE_WITH_NAME + uploadRegInfo.getNode() + IN_RESOURCE, + resource.getUniqueId(), BeEcompErrorManager.ErrorSeverity.ERROR); + return componentsUtils + .getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + } + regCapRelDef.setToNode(currentCapCompInstance.getUniqueId()); + log.debug("try to find aviable Capability req name is {} ", validReq.getName()); + CapabilityDefinition aviableCapForRel = 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(), + resource.getUniqueId(), BeEcompErrorManager.ErrorSeverity.ERROR); + return componentsUtils + .getResponseFormat(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, yamlName); + } + CapabilityRequirementRelationship capReqRel = new CapabilityRequirementRelationship(); + capReqRel.setRelation(reqAndRelationshipPair); + reqAndRelationshipPairList.add(capReqRel); + regCapRelDef.setRelationships(reqAndRelationshipPairList); + relations.add(regCapRelDef); + } + } + } else if (resource.getResourceType() != ResourceTypeEnum.VF) { + return componentsUtils.getResponseFormat(ActionStatus.OK, yamlName); + } + return componentsUtils.getResponseFormat(ActionStatus.OK); + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/CreateServiceFromYamlParameter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/CreateServiceFromYamlParameter.java new file mode 100644 index 0000000000..5d2f26a991 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/utils/CreateServiceFromYamlParameter.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 CMCC, Inc. and others. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.be.components.impl.utils; + +import lombok.Getter; +import lombok.Setter; +import org.openecomp.sdc.be.components.csar.CsarInfo; +import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.NodeTypeInfo; +import org.openecomp.sdc.be.model.ParsedToscaYamlInfo; + +import java.util.List; +import java.util.Map; +@Getter +@Setter +public class CreateServiceFromYamlParameter { + private String yamlName; + private ParsedToscaYamlInfo parsedToscaYamlInfo; + private List<ArtifactDefinition> createdArtifacts; + private String topologyTemplateYaml; + private Map<String, NodeTypeInfo> nodeTypesInfo; + private CsarInfo csarInfo; + private boolean shouldLock; + private boolean inTransaction; + private String nodeName; +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/ServiceDistributionValidation.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/ServiceDistributionValidation.java index 118ca5bd4c..695ee58300 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/ServiceDistributionValidation.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/validation/ServiceDistributionValidation.java @@ -72,6 +72,12 @@ public class ServiceDistributionValidation { } } + public void validateAbstractServiceRequest(String serviceUUID, User modifier) { + validateUserExists(modifier.getUserId()); + Service abstractService = validateServiceExists(serviceUUID); + validateDistributionServiceLifeCycleState(abstractService); + } + private Service validateServiceExists(String serviceUUID) { if (StringUtils.isEmpty(serviceUUID.trim())) { ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.BAD_REQUEST_MISSING_RESOURCE); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/AbstractTemplateServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/AbstractTemplateServlet.java new file mode 100644 index 0000000000..0320a0a795 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/AbstractTemplateServlet.java @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2020 CMCC, Inc. and others. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.be.externalapi.servlet; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.jcabi.aspects.Loggable; +import fj.data.Either; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.servers.Server; +import io.swagger.v3.oas.annotations.servers.Servers; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; + +import java.io.IOException; +import java.util.List; +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + + +import org.openecomp.sdc.be.components.impl.*; +import org.openecomp.sdc.be.components.impl.aaf.AafPermission; +import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed; +import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException; +import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.externalapi.servlet.representation.AbstractTemplateInfo; +import org.openecomp.sdc.be.externalapi.servlet.representation.CopyServiceInfo; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.model.*; +import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.resources.data.auditing.model.DistributionData; +import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo; +import org.openecomp.sdc.be.servlets.*; +import org.openecomp.sdc.be.user.UserBusinessLogic; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.datastructure.Wrapper; +import org.openecomp.sdc.common.log.elements.LoggerSupportability; +import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions; +import org.openecomp.sdc.common.log.enums.StatusCode; +import org.openecomp.sdc.common.log.wrappers.Logger; +import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.stereotype.Controller; + +/** + * This servlet provides external interfaces related to abstract templates. + * + * @author hekeguang + */ + +@Loggable(prepend = true, value = Loggable.DEBUG, trim = false) +@Path("/v1/catalog") +@Tags({@Tag(name = "SDC External APIs")}) +@Servers({@Server(url = "/sdc")}) +@Controller + +public class AbstractTemplateServlet extends AbstractValidationsServlet { + + @Context + private HttpServletRequest request; + + private final ElementBusinessLogic elementBusinessLogic; + private final AbstractTemplateBusinessLogic abstractTemplateBusinessLogic; + + private final ServiceBusinessLogic serviceBusinessLogic; + private final ResourceBusinessLogic resourceBusinessLogic; + + private static final Logger log = Logger.getLogger(AbstractTemplateServlet.class); + private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(AbstractTemplateServlet.class.getName()); + + @Inject + public AbstractTemplateServlet(UserBusinessLogic userBusinessLogic, + ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils, + ServletUtils servletUtils, ResourceImportManager resourceImportManager, + ElementBusinessLogic elementBusinessLogic, + AbstractTemplateBusinessLogic abstractTemplateBusinessLogic, ServiceBusinessLogic serviceBusinessLogic, ResourceBusinessLogic resourceBusinessLogic) { + super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager); + this.elementBusinessLogic = elementBusinessLogic; + this.abstractTemplateBusinessLogic = abstractTemplateBusinessLogic; + this.serviceBusinessLogic = serviceBusinessLogic; + this.resourceBusinessLogic = resourceBusinessLogic; + } + + private Wrapper<ResponseFormat> validateRequestHeaders(String instanceIdHeader, String userId) { + Wrapper<ResponseFormat> responseWrapper = new Wrapper<>(); + if (responseWrapper.isEmpty()) { + validateXECOMPInstanceIDHeader(instanceIdHeader, responseWrapper); + } + if (responseWrapper.isEmpty()) { + validateHttpCspUserIdHeader(userId, responseWrapper); + } + return responseWrapper; + } + + /** + * @param requestId + * @param instanceIdHeader + * @param accept + * @param authorization + * @param uuid + * @return + */ + @GET + @Path("/abstract/service/serviceUUID/{uuid}/status") + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Fetch abstract status of service", method = "GET", + summary = "Return whether the service is a virtual service", responses = {@ApiResponse(responseCode = "200", + description = "The check result of whether the service is an abstract service is returned", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = AbstractTemplateInfo.class)))), + @ApiResponse(responseCode = "400", description = "Missing 'X-ECOMP-InstanceID' HTTP header - POL5001"), + @ApiResponse(responseCode = "401", + description = "ECOMP component should authenticate itself and to re-send again HTTP request with its Basic Authentication credentials - POL5002"), + @ApiResponse(responseCode = "403", description = "ECOMP component is not authorized - POL5003"), + @ApiResponse(responseCode = "404", + description = "Error: Requested '%1' (uuid) resource was not found - SVC4063"), + @ApiResponse(responseCode = "405", + description = "Method Not Allowed : Invalid HTTP method type used ( PUT,DELETE,POST will be rejected) - POL4050"), + @ApiResponse(responseCode = "500", + description = "The GET request failed either due to internal SDC problem. ECOMP Component should continue the attempts to get the needed information - POL5000")}) + @PermissionAllowed(AafPermission.PermNames.READ_VALUE) + public Response getServiceAbstractStatus( + @Parameter(description = "X-ECOMP-RequestID header", + required = false) @HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId, + @Parameter(description = "X-ECOMP-InstanceID header", required = true) @HeaderParam( + value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader, + @Parameter(description = "Determines the format of the body of the response", + required = false) @HeaderParam(value = Constants.ACCEPT_HEADER) String accept, + @Parameter(description = "The username and password", + required = true) @HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization, + @Parameter(description = "The requested asset uuid", + required = true) @PathParam("uuid") final String uuid) throws IOException { + + Response response = null; + ResponseFormat responseFormat = null; + AuditingActionEnum auditingActionEnum = AuditingActionEnum.GET_TEMPLATE_ABSTRACT_STATUS; + String requestURI = request.getRequestURI(); + String url = request.getMethod() + " " + requestURI; + log.debug("getServiceAbstractStatus: Start handle request of {}", url); + + String assetType = "services"; + ComponentTypeEnum componentType = ComponentTypeEnum.findByParamName(assetType); + ResourceCommonInfo resourceCommonInfo = new ResourceCommonInfo(componentType.getValue()); + DistributionData distributionData = new DistributionData(instanceIdHeader, requestURI); + // Mandatory + if (instanceIdHeader == null || instanceIdHeader.isEmpty()) { + log.debug("getServiceAbstractStatus: Missing X-ECOMP-InstanceID header"); + responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID); + getComponentsUtils().auditExternalGetAsset(responseFormat, auditingActionEnum, distributionData, + resourceCommonInfo, requestId, uuid); + return buildErrorResponse(responseFormat); + } + + try { + + Either<List<? extends Component>, ResponseFormat> assetTypeData = elementBusinessLogic.getCatalogComponentsByUuidAndAssetType(assetType, uuid); + + if (assetTypeData.isRight()) { + log.debug("getServiceAbstractStatus: Service Fetching Failed"); + responseFormat = assetTypeData.right().value(); + getComponentsUtils().auditExternalGetAsset(responseFormat, auditingActionEnum, distributionData, + resourceCommonInfo, requestId, uuid); + + return buildErrorResponse(responseFormat); + } + resourceCommonInfo.setResourceName(assetTypeData.left().value().iterator().next().getName()); + log.debug("getServiceAbstractStatus: Service Fetching Success"); + Either<AbstractTemplateInfo, ResponseFormat> resMetadata = abstractTemplateBusinessLogic.getServiceAbstractStatus(assetTypeData.left().value()); + if (resMetadata.isRight()) { + log.debug("getServiceAbstractStatus: Service abstract status get Failed"); + responseFormat = resMetadata.right().value(); + + getComponentsUtils().auditExternalGetAsset(responseFormat, auditingActionEnum, distributionData, + resourceCommonInfo, requestId, uuid); + return buildErrorResponse(responseFormat); + } + Object result = RepresentationUtils.toRepresentation(resMetadata.left().value()); + responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.OK); + getComponentsUtils().auditExternalGetAsset(responseFormat, auditingActionEnum, distributionData, + resourceCommonInfo, requestId, uuid); + + response = buildOkResponse(responseFormat, result); + return response; + + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Fetch abstract status of service"); + log.debug("getServiceAbstractStatus: Fetch abstract status of service with exception", e); + throw e; + } + } + + /** + * @param requestId + * @param instanceIdHeader + * @param accept + * @param authorization + * @param uuid + * @return + */ + @POST + @Path("/abstract/service/serviceUUID/{uuid}/copy") + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Copy a new service based on the existing service", method = "POST", + summary = "Return whether the copy service is successful", responses = {@ApiResponse(responseCode = "200", + description = "ECOMP component is authenticated and list of Catalog Assets Metadata is returned", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = AbstractTemplateInfo.class)))), + @ApiResponse(responseCode = "400", description = "Missing 'X-ECOMP-InstanceID' HTTP header - POL5001"), + @ApiResponse(responseCode = "401", + description = "ECOMP component should authenticate itself and to re-send again HTTP request with its Basic Authentication credentials - POL5002"), + @ApiResponse(responseCode = "403", description = "ECOMP component is not authorized - POL5003"), + @ApiResponse(responseCode = "404", + description = "Error: Requested '%1' (uuid) resource was not found - SVC4063"), + @ApiResponse(responseCode = "405", + description = "Method Not Allowed : Invalid HTTP method type used ( PUT,DELETE,POST will be rejected) - POL4050"), + @ApiResponse(responseCode = "500", + description = "The GET request failed either due to internal SDC problem. ECOMP Component should continue the attempts to get the needed information - POL5000"), + @ApiResponse(responseCode = "409", description = "Service already exist")}) + @PermissionAllowed(AafPermission.PermNames.WRITE_VALUE) + public Response copyExistService( + @Parameter(description = "The user id", + required = true) @HeaderParam(value = Constants.USER_ID_HEADER) final String userId, + @Parameter(description = "X-ECOMP-RequestID header", + required = false) @HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId, + @Parameter(description = "X-ECOMP-InstanceID header", required = true) @HeaderParam( + value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader, + @Parameter(description = "Determines the format of the body of the response", + required = false) @HeaderParam(value = Constants.ACCEPT_HEADER) String accept, + @Parameter(description = "The username and password", + required = true) @HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization, + @Parameter(description = "The requested asset uuid", + required = true) @PathParam("uuid") final String uuid, + @Parameter(hidden = true) String data) throws IOException { + + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("copyExistService: Start handle request of {}", url); + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}", userId); + loggerSupportability.log(LoggerSupportabilityActions.CREATE_SERVICE, StatusCode.STARTED, "Starting to create a service by user {} ", userId); + + validateNotEmptyBody(data); + + Either<CopyServiceInfo, ResponseFormat> convertResponse = parseToCopyServiceInfo(data, modifier); + if (convertResponse.isRight()) { + throw new ByResponseFormatComponentException(convertResponse.right().value()); + } + + String assetType = "services"; + CopyServiceInfo copyServiceInfo = convertResponse.left().value(); + Either<List<? extends Component>, ResponseFormat> assetTypeData = elementBusinessLogic.getCatalogComponentsByUuidAndAssetType(assetType, uuid); + + if (assetTypeData.isRight() || assetTypeData.left().value().size() != 1) { + log.debug("getServiceAbstractStatus: Service Fetching Failed"); + throw new ByResponseFormatComponentException(assetTypeData.right().value()); + } + + log.debug("getServiceAbstractStatus: Service Fetching Success"); + + Service service = (Service) assetTypeData.left().value().get(0); + List<String> tags = service.getTags(); + if (tags != null && !tags.isEmpty()) { + for (int i = tags.size() - 1; i >= 0; i--) { + String tag = tags.get(i); + if (service.getName().equals(tag)) { + tags.remove(tag); + } + } + } + service.setName(copyServiceInfo.getNewServiceName()); + tags.add(copyServiceInfo.getNewServiceName()); + Either<Service, ResponseFormat> actionResponse = serviceBusinessLogic.createService(service, modifier); + + if (actionResponse.isRight()) { + log.debug("Failed to create service"); + throw new ByResponseFormatComponentException(actionResponse.right().value()); + } + + loggerSupportability.log(LoggerSupportabilityActions.CREATE_SERVICE, service.getComponentMetadataForSupportLog(), StatusCode.COMPLETE, "Service {} has been copyied by user {} ", service.getName(), userId); + + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse.left().value()); + + } + + public Either<CopyServiceInfo, ResponseFormat> parseToCopyServiceInfo(String serviceJson, User user) { + return getComponentsUtils().convertJsonToObjectUsingObjectMapper(serviceJson, user, CopyServiceInfo.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE); + } + + private CopyServiceInfo convertJsonToServiceInfo(String data) { + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.readValue(data, CopyServiceInfo.class); + } catch (IOException e) { + log.error("#convertJsonToServiceInfo - json deserialization failed with error: ", e); + return new CopyServiceInfo(); + } + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/AbstractResourceInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/AbstractResourceInfo.java new file mode 100644 index 0000000000..6bb8356fa4 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/AbstractResourceInfo.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2020 CMCC, Inc. and others. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.externalapi.servlet.representation; + +import lombok.Getter; +import lombok.Setter; +import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; + +import java.util.List; + +@Getter +@Setter +public class AbstractResourceInfo { + + private String abstractResourceUUid; + private String abstractResourceName; + //获得abstractResourceUniqueId + private String abstractResourceUniqueId; + //private String abstractResourceNormalizedName; + //获得componentInstancesRelations + private List<RequirementCapabilityRelDef> componentInstancesRelations; +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/AbstractTemplateInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/AbstractTemplateInfo.java new file mode 100644 index 0000000000..ba4cde7ded --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/AbstractTemplateInfo.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 CMCC, Inc. and others. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.externalapi.servlet.representation; + +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class AbstractTemplateInfo { + + private String serviceUUid; + private Boolean isAbstractTemplate; + //获得serviceUniqueId + private String serviceUniqueId; + private List<AbstractResourceInfo> abstractResourceInfoList; +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/CopyServiceInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/CopyServiceInfo.java new file mode 100644 index 0000000000..078d282aae --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/CopyServiceInfo.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 CMCC, Inc. and others. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.externalapi.servlet.representation; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CopyServiceInfo { + private String newServiceUUid; + + private String newServiceName; + + private String oldServiceUUid; +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/ReplaceVNFInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/ReplaceVNFInfo.java new file mode 100644 index 0000000000..db312e50ad --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/externalapi/servlet/representation/ReplaceVNFInfo.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 CMCC, Inc. and others. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openecomp.sdc.be.externalapi.servlet.representation; + +import lombok.Getter; +import lombok.Setter; +import org.openecomp.sdc.be.model.ComponentInstance; +import org.openecomp.sdc.be.model.RequirementCapabilityRelDef; + +import java.util.List; + +@Getter +@Setter +public class ReplaceVNFInfo { + /* + delete vnf param + */ + private String serviceUniqueId; + + private String abstractResourceUniqueId; + + /* + add vnf param + */ + private ComponentInstance realVNFComponentInstance; + + //private List<RequirementCapabilityRelDef> componentInstancesRelations; +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java index d3a8644136..7ac20893c9 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/impl/ComponentsUtils.java @@ -226,7 +226,7 @@ public class ComponentsUtils { * @param resource * @return */ - public ResponseFormat getResponseFormatByResource(ActionStatus actionStatus, Resource resource) { + public ResponseFormat getResponseFormatByResource(ActionStatus actionStatus, Component resource) { if (resource == null) { return getResponseFormat(actionStatus); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/info/ServiceVersionInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/info/ServiceVersionInfo.java index 185c1a474e..09ac6747f4 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/info/ServiceVersionInfo.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/info/ServiceVersionInfo.java @@ -20,6 +20,7 @@ package org.openecomp.sdc.be.info; +import com.google.common.annotations.VisibleForTesting; import lombok.Getter; import lombok.Setter; @@ -29,6 +30,9 @@ public class ServiceVersionInfo { private String version; private String url; + @VisibleForTesting + ServiceVersionInfo() {} + public ServiceVersionInfo(String serviceName, String serviceVersion, String context) { super(); this.version = serviceVersion; @@ -36,4 +40,55 @@ public class ServiceVersionInfo { sb.append("services/").append(serviceName).append("/").append(serviceVersion); url = sb.toString(); } + + + private String artifactUuid; + private String state; + private String distributionStatus; + + + public static Builder newBuilder() { + return new Builder(); + } + + public String getArtifactUuid() { + return artifactUuid; + } + public String getState() { + return state; + } + public String getDistributionStatus() { return distributionStatus; } + + + public static class Builder { + private final ServiceVersionInfo instance; + + private Builder() { + instance = new ServiceVersionInfo(); + } + + public Builder artifactUuid(String artifactUuid) { + instance.artifactUuid = artifactUuid; + return this; + } + + public Builder state(String state) { + instance.state = state; + return this; + } + + public Builder version(String version) { + instance.version = version; + return this; + } + + public Builder distributionStatus(String distributionStatus) { + instance.distributionStatus = distributionStatus; + return this; + } + + public ServiceVersionInfo build() { + return instance; + } + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java index 0cdf872f71..cb0cc239f2 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java @@ -28,6 +28,7 @@ import com.google.gson.JsonSyntaxException; import fj.data.Either; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; @@ -52,6 +53,7 @@ import org.openecomp.sdc.be.components.impl.ImportUtils; import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum; import org.openecomp.sdc.be.components.impl.ResourceImportManager; +import org.openecomp.sdc.be.components.impl.ServiceImportManager; 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; @@ -62,12 +64,17 @@ import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.ArtifactDefinition; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.UploadResourceInfo; +import org.openecomp.sdc.be.model.UploadServiceInfo; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum; +import org.openecomp.sdc.be.servlets.ServiceUploadServlet.ServiceAuthorityTypeEnum; import org.openecomp.sdc.be.user.Role; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.be.utils.TypeUtils; @@ -80,6 +87,7 @@ import org.openecomp.sdc.common.util.YamlToObjectConverter; import org.openecomp.sdc.common.zip.ZipUtils; import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.web.context.WebApplicationContext; import org.yaml.snakeyaml.Yaml; public abstract class AbstractValidationsServlet extends BeGenericServlet { @@ -94,12 +102,13 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { TOSCA_SIMPLE_YAML_PREFIX + "1_1", TOSCA_SIMPLE_YAML_PREFIX + "1_2", TOSCA_SIMPLE_YAML_PREFIX + "1_3"); - private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar"); + private static final List<String> TOSCA_YML_CSAR_VALID_SUFFIX = Arrays.asList(".yml", ".yaml", ".csar", ".meta"); protected ServletUtils servletUtils; protected ResourceImportManager resourceImportManager; protected final ComponentInstanceBusinessLogic componentInstanceBusinessLogic; + protected ServiceImportManager serviceImportManager; public AbstractValidationsServlet(UserBusinessLogic userBusinessLogic, ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils, @@ -113,6 +122,16 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { protected void init() { } + protected synchronized void initSpringFromContext() { + if (serviceImportManager == null) { + ServletContext context = servletRequest.getSession().getServletContext(); + WebAppContextWrapper webApplicationContextWrapper = (WebAppContextWrapper) context + .getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR); + WebApplicationContext webApplicationContext = webApplicationContextWrapper.getWebAppContext(context); + serviceImportManager = webApplicationContext.getBean(ServiceImportManager.class); + } + } + protected void validateResourceDoesNotExist(Wrapper<Response> responseWrapper, User user, String resourceName) { if (resourceImportManager.isResourceExist(resourceName)) { ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.RESOURCE_ALREADY_EXISTS); @@ -483,19 +502,23 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { private void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, UploadResourceInfo uploadResourceInfo, User user) { String toscaTemplatePayloadName = uploadResourceInfo.getPayloadName(); - boolean isValidSuffix = false; - if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) { - for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) { - isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix); - } - } + boolean isValidSuffix = isToscaTemplatePayloadNameValid(responseWrapper, toscaTemplatePayloadName); if (!isValidSuffix) { ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION); Response errorResponse = buildErrorResponse(responseFormat); getComponentsUtils().auditResource(responseFormat, user, uploadResourceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE); responseWrapper.setInnerElement(errorResponse); } + } + private boolean isToscaTemplatePayloadNameValid(Wrapper<Response> responseWrapper, String toscaTemplatePayloadName) { + boolean isValidSuffix = false; + if (toscaTemplatePayloadName != null && !toscaTemplatePayloadName.isEmpty()) { + for (String validSuffix : TOSCA_YML_CSAR_VALID_SUFFIX) { + isValidSuffix = isValidSuffix || toscaTemplatePayloadName.toLowerCase().endsWith(validSuffix); + } + } + return isValidSuffix; } private void validateMD5(Wrapper<Response> responseWrapper, User user, UploadResourceInfo resourceInfo, HttpServletRequest request, String resourceInfoJsonString) { @@ -721,19 +744,29 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { return new ImmutablePair<>(newResource, actionStatus); } - private Resource throwComponentException(ResponseFormat responseFormat) { + protected Resource throwComponentException(ResponseFormat responseFormat) { throw new ByResponseFormatComponentException(responseFormat); } private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Resource resource, User user, String csarUUID) { + getAndValidateComponentCsarYaml(csarUIPayload, resource, user, csarUUID); + } + + private void getAndValidateComponentCsarYaml(Map<String, byte[]> csarUIPayload, Component component, User user, String csarUUID) { Either<ImmutablePair<String, String>, ResponseFormat> getToscaYamlRes = CsarValidationUtils.getToscaYaml(csarUIPayload, csarUUID, getComponentsUtils()); if (getToscaYamlRes.isRight()) { ResponseFormat responseFormat = getToscaYamlRes.right().value(); log.debug("Error when try to get csar toscayamlFile with csar ID {}, error: {}", csarUUID, responseFormat); - BeEcompErrorManager.getInstance().logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed"); - getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.CREATE_RESOURCE); + if (component instanceof Resource) { + BeEcompErrorManager.getInstance() + .logBeDaoSystemError("Creating resource from CSAR: fetching CSAR with id " + csarUUID + " failed"); + getComponentsUtils().auditResource(responseFormat, user, (Resource)component, AuditingActionEnum.CREATE_RESOURCE); + }else { + BeEcompErrorManager.getInstance() + .logBeDaoSystemError("Creating service from CSAR: fetching CSAR with id " + csarUUID + " failed"); + } throwComponentException(responseFormat); } String toscaYaml = getToscaYamlRes.left().value().getValue(); @@ -743,7 +776,9 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { boolean isValid = yamlConvertor.isValidYaml(toscaYaml.getBytes()); if (!isValid) { ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_YAML_FILE); - getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE); + if (component instanceof Resource) { + getComponentsUtils().auditResource(responseFormat, user, (Resource)component, AuditingActionEnum.IMPORT_RESOURCE); + } throwComponentException(responseFormat); } @@ -764,7 +799,10 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { if (!isValid) { ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_TEMPLATE); - getComponentsUtils().auditResource(responseFormat, user, resource, AuditingActionEnum.IMPORT_RESOURCE); + if (component instanceof Resource) { + log.debug("enter getAndValidateComponentCsarYaml,component instanceof Resource"); + getComponentsUtils().auditResource(responseFormat, user, (Resource)component, AuditingActionEnum.IMPORT_RESOURCE); + } throwComponentException(responseFormat); } } @@ -780,23 +818,32 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { List<UploadArtifactInfo> artifactList = resourceInfoObject.getArtifactList(); if (artifactList != null) { Map<String, ArtifactDefinition> artifactsHM = new HashMap<>(); - for (UploadArtifactInfo artifact : artifactList) { - ArtifactDefinition artifactDef = new ArtifactDefinition(); - artifactDef.setArtifactName(artifact.getArtifactName()); - artifactDef.setArtifactType(artifact.getArtifactType().getType()); - artifactDef.setDescription(artifact.getArtifactDescription()); - artifactDef.setPayloadData(artifact.getArtifactData()); - artifactDef.setArtifactRef(artifact.getArtifactPath()); - artifactsHM.put(artifactDef.getArtifactName(), artifactDef); - } + buildArtifactsHM(artifactList, artifactsHM); resource.setArtifacts(artifactsHM); } } } + private void buildArtifactsHM(List<UploadArtifactInfo> artifactList, Map<String, ArtifactDefinition> artifactsHM){ + for (UploadArtifactInfo artifact : artifactList) { + ArtifactDefinition artifactDef = new ArtifactDefinition(); + artifactDef.setArtifactName(artifact.getArtifactName()); + artifactDef.setArtifactType(artifact.getArtifactType().getType()); + artifactDef.setDescription(artifact.getArtifactDescription()); + artifactDef.setPayloadData(artifact.getArtifactData()); + artifactDef.setArtifactRef(artifact.getArtifactPath()); + artifactsHM.put(artifactDef.getArtifactName(), artifactDef); + } + } + private Map<String, byte[]> getCsarFromPayload(UploadResourceInfo innerElement) { String csarUUID = innerElement.getPayloadName(); String payloadData = innerElement.getPayloadData(); + + return getComponentCsarFromPayload(csarUUID, payloadData); + } + + private Map<String, byte[]> getComponentCsarFromPayload(String csarUUID, String payloadData){ if (payloadData == null) { log.info("Failed to decode received csar {}", csarUUID); throw new ByActionStatusComponentException(ActionStatus.CSAR_NOT_FOUND, csarUUID); @@ -911,4 +958,373 @@ public abstract class AbstractValidationsServlet extends BeGenericServlet { throw new ByActionStatusComponentException(ActionStatus.MISSING_BODY); } } + + protected void commonServiceGeneralValidations( + Wrapper<Response> responseWrapper, Wrapper<User> userWrapper, + Wrapper<UploadServiceInfo> uploadServiceInfoWrapper, ServiceAuthorityTypeEnum serviceAuthorityEnum, + String userUserId, + String serviceInfoJsonString) { + + if (responseWrapper.isEmpty()) { + validateUserExist(responseWrapper, userWrapper, userUserId); + } + + if (responseWrapper.isEmpty()) { + validateUserRole(responseWrapper, userWrapper.getInnerElement(), serviceAuthorityEnum); + } + + if (responseWrapper.isEmpty()) { + validateAndFillServiceJson(responseWrapper, uploadServiceInfoWrapper, userWrapper.getInnerElement(), + serviceAuthorityEnum, serviceInfoJsonString); + } + + if (responseWrapper.isEmpty()) { + validateToscaTemplatePayloadName(responseWrapper, uploadServiceInfoWrapper.getInnerElement(), + userWrapper.getInnerElement()); + } + + } + + protected void validateUserRole(Wrapper<Response> errorResponseWrapper, User user, + ServiceAuthorityTypeEnum serviceAuthority) { + log.debug("validate user role"); + if (serviceAuthority == ServiceAuthorityTypeEnum.NORMATIVE_TYPE_BE) { + if (!user.getRole().equals(Role.ADMIN.name())) { + log.info("user is not in appropriate role to perform action"); + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(ActionStatus.RESTRICTED_OPERATION); + log.debug("audit before sending response"); + Response response = buildErrorResponse(responseFormat); + errorResponseWrapper.setInnerElement(response); + } + } else { + validateUserRole(errorResponseWrapper, user); + } + + } + + protected void validateAndFillServiceJson(Wrapper<Response> responseWrapper, + Wrapper<UploadServiceInfo> uploadServiceInfoWrapper, User user, + ServiceAuthorityTypeEnum serviceAuthorityEnum, String serviceInfo) { + boolean isValid; + try { + log.debug("The received json is {}", serviceInfo); + UploadServiceInfo serviceInfoObject = gson.fromJson(serviceInfo, UploadServiceInfo.class); + if (serviceInfoObject == null) { + isValid = false; + } else { + if (!serviceAuthorityEnum.isBackEndImport()) { + isValid = + serviceInfoObject.getPayloadName() != null && !serviceInfoObject.getPayloadName().isEmpty(); + //only service name is checked + } else { + isValid = true; + } + uploadServiceInfoWrapper.setInnerElement(serviceInfoObject); + log.debug("get isValid:{},serviceInfoObject get name:{},get tags:{},getContactId:{}," + + " getPayloadName:{}",isValid, + uploadServiceInfoWrapper.getInnerElement().getName(), + uploadServiceInfoWrapper.getInnerElement().getTags(), + uploadServiceInfoWrapper.getInnerElement().getContactId(), + uploadServiceInfoWrapper.getInnerElement().getPayloadName()); + } + + } catch (JsonSyntaxException e) { + log.debug("enter validateAndFillServiceJson,Invalid json was received. {}", e.getMessage(), e); + isValid = false; + + } + if (!isValid) { + log.info("Invalid json was received."); + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT); + Response errorResp = buildErrorResponse(responseFormat); + responseWrapper.setInnerElement(errorResp); + } + } + + protected void validateToscaTemplatePayloadName(Wrapper<Response> responseWrapper, + UploadServiceInfo uploadServiceInfo, User user) { + String toscaTemplatePayloadName = uploadServiceInfo.getPayloadName(); + boolean isValidSuffix = isToscaTemplatePayloadNameValid(responseWrapper, toscaTemplatePayloadName); + if (!isValidSuffix) { + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(ActionStatus.INVALID_TOSCA_FILE_EXTENSION); + Response errorResponse = buildErrorResponse(responseFormat); + responseWrapper.setInnerElement(errorResponse); + } + + } + + + protected void specificServiceAuthorityValidations(Wrapper<Response> responseWrapper, + Wrapper<UploadServiceInfo> uploadServiceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, + HttpServletRequest request, String serviceInfoJsonString, ServiceAuthorityTypeEnum serviceAuthorityEnum) + throws FileNotFoundException { + + if (responseWrapper.isEmpty()) { + // UI Only Validation + if (!serviceAuthorityEnum.isBackEndImport()) { + importUIValidations(responseWrapper, uploadServiceInfoWrapper.getInnerElement(), user, request, + serviceInfoJsonString); + } + + // User Defined Type Services + if (serviceAuthorityEnum.isUserTypeService() && !CsarValidationUtils.isCsarPayloadName( + uploadServiceInfoWrapper.getInnerElement().getPayloadName())) { + if (responseWrapper.isEmpty()) { + validatePayloadNameSpace(responseWrapper, uploadServiceInfoWrapper.getInnerElement(), user, + yamlStringWrapper.getInnerElement()); + } + + } + } + } + + protected void importUIValidations(Wrapper<Response> responseWrapper, UploadServiceInfo serviceInfo, User user, + HttpServletRequest request, String serviceInfoJsonString) { + if (responseWrapper.isEmpty()) { + validateMD5(responseWrapper, user, serviceInfo, request, serviceInfoJsonString); + } + if (responseWrapper.isEmpty() && request != null && request.getMethod() != null && request.getMethod() + .equals("POST")) { + validateServiceDoesNotExist(responseWrapper, user, serviceInfo.getName()); + } + } + + protected void validatePayloadNameSpace(Wrapper<Response> responseWrapper, UploadServiceInfo serviceInfo, User user, + String toscaPayload) { + boolean isValid; + String nameSpace = ""; + Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(toscaPayload); + Either<Map<String, Object>, ResultStatusEnum> toscaElement = + ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES); + if (toscaElement.isRight() || toscaElement.left().value().size() != 1) { + isValid = false; + } else { + nameSpace = toscaElement.left().value().keySet().iterator().next(); + isValid = nameSpace.startsWith(Constants.USER_DEFINED_SERVICE_NAMESPACE_PREFIX); + log.debug("enter validatePayloadNameSpace,get nameSpace:{},get Valid is:{}",nameSpace,isValid); + } + if (!isValid) { + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(ActionStatus.INVALID_SERVICE_NAMESPACE); + Response errorResponse = buildErrorResponse(responseFormat); + responseWrapper.setInnerElement(errorResponse); + } else { + String str1 = nameSpace.substring(Constants.USER_DEFINED_SERVICE_NAMESPACE_PREFIX.length()); + String[] findTypes = str1.split("\\."); + if (ResourceTypeEnum.containsName(findTypes[0].toUpperCase())) { + String type = findTypes[0].toUpperCase(); + serviceInfo.setServiceType(type); + } else { + serviceInfo.setServiceType(ResourceTypeEnum.SERVICE.name()); + } + } + + } + + protected void validateMD5(Wrapper<Response> responseWrapper, User user, UploadServiceInfo serviceInfo, + HttpServletRequest request, String serviceInfoJsonString) { + boolean isValid; + String recievedMD5 = request.getHeader(Constants.MD5_HEADER); + if (recievedMD5 == null) { + isValid = false; + } else { + String calculateMD5 = GeneralUtility.calculateMD5Base64EncodedByString(serviceInfoJsonString); + isValid = calculateMD5.equals(recievedMD5); + } + if (!isValid) { + ResponseFormat responseFormat = + getComponentsUtils().getResponseFormat(ActionStatus.INVALID_SERVICE_CHECKSUM); + Response errorResponse = buildErrorResponse(responseFormat); + responseWrapper.setInnerElement(errorResponse); + } + } + + + protected void validateServiceDoesNotExist(Wrapper<Response> responseWrapper, User user, String serviceName) { + if (serviceImportManager.isServiceExist(serviceName)) { + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.SERVICE_ALREADY_EXISTS); + Response errorResponse = buildErrorResponse(responseFormat); + responseWrapper.setInnerElement(errorResponse); + } + } + + protected void handleImportService(Wrapper<Response> responseWrapper, User user, + UploadServiceInfo serviceInfoObject, String yamlAsString, ServiceAuthorityTypeEnum authority, + boolean createNewVersion, String serviceUniqueId) throws ZipException { + + Response response = null; + Object representation = null; + ImmutablePair<Service, ActionStatus> importedServiceStatus = null; + if (CsarValidationUtils.isCsarPayloadName(serviceInfoObject.getPayloadName())) { + log.debug("import service from csar"); + importedServiceStatus = importServiceFromUICsar(serviceInfoObject, user, serviceUniqueId); + } + + if (importedServiceStatus != null) { + try { + representation = RepresentationUtils.toRepresentation(importedServiceStatus.left); + } catch (IOException e) { + log.debug("Error while building service representation : {}", e.getMessage(), e); + } + response = buildOkResponse(getComponentsUtils().getResponseFormat(importedServiceStatus.right), + representation); + } + responseWrapper.setInnerElement(response); + } + + private ImmutablePair<Service, ActionStatus> importServiceFromUICsar(UploadServiceInfo serviceInfoObject, User user, + String serviceUniqueId) throws ZipException { + + Service newService; + ImmutablePair<Service, ActionStatus> result = null; + ActionStatus actionStatus; + Service service = new Service(); + String payloadName = serviceInfoObject.getPayloadName(); + fillServiceFromServiceInfoObject(service, serviceInfoObject); + + Map<String, byte[]> csarUIPayloadRes = getCsarFromPayload(serviceInfoObject); + + getAndValidateCsarYaml(csarUIPayloadRes, service, user, payloadName); + + newService = serviceImportManager.getServiceImportBusinessLogic() + .createService(service, AuditingActionEnum.CREATE_SERVICE, user, csarUIPayloadRes, + payloadName); + actionStatus = ActionStatus.CREATED; + + return new ImmutablePair<>(newService, actionStatus); + } + + + private void fillServiceFromServiceInfoObject(Service service, UploadServiceInfo serviceInfoObject) { + serviceImportManager.populateServiceMetadata(serviceInfoObject, service); + fillArtifacts(service, serviceInfoObject); + + } + + private Map<String, byte[]> getCsarFromPayload(UploadServiceInfo innerElement) + throws ZipException { + String csarUUID = innerElement.getPayloadName(); + String payloadData = innerElement.getPayloadData(); + return getComponentCsarFromPayload(csarUUID, payloadData); + } + + private void getAndValidateCsarYaml(Map<String, byte[]> csarUIPayload, Service service, User user, + String csarUUID) { + getAndValidateComponentCsarYaml(csarUIPayload, service, user, csarUUID); + } + + private void fillArtifacts(Service service, UploadServiceInfo serviceInfoObject) { + if (service != null && serviceInfoObject != null) { + List<UploadArtifactInfo> artifactList = serviceInfoObject.getArtifactList(); + if (artifactList != null) { + Map<String, ArtifactDefinition> artifactsHM = new HashMap<>(); + buildArtifactsHM(artifactList, artifactsHM); + service.setArtifacts(artifactsHM); + } + } + } + /** + * import service payload to postman + * @param responseWrapper + * @param uploadServiceInfoWrapper + * @param yamlStringWrapper + * @param user + * @param serviceInfoJsonString + * @param serviceAuthorityEnum + * @param file + * @throws ZipException + */ + protected void fillServicePayload(Wrapper<Response> responseWrapper, Wrapper<UploadServiceInfo> uploadServiceInfoWrapper, Wrapper<String> yamlStringWrapper, User user, String serviceInfoJsonString, ServiceAuthorityTypeEnum serviceAuthorityEnum, + File file) throws ZipException { + log.debug("enter fillServicePayload"); + if (responseWrapper.isEmpty()) { + log.debug("enter fillServicePayload,get responseWrapper is empty"); + if (serviceAuthorityEnum.isBackEndImport()) { + // PrePayload Validations + if (responseWrapper.isEmpty()) { + validateDataNotNull(responseWrapper, file, serviceInfoJsonString); + } + if (responseWrapper.isEmpty()){ + log.debug("enter fillServicePayload,responseWrapper is empty"); + } + if(!serviceAuthorityEnum.equals(ServiceAuthorityTypeEnum.CSAR_TYPE_BE)){ + if (responseWrapper.isEmpty()) { + validateZip(responseWrapper, file, uploadServiceInfoWrapper.getInnerElement().getPayloadName()); + } + + // Fill PayLoad From File + if (responseWrapper.isEmpty()) { + fillToscaTemplateFromZip(yamlStringWrapper, uploadServiceInfoWrapper.getInnerElement().getPayloadName(), file); + } + }else{ + + log.debug("enter fillServicePayload,ServiceAuthorityTypeEnum is CSAR_TYPE_BE"); + if (responseWrapper.isEmpty()) { + validateCsar(responseWrapper, file, uploadServiceInfoWrapper.getInnerElement().getPayloadName()); + } + if (!responseWrapper.isEmpty()) { + log.debug("enter fillServicePayload,get responseWrapper:{}", responseWrapper); + } + // Fill PayLoad From File + if (responseWrapper.isEmpty()) { + fillServicePayloadDataFromFile(responseWrapper, uploadServiceInfoWrapper.getInnerElement(), file); + } + + } + + } else { + // Fill PayLoad From JSON + if (responseWrapper.isEmpty()) { + fillServiceToscaTemplateFromJson(responseWrapper, yamlStringWrapper, user, uploadServiceInfoWrapper.getInnerElement()); + } + } + + } + + } + + protected void fillServicePayloadDataFromFile(Wrapper<Response> responseWrapper, UploadServiceInfo uploadServiceInfoWrapper, File file) { + try(InputStream fileInputStream = new FileInputStream(file)){ + + log.debug("enter fillServicePayloadDataFromFile"); + byte [] data = new byte[(int)file.length()]; + if( fileInputStream.read(data) == -1){ + log.info("Invalid json was received."); + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT); + + Response errorResp = buildErrorResponse(responseFormat); + responseWrapper.setInnerElement(errorResp); + } + String payloadData = Base64.encodeBase64String(data); + uploadServiceInfoWrapper.setPayloadData(payloadData); + log.debug("enter fillServicePayloadDataFromFile,get payloadData:{}", + uploadServiceInfoWrapper.getPayloadData()); + + log.debug("enter fillServicePayloadDataFromFile,get uploadService:{}",uploadServiceInfoWrapper); + + } catch (IOException e) { + log.info("Invalid json was received or Error while closing input Stream."); + log.debug("Invalid json was received or Error while closing input Stream. {}", e.getMessage(), e); + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_CONTENT); + + Response errorResp = buildErrorResponse(responseFormat); + responseWrapper.setInnerElement(errorResp); + } + } + + private void fillServiceToscaTemplateFromJson(Wrapper<Response> responseWrapper, Wrapper<String> yamlStringWrapper, User user, UploadServiceInfo serviceInfo) { + if (serviceInfo.getPayloadData() == null || serviceInfo.getPayloadData().isEmpty()) { + ResponseFormat responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.INVALID_RESOURCE_PAYLOAD); + Response errorResponse = buildErrorResponse(responseFormat); + getComponentsUtils().auditResource(responseFormat, user, serviceInfo.getName(), AuditingActionEnum.IMPORT_RESOURCE); + responseWrapper.setInnerElement(errorResponse); + } else { + String toscaPayload = serviceInfo.getPayloadData(); + String decodedPayload = new String(Base64.decodeBase64(toscaPayload)); + yamlStringWrapper.setInnerElement(decodedPayload); + } + } + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java index 5c3bd859be..0896891ad3 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java @@ -71,6 +71,7 @@ import org.openecomp.sdc.be.components.impl.aaf.AafPermission; import org.openecomp.sdc.be.components.impl.aaf.PermissionAllowed; 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.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; @@ -79,6 +80,7 @@ import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.datatypes.enums.CreatedFrom; import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields; +import org.openecomp.sdc.be.externalapi.servlet.representation.ReplaceVNFInfo; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.ServletUtils; import org.openecomp.sdc.be.info.CreateAndAssotiateInfo; @@ -1623,4 +1625,100 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet { return Either.left(Arrays.asList(convertStatus.left().value())); } + @POST + @Path("/services/replaceVNF") + @Operation(description = "Replace new VNF based on the existing VNF", method = "POST", + summary = "Return whether the replace VNF is successful", responses = { + @ApiResponse(responseCode = "200", description = "ECOMP component is authenticated and list of Catalog Assets Metadata is returned", + content = @Content(array = @ArraySchema(schema = @Schema(implementation = ReplaceVNFInfo.class)))), + @ApiResponse(responseCode = "400", description = "Missing 'X-ECOMP-InstanceID' HTTP header - POL5001"), + @ApiResponse(responseCode = "401", + description = "ECOMP component should authenticate itself and to re-send again HTTP request with its Basic Authentication credentials - POL5002"), + @ApiResponse(responseCode = "403", description = "ECOMP component is not authorized - POL5003"), + @ApiResponse(responseCode = "404", + description = "Error: Requested '%1' (uuid) resource was not found - SVC4063"), + @ApiResponse(responseCode = "405", + description = "Method Not Allowed : Invalid HTTP method type used ( PUT,DELETE,POST will be rejected) - POL4050"), + @ApiResponse(responseCode = "500", + description = "The GET request failed either due to internal SDC problem. ECOMP Component should continue the attempts to get the needed information - POL5000"), + @ApiResponse(responseCode = "409", description = "Service already exist")}) + @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) + public Response replaceVNF( + @Parameter(description = "The user id", + required = true) @HeaderParam(value = Constants.USER_ID_HEADER) String userId, + @Parameter(description = "X-ECOMP-RequestID header", + required = false) @HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId, + @Parameter(description = "X-ECOMP-InstanceID header", required = true) + @HeaderParam(value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader, + @Parameter(description = "Determines the format of the body of the response", + required = false) @HeaderParam(value = Constants.ACCEPT_HEADER) String accept, + @Parameter(description = "The username and password", + required = true) @HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization, + @Context final HttpServletRequest request, + @Parameter(description = "Resource object to be created", required = true) String data) { + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("replaceVNF: Start handle request of {}", url); + User modifier = new User(); + modifier.setUserId(userId); + log.debug("replaceVNF:modifier id is {}", userId); + validateNotEmptyBody(data); + + Either<ReplaceVNFInfo, ResponseFormat> convertResponse = parseToReplaceVNFInfo(data, modifier); + if (convertResponse.isRight()) { + throw new ByResponseFormatComponentException(convertResponse.right().value()); + } + + log.debug("replaceVNF:get ReplaceVNFInfo success"); + + String containerComponentType = "services"; + ReplaceVNFInfo replaceVNFInfo = convertResponse.left().value(); + String serviceUniqueId = replaceVNFInfo.getServiceUniqueId(); + String abstractResourceUniqueId = replaceVNFInfo.getAbstractResourceUniqueId(); + + ComponentInstance componentInstance = replaceVNFInfo.getRealVNFComponentInstance(); + log.debug("replaceVNF:get ReplaceVNFInfo,serviceUniqueId:{},abstractResourceUniqueId:{}", + serviceUniqueId,abstractResourceUniqueId); + try { + /** + * delete vnf + */ + ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.findByParamName(containerComponentType); + if (componentInstanceBusinessLogic == null) { + log.debug("replaceVNF:Unsupported component type {}", containerComponentType); + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType)); + } + Either<ComponentInstance, ResponseFormat> componentInstanceEither = componentInstanceBusinessLogic.deleteAbstractComponentInstance(containerComponentType, serviceUniqueId, abstractResourceUniqueId, userId); + if (componentInstanceEither.isRight()) { + log.debug("replaceVNF:delete Abstract ComponentInstance field"); + return buildErrorResponse(componentInstanceEither.right().value()); + } + /** + * add vnf + */ + log.debug("replaceVNF,start add vnf"); + componentInstance.setInvariantName(null); + componentInstance.setCreatedFrom(CreatedFrom.UI); + + Either<ComponentInstance, ResponseFormat> realComponentInstance = componentInstanceBusinessLogic.createRealComponentInstance(containerComponentType, serviceUniqueId, userId, componentInstance); + if (realComponentInstance.isRight()) { + log.debug("replaceVNF:filed to add vnf"); + return buildErrorResponse(realComponentInstance.right().value()); + } + ComponentInstance newComponentInstance = realComponentInstance.left().value(); + log.debug("replaceVNF:success to add vnf"); + + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), newComponentInstance); + } catch (Exception e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("replaceVNF"); + log.debug("replaceVNF with exception", e); + throw e; + } + } + + private Either<ReplaceVNFInfo, ResponseFormat> parseToReplaceVNFInfo(String serviceJson, User user) { + log.debug("enter parseToReplaceVNFInfo,get serviceJson:{}",serviceJson); + return getComponentsUtils().convertJsonToObjectUsingObjectMapper(serviceJson, user, ReplaceVNFInfo.class, AuditingActionEnum.CREATE_RESOURCE, ComponentTypeEnum.SERVICE); + } + } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java index 3a341f127b..168a70aad2 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java @@ -32,11 +32,15 @@ import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.annotations.servers.Servers; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tags; +import java.io.File; import org.apache.http.HttpStatus; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.FormDataParam; import org.json.JSONException; import org.json.JSONObject; import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; import org.openecomp.sdc.be.components.impl.CsarValidationUtils; +import org.openecomp.sdc.be.components.impl.ElementBusinessLogic; import org.openecomp.sdc.be.components.impl.ImportUtils; import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic; import org.openecomp.sdc.be.components.impl.ResourceImportManager; @@ -53,6 +57,8 @@ import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.UploadResourceInfo; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.resources.data.auditing.model.DistributionData; +import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo; import org.openecomp.sdc.be.servlets.ResourceUploadServlet.ResourceAuthorityTypeEnum; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.common.api.Constants; @@ -594,4 +600,97 @@ public class ResourcesServlet extends AbstractValidationsServlet { throw e; } } + + @POST + @Path("/resources/importReplaceResource") + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Import Resource", method = "POST", summary = "Returns imported resource", responses = { + @ApiResponse(responseCode = "201", description = "Resource created"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "409", description = "Resource already exist")}) + @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) + public Response importReplaceResource( + @Parameter(description = "The user id", + required = true) @HeaderParam(value = Constants.USER_ID_HEADER) String userId, + @Parameter(description = "X-ECOMP-RequestID header", + required = false) @HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId, + @Parameter(description = "X-ECOMP-InstanceID header", required = true) @HeaderParam( + value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader, + @Parameter(description = "Determines the format of the body of the response", + required = false) @HeaderParam(value = Constants.ACCEPT_HEADER) String accept, + @Parameter(description = "The username and password", + required = true) @HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization, + @Context final HttpServletRequest request, + @Parameter(description = "FileInputStream") + @FormDataParam("resourceZip") File file, + @Parameter(description = "ContentDisposition") + @FormDataParam("resourceZip") FormDataContentDisposition contentDispositionHeader, + @Parameter(description = "resourceMetadata") + @FormDataParam("resourceZipMetadata") String resourceInfoJsonString) { + + init(); + + String requestURI = request.getRequestURI(); + String url = request.getMethod() + " " + requestURI; + log.debug("importReplaceResource,Start handle request of {}", url); + + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("importReplaceResource,modifier id is {}", userId); + + log.debug("importReplaceResource,get file:{},fileName:{}", file, file.getName()); + + Response response; + ResponseFormat responseFormat = null; + AuditingActionEnum auditingActionEnum = AuditingActionEnum.Import_Replace_Resource; + String assetType = "resources"; + + ComponentTypeEnum componentType = ComponentTypeEnum.findByParamName(assetType); + ResourceCommonInfo resourceCommonInfo = new ResourceCommonInfo(componentType.getValue()); + DistributionData distributionData = new DistributionData(instanceIdHeader, requestURI); + // Mandatory + if (instanceIdHeader == null || instanceIdHeader.isEmpty()) { + log.debug("importReplaceResource: Missing X-ECOMP-InstanceID header"); + responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID); + getComponentsUtils().auditExternalGetAsset(responseFormat, auditingActionEnum, distributionData, + resourceCommonInfo, requestId, null); + return buildErrorResponse(responseFormat); + } + + try { + Wrapper<Response> responseWrapper = new Wrapper<>(); + // file import + Wrapper<User> userWrapper = new Wrapper<>(); + Wrapper<UploadResourceInfo> uploadResourceInfoWrapper = new Wrapper<>(); + Wrapper<String> yamlStringWrapper = new Wrapper<>(); + + ResourceAuthorityTypeEnum serviceAuthorityEnum = ResourceAuthorityTypeEnum.CSAR_TYPE_BE; + + // PayLoad Validations + commonGeneralValidations(responseWrapper, userWrapper, uploadResourceInfoWrapper, serviceAuthorityEnum, userId, resourceInfoJsonString); + + fillPayload(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, modifier, resourceInfoJsonString, serviceAuthorityEnum, file); + + specificResourceAuthorityValidations(responseWrapper, uploadResourceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, resourceInfoJsonString, serviceAuthorityEnum); + + log.debug("importReplaceResource:get payload:{}", uploadResourceInfoWrapper.getInnerElement().getPayloadData()); + + log.debug("importReplaceResource:get ResourceType:{}", + uploadResourceInfoWrapper.getInnerElement().getResourceType()); + + if (responseWrapper.isEmpty()) { + log.debug("importReplaceService:start handleImport"); + handleImport(responseWrapper, userWrapper.getInnerElement(), uploadResourceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), serviceAuthorityEnum, true, null); + } + + return responseWrapper.getInnerElement(); + } catch (ZipException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Import Resource"); + log.debug("import resource failed with exception", e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + } + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java index 5292f6e9f2..57a29566b1 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java @@ -35,8 +35,13 @@ import io.swagger.v3.oas.annotations.servers.Server; import io.swagger.v3.oas.annotations.servers.Servers; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tags; +import java.io.File; +import java.io.FileNotFoundException; import org.apache.http.HttpStatus; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.FormDataParam; import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ElementBusinessLogic; import org.openecomp.sdc.be.components.impl.ResourceBusinessLogic; import org.openecomp.sdc.be.components.impl.ResourceImportManager; import org.openecomp.sdc.be.components.impl.ServiceBusinessLogic; @@ -46,15 +51,21 @@ import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponent import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.datamodel.ServiceRelations; +import org.openecomp.sdc.be.datatypes.components.ServiceMetadataDataDefinition; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.model.Component; import org.openecomp.sdc.be.model.DistributionStatusEnum; import org.openecomp.sdc.be.model.GroupInstanceProperty; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.Service; +import org.openecomp.sdc.be.model.UploadServiceInfo; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; +import org.openecomp.sdc.be.resources.data.auditing.model.DistributionData; +import org.openecomp.sdc.be.resources.data.auditing.model.ResourceCommonInfo; +import org.openecomp.sdc.be.servlets.ServiceUploadServlet.ServiceAuthorityTypeEnum; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.datastructure.Wrapper; @@ -62,6 +73,7 @@ import org.openecomp.sdc.common.log.elements.LoggerSupportability; import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions; import org.openecomp.sdc.common.log.enums.StatusCode; import org.openecomp.sdc.common.log.wrappers.Logger; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.stereotype.Controller; @@ -93,6 +105,7 @@ import java.util.Map; @Controller public class ServiceServlet extends AbstractValidationsServlet { + private final ElementBusinessLogic elementBusinessLogic; private static final Logger log = Logger.getLogger(ServiceServlet.class); private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(ServiceServlet.class.getName()); @@ -107,9 +120,10 @@ public class ServiceServlet extends AbstractValidationsServlet { ComponentsUtils componentsUtils, ServletUtils servletUtils, ResourceImportManager resourceImportManager, ServiceBusinessLogic serviceBusinessLogic, - ResourceBusinessLogic resourceBusinessLogic) { + ResourceBusinessLogic resourceBusinessLogic, ElementBusinessLogic elementBusinessLogic) { super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager); this.serviceBusinessLogic = serviceBusinessLogic; + this.elementBusinessLogic = elementBusinessLogic; } @POST @@ -723,4 +737,181 @@ public class ServiceServlet extends AbstractValidationsServlet { throw e; } } + + @POST + @Path("/services/importService") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Import Service", method = "POST", summary = "Returns imported service", responses = { + @ApiResponse(responseCode = "201", description = "Service created"), @ApiResponse(responseCode = "403", description = "Restricted operation"), @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), @ApiResponse(responseCode = "409", description = "Service already exist")}) + public Response importNsService(@Parameter(description = "Service object to be imported", required = true) String data, @Context final HttpServletRequest request, @HeaderParam(value = Constants.USER_ID_HEADER) String userId) { + + userId = (userId != null) ? userId : request.getHeader(Constants.USER_ID_HEADER); + initSpringFromContext(); + + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("Start handle request of {}" , url); + + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("modifier id is {}", userId); + + Response response; + try { + + Wrapper<Response> responseWrapper = new Wrapper<>(); + performUIImport(responseWrapper, data, request, userId, null); + return responseWrapper.getInnerElement(); + } catch (IOException | ZipException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Import Service"); + log.debug("import service failed with exception", e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + } + } + + private void performUIImport(Wrapper<Response> responseWrapper, String data, final HttpServletRequest request, String userId, String ServiceUniqueId) + throws FileNotFoundException, ZipException { + + Wrapper<User> userWrapper = new Wrapper<>(); + Wrapper<UploadServiceInfo> uploadServiceInfoWrapper = new Wrapper<>(); + Wrapper<String> yamlStringWrapper = new Wrapper<>(); + + ServiceAuthorityTypeEnum ServiceAuthorityEnum = ServiceAuthorityTypeEnum.USER_TYPE_UI; + + commonServiceGeneralValidations(responseWrapper, userWrapper, uploadServiceInfoWrapper, ServiceAuthorityEnum, userId, data); + + specificServiceAuthorityValidations(responseWrapper, uploadServiceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, data, ServiceAuthorityEnum); + + if (responseWrapper.isEmpty()) { + handleImportService(responseWrapper, userWrapper.getInnerElement(), uploadServiceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), ServiceAuthorityEnum, true, ServiceUniqueId); + } + } + + /**import ReplaceService + * + * @param userId + * @param requestId + * @param instanceIdHeader + * @param accept + * @param authorization + * @param request + * @param file + * @param contentDispositionHeader + * @param serviceInfoJsonString + * @param uuid + * @return + */ + @POST + @Path("/services/serviceUUID/{uuid}/importReplaceService") + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Import Service", method = "POST", summary = "Returns imported service", responses = { + @ApiResponse(responseCode = "201", description = "Service created"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "409", description = "Service already exist")}) + @PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE) + public Response importReplaceService( + @Parameter(description = "The user id", + required = true) @HeaderParam(value = Constants.USER_ID_HEADER) String userId, + @Parameter(description = "X-ECOMP-RequestID header", + required = false) @HeaderParam(value = Constants.X_ECOMP_REQUEST_ID_HEADER) String requestId, + @Parameter(description = "X-ECOMP-InstanceID header", required = true) @HeaderParam( + value = Constants.X_ECOMP_INSTANCE_ID_HEADER) final String instanceIdHeader, + @Parameter(description = "Determines the format of the body of the response", + required = false) @HeaderParam(value = Constants.ACCEPT_HEADER) String accept, + @Parameter(description = "The username and password", + required = true) @HeaderParam(value = Constants.AUTHORIZATION_HEADER) String authorization, + @Context final HttpServletRequest request, + @Parameter(description = "FileInputStream") + @FormDataParam("serviceZip") File file, + @Parameter(description = "ContentDisposition") + @FormDataParam("serviceZip") FormDataContentDisposition contentDispositionHeader, + @Parameter(description = "serviceMetadata") + @FormDataParam("serviceZipMetadata") String serviceInfoJsonString, + @Parameter(description = "The requested asset uuid", + required = true) @PathParam("uuid") final String uuid) { + + initSpringFromContext(); + + String requestURI = request.getRequestURI(); + String url = request.getMethod() + " " + requestURI; + log.debug("importReplaceService,Start handle request of {}", url); + + // get modifier id + User modifier = new User(); + modifier.setUserId(userId); + log.debug("importReplaceService,modifier id is {}", userId); + + log.debug("importReplaceService,get file:{},fileName:{}",file,file.getName()); + + Response response; + ResponseFormat responseFormat =null; + AuditingActionEnum auditingActionEnum = AuditingActionEnum.Import_Replace_Service; + String assetType = "services"; + + Either<List<? extends Component>, ResponseFormat> assetTypeData = elementBusinessLogic.getCatalogComponentsByUuidAndAssetType(assetType, uuid); + + if (assetTypeData.isRight() || assetTypeData.left().value().size() != 1) { + log.debug("getServiceAbstractStatus: Service Fetching Failed"); + throw new ByResponseFormatComponentException(assetTypeData.right().value()); + } + + log.debug("getServiceAbstractStatus: Service Fetching Success"); + + Service oldService = (Service) assetTypeData.left().value().get(0); + + ComponentTypeEnum componentType = ComponentTypeEnum.findByParamName(assetType); + ResourceCommonInfo resourceCommonInfo = new ResourceCommonInfo(componentType.getValue()); + DistributionData distributionData = new DistributionData(instanceIdHeader, requestURI); + // Mandatory + if (instanceIdHeader == null || instanceIdHeader.isEmpty()) { + log.debug("importReplaceService: Missing X-ECOMP-InstanceID header"); + responseFormat = getComponentsUtils().getResponseFormat(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID); + getComponentsUtils().auditExternalGetAsset(responseFormat, auditingActionEnum, distributionData, + resourceCommonInfo, requestId, null); + return buildErrorResponse(responseFormat); + } + + try { + Wrapper<Response> responseWrapper = new Wrapper<>(); + // file import + Wrapper<User> userWrapper = new Wrapper<>(); + Wrapper<UploadServiceInfo> uploadServiceInfoWrapper = new Wrapper<>(); + Wrapper<String> yamlStringWrapper = new Wrapper<>(); + + ServiceUploadServlet.ServiceAuthorityTypeEnum serviceAuthorityEnum = ServiceUploadServlet.ServiceAuthorityTypeEnum.CSAR_TYPE_BE; + + // PayLoad Validations + commonServiceGeneralValidations(responseWrapper, userWrapper, uploadServiceInfoWrapper, serviceAuthorityEnum, userId, serviceInfoJsonString); + + fillServicePayload(responseWrapper, uploadServiceInfoWrapper, yamlStringWrapper, modifier, serviceInfoJsonString, serviceAuthorityEnum, file); + + specificServiceAuthorityValidations(responseWrapper, uploadServiceInfoWrapper, yamlStringWrapper, userWrapper.getInnerElement(), request, serviceInfoJsonString, serviceAuthorityEnum); + + log.debug("importReplaceService:get payload:{}", uploadServiceInfoWrapper.getInnerElement().getPayloadData()); + + ServiceMetadataDataDefinition serviceMetadataDataDefinition = (ServiceMetadataDataDefinition)oldService.getComponentMetadataDefinition().getMetadataDataDefinition(); + + uploadServiceInfoWrapper.getInnerElement().setServiceVendorModelNumber(serviceMetadataDataDefinition.getServiceVendorModelNumber()); + uploadServiceInfoWrapper.getInnerElement().setDescription(oldService.getDescription()); + uploadServiceInfoWrapper.getInnerElement().setCategories(oldService.getCategories()); + uploadServiceInfoWrapper.getInnerElement().setIcon(oldService.getIcon()); + uploadServiceInfoWrapper.getInnerElement().setProjectCode(oldService.getProjectCode()); + + + if (responseWrapper.isEmpty()) { + log.debug("importReplaceService:start handleImportService"); + handleImportService(responseWrapper, userWrapper.getInnerElement(), uploadServiceInfoWrapper.getInnerElement(), yamlStringWrapper.getInnerElement(), serviceAuthorityEnum, true, null); + } + + return responseWrapper.getInnerElement(); + } catch (IOException | ZipException e) { + BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Import Service"); + log.debug("import service failed with exception", e); + response = buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + return response; + } + } } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceUploadServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceUploadServlet.java new file mode 100644 index 0000000000..285568560d --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceUploadServlet.java @@ -0,0 +1,129 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.servlets; + +import com.jcabi.aspects.Loggable; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.servers.Server; +import io.swagger.v3.oas.annotations.servers.Servers; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; +import java.io.File; +import javax.inject.Singleton; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.glassfish.jersey.media.multipart.FormDataContentDisposition; +import org.glassfish.jersey.media.multipart.FormDataParam; +import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ResourceImportManager; +import org.openecomp.sdc.be.components.impl.ServiceImportManager; +import org.openecomp.sdc.be.config.BeEcompErrorManager; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.impl.WebAppContextWrapper; +import org.openecomp.sdc.be.model.UploadServiceInfo; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.user.UserBusinessLogic; +import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.datastructure.Wrapper; +import org.openecomp.sdc.common.log.wrappers.Logger; +import org.springframework.stereotype.Controller; +import org.springframework.web.context.WebApplicationContext; + +/** + * Root service (exposed at "/" path) + */ + +//upload Service model by Shiyong1989@hotmail.com +@Loggable(prepend = true, value = Loggable.DEBUG, trim = false) +@Path("/v1/catalog/uploadservice") +@Tags({@Tag(name = "SDC Internal APIs")}) +@Singleton + +public class ServiceUploadServlet extends AbstractValidationsServlet { + + private static final Logger log = Logger.getLogger(ServiceUploadServlet.class); + public static final String NORMATIVE_TYPE_SERVICE = "multipart"; + public static final String CSAR_TYPE_SERVICE = "csar"; + public static final String USER_TYPE_SERVICE = "user-service"; + public static final String USER_TYPE_SERVICE_UI_IMPORT = "user-servcie-ui-import"; + + public ServiceUploadServlet(UserBusinessLogic userBusinessLogic, + ComponentInstanceBusinessLogic componentInstanceBL, + ComponentsUtils componentsUtils, ServletUtils servletUtils, + ResourceImportManager resourceImportManager) { + super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager); + } + + public enum ServiceAuthorityTypeEnum { + NORMATIVE_TYPE_BE(NORMATIVE_TYPE_SERVICE, true, false), USER_TYPE_BE(USER_TYPE_SERVICE, true, true), + USER_TYPE_UI(USER_TYPE_SERVICE_UI_IMPORT, false, true), CSAR_TYPE_BE(CSAR_TYPE_SERVICE, true, true); + + private String urlPath; + private boolean isBackEndImport, isUserTypeService; + + public static ServiceAuthorityTypeEnum findByUrlPath(String urlPath) { + ServiceAuthorityTypeEnum found = null; + for (ServiceAuthorityTypeEnum curr : ServiceAuthorityTypeEnum.values()) { + if (curr.getUrlPath().equals(urlPath)) { + found = curr; + break; + } + } + return found; + } + + private ServiceAuthorityTypeEnum(String urlPath, boolean isBackEndImport, boolean isUserTypeService) { + this.urlPath = urlPath; + this.isBackEndImport = isBackEndImport; + this.isUserTypeService = isUserTypeService; + } + + public String getUrlPath() { + return urlPath; + } + + public boolean isBackEndImport() { + return isBackEndImport; + } + + public boolean isUserTypeService() { + return isUserTypeService; + } + } +} + diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java index 1f33a2424b..e19ea21c74 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java @@ -25,6 +25,7 @@ import static org.openecomp.sdc.be.tosca.ComponentCache.MergeStrategy.overwriteI import fj.F; import fj.data.Either; +import java.text.SimpleDateFormat; import io.vavr.Tuple2; import io.vavr.control.Try; import io.vavr.control.Option; @@ -34,6 +35,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; @@ -43,6 +45,7 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.TimeZone; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -150,6 +153,8 @@ public class CsarUtils { private static final String TOSCA_META_PATH_FILE_NAME = "TOSCA-Metadata/TOSCA.meta"; private static final String TOSCA_META_VERSION = "1.0"; private static final String CSAR_VERSION = "1.1"; + // add manifest + private static final String Service_Manifest = "NS.mf"; public static final String ARTIFACTS = "Artifacts"; private static final String DEFINITION = "Definitions"; private static final String DEL_PATTERN = "([/\\\\]+)"; @@ -270,6 +275,9 @@ public class CsarUtils { String fileName = artifactDef.getArtifactName(); zip.putNextEntry(new ZipEntry(DEFINITIONS_PATH + fileName)); zip.write(mainYaml); + + LifecycleStateEnum lifecycleState = component.getLifecycleState(); + addServiceMf(component, zip, lifecycleState, isInCertificationRequest, fileName, mainYaml); //US798487 - Abstraction of complex types if (!ModelConverter.isAtomicComponent(component)){ @@ -317,6 +325,41 @@ public class CsarUtils { return writeAllFilesToCsar(component, collectedComponentCsarDefinition.left().value(), zip, isInCertificationRequest); } + private void addServiceMf(Component component, ZipOutputStream zip, LifecycleStateEnum lifecycleState, boolean isInCertificationRequest, String fileName, byte[] mainYaml) throws IOException{ + // add mf + if((component.getComponentType() == ComponentTypeEnum.SERVICE) && (lifecycleState != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT)){ + String serviceName = component.getName(); + String createdBy = component.getCreatorUserId(); + String serviceVersion; + if(isInCertificationRequest){ + int tmp = Integer.valueOf(component.getVersion().split("\\.")[0]) + 1; + serviceVersion = String.valueOf(tmp) + ".0"; + } + else{ + serviceVersion = component.getVersion(); + } + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'"); + format.setTimeZone(TimeZone.getTimeZone("UTC")); + //String createDate = format.format(new Date(component.getCreationDate())); + Date date = new Date(); + String releaseTime = format.format(date); + + if (component.getCategories() == null || component.getCategories().get(0) == null){ + return; + } + + String serviceType = component.getCategories().get(0).getName(); + String description = component.getDescription(); + String serviceTemplate = DEFINITIONS_PATH + fileName; + String hash = GeneralUtility.calculateMD5Base64EncodedByByteArray(mainYaml); + String nsMfBlock0 = createNsMfBlock0(serviceName, createdBy, serviceVersion, releaseTime, serviceType, description, serviceTemplate, hash); + byte[] nsMfBlock0Byte = nsMfBlock0.getBytes(); + zip.putNextEntry(new ZipEntry(Service_Manifest)); + zip.write(nsMfBlock0Byte); + } + } + private Either<ToscaRepresentation, ResponseFormat> fetchToscaRepresentation( Component component, boolean getFromCS, @@ -748,6 +791,24 @@ public class CsarUtils { final String block0template = "TOSCA-Meta-File-Version: %s\nCSAR-Version: %s\nCreated-By: %s\nEntry-Definitions: Definitions/%s\n\nName: csar.meta\nContent-Type: text/plain\n"; return String.format(block0template, metaFileVersion, csarVersion, createdBy, entryDef); } + + private String createNsMfBlock0(String serviceName, String createdBy, String serviceVersion, String releaseTime, + String serviceType, String description, String serviceTemplate, String hash) { + final String block0template = "metadata??\n" + + "ns_product_name: %s\n" + + "ns_provider_id: %s\n" + + "ns_package_version: %s\n" + + //"ns_create_date_time: %s\n" + + "ns_release_data_time: %s\n" + + "ns_type: %s\n" + + "ns_package_description: %s\n\n" + + "Source: %s\n" + + "Algorithm: MD5\n" + + "Hash: %s\n\n"; + return String + .format(block0template, serviceName, createdBy, serviceVersion, releaseTime, serviceType, description, + serviceTemplate, hash); + } /** * Extracts artifacts of VFCs from CSAR diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaUtils.java index 902d789d87..5b03b6378e 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaUtils.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaUtils.java @@ -38,7 +38,7 @@ public class ToscaUtils { public static boolean isNotComplexVfc(Component component) { if (ComponentTypeEnum.RESOURCE == component.getComponentType()) { ResourceTypeEnum resourceType = ((ResourceMetadataDataDefinition) component.getComponentMetadataDefinition().getMetadataDataDefinition()).getResourceType(); - if (ResourceTypeEnum.CVFC == resourceType) { + if (ResourceTypeEnum.CVFC == resourceType ) { return false; } } |