# 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.parser import implements_specification 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 `__ """ @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 `__ """ @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', 'tosca-simple-1.0') class ParameterDefinition(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 `__ """ @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. :type: :obj:`basestring` """ @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. """ @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 `__ """ @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 `__ """ @field_validator(type_validator('interface type', convert_name_to_full_type_name, 'interface_types')) @primitive_field(str) 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) if self.operations: for operation in self.operations.itervalues(): # pylint: disable=no-member operation._validate(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. :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 `__ """ @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) @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 `__ """ @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