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
22 from toscaparser.utils.gettextutils import _
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
52 if self.sub_mapping_def:
53 return self.sub_mapping_def.get(self.NODE_TYPE)
56 def get_node_type(cls, sub_mapping_def):
57 if isinstance(sub_mapping_def, dict):
58 return sub_mapping_def.get(cls.NODE_TYPE)
62 return self.sub_mapping_def.get(self.NODE_TYPE)
65 def capabilities(self):
66 return self.sub_mapping_def.get(self.CAPABILITIES)
69 def requirements(self):
70 return self.sub_mapping_def.get(self.REQUIREMENTS)
73 def node_definition(self):
74 return NodeType(self.node_type, self.custom_defs)
81 # SubstitutionMapping class syntax validation
82 self._validate_inputs()
83 self._validate_capabilities()
84 self._validate_requirements()
85 self._validate_outputs()
87 def _validate_keys(self):
88 """validate the keys of substitution mappings."""
89 for key in self.sub_mapping_def.keys():
90 if key not in self.SECTIONS:
91 ExceptionCollector.appendException(
92 UnknownFieldError(what=_('SubstitutionMappings'),
95 def _validate_type(self):
96 """validate the node_type of substitution mappings."""
97 node_type = self.sub_mapping_def.get(self.NODE_TYPE)
99 ExceptionCollector.appendException(
100 MissingRequiredFieldError(
101 what=_('SubstitutionMappings used in topology_template'),
102 required=self.NODE_TYPE))
104 node_type_def = self.custom_defs.get(node_type)
105 if not node_type_def:
106 ExceptionCollector.appendException(
107 InvalidNodeTypeError(what=node_type_def))
109 def _validate_inputs(self):
110 """validate the inputs of substitution mappings.
112 The inputs in service template which provides substutition mappings
113 must be in properties of node template which is mapped or provide
114 defualt value. Currently the input.name is not restrict to be the
115 same as property name in specification, but they should be equal
116 for current implementation.
119 # Must provide parameters for required properties of node_type
120 # This checking is internal(inside SubstitutionMappings)
121 for propery in self.node_definition.get_properties_def_objects():
122 # Check property which is 'required' and has no 'default' value
123 if propery.required and propery.default is None and \
124 propery.name not in [input.name for input in self.inputs]:
125 ExceptionCollector.appendException(
126 MissingRequiredInputError(
127 what=_('SubstitutionMappings with node_type:')
129 input_name=propery.name))
131 # Get property names from substituted node tempalte
132 property_names = list(self.sub_mapped_node_template
133 .get_properties().keys()
134 if self.sub_mapped_node_template else [])
135 # Sub_mapped_node_template is None(deploy standaolone), will check
136 # according to node_type
137 if 0 == len(property_names):
138 property_names = list(self.node_definition
139 .get_properties_def().keys())
140 # Provide default value for parameter which is not property of
141 # node with the type node_type, this may not be mandatory for
142 # current implematation, but the specification express it mandatory.
143 # This checking is external(outside SubstitutionMappings)
144 for input in self.inputs:
145 if input.name not in property_names and input.default is None:
146 ExceptionCollector.appendException(
147 MissingRequiredParameterError(
148 what=_('SubstitutionMappings with node_type:')
150 input_name=input.name))
152 def _validate_capabilities(self):
153 """validate the capabilities of substitution mappings."""
155 # The capabilites must be in node template wchich be mapped.
156 tpls_capabilities = self.sub_mapping_def.get(self.CAPABILITIES)
157 node_capabiliteys = self.sub_mapped_node_template.get_capabilities() \
158 if self.sub_mapped_node_template else None
159 for cap in node_capabiliteys.keys() if node_capabiliteys else []:
160 if (tpls_capabilities and
161 cap not in list(tpls_capabilities.keys())):
163 # ExceptionCollector.appendException(
164 # UnknownFieldError(what='SubstitutionMappings',
167 def _validate_requirements(self):
168 """validate the requirements of substitution mappings."""
170 # The requirements must be in node template wchich be mapped.
171 tpls_requirements = self.sub_mapping_def.get(self.REQUIREMENTS)
172 node_requirements = self.sub_mapped_node_template.requirements \
173 if self.sub_mapped_node_template else None
174 for req in node_requirements if node_requirements else []:
175 if (tpls_requirements and
176 req not in list(tpls_requirements.keys())):
178 # ExceptionCollector.appendException(
179 # UnknownFieldError(what='SubstitutionMappings',
182 def _validate_outputs(self):
183 """validate the outputs of substitution mappings."""
185 # The outputs in service template which defines substutition mappings
186 # must be in atrributes of node template wchich be mapped.
187 # outputs_names = self.sub_mapped_node_template.get_properties().
188 # keys() if self.sub_mapped_node_template else None
189 # for name in outputs_names:
190 # if name not in [output.name for input in self.outputs]:
191 # ExceptionCollector.appendException(
192 # UnknownFieldError(what='SubstitutionMappings',