package org.alien4cloud.tosca.editor.services;
import java.nio.file.Path;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.alien4cloud.tosca.catalog.ArchiveParserUtil;
import org.alien4cloud.tosca.catalog.IArchivePostProcessor;
import org.alien4cloud.tosca.editor.EditionContextManager;
import org.alien4cloud.tosca.editor.exception.EditorToscaYamlInvalidException;
import org.alien4cloud.tosca.editor.exception.EditorToscaYamlNotSupportedException;
import org.alien4cloud.tosca.editor.exception.EditorToscaYamlParsingException;
import org.alien4cloud.tosca.model.templates.Topology;
import org.alien4cloud.tosca.model.types.AbstractToscaType;
import org.springframework.stereotype.Component;
import alien4cloud.paas.wf.WorkflowsBuilderService;
import alien4cloud.tosca.context.ToscaContext;
import alien4cloud.tosca.model.ArchiveRoot;
import alien4cloud.tosca.parser.ParsingErrorLevel;
import alien4cloud.tosca.parser.ParsingException;
import alien4cloud.tosca.parser.ParsingResult;
import alien4cloud.tosca.parser.ToscaArchiveParser;
/**
* Process the upload of a topology in the context of the editor.
*/
@Component
public class EditorTopologyUploadService {
@Inject
private ToscaArchiveParser toscaArchiveParser;
@Resource(name = "editorArchivePostProcessor")
private IArchivePostProcessor postProcessor;
@Inject
private WorkflowsBuilderService workflowBuilderService;
public void processTopologyDir(Path archivePath, String workspace) {
// parse the archive.
try {
ParsingResult<ArchiveRoot> parsingResult = toscaArchiveParser.parseDir(archivePath);
processTopologyParseResult(archivePath, parsingResult, workspace);
} catch (ParsingException e) {
// Manage parsing error and dispatch them in the right editor exception
throw new EditorToscaYamlInvalidException("The uploaded file to override the topology yaml is not a valid Tosca Yaml.");
}
}
/**
* Process the import of a topology archive or yaml in the context of the editor.
*
* @param archivePath The path of the yaml or archive.
*/
public void processTopology(Path archivePath, String workspace) {
// parse the archive.
try {
ParsingResult<ArchiveRoot> parsingResult = toscaArchiveParser.parse(archivePath, true);
processTopologyParseResult(archivePath, parsingResult, workspace);
} catch (ParsingException e) {
// Manage parsing error and dispatch them in the right editor exception
throw new EditorToscaYamlParsingException("The uploaded file to override the topology yaml is not a valid Tosca Yaml.");
}
}
private void processTopologyParseResult(Path archivePath, ParsingResult<ArchiveRoot> parsingResult, String workspace) {
// parse the archive.
parsingResult = postProcessor.process(archivePath, parsingResult, workspace);
// check if any blocker error has been found during parsing process.
if (parsingResult.hasError(ParsingErrorLevel.ERROR)) {
// do not save anything if any blocker error has been found during import.
throw new EditorToscaYamlParsingException("Uploaded yaml files is not a valid tosca template", ArchiveParserUtil.toSimpleResult(parsingResult));
}
if (parsingResult.getResult().hasToscaTypes()) {
throw new EditorToscaYamlNotSupportedException("Tosca types are currently not supported in the topology editor context.");
}
if (!parsingResult.getResult().hasToscaTopologyTemplate()) {
throw new EditorToscaYamlNotSupportedException("A topology template is required in the topology edition context.");
}
Topology currentTopology = EditionContextManager.getTopology();
Topology parsedTopology = parsingResult.getResult().getTopology();
if (!currentTopology.getArchiveName().equals(parsedTopology.getArchiveName())
|| !currentTopology.getArchiveVersion().equals(parsedTopology.getArchiveVersion())) {
throw new EditorToscaYamlNotSupportedException(
"Template name and version must be set to [" + currentTopology.getArchiveName() + ":" + currentTopology.getArchiveVersion()
+ "] and cannot be updated to [" + parsedTopology.getArchiveName() + ":" + parsedTopology.getArchiveVersion() + "]");
}
// Copy static elements from the topology
parsedTopology.setId(currentTopology.getId());
// Update editor tosca context
ToscaContext.get().resetDependencies(parsedTopology.getDependencies());
// init the workflows for the topology based on the yaml
WorkflowsBuilderService.TopologyContext topologyContext = workflowBuilderService
.buildCachedTopologyContext(new WorkflowsBuilderService.TopologyContext() {
@Override
public Topology getTopology() {
return parsedTopology;
}
@Override
public <T extends AbstractToscaType> T findElement(Class<T> clazz, String id) {
return ToscaContext.get(clazz, id);
}
});
workflowBuilderService.initWorkflows(topologyContext);
// update the topology in the edition context with the new one
EditionContextManager.get().setTopology(parsingResult.getResult().getTopology());
}
}