Disable syslog in heat-translator for functest integration
[parser.git] / tosca2heat / tosca-parser / toscaparser / tosca_template.py
index 28fa57b..c961941 100644 (file)
 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 MissingRequiredParameterError
 from toscaparser.common.exception import UnknownFieldError
 from toscaparser.common.exception import ValidationError
 from toscaparser.elements.entity_type import update_definitions
@@ -35,14 +37,14 @@ 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,
+            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',
-            'policy_types', 'group_types', 'repositories')
+            'interface_types', 'policy_types', 'group_types', 'repositories')
 # Sections that are specific to individual template definitions
 SPECIAL_SECTIONS = (METADATA) = ('metadata')
 
@@ -54,17 +56,20 @@ YAML_LOADER = toscaparser.utils.yamlparser.load_yaml
 class ToscaTemplate(object):
     exttools = ExtTools()
 
-    VALID_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0']
+    VALID_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0',
+                               'tosca_simple_yaml_1_1']
 
     VALID_TEMPLATE_VERSIONS.extend(exttools.get_versions())
 
-    ADDITIONAL_SECTIONS = {'tosca_simple_yaml_1_0': SPECIAL_SECTIONS}
+    ADDITIONAL_SECTIONS = {'tosca_simple_yaml_1_0': SPECIAL_SECTIONS,
+                           'tosca_simple_yaml_1_1': 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, sub_mapped_node_template=None):
+                 yaml_dict_tpl=None, sub_mapped_node_template=None,
+                 no_required_paras_valid=False):
         if sub_mapped_node_template is None:
             ExceptionCollector.start()
         self.a_file = a_file
@@ -74,6 +79,7 @@ class ToscaTemplate(object):
         self.sub_mapped_node_template = sub_mapped_node_template
         self.nested_tosca_tpls_with_topology = {}
         self.nested_tosca_templates_with_topology = []
+        self.no_required_paras_valid = no_required_paras_valid
         if path:
             self.input_path = path
             self.path = self._get_path(path)
@@ -105,6 +111,7 @@ class ToscaTemplate(object):
                 self.relationship_templates = self._relationship_templates()
                 self.nodetemplates = self._nodetemplates()
                 self.outputs = self._outputs()
+                self.policies = self._policies()
                 self._handle_nested_tosca_templates_with_topology()
                 self.graph = ToscaGraph(self.nodetemplates)
 
@@ -161,9 +168,12 @@ class ToscaTemplate(object):
     def _tpl_topology_template(self):
         return self.tpl.get(TOPOLOGY_TEMPLATE)
 
+    def _policies(self):
+        return self.topology_template.policies
+
     def _get_all_custom_defs(self, imports=None):
         types = [IMPORTS, NODE_TYPES, CAPABILITY_TYPES, RELATIONSHIP_TYPES,
-                 DATA_TYPES, POLICY_TYPES, GROUP_TYPES]
+                 DATA_TYPES, INTERFACE_TYPES, POLICY_TYPES, GROUP_TYPES]
         custom_defs_final = {}
         custom_defs = self._get_custom_types(types, imports)
         if custom_defs:
@@ -195,9 +205,9 @@ class ToscaTemplate(object):
             imports = self._tpl_imports()
 
         if imports:
-            custom_service = \
-                toscaparser.imports.ImportsLoader(imports, self.path,
-                                                  type_defs, self.tpl)
+            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)
@@ -226,17 +236,37 @@ class ToscaTemplate(object):
         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):
-                    nested_template = ToscaTemplate(
-                        path=fname, parsed_params=self.parsed_params,
-                        yaml_dict_tpl=tosca_tpl,
-                        sub_mapped_node_template=nodetemplate)
-                    if nested_template.has_substitution_mappings():
-                        fnames = \
-                            [tpl.path for tpl in
-                             self.nested_tosca_templates_with_topology]
-                        if fname not in fnames:
-                            self.nested_tosca_templates_with_topology.\
-                                append(nested_template)
+                    parsed_params = self._get_params_for_nested_template(
+                        nodetemplate)
+
+                    cache_exeptions = deepcopy(ExceptionCollector.exceptions)
+                    cache_exeptions_state = \
+                        deepcopy(ExceptionCollector.collecting)
+                    nested_template = None
+                    try:
+                        nrpv = self.no_required_paras_valid
+                        nested_template = ToscaTemplate(
+                            path=fname, parsed_params=parsed_params,
+                            sub_mapped_node_template=nodetemplate,
+                            no_required_paras_valid=nrpv)
+                    except ValidationError as e:
+                        msg = _('  ===== nested service template ===== ')
+                        log.error(msg)
+                        log.error(e.message)
+                        raise e
+
+                    ExceptionCollector.exceptions = deepcopy(cache_exeptions)
+                    ExceptionCollector.collecting = \
+                        deepcopy(cache_exeptions_state)
+
+                    if nested_template and \
+                            nested_template._has_substitution_mappings():
+                        # Record the nested templates in top level template
+                        self.nested_tosca_templates_with_topology.\
+                            append(nested_template)
+                        # Set the substitution toscatemplate for mapped node
+                        nodetemplate.sub_mapping_tosca_template = \
+                            nested_template
 
     def _validate_field(self):
         version = self._tpl_version()
@@ -261,11 +291,12 @@ class ToscaTemplate(object):
                     what=version,
                     valid_versions=', '. join(self.VALID_TEMPLATE_VERSIONS)))
         else:
-            if version != 'tosca_simple_yaml_1_0':
+            if (version != 'tosca_simple_yaml_1_0' and
+                    version != 'tosca_simple_yaml_1_1'):
                 update_definitions(version)
 
     def _get_path(self, path):
-        if path.lower().endswith('.yaml'):
+        if path.lower().endswith('.yaml') or path.lower().endswith('.yml'):
             return path
         elif path.lower().endswith(('.zip', '.csar')):
             # a CSAR archive
@@ -281,6 +312,10 @@ class ToscaTemplate(object):
 
     def verify_template(self):
         if ExceptionCollector.exceptionsCaught():
+            if self.no_required_paras_valid:
+                ExceptionCollector.removeException(
+                    MissingRequiredParameterError)
+
             if self.input_path:
                 raise ValidationError(
                     message=(_('\nThe input "%(path)s" failed validation with '
@@ -310,13 +345,23 @@ class ToscaTemplate(object):
         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):
+    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