1 # Licensed under the Apache License, Version 2.0 (the "License"); you may
2 # not use this file except in compliance with the License. You may obtain
3 # a copy of the License at
5 # http://www.apache.org/licenses/LICENSE-2.0
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 # License for the specific language governing permissions and limitations
15 from toscaparser.common.exception import ExceptionCollector
16 from toscaparser.common.exception import InvalidNodeTypeError
17 from toscaparser.common.exception import MissingRequiredFieldError
18 from toscaparser.common.exception import MissingRequiredInputError
19 from toscaparser.common.exception import MissingRequiredParameterError
20 from toscaparser.common.exception import UnknownFieldError
21 from toscaparser.elements.nodetype import NodeType
24 log = logging.getLogger('tosca')
27 class SubstitutionMappings(object):
28 '''SubstitutionMappings class declaration
30 Substitution_mappings exports the topology template as an
31 implementation of a Node type.
34 SECTIONS = (NODE_TYPE, REQUIREMENTS, CAPABILITIES) = \
35 ('node_type', 'requirements', 'capabilities')
37 def __init__(self, sub_mapping_def, nodetemplates, inputs, outputs,
38 sub_mapped_node_template, custom_defs):
39 self.nodetemplates = nodetemplates
40 self.sub_mapping_def = sub_mapping_def
41 self.inputs = inputs or []
42 self.outputs = outputs or []
43 self.sub_mapped_node_template = sub_mapped_node_template
44 self.custom_defs = custom_defs or {}
47 self._capabilities = None
48 self._requirements = None
51 def get_node_type(cls, sub_mapping_def):
52 if isinstance(sub_mapping_def, dict):
53 return sub_mapping_def.get(cls.NODE_TYPE)
57 return self.sub_mapping_def.get(self.NODE_TYPE)
60 def capabilities(self):
61 return self.sub_mapping_def.get(self.CAPABILITIES)
64 def requirements(self):
65 return self.sub_mapping_def.get(self.REQUIREMENTS)
68 def node_definition(self):
69 return NodeType(self.node_type, self.custom_defs)
76 # SubstitutionMapping class syntax validation
77 self._validate_inputs()
78 self._validate_capabilities()
79 self._validate_requirements()
80 self._validate_outputs()
82 def _validate_keys(self):
83 """validate the keys of substitution mappings."""
84 for key in self.sub_mapping_def.keys():
85 if key not in self.SECTIONS:
86 ExceptionCollector.appendException(
87 UnknownFieldError(what='SubstitutionMappings',
90 def _validate_type(self):
91 """validate the node_type of substitution mappings."""
92 node_type = self.sub_mapping_def.get(self.NODE_TYPE)
94 ExceptionCollector.appendException(
95 MissingRequiredFieldError(
96 what=_('SubstitutionMappings used in topology_template'),
97 required=self.NODE_TYPE))
99 node_type_def = self.custom_defs.get(node_type)
100 if not node_type_def:
101 ExceptionCollector.appendException(
102 InvalidNodeTypeError(what=node_type_def))
104 def _validate_inputs(self):
105 """validate the inputs of substitution mappings.
107 The inputs in service template which provides substutition mappings
108 must be in properties of node template which is mapped or provide
109 defualt value. Currently the input.name is not restrict to be the
110 same as property name in specification, but they should be equal
111 for current implementation.
114 # Must provide parameters for required properties of node_type
115 # This checking is internal(inside SubstitutionMappings)
116 for propery in self.node_definition.get_properties_def_objects():
117 # Check property which is 'required' and has no 'default' value
118 if propery.required and propery.default is None and \
119 propery.name not in [input.name for input in self.inputs]:
120 ExceptionCollector.appendException(
121 MissingRequiredInputError(
122 what='SubstitutionMappings with node_type:'
124 input_name=propery.name))
126 # Get property names from substituted node tempalte
127 property_names = list(self.sub_mapped_node_template
128 .get_properties().keys()
129 if self.sub_mapped_node_template else [])
130 # Sub_mapped_node_template is None(deploy standaolone), will check
131 # according to node_type
132 if 0 == len(property_names):
133 property_names = list(self.node_definition
134 .get_properties_def().keys())
135 # Provide default value for parameter which is not property of
136 # node with the type node_type, this may not be mandatory for
137 # current implematation, but the specification express it mandatory.
138 # This checking is external(outside SubstitutionMappings)
139 for input in self.inputs:
140 if input.name not in property_names and input.default is None:
141 ExceptionCollector.appendException(
142 MissingRequiredParameterError(
143 what='SubstitutionMappings with node_type:'
145 input_name=input.name))
147 def _validate_capabilities(self):
148 """validate the capabilities of substitution mappings."""
150 # The capabilites must be in node template wchich be mapped.
151 tpls_capabilities = self.sub_mapping_def.get(self.CAPABILITIES)
152 node_capabiliteys = self.sub_mapped_node_template.get_capabilities() \
153 if self.sub_mapped_node_template else None
154 for cap in node_capabiliteys.keys() if node_capabiliteys else []:
155 if (tpls_capabilities and
156 cap not in list(tpls_capabilities.keys())):
158 # ExceptionCollector.appendException(
159 # UnknownFieldError(what='SubstitutionMappings',
162 def _validate_requirements(self):
163 """validate the requirements of substitution mappings."""
165 # The requirements must be in node template wchich be mapped.
166 tpls_requirements = self.sub_mapping_def.get(self.REQUIREMENTS)
167 node_requirements = self.sub_mapped_node_template.requirements \
168 if self.sub_mapped_node_template else None
169 for req in node_requirements if node_requirements else []:
170 if (tpls_requirements and
171 req not in list(tpls_requirements.keys())):
173 # ExceptionCollector.appendException(
174 # UnknownFieldError(what='SubstitutionMappings',
177 def _validate_outputs(self):
178 """validate the outputs of substitution mappings."""
180 # The outputs in service template which defines substutition mappings
181 # must be in atrributes of node template wchich be mapped.
182 # outputs_names = self.sub_mapped_node_template.get_properties().
183 # keys() if self.sub_mapped_node_template else None
184 # for name in outputs_names:
185 # if name not in [output.name for input in self.outputs]:
186 # ExceptionCollector.appendException(
187 # UnknownFieldError(what='SubstitutionMappings',