aboutsummaryrefslogtreecommitdiffstats
path: root/jtosca/src/main/java/org/openecomp/sdc/toscaparser/ToscaTemplate.java
diff options
context:
space:
mode:
Diffstat (limited to 'jtosca/src/main/java/org/openecomp/sdc/toscaparser/ToscaTemplate.java')
-rw-r--r--jtosca/src/main/java/org/openecomp/sdc/toscaparser/ToscaTemplate.java987
1 files changed, 987 insertions, 0 deletions
diff --git a/jtosca/src/main/java/org/openecomp/sdc/toscaparser/ToscaTemplate.java b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/ToscaTemplate.java
new file mode 100644
index 0000000..25be141
--- /dev/null
+++ b/jtosca/src/main/java/org/openecomp/sdc/toscaparser/ToscaTemplate.java
@@ -0,0 +1,987 @@
+package org.openecomp.sdc.toscaparser;
+
+import org.openecomp.sdc.toscaparser.common.ExceptionCollector;
+import org.openecomp.sdc.toscaparser.common.JToscaException;
+import org.openecomp.sdc.toscaparser.elements.EntityType;
+import org.openecomp.sdc.toscaparser.elements.Metadata;
+import org.openecomp.sdc.toscaparser.extensions.ExtTools;
+import org.openecomp.sdc.toscaparser.parameters.Input;
+import org.openecomp.sdc.toscaparser.parameters.Output;
+import org.openecomp.sdc.toscaparser.prereq.CSAR;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class ToscaTemplate extends Object {
+
+ private static Logger log = LoggerFactory.getLogger(ToscaTemplate.class.getName());
+
+ // TOSCA template key names
+ private static final String DEFINITION_VERSION = "tosca_definitions_version";
+ private static final String DEFAULT_NAMESPACE = "tosca_default_namespace";
+ private static final String TEMPLATE_NAME = "template_name";
+ private static final String TOPOLOGY_TEMPLATE = "topology_template";
+ private static final String TEMPLATE_AUTHOR = "template_author";
+ private static final String TEMPLATE_VERSION = "template_version";
+ private static final String DESCRIPTION = "description";
+ private static final String IMPORTS = "imports";
+ private static final String DSL_DEFINITIONS = "dsl_definitions";
+ private static final String NODE_TYPES = "node_types";
+ private static final String RELATIONSHIP_TYPES = "relationship_types";
+ private static final String RELATIONSHIP_TEMPLATES = "relationship_templates";
+ private static final String CAPABILITY_TYPES = "capability_types";
+ private static final String ARTIFACT_TYPES = "artifact_types";
+ private static final String DATA_TYPES = "data_types";
+ private static final String INTERFACE_TYPES = "interface_types";
+ private static final String POLICY_TYPES = "policy_types";
+ private static final String GROUP_TYPES = "group_types";
+ private static final String REPOSITORIES = "repositories";
+
+ private static String SECTIONS[] = {
+ DEFINITION_VERSION, DEFAULT_NAMESPACE, TEMPLATE_NAME,
+ TOPOLOGY_TEMPLATE, TEMPLATE_AUTHOR, TEMPLATE_VERSION,
+ DESCRIPTION, IMPORTS, DSL_DEFINITIONS, NODE_TYPES,
+ RELATIONSHIP_TYPES, RELATIONSHIP_TEMPLATES,
+ CAPABILITY_TYPES, ARTIFACT_TYPES, DATA_TYPES,
+ INTERFACE_TYPES, POLICY_TYPES, GROUP_TYPES, REPOSITORIES
+ };
+
+ // Sections that are specific to individual template definitions
+ private static final String METADATA = "metadata";
+ private static ArrayList<String> SPECIAL_SECTIONS;
+
+ private ExtTools exttools = new ExtTools();
+
+ private ArrayList<String> VALID_TEMPLATE_VERSIONS;
+ private LinkedHashMap<String,ArrayList<String>> ADDITIONAL_SECTIONS;
+
+ private boolean bAbortOnParsingErrors = false;
+ private boolean isFile;
+ private String path;
+ private String inputPath;
+ private LinkedHashMap<String,Object> parsedParams;
+ private LinkedHashMap<String,Object> tpl;
+ private String version;
+ private ArrayList<Object> imports;
+ private LinkedHashMap<String,Object> relationshipTypes;
+ private Metadata metaData;
+ private String description;
+ private TopologyTemplate topologyTemplate;
+ private ArrayList<Repository> repositories;
+ private ArrayList<Input> inputs;
+ private ArrayList<RelationshipTemplate> relationshipTemplates;
+ private ArrayList<NodeTemplate> nodeTemplates;
+ private ArrayList<Output> outputs;
+ private ArrayList<Policy> policies;
+ private LinkedHashMap<String,Object> nestedToscaTplsWithTopology;
+ private ArrayList<TopologyTemplate> nestedToscaTemplatesWithTopology;
+ private ToscaGraph graph;
+ private String csarTempDir;
+ private int nestingLoopCounter;
+
+ @SuppressWarnings("unchecked")
+ public ToscaTemplate(String _path,
+ LinkedHashMap<String,Object> _parsedParams,
+ boolean aFile,
+ LinkedHashMap<String,Object> yamlDictTpl) throws JToscaException {
+
+ VALID_TEMPLATE_VERSIONS = new ArrayList<>();
+ VALID_TEMPLATE_VERSIONS.add("tosca_simple_yaml_1_0");
+ VALID_TEMPLATE_VERSIONS.addAll(exttools.getVersions());
+ ADDITIONAL_SECTIONS = new LinkedHashMap<>();
+ SPECIAL_SECTIONS = new ArrayList<>();
+ SPECIAL_SECTIONS.add(METADATA);
+ ADDITIONAL_SECTIONS.put("tosca_simple_yaml_1_0",SPECIAL_SECTIONS);
+ ADDITIONAL_SECTIONS.putAll(exttools.getSections());
+
+ //long startTime = System.nanoTime();
+
+ ExceptionCollector.start();
+
+ isFile = aFile;
+ inputPath = null;
+ path = null;
+ tpl = null;
+ csarTempDir = null;
+ nestedToscaTplsWithTopology = new LinkedHashMap<String,Object>();
+ nestedToscaTemplatesWithTopology = new ArrayList<TopologyTemplate>();
+
+ if(_path != null && !_path.isEmpty()) {
+ // save the original input path
+ inputPath = _path;
+ // get the actual path (will change with CSAR)
+ path = _getPath(_path);
+ // load the YAML template
+ if (path != null && !path.isEmpty()) {
+ try {
+ //System.out.println("Loading YAML file " + path);
+ log.debug("ToscaTemplate Loading YAMEL file {}", path);
+ InputStream input = new FileInputStream(new File(path));
+ Yaml yaml = new Yaml();
+ Object data = yaml.load(input);
+ this.tpl = (LinkedHashMap<String,Object>) data;
+ }
+ catch (FileNotFoundException e) {
+ log.error("ToscaTemplate - Exception loading yaml: {}", e.getMessage());
+ return;
+ }
+ catch(Exception e) {
+ log.error("ToscaTemplate - Error loading yaml, aborting");
+ return;
+ }
+
+ if(yamlDictTpl != null) {
+ //msg = (_('Both path and yaml_dict_tpl arguments were '
+ // 'provided. Using path and ignoring yaml_dict_tpl.'))
+ //log.info(msg)
+ log.debug("ToscaTemplate - Both path and yaml_dict_tpl arguments were provided. Using path and ignoring yaml_dict_tpl");
+ }
+ }
+ else {
+ // no input to process...
+ _abort();
+ }
+ }
+ else {
+ if(yamlDictTpl != null) {
+ tpl = yamlDictTpl;
+ }
+ else {
+ ExceptionCollector.appendException(
+ "ValueError: No path or yaml_dict_tpl was provided. There is nothing to parse");
+ log.debug("ToscaTemplate ValueError: No path or yaml_dict_tpl was provided. There is nothing to parse");
+
+ }
+ }
+
+ if(tpl != null) {
+ parsedParams = _parsedParams;
+ _validateField();
+ this.version = _tplVersion();
+ this.metaData = _tplMetaData();
+ this.relationshipTypes = _tplRelationshipTypes();
+ this.description = _tplDescription();
+ this.topologyTemplate = _topologyTemplate();
+ this.repositories = _tplRepositories();
+ if(topologyTemplate.getTpl() != null) {
+ this.inputs = _inputs();
+ this.relationshipTemplates = _relationshipTemplates();
+ this.nodeTemplates = _nodeTemplates();
+ this.outputs = _outputs();
+ this.policies = _policies();
+ _handleNestedToscaTemplatesWithTopology();
+ graph = new ToscaGraph(nodeTemplates);
+ }
+ }
+
+ if(csarTempDir != null) {
+ CSAR.deleteDir(new File(csarTempDir));
+ csarTempDir = null;
+ }
+
+ ExceptionCollector.stop();
+ verifyTemplate();
+ }
+
+ private void _abort() throws JToscaException {
+ // print out all exceptions caught
+ verifyTemplate();
+ throw new JToscaException("jtosca aborting");
+ }
+ private TopologyTemplate _topologyTemplate() {
+ return new TopologyTemplate(
+ _tplTopologyTemplate(),
+ _getAllCustomDefs(imports),
+ relationshipTypes,
+ parsedParams,
+ null);
+ }
+
+ private ArrayList<Input> _inputs() {
+ return topologyTemplate.getInputs();
+ }
+
+ private ArrayList<NodeTemplate> _nodeTemplates() {
+ return topologyTemplate.getNodeTemplates();
+ }
+
+ private ArrayList<RelationshipTemplate> _relationshipTemplates() {
+ return topologyTemplate.getRelationshipTemplates();
+ }
+
+ private ArrayList<Output> _outputs() {
+ return topologyTemplate.getOutputs();
+ }
+
+ private String _tplVersion() {
+ return (String)tpl.get(DEFINITION_VERSION);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Metadata _tplMetaData() {
+ Object mdo = tpl.get(METADATA);
+ if(mdo instanceof LinkedHashMap) {
+ return new Metadata((Map<String, Object>)mdo);
+ }
+ else {
+ return null;
+ }
+ }
+
+ private String _tplDescription() {
+ return (String)tpl.get(DESCRIPTION);
+ }
+
+ private ArrayList<Object> _tplImports() {
+ return (ArrayList<Object>)tpl.get(IMPORTS);
+ }
+
+ private ArrayList<Repository> _tplRepositories() {
+ LinkedHashMap<String,Object> repositories =
+ (LinkedHashMap<String,Object>)tpl.get(REPOSITORIES);
+ ArrayList<Repository> reposit = new ArrayList<>();
+ if(repositories != null) {
+ for(Map.Entry<String,Object> me: repositories.entrySet()) {
+ Repository reposits = new Repository(me.getKey(),me.getValue());
+ reposit.add(reposits);
+ }
+ }
+ return reposit;
+ }
+
+ private LinkedHashMap<String,Object> _tplRelationshipTypes() {
+ return (LinkedHashMap<String,Object>)_getCustomTypes(RELATIONSHIP_TYPES,null);
+ }
+
+ @SuppressWarnings("unchecked")
+ private LinkedHashMap<String,Object> _tplRelationshipTemplates() {
+ return (LinkedHashMap<String,Object>)_tplTopologyTemplate().get(RELATIONSHIP_TEMPLATES);
+ }
+
+ @SuppressWarnings("unchecked")
+ private LinkedHashMap<String,Object> _tplTopologyTemplate() {
+ return (LinkedHashMap<String,Object>)tpl.get(TOPOLOGY_TEMPLATE);
+ }
+
+ private ArrayList<Policy> _policies() {
+ return topologyTemplate.getPolicies();
+ }
+
+ private LinkedHashMap<String,Object> _getAllCustomDefs(ArrayList<Object> alImports) {
+
+ String types[] = {
+ IMPORTS, NODE_TYPES, CAPABILITY_TYPES, RELATIONSHIP_TYPES,
+ DATA_TYPES, INTERFACE_TYPES, POLICY_TYPES, GROUP_TYPES
+ };
+ LinkedHashMap<String,Object> customDefsFinal = new LinkedHashMap<String,Object>();
+ LinkedHashMap<String,Object> customDefs = _getCustomTypes(types,alImports);
+ if(customDefs != null) {
+ customDefsFinal.putAll(customDefs);
+ if(customDefs.get(IMPORTS) != null) {
+ @SuppressWarnings("unchecked")
+ LinkedHashMap<String,Object> importDefs = _getAllCustomDefs((ArrayList<Object>)customDefs.get(IMPORTS));
+ customDefsFinal.putAll(importDefs);
+ }
+ }
+
+ // As imports are not custom_types, remove from the dict
+ customDefsFinal.remove(IMPORTS);
+
+ return customDefsFinal;
+ }
+
+ @SuppressWarnings("unchecked")
+ private LinkedHashMap<String,Object> _getCustomTypes(Object typeDefinitions,ArrayList<Object> alImports) {
+
+ // Handle custom types defined in imported template files
+ // This method loads the custom type definitions referenced in "imports"
+ // section of the TOSCA YAML template.
+
+ LinkedHashMap<String,Object> customDefs = new LinkedHashMap<String,Object>();
+ ArrayList<String> typeDefs = new ArrayList<String>();
+ if(typeDefinitions instanceof String[]) {
+ for(String s: (String[])typeDefinitions) {
+ typeDefs.add(s);
+ }
+ }
+ else {
+ typeDefs.add((String)typeDefinitions);
+ }
+
+ if(alImports == null) {
+ alImports = _tplImports();
+ }
+
+ if(alImports != null) {
+ ImportsLoader customService = new ImportsLoader(alImports,path,typeDefs,tpl);
+ ArrayList<LinkedHashMap<String,Object>> nestedToscaTpls = customService.getNestedToscaTpls();
+ _updateNestedToscaTplsWithTopology(nestedToscaTpls);
+
+ customDefs = customService.getCustomDefs();
+ if(customDefs == null) {
+ return null;
+ }
+ }
+
+ //Handle custom types defined in current template file
+ for(String td: typeDefs) {
+ if(!td.equals(IMPORTS)) {
+ LinkedHashMap<String,Object> innerCustomTypes = (LinkedHashMap<String,Object> )tpl.get(td);
+ if(innerCustomTypes != null) {
+ customDefs.putAll(innerCustomTypes);
+ }
+ }
+ }
+ return customDefs;
+ }
+
+ private void _updateNestedToscaTplsWithTopology(ArrayList<LinkedHashMap<String,Object>> nestedToscaTpls) {
+ for(LinkedHashMap<String,Object> ntpl: nestedToscaTpls) {
+ // there is just one key:value pair in ntpl
+ for(Map.Entry<String,Object> me: ntpl.entrySet()) {
+ String fileName = me.getKey();
+ @SuppressWarnings("unchecked")
+ LinkedHashMap<String,Object> toscaTpl = (LinkedHashMap<String,Object>)me.getValue();
+ if(toscaTpl.get(TOPOLOGY_TEMPLATE) != null) {
+ if(nestedToscaTplsWithTopology.get(fileName) == null) {
+ nestedToscaTplsWithTopology.putAll(ntpl);
+ }
+ }
+ }
+ }
+ }
+
+ // **experimental** (multi level nesting) RECURSIVE - BEWARE OF INIFINITE LOOPS...
+ private void _handleNestedToscaTemplatesWithTopology2(TopologyTemplate tt) {
+ if(++nestingLoopCounter > 10) {
+ log.error("ToscaTemplate - _handleNestedToscaTemplatesWithTopology2 - Nested Topologies Loop: too many levels, aborting");
+ return;
+ }
+ for(Map.Entry<String,Object> me: nestedToscaTplsWithTopology.entrySet()) {
+ String fname = me.getKey();
+ LinkedHashMap<String,Object> toscaTpl =
+ (LinkedHashMap<String,Object>)me.getValue();
+ for(NodeTemplate nt: tt.getNodeTemplates()) {
+ if(_isSubMappedNode2(nt,toscaTpl)) {
+ parsedParams = _getParamsForNestedTemplate(nt);
+ LinkedHashMap<String,Object> topologyTpl =
+ (LinkedHashMap<String,Object>)toscaTpl.get(TOPOLOGY_TEMPLATE);
+ TopologyTemplate topologyWithSubMapping =
+ new TopologyTemplate(topologyTpl,
+ _getAllCustomDefs(null),
+ relationshipTypes,
+ parsedParams,
+ nt);
+ if(topologyWithSubMapping.getSubstitutionMappings() != null) {
+ // Record nested topology templates in top level template
+ //nestedToscaTemplatesWithTopology.add(topologyWithSubMapping);
+ // Set substitution mapping object for mapped node
+ nt.setSubMappingToscaTemplate2(
+ topologyWithSubMapping.getSubstitutionMappings());
+ _handleNestedToscaTemplatesWithTopology2(topologyWithSubMapping);
+ }
+ }
+ }
+ }
+ }
+
+ private void _handleNestedToscaTemplatesWithTopology() {
+ for(Map.Entry<String,Object> me: nestedToscaTplsWithTopology.entrySet()) {
+ String fname = me.getKey();
+ LinkedHashMap<String,Object> toscaTpl =
+ (LinkedHashMap<String,Object>)me.getValue();
+ for(NodeTemplate nt: nodeTemplates) {
+ if(_isSubMappedNode(nt,toscaTpl)) {
+ parsedParams = _getParamsForNestedTemplate(nt);
+ LinkedHashMap<String,Object> topologyTpl =
+ (LinkedHashMap<String,Object>)toscaTpl.get(TOPOLOGY_TEMPLATE);
+ TopologyTemplate topologyWithSubMapping =
+ new TopologyTemplate(topologyTpl,
+ _getAllCustomDefs(null),
+ relationshipTypes,
+ parsedParams,
+ nt);
+ if(topologyWithSubMapping.getSubstitutionMappings() != null) {
+ // Record nested topology templates in top level template
+ nestedToscaTemplatesWithTopology.add(topologyWithSubMapping);
+ // Set substitution mapping object for mapped node
+ nt.setSubMappingToscaTemplate(
+ topologyWithSubMapping.getSubstitutionMappings());
+ }
+ }
+ }
+ }
+ }
+
+ private void _validateField() {
+ String sVersion = _tplVersion();
+ if(sVersion == null) {
+ ExceptionCollector.appendException(String.format(
+ "MissingRequiredField: Template is missing required field \"%s\"",DEFINITION_VERSION));
+ }
+ else {
+ _validateVersion(sVersion);
+ this.version = sVersion;
+ }
+
+ for (String sKey : tpl.keySet()) {
+ boolean bFound = false;
+ for (String sSection: SECTIONS) {
+ if(sKey.equals(sSection)) {
+ bFound = true;
+ break;
+ }
+ }
+ // check ADDITIONAL_SECTIONS
+ if(!bFound) {
+ if(ADDITIONAL_SECTIONS.get(version) != null &&
+ ADDITIONAL_SECTIONS.get(version).contains(sKey)) {
+ bFound = true;
+ }
+ }
+ if(!bFound) {
+ ExceptionCollector.appendException(String.format(
+ "UnknownFieldError: Template contains unknown field \"%s\"",
+ sKey));
+ }
+ }
+ }
+
+ private void _validateVersion(String sVersion) {
+ boolean bFound = false;
+ for(String vtv: VALID_TEMPLATE_VERSIONS) {
+ if(sVersion.equals(vtv)) {
+ bFound = true;
+ break;
+ }
+ }
+ if(!bFound) {
+ ExceptionCollector.appendException(String.format(
+ "InvalidTemplateVersion: \"%s\" is invalid. Valid versions are %s",
+ sVersion,VALID_TEMPLATE_VERSIONS.toString()));
+ }
+ else if(!sVersion.equals("tosca_simple_yaml_1_0")) {
+ EntityType.updateDefinitions(sVersion);
+ }
+ }
+
+ private String _getPath(String _path) {
+ if (_path.toLowerCase().endsWith(".yaml") || _path.toLowerCase().endsWith(".yml")) {
+ return _path;
+ }
+ else if (_path.toLowerCase().endsWith(".zip") || _path.toLowerCase().endsWith(".csar")) {
+ // a CSAR archive
+ CSAR csar = new CSAR(_path, isFile);
+ if (csar.validate()) {
+ try {
+ csar.decompress();
+ }
+ catch (IOException e) {
+ log.error("ToscaTemplate - _getPath - IOException trying to decompress {}", _path);
+ return null;
+ }
+ isFile = true; // the file has been decompressed locally
+ csar.cleanup();
+ csarTempDir = csar.getTempDir();
+ return csar.getTempDir() + File.separator + csar.getMainTemplate();
+ }
+ }
+ else {
+ ExceptionCollector.appendException("ValueError: " + _path + " is not a valid file");
+ return null;
+ }
+ return null;
+ }
+
+ private void verifyTemplate() throws JToscaException {
+ ArrayList<String> exceptionStrings = ExceptionCollector.getExceptionReport();
+ if (exceptionStrings != null && exceptionStrings.size() > 0) {
+ int nexc = ExceptionCollector.errorsCaught();
+ log.error("ToscaTemplate - verifyTemplate - {} Parsing Exception{} occurred...", nexc, (nexc > 1 ? "s" : ""));
+ for (String s : exceptionStrings) {
+ if (s != null) {
+ log.debug("ToscaTemplate - verifyTemplate - {}", s);
+ }
+ }
+ if(bAbortOnParsingErrors) {
+ throw new JToscaException("Aborting because of parsing errors");
+ }
+ }
+ else {
+ if (inputPath != null) {
+ log.debug("ToscaTemplate - verifyTemplate - The input {} passed validation", inputPath);
+ }
+ }
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public TopologyTemplate getTopologyTemplate() {
+ return topologyTemplate;
+ }
+
+ public Metadata getMetaData() {
+ return metaData;
+ }
+
+ public ArrayList<Input> getInputs() {
+ return inputs;
+ }
+
+ public ArrayList<Output> getOutputs() {
+ return outputs;
+ }
+
+ public ArrayList<Policy> getPolicies() {
+ return policies;
+ }
+
+ public ArrayList<NodeTemplate> getNodeTemplates() {
+ return nodeTemplates;
+ }
+
+ private boolean _isSubMappedNode(NodeTemplate nt,LinkedHashMap<String,Object> toscaTpl) {
+ // Return True if the nodetemple is substituted
+ if(nt != null && nt.getSubMappingToscaTemplate() == null &&
+ getSubMappingNodeType(toscaTpl).equals(nt.getType()) &&
+ nt.getInterfaces().size() < 1) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean _isSubMappedNode2(NodeTemplate nt,LinkedHashMap<String,Object> toscaTpl) {
+ // Return True if the nodetemple is substituted
+ if(nt != null && nt.getSubMappingToscaTemplate2() == null &&
+ getSubMappingNodeType(toscaTpl).equals(nt.getType()) &&
+ nt.getInterfaces().size() < 1) {
+ return true;
+ }
+ return false;
+ }
+
+ private LinkedHashMap<String,Object> _getParamsForNestedTemplate(NodeTemplate nt) {
+ // Return total params for nested_template
+ LinkedHashMap<String,Object> pparams;
+ if(parsedParams != null) {
+ pparams = parsedParams;
+ }
+ else {
+ pparams = new LinkedHashMap<String,Object>();
+ }
+ if(nt != null) {
+ for(String pname: nt.getProperties().keySet()) {
+ pparams.put(pname,nt.getPropertyValue(pname));
+ }
+ }
+ return pparams;
+ }
+
+ private String getSubMappingNodeType(LinkedHashMap<String,Object> toscaTpl) {
+ // Return substitution mappings node type
+ if(toscaTpl != null) {
+ return TopologyTemplate.getSubMappingNodeType(
+ (LinkedHashMap<String,Object>)toscaTpl.get(TOPOLOGY_TEMPLATE));
+ }
+ return null;
+ }
+
+ private boolean _hasSubstitutionMapping() {
+ // Return True if the template has valid substitution mappings
+ return topologyTemplate != null &&
+ topologyTemplate.getSubstitutionMappings() != null;
+ }
+
+ public boolean hasNestedTemplates() {
+ // Return True if the tosca template has nested templates
+ return nestedToscaTemplatesWithTopology != null &&
+ nestedToscaTemplatesWithTopology.size() >= 1;
+
+ }
+
+ public ArrayList<TopologyTemplate> getNestedTemplates() {
+ return nestedToscaTemplatesWithTopology;
+ }
+
+ public void setAbortOnParsingErrors(boolean b) {
+ bAbortOnParsingErrors = b;
+ }
+
+ @Override
+ public String toString() {
+ return "ToscaTemplate{" +
+ "exttools=" + exttools +
+ ", VALID_TEMPLATE_VERSIONS=" + VALID_TEMPLATE_VERSIONS +
+ ", ADDITIONAL_SECTIONS=" + ADDITIONAL_SECTIONS +
+ ", bAbortOnParsingErrors=" + bAbortOnParsingErrors +
+ ", isFile=" + isFile +
+ ", path='" + path + '\'' +
+ ", inputPath='" + inputPath + '\'' +
+ ", parsedParams=" + parsedParams +
+ ", tpl=" + tpl +
+ ", version='" + version + '\'' +
+ ", imports=" + imports +
+ ", relationshipTypes=" + relationshipTypes +
+ ", metaData=" + metaData +
+ ", description='" + description + '\'' +
+ ", topologyTemplate=" + topologyTemplate +
+ ", repositories=" + repositories +
+ ", inputs=" + inputs +
+ ", relationshipTemplates=" + relationshipTemplates +
+ ", nodeTemplates=" + nodeTemplates +
+ ", outputs=" + outputs +
+ ", policies=" + policies +
+ ", nestedToscaTplsWithTopology=" + nestedToscaTplsWithTopology +
+ ", nestedToscaTemplatesWithTopology=" + nestedToscaTemplatesWithTopology +
+ ", graph=" + graph +
+ ", csarTempDir='" + csarTempDir + '\'' +
+ ", nestingLoopCounter=" + nestingLoopCounter +
+ '}';
+ }
+}
+
+/*python
+
+import logging
+import os
+
+from copy import deepcopy
+from toscaparser.common.exception import ExceptionCollector
+from toscaparser.common.exception import InvalidTemplateVersion
+from toscaparser.common.exception import MissingRequiredFieldError
+from toscaparser.common.exception import UnknownFieldError
+from toscaparser.common.exception import ValidationError
+from toscaparser.elements.entity_type import update_definitions
+from toscaparser.extensions.exttools import ExtTools
+import org.openecomp.sdc.toscaparser.imports
+from toscaparser.prereq.csar import CSAR
+from toscaparser.repositories import Repository
+from toscaparser.topology_template import TopologyTemplate
+from toscaparser.tpl_relationship_graph import ToscaGraph
+from toscaparser.utils.gettextutils import _
+import org.openecomp.sdc.toscaparser.utils.yamlparser
+
+
+# TOSCA template key names
+SECTIONS = (DEFINITION_VERSION, DEFAULT_NAMESPACE, TEMPLATE_NAME,
+ TOPOLOGY_TEMPLATE, TEMPLATE_AUTHOR, TEMPLATE_VERSION,
+ DESCRIPTION, IMPORTS, DSL_DEFINITIONS, NODE_TYPES,
+ RELATIONSHIP_TYPES, RELATIONSHIP_TEMPLATES,
+ CAPABILITY_TYPES, ARTIFACT_TYPES, DATA_TYPES, INTERFACE_TYPES,
+ POLICY_TYPES, GROUP_TYPES, REPOSITORIES) = \
+ ('tosca_definitions_version', 'tosca_default_namespace',
+ 'template_name', 'topology_template', 'template_author',
+ 'template_version', 'description', 'imports', 'dsl_definitions',
+ 'node_types', 'relationship_types', 'relationship_templates',
+ 'capability_types', 'artifact_types', 'data_types',
+ 'interface_types', 'policy_types', 'group_types', 'repositories')
+# Sections that are specific to individual template definitions
+SPECIAL_SECTIONS = (METADATA) = ('metadata')
+
+log = logging.getLogger("tosca.model")
+
+YAML_LOADER = toscaparser.utils.yamlparser.load_yaml
+
+
+class ToscaTemplate(object):
+ exttools = ExtTools()
+
+ VALID_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0']
+
+ VALID_TEMPLATE_VERSIONS.extend(exttools.get_versions())
+
+ ADDITIONAL_SECTIONS = {'tosca_simple_yaml_1_0': SPECIAL_SECTIONS}
+
+ ADDITIONAL_SECTIONS.update(exttools.get_sections())
+
+ '''Load the template data.'''
+ def __init__(self, path=None, parsed_params=None, a_file=True,
+ yaml_dict_tpl=None):
+
+ ExceptionCollector.start()
+ self.a_file = a_file
+ self.input_path = None
+ self.path = None
+ self.tpl = None
+ self.nested_tosca_tpls_with_topology = {}
+ self.nested_tosca_templates_with_topology = []
+ if path:
+ self.input_path = path
+ self.path = self._get_path(path)
+ if self.path:
+ self.tpl = YAML_LOADER(self.path, self.a_file)
+ if yaml_dict_tpl:
+ msg = (_('Both path and yaml_dict_tpl arguments were '
+ 'provided. Using path and ignoring yaml_dict_tpl.'))
+ log.info(msg)
+ print(msg)
+ else:
+ if yaml_dict_tpl:
+ self.tpl = yaml_dict_tpl
+ else:
+ ExceptionCollector.appendException(
+ ValueError(_('No path or yaml_dict_tpl was provided. '
+ 'There is nothing to parse.')))
+
+ if self.tpl:
+ self.parsed_params = parsed_params
+ self._validate_field()
+ self.version = self._tpl_version()
+ self.relationship_types = self._tpl_relationship_types()
+ self.description = self._tpl_description()
+ self.topology_template = self._topology_template()
+ self.repositories = self._tpl_repositories()
+ if self.topology_template.tpl:
+ self.inputs = self._inputs()
+ self.relationship_templates = self._relationship_templates()
+ self.nodetemplates = self._nodetemplates()
+ self.outputs = self._outputs()
+ self._handle_nested_tosca_templates_with_topology()
+ self.graph = ToscaGraph(self.nodetemplates)
+
+ ExceptionCollector.stop()
+ self.verify_template()
+
+ def _topology_template(self):
+ return TopologyTemplate(self._tpl_topology_template(),
+ self._get_all_custom_defs(),
+ self.relationship_types,
+ self.parsed_params,
+ None)
+
+ def _inputs(self):
+ return self.topology_template.inputs
+
+ def _nodetemplates(self):
+ return self.topology_template.nodetemplates
+
+ def _relationship_templates(self):
+ return self.topology_template.relationship_templates
+
+ def _outputs(self):
+ return self.topology_template.outputs
+
+ def _tpl_version(self):
+ return self.tpl.get(DEFINITION_VERSION)
+
+ def _tpl_description(self):
+ desc = self.tpl.get(DESCRIPTION)
+ if desc:
+ return desc.rstrip()
+
+ def _tpl_imports(self):
+ return self.tpl.get(IMPORTS)
+
+ def _tpl_repositories(self):
+ repositories = self.tpl.get(REPOSITORIES)
+ reposit = []
+ if repositories:
+ for name, val in repositories.items():
+ reposits = Repository(name, val)
+ reposit.append(reposits)
+ return reposit
+
+ def _tpl_relationship_types(self):
+ return self._get_custom_types(RELATIONSHIP_TYPES)
+
+ def _tpl_relationship_templates(self):
+ topology_template = self._tpl_topology_template()
+ return topology_template.get(RELATIONSHIP_TEMPLATES)
+
+ def _tpl_topology_template(self):
+ return self.tpl.get(TOPOLOGY_TEMPLATE)
+
+ def _get_all_custom_defs(self, imports=None):
+ types = [IMPORTS, NODE_TYPES, CAPABILITY_TYPES, RELATIONSHIP_TYPES,
+ DATA_TYPES, INTERFACE_TYPES, POLICY_TYPES, GROUP_TYPES]
+ custom_defs_final = {}
+ custom_defs = self._get_custom_types(types, imports)
+ if custom_defs:
+ custom_defs_final.update(custom_defs)
+ if custom_defs.get(IMPORTS):
+ import_defs = self._get_all_custom_defs(
+ custom_defs.get(IMPORTS))
+ custom_defs_final.update(import_defs)
+
+ # As imports are not custom_types, removing from the dict
+ custom_defs_final.pop(IMPORTS, None)
+ return custom_defs_final
+
+ def _get_custom_types(self, type_definitions, imports=None):
+ """Handle custom types defined in imported template files
+
+ This method loads the custom type definitions referenced in "imports"
+ section of the TOSCA YAML template.
+ """
+ custom_defs = {}
+ type_defs = []
+ if not isinstance(type_definitions, list):
+ type_defs.append(type_definitions)
+ else:
+ type_defs = type_definitions
+
+ if not imports:
+ imports = self._tpl_imports()
+
+ if imports:
+ custom_service = toscaparser.imports.\
+ ImportsLoader(imports, self.path,
+ type_defs, self.tpl)
+
+ nested_tosca_tpls = custom_service.get_nested_tosca_tpls()
+ self._update_nested_tosca_tpls_with_topology(nested_tosca_tpls)
+
+ custom_defs = custom_service.get_custom_defs()
+ if not custom_defs:
+ return
+
+ # Handle custom types defined in current template file
+ for type_def in type_defs:
+ if type_def != IMPORTS:
+ inner_custom_types = self.tpl.get(type_def) or {}
+ if inner_custom_types:
+ custom_defs.update(inner_custom_types)
+ return custom_defs
+
+ def _update_nested_tosca_tpls_with_topology(self, nested_tosca_tpls):
+ for tpl in nested_tosca_tpls:
+ filename, tosca_tpl = list(tpl.items())[0]
+ if (tosca_tpl.get(TOPOLOGY_TEMPLATE) and
+ filename not in list(
+ self.nested_tosca_tpls_with_topology.keys())):
+ self.nested_tosca_tpls_with_topology.update(tpl)
+
+ def _handle_nested_tosca_templates_with_topology(self):
+ for fname, tosca_tpl in self.nested_tosca_tpls_with_topology.items():
+ for nodetemplate in self.nodetemplates:
+ if self._is_sub_mapped_node(nodetemplate, tosca_tpl):
+ parsed_params = self._get_params_for_nested_template(
+ nodetemplate)
+ topology_tpl = tosca_tpl.get(TOPOLOGY_TEMPLATE)
+ topology_with_sub_mapping = TopologyTemplate(
+ topology_tpl,
+ self._get_all_custom_defs(),
+ self.relationship_types,
+ parsed_params,
+ nodetemplate)
+ if topology_with_sub_mapping.substitution_mappings:
+ # Record nested topo templates in top level template
+ self.nested_tosca_templates_with_topology.\
+ append(topology_with_sub_mapping)
+ # Set substitution mapping object for mapped node
+ nodetemplate.sub_mapping_tosca_template = \
+ topology_with_sub_mapping.substitution_mappings
+
+ def _validate_field(self):
+ version = self._tpl_version()
+ if not version:
+ ExceptionCollector.appendException(
+ MissingRequiredFieldError(what='Template',
+ required=DEFINITION_VERSION))
+ else:
+ self._validate_version(version)
+ self.version = version
+
+ for name in self.tpl:
+ if (name not in SECTIONS and
+ name not in self.ADDITIONAL_SECTIONS.get(version, ())):
+ ExceptionCollector.appendException(
+ UnknownFieldError(what='Template', field=name))
+
+ def _validate_version(self, version):
+ if version not in self.VALID_TEMPLATE_VERSIONS:
+ ExceptionCollector.appendException(
+ InvalidTemplateVersion(
+ what=version,
+ valid_versions=', '. join(self.VALID_TEMPLATE_VERSIONS)))
+ else:
+ if version != 'tosca_simple_yaml_1_0':
+ update_definitions(version)
+
+ def _get_path(self, path):
+ if path.lower().endswith(('.yaml','.yml')):
+ return path
+ elif path.lower().endswith(('.zip', '.csar')):
+ # a CSAR archive
+ csar = CSAR(path, self.a_file)
+ if csar.validate():
+ csar.decompress()
+ self.a_file = True # the file has been decompressed locally
+ return os.path.join(csar.temp_dir, csar.get_main_template())
+ else:
+ ExceptionCollector.appendException(
+ ValueError(_('"%(path)s" is not a valid file.')
+ % {'path': path}))
+
+ def verify_template(self):
+ if ExceptionCollector.exceptionsCaught():
+ if self.input_path:
+ raise ValidationError(
+ message=(_('\nThe input "%(path)s" failed validation with '
+ 'the following error(s): \n\n\t')
+ % {'path': self.input_path}) +
+ '\n\t'.join(ExceptionCollector.getExceptionsReport()))
+ else:
+ raise ValidationError(
+ message=_('\nThe pre-parsed input failed validation with '
+ 'the following error(s): \n\n\t') +
+ '\n\t'.join(ExceptionCollector.getExceptionsReport()))
+ else:
+ if self.input_path:
+ msg = (_('The input "%(path)s" successfully passed '
+ 'validation.') % {'path': self.input_path})
+ else:
+ msg = _('The pre-parsed input successfully passed validation.')
+
+ log.info(msg)
+
+ def _is_sub_mapped_node(self, nodetemplate, tosca_tpl):
+ """Return True if the nodetemple is substituted."""
+ if (nodetemplate and not nodetemplate.sub_mapping_tosca_template and
+ self.get_sub_mapping_node_type(tosca_tpl) == nodetemplate.type
+ and len(nodetemplate.interfaces) < 1):
+ return True
+ else:
+ return False
+
+ def _get_params_for_nested_template(self, nodetemplate):
+ """Return total params for nested_template."""
+ parsed_params = deepcopy(self.parsed_params) \
+ if self.parsed_params else {}
+ if nodetemplate:
+ for pname in nodetemplate.get_properties():
+ parsed_params.update({pname:
+ nodetemplate.get_property_value(pname)})
+ return parsed_params
+
+ def get_sub_mapping_node_type(self, tosca_tpl):
+ """Return substitution mappings node type."""
+ if tosca_tpl:
+ return TopologyTemplate.get_sub_mapping_node_type(
+ tosca_tpl.get(TOPOLOGY_TEMPLATE))
+
+ def _has_substitution_mappings(self):
+ """Return True if the template has valid substitution mappings."""
+ return self.topology_template is not None and \
+ self.topology_template.substitution_mappings is not None
+
+ def has_nested_templates(self):
+ """Return True if the tosca template has nested templates."""
+ return self.nested_tosca_templates_with_topology is not None and \
+ len(self.nested_tosca_templates_with_topology) >= 1
+*/ \ No newline at end of file