vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / extensions / aria_extension_tosca / simple_v1_0 / modeling / parameters.py
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements.  See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License.  You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 from aria.utils.collections import (merge, deepcopy_with_locators, OrderedDict)
17 from aria.utils.formatting import pluralize
18 from aria.parser.presentation import Value
19 from aria.parser.validation import Issue
20
21 from .data_types import (coerce_value, get_primitive_data_type)
22 from ..presentation.types import get_type_by_name
23
24
25 #
26 # ArtifactType, DataType, CapabilityType, RelationshipType, NodeType, GroupType, PolicyType
27 #
28
29 def get_inherited_parameter_definitions(context, presentation, field_name, for_presentation=None):
30     """
31     Returns our parameter definitions added on top of those of our parent, if we have one
32     (recursively).
33
34     Allows overriding all aspects of parent properties except data type.
35     """
36
37     if for_presentation is None:
38         for_presentation = presentation
39
40     # Get definitions from parent
41     # If we inherit from a primitive, it does not have a parent:
42     parent = presentation._get_parent(context) if hasattr(presentation, '_get_parent') else None
43     definitions = get_inherited_parameter_definitions(context, parent, field_name,
44                                                       for_presentation) \
45                                                       if parent is not None else OrderedDict()
46
47     # Add/merge our definitions
48     # If we inherit from a primitive, it does not have our field
49     our_definitions = getattr(presentation, field_name, None)
50     if our_definitions:
51         our_definitions_clone = OrderedDict()
52         for name, our_definition in our_definitions.iteritems():
53             our_definitions_clone[name] = our_definition._clone(for_presentation)
54         our_definitions = our_definitions_clone
55         merge_parameter_definitions(context, presentation, definitions, our_definitions, field_name)
56
57     for definition in definitions.itervalues():
58         definition._reset_method_cache()
59
60     return definitions
61
62
63 #
64 # NodeTemplate, RelationshipTemplate, GroupTemplate, PolicyTemplate
65 #
66
67 def get_assigned_and_defined_parameter_values(context, presentation, field_name):
68     """
69     Returns the assigned parameter values while making sure they are defined in our type.
70
71     The parameter definition's default value, if available, will be used if we did not assign it.
72
73     Makes sure that required parameters indeed end up with a value.
74     """
75
76     values = OrderedDict()
77
78     the_type = presentation._get_type(context)
79     field_name_plural = pluralize(field_name)
80     assignments = getattr(presentation, field_name_plural)
81     get_fn_name = '_get_{0}'.format(field_name_plural)
82     definitions = getattr(the_type, get_fn_name)(context) if the_type is not None else None
83
84     # Fill in our assignments, but make sure they are defined
85     if assignments:
86         for name, value in assignments.iteritems():
87             if (definitions is not None) and (name in definitions):
88                 definition = definitions[name]
89                 values[name] = coerce_parameter_value(context, value, definition, value.value)
90             else:
91                 context.validation.report('assignment to undefined {0} "{1}" in "{2}"'
92                                           .format(field_name, name, presentation._fullname),
93                                           locator=value._locator, level=Issue.BETWEEN_TYPES)
94
95     # Fill in defaults from the definitions
96     if definitions:
97         for name, definition in definitions.iteritems():
98             # Note: attributes will always have a default value, even if it's None
99             if (name not in values) and \
100                 (('default' in definition._raw) or (field_name == 'attribute')):
101                 values[name] = coerce_parameter_value(context, presentation, definition,
102                                                       definition.default)
103
104     validate_required_values(context, presentation, values, definitions)
105
106     # Fill in nulls for missing values that are *not* required
107     if definitions:
108         for name, definition in definitions.iteritems():
109             if (name not in values) and not getattr(definition, 'required', False):
110                 values[name] = coerce_parameter_value(context, presentation, definition, None)
111
112     return values
113
114
115 #
116 # TopologyTemplate
117 #
118
119 def get_parameter_values(context, presentation, field_name):
120     values = OrderedDict()
121
122     parameters = getattr(presentation, field_name)
123
124     # Fill in defaults and values
125     if parameters:
126         for name, parameter in parameters.iteritems():
127             if values.get(name) is None:
128                 if hasattr(parameter, 'value') and (parameter.value is not None):
129                     # For parameters only:
130                     values[name] = coerce_parameter_value(context, presentation, parameter,
131                                                           parameter.value)
132                 else:
133                     default = parameter.default if hasattr(parameter, 'default') else None
134                     values[name] = coerce_parameter_value(context, presentation, parameter, default)
135
136     return values
137
138
139 #
140 # Utils
141 #
142
143 def validate_required_values(context, presentation, values, definitions):
144     """
145     Check if required properties have not been assigned.
146     """
147
148     if not definitions:
149         return
150     for name, definition in definitions.iteritems():
151         if getattr(definition, 'required', False) and \
152             ((values is None) or (values.get(name) is None)):
153             context.validation.report('required property "%s" is not assigned a value in "%s"'
154                                       % (name, presentation._fullname),
155                                       locator=presentation._get_child_locator('properties'),
156                                       level=Issue.BETWEEN_TYPES)
157
158
159 def merge_raw_parameter_definition(context, presentation, raw_property_definition,
160                                    our_property_definition, field_name, property_name):
161     # Check if we changed the parameter type
162     type1_name = raw_property_definition.get('type')
163     type1 = get_type_by_name(context, type1_name, 'data_types')
164     if type1 is None:
165         type1 = get_primitive_data_type(type1_name)
166     our_property_definition._reset_method_cache()
167     type2 = our_property_definition._get_type(context)
168
169     if type1 != type2:
170         if not hasattr(type1, '_is_descendant') or not type1._is_descendant(context, type2):
171             context.validation.report(
172                 'property definition type "{0}" is not a descendant of overridden '
173                 'property definition type "{1}"' \
174                 .format(type1_name, type2._name),
175                 locator=presentation._get_child_locator(field_name, property_name),
176                 level=Issue.BETWEEN_TYPES)
177
178     merge(raw_property_definition, our_property_definition._raw)
179
180
181 def merge_raw_parameter_definitions(context, presentation, raw_property_definitions,
182                                     our_property_definitions, field_name):
183     if not our_property_definitions:
184         return
185     for property_name, our_property_definition in our_property_definitions.iteritems():
186         if property_name in raw_property_definitions:
187             raw_property_definition = raw_property_definitions[property_name]
188             merge_raw_parameter_definition(context, presentation, raw_property_definition,
189                                            our_property_definition, field_name, property_name)
190         else:
191             raw_property_definitions[property_name] = \
192                 deepcopy_with_locators(our_property_definition._raw)
193
194
195 def merge_parameter_definitions(context, presentation, property_definitions,
196                                 our_property_definitions, field_name):
197     if not our_property_definitions:
198         return
199     for property_name, our_property_definition in our_property_definitions.iteritems():
200         if property_name in property_definitions:
201             property_definition = property_definitions[property_name]
202             merge_raw_parameter_definition(context, presentation, property_definition._raw,
203                                            our_property_definition, field_name, property_name)
204         else:
205             property_definitions[property_name] = our_property_definition
206
207
208 # Works on properties, inputs, and parameters
209 def coerce_parameter_value(context, presentation, definition, value, aspect=None):
210     the_type = definition._get_type(context) if definition is not None else None
211     entry_schema = definition.entry_schema if definition is not None else None
212     constraints = definition._get_constraints(context) \
213         if ((definition is not None) and hasattr(definition, '_get_constraints')) else None
214     value = coerce_value(context, presentation, the_type, entry_schema, constraints, value, aspect)
215     if (the_type is not None) and hasattr(the_type, '_name'):
216         type_name = the_type._name
217     else:
218         type_name = getattr(definition, 'type', None)
219     description = getattr(definition, 'description', None)
220     description = description.value if description is not None else None
221     required = getattr(definition, 'required', None)
222     return Value(type_name, value, description, required)
223
224
225 def convert_parameter_definitions_to_values(context, definitions):
226     values = OrderedDict()
227     for name, definition in definitions.iteritems():
228         default = definition.default
229         values[name] = coerce_parameter_value(context, definition, definition, default)
230     return values