http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/data.yaml ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/data.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/data.yaml new file mode 100644 index 0000000..97467ba --- /dev/null +++ b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/data.yaml @@ -0,0 +1,91 @@ +# 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. + +data_types: + + tosca.datatypes.compute.Container.Architecture.CPUAllocation: + _extensions: + shorthand_name: Container.Architecture.CPUAllocation # seems to be a mistake in the spec; the norm is to add a "Container.Architecture." prefix + type_qualified_name: tosca:Container.Architecture.CPUAllocation + specification: tosca-simple-nfv-1.0 + specification_section: 8.3.1 + description: >- + Granular CPU allocation requirements for NFV workloads. + derived_from: tosca.datatypes.Root + properties: + cpu_affinity: + description: >- + Describes whether vCPU need to be pinned to dedicated CPU core or shared dynamically. + type: string + constraints: + - valid_values: [ shared, dedicated ] + required: false + thread_allocation: + description: >- + Describe thread allocation requirement. + type: string + constraints: + - valid_values: [ avoid, isolate, separate, prefer ] + required: false + socket_count: + description: >- + Number of CPU sockets. + type: integer + required: false + core_count: + description: >- + Number of cores per socket. + type: integer + required: false + thread_count: + description: >- + Number of threads per core. + type: integer + required: false + + tosca.datatypes.compute.Container.Architecture.NUMA: + _extensions: + shorthand_name: Container.Architecture.NUMA # seems to be a mistake in the spec; the norm is to add a "Container.Architecture." prefix + type_qualified_name: tosca:Container.Architecture.NUMA + specification: tosca-simple-nfv-1.0 + specification_section: 8.3.2 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc447714697' + description: >- + Granular Non-Uniform Memory Access (NUMA) topology requirements for NFV workloads. + derived_from: tosca.datatypes.Root + properties: + id: + description: >- + CPU socket identifier. + type: integer + constraints: + - greater_or_equal: 0 + required: false + vcpus: + description: >- + List of specific host cpu numbers within a NUMA socket complex. + + TODO: need a new base type, with non-overlapping, positive value validation (exclusivity), + type: map + entry_schema: + type: integer + required: false + mem_size: + description: >- + Size of memory allocated from this NUMA memory bank. + type: scalar-unit.size + constraints: + - greater_or_equal: 0 MB + required: false
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/groups.yaml ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/groups.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/groups.yaml new file mode 100644 index 0000000..4a01519 --- /dev/null +++ b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/groups.yaml @@ -0,0 +1,56 @@ +# 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. + +group_types: + + tosca.groups.nfv.VNFFG: + _extensions: + shorthand_name: VNFFG # the spec must be mistaken here, says "VL" + type_qualified_name: tosca:VNFFG + specification: tosca-simple-nfv-1.0 + specification_section: 10.6.1 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc447714727' + description: >- + The NFV VNFFG group type represents a logical VNF forwarding graph entity as defined by [ETSI GS NFV-MAN 001 v1.1.1]. + derived_from: tosca.groups.Root + properties: + vendor: + description: >- + Specify the vendor generating this VNFFG. + type: string + version: + description: >- + Specify the identifier (e.g. name), version, and description of service this VNFFG is describing. + type: string + number_of_endpoints: + description: >- + Count of the external endpoints included in this VNFFG, to form an index. + type: integer + dependent_virtual_link: + description: >- + Reference to a list of VLD used in this Forwarding Graph. + type: list + entry_schema: string + connection_point: + description: >- + Reference to Connection Points forming the VNFFG. + type: list + entry_schema: string + constituent_vnfs: + description: >- + Reference to a list of VNFD used in this VNF Forwarding Graph. + type: list + entry_schema: string + members: [ tosca.nodes.nfv.FP ] http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/nodes.yaml ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/nodes.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/nodes.yaml new file mode 100644 index 0000000..5b9a653 --- /dev/null +++ b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/nodes.yaml @@ -0,0 +1,183 @@ +# 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. + +node_types: + + tosca.nodes.nfv.VNF: + _extensions: + shorthand_name: VNF # ommitted in the spec (seems to be a mistake) + type_qualified_name: tosca:VNF + specification: tosca-simple-nfv-1.0 + specification_section: 8.5.1 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc379455076' + description: >- + The NFV VNF Node Type represents a Virtual Network Function as defined by [ETSI GS NFV-MAN 001 v1.1.1]. It is the default + type that all other VNF Node Types derive from. This allows for all VNF nodes to have a consistent set of features for + modeling and management (e.g., consistent definitions for requirements, capabilities and lifecycle interfaces). + derived_from: tosca.nodes.Root + properties: + id: + description: >- + ID of this VNF. + type: string + vendor: + description: >- + Name of the vendor who generate this VNF. + type: string + version: + description: >- + Version of the software for this VNF. + type: string + requirements: + - virtual_link: + capability: tosca.capabilities.nfv.VirtualLinkable + relationship: tosca.relationships.nfv.VirtualLinksTo + + tosca.nodes.nfv.VDU: + _extensions: + shorthand_name: VDU + type_qualified_name: tosca:VDU + specification: tosca-simple-nfv-1.0 + specification_section: 8.5.2 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc419290242' + description: >- + The NFV vdu node type represents a logical vdu entity as defined by [ETSI GS NFV-MAN 001 v1.1.1]. + derived_from: tosca.nodes.Root + capabilities: + nfv_compute: + type: tosca.capabilities.Compute.Container.Architecture + virtual_binding: + type: tosca.capabilities.nfv.VirtualBindable + monitoring_parameter: + type: tosca.capabilities.nfv.Metric + + tosca.nodes.nfv.CP: + _extensions: + shorthand_name: CP + type_qualified_name: tosca:CP + specification: tosca-simple-nfv-1.0 + specification_section: 8.5.3 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc419290245' + description: >- + The NFV CP node represents a logical connection point entity as defined by [ETSI GS NFV-MAN 001 v1.1.1]. A connection point + may be, for example, a virtual port, a virtual NIC address, a physical port, a physical NIC address or the endpoint of an IP + VPN enabling network connectivity. It is assumed that each type of connection point will be modeled using subtypes of the CP + type. + derived_from: tosca.nodes.network.Port + properties: + type: + description: >- + This may be, for example, a virtual port, a virtual NIC address, a SR-IOV port, a physical port, a physical NIC address + or the endpoint of an IP VPN enabling network connectivity. + type: string + anti_spoof_protection: + description: >- + Indicates of whether anti-spoofing rule need to be enabled for this vNIC. This is applicable only when CP type is virtual + NIC (vPort). + type: boolean + required: false + attributes: + address: + description: >- + The actual virtual NIC address that is been assigned when instantiating the connection point. + type: string + requirements: + - virtual_link: + capability: tosca.capabilities.nfv.VirtualLinkable + relationship: tosca.relationships.nfv.VirtualLinksTo + - virtual_binding: + capability: tosca.capabilities.nfv.VirtualBindable + relationship: tosca.relationships.nfv.VirtualBindsTo + + tosca.nodes.nfv.FP: + _extensions: + shorthand_name: FP # the spec must be mistaken here, says "VL" + type_qualified_name: tosca:FP + specification: tosca-simple-nfv-1.0 + specification_section: 10.5.1 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc447714722' + description: >- + The NFV FP node type represents a logical network forwarding path entity as defined by [ETSI GS NFV-MAN 001 v1.1.1]. + derived_from: tosca.nodes.Root + properties: + policy: + description: >- + A policy or rule to apply to the NFP + type: string + required: false + requirements: + - forwarder: + capability: tosca.capabilities.nfv.Forwarder + + # + # Virtual link + # + + tosca.nodes.nfv.VL: + _extensions: + shorthand_name: VL + type_qualified_name: tosca:VL + specification: tosca-simple-nfv-1.0 + specification_section: 9.1 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc419290251' + description: >- + The NFV VL node type represents a logical virtual link entity as defined by [ETSI GS NFV-MAN 001 v1.1.1]. It is the default + type from which all other virtual link types derive. + derived_from: tosca.nodes.network.Network + properties: + vendor: + description: >- + Vendor generating this VLD. + type: string + capabilities: + virtual_linkable: + type: tosca.capabilities.nfv.VirtualLinkable + + tosca.nodes.nfv.VL.ELine: + _extensions: + shorthand_name: VL.ELine # ommitted in the spec (seems to be a mistake) + type_qualified_name: tosca:VL.ELine + specification: tosca-simple-nfv-1.0 + specification_section: 9.2 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc419290256' + description: >- + The NFV VL.ELine node represents an E-Line virtual link entity. + derived_from: tosca.nodes.nfv.VL + capabilities: + virtual_linkable: + type: tosca.capabilities.nfv.VirtualLinkable + occurrences: [ 2, UNBOUNDED ] # the spec is wrong here, must be a range + + tosca.nodes.nfv.VL.ELAN: + _extensions: + shorthand_name: VL.ELAN # ommitted in the spec (seems to be a mistake) + type_qualified_name: tosca:VL.ELAN + specification: tosca-simple-nfv-1.0 + specification_section: 9.3 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc419290257' + description: >- + The NFV VL.ELan node represents an E-LAN virtual link entity. + derived_from: tosca.nodes.network.Network + + tosca.nodes.nfv.VL.ETree: + _extensions: + shorthand_name: VL.ETree # ommitted in the spec (seems to be a mistake) + type_qualified_name: tosca:VL.ETree + specification: tosca-simple-nfv-1.0 + specification_section: 9.4 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc419290258' + description: >- + The NFV VL.ETree node represents an E-Tree virtual link entity. + derived_from: tosca.nodes.nfv.VL http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/relationships.yaml ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/relationships.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/relationships.yaml new file mode 100644 index 0000000..b745735 --- /dev/null +++ b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/relationships.yaml @@ -0,0 +1,64 @@ +# 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. + +relationship_types: + + tosca.relationships.nfv.VirtualBindsTo: + _extensions: + shorthand_name: VirtualBindsTo + type_qualified_name: tosca:VirtualBindsTo + specification: tosca-simple-nfv-1.0 + specification_section: 8.4.1 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc419290234' + description: >- + This relationship type represents an association relationship between VDU and CP node types. + derived_from: tosca.relationships.DependsOn + valid_target_types: [ tosca.capabilities.nfv.VirtualBindable ] + + tosca.relationships.nfv.Monitor: + _extensions: + shorthand_name: Monitor + type_qualified_name: tosca:Monitor + specification: tosca-simple-nfv-1.0 + specification_section: 8.4.2 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc418607880' + description: >- + This relationship type represents an association relationship to the Metric capability of VDU node types. + derived_from: tosca.relationships.ConnectsTo + valid_target_types: [ tosca.capabilities.nfv.Metric ] + + tosca.relationships.nfv.ForwardsTo: + _extensions: + shorthand_name: ForwardsTo + type_qualified_name: tosca:ForwardsTo + specification: tosca-simple-nfv-1.0 + specification_section: 10.4.1 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc447714720' + description: >- + This relationship type represents a traffic flow between two connection point node types. + derived_from: tosca.relationships.Root + valid_target_types: [ tosca.capabilities.nfv.Forwarder ] + + tosca.relationships.nfv.VirtualLinksTo: + _extensions: + shorthand_name: VirtualLinksTo + type_qualified_name: tosca:VirtualLinksTo + specification: tosca-simple-nfv-1.0 + specification_section: 11.4.1 + specification_url: 'http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html#_Toc447714737' + description: >- + This relationship type represents an association relationship between VNFs and VL node types. + derived_from: tosca.relationships.DependsOn + valid_target_types: [ tosca.capabilities.nfv.VirtualLinkable ] http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/tosca-simple-nfv-1.0.yaml ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/tosca-simple-nfv-1.0.yaml b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/tosca-simple-nfv-1.0.yaml new file mode 100644 index 0000000..911ff3b --- /dev/null +++ b/extensions/aria_extension_tosca/profiles/tosca-simple-nfv-1.0/tosca-simple-nfv-1.0.yaml @@ -0,0 +1,21 @@ +# 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. + +imports: + - capabilities.yaml + - data.yaml + - groups.yaml + - nodes.yaml + - relationships.yaml http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/simple_nfv_v1_0/__init__.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_nfv_v1_0/__init__.py b/extensions/aria_extension_tosca/simple_nfv_v1_0/__init__.py new file mode 100644 index 0000000..313e3ef --- /dev/null +++ b/extensions/aria_extension_tosca/simple_nfv_v1_0/__init__.py @@ -0,0 +1,19 @@ +# 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 .presenter import ToscaSimpleNfvPresenter1_0 + +__all__ = ( + 'ToscaSimpleNfvPresenter1_0',) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py b/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py new file mode 100644 index 0000000..e26ca7b --- /dev/null +++ b/extensions/aria_extension_tosca/simple_nfv_v1_0/presenter.py @@ -0,0 +1,44 @@ +# 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.parser.utils import (FrozenList, EMPTY_READ_ONLY_LIST, cachedmethod) + +from ..simple_v1_0 import ToscaSimplePresenter1_0 + +class ToscaSimpleNfvPresenter1_0(ToscaSimplePresenter1_0): # pylint: disable=invalid-name + """ + ARIA presenter for the `TOSCA Simple Profile for NFV v1.0 csd03 <http://docs.oasis-open.org + /tosca/tosca-nfv/v1.0/csd03/tosca-nfv-v1.0-csd03.html>`__. + + Supported :code:`tosca_definitions_version` values: + + * :code:`tosca_simple_profile_for_nfv_1_0` + """ + + DSL_VERSIONS = ('tosca_simple_profile_for_nfv_1_0',) + ALLOWED_IMPORTED_DSL_VERSIONS = ('tosca_simple_yaml_1_0', 'tosca_simple_profile_for_nfv_1_0') + SIMPLE_PROFILE_FOR_NFV_LOCATION = 'tosca-simple-nfv-1.0/tosca-simple-nfv-1.0.yaml' + + # Presenter + + @cachedmethod + def _get_import_locations(self, context): + import_locations = [] + if context.presentation.import_profile: + import_locations += (self.SIMPLE_PROFILE_LOCATION, self.SIMPLE_PROFILE_FOR_NFV_LOCATION) + imports = self._get('service_template', 'imports') + if imports: + import_locations += [i.file for i in imports] + return FrozenList(import_locations) if import_locations else EMPTY_READ_ONLY_LIST http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/simple_v1_0/__init__.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/__init__.py b/extensions/aria_extension_tosca/simple_v1_0/__init__.py new file mode 100644 index 0000000..29df362 --- /dev/null +++ b/extensions/aria_extension_tosca/simple_v1_0/__init__.py @@ -0,0 +1,100 @@ +# 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 .presenter import ToscaSimplePresenter1_0 +from .assignments import (PropertyAssignment, OperationAssignment, InterfaceAssignment, + RelationshipAssignment, RequirementAssignment, AttributeAssignment, + CapabilityAssignment, ArtifactAssignment) +from .definitions import (PropertyDefinition, AttributeDefinition, ParameterDefinition, + OperationDefinition, InterfaceDefinition, RelationshipDefinition, + RequirementDefinition, CapabilityDefinition) +from .filters import CapabilityFilter, NodeFilter +from .misc import (Description, MetaData, Repository, Import, ConstraintClause, EntrySchema, + OperationImplementation, SubstitutionMappingsRequirement, + SubstitutionMappingsCapability, SubstitutionMappings) +from .templates import (NodeTemplate, RelationshipTemplate, GroupTemplate, PolicyTemplate, + TopologyTemplate, ServiceTemplate) +from .types import (ArtifactType, DataType, CapabilityType, InterfaceType, RelationshipType, + NodeType, GroupType, PolicyType) +from .data_types import (Timestamp, Version, Range, List, Map, ScalarSize, ScalarTime, + ScalarFrequency) +from .functions import (Concat, Token, GetInput, GetProperty, GetAttribute, GetOperationOutput, + GetNodesOfType, GetArtifact) + +MODULES = ( + 'modeling', + 'presentation') + +__all__ = ( + 'MODULES', + 'ToscaSimplePresenter1_0', + 'PropertyAssignment', + 'OperationAssignment', + 'InterfaceAssignment', + 'RelationshipAssignment', + 'RequirementAssignment', + 'AttributeAssignment', + 'CapabilityAssignment', + 'ArtifactAssignment', + 'PropertyDefinition', + 'AttributeDefinition', + 'ParameterDefinition', + 'OperationDefinition', + 'InterfaceDefinition', + 'RelationshipDefinition', + 'RequirementDefinition', + 'CapabilityDefinition', + 'CapabilityFilter', + 'NodeFilter', + 'Description', + 'MetaData', + 'Repository', + 'Import', + 'ConstraintClause', + 'EntrySchema', + 'OperationImplementation', + 'SubstitutionMappingsRequirement', + 'SubstitutionMappingsCapability', + 'SubstitutionMappings', + 'NodeTemplate', + 'RelationshipTemplate', + 'GroupTemplate', + 'PolicyTemplate', + 'TopologyTemplate', + 'ServiceTemplate', + 'ArtifactType', + 'DataType', + 'CapabilityType', + 'InterfaceType', + 'RelationshipType', + 'NodeType', + 'GroupType', + 'PolicyType', + 'Timestamp', + 'Version', + 'Range', + 'List', + 'Map', + 'ScalarSize', + 'ScalarTime', + 'ScalarFrequency', + 'Concat', + 'Token', + 'GetInput', + 'GetProperty', + 'GetAttribute', + 'GetOperationOutput', + 'GetNodesOfType', + 'GetArtifact') http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/simple_v1_0/assignments.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/assignments.py b/extensions/aria_extension_tosca/simple_v1_0/assignments.py new file mode 100644 index 0000000..6f42d79 --- /dev/null +++ b/extensions/aria_extension_tosca/simple_v1_0/assignments.py @@ -0,0 +1,414 @@ +# 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.parser import dsl_specification +from aria.parser.presentation import (AsIsPresentation, has_fields, allow_unknown_fields, + short_form_field, primitive_field, object_field, + object_dict_field, object_dict_unknown_fields, + field_validator, type_validator) +from aria.parser.utils import FrozenDict, cachedmethod + +from .filters import NodeFilter +from .misc import Description, OperationImplementation +from .modeling.properties import get_assigned_and_defined_property_values +from .presentation.extensible import ExtensiblePresentation +from .presentation.field_validators import (node_template_or_type_validator, + relationship_template_or_type_validator, + capability_definition_or_type_validator, + node_filter_validator) +from .presentation.types import (convert_shorthand_to_full_type_name, + get_type_by_full_or_shorthand_name) + +@dsl_specification('3.5.9', 'tosca-simple-1.0') +class PropertyAssignment(AsIsPresentation): + """ + This section defines the grammar for assigning values to named properties within TOSCA Node and + Relationship templates that are defined in their corresponding named types. + + 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_VALUE_ASSIGNMENT>`__ + """ + +@short_form_field('implementation') +@has_fields +@dsl_specification('3.5.13-2', 'tosca-simple-1.0') +class OperationAssignment(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. + + :rtype: :class:`Description` + """ + + @object_field(OperationImplementation) + def implementation(self): + """ + The optional implementation artifact name (e.g., a script file name within a TOSCA CSAR + file). + + :rtype: :class:`OperationImplementation` + """ + + @object_dict_field(PropertyAssignment) + def inputs(self): + """ + The optional list of input property assignments (i.e., parameters assignments) for operation + definitions that are within TOSCA Node or Relationship Template definitions. This includes + when operation definitions are included as part of a Requirement assignment in a Node + Template. + + :rtype: dict of str, :class:`PropertyAssignment` + """ + +@allow_unknown_fields +@has_fields +@dsl_specification('3.5.14-2', 'tosca-simple-1.0') +class InterfaceAssignment(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>`__ + """ + + @object_dict_field(PropertyAssignment) + def inputs(self): + """ + The optional list of input property assignments (i.e., parameters assignments) for interface + definitions that are within TOSCA Node or Relationship Template definitions. This includes + when interface definitions are referenced as part of a Requirement assignment in a Node + Template. + + :rtype: dict of str, :class:`PropertyAssignment` + """ + + @object_dict_unknown_fields(OperationAssignment) + def operations(self): + """ + :rtype: dict of str, :class:`OperationAssignment` + """ + + @cachedmethod + def _get_type(self, context): + the_type = self._container._get_type(context) + + if isinstance(the_type, tuple): + # In RelationshipAssignment + the_type = the_type[0] # This could be a RelationshipTemplate + + interface_definitions = the_type._get_interfaces(context) \ + if the_type is not None else None + interface_definition = interface_definitions.get(self._name) \ + if interface_definitions is not None else None + return interface_definition._get_type(context) \ + if interface_definition is not None else None + + def _validate(self, context): + super(InterfaceAssignment, 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 RelationshipAssignment(ExtensiblePresentation): + @field_validator(relationship_template_or_type_validator) + @primitive_field(str) + def type(self): + """ + The optional reserved keyname used to provide the name of the Relationship Type for the + requirement assignment's relationship keyname. + + :rtype: str + """ + + @object_dict_field(PropertyAssignment) + def properties(self): + """ + ARIA NOTE: This field is not mentioned in the spec, but is implied. + + :rtype: dict of str, :class:`PropertyAssignment` + """ + + @object_dict_field(InterfaceAssignment) + def interfaces(self): + """ + The optional reserved keyname used to reference declared (named) interface definitions of + the corresponding Relationship Type in order to provide Property assignments for these + interfaces or operations of these interfaces. + + :rtype: dict of str, :class:`InterfaceAssignment` + """ + + @cachedmethod + def _get_type(self, context): + type_name = self.type + if type_name is not None: + the_type = context.presentation.get_from_dict('service_template', 'topology_template', + 'relationship_templates', type_name) + if the_type is not None: + return the_type, 'relationship_template' + the_type = get_type_by_full_or_shorthand_name(context, type_name, 'relationship_types') + if the_type is not None: + return the_type, 'relationship_type' + return None, None + +@short_form_field('node') +@has_fields +@dsl_specification('3.7.2', 'tosca-simple-1.0') +class RequirementAssignment(ExtensiblePresentation): + """ + A Requirement assignment allows template authors to provide either concrete names of TOSCA + templates or provide abstract selection criteria for providers to use to find matching TOSCA + templates that are used to fulfill a named requirement's declared TOSCA Node 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_REQUIREMENT_ASSIGNMENT>`__ + """ + + # The example in 3.7.2.2.2 shows unknown fields in addition to these, but is this a mistake? + + @field_validator(capability_definition_or_type_validator) + @primitive_field(str) + def capability(self): + """ + The optional reserved keyname used to provide the name of either a: + + * Capability definition within a target node template that can fulfill the requirement. + * Capability Type that the provider will use to select a type-compatible target node + template to fulfill the requirement at runtime. + + :rtype: str + """ + + @field_validator(node_template_or_type_validator) + @primitive_field(str) + def node(self): + """ + The optional reserved keyname used to identify the target node of a relationship. + Specifically, it is used to provide either a: + + * Node Template name that can fulfill the target node requirement. + * Node Type name that the provider will use to select a type-compatible node template to + fulfill the requirement at runtime. + + :rtype: str + """ + + @object_field(RelationshipAssignment) + def relationship(self): + """ + The optional reserved keyname used to provide the name of either a: + + * Relationship Template to use to relate the source node to the (capability in the) target + node when fulfilling the requirement. + * Relationship Type that the provider will use to select a type-compatible relationship + template to relate the source node to the target node at runtime. + + :rtype: :class:`RequirementRelationshipAssignment` + """ + + @field_validator(node_filter_validator) + @object_field(NodeFilter) + def node_filter(self): + """ + The optional filter definition that TOSCA orchestrators or providers would use to select a + type-compatible target node that can fulfill the associated abstract requirement at runtime. + + :rtype: :class:`NodeFilter` + """ + + @cachedmethod + def _get_node(self, context): + node_name = self.node + if node_name is not None: + node = context.presentation.get_from_dict('service_template', 'topology_template', + 'node_templates', node_name) + if node is not None: + return node, 'node_template' + node = context.presentation.get_from_dict('service_template', 'node_types', node_name) + if node is not None: + return node, 'node_type' + return None, None + + @cachedmethod + def _get_capability(self, context): + capability = self.capability + + if capability is not None: + node, node_variant = self._get_node(context) + if node_variant == 'node_template': + capabilities = node._get_capabilities(context) + if capability in capabilities: + return capabilities[capability], 'capability_assignment' + else: + capability_types = context.presentation.get_from_dict('service_template', + 'capability_types') + if (capability_types is not None) and (capability in capability_types): + return capability_types[capability], 'capability_type' + + return None, None + +@dsl_specification('3.5.11', 'tosca-simple-1.0') +class AttributeAssignment(AsIsPresentation): + """ + This section defines the grammar for assigning values to named attributes within TOSCA Node and + Relationship templates which are defined in their corresponding named types. + + 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_VALUE_ASSIGNMENT>`__ + """ + +@has_fields +@dsl_specification('3.7.1', 'tosca-simple-1.0') +class CapabilityAssignment(ExtensiblePresentation): + """ + A capability assignment allows node template authors to assign values to properties and + attributes for a named capability definition that is part of a Node Template's type definition. + + 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_ASSIGNMENT>`__ + """ + + @object_dict_field(PropertyAssignment) + def properties(self): + """ + An optional list of property definitions for the Capability definition. + + :rtype: dict of str, :class:`PropertyAssignment` + """ + + @object_dict_field(AttributeAssignment) + def attributes(self): + """ + An optional list of attribute definitions for the Capability definition. + + :rtype: dict of str, :class:`AttributeAssignment` + """ + + @cachedmethod + def _get_definition(self, context): + node_type = self._container._get_type(context) + capability_definitions = node_type._get_capabilities(context) \ + if node_type is not None else None + return capability_definitions.get(self._name) \ + if capability_definitions is not None else None + + @cachedmethod + def _get_type(self, context): + capability_definition = self._get_definition(context) + return capability_definition._get_type(context) \ + if capability_definition is not None else None + +@has_fields +@dsl_specification('3.5.6', 'tosca-simple-1.0') +class ArtifactAssignment(ExtensiblePresentation): + """ + An artifact definition defines a named, typed file that can be associated with Node Type or Node + Template and used by orchestration engine to facilitate deployment and implementation of + interface operations. + + 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_ENTITY_ARTIFACT_DEF>`__ + """ + + @field_validator(type_validator('artifact type', convert_shorthand_to_full_type_name, + 'artifact_types')) + @primitive_field(str, required=True) + def type(self): + """ + The required artifact type for the artifact definition. + + :rtype: str + """ + + @primitive_field(str, required=True) + def file(self): + """ + The required URI string (relative or absolute) which can be used to locate the artifact's + file. + + :rtype: str + """ + + @field_validator(type_validator('repository', 'repositories')) + @primitive_field(str) + def repository(self): + """ + The optional name of the repository definition which contains the location of the external + repository that contains the artifact. The artifact is expected to be referenceable by its + file URI within the repository. + + :rtype: str + """ + + @object_field(Description) + def description(self): + """ + The optional description for the artifact definition. + + :rtype: :class:`Description` + """ + + @primitive_field(str) + def deploy_path(self): + """ + The file path the associated file would be deployed into within the target node's container. + + :rtype: str + """ + + @object_dict_field(PropertyAssignment) + def properties(self): + """ + ARIA NOTE: This field is not mentioned in the spec, but is implied. + + :rtype: dict of str, :class:`PropertyAssignment` + """ + + @cachedmethod + def _get_type(self, context): + return get_type_by_full_or_shorthand_name(context, self.type, 'artifact_types') + + @cachedmethod + def _get_repository(self, context): + return context.presentation.get_from_dict('service_template', 'repositories', + self.repository) + + @cachedmethod + def _get_property_values(self, context): + return FrozenDict(get_assigned_and_defined_property_values(context, self)) + + @cachedmethod + def _validate(self, context): + super(ArtifactAssignment, self)._validate(context) + self._get_property_values(context) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/simple_v1_0/data_types.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/data_types.py b/extensions/aria_extension_tosca/simple_v1_0/data_types.py new file mode 100644 index 0000000..40e1e21 --- /dev/null +++ b/extensions/aria_extension_tosca/simple_v1_0/data_types.py @@ -0,0 +1,536 @@ +# 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. + +import re +from collections import OrderedDict +from functools import total_ordering +from datetime import datetime, tzinfo, timedelta + +from aria.parser import dsl_specification +from aria.parser.utils import StrictDict, safe_repr + +from .modeling.data_types import (coerce_to_data_type_class, report_issue_for_bad_format, + coerce_value) + +class Timezone(tzinfo): + """ + Timezone as fixed offset in hours and minutes east of UTC. + """ + + def __init__(self, hours=0, minutes=0): + super(Timezone, self).__init__() + self._offset = timedelta(hours=hours, minutes=minutes) + + def utcoffset(self, dt): # pylint: disable=unused-argument + return self._offset + + def tzname(self, dt): # pylint: disable=unused-argument + return str(self._offset) + + def dst(self, dt): # pylint: disable=unused-argument + return Timezone._ZERO + + _ZERO = timedelta(0) + +UTC = Timezone() + +@total_ordering +@dsl_specification('timestamp', 'yaml-1.1') +class Timestamp(object): + ''' + TOSCA timestamps follow the YAML specification, which in turn is a variant of ISO8601. + + Long forms and short forms (without time of day and assuming UTC timezone) are supported for + parsing. The canonical form (for rendering) matches the long form at the UTC timezone. + + See the `Timestamp Language-Independent Type for YAML Version 1.1 (Working Draft 2005-01-18) + <http://yaml.org/type/timestamp.html>`__ + ''' + + REGULAR_SHORT = r'^(?P<year>[0-9][0-9][0-9][0-9])-(?P<month>[0-9][0-9])-(?P<day>[0-9][0-9])$' + REGULAR_LONG = \ + r'^(?P<year>[0-9][0-9][0-9][0-9])-(?P<month>[0-9][0-9]?)-(?P<day>[0-9][0-9]?)' + \ + r'([Tt]|[ \t]+)' \ + r'(?P<hour>[0-9][0-9]?):(?P<minute>[0-9][0-9]):(?P<second>[0-9][0-9])' + \ + r'(?P<fraction>\.[0-9]*)?' + \ + r'(([ \t]*)Z|(?P<tzhour>[-+][0-9][0-9])?(:(?P<tzminute>[0-9][0-9])?)?)?$' + CANONICAL = '%Y-%m-%dT%H:%M:%S' + + def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument + value = str(value) + match = re.match(Timestamp.REGULAR_SHORT, value) + if match is not None: + # Parse short form + year = int(match.group('year')) + month = int(match.group('month')) + day = int(match.group('day')) + self.value = datetime(year, month, day, tzinfo=UTC) + else: + match = re.match(Timestamp.REGULAR_LONG, value) + if match is not None: + # Parse long form + year = int(match.group('year')) + month = int(match.group('month')) + day = int(match.group('day')) + hour = match.group('hour') + if hour is not None: + hour = int(hour) + minute = match.group('minute') + if minute is not None: + minute = int(minute) + second = match.group('second') + if second is not None: + second = int(second) + fraction = match.group('fraction') + if fraction is not None: + fraction = int(float(fraction) * 1000000.0) # convert to microseconds + tzhour = match.group('tzhour') + if tzhour is not None: + tzhour = int(tzhour) + else: + tzhour = 0 + tzminute = match.group('tzminute') + if tzminute is not None: + tzminute = int(tzminute) + else: + tzminute = 0 + self.value = datetime(year, month, day, hour, minute, second, fraction, + Timezone(tzhour, tzminute)) + else: + raise ValueError( + 'timestamp must be formatted as YAML ISO8601 variant or "YYYY-MM-DD": %s' + % safe_repr(value)) + + @property + def as_datetime_utc(self): + return self.value.astimezone(UTC) + + @property + def as_raw(self): + return self.__str__() + + def __str__(self): + the_datetime = self.as_datetime_utc + return '%s%sZ' \ + % (the_datetime.strftime(Timestamp.CANONICAL), Timestamp._fraction_as_str(the_datetime)) + + def __repr__(self): + return repr(self.__str__()) + + def __eq__(self, timestamp): + if not isinstance(timestamp, Timestamp): + return False + return self.value == timestamp.value + + def __lt__(self, timestamp): + return self.value < timestamp.value + + @staticmethod + def _fraction_as_str(the_datetime): + return '{0:g}'.format(the_datetime.microsecond / 1000000.0).lstrip('0') + +@total_ordering +@dsl_specification('3.2.2', 'tosca-simple-1.0') +class Version(object): + """ + TOSCA supports the concept of "reuse" of type definitions, as well as template definitions which + could be version and change over time. It is important to provide a reliable, normative means to + represent a version string which enables the comparison and management of types and templates + over time. Therefore, the TOSCA TC intends to provide a normative version type (string) for this + purpose in future Working Drafts of this specification. + + 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 + #TYPE_TOSCA_VERSION>`__ + """ + + REGULAR = \ + r'^(?P<major>\d+)\.(?P<minor>\d+)(\.(?P<fix>\d+)' + \ + r'((\.(?P<qualifier>\d+))(\-(?P<build>\d+))?)?)?$' + + @staticmethod + def key(version): + """ + Key method for fast sorting. + """ + return (version.major, version.minor, version.fix, version.qualifier, version.build) + + def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument + str_value = str(value) + match = re.match(Version.REGULAR, str_value) + if match is None: + raise ValueError( + 'version must be formatted as <major_version>.<minor_version>' + '[.<fix_version>[.<qualifier>[-<build_version]]]: %s' + % safe_repr(value)) + + self.value = str_value + + self.major = match.group('major') + self.major = int(self.major) + self.minor = match.group('minor') + self.minor = int(self.minor) + self.fix = match.group('fix') + if self.fix is not None: + self.fix = int(self.fix) + self.qualifier = match.group('qualifier') + if self.qualifier is not None: + self.qualifier = int(self.qualifier) + self.build = match.group('build') + if self.build is not None: + self.build = int(self.build) + + @property + def as_raw(self): + return self.value + + def __str__(self): + return self.value + + def __repr__(self): + return repr(self.__str__()) + + def __eq__(self, version): + if not isinstance(version, Version): + return False + return (self.major, self.minor, self.fix, self.qualifier, self.build) == \ + (version.major, version.minor, version.fix, version.qualifier, version.build) + + def __lt__(self, version): + if self.major < version.major: + return True + elif self.major == version.major: + if self.minor < version.minor: + return True + elif self.minor == version.minor: + if self.fix < version.fix: + return True + elif self.fix == version.fix: + if self.qualifier < version.qualifier: + return True + elif self.qualifier == version.qualifier: + if self.build < version.build: + return True + return False + +@dsl_specification('3.2.3', 'tosca-simple-1.0') +class Range(object): + """ + The range type can be used to define numeric ranges with a lower and upper boundary. For + example, this allows for specifying a range of ports to be opened in a firewall. + + 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 + #TYPE_TOSCA_RANGE>`__ + """ + + def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument + if not isinstance(value, list): + raise ValueError('range value is not a list: %s' % safe_repr(value)) + if len(value) != 2: + raise ValueError('range value does not have exactly 2 elements: %s' % safe_repr(value)) + + def is_int(v): + return isinstance(v, int) and (not isinstance(v, bool)) # In Python bool is an int + + if not is_int(value[0]): + raise ValueError('lower bound of range is not a valid integer: %s' + % safe_repr(value[0])) + + if value[1] != 'UNBOUNDED': + if not is_int(value[1]): + raise ValueError('upper bound of range is not a valid integer or "UNBOUNDED": %s' + % safe_repr(value[0])) + + if value[0] >= value[1]: + raise ValueError( + 'upper bound of range is not greater than the lower bound: %s >= %s' + % (safe_repr(value[0]), safe_repr(value[1]))) + + self.value = value + + def is_in(self, value): + if value < self.value[0]: + return False + if (self.value[1] != 'UNBOUNDED') and (value > self.value[1]): + return False + return True + + @property + def as_raw(self): + return list(self.value) + +@dsl_specification('3.2.4', 'tosca-simple-1.0') +class List(list): + """ + The list type allows for specifying multiple values for a parameter of property. For example, if + an application allows for being configured to listen on multiple ports, a list of ports could be + configured using the list data 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 + #TYPE_TOSCA_LIST>`__ + """ + + @staticmethod + def _create(context, presentation, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument + if not isinstance(value, list): + raise ValueError('"list" data type value is not a list: %s' % safe_repr(value)) + + entry_schema_type = entry_schema._get_type(context) + entry_schema_constraints = entry_schema.constraints + + the_list = List() + for v in value: + v = coerce_value(context, presentation, entry_schema_type, None, + entry_schema_constraints, v, aspect) + if v is not None: + the_list.append(v) + + return the_list + + # Can't define as property because it's old-style Python class + def as_raw(self): + return list(self) + +@dsl_specification('3.2.5', 'tosca-simple-1.0') +class Map(StrictDict): + """ + The map type allows for specifying multiple values for a parameter of property as a map. In + contrast to the list type, where each entry can only be addressed by its index in the list, + entries in a map are named elements that can be addressed by their keys. + + 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 + #TYPE_TOSCA_MAP>`__ + """ + + @staticmethod + def _create(context, presentation, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument + if not isinstance(value, dict): + raise ValueError('"map" data type value is not a dict: %s' % safe_repr(value)) + + if entry_schema is None: + raise ValueError('"map" data type does not define "entry_schema"') + + entry_schema_type = entry_schema._get_type(context) + entry_schema_constraints = entry_schema.constraints + + the_map = Map() + for k, v in value.iteritems(): + v = coerce_value(context, presentation, entry_schema_type, None, + entry_schema_constraints, v, aspect) + if v is not None: + the_map[k] = v + + return the_map + + def __init__(self, items=None): + super(Map, self).__init__(items, key_class=str) + + # Can't define as property because it's old-style Python class + def as_raw(self): + return OrderedDict(self) + +@total_ordering +@dsl_specification('3.2.6', 'tosca-simple-1.0') +class Scalar(object): + """ + The scalar-unit type can be used to define scalar values along with a unit from the list of + recognized units. + + 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 + #TYPE_TOSCA_SCALAR_UNIT>`__ + """ + + @staticmethod + def key(scalar): + """ + Key method for fast sorting. + """ + return scalar.value + + def __init__(self, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument + str_value = str(value) + match = re.match(self.REGULAR, str_value) # pylint: disable=no-member + if match is None: + raise ValueError('scalar must be formatted as <scalar> <unit>: %s' % safe_repr(value)) + + self.factor = float(match.group('scalar')) + self.unit = match.group('unit') + + unit_lower = self.unit.lower() + unit_size = None + for k, v in self.UNITS.iteritems(): # pylint: disable=no-member + if k.lower() == unit_lower: + self.unit = k + unit_size = v + break + if unit_size is None: + raise ValueError('scalar specified with unsupported unit: %s' % safe_repr(self.unit)) + + self.value = self.TYPE(self.factor * unit_size) # pylint: disable=no-member + + @property + def as_raw(self): + return OrderedDict(( + ('value', self.value), + ('factor', self.factor), + ('unit', self.unit), + ('unit_size', self.UNITS[self.unit]))) # pylint: disable=no-member + + def __str__(self): + return '%s %s' % (self.value, self.UNIT) # pylint: disable=no-member + + def __repr__(self): + return repr(self.__str__()) + + def __eq__(self, scalar): + if isinstance(scalar, Scalar): + value = scalar.value + else: + value = self.TYPE(scalar) # pylint: disable=no-member + return self.value == value + + def __lt__(self, scalar): + if isinstance(scalar, Scalar): + value = scalar.value + else: + value = self.TYPE(scalar) # pylint: disable=no-member + return self.value < value + +@dsl_specification('3.2.6.4', 'tosca-simple-1.0') +class ScalarSize(Scalar): + """ + Integer scalar for counting bytes. + + 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 + #TYPE_TOSCA_SCALAR_UNIT_SIZE>`__ + """ + + # See: http://www.regular-expressions.info/floatingpoint.html + REGULAR = \ + r'^(?P<scalar>[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*(?P<unit>B|kB|KiB|MB|MiB|GB|GiB|TB|TiB)$' + + UNITS = { + 'B': 1, + 'kB': 1000, + 'KiB': 1024, + 'MB': 1000000, + 'MiB': 1048576, + 'GB': 1000000000, + 'GiB': 1073741824, + 'TB': 1000000000000, + 'TiB': 1099511627776} + + TYPE = int + UNIT = 'bytes' + +@dsl_specification('3.2.6.5', 'tosca-simple-1.0') +class ScalarTime(Scalar): + """ + Floating point scalar for counting seconds. + + 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 + #TYPE_TOSCA_SCALAR_UNIT_TIME>`__ + """ + + # See: http://www.regular-expressions.info/floatingpoint.html + REGULAR = r'^(?P<scalar>[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*(?P<unit>ns|us|ms|s|m|h|d)$' + + UNITS = { + 'ns': 0.000000001, + 'us': 0.000001, + 'ms': 0.001, + 's': 1.0, + 'm': 60.0, + 'h': 3600.0, + 'd': 86400.0} + + TYPE = float + UNIT = 'seconds' + +@dsl_specification('3.2.6.6', 'tosca-simple-1.0') +class ScalarFrequency(Scalar): + """ + Floating point scalar for counting cycles per second (Hz). + + 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 + #TYPE_TOSCA_SCALAR_UNIT_FREQUENCY>`__ + """ + + # See: http://www.regular-expressions.info/floatingpoint.html + REGULAR = r'^(?P<scalar>[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)\s*(?P<unit>Hz|kHz|MHz|GHz)$' + + UNITS = { + 'Hz': 1.0, + 'kHz': 1000.0, + 'MHz': 1000000.0, + 'GHz': 1000000000.0} + + TYPE = float + UNIT = 'Hz' + +# +# The following are hooked in the YAML as 'coerce_value' extensions +# + +def coerce_timestamp(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument + return coerce_to_data_type_class(context, presentation, Timestamp, entry_schema, constraints, + value, aspect) + +def coerce_version(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument + return coerce_to_data_type_class(context, presentation, Version, entry_schema, constraints, + value, aspect) + +def coerce_range(context, presentation, the_type, entry_schema, constraints, value, aspect): + if aspect == 'in_range': + # When we're in a "in_range" constraint, the values are *not* themselves ranges, but numbers + try: + return float(value) + except ValueError as e: + report_issue_for_bad_format(context, presentation, the_type, value, aspect, e) + except TypeError as e: + report_issue_for_bad_format(context, presentation, the_type, value, aspect, e) + else: + return coerce_to_data_type_class(context, presentation, Range, entry_schema, constraints, + value, aspect) + +def coerce_list(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument + return coerce_to_data_type_class(context, presentation, List, entry_schema, constraints, + value, aspect) + +def coerce_map_value(context, presentation, the_type, entry_schema, constraints, value, aspect): # pylint: disable=unused-argument + return coerce_to_data_type_class(context, presentation, Map, entry_schema, constraints, value, + aspect) + +def coerce_scalar_unit_size(context, presentation, the_type, entry_schema, constraints, value, # pylint: disable=unused-argument + aspect): + return coerce_to_data_type_class(context, presentation, ScalarSize, entry_schema, constraints, + value, aspect) + +def coerce_scalar_unit_time(context, presentation, the_type, entry_schema, constraints, value, # pylint: disable=unused-argument + aspect): + return coerce_to_data_type_class(context, presentation, ScalarTime, entry_schema, constraints, + value, aspect) + +def coerce_scalar_unit_frequency(context, presentation, the_type, entry_schema, constraints, value, # pylint: disable=unused-argument + aspect): + return coerce_to_data_type_class(context, presentation, ScalarFrequency, entry_schema, + constraints, value, aspect) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8ee1470e/extensions/aria_extension_tosca/simple_v1_0/definitions.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/definitions.py b/extensions/aria_extension_tosca/simple_v1_0/definitions.py new file mode 100644 index 0000000..e595e07 --- /dev/null +++ b/extensions/aria_extension_tosca/simple_v1_0/definitions.py @@ -0,0 +1,503 @@ +# 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.parser import dsl_specification +from aria.parser.utils import (FrozenDict, cachedmethod) +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_shorthand_to_full_type_name, + get_type_by_full_or_shorthand_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 +@dsl_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 :code:`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. + + :rtype: str + """ + + @object_field(Description) + def description(self): + """ + The optional description for the property. + + :rtype: :class:`Description` + """ + + @primitive_field(bool, default=True) + def required(self): + """ + An optional key that declares a property as required (true) or not (false). + + :rtype: 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. + + :rtype: str + """ + + @primitive_field(str, default='supported', allowed=('supported', 'unsupported', 'experimental', + 'deprecated')) + @dsl_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. + + :rtype: str + """ + + @object_list_field(ConstraintClause) + def constraints(self): + """ + The optional list of sequenced constraint clauses for the property. + + :rtype: 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. + + :rtype: str + """ + + @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 +@dsl_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 :code:`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. + + :rtype: str + """ + + @object_field(Description) + def description(self): + """ + The optional description for the attribute. + + :rtype: :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. + + :rtype: str + """ + + @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. + + :rtype: str + """ + + @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. + + :rtype: str + """ + + @cachedmethod + def _get_type(self, context): + return get_data_type(context, self, 'type') + +@has_fields +@dsl_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 <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_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. + + :rtype: str + """ + + @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 +@dsl_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. + + :rtype: :class:`Description` + """ + + @object_field(OperationImplementation) + def implementation(self): + """ + The optional implementation artifact name (e.g., a script file name within a TOSCA CSAR + file). + + :rtype: :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. + + :rtype: dict of str, :class:`PropertyDefinition` + """ + +@allow_unknown_fields +@has_fields +@dsl_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_shorthand_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. + + :rtype: str + """ + + @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. + + :rtype: dict of str, :class:`PropertyDefinition` + """ + + @object_dict_unknown_fields(OperationDefinition) + def operations(self): + """ + :rtype: dict of str, :class:`OperationDefinition` + """ + + @cachedmethod + def _get_type(self, context): + return get_type_by_full_or_shorthand_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): + @field_validator(type_validator('relationship type', convert_shorthand_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. + + :rtype: str + """ + + @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. + + :rtype: list of :class:`InterfaceDefinition` + """ + + @cachedmethod + def _get_type(self, context): + return get_type_by_full_or_shorthand_name(context, self.type, 'relationship_types') + +@short_form_field('capability') +@has_fields +@dsl_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_shorthand_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. + + :rtype: str + """ + + @field_validator(type_validator('node type', convert_shorthand_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. + + :rtype: str + """ + + @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. + + :rtype: :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. + + :rtype: :class:`Range` + """ + + @cachedmethod + def _get_capability_type(self, context): + return get_type_by_full_or_shorthand_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 +@dsl_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_shorthand_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. + + :rtype: str + """ + + @object_field(Description) + def description(self): + """ + The optional description of the Capability definition. + + :rtype: :class:`Description` + """ + + @object_dict_field(PropertyDefinition) + def properties(self): + """ + An optional list of property definitions for the Capability definition. + + :rtype: dict of str, :class:`PropertyDefinition` + """ + + @object_dict_field(AttributeDefinition) + def attributes(self): + """ + An optional list of attribute definitions for the Capability definition. + + :rtype: dict of str, :class:`AttributeDefinition` + """ + + @field_validator(list_type_validator('node type', convert_shorthand_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. + + :rtype: list of str + """ + + @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 + :code:`UNBOUNDED` relationships. + + Note: the keyword :code:`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. + + :rtype: :class:`Range` + """ + + @cachedmethod + def _get_type(self, context): + return get_type_by_full_or_shorthand_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