package alien4cloud.topology; import java.util.List; import javax.annotation.Resource; import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; import org.alien4cloud.tosca.model.templates.Topology; import alien4cloud.paas.wf.WorkflowsBuilderService; import alien4cloud.topology.task.AbstractRelationshipTask; import alien4cloud.topology.task.AbstractTask; import alien4cloud.topology.task.ArtifactTask; import alien4cloud.topology.task.InputArtifactTask; import alien4cloud.topology.task.NodeFiltersTask; import alien4cloud.topology.task.PropertiesTask; import alien4cloud.topology.task.RequirementsTask; import alien4cloud.topology.task.SuggestionsTask; import alien4cloud.topology.task.TaskLevel; import alien4cloud.topology.task.WorkflowTask; import alien4cloud.topology.validation.NodeFilterValidationService; import alien4cloud.topology.validation.TopologyAbstractRelationshipValidationService; import alien4cloud.topology.validation.TopologyArtifactsValidationService; import alien4cloud.topology.validation.TopologyPropertiesValidationService; import alien4cloud.topology.validation.TopologyRequirementBoundsValidationServices; import lombok.extern.slf4j.Slf4j; @Service @Slf4j public class TopologyValidationService { @Resource private TopologyPropertiesValidationService topologyPropertiesValidationService; @Resource private TopologyRequirementBoundsValidationServices topologyRequirementBoundsValidationServices; @Resource private TopologyAbstractRelationshipValidationService topologyAbstractRelationshipValidationService; @Resource private NodeFilterValidationService nodeFilterValidationService; @Resource private WorkflowsBuilderService workflowBuilderService; @Resource private TopologyArtifactsValidationService topologyArtifactsValidationService; /** * Validate if a topology is valid for deployment configuration or not, * This is done before deployment configuration * * @param topology topology to be validated * @return the validation result */ public TopologyValidationResult validateTopology(Topology topology) { TopologyValidationResult dto = new TopologyValidationResult(); if (topology.getNodeTemplates() == null || topology.getNodeTemplates().size() < 1) { dto.setValid(false); return dto; } // validate the workflows dto.addTasks(workflowBuilderService.validateWorkflows(topology)); // validate abstract relationships dto.addTasks(topologyAbstractRelationshipValidationService.validateAbstractRelationships(topology)); // validate abstract node types and find suggestions // in this step, this is a warning, since they can be replaced by nodes comming from the location // TODO should we do this here or not? // dto.addToWarningList(topologyAbstractNodeValidationService.findReplacementForAbstracts(topology)); // validate requirements lowerBounds dto.addTasks(topologyRequirementBoundsValidationServices.validateRequirementsLowerBounds(topology)); // validate the node filters for all relationships dto.addTasks(nodeFilterValidationService.validateStaticRequirementFilters(topology)); // validate that all artifacts has been filled dto.addTasks(topologyArtifactsValidationService.validate(topology)); // validate required properties (properties of NodeTemplate, Relationship and Capability) List<PropertiesTask> validateProperties = topologyPropertiesValidationService.validateStaticProperties(topology); // List<PropertiesTask> validateProperties = null; if (hasOnlyPropertiesWarnings(validateProperties)) { dto.addWarnings(validateProperties); } else { dto.addTasks(validateProperties); } dto.setValid(isValidTaskList(dto.getTaskList())); return dto; } public static boolean hasOnlyPropertiesWarnings(List<PropertiesTask> properties) { if (properties == null) { return true; } for (PropertiesTask task : properties) { if (CollectionUtils.isNotEmpty(task.getProperties().get(TaskLevel.REQUIRED)) || CollectionUtils.isNotEmpty(task.getProperties().get(TaskLevel.ERROR))) { return false; } } return true; } /** * Define if a tasks list is valid or not regarding task types * * @param taskList * @return */ public static boolean isValidTaskList(List<AbstractTask> taskList) { if (taskList == null) { return true; } for (AbstractTask task : taskList) { // checking some required tasks if (task instanceof SuggestionsTask || task instanceof RequirementsTask || task instanceof PropertiesTask || task instanceof NodeFiltersTask || task instanceof WorkflowTask || task instanceof ArtifactTask || task instanceof InputArtifactTask || task instanceof AbstractRelationshipTask) { return false; } } return true; } }