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
8 # http://www.apache.org/licenses/LICENSE-2.0
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.
16 from aria.utils.collections import FrozenDict
17 from aria.utils.caching import cachedmethod
18 from aria.parser import implements_specification
19 from aria.parser.presentation import (AsIsPresentation, has_fields, allow_unknown_fields,
20 short_form_field, primitive_field, object_field,
21 object_dict_field, object_dict_unknown_fields,
22 field_validator, type_validator)
24 from .filters import NodeFilter
25 from .misc import Description, OperationImplementation
26 from .modeling.parameters import get_assigned_and_defined_parameter_values
27 from .presentation.extensible import ExtensiblePresentation
28 from .presentation.field_validators import (node_template_or_type_validator,
29 relationship_template_or_type_validator,
30 capability_definition_or_type_validator,
31 node_filter_validator)
32 from .presentation.types import (convert_name_to_full_type_name, get_type_by_name)
36 @implements_specification('3.5.9', 'tosca-simple-1.0')
37 class PropertyAssignment(AsIsPresentation):
39 This section defines the grammar for assigning values to named properties within TOSCA Node and
40 Relationship templates that are defined in their corresponding named types.
42 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
43 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
44 #DEFN_ELEMENT_PROPERTY_VALUE_ASSIGNMENT>`__
48 @short_form_field('implementation')
50 @implements_specification('3.5.13-2', 'tosca-simple-1.0')
51 class OperationAssignment(ExtensiblePresentation):
53 An operation definition defines a named function or procedure that can be bound to an
54 implementation artifact (e.g., a script).
56 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
57 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
58 #DEFN_ELEMENT_OPERATION_DEF>`__
61 @object_field(Description)
62 def description(self):
64 The optional description string for the associated named operation.
66 :type: :class:`Description`
69 @object_field(OperationImplementation)
70 def implementation(self):
72 The optional implementation artifact name (e.g., a script file name within a TOSCA CSAR
75 :type: :class:`OperationImplementation`
78 @object_dict_field(PropertyAssignment)
81 The optional list of input property assignments (i.e., parameters assignments) for operation
82 definitions that are within TOSCA Node or Relationship Template definitions. This includes
83 when operation definitions are included as part of a Requirement assignment in a Node
86 :type: {:obj:`basestring`: :class:`PropertyAssignment`}
90 def _get_extensions(self, context):
91 def update_inherited_extensions(extensions, interface_type):
92 parent = interface_type._get_parent(context)
93 if parent is not None:
94 update_inherited_extensions(extensions, parent)
95 operation_definition = interface_type.operations.get(self._name)
96 if operation_definition is not None:
97 if operation_definition._extensions:
98 extensions.update(operation_definition._extensions)
101 update_inherited_extensions(extensions, self._container._get_type(context))
102 if self._container._extensions:
103 extensions.update(self._container._extensions)
105 extensions.update(self._extensions)
109 @allow_unknown_fields
111 @implements_specification('3.5.14-2', 'tosca-simple-1.0')
112 class InterfaceAssignment(ExtensiblePresentation):
114 An interface definition defines a named interface that can be associated with a Node or
117 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
118 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
119 #DEFN_ELEMENT_INTERFACE_DEF>`__
122 @object_dict_field(PropertyAssignment)
125 The optional list of input property assignments (i.e., parameters assignments) for interface
126 definitions that are within TOSCA Node or Relationship Template definitions. This includes
127 when interface definitions are referenced as part of a Requirement assignment in a Node
130 :type: {:obj:`basestring`: :class:`PropertyAssignment`}
133 @object_dict_unknown_fields(OperationAssignment)
134 def operations(self):
136 :type: {:obj:`basestring`: :class:`OperationAssignment`}
140 def _get_type(self, context):
141 the_type = self._container._get_type(context)
143 if isinstance(the_type, tuple):
144 # In RelationshipAssignment
145 the_type = the_type[0] # This could be a RelationshipTemplate
147 interface_definitions = the_type._get_interfaces(context) \
148 if the_type is not None else None
149 interface_definition = interface_definitions.get(self._name) \
150 if interface_definitions is not None else None
151 return interface_definition._get_type(context) \
152 if interface_definition is not None else None
154 def _validate(self, context):
155 super(InterfaceAssignment, self)._validate(context)
157 for operation in self.operations.itervalues(): # pylint: disable=no-member
158 operation._validate(context)
161 @short_form_field('type')
163 class RelationshipAssignment(ExtensiblePresentation):
165 Relationship assignment.
168 @field_validator(relationship_template_or_type_validator)
169 @primitive_field(str)
172 The optional reserved keyname used to provide the name of the Relationship Type for the
173 requirement assignment's relationship keyname.
175 :type: :obj:`basestring`
178 @object_dict_field(PropertyAssignment)
179 def properties(self):
181 ARIA NOTE: This field is not mentioned in the spec, but is implied.
183 :type: {:obj:`basestring`: :class:`PropertyAssignment`}
186 @object_dict_field(InterfaceAssignment)
187 def interfaces(self):
189 The optional reserved keyname used to reference declared (named) interface definitions of
190 the corresponding Relationship Type in order to provide Property assignments for these
191 interfaces or operations of these interfaces.
193 :type: {:obj:`basestring`: :class:`InterfaceAssignment`}
197 def _get_type(self, context):
198 type_name = self.type
199 if type_name is not None:
200 the_type = context.presentation.get_from_dict('service_template', 'topology_template',
201 'relationship_templates', type_name)
202 if the_type is not None:
203 return the_type, 'relationship_template'
204 the_type = get_type_by_name(context, type_name, 'relationship_types')
205 if the_type is not None:
206 return the_type, 'relationship_type'
210 @short_form_field('node')
212 @implements_specification('3.7.2', 'tosca-simple-1.0')
213 class RequirementAssignment(ExtensiblePresentation):
215 A Requirement assignment allows template authors to provide either concrete names of TOSCA
216 templates or provide abstract selection criteria for providers to use to find matching TOSCA
217 templates that are used to fulfill a named requirement's declared TOSCA Node Type.
219 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
220 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
221 #DEFN_ELEMENT_REQUIREMENT_ASSIGNMENT>`__
224 # The example in 3.7.2.2.2 shows unknown fields in addition to these, but is this a mistake?
226 @field_validator(capability_definition_or_type_validator)
227 @primitive_field(str)
228 def capability(self):
230 The optional reserved keyname used to provide the name of either a:
232 * Capability definition within a target node template that can fulfill the requirement.
233 * Capability Type that the provider will use to select a type-compatible target node
234 template to fulfill the requirement at runtime.
236 :type: :obj:`basestring`
239 @field_validator(node_template_or_type_validator)
240 @primitive_field(str)
243 The optional reserved keyname used to identify the target node of a relationship.
244 Specifically, it is used to provide either a:
246 * Node Template name that can fulfill the target node requirement.
247 * Node Type name that the provider will use to select a type-compatible node template to
248 fulfill the requirement at runtime.
250 :type: :obj:`basestring`
253 @object_field(RelationshipAssignment)
254 def relationship(self):
256 The optional reserved keyname used to provide the name of either a:
258 * Relationship Template to use to relate the source node to the (capability in the) target
259 node when fulfilling the requirement.
260 * Relationship Type that the provider will use to select a type-compatible relationship
261 template to relate the source node to the target node at runtime.
263 :type: :class:`RelationshipAssignment`
266 @field_validator(node_filter_validator)
267 @object_field(NodeFilter)
268 def node_filter(self):
270 The optional filter definition that TOSCA orchestrators or providers would use to select a
271 type-compatible target node that can fulfill the associated abstract requirement at runtime.
273 :type: :class:`NodeFilter`
277 def _get_node(self, context):
281 node_template = context.presentation.get_from_dict('service_template',
283 'node_templates', node)
284 if node_template is not None:
285 return node_template, 'node_template'
286 node_type = get_type_by_name(context, node, 'node_types')
287 if node_type is not None:
288 return node_type, 'node_type'
293 def _get_capability(self, context):
294 capability = self.capability
296 if capability is not None:
297 node, node_variant = self._get_node(context)
298 if node_variant == 'node_template':
299 capabilities = node._get_capabilities(context)
300 if capability in capabilities:
301 return capabilities[capability], 'capability_assignment'
302 capability_type = get_type_by_name(context, capability, 'capability_types')
303 if capability_type is not None:
304 return capability_type, 'capability_type'
309 @implements_specification('3.5.11', 'tosca-simple-1.0')
310 class AttributeAssignment(AsIsPresentation):
312 This section defines the grammar for assigning values to named attributes within TOSCA Node and
313 Relationship templates which are defined in their corresponding named types.
315 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
316 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
317 #DEFN_ELEMENT_ATTRIBUTE_VALUE_ASSIGNMENT>`__
322 @implements_specification('3.7.1', 'tosca-simple-1.0')
323 class CapabilityAssignment(ExtensiblePresentation):
325 A capability assignment allows node template authors to assign values to properties and
326 attributes for a named capability definition that is part of a Node Template's type definition.
328 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
329 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
330 #DEFN_ELEMENT_CAPABILITY_ASSIGNMENT>`__
333 @object_dict_field(PropertyAssignment)
334 def properties(self):
336 An optional list of property definitions for the Capability definition.
338 :type: {:obj:`basestring`: :class:`PropertyAssignment`}
341 @object_dict_field(AttributeAssignment)
342 def attributes(self):
344 An optional list of attribute definitions for the Capability definition.
346 :type: {:obj:`basestring`: :class:`AttributeAssignment`}
350 def _get_definition(self, context):
351 node_type = self._container._get_type(context)
352 capability_definitions = node_type._get_capabilities(context) \
353 if node_type is not None else None
354 return capability_definitions.get(self._name) \
355 if capability_definitions is not None else None
358 def _get_type(self, context):
359 capability_definition = self._get_definition(context)
360 return capability_definition._get_type(context) \
361 if capability_definition is not None else None
365 @implements_specification('3.5.6', 'tosca-simple-1.0')
366 class ArtifactAssignmentForType(ExtensiblePresentation):
368 An artifact definition defines a named, typed file that can be associated with Node Type or Node
369 Template and used by orchestration engine to facilitate deployment and implementation of
370 interface operations.
372 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
373 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
374 #DEFN_ENTITY_ARTIFACT_DEF>`__
377 @field_validator(type_validator('artifact type', convert_name_to_full_type_name,
379 @primitive_field(str, required=True)
382 The required artifact type for the artifact definition.
384 :type: :obj:`basestring`
387 @primitive_field(str, required=True)
390 The required URI string (relative or absolute) which can be used to locate the artifact's
393 :type: :obj:`basestring`
396 @field_validator(type_validator('repository', 'repositories'))
397 @primitive_field(str)
398 def repository(self):
400 The optional name of the repository definition which contains the location of the external
401 repository that contains the artifact. The artifact is expected to be referenceable by its
402 file URI within the repository.
404 :type: :obj:`basestring`
407 @object_field(Description)
408 def description(self):
410 The optional description for the artifact definition.
412 :type: :class:`Description`
415 @primitive_field(str)
416 def deploy_path(self):
418 The file path the associated file would be deployed into within the target node's container.
420 :type: :obj:`basestring`
423 @object_dict_field(PropertyAssignment)
424 def properties(self):
426 ARIA NOTE: This field is not mentioned in the spec, but is implied.
428 :type: {:obj:`basestring`: :class:`PropertyAssignment`}
432 def _get_type(self, context):
433 return get_type_by_name(context, self.type, 'artifact_types')
436 def _get_repository(self, context):
437 return context.presentation.get_from_dict('service_template', 'repositories',
441 def _get_property_values(self, context):
442 return FrozenDict(get_assigned_and_defined_parameter_values(context, self, 'property'))
445 def _validate(self, context):
446 super(ArtifactAssignmentForType, self)._validate(context)
449 class ArtifactAssignment(ArtifactAssignmentForType):
451 def _validate(self, context):
452 super(ArtifactAssignment, self)._validate(context)
453 self._get_property_values(context)