You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ariatosca.apache.org by em...@apache.org on 2017/06/28 02:50:21 UTC
[2/3] incubator-ariatosca git commit: Full documentation of models;
fix to subtitution
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py
index 033785d..fa79091 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -49,45 +49,9 @@ from . import (
class ServiceBase(InstanceModelMixin):
"""
- A service is usually an instance of a :class:`ServiceTemplate`.
-
- You will usually not create it programmatically, but instead instantiate it from a service
- template.
-
- :ivar name: name (unique for this ARIA installation)
- :vartype name: basestring
- :ivar service_template: template from which this service was instantiated (optional)
- :vartype service_template: ServiceTemplate
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar meta_data: custom annotations
- :vartype meta_data: {:obj:`basestring`: :class:`Metadata`}
- :ivar nodes: nodes
- :vartype nodes: {:obj:`basestring`: :class:`Node`}
- :ivar groups: groups of nodes
- :vartype groups: {:obj:`basestring`: :class:`Group`}
- :ivar policies: policies
- :vartype policies: {:obj:`basestring`: :class:`Policy`]}
- :ivar substitution: the entire service can appear as a node
- :vartype substitution: :class:`Substitution`
- :ivar inputs: externally provided parameters
- :vartype inputs: {:obj:`basestring`: :class:`Input`}
- :ivar outputs: these parameters are filled in after service installation
- :vartype outputs: {:obj:`basestring`: :class:`Output`}
- :ivar workflows: custom workflows that can be performed on the service
- :vartype workflows: {:obj:`basestring`: :class:`Operation`}
- :ivar plugins: plugins used by the service
- :vartype plugins: {:obj:`basestring`: :class:`Plugin`}
- :ivar created_at: creation timestamp
- :vartype created_at: :class:`datetime.datetime`
- :ivar updated_at: update timestamp
- :vartype updated_at: :class:`datetime.datetime`
- :ivar modifications: modifications of this service
- :vartype modifications: [:class:`ServiceModification`]
- :ivar updates: updates of this service
- :vartype updates: [:class:`ServiceUpdate`]
- :ivar executions: executions on this service
- :vartype executions: [:class:`Execution`]
+ Usually an instance of a :class:`ServiceTemplate` and its many associated templates (node
+ templates, group templates, policy templates, etc.). However, it can also be created
+ programmatically.
"""
__tablename__ = 'service'
@@ -95,20 +59,6 @@ class ServiceBase(InstanceModelMixin):
__private_fields__ = ('substitution_fk',
'service_template_fk')
- # region foreign keys
-
- @declared_attr
- def substitution_fk(cls):
- """Service one-to-one to Substitution"""
- return relationship.foreign_key('substitution', nullable=True)
-
- @declared_attr
- def service_template_fk(cls):
- """For Service many-to-one to ServiceTemplate"""
- return relationship.foreign_key('service_template', nullable=True)
-
- # endregion
-
# region association proxies
@declared_attr
@@ -122,6 +72,11 @@ class ServiceBase(InstanceModelMixin):
@declared_attr
def substitution(cls):
+ """
+ Exposes the entire service as a single node.
+
+ :type: :class:`Substitution`
+ """
return relationship.one_to_one(cls, 'substitution', back_populates=relationship.NO_BACK_POP)
# endregion
@@ -130,38 +85,83 @@ class ServiceBase(InstanceModelMixin):
@declared_attr
def outputs(cls):
+ """
+ Output parameters.
+
+ :type: {:obj:`basestring`: :class:`Output`}
+ """
return relationship.one_to_many(cls, 'output', dict_key='name')
@declared_attr
def inputs(cls):
+ """
+ Externally provided parameters.
+
+ :type: {:obj:`basestring`: :class:`Input`}
+ """
return relationship.one_to_many(cls, 'input', dict_key='name')
@declared_attr
def updates(cls):
+ """
+ Service updates.
+
+ :type: [:class:`ServiceUpdate`]
+ """
return relationship.one_to_many(cls, 'service_update')
@declared_attr
def modifications(cls):
+ """
+ Service modifications.
+
+ :type: [:class:`ServiceModification`]
+ """
return relationship.one_to_many(cls, 'service_modification')
@declared_attr
def executions(cls):
+ """
+ Executions.
+
+ :type: [:class:`Execution`]
+ """
return relationship.one_to_many(cls, 'execution')
@declared_attr
def nodes(cls):
+ """
+ Nodes.
+
+ :type: {:obj:`basestring`, :class:`Node`}
+ """
return relationship.one_to_many(cls, 'node', dict_key='name')
@declared_attr
def groups(cls):
+ """
+ Groups.
+
+ :type: {:obj:`basestring`, :class:`Group`}
+ """
return relationship.one_to_many(cls, 'group', dict_key='name')
@declared_attr
def policies(cls):
+ """
+ Policies.
+
+ :type: {:obj:`basestring`, :class:`Policy`}
+ """
return relationship.one_to_many(cls, 'policy', dict_key='name')
@declared_attr
def workflows(cls):
+ """
+ Workflows.
+
+ :type: {:obj:`basestring`, :class:`Operation`}
+ """
return relationship.one_to_many(cls, 'operation', dict_key='name')
# endregion
@@ -170,6 +170,11 @@ class ServiceBase(InstanceModelMixin):
@declared_attr
def service_template(cls):
+ """
+ Source service template (can be ``None``).
+
+ :type: :class:`ServiceTemplate`
+ """
return relationship.many_to_one(cls, 'service_template')
# endregion
@@ -178,18 +183,56 @@ class ServiceBase(InstanceModelMixin):
@declared_attr
def meta_data(cls):
+ """
+ Associated metadata.
+
+ :type: {:obj:`basestring`, :class:`Metadata`}
+ """
# Warning! We cannot use the attr name "metadata" because it's used by SQLAlchemy!
return relationship.many_to_many(cls, 'metadata', dict_key='name')
@declared_attr
def plugins(cls):
+ """
+ Associated plugins.
+
+ :type: {:obj:`basestring`, :class:`Plugin`}
+ """
return relationship.many_to_many(cls, 'plugin', dict_key='name')
# endregion
- description = Column(Text)
- created_at = Column(DateTime, nullable=False, index=True)
- updated_at = Column(DateTime)
+ # region foreign keys
+
+ @declared_attr
+ def substitution_fk(cls):
+ """Service one-to-one to Substitution"""
+ return relationship.foreign_key('substitution', nullable=True)
+
+ @declared_attr
+ def service_template_fk(cls):
+ """For Service many-to-one to ServiceTemplate"""
+ return relationship.foreign_key('service_template', nullable=True)
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
+
+ created_at = Column(DateTime, nullable=False, index=True, doc="""
+ Creation timestamp.
+
+ :type: :class:`~datetime.datetime`
+ """)
+
+ updated_at = Column(DateTime, doc="""
+ Update timestamp.
+
+ :type: :class:`~datetime.datetime`
+ """)
def satisfy_requirements(self):
satisfied = True
@@ -315,48 +358,12 @@ class ServiceBase(InstanceModelMixin):
class NodeBase(InstanceModelMixin):
"""
- Usually an instance of a :class:`NodeTemplate`.
+ Typed vertex in the service topology.
+
+ Nodes may have zero or more :class:`Relationship` instances to other nodes, together forming
+ a many-to-many node graph.
- Nodes may have zero or more :class:`Relationship` instances to other nodes.
-
- :ivar name: name (unique for this service)
- :vartype name: basestring
- :ivar node_template: template from which this node was instantiated (optional)
- :vartype node_template: :class:`NodeTemplate`
- :ivar type: node type
- :vartype type: Type
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar interfaces: bundles of operations
- :vartype interfaces: {:obj:`basestring`: :class:`Interface`}
- :ivar artifacts: associated files
- :vartype artifacts: {:obj:`basestring`: :class:`Artifact`}
- :ivar capabilities: exposed capabilities
- :vartype capabilities: {:obj:`basestring`: :class:`Capability`}
- :ivar outbound_relationships: relationships to other nodes
- :vartype outbound_relationships: [:class:`Relationship`]
- :ivar inbound_relationships: relationships from other nodes
- :vartype inbound_relationships: [:class:`Relationship`]
- :ivar host: host node (can be self)
- :vartype host: :class:`Node`
- :ivar state: the state of the node, according to to the TOSCA-defined node states
- :vartype state: string
- :ivar version: used by :mod:`aria.storage.instrumentation`
- :vartype version: int
- :ivar service: containing service
- :vartype service: :class:`Service`
- :ivar groups: we are a member of these groups
- :vartype groups: [:class:`Group`]
- :ivar policies: policies enacted on this node
- :vartype policies: [:class:`Policy`]
- :ivar substitution_mapping: our contribution to service substitution
- :vartype substitution_mapping: :class:`SubstitutionMapping`
- :ivar tasks: tasks for this node
- :vartype tasks: [:class:`Task`]
- :ivar hosted_tasks: tasks on this node
- :vartype hosted_tasks: [:class:`Task`]
+ Usually an instance of a :class:`NodeTemplate`.
"""
__tablename__ = 'node'
@@ -375,67 +382,24 @@ class NodeBase(InstanceModelMixin):
STARTED = 'started'
STOPPING = 'stopping'
DELETING = 'deleting'
- # 'deleted' isn't actually part of the tosca spec, since according the description of the
- # 'deleting' state: "Node is transitioning from its current state to one where it is deleted and
- # its state is no longer tracked by the instance model."
- # However, we prefer to be able to retrieve information about deleted nodes, so we chose to add
- # this 'deleted' state to enable us to do so.
DELETED = 'deleted'
ERROR = 'error'
- STATES = [INITIAL, CREATING, CREATED, CONFIGURING, CONFIGURED, STARTING, STARTED, STOPPING,
- DELETING, DELETED, ERROR]
+ # 'deleted' isn't actually part of the TOSCA spec, since according the description of the
+ # 'deleting' state: "Node is transitioning from its current state to one where it is deleted and
+ # its state is no longer tracked by the instance model." However, we prefer to be able to
+ # retrieve information about deleted nodes, so we chose to add this 'deleted' state to enable us
+ # to do so.
+
+ STATES = (INITIAL, CREATING, CREATED, CONFIGURING, CONFIGURED, STARTING, STARTED, STOPPING,
+ DELETING, DELETED, ERROR)
- _op_to_state = {'create': {'transitional': CREATING, 'finished': CREATED},
+ _OP_TO_STATE = {'create': {'transitional': CREATING, 'finished': CREATED},
'configure': {'transitional': CONFIGURING, 'finished': CONFIGURED},
'start': {'transitional': STARTING, 'finished': STARTED},
'stop': {'transitional': STOPPING, 'finished': CONFIGURED},
'delete': {'transitional': DELETING, 'finished': DELETED}}
- @classmethod
- def determine_state(cls, op_name, is_transitional):
- """ :returns the state the node should be in as a result of running the
- operation on this node.
-
- e.g. if we are running tosca.interfaces.node.lifecycle.Standard.create, then
- the resulting state should either 'creating' (if the task just started) or 'created'
- (if the task ended).
-
- If the operation is not a standard tosca lifecycle operation, then we return None"""
-
- state_type = 'transitional' if is_transitional else 'finished'
- try:
- return cls._op_to_state[op_name][state_type]
- except KeyError:
- return None
-
- def is_available(self):
- return self.state not in (self.INITIAL, self.DELETED, self.ERROR)
-
- # region foreign_keys
-
- @declared_attr
- def type_fk(cls):
- """For Node many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def host_fk(cls):
- """For Node one-to-one to Node"""
- return relationship.foreign_key('node', nullable=True)
-
- @declared_attr
- def service_fk(cls):
- """For Service one-to-many to Node"""
- return relationship.foreign_key('service')
-
- @declared_attr
- def node_template_fk(cls):
- """For Node many-to-one to NodeTemplate"""
- return relationship.foreign_key('node_template')
-
- # endregion
-
# region association proxies
@declared_attr
@@ -454,6 +418,14 @@ class NodeBase(InstanceModelMixin):
@declared_attr
def host(cls): # pylint: disable=method-hidden
+ """
+ Node in which we are hosted (can be ``None``).
+
+ Normally the host node is found by following the relationship graph (relationships with
+ ``host`` roles) to final nodes (with ``host`` roles).
+
+ :type: :class:`Node`
+ """
return relationship.one_to_one_self(cls, 'host_fk')
# endregion
@@ -462,30 +434,65 @@ class NodeBase(InstanceModelMixin):
@declared_attr
def tasks(cls):
+ """
+ Associated tasks.
+
+ :type: [:class:`Task`]
+ """
return relationship.one_to_many(cls, 'task')
@declared_attr
def interfaces(cls):
+ """
+ Associated interfaces.
+
+ :type: {:obj:`basestring`: :class:`Interface`}
+ """
return relationship.one_to_many(cls, 'interface', dict_key='name')
@declared_attr
def properties(cls):
+ """
+ Associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
@declared_attr
def attributes(cls):
+ """
+ Associated mutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Attribute`}
+ """
return relationship.one_to_many(cls, 'attribute', dict_key='name')
@declared_attr
def artifacts(cls):
+ """
+ Associated artifacts.
+
+ :type: {:obj:`basestring`: :class:`Artifact`}
+ """
return relationship.one_to_many(cls, 'artifact', dict_key='name')
@declared_attr
def capabilities(cls):
+ """
+ Associated exposed capabilities.
+
+ :type: {:obj:`basestring`: :class:`Capability`}
+ """
return relationship.one_to_many(cls, 'capability', dict_key='name')
@declared_attr
def outbound_relationships(cls):
+ """
+ Relationships to other nodes.
+
+ :type: [:class:`Relationship`]
+ """
return relationship.one_to_many(
cls, 'relationship', child_fk='source_node_fk', back_populates='source_node',
rel_kwargs=dict(
@@ -496,6 +503,11 @@ class NodeBase(InstanceModelMixin):
@declared_attr
def inbound_relationships(cls):
+ """
+ Relationships from other nodes.
+
+ :type: [:class:`Relationship`]
+ """
return relationship.one_to_many(
cls, 'relationship', child_fk='target_node_fk', back_populates='target_node',
rel_kwargs=dict(
@@ -510,24 +522,97 @@ class NodeBase(InstanceModelMixin):
@declared_attr
def service(cls):
+ """
+ Containing service.
+
+ :type: :class:`Service`
+ """
return relationship.many_to_one(cls, 'service')
@declared_attr
def node_template(cls):
+ """
+ Source node template (can be ``None``).
+
+ :type: :class:`NodeTemplate`
+ """
return relationship.many_to_one(cls, 'node_template')
@declared_attr
def type(cls):
+ """
+ Node type.
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
# endregion
- description = Column(Text)
- state = Column(Enum(*STATES, name='node_state'), nullable=False, default=INITIAL)
- version = Column(Integer, default=1)
+ # region foreign_keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For Node many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def host_fk(cls):
+ """For Node one-to-one to Node"""
+ return relationship.foreign_key('node', nullable=True)
+
+ @declared_attr
+ def service_fk(cls):
+ """For Service one-to-many to Node"""
+ return relationship.foreign_key('service')
+
+ @declared_attr
+ def node_template_fk(cls):
+ """For Node many-to-one to NodeTemplate"""
+ return relationship.foreign_key('node_template')
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
+
+ state = Column(Enum(*STATES, name='node_state'), nullable=False, default=INITIAL, doc="""
+ TOSCA state.
+
+ :type: :obj:`basestring`
+ """)
+
+ version = Column(Integer, default=1, doc="""
+ Used by :mod:`aria.storage.instrumentation`.
+
+ :type: :obj:`int`
+ """)
__mapper_args__ = {'version_id_col': version} # Enable SQLAlchemy automatic version counting
+ @classmethod
+ def determine_state(cls, op_name, is_transitional):
+ """ :returns the state the node should be in as a result of running the
+ operation on this node.
+
+ e.g. if we are running tosca.interfaces.node.lifecycle.Standard.create, then
+ the resulting state should either 'creating' (if the task just started) or 'created'
+ (if the task ended).
+
+ If the operation is not a standard tosca lifecycle operation, then we return None"""
+
+ state_type = 'transitional' if is_transitional else 'finished'
+ try:
+ return cls._OP_TO_STATE[op_name][state_type]
+ except KeyError:
+ return None
+
+ def is_available(self):
+ return self.state not in (self.INITIAL, self.DELETED, self.ERROR)
+
@property
def host_address(self):
if self.host and self.host.attributes:
@@ -702,26 +787,9 @@ class NodeBase(InstanceModelMixin):
class GroupBase(InstanceModelMixin):
"""
- Usually an instance of a :class:`GroupTemplate`.
+ Typed logical container for zero or more :class:`Node` instances.
- :ivar name: name (unique for this service)
- :vartype name: basestring
- :ivar group_template: template from which this group was instantiated (optional)
- :vartype group_template: :class:`GroupTemplate`
- :ivar type: group type
- :vartype type: Type
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar nodes: members of this group
- :vartype nodes: [:class:`Node`]
- :ivar properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar interfaces: bundles of operations
- :vartype interfaces: {:obj:`basestring`: :class:`Interface`}
- :ivar service: containing service
- :vartype service: :class:`Service`
- :ivar policies: policies enacted on this group
- :vartype policies: [:class:`Policy`]
+ Usually an instance of a :class:`GroupTemplate`.
"""
__tablename__ = 'group'
@@ -730,25 +798,6 @@ class GroupBase(InstanceModelMixin):
'service_fk',
'group_template_fk')
- # region foreign_keys
-
- @declared_attr
- def type_fk(cls):
- """For Group many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def service_fk(cls):
- """For Service one-to-many to Group"""
- return relationship.foreign_key('service')
-
- @declared_attr
- def group_template_fk(cls):
- """For Group many-to-one to GroupTemplate"""
- return relationship.foreign_key('group_template', nullable=True)
-
- # endregion
-
# region association proxies
# endregion
@@ -761,10 +810,20 @@ class GroupBase(InstanceModelMixin):
@declared_attr
def properties(cls):
+ """
+ Associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
@declared_attr
def interfaces(cls):
+ """
+ Associated interfaces.
+
+ :type: {:obj:`basestring`: :class:`Interface`}
+ """
return relationship.one_to_many(cls, 'interface', dict_key='name')
# endregion
@@ -773,14 +832,29 @@ class GroupBase(InstanceModelMixin):
@declared_attr
def service(cls):
+ """
+ Containing service.
+
+ :type: :class:`Service`
+ """
return relationship.many_to_one(cls, 'service')
@declared_attr
def group_template(cls):
+ """
+ Source group template (can be ``None``).
+
+ :type: :class:`GroupTemplate`
+ """
return relationship.many_to_one(cls, 'group_template')
@declared_attr
def type(cls):
+ """
+ Group type.
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
# endregion
@@ -789,11 +863,39 @@ class GroupBase(InstanceModelMixin):
@declared_attr
def nodes(cls):
+ """
+ Member nodes.
+
+ :type: [:class:`Node`]
+ """
return relationship.many_to_many(cls, 'node')
# endregion
- description = Column(Text)
+ # region foreign_keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For Group many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def service_fk(cls):
+ """For Service one-to-many to Group"""
+ return relationship.foreign_key('service')
+
+ @declared_attr
+ def group_template_fk(cls):
+ """For Group many-to-one to GroupTemplate"""
+ return relationship.foreign_key('group_template', nullable=True)
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
def configure_operations(self):
for interface in self.interfaces.itervalues():
@@ -830,24 +932,10 @@ class GroupBase(InstanceModelMixin):
class PolicyBase(InstanceModelMixin):
"""
- Usually an instance of a :class:`PolicyTemplate`.
+ Typed set of orchestration hints applied to zero or more :class:`Node` or :class:`Group`
+ instances.
- :ivar name: name (unique for this service)
- :vartype name: basestring
- :ivar policy_template: template from which this policy was instantiated (optional)
- :vartype policy_template: :class:`PolicyTemplate`
- :ivar type: policy type
- :vartype type: Type
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar nodes: policy will be enacted on all these nodes
- :vartype nodes: [:class:`Node`]
- :ivar groups: policy will be enacted on all nodes in these groups
- :vartype groups: [:class:`Group`]
- :ivar properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar service: containing service
- :vartype service: :class:`Service`
+ Usually an instance of a :class:`PolicyTemplate`.
"""
__tablename__ = 'policy'
@@ -856,25 +944,6 @@ class PolicyBase(InstanceModelMixin):
'service_fk',
'policy_template_fk')
- # region foreign_keys
-
- @declared_attr
- def type_fk(cls):
- """For Policy many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def service_fk(cls):
- """For Service one-to-many to Policy"""
- return relationship.foreign_key('service')
-
- @declared_attr
- def policy_template_fk(cls):
- """For Policy many-to-one to PolicyTemplate"""
- return relationship.foreign_key('policy_template', nullable=True)
-
- # endregion
-
# region association proxies
# endregion
@@ -887,6 +956,11 @@ class PolicyBase(InstanceModelMixin):
@declared_attr
def properties(cls):
+ """
+ Associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
# endregion
@@ -895,14 +969,29 @@ class PolicyBase(InstanceModelMixin):
@declared_attr
def service(cls):
+ """
+ Containing service.
+
+ :type: :class:`Service`
+ """
return relationship.many_to_one(cls, 'service')
@declared_attr
def policy_template(cls):
+ """
+ Source policy template (can be ``None``).
+
+ :type: :class:`PolicyTemplate`
+ """
return relationship.many_to_one(cls, 'policy_template')
@declared_attr
def type(cls):
+ """
+ Group type.
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
# endregion
@@ -911,15 +1000,48 @@ class PolicyBase(InstanceModelMixin):
@declared_attr
def nodes(cls):
+ """
+ Policy is enacted on these nodes.
+
+ :type: {:obj:`basestring`: :class:`Node`}
+ """
return relationship.many_to_many(cls, 'node')
@declared_attr
def groups(cls):
+ """
+ Policy is enacted on nodes in these groups.
+
+ :type: {:obj:`basestring`: :class:`Group`}
+ """
return relationship.many_to_many(cls, 'group')
# endregion
- description = Column(Text)
+ # region foreign_keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For Policy many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def service_fk(cls):
+ """For Service one-to-many to Policy"""
+ return relationship.foreign_key('service')
+
+ @declared_attr
+ def policy_template_fk(cls):
+ """For Policy many-to-one to PolicyTemplate"""
+ return relationship.foreign_key('policy_template', nullable=True)
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
@property
def as_raw(self):
@@ -954,18 +1076,9 @@ class PolicyBase(InstanceModelMixin):
class SubstitutionBase(InstanceModelMixin):
"""
- Used to substitute a single node for the entire deployment.
+ Exposes the entire service as a single node.
Usually an instance of a :class:`SubstitutionTemplate`.
-
- :ivar substitution_template: template from which this substitution was instantiated (optional)
- :vartype substitution_template: :class:`SubstitutionTemplate`
- :ivar node_type: exposed node type
- :vartype node_type: :class:`Type`
- :ivar mappings: requirement and capability mappings
- :vartype mappings: {:obj:`basestring`: :class:`SubstitutionTemplate`}
- :ivar service: containing service
- :vartype service: :class:`Service`
"""
__tablename__ = 'substitution'
@@ -973,21 +1086,7 @@ class SubstitutionBase(InstanceModelMixin):
__private_fields__ = ('node_type_fk',
'substitution_template_fk')
- # region foreign_keys
-
- @declared_attr
- def node_type_fk(cls):
- """For Substitution many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def substitution_template_fk(cls):
- """For Substitution many-to-one to SubstitutionTemplate"""
- return relationship.foreign_key('substitution_template', nullable=True)
-
- # endregion
-
- # region association proxies
+ # region association proxies
# endregion
@@ -999,6 +1098,11 @@ class SubstitutionBase(InstanceModelMixin):
@declared_attr
def mappings(cls):
+ """
+ Map requirement and capabilities to exposed node.
+
+ :type: {:obj:`basestring`: :class:`SubstitutionMapping`}
+ """
return relationship.one_to_many(cls, 'substitution_mapping', dict_key='name')
# endregion
@@ -1007,18 +1111,47 @@ class SubstitutionBase(InstanceModelMixin):
@declared_attr
def service(cls):
+ """
+ Containing service.
+
+ :type: :class:`Service`
+ """
return relationship.one_to_one(cls, 'service', back_populates=relationship.NO_BACK_POP)
@declared_attr
def substitution_template(cls):
+ """
+ Source substitution template (can be ``None``).
+
+ :type: :class:`SubstitutionTemplate`
+ """
return relationship.many_to_one(cls, 'substitution_template')
@declared_attr
def node_type(cls):
+ """
+ Exposed node type.
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
# endregion
+ # region foreign_keys
+
+ @declared_attr
+ def node_type_fk(cls):
+ """For Substitution many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def substitution_template_fk(cls):
+ """For Substitution many-to-one to SubstitutionTemplate"""
+ return relationship.foreign_key('substitution_template', nullable=True)
+
+ # endregion
+
@property
def as_raw(self):
return collections.OrderedDict((
@@ -1041,85 +1174,98 @@ class SubstitutionBase(InstanceModelMixin):
class SubstitutionMappingBase(InstanceModelMixin):
"""
- Used by :class:`Substitution` to map a capability or a requirement to a node.
+ Used by :class:`Substitution` to map a capability or a requirement to the exposed node.
- Only one of `capability_template` and `requirement_template` can be set.
+ The :attr:`name` field should match the capability or requirement template name on the exposed
+ node's type.
- Usually an instance of a :class:`SubstitutionTemplate`.
+ Only one of :attr:`capability` and :attr:`requirement_template` can be set. If the latter is
+ set, then :attr:`node` must also be set.
- :ivar name: exposed capability or requirement name
- :vartype name: basestring
- :ivar node: node
- :vartype node: Node
- :ivar capability: capability in the node
- :vartype capability: :class:`Capability`
- :ivar requirement_template: requirement template in the node template
- :vartype requirement_template: :class:`RequirementTemplate`
- :ivar substitution: containing substitution
- :vartype substitution: :class:`Substitution`
+ Usually an instance of a :class:`SubstitutionMappingTemplate`.
"""
__tablename__ = 'substitution_mapping'
__private_fields__ = ('substitution_fk',
- 'node_fk',
'capability_fk',
- 'requirement_template_fk')
+ 'requirement_template_fk',
+ 'node_fk')
- # region foreign keys
+ # region association proxies
- @declared_attr
- def substitution_fk(cls):
- """For Substitution one-to-many to SubstitutionMapping"""
- return relationship.foreign_key('substitution')
+ # endregion
+
+ # region one_to_one relationships
@declared_attr
- def node_fk(cls):
- """For Substitution one-to-one to NodeTemplate"""
- return relationship.foreign_key('node')
+ def capability(cls):
+ """
+ Capability to expose (can be ``None``).
+
+ :type: :class:`Capability`
+ """
+ return relationship.one_to_one(cls, 'capability', back_populates=relationship.NO_BACK_POP)
@declared_attr
- def capability_fk(cls):
- """For Substitution one-to-one to Capability"""
- return relationship.foreign_key('capability', nullable=True)
+ def requirement_template(cls):
+ """
+ Requirement template to expose (can be ``None``).
+
+ :type: :class:`RequirementTemplate`
+ """
+ return relationship.one_to_one(cls, 'requirement_template',
+ back_populates=relationship.NO_BACK_POP)
@declared_attr
- def requirement_template_fk(cls):
- """For Substitution one-to-one to RequirementTemplate"""
- return relationship.foreign_key('requirement_template', nullable=True)
+ def node(cls):
+ """
+ Node for which to expose :attr:`requirement_template` (can be ``None``).
+
+ :type: :class:`Node`
+ """
+ return relationship.one_to_one(cls, 'node', back_populates=relationship.NO_BACK_POP)
# endregion
- # region association proxies
+ # region one_to_many relationships
# endregion
- # region one_to_one relationships
+ # region many_to_one relationships
@declared_attr
def substitution(cls):
+ """
+ Containing substitution.
+
+ :type: :class:`Substitution`
+ """
return relationship.many_to_one(cls, 'substitution', back_populates='mappings')
- @declared_attr
- def node(cls):
- return relationship.one_to_one(cls, 'node', back_populates=relationship.NO_BACK_POP)
+ # endregion
- @declared_attr
- def capability(cls):
- return relationship.one_to_one(cls, 'capability', back_populates=relationship.NO_BACK_POP)
+ # region foreign keys
@declared_attr
- def requirement_template(cls):
- return relationship.one_to_one(
- cls, 'requirement_template', back_populates=relationship.NO_BACK_POP)
-
- # endregion
+ def substitution_fk(cls):
+ """For Substitution one-to-many to SubstitutionMapping"""
+ return relationship.foreign_key('substitution')
- # region one_to_many relationships
+ @declared_attr
+ def capability_fk(cls):
+ """For Substitution one-to-one to Capability"""
+ return relationship.foreign_key('capability', nullable=True)
- # endregion
+ @declared_attr
+ def node_fk(cls):
+ """For Substitution one-to-one to Node"""
+ return relationship.foreign_key('node', nullable=True)
- # region many_to_one relationships
+ @declared_attr
+ def requirement_template_fk(cls):
+ """For Substitution one-to-one to RequirementTemplate"""
+ return relationship.foreign_key('requirement_template', nullable=True)
# endregion
@@ -1142,44 +1288,24 @@ class SubstitutionMappingBase(InstanceModelMixin):
def dump(self):
context = ConsumptionContext.get_thread_local()
- console.puts('{0} -> {1}.{2}'.format(
- context.style.node(self.name),
- context.style.node(self.node.name),
- context.style.node(self.capability.name
- if self.capability
- else self.requirement_template.name)))
+ if self.capability is not None:
+ console.puts('{0} -> {1}.{2}'.format(
+ context.style.node(self.name),
+ context.style.node(self.capability.node.name),
+ context.style.node(self.capability.name)))
+ else:
+ console.puts('{0} -> {1}.{2}'.format(
+ context.style.node(self.name),
+ context.style.node(self.node.name),
+ context.style.node(self.requirement_template.name)))
class RelationshipBase(InstanceModelMixin):
"""
- Connects :class:`Node` to a capability in another node.
-
- Might be an instance of a :class:`RelationshipTemplate`.
-
- :ivar name: name (usually the name of the requirement at the source node template)
- :vartype name: basestring
- :ivar relationship_template: template from which this relationship was instantiated (optional)
- :vartype relationship_template: :class:`RelationshipTemplate`
- :ivar requirement_template: template from which this relationship was instantiated (optional)
- :vartype requirement_template: :class:`RequirementTemplate`
- :ivar type: relationship type
- :vartype type: Type
- :ivar target_capability: capability at the target node (optional)
- :vartype target_capability: :class:`Capability`
- :ivar properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar interfaces: bundles of operations
- :vartype interfaces: {:obj:`basestring`: :class:`Interfaces`}
- :ivar source_position: position of the relationship in the outbound relationships.
- :vartype source_position: int
- :ivar target_position: position of the relationship in the inbound relationships.
- :vartype target_position: int
- :ivar source_node: source node
- :vartype source_node: :class:`Node`
- :ivar target_node: target node
- :vartype target_node: :class:`Node`
- :ivar tasks: tasks for this relationship
- :vartype tasks: [:class:`Task`]
+ Optionally-typed edge in the service topology, connecting a :class:`Node` to a
+ :class:`Capability` of another node.
+
+ Might be an instance of :class:`RelationshipTemplate` and/or :class:`RequirementTemplate`.
"""
__tablename__ = 'relationship'
@@ -1193,40 +1319,6 @@ class RelationshipBase(InstanceModelMixin):
'target_position',
'source_position')
- # region foreign keys
-
- @declared_attr
- def type_fk(cls):
- """For Relationship many-to-one to Type"""
- return relationship.foreign_key('type', nullable=True)
-
- @declared_attr
- def source_node_fk(cls):
- """For Node one-to-many to Relationship"""
- return relationship.foreign_key('node')
-
- @declared_attr
- def target_node_fk(cls):
- """For Node one-to-many to Relationship"""
- return relationship.foreign_key('node')
-
- @declared_attr
- def target_capability_fk(cls):
- """For Relationship one-to-one to Capability"""
- return relationship.foreign_key('capability', nullable=True)
-
- @declared_attr
- def requirement_template_fk(cls):
- """For Relationship many-to-one to RequirementTemplate"""
- return relationship.foreign_key('requirement_template', nullable=True)
-
- @declared_attr
- def relationship_template_fk(cls):
- """For Relationship many-to-one to RelationshipTemplate"""
- return relationship.foreign_key('relationship_template', nullable=True)
-
- # endregion
-
# region association proxies
@declared_attr
@@ -1245,6 +1337,11 @@ class RelationshipBase(InstanceModelMixin):
@declared_attr
def target_capability(cls):
+ """
+ Target capability.
+
+ :type: :class:`Capability`
+ """
return relationship.one_to_one(cls, 'capability', back_populates=relationship.NO_BACK_POP)
# endregion
@@ -1253,14 +1350,29 @@ class RelationshipBase(InstanceModelMixin):
@declared_attr
def tasks(cls):
+ """
+ Associated tasks.
+
+ :type: [:class:`Task`]
+ """
return relationship.one_to_many(cls, 'task')
@declared_attr
def interfaces(cls):
+ """
+ Associated interfaces.
+
+ :type: {:obj:`basestring`: :class:`Interface`}
+ """
return relationship.one_to_many(cls, 'interface', dict_key='name')
@declared_attr
def properties(cls):
+ """
+ Associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
# endregion
@@ -1269,30 +1381,98 @@ class RelationshipBase(InstanceModelMixin):
@declared_attr
def source_node(cls):
+ """
+ Source node.
+
+ :type: :class:`Node`
+ """
return relationship.many_to_one(
cls, 'node', fk='source_node_fk', back_populates='outbound_relationships')
@declared_attr
def target_node(cls):
+ """
+ Target node.
+
+ :type: :class:`Node`
+ """
return relationship.many_to_one(
cls, 'node', fk='target_node_fk', back_populates='inbound_relationships')
@declared_attr
def relationship_template(cls):
+ """
+ Source relationship template (can be ``None``).
+
+ :type: :class:`RelationshipTemplate`
+ """
return relationship.many_to_one(cls, 'relationship_template')
@declared_attr
def requirement_template(cls):
+ """
+ Source requirement template (can be ``None``).
+
+ :type: :class:`RequirementTemplate`
+ """
return relationship.many_to_one(cls, 'requirement_template')
@declared_attr
def type(cls):
+ """
+ Relationship type.
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
# endregion
- source_position = Column(Integer)
- target_position = Column(Integer)
+ # region foreign keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For Relationship many-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ @declared_attr
+ def source_node_fk(cls):
+ """For Node one-to-many to Relationship"""
+ return relationship.foreign_key('node')
+
+ @declared_attr
+ def target_node_fk(cls):
+ """For Node one-to-many to Relationship"""
+ return relationship.foreign_key('node')
+
+ @declared_attr
+ def target_capability_fk(cls):
+ """For Relationship one-to-one to Capability"""
+ return relationship.foreign_key('capability', nullable=True)
+
+ @declared_attr
+ def requirement_template_fk(cls):
+ """For Relationship many-to-one to RequirementTemplate"""
+ return relationship.foreign_key('requirement_template', nullable=True)
+
+ @declared_attr
+ def relationship_template_fk(cls):
+ """For Relationship many-to-one to RelationshipTemplate"""
+ return relationship.foreign_key('relationship_template', nullable=True)
+
+ # endregion
+
+ source_position = Column(Integer, doc="""
+ Position at source.
+
+ :type: :obj:`int`
+ """)
+
+ target_position = Column(Integer, doc="""
+ Position at target.
+
+ :type: :obj:`int`
+ """)
def configure_operations(self):
for interface in self.interfaces.itervalues():
@@ -1340,30 +1520,10 @@ class RelationshipBase(InstanceModelMixin):
class CapabilityBase(InstanceModelMixin):
"""
- A capability of a :class:`Node`.
+ Typed attachment serving two purposes: to provide extra properties and attributes to a
+ :class:`Node`, and to expose targets for :class:`Relationship` instances from other nodes.
Usually an instance of a :class:`CapabilityTemplate`.
-
- :ivar name: Name (unique for the node)
- :vartype name: basestring
- :ivar capability_template: template from which this capability was instantiated (optional)
- :vartype capability_template: :class:`capabilityTemplate`
- :ivar type: capability type
- :vartype type: Type
- :ivar min_occurrences: minimum number of requirement matches required
- :vartype min_occurrences: int
- :ivar max_occurrences: maximum number of requirement matches allowed
- :vartype min_occurrences: int
- :ivar occurrences: actual number of requirement matches
- :vartype occurrences: int
- :ivar properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar node: containing node
- :vartype node: Node
- :ivar relationship: available when we are the target of a relationship
- :vartype relationship: :class:`Relationship`
- :ivar substitution_mapping: our contribution to service substitution
- :vartype substitution_mapping: :class:`SubstitutionMapping`
"""
__tablename__ = 'capability'
@@ -1372,25 +1532,6 @@ class CapabilityBase(InstanceModelMixin):
'node_fk',
'capability_template_fk')
- # region foreign_keys
-
- @declared_attr
- def type_fk(cls):
- """For Capability many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def node_fk(cls):
- """For Node one-to-many to Capability"""
- return relationship.foreign_key('node')
-
- @declared_attr
- def capability_template_fk(cls):
- """For Capability many-to-one to CapabilityTemplate"""
- return relationship.foreign_key('capability_template', nullable=True)
-
- # endregion
-
# region association proxies
# endregion
@@ -1403,6 +1544,11 @@ class CapabilityBase(InstanceModelMixin):
@declared_attr
def properties(cls):
+ """
+ Associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
# endregion
@@ -1411,21 +1557,69 @@ class CapabilityBase(InstanceModelMixin):
@declared_attr
def node(cls):
+ """
+ Containing node.
+
+ :type: :class:`Node`
+ """
return relationship.many_to_one(cls, 'node')
@declared_attr
def capability_template(cls):
+ """
+ Source capability template (can be ``None``).
+
+ :type: :class:`CapabilityTemplate`
+ """
return relationship.many_to_one(cls, 'capability_template')
@declared_attr
def type(cls):
+ """
+ Capability type.
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
# endregion
- min_occurrences = Column(Integer, default=None)
- max_occurrences = Column(Integer, default=None)
- occurrences = Column(Integer, default=0)
+ # region foreign_keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For Capability many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def node_fk(cls):
+ """For Node one-to-many to Capability"""
+ return relationship.foreign_key('node')
+
+ @declared_attr
+ def capability_template_fk(cls):
+ """For Capability many-to-one to CapabilityTemplate"""
+ return relationship.foreign_key('capability_template', nullable=True)
+
+ # endregion
+
+ min_occurrences = Column(Integer, default=None, doc="""
+ Minimum number of requirement matches required.
+
+ :type: :obj:`int`
+ """)
+
+ max_occurrences = Column(Integer, default=None, doc="""
+ Maximum number of requirement matches allowed.
+
+ :type: :obj:`int`
+ """)
+
+ occurrences = Column(Integer, default=0, doc="""
+ Number of requirement matches.
+
+ :type: :obj:`int`
+ """)
@property
def has_enough_relationships(self):
@@ -1469,28 +1663,11 @@ class CapabilityBase(InstanceModelMixin):
class InterfaceBase(InstanceModelMixin):
"""
- A typed set of :class:`Operation`.
-
- Usually an instance of :class:`InterfaceTemplate`.
-
- :ivar name: name (unique for the node, group, or relationship)
- :vartype name: basestring
- :ivar interface_template: template from which this interface was instantiated (optional)
- :vartype interface_template: :class:`InterfaceTemplate`
- :ivar type: interface type
- :vartype type: Type
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar inputs: inputs that can be used by all operations in the interface
- :vartype inputs: {:obj:`basestring`: :class:`Input`}
- :ivar operations: operations
- :vartype operations: {:obj:`basestring`: :class:`Operation`}
- :ivar node: Containing node
- :vartype node: Node
- :ivar group: containing group
- :vartype group: :class:`Group`
- :ivar relationship: containing relationship
- :vartype relationship: :class:`Relationship`
+ Typed bundle of :class:`Operation` instances.
+
+ Can be associated with a :class:`Node`, a :class:`Group`, or a :class:`Relationship`.
+
+ Usually an instance of a :class:`InterfaceTemplate`.
"""
__tablename__ = 'interface'
@@ -1501,35 +1678,6 @@ class InterfaceBase(InstanceModelMixin):
'relationship_fk',
'interface_template_fk')
- # region foreign_keys
-
- @declared_attr
- def type_fk(cls):
- """For Interface many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def node_fk(cls):
- """For Node one-to-many to Interface"""
- return relationship.foreign_key('node', nullable=True)
-
- @declared_attr
- def group_fk(cls):
- """For Group one-to-many to Interface"""
- return relationship.foreign_key('group', nullable=True)
-
- @declared_attr
- def relationship_fk(cls):
- """For Relationship one-to-many to Interface"""
- return relationship.foreign_key('relationship', nullable=True)
-
- @declared_attr
- def interface_template_fk(cls):
- """For Interface many-to-one to InterfaceTemplate"""
- return relationship.foreign_key('interface_template', nullable=True)
-
- # endregion
-
# region association proxies
# endregion
@@ -1542,10 +1690,20 @@ class InterfaceBase(InstanceModelMixin):
@declared_attr
def inputs(cls):
+ """
+ Parameters for all operations of the interface.
+
+ :type: {:obj:`basestring`: :class:`Input`}
+ """
return relationship.one_to_many(cls, 'input', dict_key='name')
@declared_attr
def operations(cls):
+ """
+ Associated operations.
+
+ :type: {:obj:`basestring`: :class:`Operation`}
+ """
return relationship.one_to_many(cls, 'operation', dict_key='name')
# endregion
@@ -1554,27 +1712,85 @@ class InterfaceBase(InstanceModelMixin):
@declared_attr
def node(cls):
- return relationship.many_to_one(cls, 'node')
+ """
+ Containing node (can be ``None``).
- @declared_attr
- def relationship(cls):
- return relationship.many_to_one(cls, 'relationship')
+ :type: :class:`Node`
+ """
+ return relationship.many_to_one(cls, 'node')
@declared_attr
def group(cls):
+ """
+ Containing group (can be ``None``).
+
+ :type: :class:`Group`
+ """
return relationship.many_to_one(cls, 'group')
@declared_attr
+ def relationship(cls):
+ """
+ Containing relationship (can be ``None``).
+
+ :type: :class:`Relationship`
+ """
+ return relationship.many_to_one(cls, 'relationship')
+
+ @declared_attr
def interface_template(cls):
+ """
+ Source interface template (can be ``None``).
+
+ :type: :class:`InterfaceTemplate`
+ """
return relationship.many_to_one(cls, 'interface_template')
@declared_attr
def type(cls):
+ """
+ Interface type.
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
# endregion
- description = Column(Text)
+ # region foreign_keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For Interface many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def node_fk(cls):
+ """For Node one-to-many to Interface"""
+ return relationship.foreign_key('node', nullable=True)
+
+ @declared_attr
+ def group_fk(cls):
+ """For Group one-to-many to Interface"""
+ return relationship.foreign_key('group', nullable=True)
+
+ @declared_attr
+ def relationship_fk(cls):
+ """For Relationship one-to-many to Interface"""
+ return relationship.foreign_key('relationship', nullable=True)
+
+ @declared_attr
+ def interface_template_fk(cls):
+ """For Interface many-to-one to InterfaceTemplate"""
+ return relationship.foreign_key('interface_template', nullable=True)
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
def configure_operations(self):
for operation in self.operations.itervalues():
@@ -1610,44 +1826,21 @@ class InterfaceBase(InstanceModelMixin):
class OperationBase(InstanceModelMixin):
"""
- An operation in a :class:`Interface`.
+ Entry points to Python functions called as part of a workflow execution.
- Might be an instance of :class:`OperationTemplate`.
+ The operation signature (its :attr:`name` and its :attr:`inputs`'s names and types) is declared
+ by the type of the :class:`Interface`, however each operation can provide its own
+ :attr:`implementation` as well as additional inputs.
- :ivar name: name (unique for the interface or service)
- :vartype name: basestring
- :ivar operation_template: template from which this operation was instantiated (optional)
- :vartype operation_template: :class:`OperationTemplate`
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar relationship_edge: when ``True`` specifies that the operation is on the relationship's
- target edge instead of its source (only used by relationship
- operations)
- :vartype relationship_edge: bool
- :ivar implementation: implementation (interpreted by the plugin)
- :vartype implementation: basestring
- :ivar dependencies: dependency strings (interpreted by the plugin)
- :vartype dependencies: [obj:`basestring`]
- :ivar inputs: input that can be used by this operation
- :vartype inputs: {:obj:`basestring`: :class:`Input`}
- :ivar plugin: associated plugin
- :vartype plugin: Plugin
- :ivar configurations: configuration (interpreted by the plugin)
- :vartype configurations: {obj:`basestring`: :class:`Configuration`}
- :ivar function: name of the operation function
- :vartype function: basestring
- :ivar arguments: arguments to send to the operation function
- :vartype arguments: {:obj:`basestring`: :class:`Argument`}
- :ivar executor: name of executor to run the operation with
- :vartype executor: basestring
- :ivar max_attempts: maximum number of attempts allowed in case of failure
- :vartype max_attempts: int
- :ivar retry_interval: interval between retries (in seconds)
- :vartype retry_interval: int
- :ivar interface: containing interface
- :vartype interface: Interface
- :ivar service: containing service
- :vartype service: Service
+ The Python :attr:`function` is usually provided by an associated :class:`Plugin`. Its purpose is
+ to execute the implementation, providing it with both the operation's and interface's inputs.
+ The :attr:`arguments` of the function should be set according to the specific signature of the
+ function.
+
+ Additionally, :attr:`configuration` parameters can be provided as hints to configure the
+ function's behavior. For example, they can be used to configure remote execution credentials.
+
+ Might be an instance of :class:`OperationTemplate`.
"""
__tablename__ = 'operation'
@@ -1657,30 +1850,6 @@ class OperationBase(InstanceModelMixin):
'plugin_fk',
'operation_template_fk')
- # region foreign_keys
-
- @declared_attr
- def service_fk(cls):
- """For Service one-to-many to Operation"""
- return relationship.foreign_key('service', nullable=True)
-
- @declared_attr
- def interface_fk(cls):
- """For Interface one-to-many to Operation"""
- return relationship.foreign_key('interface', nullable=True)
-
- @declared_attr
- def plugin_fk(cls):
- """For Operation one-to-one to Plugin"""
- return relationship.foreign_key('plugin', nullable=True)
-
- @declared_attr
- def operation_template_fk(cls):
- """For Operation many-to-one to OperationTemplate"""
- return relationship.foreign_key('operation_template', nullable=True)
-
- # endregion
-
# region association proxies
# endregion
@@ -1689,6 +1858,11 @@ class OperationBase(InstanceModelMixin):
@declared_attr
def plugin(cls):
+ """
+ Associated plugin.
+
+ :type: :class:`Plugin`
+ """
return relationship.one_to_one(cls, 'plugin', back_populates=relationship.NO_BACK_POP)
# endregion
@@ -1697,30 +1871,60 @@ class OperationBase(InstanceModelMixin):
@declared_attr
def inputs(cls):
- return relationship.one_to_many(cls, 'input', dict_key='name')
+ """
+ Parameters provided to the :attr:`implementation`.
- @declared_attr
- def configurations(cls):
- return relationship.one_to_many(cls, 'configuration', dict_key='name')
+ :type: {:obj:`basestring`: :class:`Input`}
+ """
+ return relationship.one_to_many(cls, 'input', dict_key='name')
@declared_attr
def arguments(cls):
+ """
+ Arguments sent to the Python :attr:`function`.
+
+ :type: {:obj:`basestring`: :class:`Argument`}
+ """
return relationship.one_to_many(cls, 'argument', dict_key='name')
+ @declared_attr
+ def configurations(cls):
+ """
+ Configuration parameters for the Python :attr:`function`.
+
+ :type: {:obj:`basestring`: :class:`Configuration`}
+ """
+ return relationship.one_to_many(cls, 'configuration', dict_key='name')
+
# endregion
# region many_to_one relationships
@declared_attr
def service(cls):
+ """
+ Containing service (can be ``None``). For workflow operations.
+
+ :type: :class:`Service`
+ """
return relationship.many_to_one(cls, 'service', back_populates='workflows')
@declared_attr
def interface(cls):
+ """
+ Containing interface (can be ``None``).
+
+ :type: :class:`Interface`
+ """
return relationship.many_to_one(cls, 'interface')
@declared_attr
def operation_template(cls):
+ """
+ Source operation template (can be ``None``).
+
+ :type: :class:`OperationTemplate`
+ """
return relationship.many_to_one(cls, 'operation_template')
# endregion
@@ -1729,14 +1933,78 @@ class OperationBase(InstanceModelMixin):
# endregion
- description = Column(Text)
- relationship_edge = Column(Boolean)
- implementation = Column(Text)
- dependencies = Column(modeling_types.StrictList(item_cls=basestring))
- function = Column(Text)
- executor = Column(Text)
- max_attempts = Column(Integer)
- retry_interval = Column(Integer)
+ # region foreign_keys
+
+ @declared_attr
+ def service_fk(cls):
+ """For Service one-to-many to Operation"""
+ return relationship.foreign_key('service', nullable=True)
+
+ @declared_attr
+ def interface_fk(cls):
+ """For Interface one-to-many to Operation"""
+ return relationship.foreign_key('interface', nullable=True)
+
+ @declared_attr
+ def plugin_fk(cls):
+ """For Operation one-to-one to Plugin"""
+ return relationship.foreign_key('plugin', nullable=True)
+
+ @declared_attr
+ def operation_template_fk(cls):
+ """For Operation many-to-one to OperationTemplate"""
+ return relationship.foreign_key('operation_template', nullable=True)
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
+
+ relationship_edge = Column(Boolean, doc="""
+ When ``True`` specifies that the operation is on the relationship's target edge; ``False`` is
+ the source edge (only used by operations on relationships)
+
+ :type: :obj:`bool`
+ """)
+
+ implementation = Column(Text, doc="""
+ Implementation (usually the name of an artifact).
+
+ :type: :obj:`basestring`
+ """)
+
+ dependencies = Column(modeling_types.StrictList(item_cls=basestring), doc="""
+ Dependencies (usually names of artifacts).
+
+ :type: [:obj:`basestring`]
+ """)
+
+ function = Column(Text, doc="""
+ Full path to Python function.
+
+ :type: :obj:`basestring`
+ """)
+
+ executor = Column(Text, doc="""
+ Name of executor.
+
+ :type: :obj:`basestring`
+ """)
+
+ max_attempts = Column(Integer, doc="""
+ Maximum number of attempts allowed in case of task failure.
+
+ :type: :obj:`int`
+ """)
+
+ retry_interval = Column(Integer, doc="""
+ Interval between task retry attemps (in seconds).
+
+ :type: :obj:`float`
+ """)
def configure(self):
if (self.implementation is None) and (self.function is None):
@@ -1829,30 +2097,9 @@ class OperationBase(InstanceModelMixin):
class ArtifactBase(InstanceModelMixin):
"""
- A file associated with a :class:`Node`.
+ Typed file, either provided in a CSAR or downloaded from a repository.
Usually an instance of :class:`ArtifactTemplate`.
-
- :ivar name: name (unique for the node)
- :vartype name: basestring
- :ivar artifact_template: template from which this artifact was instantiated (optional)
- :vartype artifact_template: ArtifactTemplate
- :ivar type: artifact type
- :vartype type: Type
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar source_path: source path (CSAR or repository)
- :vartype source_path: basestring
- :ivar target_path: path at destination machine
- :vartype target_path: basestring
- :ivar repository_url: repository URL
- :vartype repository_path: basestring
- :ivar repository_credential: credentials for accessing the repository
- :vartype repository_credential: {:obj:`basestring`: :obj:`basestring`}
- :ivar properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar node: containing node
- :vartype node: Node
"""
__tablename__ = 'artifact'
@@ -1861,25 +2108,6 @@ class ArtifactBase(InstanceModelMixin):
'node_fk',
'artifact_template_fk')
- # region foreign_keys
-
- @declared_attr
- def type_fk(cls):
- """For Artifact many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def node_fk(cls):
- """For Node one-to-many to Artifact"""
- return relationship.foreign_key('node')
-
- @declared_attr
- def artifact_template_fk(cls):
- """For Artifact many-to-one to ArtifactTemplate"""
- return relationship.foreign_key('artifact_template', nullable=True)
-
- # endregion
-
# region association proxies
# endregion
@@ -1892,29 +2120,94 @@ class ArtifactBase(InstanceModelMixin):
@declared_attr
def properties(cls):
+ """
+ Associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
# endregion
# region many_to_one relationships
+
@declared_attr
def node(cls):
+ """
+ Containing node.
+
+ :type: :class:`Node`
+ """
return relationship.many_to_one(cls, 'node')
@declared_attr
def artifact_template(cls):
+ """
+ Source artifact template (can be ``None``).
+
+ :type: :class:`ArtifactTemplate`
+ """
return relationship.many_to_one(cls, 'artifact_template')
@declared_attr
def type(cls):
+ """
+ Artifact type.
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
+
+ # endregion
+
+ # region foreign_keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For Artifact many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def node_fk(cls):
+ """For Node one-to-many to Artifact"""
+ return relationship.foreign_key('node')
+
+ @declared_attr
+ def artifact_template_fk(cls):
+ """For Artifact many-to-one to ArtifactTemplate"""
+ return relationship.foreign_key('artifact_template', nullable=True)
+
# endregion
- description = Column(Text)
- source_path = Column(Text)
- target_path = Column(Text)
- repository_url = Column(Text)
- repository_credential = Column(modeling_types.StrictDict(basestring, basestring))
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
+
+ source_path = Column(Text, doc="""
+ Source path (in CSAR or repository).
+
+ :type: :obj:`basestring`
+ """)
+
+ target_path = Column(Text, doc="""
+ Path at which to install at destination.
+
+ :type: :obj:`basestring`
+ """)
+
+ repository_url = Column(Text, doc="""
+ Repository URL.
+
+ :type: :obj:`basestring`
+ """)
+
+ repository_credential = Column(modeling_types.StrictDict(basestring, basestring), doc="""
+ Credentials for accessing the repository.
+
+ :type: {:obj:`basestring`, :obj:`basestring`}
+ """)
@property
def as_raw(self):