Merge "Add keys validation testcase in substitution_mapping class"
[parser.git] / tosca2heat / tosca-parser / toscaparser / substitution_mappings.py
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
4 #
5 #         http://www.apache.org/licenses/LICENSE-2.0
6 #
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
11 #    under the License.
12
13 import logging
14
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 _
23
24 log = logging.getLogger('tosca')
25
26
27 class SubstitutionMappings(object):
28     '''SubstitutionMappings class declaration
29
30     Substitution_mappings exports the topology template as an
31     implementation of a Node type.
32     '''
33
34     SECTIONS = (NODE_TYPE, REQUIREMENTS, CAPABILITIES) = \
35                ('node_type', 'requirements', 'capabilities')
36
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 {}
45         self._validate()
46
47         self._capabilities = None
48         self._requirements = None
49
50     @property
51     def type(self):
52         if self.sub_mapping_def:
53             return self.sub_mapping_def.get(self.NODE_TYPE)
54
55     @classmethod
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)
59
60     @property
61     def node_type(self):
62         return self.sub_mapping_def.get(self.NODE_TYPE)
63
64     @property
65     def capabilities(self):
66         return self.sub_mapping_def.get(self.CAPABILITIES)
67
68     @property
69     def requirements(self):
70         return self.sub_mapping_def.get(self.REQUIREMENTS)
71
72     @property
73     def node_definition(self):
74         return NodeType(self.node_type, self.custom_defs)
75
76     def _validate(self):
77         # basic valiation
78         self._validate_keys()
79         self._validate_type()
80
81         # SubstitutionMapping class syntax validation
82         self._validate_inputs()
83         self._validate_capabilities()
84         self._validate_requirements()
85         self._validate_outputs()
86
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'),
93                                       field=key))
94
95     def _validate_type(self):
96         """validate the node_type of substitution mappings."""
97         node_type = self.sub_mapping_def.get(self.NODE_TYPE)
98         if not node_type:
99             ExceptionCollector.appendException(
100                 MissingRequiredFieldError(
101                     what=_('SubstitutionMappings used in topology_template'),
102                     required=self.NODE_TYPE))
103
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))
108
109     def _validate_inputs(self):
110         """validate the inputs of substitution mappings.
111
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.
117         """
118
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:')
128                         + self.node_type,
129                         input_name=propery.name))
130
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:')
149                         + self.node_type,
150                         input_name=input.name))
151
152     def _validate_capabilities(self):
153         """validate the capabilities of substitution mappings."""
154
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())):
162                 pass
163                 # ExceptionCollector.appendException(
164                 #    UnknownFieldError(what='SubstitutionMappings',
165                 #                      field=cap))
166
167     def _validate_requirements(self):
168         """validate the requirements of substitution mappings."""
169
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())):
177                 pass
178                 # ExceptionCollector.appendException(
179                 #    UnknownFieldError(what='SubstitutionMappings',
180                 #                      field=req))
181
182     def _validate_outputs(self):
183         """validate the outputs of substitution mappings."""
184         pass
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',
193         #                              field=name))