| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| from aria.utils.collections import FrozenDict |
| from aria.utils.caching import cachedmethod |
| from aria.utils.formatting import safe_repr |
| from aria.parser import implements_specification |
| from aria.parser.validation import Issue |
| from aria.parser.presentation import (has_fields, short_form_field, allow_unknown_fields, |
| primitive_field, primitive_list_field, object_field, |
| object_list_field, object_dict_field, |
| object_dict_unknown_fields, field_validator, |
| field_getter, type_validator, list_type_validator) |
| |
| from .data_types import Range |
| from .misc import (Description, ConstraintClause, OperationImplementation, EntrySchema) |
| from .presentation.extensible import ExtensiblePresentation |
| from .presentation.field_getters import data_type_class_getter |
| from .presentation.field_validators import (data_type_validator, data_value_validator, |
| entry_schema_validator) |
| from .presentation.types import (convert_name_to_full_type_name, get_type_by_name) |
| from .modeling.data_types import get_data_type, get_property_constraints |
| from .modeling.interfaces import (get_and_override_input_definitions_from_type, |
| get_and_override_operation_definitions_from_type) |
| |
| |
| @has_fields |
| @implements_specification('3.5.8', 'tosca-simple-1.0') |
| class PropertyDefinition(ExtensiblePresentation): |
| """ |
| A property definition defines a named, typed value and related data that can be associated with |
| an entity defined in this specification (e.g., Node Types, Relationship Types, Capability Types, |
| etc.). Properties are used by template authors to provide input values to TOSCA entities which |
| indicate their "desired state" when they are instantiated. The value of a property can be |
| retrieved using the ``get_property`` function within TOSCA Service Templates. |
| |
| See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca |
| /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html |
| #DEFN_ELEMENT_PROPERTY_DEFN>`__ |
| """ |
| |
| @field_validator(data_type_validator()) |
| @primitive_field(str, required=True) |
| def type(self): |
| """ |
| The required data type for the property. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @object_field(Description) |
| def description(self): |
| """ |
| The optional description for the property. |
| |
| :type: :class:`Description` |
| """ |
| |
| @primitive_field(bool, default=True) |
| def required(self): |
| """ |
| An optional key that declares a property as required (true) or not (false). |
| |
| :type: bool |
| """ |
| |
| @field_validator(data_value_validator) |
| @primitive_field() |
| def default(self): |
| """ |
| An optional key that may provide a value to be used as a default if not provided by another |
| means. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @primitive_field(str, default='supported', allowed=('supported', 'unsupported', 'experimental', |
| 'deprecated')) |
| @implements_specification(section='3.5.8.3', spec='tosca-simple-1.0') |
| def status(self): |
| """ |
| The optional status of the property relative to the specification or implementation. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @object_list_field(ConstraintClause) |
| def constraints(self): |
| """ |
| The optional list of sequenced constraint clauses for the property. |
| |
| :type: list of (str, :class:`ConstraintClause`) |
| """ |
| |
| @field_validator(entry_schema_validator) |
| @object_field(EntrySchema) |
| def entry_schema(self): |
| """ |
| The optional key that is used to declare the name of the Datatype definition for entries of |
| set types such as the TOSCA list or map. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @cachedmethod |
| def _get_type(self, context): |
| return get_data_type(context, self, 'type') |
| |
| @cachedmethod |
| def _get_constraints(self, context): |
| return get_property_constraints(context, self) |
| |
| |
| @has_fields |
| @implements_specification('3.5.10', 'tosca-simple-1.0') |
| class AttributeDefinition(ExtensiblePresentation): |
| """ |
| An attribute definition defines a named, typed value that can be associated with an entity |
| defined in this specification (e.g., a Node, Relationship or Capability Type). Specifically, it |
| is used to expose the "actual state" of some property of a TOSCA entity after it has been |
| deployed and instantiated (as set by the TOSCA orchestrator). Attribute values can be retrieved |
| via the ``get_attribute`` function from the instance model and used as values to other |
| entities within TOSCA Service Templates. |
| |
| See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca |
| /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html |
| #DEFN_ELEMENT_ATTRIBUTE_DEFN>`__ |
| """ |
| |
| @field_validator(data_type_validator()) |
| @primitive_field(str, required=True) |
| def type(self): |
| """ |
| The required data type for the attribute. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @object_field(Description) |
| def description(self): |
| """ |
| The optional description for the attribute. |
| |
| :type: :class:`Description` |
| """ |
| |
| @field_validator(data_value_validator) |
| @primitive_field() |
| def default(self): |
| """ |
| An optional key that may provide a value to be used as a default if not provided by another |
| means. |
| |
| This value SHALL be type compatible with the type declared by the property definition's type |
| keyname. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @primitive_field(str, default='supported', allowed=('supported', 'unsupported', 'experimental', |
| 'deprecated')) |
| def status(self): |
| """ |
| The optional status of the attribute relative to the specification or implementation. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @field_validator(entry_schema_validator) |
| @object_field(EntrySchema) |
| def entry_schema(self): |
| """ |
| The optional key that is used to declare the name of the Datatype definition for entries of |
| set types such as the TOSCA list or map. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @cachedmethod |
| def _get_type(self, context): |
| return get_data_type(context, self, 'type') |
| |
| |
| @has_fields |
| @implements_specification('3.5.12-1', 'tosca-simple-1.0') |
| class InputDefinition(PropertyDefinition): |
| """ |
| A parameter definition is essentially a TOSCA property definition; however, it also allows a |
| value to be assigned to it (as for a TOSCA property assignment). In addition, in the case of |
| output parameters, it can optionally inherit the data type of the value assigned to it rather |
| than have an explicit data type defined for it. |
| |
| See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca |
| /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html |
| #DEFN_ELEMENT_PARAMETER_DEF>`__ |
| """ |
| |
| @field_validator(data_value_validator) |
| @primitive_field() |
| def value(self): |
| """ |
| The type-compatible value to assign to the named parameter. Parameter values may be provided |
| as the result from the evaluation of an expression or a function. |
| """ |
| |
| |
| @has_fields |
| @implements_specification('3.5.12-2', 'tosca-simple-1.0') |
| class OutputDefinition(InputDefinition): |
| @field_validator(data_type_validator()) |
| @primitive_field(str) |
| def type(self): |
| """ |
| The required data type for the parameter. |
| |
| Note: This keyname is required for a TOSCA Property definition, but is not for a TOSCA |
| Parameter definition. |
| |
| ARIA NOTE: the spec must be mistaken: inputs should have this field requires, only outputs |
| have it as optional. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| |
| @short_form_field('implementation') |
| @has_fields |
| @implements_specification('3.5.13-1', 'tosca-simple-1.0') |
| class OperationDefinition(ExtensiblePresentation): |
| """ |
| An operation definition defines a named function or procedure that can be bound to an |
| implementation artifact (e.g., a script). |
| |
| See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca |
| /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html |
| #DEFN_ELEMENT_OPERATION_DEF>`__ |
| """ |
| |
| @object_field(Description) |
| def description(self): |
| """ |
| The optional description string for the associated named operation. |
| |
| :type: :class:`Description` |
| """ |
| |
| @object_field(OperationImplementation) |
| def implementation(self): |
| """ |
| The optional implementation artifact name (e.g., a script file name within a TOSCA CSAR |
| file). |
| |
| :type: :class:`OperationImplementation` |
| """ |
| |
| @object_dict_field(PropertyDefinition) |
| def inputs(self): |
| """ |
| The optional list of input property definitions available to all defined operations for |
| interface definitions that are within TOSCA Node or Relationship Type definitions. This |
| includes when interface definitions are included as part of a Requirement definition in a |
| Node Type. |
| |
| :type: {:obj:`basestring`: :class:`PropertyDefinition`} |
| """ |
| |
| |
| @allow_unknown_fields |
| @has_fields |
| @implements_specification('3.5.14-1', 'tosca-simple-1.0') |
| class InterfaceDefinition(ExtensiblePresentation): |
| """ |
| An interface definition defines a named interface that can be associated with a Node or |
| Relationship Type. |
| |
| See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca |
| /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html |
| #DEFN_ELEMENT_INTERFACE_DEF>`__ |
| """ |
| |
| @field_validator(type_validator('interface type', convert_name_to_full_type_name, |
| 'interface_types')) |
| @primitive_field(str, required=True) |
| def type(self): |
| """ |
| ARIA NOTE: This field is not mentioned in the spec, but is implied. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @object_dict_field(PropertyDefinition) |
| def inputs(self): |
| """ |
| The optional list of input property definitions available to all defined operations for |
| interface definitions that are within TOSCA Node or Relationship Type definitions. This |
| includes when interface definitions are included as part of a Requirement definition in a |
| Node Type. |
| |
| :type: {:obj:`basestring`: :class:`PropertyDefinition`} |
| """ |
| |
| @object_dict_unknown_fields(OperationDefinition) |
| def operations(self): |
| """ |
| :type: {:obj:`basestring`: :class:`OperationDefinition`} |
| """ |
| |
| @cachedmethod |
| def _get_type(self, context): |
| return get_type_by_name(context, self.type, 'interface_types') |
| |
| @cachedmethod |
| def _get_inputs(self, context): |
| return FrozenDict(get_and_override_input_definitions_from_type(context, self)) |
| |
| @cachedmethod |
| def _get_operations(self, context): |
| return FrozenDict(get_and_override_operation_definitions_from_type(context, self)) |
| |
| def _validate(self, context): |
| super(InterfaceDefinition, self)._validate(context) |
| self._get_inputs(context) |
| self._get_operations(context) |
| |
| |
| @short_form_field('type') |
| @has_fields |
| class RelationshipDefinition(ExtensiblePresentation): |
| """ |
| Relationship definition. |
| """ |
| |
| @field_validator(type_validator('relationship type', convert_name_to_full_type_name, |
| 'relationship_types')) |
| @primitive_field(str, required=True) |
| def type(self): |
| """ |
| The optional reserved keyname used to provide the name of the Relationship Type for the |
| requirement definition's relationship keyname. |
| |
| ARIA NOTE: the spec shows this as a required field. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @object_dict_field(InterfaceDefinition) |
| def interfaces(self): |
| """ |
| The optional reserved keyname used to reference declared (named) interface definitions of |
| the corresponding Relationship Type in order to declare additional Property definitions for |
| these interfaces or operations of these interfaces. |
| |
| :type: list of :class:`InterfaceDefinition` |
| """ |
| |
| @cachedmethod |
| def _get_type(self, context): |
| return get_type_by_name(context, self.type, 'relationship_types') |
| |
| |
| |
| @short_form_field('capability') |
| @has_fields |
| @implements_specification('3.6.2', 'tosca-simple-1.0') |
| class RequirementDefinition(ExtensiblePresentation): |
| """ |
| The Requirement definition describes a named requirement (dependencies) of a TOSCA Node Type or |
| Node template which needs to be fulfilled by a matching Capability definition declared by |
| another TOSCA modelable entity. The requirement definition may itself include the specific name |
| of the fulfilling entity (explicitly) or provide an abstract type, along with additional |
| filtering characteristics, that a TOSCA orchestrator can use to fulfill the capability at |
| runtime (implicitly). |
| |
| See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca |
| /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html |
| #DEFN_ELEMENT_REQUIREMENT_DEF>`__ |
| """ |
| |
| @field_validator(type_validator('capability type', convert_name_to_full_type_name, |
| 'capability_types')) |
| @primitive_field(str, required=True) |
| def capability(self): |
| """ |
| The required reserved keyname used that can be used to provide the name of a valid |
| Capability Type that can fulfill the requirement. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @field_validator(type_validator('node type', convert_name_to_full_type_name, |
| 'node_types')) |
| @primitive_field(str) |
| def node(self): |
| """ |
| The optional reserved keyname used to provide the name of a valid Node Type that contains |
| the capability definition that can be used to fulfill the requirement. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @object_field(RelationshipDefinition) |
| def relationship(self): |
| """ |
| The optional reserved keyname used to provide the name of a valid Relationship Type to |
| construct when fulfilling the requirement. |
| |
| :type: :class:`RelationshipDefinition` |
| """ |
| |
| @field_getter(data_type_class_getter(Range)) |
| @primitive_field() |
| def occurrences(self): |
| """ |
| The optional minimum and maximum occurrences for the requirement. |
| |
| Note: the keyword UNBOUNDED is also supported to represent any positive integer. |
| |
| :type: :class:`Range` |
| """ |
| |
| @cachedmethod |
| def _get_capability_type(self, context): |
| return get_type_by_name(context, self.capability, 'capability_types') |
| |
| @cachedmethod |
| def _get_node_type(self, context): |
| return context.presentation.get_from_dict('service_template', 'node_types', self.node) |
| |
| def _validate(self, context): |
| super(RequirementDefinition, self)._validate(context) |
| occurrences = self.occurrences |
| if (occurrences is not None) and ((occurrences.value[0] < 0) or \ |
| ((occurrences.value[1] != 'UNBOUNDED') and (occurrences.value[1] < 0))): |
| context.validation.report( |
| 'requirements definition "{0}" occurrences range includes negative integers: {1}' |
| .format(self._name, safe_repr(occurrences)), |
| locator=self._locator, level=Issue.BETWEEN_TYPES) |
| |
| |
| @short_form_field('type') |
| @has_fields |
| @implements_specification('3.6.1', 'tosca-simple-1.0') |
| class CapabilityDefinition(ExtensiblePresentation): |
| """ |
| A capability definition defines a named, typed set of data that can be associated with Node Type |
| or Node Template to describe a transparent capability or feature of the software component the |
| node describes. |
| |
| See the `TOSCA Simple Profile v1.0 cos01 specification <http://docs.oasis-open.org/tosca |
| /TOSCA-Simple-Profile-YAML/v1.0/cos01/TOSCA-Simple-Profile-YAML-v1.0-cos01.html |
| #DEFN_ELEMENT_CAPABILITY_DEFN>`__ |
| """ |
| |
| @field_validator(type_validator('capability type', convert_name_to_full_type_name, |
| 'capability_types')) |
| @primitive_field(str, required=True) |
| def type(self): |
| """ |
| The required name of the Capability Type the capability definition is based upon. |
| |
| :type: :obj:`basestring` |
| """ |
| |
| @object_field(Description) |
| def description(self): |
| """ |
| The optional description of the Capability definition. |
| |
| :type: :class:`Description` |
| """ |
| |
| @object_dict_field(PropertyDefinition) |
| def properties(self): |
| """ |
| An optional list of property definitions for the Capability definition. |
| |
| :type: {:obj:`basestring`: :class:`PropertyDefinition`} |
| """ |
| |
| @object_dict_field(AttributeDefinition) |
| def attributes(self): |
| """ |
| An optional list of attribute definitions for the Capability definition. |
| |
| :type: {:obj:`basestring`: :class:`AttributeDefinition`} |
| """ |
| |
| @field_validator(list_type_validator('node type', convert_name_to_full_type_name, |
| 'node_types')) |
| @primitive_list_field(str) |
| def valid_source_types(self): |
| """ |
| An optional list of one or more valid names of Node Types that are supported as valid |
| sources of any relationship established to the declared Capability Type. |
| |
| :type: [:obj:`basestring`] |
| """ |
| |
| @field_getter(data_type_class_getter(Range)) |
| @primitive_field() |
| def occurrences(self): |
| """ |
| The optional minimum and maximum occurrences for the capability. By default, an exported |
| Capability should allow at least one relationship to be formed with it with a maximum of |
| ``UNBOUNDED`` relationships. |
| |
| Note: the keyword ``UNBOUNDED`` is also supported to represent any positive integer. |
| |
| ARIA NOTE: The spec seems wrong here: the implied default should be ``[0,UNBOUNDED]``, not |
| ``[1,UNBOUNDED]``, otherwise it would imply that at 1 least one relationship *must* be |
| formed. |
| |
| :type: :class:`Range` |
| """ |
| |
| @cachedmethod |
| def _get_type(self, context): |
| return get_type_by_name(context, self.type, 'capability_types') |
| |
| @cachedmethod |
| def _get_parent(self, context): |
| container_parent = self._container._get_parent(context) |
| container_parent_capabilities = container_parent._get_capabilities(context) \ |
| if container_parent is not None else None |
| return container_parent_capabilities.get(self._name) \ |
| if container_parent_capabilities is not None else None |
| |
| def _validate(self, context): |
| super(CapabilityDefinition, self)._validate(context) |
| occurrences = self.occurrences |
| if (occurrences is not None) and ((occurrences.value[0] < 0) or \ |
| ((occurrences.value[1] != 'UNBOUNDED') and (occurrences.value[1] < 0))): |
| context.validation.report( |
| 'capability definition "{0}" occurrences range includes negative integers: {1}' |
| .format(self._name, safe_repr(occurrences)), |
| locator=self._locator, level=Issue.BETWEEN_TYPES) |