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, FrozenList)
17 from aria.utils.caching import cachedmethod
18 from aria.parser import implements_specification
19 from aria.parser.presentation import (has_fields, allow_unknown_fields, primitive_field,
20 primitive_list_field, object_field, object_dict_field,
21 object_list_field, object_sequenced_list_field,
22 object_dict_unknown_fields, field_getter, field_validator,
23 list_type_validator, derived_from_validator,
24 get_parent_presentation)
26 from .assignments import ArtifactAssignmentForType
27 from .data_types import Version
28 from .definitions import (PropertyDefinition, AttributeDefinition, InterfaceDefinition,
29 RequirementDefinition, CapabilityDefinition, OperationDefinition)
30 from .misc import (Description, ConstraintClause)
31 from .modeling.artifacts import get_inherited_artifact_definitions
32 from .modeling.capabilities import (get_inherited_valid_source_types,
33 get_inherited_capability_definitions)
34 from .modeling.data_types import (get_data_type, get_inherited_constraints, coerce_data_type_value,
35 validate_data_type_name)
36 from .modeling.interfaces import (get_inherited_interface_definitions, get_inherited_operations)
37 from .modeling.policies import get_inherited_targets
38 from .modeling.parameters import get_inherited_parameter_definitions
39 from .modeling.requirements import get_inherited_requirement_definitions
40 from .presentation.extensible import ExtensiblePresentation
41 from .presentation.field_getters import data_type_class_getter
42 from .presentation.field_validators import (data_type_derived_from_validator,
43 data_type_constraints_validator,
44 data_type_properties_validator,
45 list_node_type_or_group_type_validator)
46 from .presentation.types import convert_name_to_full_type_name
51 @implements_specification('3.6.3', 'tosca-simple-1.0')
52 class ArtifactType(ExtensiblePresentation):
54 An Artifact Type is a reusable entity that defines the type of one or more files that are used
55 to define implementation or deployment artifacts that are referenced by nodes or relationships
58 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
59 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
60 #DEFN_ENTITY_ARTIFACT_TYPE>`__
63 @field_validator(derived_from_validator(convert_name_to_full_type_name, 'artifact_types'))
65 def derived_from(self):
67 An optional parent Artifact Type name the Artifact Type derives from.
69 :type: :obj:`basestring`
72 @field_getter(data_type_class_getter(Version))
76 An optional version for the Artifact Type definition.
78 :type: :class:`Version`
81 @object_field(Description)
82 def description(self):
84 An optional description for the Artifact Type.
86 :type: :class:`Description`
92 The required mime type property for the Artifact Type.
94 :type: :obj:`basestring`
97 @primitive_list_field(str)
100 The required file extension property for the Artifact Type.
102 :type: [:obj:`basestring`]
105 @object_dict_field(PropertyDefinition)
106 def properties(self):
108 An optional list of property definitions for the Artifact Type.
110 :type: {:obj:`basestring`: :class:`PropertyDefinition`}
114 def _get_parent(self, context):
115 return get_parent_presentation(context, self, convert_name_to_full_type_name,
119 def _get_properties(self, context):
120 return FrozenDict(get_inherited_parameter_definitions(context, self, 'properties'))
122 def _validate(self, context):
123 super(ArtifactType, self)._validate(context)
124 self._get_properties(context)
126 def _dump(self, context):
127 self._dump_content(context, (
137 @implements_specification('3.6.5', 'tosca-simple-1.0')
138 class DataType(ExtensiblePresentation):
140 A Data Type definition defines the schema for new named datatypes in TOSCA.
142 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
143 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
144 #DEFN_ENTITY_DATA_TYPE>`__
147 @field_validator(data_type_derived_from_validator)
148 @primitive_field(str)
149 def derived_from(self):
151 The optional key used when a datatype is derived from an existing TOSCA Data Type.
153 :type: :obj:`basestring`
156 @object_field(Version)
159 An optional version for the Data Type definition.
161 :type: :class:`Version`
164 @object_field(Description)
165 def description(self):
167 The optional description for the Data Type.
169 :type: :class:`Description`
172 @field_validator(data_type_constraints_validator)
173 @object_list_field(ConstraintClause)
174 def constraints(self):
176 The optional list of sequenced constraint clauses for the Data Type.
178 :type: list of (str, :class:`ConstraintClause`)
181 @field_validator(data_type_properties_validator)
182 @object_dict_field(PropertyDefinition)
183 def properties(self):
185 The optional list property definitions that comprise the schema for a complex Data Type in
188 :type: {:obj:`basestring`: :class:`PropertyDefinition`}
192 def _get_parent(self, context):
193 return get_data_type(context, self, 'derived_from', allow_none=True)
196 def _is_descendant(self, context, the_type):
199 if not hasattr(the_type, '_name'):
200 # Must be a primitive type
201 return self._get_primitive_ancestor(context) == the_type
202 if the_type._name == self._name:
204 return self._is_descendant(context, the_type._get_parent(context))
207 def _get_primitive_ancestor(self, context):
208 parent = self._get_parent(context)
209 if parent is not None:
210 if not isinstance(parent, DataType):
213 return parent._get_primitive_ancestor(context) # pylint: disable=no-member
217 def _get_properties(self, context):
218 return FrozenDict(get_inherited_parameter_definitions(context, self, 'properties'))
221 def _get_constraints(self, context):
222 return get_inherited_constraints(context, self)
224 def _validate(self, context):
225 super(DataType, self)._validate(context)
226 validate_data_type_name(context, self)
227 self._get_properties(context)
229 def _coerce_value(self, context, presentation, entry_schema, constraints, value, aspect):
230 return coerce_data_type_value(context, presentation, self, entry_schema, constraints, value,
233 def _dump(self, context):
234 self._dump_content(context, (
243 @implements_specification('3.6.6', 'tosca-simple-1.0')
244 class CapabilityType(ExtensiblePresentation):
246 A Capability Type is a reusable entity that describes a kind of capability that a Node Type can
247 declare to expose. Requirements (implicit or explicit) that are declared as part of one node can
248 be matched to (i.e., fulfilled by) the Capabilities declared by another node.
250 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
251 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
252 #DEFN_ENTITY_CAPABILITY_TYPE>`__
255 @field_validator(derived_from_validator(convert_name_to_full_type_name, 'capability_types'))
256 @primitive_field(str)
257 def derived_from(self):
259 An optional parent capability type name this new Capability Type derives from.
261 :type: :obj:`basestring`
264 @object_field(Version)
267 An optional version for the Capability Type definition.
269 :type: :class:`Version`
272 @object_field(Description)
273 def description(self):
275 An optional description for the Capability Type.
277 :type: :class:`Description`
280 @object_dict_field(PropertyDefinition)
281 def properties(self):
283 An optional list of property definitions for the Capability Type.
285 ARIA NOTE: The spec says 'list', but the examples are all of dicts.
287 :type: {:obj:`basestring`: :class:`PropertyDefinition`}
290 @object_dict_field(AttributeDefinition)
291 def attributes(self):
293 An optional list of attribute definitions for the Capability Type.
295 :type: {:obj:`basestring`: :class:`AttributeDefinition`}
298 @field_validator(list_type_validator('node type', convert_name_to_full_type_name, 'node_types'))
299 @primitive_list_field(str)
300 def valid_source_types(self):
302 An optional list of one or more valid names of Node Types that are supported as valid
303 sources of any relationship established to the declared Capability Type.
305 :type: [:obj:`basestring`]
309 def _get_parent(self, context):
310 return get_parent_presentation(context, self, convert_name_to_full_type_name,
314 def _is_descendant(self, context, other_type):
315 """returns True iff `other_type` is a descendant of the represented capability type"""
316 if other_type is None:
318 elif other_type._name == self._name:
320 return self._is_descendant(context, other_type._get_parent(context))
323 def _get_properties(self, context):
324 return FrozenDict(get_inherited_parameter_definitions(context, self, 'properties'))
327 def _get_valid_source_types(self, context):
328 return get_inherited_valid_source_types(context, self)
330 def _validate(self, context):
331 super(CapabilityType, self)._validate(context)
332 self._get_properties(context)
334 def _dump(self, context):
335 self._dump_content(context, (
339 'valid_source_types',
344 @allow_unknown_fields
346 @implements_specification('3.6.4', 'tosca-simple-1.0')
347 class InterfaceType(ExtensiblePresentation):
349 An Interface Type is a reusable entity that describes a set of operations that can be used to
350 interact with or manage a node or relationship in a TOSCA topology.
352 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
353 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
354 #DEFN_ENTITY_INTERFACE_TYPE>`__
357 @field_validator(derived_from_validator(convert_name_to_full_type_name, 'interface_types'))
358 @primitive_field(str)
359 def derived_from(self):
361 An optional parent Interface Type name this new Interface Type derives from.
363 :type: :obj:`basestring`
366 @object_field(Version)
369 An optional version for the Interface Type definition.
371 :type: :class:`Version`
374 @object_field(Description)
375 def description(self):
377 An optional description for the Interface Type.
379 :type: :class:`Description`
382 @object_dict_field(PropertyDefinition)
385 The optional list of input parameter definitions.
387 :type: {:obj:`basestring`: :class:`PropertyDefinition`}
390 @object_dict_unknown_fields(OperationDefinition)
391 def operations(self):
393 :type: {:obj:`basestring`: :class:`OperationDefinition`}
397 def _get_parent(self, context):
398 return get_parent_presentation(context, self, convert_name_to_full_type_name,
402 def _is_descendant(self, context, the_type):
405 elif the_type._name == self._name:
407 return self._is_descendant(context, the_type._get_parent(context))
410 def _get_inputs(self, context):
411 return FrozenDict(get_inherited_parameter_definitions(context, self, 'inputs'))
414 def _get_operations(self, context):
415 return FrozenDict(get_inherited_operations(context, self))
417 def _validate(self, context):
418 super(InterfaceType, self)._validate(context)
419 self._get_inputs(context)
420 for operation in self.operations.itervalues(): # pylint: disable=no-member
421 operation._validate(context)
423 def _dump(self, context):
424 self._dump_content(context, (
433 @implements_specification('3.6.9', 'tosca-simple-1.0')
434 class RelationshipType(ExtensiblePresentation):
436 A Relationship Type is a reusable entity that defines the type of one or more relationships
437 between Node Types or Node Templates.
439 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
440 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
441 #DEFN_ENTITY_RELATIONSHIP_TYPE>`__
444 @field_validator(derived_from_validator(convert_name_to_full_type_name, 'relationship_types'))
445 @primitive_field(str)
446 def derived_from(self):
448 An optional parent Relationship Type name the Relationship Type derives from.
450 :type: :obj:`basestring`
453 @object_field(Version)
456 An optional version for the Relationship Type definition.
458 :type: :class:`Version`
461 @object_field(Description)
462 def description(self):
464 An optional description for the Relationship Type.
466 :type: :class:`Description`
469 @object_dict_field(PropertyDefinition)
470 def properties(self):
472 An optional list of property definitions for the Relationship Type.
474 :type: {:obj:`basestring`: :class:`PropertyDefinition`}
477 @object_dict_field(AttributeDefinition)
478 def attributes(self):
480 An optional list of attribute definitions for the Relationship Type.
482 :type: {:obj:`basestring`: :class:`AttributeDefinition`}
485 @object_dict_field(InterfaceDefinition)
486 def interfaces(self):
488 An optional list of interface definitions interfaces supported by the Relationship Type.
490 :type: {:obj:`basestring`: :class:`InterfaceDefinition`}
493 @field_validator(list_type_validator('capability type', convert_name_to_full_type_name,
495 @primitive_list_field(str)
496 def valid_target_types(self):
498 An optional list of one or more names of Capability Types that are valid targets for this
501 :type: [:obj:`basestring`]
505 def _get_parent(self, context):
506 return get_parent_presentation(context, self, convert_name_to_full_type_name,
507 'relationship_types')
510 def _is_descendant(self, context, the_type):
513 elif the_type._name == self._name:
515 return self._is_descendant(context, the_type._get_parent(context))
518 def _get_properties(self, context):
519 return FrozenDict(get_inherited_parameter_definitions(context, self, 'properties'))
522 def _get_attributes(self, context):
523 return FrozenDict(get_inherited_parameter_definitions(context, self, 'attributes'))
526 def _get_interfaces(self, context):
527 return FrozenDict(get_inherited_interface_definitions(context, self, 'relationship type'))
529 def _validate(self, context):
530 super(RelationshipType, self)._validate(context)
531 self._get_properties(context)
532 self._get_attributes(context)
533 self._get_interfaces(context)
535 def _dump(self, context):
536 self._dump_content(context, (
540 'valid_target_types',
547 @implements_specification('3.6.8', 'tosca-simple-1.0')
548 class NodeType(ExtensiblePresentation):
550 A Node Type is a reusable entity that defines the type of one or more Node Templates. As such, a
551 Node Type defines the structure of observable properties via a Properties Definition, the
552 Requirements and Capabilities of the node as well as its supported interfaces.
554 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
555 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
556 #DEFN_ENTITY_NODE_TYPE>`__
559 @field_validator(derived_from_validator(convert_name_to_full_type_name, 'node_types'))
560 @primitive_field(str)
561 def derived_from(self):
563 An optional parent Node Type name this new Node Type derives from.
565 :type: :obj:`basestring`
568 @object_field(Version)
571 An optional version for the Node Type definition.
573 :type: :class:`Version`
576 @object_field(Description)
577 def description(self):
579 An optional description for the Node Type.
581 :type: :class:`Description`
584 @object_dict_field(PropertyDefinition)
585 def properties(self):
587 An optional list of property definitions for the Node Type.
589 :type: {:obj:`basestring`: :class:`PropertyDefinition`}
592 @object_dict_field(AttributeDefinition)
593 def attributes(self):
595 An optional list of attribute definitions for the Node Type.
597 :type: {:obj:`basestring`: :class:`AttributeDefinition`}
600 @object_sequenced_list_field(RequirementDefinition)
601 def requirements(self):
603 An optional sequenced list of requirement definitions for the Node Type.
605 ARIA NOTE: The spec seems wrong to make this a sequenced list. It seems that when you have
606 more than one requirement of the same name, behavior is undefined. The idea is to use the
607 "occurrences" field if you need to limit the number of requirement assignments.
609 :type: list of (str, :class:`RequirementDefinition`)
612 @object_dict_field(CapabilityDefinition)
613 def capabilities(self):
615 An optional list of capability definitions for the Node Type.
617 :type: list of :class:`CapabilityDefinition`
620 @object_dict_field(InterfaceDefinition)
621 def interfaces(self):
623 An optional list of interface definitions supported by the Node Type.
625 :type: {:obj:`basestring`: :class:`InterfaceDefinition`}
628 @object_dict_field(ArtifactAssignmentForType)
631 An optional list of named artifact definitions for the Node Type.
633 :type: {:obj:`basestring`: :class:`ArtifactAssignmentForType`}
637 def _get_parent(self, context):
638 return get_parent_presentation(context, self, convert_name_to_full_type_name, 'node_types')
641 def _is_descendant(self, context, the_type):
644 elif the_type._name == self._name:
646 return self._is_descendant(context, the_type._get_parent(context))
649 def _get_properties(self, context):
650 return FrozenDict(get_inherited_parameter_definitions(context, self, 'properties'))
653 def _get_attributes(self, context):
654 return FrozenDict(get_inherited_parameter_definitions(context, self, 'attributes'))
657 def _get_requirements(self, context):
658 return FrozenList(get_inherited_requirement_definitions(context, self))
661 def _get_capabilities(self, context):
662 return FrozenDict(get_inherited_capability_definitions(context, self))
665 def _get_interfaces(self, context):
666 return FrozenDict(get_inherited_interface_definitions(context, self, 'node type'))
669 def _get_artifacts(self, context):
670 return FrozenDict(get_inherited_artifact_definitions(context, self))
672 def _validate(self, context):
673 super(NodeType, self)._validate(context)
674 self._get_properties(context)
675 self._get_attributes(context)
676 self._get_requirements(context)
677 self._get_capabilities(context)
678 self._get_interfaces(context)
679 self._get_artifacts(context)
681 def _dump(self, context):
682 self._dump_content(context, (
695 @implements_specification('3.6.10', 'tosca-simple-1.0')
696 class GroupType(ExtensiblePresentation):
698 A Group Type defines logical grouping types for nodes, typically for different management
699 purposes. Groups can effectively be viewed as logical nodes that are not part of the physical
700 deployment topology of an application, yet can have capabilities and the ability to attach
701 policies and interfaces that can be applied (depending on the group type) to its member nodes.
703 Conceptually, group definitions allow the creation of logical "membership" relationships to
704 nodes in a service template that are not a part of the application's explicit requirement
705 dependencies in the topology template (i.e. those required to actually get the application
706 deployed and running). Instead, such logical membership allows for the introduction of things
707 such as group management and uniform application of policies (i.e., requirements that are also
708 not bound to the application itself) to the group's members.
710 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
711 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
712 #DEFN_ENTITY_GROUP_TYPE>`__
715 @field_validator(derived_from_validator(convert_name_to_full_type_name, 'group_types'))
716 @primitive_field(str)
717 def derived_from(self):
719 An optional parent Group Type name the Group Type derives from.
721 :type: :obj:`basestring`
724 @object_field(Version)
727 An optional version for the Group Type definition.
729 :type: :class:`Version`
732 @object_field(Description)
733 def description(self):
735 The optional description for the Group Type.
737 :type: :class:`Description`
740 @object_dict_field(PropertyDefinition)
741 def properties(self):
743 An optional list of property definitions for the Group Type.
745 :type: {:obj:`basestring`: :class:`PropertyDefinition`}
748 @field_validator(list_type_validator('node type', convert_name_to_full_type_name, 'node_types'))
749 @primitive_list_field(str)
752 An optional list of one or more names of Node Types that are valid (allowed) as members of
755 Note: This can be viewed by TOSCA Orchestrators as an implied relationship from the listed
756 members nodes to the group, but one that does not have operational lifecycle considerations.
757 For example, if we were to name this as an explicit Relationship Type we might call this
760 :type: [:obj:`basestring`]
763 @object_dict_field(InterfaceDefinition)
764 def interfaces(self):
766 An optional list of interface definitions supported by the Group Type.
768 :type: {:obj:`basestring`: :class:`InterfaceDefinition`}
772 def _get_parent(self, context):
773 return get_parent_presentation(context, self, convert_name_to_full_type_name,
777 def _is_descendant(self, context, the_type):
780 elif the_type._name == self._name:
782 return self._is_descendant(context, the_type._get_parent(context))
785 def _get_properties(self, context):
786 return FrozenDict(get_inherited_parameter_definitions(context, self, 'properties'))
789 def _get_interfaces(self, context):
790 return FrozenDict(get_inherited_interface_definitions(context, self, 'group type'))
792 def _validate(self, context):
793 super(GroupType, self)._validate(context)
794 self._get_properties(context)
795 self._get_interfaces(context)
797 def _dump(self, context):
798 self._dump_content(context, (
808 @implements_specification('3.6.11', 'tosca-simple-1.0')
809 class PolicyType(ExtensiblePresentation):
811 A Policy Type defines a type of requirement that affects or governs an application or service's
812 topology at some stage of its lifecycle, but is not explicitly part of the topology itself
813 (i.e., it does not prevent the application or service from being deployed or run if it did not
816 See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca
817 /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html
818 #DEFN_ENTITY_POLICY_TYPE>`__
821 @field_validator(derived_from_validator(convert_name_to_full_type_name, 'policy_types'))
822 @primitive_field(str)
823 def derived_from(self):
825 An optional parent Policy Type name the Policy Type derives from.
827 :type: :obj:`basestring`
830 @object_field(Version)
833 An optional version for the Policy Type definition.
835 :type: :class:`Version`
838 @object_field(Description)
839 def description(self):
841 The optional description for the Policy Type.
843 :type: :class:`Description`
846 @object_dict_field(PropertyDefinition)
847 def properties(self):
849 An optional list of property definitions for the Policy Type.
851 :type: :class:`PropertyDefinition`
854 @field_validator(list_node_type_or_group_type_validator)
855 @primitive_list_field(str)
858 An optional list of valid Node Types or Group Types the Policy Type can be applied to.
860 Note: This can be viewed by TOSCA Orchestrators as an implied relationship to the target
861 nodes, but one that does not have operational lifecycle considerations. For example, if we
862 were to name this as an explicit Relationship Type we might call this "AppliesTo" (node or
865 :type: [:obj:`basestring`]
869 def _get_parent(self, context):
870 return get_parent_presentation(context, self, convert_name_to_full_type_name,
874 def _get_properties(self, context):
875 return FrozenDict(get_inherited_parameter_definitions(context, self, 'properties'))
878 def _get_targets(self, context):
879 node_types, group_types = get_inherited_targets(context, self)
880 return FrozenList(node_types), FrozenList(group_types)
882 def _validate(self, context):
883 super(PolicyType, self)._validate(context)
884 self._get_properties(context)
886 def _dump(self, context):
887 self._dump_content(context, (