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:20 UTC
[1/3] incubator-ariatosca git commit: Full documentation of models;
fix to subtitution
Repository: incubator-ariatosca
Updated Branches:
refs/heads/ARIA-286-sphinx-documentation 7ed92d0fe -> 4ebbbb156
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index ba62416..70ec831 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -49,51 +49,10 @@ from . import (
class ServiceTemplateBase(TemplateModelMixin):
"""
- A service template is a source for creating :class:`Service` instances.
-
- It is usually created by various DSL parsers, such as ARIA's TOSCA extension. However, it can
- also be created programmatically.
-
- :ivar name: name (unique for this ARIA installation)
- :vartype name: basestring
- :ivar main_file_name: filename of CSAR or YAML file from which this service template was parsed
- :vartype main_file_name: basestring
- :ivar meta_data: custom annotations
- :vartype meta_data: {:obj:`basestring`: :class:`Metadata`}
- :ivar node_templates: templates for creating nodes
- :vartype node_templates: {:obj:`basestring`: :class:`NodeTemplate`}
- :ivar group_templates: templates for creating groups
- :vartype group_templates: {:obj:`basestring`: :class:`GroupTemplate`}
- :ivar policy_templates: templates for creating policies
- :vartype policy_templates: {:obj:`basestring`: :class:`PolicyTemplate`}
- :ivar substitution_template: the entire service can appear as a node
- :vartype substitution_template: :class:`SubstitutionTemplate`
- :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 workflow_templates: custom workflows that can be performed on the service
- :vartype workflow_templates: {:obj:`basestring`: :class:`OperationTemplate`}
- :ivar plugin_specifications: plugins used by the service
- :vartype plugin_specifications: {:obj:`basestring`: :class:`PluginSpecification`}
- :ivar node_types: base for the node type hierarchy
- :vartype node_types: Type
- :ivar group_types: base for the group type hierarchy
- :vartype group_types: Type
- :ivar policy_types: base for the policy type hierarchy
- :vartype policy_types: Type
- :ivar relationship_types: base for the relationship type hierarchy
- :vartype relationship_types: Type
- :ivar capability_types: base for the capability type hierarchy
- :vartype capability_types: Type
- :ivar interface_types: base for the interface type hierarchy
- :vartype interface_types: Type
- :ivar artifact_types: base for the artifact type hierarchy
- :vartype artifact_types: Type
- :ivar created_at: creation timestamp
- :vartype created_at: datetime.datetime
- :ivar updated_at: update timestamp
- :vartype updated_at: datetime.datetime
+ Template for creating :class:`Service` instances.
+
+ Usually created by various DSL parsers, such as ARIA's TOSCA extension. However, it can also be
+ created programmatically.
"""
__tablename__ = 'service_template'
@@ -107,54 +66,29 @@ class ServiceTemplateBase(TemplateModelMixin):
'interface_type_fk',
'artifact_type_fk')
- description = Column(Text)
- main_file_name = Column(Text)
- created_at = Column(DateTime, nullable=False, index=True)
- updated_at = Column(DateTime)
-
- # region foreign keys
-
- @declared_attr
- def substitution_template_fk(cls):
- """For ServiceTemplate one-to-one to SubstitutionTemplate"""
- return relationship.foreign_key('substitution_template', nullable=True)
-
- @declared_attr
- def node_type_fk(cls):
- """For ServiceTemplate one-to-one to Type"""
- return relationship.foreign_key('type', nullable=True)
-
- @declared_attr
- def group_type_fk(cls):
- """For ServiceTemplate one-to-one to Type"""
- return relationship.foreign_key('type', nullable=True)
+ description = Column(Text, doc="""
+ Human-readable description.
- @declared_attr
- def policy_type_fk(cls):
- """For ServiceTemplate one-to-one to Type"""
- return relationship.foreign_key('type', nullable=True)
+ :type: :obj:`basestring`
+ """)
- @declared_attr
- def relationship_type_fk(cls):
- """For ServiceTemplate one-to-one to Type"""
- return relationship.foreign_key('type', nullable=True)
+ main_file_name = Column(Text, doc="""
+ Filename of CSAR or YAML file from which this service template was parsed.
+
+ :type: :obj:`basestring`
+ """)
- @declared_attr
- def capability_type_fk(cls):
- """For ServiceTemplate one-to-one to Type"""
- return relationship.foreign_key('type', nullable=True)
+ created_at = Column(DateTime, nullable=False, index=True, doc="""
+ Creation timestamp.
- @declared_attr
- def interface_type_fk(cls):
- """For ServiceTemplate one-to-one to Type"""
- return relationship.foreign_key('type', nullable=True)
+ :type: :class:`~datetime.datetime`
+ """)
- @declared_attr
- def artifact_type_fk(cls):
- """For ServiceTemplate one-to-one to Type"""
- return relationship.foreign_key('type', nullable=True)
+ updated_at = Column(DateTime, doc="""
+ Update timestamp.
- # endregion
+ :type: :class:`~datetime.datetime`
+ """)
# region association proxies
@@ -164,41 +98,81 @@ class ServiceTemplateBase(TemplateModelMixin):
@declared_attr
def substitution_template(cls):
+ """
+ Exposes an entire service as a single node.
+
+ :type: :class:`SubstitutionTemplate`
+ """
return relationship.one_to_one(
cls, 'substitution_template', back_populates=relationship.NO_BACK_POP)
@declared_attr
def node_types(cls):
+ """
+ Base for the node type hierarchy,
+
+ :type: :class:`Type`
+ """
return relationship.one_to_one(
cls, 'type', fk='node_type_fk', back_populates=relationship.NO_BACK_POP)
@declared_attr
def group_types(cls):
+ """
+ Base for the group type hierarchy,
+
+ :type: :class:`Type`
+ """
return relationship.one_to_one(
cls, 'type', fk='group_type_fk', back_populates=relationship.NO_BACK_POP)
@declared_attr
def policy_types(cls):
+ """
+ Base for the policy type hierarchy,
+
+ :type: :class:`Type`
+ """
return relationship.one_to_one(
cls, 'type', fk='policy_type_fk', back_populates=relationship.NO_BACK_POP)
@declared_attr
def relationship_types(cls):
+ """
+ Base for the relationship type hierarchy,
+
+ :type: :class:`Type`
+ """
return relationship.one_to_one(
cls, 'type', fk='relationship_type_fk', back_populates=relationship.NO_BACK_POP)
@declared_attr
def capability_types(cls):
+ """
+ Base for the capability type hierarchy,
+
+ :type: :class:`Type`
+ """
return relationship.one_to_one(
cls, 'type', fk='capability_type_fk', back_populates=relationship.NO_BACK_POP)
@declared_attr
def interface_types(cls):
+ """
+ Base for the interface type hierarchy,
+
+ :type: :class:`Type`
+ """
return relationship.one_to_one(
cls, 'type', fk='interface_type_fk', back_populates=relationship.NO_BACK_POP)
@declared_attr
def artifact_types(cls):
+ """
+ Base for the artifact type hierarchy,
+
+ :type: :class:`Type`
+ """
return relationship.one_to_one(
cls, 'type', fk='artifact_type_fk', back_populates=relationship.NO_BACK_POP)
@@ -217,30 +191,65 @@ class ServiceTemplateBase(TemplateModelMixin):
@declared_attr
def node_templates(cls):
- return relationship.one_to_many(cls, 'node_template', dict_key='name')
-
- @declared_attr
- def outputs(cls):
- return relationship.one_to_many(cls, 'output', dict_key='name')
+ """
+ Templates for creating nodes.
- @declared_attr
- def inputs(cls):
- return relationship.one_to_many(cls, 'input', dict_key='name')
+ :type: {:obj:`basestring`, :class:`NodeTemplate`}
+ """
+ return relationship.one_to_many(cls, 'node_template', dict_key='name')
@declared_attr
def group_templates(cls):
+ """
+ Templates for creating groups.
+
+ :type: {:obj:`basestring`, :class:`GroupTemplate`}
+ """
return relationship.one_to_many(cls, 'group_template', dict_key='name')
@declared_attr
def policy_templates(cls):
+ """
+ Templates for creating policies.
+
+ :type: {:obj:`basestring`, :class:`PolicyTemplate`}
+ """
return relationship.one_to_many(cls, 'policy_template', dict_key='name')
@declared_attr
def workflow_templates(cls):
+ """
+ Templates for creating workflows.
+
+ :type: {:obj:`basestring`, :class:`OperationTemplate`}
+ """
return relationship.one_to_many(cls, 'operation_template', dict_key='name')
@declared_attr
+ def outputs(cls):
+ """
+ Declarations for output parameters are filled in after service installation.
+
+ :type: {:obj:`basestring`: :class:`Output`}
+ """
+ return relationship.one_to_many(cls, 'output', dict_key='name')
+
+ @declared_attr
+ def inputs(cls):
+ """
+ Declarations for externally provided parameters.
+
+ :type: {:obj:`basestring`: :class:`Input`}
+ """
+ return relationship.one_to_many(cls, 'input', dict_key='name')
+
+ @declared_attr
def plugin_specifications(cls):
+ """
+ Required plugins for instantiated services.
+
+ :type: {:obj:`basestring`: :class:`PluginSpecification`}
+ """
return relationship.one_to_many(cls, 'plugin_specification', dict_key='name')
# endregion
@@ -253,11 +262,60 @@ class ServiceTemplateBase(TemplateModelMixin):
@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')
# endregion
+ # region foreign keys
+
+ @declared_attr
+ def substitution_template_fk(cls):
+ """For ServiceTemplate one-to-one to SubstitutionTemplate"""
+ return relationship.foreign_key('substitution_template', nullable=True)
+
+ @declared_attr
+ def node_type_fk(cls):
+ """For ServiceTemplate one-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ @declared_attr
+ def group_type_fk(cls):
+ """For ServiceTemplate one-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ @declared_attr
+ def policy_type_fk(cls):
+ """For ServiceTemplate one-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ @declared_attr
+ def relationship_type_fk(cls):
+ """For ServiceTemplate one-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ @declared_attr
+ def capability_type_fk(cls):
+ """For ServiceTemplate one-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ @declared_attr
+ def interface_type_fk(cls):
+ """For ServiceTemplate one-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ @declared_attr
+ def artifact_type_fk(cls):
+ """For ServiceTemplate one-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ # endregion
+
@property
def as_raw(self):
return collections.OrderedDict((
@@ -402,43 +460,8 @@ class ServiceTemplateBase(TemplateModelMixin):
class NodeTemplateBase(TemplateModelMixin):
"""
- A template for creating zero or more :class:`Node` instances.
-
- :ivar name: name (unique for this service template; will usually be used as a prefix for node
- names)
- :vartype name: basestring
- :ivar type: node type
-
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar default_instances: default number nodes that will appear in the service
- :vartype default_instances: int
- :ivar min_instances: minimum number nodes that will appear in the service
- :vartype min_instances: int
- :ivar max_instances: maximum number nodes that will appear in the service
- :vartype max_instances: int
- :ivar properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar interface_templates: bundles of operations
- :vartype interface_templates: {:obj:`basestring`: :class:`InterfaceTemplate`}
- :ivar artifact_templates: associated files
- :vartype artifact_templates: {:obj:`basestring`: :class:`ArtifactTemplate`}
- :ivar capability_templates: exposed capabilities
- :vartype capability_templates: {:obj:`basestring`: :class:`CapabilityTemplate`}
- :ivar requirement_templates: potential relationships with other nodes
- :vartype requirement_templates: [:class:`RequirementTemplate`]
- :ivar target_node_template_constraints: constraints for filtering relationship targets
- :vartype target_node_template_constraints: [:class:`NodeTemplateConstraint`]
- :ivar service_template: containing service template
- :vartype service_template: ServiceTemplate
- :ivar group_templates: we are a member of these groups
- :vartype group_templates: [:class:`GroupTemplate`]
- :ivar policy_templates: policy templates enacted on this node
- :vartype policy_templates: [:class:`PolicyTemplate`]
- :ivar substitution_template_mapping: our contribution to service substitution
- :vartype substitution_template_mapping: :class:`SubstitutionTemplateMapping`
- :ivar nodes: instantiated nodes
- :vartype nodes: [:class:`Node`]
+ Template for creating zero or more :class:`Node` instances, which are typed vertices in the
+ service topology.
"""
__tablename__ = 'node_template'
@@ -446,20 +469,6 @@ class NodeTemplateBase(TemplateModelMixin):
__private_fields__ = ('type_fk',
'service_template_fk')
- # region foreign_keys
-
- @declared_attr
- def type_fk(cls):
- """For NodeTemplate many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def service_template_fk(cls):
- """For ServiceTemplate one-to-many to NodeTemplate"""
- return relationship.foreign_key('service_template')
-
- # endregion
-
# region association proxies
@declared_attr
@@ -482,30 +491,65 @@ class NodeTemplateBase(TemplateModelMixin):
@declared_attr
def nodes(cls):
+ """
+ Instantiated nodes.
+
+ :type: [:class:`Node`]
+ """
return relationship.one_to_many(cls, 'node')
@declared_attr
def interface_templates(cls):
+ """
+ Associated interface templates.
+
+ :type: {:obj:`basestring`: :class:`InterfaceTemplate`}
+ """
return relationship.one_to_many(cls, 'interface_template', dict_key='name')
@declared_attr
def artifact_templates(cls):
+ """
+ Associated artifacts.
+
+ :type: {:obj:`basestring`: :class:`ArtifactTemplate`}
+ """
return relationship.one_to_many(cls, 'artifact_template', dict_key='name')
@declared_attr
def capability_templates(cls):
+ """
+ Associated exposed capability templates.
+
+ :type: {:obj:`basestring`: :class:`CapabilityTemplate`}
+ """
return relationship.one_to_many(cls, 'capability_template', dict_key='name')
@declared_attr
def requirement_templates(cls):
+ """
+ Associated potential relationships with other nodes.
+
+ :type: [:class:`RequirementTemplate`]
+ """
return relationship.one_to_many(cls, 'requirement_template', child_fk='node_template_fk')
@declared_attr
def properties(cls):
+ """
+ Declarations for associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
@declared_attr
def attributes(cls):
+ """
+ Declarations for associated mutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Attribute`}
+ """
return relationship.one_to_many(cls, 'attribute', dict_key='name')
# endregion
@@ -514,19 +558,67 @@ class NodeTemplateBase(TemplateModelMixin):
@declared_attr
def type(cls):
+ """
+ Node type.
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
@declared_attr
def service_template(cls):
+ """
+ Containing service template.
+
+ :type: :class:`ServiceTemplate`
+ """
return relationship.many_to_one(cls, 'service_template')
# endregion
- description = Column(Text)
- default_instances = Column(Integer, default=1)
- min_instances = Column(Integer, default=0)
- max_instances = Column(Integer, default=None)
- target_node_template_constraints = Column(PickleType)
+ # region foreign_keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For NodeTemplate many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def service_template_fk(cls):
+ """For ServiceTemplate one-to-many to NodeTemplate"""
+ return relationship.foreign_key('service_template')
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
+
+ default_instances = Column(Integer, default=1, doc="""
+ Default number nodes that will appear in the service.
+
+ :type: :obj:`int`
+ """)
+
+ min_instances = Column(Integer, default=0, doc="""
+ Minimum number nodes that will appear in the service.
+
+ :type: :obj:`int`
+ """)
+
+ max_instances = Column(Integer, default=None, doc="""
+ Maximum number nodes that will appear in the service.
+
+ :type: :obj:`int`
+ """)
+
+ target_node_template_constraints = Column(PickleType, doc="""
+ Constraints for filtering relationship targets.
+
+ :type: [:class:`NodeTemplateConstraint`]
+ """)
def is_target_node_template_valid(self, target_node_template):
if self.target_node_template_constraints:
@@ -617,28 +709,8 @@ class NodeTemplateBase(TemplateModelMixin):
class GroupTemplateBase(TemplateModelMixin):
"""
- A template for creating a :class:`Group` instance.
-
- Groups are logical containers for zero or more nodes.
-
- :ivar name: name (unique for this service template)
- :vartype name: basestring
- :ivar type: group type
-
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar node_templates: all nodes instantiated by these templates will be members of the group
- :vartype node_templates: [:class:`NodeTemplate`]
- :ivar properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar interface_templates: bundles of operations
- :vartype interface_templates: {:obj:`basestring`: :class:`InterfaceTemplate`}
- :ivar service_template: containing service template
- :vartype service_template: :class:`ServiceTemplate`
- :ivar policy_templates: policy templates enacted on this group
- :vartype policy_templates: [:class:`PolicyTemplate`]
- :ivar groups: instantiated groups
- :vartype groups: [:class:`Group`]
+ Template for creating a :class:`Group` instance, which is a typed logical container for zero or
+ more :class:`Node` instances.
"""
__tablename__ = 'group_template'
@@ -646,20 +718,6 @@ class GroupTemplateBase(TemplateModelMixin):
__private_fields__ = ('type_fk',
'service_template_fk')
- # region foreign keys
-
- @declared_attr
- def type_fk(cls):
- """For GroupTemplate many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def service_template_fk(cls):
- """For ServiceTemplate one-to-many to GroupTemplate"""
- return relationship.foreign_key('service_template')
-
- # endregion
-
# region association proxies
# endregion
@@ -672,14 +730,29 @@ class GroupTemplateBase(TemplateModelMixin):
@declared_attr
def groups(cls):
+ """
+ Instantiated groups.
+
+ :type: [:class:`Group`]
+ """
return relationship.one_to_many(cls, 'group')
@declared_attr
def interface_templates(cls):
+ """
+ Associated interface templates.
+
+ :type: {:obj:`basestring`: :class:`InterfaceTemplate`}
+ """
return relationship.one_to_many(cls, 'interface_template', dict_key='name')
@declared_attr
def properties(cls):
+ """
+ Declarations for associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
# endregion
@@ -688,10 +761,20 @@ class GroupTemplateBase(TemplateModelMixin):
@declared_attr
def service_template(cls):
+ """
+ Containing service template.
+
+ :type: :class:`ServiceTemplate`
+ """
return relationship.many_to_one(cls, 'service_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
@@ -700,18 +783,41 @@ class GroupTemplateBase(TemplateModelMixin):
@declared_attr
def node_templates(cls):
+ """
+ Nodes instantiated by these templates will be members of the group.
+
+ :type: [:class:`NodeTemplate`]
+ """
return relationship.many_to_many(cls, 'node_template')
# endregion
- description = Column(Text)
+ # region foreign keys
- @property
- def as_raw(self):
- return collections.OrderedDict((
- ('name', self.name),
- ('description', self.description),
- ('type_name', self.type.name),
+ @declared_attr
+ def type_fk(cls):
+ """For GroupTemplate many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def service_template_fk(cls):
+ """For ServiceTemplate one-to-many to GroupTemplate"""
+ return relationship.foreign_key('service_template')
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
+
+ @property
+ def as_raw(self):
+ return collections.OrderedDict((
+ ('name', self.name),
+ ('description', self.description),
+ ('type_name', self.type.name),
('properties', formatting.as_raw_dict(self.properties)),
('interface_templates', formatting.as_raw_list(self.interface_templates))))
@@ -752,24 +858,8 @@ class GroupTemplateBase(TemplateModelMixin):
class PolicyTemplateBase(TemplateModelMixin):
"""
- Policies can be applied to zero or more :class:`NodeTemplate` or :class:`GroupTemplate`
- instances.
-
- :ivar name: name (unique for this service template)
- :vartype name: basestring
- :ivar type: policy type
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar node_templates: policy will be enacted on all nodes instantiated by these templates
- :vartype node_templates: [:class:`NodeTemplate`]
- :ivar group_templates: policy will be enacted on all nodes in these groups
- :vartype group_templates: [:class:`GroupTemplate`]
- :ivar properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar service_template: containing service template
- :vartype service_template: :class:`ServiceTemplate`
- :ivar policies: instantiated policies
- :vartype policies: [:class:`Policy`]
+ Template for creating a :class:`Policy` instance, which is a typed set of orchestration hints
+ applied to zero or more :class:`Node` or :class:`Group` instances.
"""
__tablename__ = 'policy_template'
@@ -777,20 +867,6 @@ class PolicyTemplateBase(TemplateModelMixin):
__private_fields__ = ('type_fk',
'service_template_fk')
- # region foreign keys
-
- @declared_attr
- def type_fk(cls):
- """For PolicyTemplate many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def service_template_fk(cls):
- """For ServiceTemplate one-to-many to PolicyTemplate"""
- return relationship.foreign_key('service_template')
-
- # endregion
-
# region association proxies
# endregion
@@ -803,10 +879,20 @@ class PolicyTemplateBase(TemplateModelMixin):
@declared_attr
def policies(cls):
+ """
+ Instantiated policies.
+
+ :type: [:class:`Policy`]
+ """
return relationship.one_to_many(cls, 'policy')
@declared_attr
def properties(cls):
+ """
+ Declarations for associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
# endregion
@@ -815,10 +901,20 @@ class PolicyTemplateBase(TemplateModelMixin):
@declared_attr
def service_template(cls):
+ """
+ Containing service template.
+
+ :type: :class:`ServiceTemplate`
+ """
return relationship.many_to_one(cls, 'service_template')
@declared_attr
def type(cls):
+ """
+ Policy type.
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(cls, 'type', back_populates=relationship.NO_BACK_POP)
# endregion
@@ -827,15 +923,43 @@ class PolicyTemplateBase(TemplateModelMixin):
@declared_attr
def node_templates(cls):
+ """
+ Policy will be enacted on all nodes instantiated by these templates.
+
+ :type: {:obj:`basestring`: :class:`NodeTemplate`}
+ """
return relationship.many_to_many(cls, 'node_template')
@declared_attr
def group_templates(cls):
+ """
+ Policy will be enacted on all nodes in all groups instantiated by these templates.
+
+ :type: {:obj:`basestring`: :class:`GroupTemplate`}
+ """
return relationship.many_to_many(cls, 'group_template')
# endregion
- description = Column(Text)
+ # region foreign keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For PolicyTemplate many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def service_template_fk(cls):
+ """For ServiceTemplate one-to-many to PolicyTemplate"""
+ return relationship.foreign_key('service_template')
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
@property
def as_raw(self):
@@ -884,31 +1008,14 @@ class PolicyTemplateBase(TemplateModelMixin):
class SubstitutionTemplateBase(TemplateModelMixin):
"""
- Used to substitute a single node for the entire deployment.
-
- :ivar node_type: exposed node type
- :vartype node_type: Type
- :ivar mappings: requirement and capability mappings
- :vartype mappings: {:obj:`basestring`: :class:`SubstitutionTemplateMapping`}
- :ivar service_template: containing service template
- :vartype service_template: :class:`ServiceTemplate`
- :ivar substitutions: instantiated substitutions
- :vartype substitutions: [:class:`Substitution`]
+ Template for creating a :class:`Substitution` instance, which exposes an entire instantiated
+ service as a single node.
"""
__tablename__ = 'substitution_template'
__private_fields__ = ('node_type_fk',)
- # region foreign keys
-
- @declared_attr
- def node_type_fk(cls):
- """For SubstitutionTemplate many-to-one to Type"""
- return relationship.foreign_key('type')
-
- # endregion
-
# region association proxies
# endregion
@@ -921,10 +1028,20 @@ class SubstitutionTemplateBase(TemplateModelMixin):
@declared_attr
def substitutions(cls):
+ """
+ Instantiated substitutions.
+
+ :type: [:class:`Substitution`]
+ """
return relationship.one_to_many(cls, 'substitution')
@declared_attr
def mappings(cls):
+ """
+ Map requirement and capabilities to exposed node.
+
+ :type: {:obj:`basestring`: :class:`SubstitutionTemplateMapping`}
+ """
return relationship.one_to_many(cls, 'substitution_template_mapping', dict_key='name')
# endregion
@@ -933,10 +1050,24 @@ class SubstitutionTemplateBase(TemplateModelMixin):
@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 SubstitutionTemplate many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ # endregion
+
@property
def as_raw(self):
return collections.OrderedDict((
@@ -966,53 +1097,21 @@ class SubstitutionTemplateBase(TemplateModelMixin):
class SubstitutionTemplateMappingBase(TemplateModelMixin):
"""
- Used by :class:`SubstitutionTemplate` to map a capability or a requirement to a node.
-
- Only one of `capability_template` and `requirement_template` can be set.
-
- :ivar name: exposed capability or requirement name
- :vartype name: basestring
- :ivar node_template: node template
- :vartype node_template: NodeTemplate
- :ivar capability_template: capability template in the node template
- :vartype capability_template: CapabilityTemplate
- :ivar requirement_template: requirement template in the node template
- :vartype requirement_template: RequirementTemplate
- :ivar substitution_template: containing substitution template
- :vartype substitution_template: SubstitutionTemplate
+ Used by :class:`SubstitutionTemplate` to map a capability template or a requirement template to
+ the exposed node.
+
+ The :attr:`name` field should match the capability or requirement name on the exposed node's
+ type.
+
+ Only one of :attr:`capability_template` and :attr:`requirement_template` can be set.
"""
__tablename__ = 'substitution_template_mapping'
__private_fields__ = ('substitution_template_fk',
- 'node_template_fk',
'capability_template_fk',
'requirement_template_fk')
- # region foreign keys
-
- @declared_attr
- def substitution_template_fk(cls):
- """For SubstitutionTemplate one-to-many to SubstitutionTemplateMapping"""
- return relationship.foreign_key('substitution_template')
-
- @declared_attr
- def node_template_fk(cls):
- """For SubstitutionTemplate one-to-one to NodeTemplate"""
- return relationship.foreign_key('node_template')
-
- @declared_attr
- def capability_template_fk(cls):
- """For SubstitutionTemplate one-to-one to CapabilityTemplate"""
- return relationship.foreign_key('capability_template', nullable=True)
-
- @declared_attr
- def requirement_template_fk(cls):
- """For SubstitutionTemplate one-to-one to RequirementTemplate"""
- return relationship.foreign_key('requirement_template', nullable=True)
-
- # endregion
-
# region association proxies
# endregion
@@ -1020,17 +1119,22 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
# region one_to_one relationships
@declared_attr
- def node_template(cls):
- return relationship.one_to_one(
- cls, 'node_template', back_populates=relationship.NO_BACK_POP)
-
- @declared_attr
def capability_template(cls):
+ """
+ Capability template to expose (can be ``None``).
+
+ :type: :class:`CapabilityTemplate`
+ """
return relationship.one_to_one(
cls, 'capability_template', back_populates=relationship.NO_BACK_POP)
@declared_attr
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)
@@ -1044,10 +1148,34 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
@declared_attr
def substitution_template(cls):
+ """
+ Containing substitution template.
+
+ :type: :class:`SubstitutionTemplate`
+ """
return relationship.many_to_one(cls, 'substitution_template', back_populates='mappings')
# endregion
+ # region foreign keys
+
+ @declared_attr
+ def substitution_template_fk(cls):
+ """For SubstitutionTemplate one-to-many to SubstitutionTemplateMapping"""
+ return relationship.foreign_key('substitution_template')
+
+ @declared_attr
+ def capability_template_fk(cls):
+ """For SubstitutionTemplate one-to-one to CapabilityTemplate"""
+ return relationship.foreign_key('capability_template', nullable=True)
+
+ @declared_attr
+ def requirement_template_fk(cls):
+ """For SubstitutionTemplate one-to-one to RequirementTemplate"""
+ return relationship.foreign_key('requirement_template', nullable=True)
+
+ # endregion
+
@property
def as_raw(self):
return collections.OrderedDict((
@@ -1059,7 +1187,11 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
def instantiate(self, container):
from . import models
context = ConsumptionContext.get_thread_local()
- nodes = self.node_template.nodes
+ if self.capability_template is not None:
+ node_template = self.capability_template.node_template
+ else:
+ node_template = self.requirement_template.node_template
+ nodes = node_template.nodes
if len(nodes) == 0:
context.validation.report(
'mapping "{0}" refers to node template "{1}" but there are no '
@@ -1075,9 +1207,10 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
if a_capability.capability_template.name == self.capability_template.name:
capability = a_capability
return models.SubstitutionMapping(name=self.name,
- node=node,
capability=capability,
- requirement_template=self.requirement_template)
+ requirement_template=self.requirement_template,
+ node=node)
+
def validate(self):
context = ConsumptionContext.get_thread_local()
@@ -1090,9 +1223,13 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
def dump(self):
context = ConsumptionContext.get_thread_local()
+ if self.capability_template is not None:
+ node_template = self.capability_template.node_template
+ else:
+ node_template = self.requirement_template.node_template
console.puts('{0} -> {1}.{2}'.format(
context.style.node(self.name),
- context.style.node(self.node_template.name),
+ context.style.node(node_template.name),
context.style.node(self.capability_template.name
if self.capability_template
else self.requirement_template.name)))
@@ -1100,70 +1237,26 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin):
class RequirementTemplateBase(TemplateModelMixin):
"""
- A requirement for a :class:`NodeTemplate`. During instantiation will be matched with a
- capability of another node.
-
- Requirements may optionally contain a :class:`RelationshipTemplate` that will be created between
- the nodes.
-
- :ivar name: name (a node template can have multiple requirements with the same name)
- :vartype name: basestring
- :ivar target_node_type: required node type (optional)
- :vartype target_node_type: Type
- :ivar target_node_template: required node template (optional)
- :vartype target_node_template: NodeTemplate
- :ivar target_capability_type: required capability type (optional)
- :vartype target_capability_type: Type
- :ivar target_capability_name: name of capability in target node (optional)
- :vartype target_capability_name: basestring
- :ivar target_node_template_constraints: constraints for filtering relationship targets
- :vartype target_node_template_constraints: [:class:`NodeTemplateConstraint`]
- :ivar relationship_template: template for relationships (optional)
- :vartype relationship_template: RelationshipTemplate
- :ivar node_template: containing node template
- :vartype node_template: NodeTemplate
- :ivar substitution_template_mapping: our contribution to service substitution
- :vartype substitution_template_mapping: :class:`SubstitutionTemplateMapping`
- :ivar substitution_mapping: our contribution to service substitution
- :vartype substitution_mapping: SubstitutionMapping
- """
-
- __tablename__ = 'requirement_template'
-
- __private_fields__ = ('target_node_type_fk',
- 'target_node_template_fk',
- 'target_capability_type_fk'
- 'node_template_fk',
- 'relationship_template_fk')
-
- # region foreign keys
-
- @declared_attr
- def target_node_type_fk(cls):
- """For RequirementTemplate many-to-one to Type"""
- return relationship.foreign_key('type', nullable=True)
+ Template for creating :class:`Relationship` instances, which are optionally-typed edges in the
+ service topology, connecting a :class:`Node` to a :class:`Capability` of another node.
- @declared_attr
- def target_node_template_fk(cls):
- """For RequirementTemplate one-to-one to NodeTemplate"""
- return relationship.foreign_key('node_template', nullable=True)
+ Note that there is no equivalent "Requirement" instance model. Instead, during instantiation a
+ requirement template is matched with a capability and a :class:`Relationship` is instantiated.
- @declared_attr
- def target_capability_type_fk(cls):
- """For RequirementTemplate one-to-one to NodeTemplate"""
- return relationship.foreign_key('type', nullable=True)
+ A requirement template *must* target a :class:`CapabilityType` or a capability name. It can
+ optionally target a specific :class:`NodeType` or :class:`NodeTemplate`.
- @declared_attr
- def node_template_fk(cls):
- """For NodeTemplate one-to-many to RequirementTemplate"""
- return relationship.foreign_key('node_template')
+ Requirement templates may optionally contain a :class:`RelationshipTemplate`. If they do not,
+ a :class:`Relationship` will be instantiated with default values.
+ """
- @declared_attr
- def relationship_template_fk(cls):
- """For RequirementTemplate one-to-one to RelationshipTemplate"""
- return relationship.foreign_key('relationship_template', nullable=True)
+ __tablename__ = 'requirement_template'
- # endregion
+ __private_fields__ = ('target_capability_type_fk',
+ 'target_node_template_fk',
+ 'target_node_type_fk',
+ 'relationship_template_fk',
+ 'node_template_fk')
# region association proxies
@@ -1172,21 +1265,36 @@ class RequirementTemplateBase(TemplateModelMixin):
# region one_to_one relationships
@declared_attr
- def target_node_template(cls):
+ def target_capability_type(cls):
+ """
+ Target capability type.
+
+ :type: :class:`CapabilityType`
+ """
return relationship.one_to_one(cls,
- 'node_template',
- fk='target_node_template_fk',
+ 'type',
+ fk='target_capability_type_fk',
back_populates=relationship.NO_BACK_POP)
@declared_attr
- def target_capability_type(cls):
+ def target_node_template(cls):
+ """
+ Target node template (can be ``None``).
+
+ :type: :class:`NodeTemplate`
+ """
return relationship.one_to_one(cls,
- 'type',
- fk='target_capability_type_fk',
+ 'node_template',
+ fk='target_node_template_fk',
back_populates=relationship.NO_BACK_POP)
@declared_attr
def relationship_template(cls):
+ """
+ Associated relationship template (can be ``None``).
+
+ :type: :class:`RelationshipTemplate`
+ """
return relationship.one_to_one(cls, 'relationship_template')
# endregion
@@ -1195,6 +1303,11 @@ class RequirementTemplateBase(TemplateModelMixin):
@declared_attr
def relationships(cls):
+ """
+ Instantiated relationships.
+
+ :type: [:class:`Relationship`]
+ """
return relationship.one_to_many(cls, 'relationship')
# endregion
@@ -1203,17 +1316,65 @@ class RequirementTemplateBase(TemplateModelMixin):
@declared_attr
def node_template(cls):
+ """
+ Containing node template.
+
+ :type: :class:`NodeTemplate`
+ """
return relationship.many_to_one(cls, 'node_template', fk='node_template_fk')
@declared_attr
def target_node_type(cls):
+ """
+ Target node type (can be ``None``).
+
+ :type: :class:`Type`
+ """
return relationship.many_to_one(
cls, 'type', fk='target_node_type_fk', back_populates=relationship.NO_BACK_POP)
# endregion
- target_capability_name = Column(Text)
- target_node_template_constraints = Column(PickleType)
+ # region foreign keys
+
+ @declared_attr
+ def target_node_type_fk(cls):
+ """For RequirementTemplate many-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ @declared_attr
+ def target_node_template_fk(cls):
+ """For RequirementTemplate one-to-one to NodeTemplate"""
+ return relationship.foreign_key('node_template', nullable=True)
+
+ @declared_attr
+ def target_capability_type_fk(cls):
+ """For RequirementTemplate one-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ @declared_attr
+ def node_template_fk(cls):
+ """For NodeTemplate one-to-many to RequirementTemplate"""
+ return relationship.foreign_key('node_template')
+
+ @declared_attr
+ def relationship_template_fk(cls):
+ """For RequirementTemplate one-to-one to RelationshipTemplate"""
+ return relationship.foreign_key('relationship_template', nullable=True)
+
+ # endregion
+
+ target_capability_name = Column(Text, doc="""
+ Target capability name in node template or node type (can be ``None``).
+
+ :type: :obj:`basestring`
+ """)
+
+ target_node_template_constraints = Column(PickleType, doc="""
+ Constraints for filtering relationship targets.
+
+ :type: [:class:`NodeTemplateConstraint`]
+ """)
def find_target(self, source_node_template):
context = ConsumptionContext.get_thread_local()
@@ -1318,43 +1479,18 @@ class RequirementTemplateBase(TemplateModelMixin):
class RelationshipTemplateBase(TemplateModelMixin):
"""
- Optional addition to a :class:`RequirementTemplate` in :class:`NodeTemplate` that can be applied
- when the requirement is matched with a capability.
-
- Note that a relationship template here is not equivalent to a relationship template entity in
- TOSCA. For example, a TOSCA requirement specifying a relationship type instead of a template
- would still be represented here as a relationship template.
+ Optional addition to a :class:`RequirementTemplate`.
- :ivar name: name (optional; if present is unique for this service template)
- :vartype name: basestring
- :ivar type: relationship type
-
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar interface_templates: bundles of operations
- :vartype interface_templates: {:obj:`basestring`: :class:`InterfaceTemplate`}
- :ivar requirement_template: containing requirement template
- :vartype requirement_template: RequirementTemplate
- :ivar relationships: instantiated relationships
- :vartype relationships: [:class:`Relationship`]
+ Note that a relationship template here is not exactly equivalent to a relationship template
+ entity in TOSCA. For example, a TOSCA requirement specifying a relationship type rather than a
+ relationship template would still be represented here as a relationship template.
"""
__tablename__ = 'relationship_template'
__private_fields__ = ('type_fk',)
- # region foreign keys
-
- @declared_attr
- def type_fk(cls):
- """For RelationshipTemplate many-to-one to Type"""
- return relationship.foreign_key('type', nullable=True)
-
- # endregion
-
- # region association proxies
+ # region association proxies
# endregion
@@ -1366,14 +1502,29 @@ class RelationshipTemplateBase(TemplateModelMixin):
@declared_attr
def relationships(cls):
+ """
+ Instantiated relationships.
+
+ :type: [:class:`Relationship`]
+ """
return relationship.one_to_many(cls, 'relationship')
@declared_attr
def interface_templates(cls):
+ """
+ Associated interface templates.
+
+ :type: {:obj:`basestring`: :class:`InterfaceTemplate`}
+ """
return relationship.one_to_many(cls, 'interface_template', dict_key='name')
@declared_attr
def properties(cls):
+ """
+ Declarations for associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
# endregion
@@ -1382,11 +1533,29 @@ class RelationshipTemplateBase(TemplateModelMixin):
@declared_attr
def type(cls):
+ """
+ Relationship 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 RelationshipTemplate many-to-one to Type"""
+ return relationship.foreign_key('type', nullable=True)
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
@property
def as_raw(self):
@@ -1431,29 +1600,9 @@ class RelationshipTemplateBase(TemplateModelMixin):
class CapabilityTemplateBase(TemplateModelMixin):
"""
- A capability of a :class:`NodeTemplate`. Nodes expose zero or more capabilities that can be
- matched with :class:`Requirement` instances of other nodes.
-
- :ivar name: name (unique for the node template)
- :vartype name: basestring
- :ivar type: capability type
-
- :ivar description: human-readable description
- :vartype description: basestring
- :ivar valid_source_node_types: reject requirements that are not from these node types (optional)
- :vartype valid_source_node_types: 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 properties: associated parameters
- :vartype properties: {:obj:`basestring`: :class:`Property`}
- :ivar node_template: containing node template
- :vartype node_template: NodeTemplate
- :ivar substitution_template_mapping: our contribution to service substitution
- :vartype substitution_template_mapping: SubstitutionTemplateMapping
- :ivar capabilities: instantiated capabilities
- :vartype capabilities: [:class:`Capability`]
+ Template for creating :class:`Capability` instances, typed attachments which serve two purposes:
+ to provide extra properties and attributes to :class:`Node` instances, and to expose targets for
+ :class:`Relationship` instances from other nodes.
"""
__tablename__ = 'capability_template'
@@ -1461,21 +1610,6 @@ class CapabilityTemplateBase(TemplateModelMixin):
__private_fields__ = ('type_fk',
'node_template_fk')
- # region foreign keys
-
- @declared_attr
- def type_fk(cls):
- """For CapabilityTemplate many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def node_template_fk(cls):
- """For NodeTemplate one-to-many to CapabilityTemplate"""
- return relationship.foreign_key('node_template')
-
- # endregion
-
-
# region association proxies
# endregion
@@ -1488,10 +1622,20 @@ class CapabilityTemplateBase(TemplateModelMixin):
@declared_attr
def capabilities(cls):
+ """
+ Instantiated capabilities.
+
+ :type: [:class:`Capability`]
+ """
return relationship.one_to_many(cls, 'capability')
@declared_attr
def properties(cls):
+ """
+ Declarations for associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
# endregion
@@ -1500,10 +1644,20 @@ class CapabilityTemplateBase(TemplateModelMixin):
@declared_attr
def node_template(cls):
+ """
+ Containing node template.
+
+ :type: :class:`NodeTemplate`
+ """
return relationship.many_to_one(cls, 'node_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
@@ -1512,13 +1666,46 @@ class CapabilityTemplateBase(TemplateModelMixin):
@declared_attr
def valid_source_node_types(cls):
+ """
+ Reject requirements that are not from these node types.
+
+ :type: [:class:`Type`]
+ """
return relationship.many_to_many(cls, 'type', prefix='valid_sources')
# endregion
- description = Column(Text)
- min_occurrences = Column(Integer, default=None) # optional
- max_occurrences = Column(Integer, default=None) # optional
+ # region foreign keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For CapabilityTemplate many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def node_template_fk(cls):
+ """For NodeTemplate one-to-many to CapabilityTemplate"""
+ return relationship.foreign_key('node_template')
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
+
+ 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`
+ """)
def satisfies_requirement(self,
source_node_template,
@@ -1593,26 +1780,11 @@ class CapabilityTemplateBase(TemplateModelMixin):
class InterfaceTemplateBase(TemplateModelMixin):
"""
- A typed set of :class:`OperationTemplate`.
+ Template for creating :class:`Interface` instances, which are typed bundles of
+ :class:`Operation` instances.
- :ivar name: name (unique for the node, group, or relationship template)
- :vartype name: basestring
- :ivar type: interface 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 operation_templates: operations
- :vartype operation_templates: {:obj:`basestring`: :class:`OperationTemplate`}
- :ivar node_template: containing node template
- :vartype node_template: NodeTemplate
- :ivar group_template: containing group template
- :vartype group_template: GroupTemplate
- :ivar relationship_template: containing relationship template
- :vartype relationship_template: RelationshipTemplate
- :ivar interfaces: instantiated interfaces
- :vartype interfaces: [:class:`Interface`]
+ Can be associated with a :class:`NodeTemplate`, a :class:`GroupTemplate`, or a
+ :class:`RelationshipTemplate`.
"""
__tablename__ = 'interface_template'
@@ -1622,30 +1794,6 @@ class InterfaceTemplateBase(TemplateModelMixin):
'group_template_fk',
'relationship_template_fk')
- # region foreign keys
-
- @declared_attr
- def type_fk(cls):
- """For InterfaceTemplate many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def node_template_fk(cls):
- """For NodeTemplate one-to-many to InterfaceTemplate"""
- return relationship.foreign_key('node_template', nullable=True)
-
- @declared_attr
- def group_template_fk(cls):
- """For GroupTemplate one-to-many to InterfaceTemplate"""
- return relationship.foreign_key('group_template', nullable=True)
-
- @declared_attr
- def relationship_template_fk(cls):
- """For RelationshipTemplate one-to-many to InterfaceTemplate"""
- return relationship.foreign_key('relationship_template', nullable=True)
-
- # endregion
-
# region association proxies
# endregion
@@ -1658,14 +1806,30 @@ class InterfaceTemplateBase(TemplateModelMixin):
@declared_attr
def inputs(cls):
+ """
+ Declarations for externally provided parameters that can be used by all operations of the
+ interface.
+
+ :type: {:obj:`basestring`: :class:`Input`}
+ """
return relationship.one_to_many(cls, 'input', dict_key='name')
@declared_attr
def interfaces(cls):
+ """
+ Instantiated interfaces.
+
+ :type: [:class:`Interface`]
+ """
return relationship.one_to_many(cls, 'interface')
@declared_attr
def operation_templates(cls):
+ """
+ Associated operation templates.
+
+ :type: {:obj:`basestring`: :class:`OperationTemplate`}
+ """
return relationship.one_to_many(cls, 'operation_template', dict_key='name')
# endregion
@@ -1673,24 +1837,72 @@ class InterfaceTemplateBase(TemplateModelMixin):
# region many_to_one relationships
@declared_attr
- def relationship_template(cls):
- return relationship.many_to_one(cls, 'relationship_template')
+ def node_template(cls):
+ """
+ Containing node template (can be ``None``).
+
+ :type: :class:`NodeTemplate`
+ """
+ return relationship.many_to_one(cls, 'node_template')
@declared_attr
def group_template(cls):
+ """
+ Containing group template (can be ``None``).
+
+ :type: :class:`GroupTemplate`
+ """
return relationship.many_to_one(cls, 'group_template')
@declared_attr
- def node_template(cls):
- return relationship.many_to_one(cls, 'node_template')
+ def relationship_template(cls):
+ """
+ Containing relationship template (can be ``None``).
+
+ :type: :class:`RelationshipTemplate`
+ """
+ return relationship.many_to_one(cls, 'relationship_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 InterfaceTemplate many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def node_template_fk(cls):
+ """For NodeTemplate one-to-many to InterfaceTemplate"""
+ return relationship.foreign_key('node_template', nullable=True)
+
+ @declared_attr
+ def group_template_fk(cls):
+ """For GroupTemplate one-to-many to InterfaceTemplate"""
+ return relationship.foreign_key('group_template', nullable=True)
+
+ @declared_attr
+ def relationship_template_fk(cls):
+ """For RelationshipTemplate one-to-many to InterfaceTemplate"""
+ return relationship.foreign_key('relationship_template', nullable=True)
+
+ # endregion
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
@property
def as_raw(self):
@@ -1733,42 +1945,8 @@ class InterfaceTemplateBase(TemplateModelMixin):
class OperationTemplateBase(TemplateModelMixin):
"""
- An operation in a :class:`InterfaceTemplate`.
-
- Operations are executed by an associated :class:`PluginSpecification` via an executor.
-
- :ivar name: name (unique for the interface or service template)
- :vartype name: basestring
- :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: inputs that can be used by this operation
- :vartype inputs: {:obj:`basestring`: :class:`Input`}
- :ivar plugin_specification: associated plugin
- :vartype plugin_specification: PluginSpecification
- :ivar configurations: configuration (interpreted by the plugin)
- :vartype configurations: {obj:`basestring`: :class:`Configuration`}
- :ivar function: name of the operation function
- :vartype function: basestring
- :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_template: containing interface template
- :vartype interface_template: InterfaceTemplate
- :ivar service_template: containing service template
- :vartype service_template: ServiceTemplate
- :ivar operations: instantiated operations
- :vartype operations: [:class:`Operation`]
+ Template for creating :class:`Operation` instances, which are entry points to Python functions
+ called as part of a workflow execution.
"""
__tablename__ = 'operation_template'
@@ -1777,25 +1955,6 @@ class OperationTemplateBase(TemplateModelMixin):
'interface_template_fk',
'plugin_fk')
- # region foreign keys
-
- @declared_attr
- def service_template_fk(cls):
- """For ServiceTemplate one-to-many to OperationTemplate"""
- return relationship.foreign_key('service_template', nullable=True)
-
- @declared_attr
- def interface_template_fk(cls):
- """For InterfaceTemplate one-to-many to OperationTemplate"""
- return relationship.foreign_key('interface_template', nullable=True)
-
- @declared_attr
- def plugin_specification_fk(cls):
- """For OperationTemplate one-to-one to PluginSpecification"""
- return relationship.foreign_key('plugin_specification', nullable=True)
-
- # endregion
-
# region association proxies
# endregion
@@ -1804,6 +1963,11 @@ class OperationTemplateBase(TemplateModelMixin):
@declared_attr
def plugin_specification(cls):
+ """
+ Associated plugin specification.
+
+ :type: :class:`PluginSpecification`
+ """
return relationship.one_to_one(
cls, 'plugin_specification', back_populates=relationship.NO_BACK_POP)
@@ -1812,15 +1976,30 @@ class OperationTemplateBase(TemplateModelMixin):
# region one_to_many relationships
@declared_attr
- def inputs(cls):
- return relationship.one_to_many(cls, 'input', dict_key='name')
-
- @declared_attr
def operations(cls):
+ """
+ Instantiated operations.
+
+ :type: [:class:`Operation`]
+ """
return relationship.one_to_many(cls, 'operation')
@declared_attr
+ def inputs(cls):
+ """
+ Declarations for parameters provided to the :attr:`implementation`.
+
+ :type: {:obj:`basestring`: :class:`Input`}
+ """
+ return relationship.one_to_many(cls, 'input', dict_key='name')
+
+ @declared_attr
def configurations(cls):
+ """
+ Configuration parameters for the operation instance Python :attr:`function`.
+
+ :type: {:obj:`basestring`: :class:`Configuration`}
+ """
return relationship.one_to_many(cls, 'configuration', dict_key='name')
# endregion
@@ -1829,11 +2008,21 @@ class OperationTemplateBase(TemplateModelMixin):
@declared_attr
def service_template(cls):
+ """
+ Containing service template (can be ``None``). For workflow operation templates.
+
+ :type: :class:`ServiceTemplate`
+ """
return relationship.many_to_one(cls, 'service_template',
back_populates='workflow_templates')
@declared_attr
def interface_template(cls):
+ """
+ Containing interface template (can be ``None``).
+
+ :type: :class:`InterfaceTemplate`
+ """
return relationship.many_to_one(cls, 'interface_template')
# endregion
@@ -1842,14 +2031,73 @@ class OperationTemplateBase(TemplateModelMixin):
# 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_template_fk(cls):
+ """For ServiceTemplate one-to-many to OperationTemplate"""
+ return relationship.foreign_key('service_template', nullable=True)
+
+ @declared_attr
+ def interface_template_fk(cls):
+ """For InterfaceTemplate one-to-many to OperationTemplate"""
+ return relationship.foreign_key('interface_template', nullable=True)
+
+ @declared_attr
+ def plugin_specification_fk(cls):
+ """For OperationTemplate one-to-one to PluginSpecification"""
+ return relationship.foreign_key('plugin_specification', 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`
+ """)
@property
def as_raw(self):
@@ -1922,28 +2170,8 @@ class OperationTemplateBase(TemplateModelMixin):
class ArtifactTemplateBase(TemplateModelMixin):
"""
- A file associated with a :class:`NodeTemplate`.
-
- :ivar name: name (unique for the node template)
- :vartype name: basestring
- :ivar type: artifact 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_template: containing node template
- :vartype node_template: NodeTemplate
- :ivar artifacts: instantiated artifacts
- :vartype artifacts: [:class:`Artifact`]
+ Template for creating an :class:`Artifact` instance, which is a typed file, either provided in a
+ CSAR or downloaded from a repository.
"""
__tablename__ = 'artifact_template'
@@ -1951,20 +2179,6 @@ class ArtifactTemplateBase(TemplateModelMixin):
__private_fields__ = ('type_fk',
'node_template_fk')
- # region foreign keys
-
- @declared_attr
- def type_fk(cls):
- """For ArtifactTemplate many-to-one to Type"""
- return relationship.foreign_key('type')
-
- @declared_attr
- def node_template_fk(cls):
- """For NodeTemplate one-to-many to ArtifactTemplate"""
- return relationship.foreign_key('node_template')
-
- # endregion
-
# region association proxies
# endregion
@@ -1977,10 +2191,20 @@ class ArtifactTemplateBase(TemplateModelMixin):
@declared_attr
def artifacts(cls):
+ """
+ Instantiated artifacts.
+
+ :type: [:class:`Artifact`]
+ """
return relationship.one_to_many(cls, 'artifact')
@declared_attr
def properties(cls):
+ """
+ Declarations for associated immutable parameters.
+
+ :type: {:obj:`basestring`: :class:`Property`}
+ """
return relationship.one_to_many(cls, 'property', dict_key='name')
# endregion
@@ -1989,19 +2213,67 @@ class ArtifactTemplateBase(TemplateModelMixin):
@declared_attr
def node_template(cls):
+ """
+ Containing node template.
+
+ :type: :class:`NodeTemplate`
+ """
return relationship.many_to_one(cls, 'node_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
- description = Column(Text)
- source_path = Column(Text)
- target_path = Column(Text)
- repository_url = Column(Text)
- repository_credential = Column(modeling_types.StrictDict(basestring, basestring))
+ # region foreign keys
+
+ @declared_attr
+ def type_fk(cls):
+ """For ArtifactTemplate many-to-one to Type"""
+ return relationship.foreign_key('type')
+
+ @declared_attr
+ def node_template_fk(cls):
+ """For NodeTemplate one-to-many to ArtifactTemplate"""
+ return relationship.foreign_key('node_template')
+
+ # endregion
+
+ 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):
@@ -2055,16 +2327,9 @@ class ArtifactTemplateBase(TemplateModelMixin):
class PluginSpecificationBase(TemplateModelMixin):
"""
- Plugin specification.
-
- :ivar name: required plugin name
- :vartype name: basestring
- :ivar version: minimum plugin version
- :vartype version: basestring
- :ivar enabled: whether the plugin is enabled
- :vartype enabled: bool
- :ivar plugin: the matching plugin (or ``None`` if not matched)
- :vartype plugin: Plugin
+ Requirement for a :class:`Plugin`.
+
+ The actual plugin to be selected depends on those currently installed in ARIA.
"""
__tablename__ = 'plugin_specification'
@@ -2072,35 +2337,54 @@ class PluginSpecificationBase(TemplateModelMixin):
__private_fields__ = ('service_template_fk',
'plugin_fk')
- version = Column(Text)
- enabled = Column(Boolean, nullable=False, default=True)
-
- # region foreign keys
+ version = Column(Text, doc="""
+ Minimum plugin version.
- @declared_attr
- def service_template_fk(cls):
- """For ServiceTemplate one-to-many to PluginSpecification"""
- return relationship.foreign_key('service_template', nullable=True)
+ :type: :obj:`basestring`
+ """)
- @declared_attr
- def plugin_fk(cls):
- """For PluginSpecification many-to-one to Plugin"""
- return relationship.foreign_key('plugin', nullable=True)
+ enabled = Column(Boolean, nullable=False, default=True, doc="""
+ Whether the plugin is enabled.
- # endregion
+ :type: :obj:`bool`
+ """)
# region many_to_one relationships
@declared_attr
def service_template(cls):
+ """
+ Containing service template.
+
+ :type: :class:`ServiceTemplate`
+ """
return relationship.many_to_one(cls, 'service_template')
@declared_attr
def plugin(cls): # pylint: disable=method-hidden
+ """
+ Matched plugin.
+
+ :type: :class:`Plugin`
+ """
return relationship.many_to_one(cls, 'plugin', back_populates=relationship.NO_BACK_POP)
# endregion
+ # region foreign keys
+
+ @declared_attr
+ def service_template_fk(cls):
+ """For ServiceTemplate one-to-many to PluginSpecification"""
+ return relationship.foreign_key('service_template', nullable=True)
+
+ @declared_attr
+ def plugin_fk(cls):
+ """For PluginSpecification many-to-one to Plugin"""
+ return relationship.foreign_key('plugin', nullable=True)
+
+ # endregion
+
@property
def as_raw(self):
return collections.OrderedDict((
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/types.py
----------------------------------------------------------------------
diff --git a/aria/modeling/types.py b/aria/modeling/types.py
index 4c25f93..c34326e 100644
--- a/aria/modeling/types.py
+++ b/aria/modeling/types.py
@@ -14,7 +14,7 @@
# limitations under the License.
"""
-Allows JSON-serializable collections to be used as SQLAlchemy column types.
+Allows JSON-serializable collections to be used as SQLAlchemy column types.
"""
import json
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/utils.py
----------------------------------------------------------------------
diff --git a/aria/modeling/utils.py b/aria/modeling/utils.py
index 9d02194..a60a7a5 100644
--- a/aria/modeling/utils.py
+++ b/aria/modeling/utils.py
@@ -34,9 +34,9 @@ class ModelJSONEncoder(JSONEncoder):
JSON encoder that automatically unwraps ``value`` attributes.
"""
def __init__(self, *args, **kwargs):
- # Hack to make sure Sphinx doesn't grab the base constructor's docstring
- super(self, JSONEncoder).__init__(*args, **kwargs)
-
+ # Just here to make sure Sphinx doesn't grab the base constructor's docstring
+ super(ModelJSONEncoder, self).__init__(*args, **kwargs)
+
def default(self, o): # pylint: disable=method-hidden
from .mixins import ModelMixin
if isinstance(o, ModelMixin):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/parser/loading/context.py
----------------------------------------------------------------------
diff --git a/aria/parser/loading/context.py b/aria/parser/loading/context.py
index e4ada0e..1d1aaf6 100644
--- a/aria/parser/loading/context.py
+++ b/aria/parser/loading/context.py
@@ -23,7 +23,7 @@ class LoadingContext(object):
Properties:
:ivar loader_source: for finding loader instances
- :vartype loader_source: LoaderSource
+ :vartype loader_source: LoaderSource
:ivar prefixes: additional prefixes for :class:`UriTextLoader`
:vartype prefixes: [:obj:`basestring`]
"""
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/parser/presentation/presentation.py
----------------------------------------------------------------------
diff --git a/aria/parser/presentation/presentation.py b/aria/parser/presentation/presentation.py
index b92506c..0fcb9e4 100644
--- a/aria/parser/presentation/presentation.py
+++ b/aria/parser/presentation/presentation.py
@@ -183,8 +183,8 @@ class Presentation(PresentationBase):
ARIA presentation classes will often be decorated with ``@has_fields``, as that mechanism
automates a lot of field-specific validation. However, that is not a requirement.
- Make sure that your utility property and method names begin with a "\_", because those names
- without a "\_" prefix are normally reserved for fields.
+ Make sure that your utility property and method names begin with a ``_``, because those names
+ without a ``_`` prefix are normally reserved for fields.
"""
def _validate(self, context):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/utils/caching.py
----------------------------------------------------------------------
diff --git a/aria/utils/caching.py b/aria/utils/caching.py
index 5c82b0d..4c3d82b 100644
--- a/aria/utils/caching.py
+++ b/aria/utils/caching.py
@@ -43,7 +43,7 @@ class cachedmethod(object): # pylint: disable=invalid-name
ENABLED = True
def __init__(self, func):
- self.__doc__ = func.__doc__
+ self.__doc__ = func.__doc__
self.func = func
self.hits = 0
self.misses = 0
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/utils/collections.py
----------------------------------------------------------------------
diff --git a/aria/utils/collections.py b/aria/utils/collections.py
index 89bb390..d8b7e90 100644
--- a/aria/utils/collections.py
+++ b/aria/utils/collections.py
@@ -36,8 +36,7 @@ class FrozenList(list):
"""
An immutable list.
- After initialization it will raise :class:`TypeError` exceptions if modification
- is attempted.
+ After initialization it will raise :class:`TypeError` exceptions if modification is attempted.
Note that objects stored in the list may not be immutable.
"""
@@ -82,12 +81,12 @@ class FrozenList(list):
EMPTY_READ_ONLY_LIST = FrozenList()
+
class FrozenDict(OrderedDict):
"""
An immutable ordered dict.
- After initialization it will raise :class:`TypeError` exceptions if modification
- is attempted.
+ After initialization it will raise :class:`TypeError` exceptions if modification is attempted.
Note that objects stored in the dict may not be immutable.
"""
@@ -113,6 +112,7 @@ class FrozenDict(OrderedDict):
EMPTY_READ_ONLY_DICT = FrozenDict()
+
class StrictList(list):
"""
A list that raises :class:`TypeError` exceptions when objects of the wrong type are inserted.
@@ -172,10 +172,11 @@ class StrictList(list):
value = self._wrap(value)
return super(StrictList, self).insert(index, value)
+
class StrictDict(OrderedDict):
"""
- An ordered dict that raises :class:`TypeError` exceptions
- when keys or values of the wrong type are used.
+ An ordered dict that raises :class:`TypeError` exceptions when keys or values of the wrong type
+ are used.
"""
def __init__(self,
@@ -215,6 +216,7 @@ class StrictDict(OrderedDict):
value = self.wrapper_function(value)
return super(StrictDict, self).__setitem__(key, value)
+
def merge(dict_a, dict_b, path=None, strict=False):
"""
Merges dicts, recursively.
@@ -238,9 +240,11 @@ def merge(dict_a, dict_b, path=None, strict=False):
dict_a[key] = value_b
return dict_a
+
def is_removable(_container, _key, v):
return (v is None) or ((isinstance(v, dict) or isinstance(v, list)) and (len(v) == 0))
+
def prune(value, is_removable_function=is_removable):
"""
Deletes ``None`` and empty lists and dicts, recursively.
@@ -263,6 +267,7 @@ def prune(value, is_removable_function=is_removable):
# TODO: Move following two methods to some place parser specific
+
def deepcopy_with_locators(value):
"""
Like :func:`deepcopy`, but also copies over locators.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/docs/aria.modeling.models.rst
----------------------------------------------------------------------
diff --git a/docs/aria.modeling.models.rst b/docs/aria.modeling.models.rst
index 13f9494..b1ddb29 100644
--- a/docs/aria.modeling.models.rst
+++ b/docs/aria.modeling.models.rst
@@ -19,3 +19,4 @@
---------------------------
.. automodule:: aria.modeling.models
+ :no-show-inheritance:
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/docs/conf.py
----------------------------------------------------------------------
diff --git a/docs/conf.py b/docs/conf.py
index 4f57968..b1a17ea 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -374,35 +374,41 @@ autodoc_default_flags = [
'show-inheritance'
]
-_skip_fields = (
+_SKIP_MEMBERS = (
'FIELDS',
'ALLOW_UNKNOWN_FIELDS',
'SHORT_FORM_FIELD'
)
-_no_skip_fields = (
+_SKIP_MEMBER_SUFFIXES = (
+ '_fk'
+)
+
+_NEVER_SKIP_MEMBERS = (
'__evaluate__',
)
# Event handling
def on_skip_members(app, what, name, obj, skip, options):
- if (name in _skip_fields) or name.endswith('_fk'):
- skip = True
- elif name in _no_skip_fields:
- skip = False
+ if name in _NEVER_SKIP_MEMBERS:
+ return False
+ if name in _SKIP_MEMBERS:
+ return True
+ for suffix in _SKIP_MEMBER_SUFFIXES:
+ if name.endswith(suffix):
+ return True
return skip
from sphinx.domains.python import PythonDomain
-class PatchedPythonDomain(PythonDomain):
+class _PatchedPythonDomain(PythonDomain):
# See: https://github.com/sphinx-doc/sphinx/issues/3866
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
if 'refspecific' in node:
del node['refspecific']
- return super(PatchedPythonDomain, self).resolve_xref(
+ return super(_PatchedPythonDomain, self).resolve_xref(
env, fromdocname, builder, typ, target, node, contnode)
def setup(app):
app.connect('autodoc-skip-member', on_skip_members)
- app.override_domain(PatchedPythonDomain)
- print PatchedPythonDomain.roles
+ app.override_domain(_PatchedPythonDomain)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
index 5813ccf..957dc7b 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -484,7 +484,6 @@ def create_substitution_template_model(context, service_template, substitution_m
node_template_model.capability_templates[capability.capability]
model.mappings[name] = \
SubstitutionTemplateMapping(name=name,
- node_template=node_template_model,
capability_template=capability_template_model)
requirements = substitution_mappings.requirements
@@ -499,7 +498,6 @@ def create_substitution_template_model(context, service_template, substitution_m
break
model.mappings[name] = \
SubstitutionTemplateMapping(name=name,
- node_template=node_template_model,
requirement_template=requirement_template_model)
return model
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/tests/orchestrator/workflows/core/test_events.py
----------------------------------------------------------------------
diff --git a/tests/orchestrator/workflows/core/test_events.py b/tests/orchestrator/workflows/core/test_events.py
index 2b82443..6a4fdd0 100644
--- a/tests/orchestrator/workflows/core/test_events.py
+++ b/tests/orchestrator/workflows/core/test_events.py
@@ -129,8 +129,8 @@ def run_standard_lifecycle_operation_on_node(ctx, op_name):
def _assert_node_state_changed_as_a_result_of_standard_lifecycle_operation(node, op_name):
- assert global_test_dict['transitional_state'] == NodeBase._op_to_state[op_name]['transitional']
- assert node.state == NodeBase._op_to_state[op_name]['finished']
+ assert global_test_dict['transitional_state'] == NodeBase._OP_TO_STATE[op_name]['transitional']
+ assert node.state == NodeBase._OP_TO_STATE[op_name]['finished']
@workflow
[3/3] incubator-ariatosca git commit: Full documentation of models;
fix to subtitution
Posted by em...@apache.org.
Full documentation of models; fix to subtitution
Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/4ebbbb15
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/4ebbbb15
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/4ebbbb15
Branch: refs/heads/ARIA-286-sphinx-documentation
Commit: 4ebbbb15664a09d80088cf82e8d3c3f1ee6fde62
Parents: 7ed92d0
Author: Tal Liron <ta...@gmail.com>
Authored: Tue Jun 27 21:49:59 2017 -0500
Committer: Tal Liron <ta...@gmail.com>
Committed: Tue Jun 27 21:49:59 2017 -0500
----------------------------------------------------------------------
aria/cli/inputs.py | 16 +-
aria/cli/service_template_utils.py | 2 +-
aria/cli/table.py | 16 +-
aria/cli/utils.py | 16 +-
aria/logger.py | 2 +-
aria/modeling/functions.py | 4 +-
aria/modeling/mixins.py | 45 +-
aria/modeling/models.py | 19 +-
aria/modeling/orchestration.py | 591 ++++---
aria/modeling/service_changes.py | 57 +-
aria/modeling/service_common.py | 395 +++--
aria/modeling/service_instance.py | 1465 ++++++++++-------
aria/modeling/service_template.py | 1508 +++++++++++-------
aria/modeling/types.py | 2 +-
aria/modeling/utils.py | 6 +-
aria/parser/loading/context.py | 2 +-
aria/parser/presentation/presentation.py | 4 +-
aria/utils/caching.py | 2 +-
aria/utils/collections.py | 17 +-
docs/aria.modeling.models.rst | 1 +
docs/conf.py | 26 +-
.../simple_v1_0/modeling/__init__.py | 2 -
.../orchestrator/workflows/core/test_events.py | 4 +-
23 files changed, 2560 insertions(+), 1642 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/cli/inputs.py
----------------------------------------------------------------------
diff --git a/aria/cli/inputs.py b/aria/cli/inputs.py
index 11f70a0..bea3e1a 100644
--- a/aria/cli/inputs.py
+++ b/aria/cli/inputs.py
@@ -29,14 +29,14 @@ def inputs_to_dict(resources):
"""
Returns a dictionary of inputs
- ``resources`` can be:
-
- * A list of files.
- * A single file
- * A directory containing multiple input files
- * A key1=value1;key2=value2 pairs string.
- * A string formatted as JSON/YAML.
- * Wildcard based string (e.g. ``*-inputs.yaml``)
+ :param resources: can be:
+
+ * list of files
+ * single file
+ * directory containing multiple input files
+ * ``key1=value1;key2=value2`` pairs string.
+ * string formatted as JSON/YAML
+ * wildcard based string (e.g. ``*-inputs.yaml``)
"""
if not resources:
return dict()
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/cli/service_template_utils.py
----------------------------------------------------------------------
diff --git a/aria/cli/service_template_utils.py b/aria/cli/service_template_utils.py
index abfbf9a..5312522 100644
--- a/aria/cli/service_template_utils.py
+++ b/aria/cli/service_template_utils.py
@@ -41,7 +41,7 @@ def get(source, service_template_filename):
:param source: path/URL/GitHub repo to archive/service-template file
:type source: basestring
:param service_template_filename: path to service template if source is a non-CSAR archive
- (with CSAR archives, this is read from the metadata file)
+ with CSAR archives, this is read from the metadata file)
:type service_template_filename: basestring
:return: path to main service template file
:rtype: basestring
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/cli/table.py
----------------------------------------------------------------------
diff --git a/aria/cli/table.py b/aria/cli/table.py
index a4e959c..74487ae 100644
--- a/aria/cli/table.py
+++ b/aria/cli/table.py
@@ -33,16 +33,15 @@ def print_data(columns, items, header_text,
:param columns: columns of the table, e.g. ``['id','name']``
:type columns: iterable of basestring
:param items: each element must have keys or attributes corresponding to the ``columns`` items,
- e.g. ``[{'id':'123', 'name':'Pete'}]``
+ e.g. ``[{'id':'123', 'name':'Pete'}]``
:type data: [{:obj:`basestring`: :obj:`basestring`}]
:param column_formatters: maps column name to formatter, a function that may manipulate the
- string values printed for this column, e.g.
- ``{'created_at': timestamp_formatter}``
+ string values printed for this column, e.g. ``{'created_at': timestamp_formatter}``
+ :type column_formatters: {:obj:`basestring`: :obj:`function`}
:param col_max_width: maximum width of table
:type col_max_width: int
- :type column_formatters: {obj:`basestring`: :obj:`function`}
:param defaults: default values for keys that don't exist in the data itself, e.g.
- ``{'serviceId':'123'}``
+ ``{'serviceId':'123'}``
:type defaults: {:obj:`basestring`: :obj:`basestring`}
"""
if items is None:
@@ -68,14 +67,13 @@ def _generate(cols, data, column_formatters=None, defaults=None):
:param cols: columns of the table, e.g. ``['id','name']``
:type cols: iterable of :obj:`basestring`
:param data: each element must have keys or attributes corresponding to the ``cols`` items,
- e.g. ``[{'id':'123', 'name':'Pete'}]``
+ e.g. ``[{'id':'123', 'name':'Pete'}]``
:type data: [{:obj:`basestring`: :obj:`basestring`}]
:param column_formatters: maps column name to formatter, a function that may manipulate the
- string values printed for this column, e.g.
- ``{'created_at': timestamp_formatter}``
+ string values printed for this column, e.g. ``{'created_at': timestamp_formatter}``
:type column_formatters: {:obj:`basestring`: :obj:`function`}
:param defaults: default values for keys that don't exist in the data itself, e.g.
- ``{'serviceId':'123'}``
+ ``{'serviceId':'123'}``
:type defaults: {:obj:`basestring`: :obj:`basestring`}
"""
def get_values_per_column(column, row_data):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/cli/utils.py
----------------------------------------------------------------------
diff --git a/aria/cli/utils.py b/aria/cli/utils.py
index 0d0666b..697ff37 100644
--- a/aria/cli/utils.py
+++ b/aria/cli/utils.py
@@ -80,8 +80,8 @@ def generate_progress_handler(file_path, action='', max_bar_length=80):
:param max_bar_length: maximum allowed length of the bar
:return: configured ``print_progress`` function
"""
- # We want to limit the maximum line length to 80, but allow for a smaller
- # terminal size. We also include the action string, and some extra chars
+ # We want to limit the maximum line length to 80, but allow for a smaller terminal size. We also
+ # include the action string, and some extra chars
terminal_width = get_terminal_size().columns
# This takes care of the case where there is no terminal (e.g. unittest)
@@ -105,16 +105,12 @@ def generate_progress_handler(file_path, action='', max_bar_length=80):
:param total_bytes: total number of bytes in the file
"""
- filled_length = min(bar_length, int(round(bar_length * read_bytes /
- float(total_bytes))))
- percents = min(100.00, round(
- 100.00 * (read_bytes / float(total_bytes)), 2))
+ filled_length = min(bar_length, int(round(bar_length * read_bytes / float(total_bytes))))
+ percents = min(100.00, round(100.00 * (read_bytes / float(total_bytes)), 2))
bar = '#' * filled_length + '-' * (bar_length - filled_length) # pylint: disable=blacklisted-name
- # The \r caret makes sure the cursor moves back to the beginning of
- # the line
- sys.stdout.write('\r{0} {1} |{2}| {3}%'.format(
- action, file_name, bar, percents))
+ # The \r caret makes sure the cursor moves back to the beginning of the line
+ sys.stdout.write('\r{0} {1} |{2}| {3}%'.format(action, file_name, bar, percents))
if read_bytes >= total_bytes:
sys.stdout.write(os.linesep)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/logger.py
----------------------------------------------------------------------
diff --git a/aria/logger.py b/aria/logger.py
index 2ccff25..3b01e48 100644
--- a/aria/logger.py
+++ b/aria/logger.py
@@ -125,7 +125,7 @@ def create_sqla_log_handler(model, log_cls, execution_id, level=logging.DEBUG):
class _DefaultConsoleFormat(logging.Formatter):
"""
Info level log format: ``%(message)s``
-
+
Every other log level is formatted: ``%(levelname)s: %(message)s``
"""
def format(self, record):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/functions.py
----------------------------------------------------------------------
diff --git a/aria/modeling/functions.py b/aria/modeling/functions.py
index b764aa8..6544adf 100644
--- a/aria/modeling/functions.py
+++ b/aria/modeling/functions.py
@@ -42,7 +42,7 @@ class Function(object):
:rtype: :class:`Evaluation` (or any object with ``value`` and ``final`` properties)
:raises CannotEvaluateFunctionException: if cannot be evaluated at this time (do *not* just
- return ``None``)
+ return ``None``)
"""
raise NotImplementedError
@@ -55,7 +55,7 @@ class Function(object):
class Evaluation(object):
"""
An evaluated :class:`Function` return value.
-
+
:ivar value: evaluated value
:ivar final: whether the value is final
:vartype final: boolean
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/mixins.py
----------------------------------------------------------------------
diff --git a/aria/modeling/mixins.py b/aria/modeling/mixins.py
index e707f02..aafc1e9 100644
--- a/aria/modeling/mixins.py
+++ b/aria/modeling/mixins.py
@@ -99,8 +99,17 @@ class ModelMixin(object):
class ModelIDMixin(object):
- id = Column(Integer, primary_key=True, autoincrement=True)
- name = Column(Text, index=True)
+ id = Column(Integer, primary_key=True, autoincrement=True, doc="""
+ Unique ID.
+
+ :type: :obj:`int`
+ """)
+
+ name = Column(Text, index=True, doc="""
+ Model name.
+
+ :type: :obj:`basestring`
+ """)
@classmethod
def id_column_name(cls):
@@ -150,21 +159,22 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
This model can be used as the ``container_holder`` argument for
:func:`~aria.modeling.functions.evaluate`.
-
- :ivar name: name
- :vartype name: basestring
- :ivar type_name: type name
- :vartype type_name: basestring
- :ivar value: value
- :ivar description: description
- :vartype description: basestring
"""
__tablename__ = 'parameter'
- name = Column(Text)
- type_name = Column(Text)
- description = Column(Text)
+ type_name = Column(Text, doc="""
+ Type name.
+
+ :type: :obj:`basestring`
+ """)
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
+
_value = Column(PickleType)
@property
@@ -189,7 +199,7 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
*All* parameters should have an owner model.
:raises exceptions.ValueError: if failed to find an owner, which signifies an abnormal,
- orphaned parameter
+ orphaned parameter
"""
# Find first non-null relationship
@@ -214,7 +224,7 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
*All* parameters should have a container model.
:raises exceptions.ValueError: if failed to find a container model, which signifies an
- abnormal, orphaned parameter
+ abnormal, orphaned parameter
"""
from . import models
@@ -260,7 +270,7 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
not contained in a service.
:raises exceptions.ValueError: if failed to find a container model, which signifies an
- abnormal, orphaned parameter
+ abnormal, orphaned parameter
"""
from . import models
@@ -279,7 +289,7 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
``None`` if not contained in a service template.
:raises exceptions.ValueError: if failed to find a container model, which signifies an
- abnormal, orphaned parameter
+ abnormal, orphaned parameter
"""
from . import models
@@ -355,7 +365,6 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
description=description)
def as_other_parameter_model(self, other_model_cls):
-
name, value = self.unwrapped
return other_model_cls.wrap(name, value)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/models.py
----------------------------------------------------------------------
diff --git a/aria/modeling/models.py b/aria/modeling/models.py
index 129b5bb..f2aa1ea 100644
--- a/aria/modeling/models.py
+++ b/aria/modeling/models.py
@@ -31,15 +31,15 @@ from . import (
service_changes,
service_common,
orchestration,
- mixins,
+ mixins
)
+
aria_declarative_base = declarative_base(cls=mixins.ModelIDMixin)
# See also models_to_register at the bottom of this file
__all__ = (
- 'aria_declarative_base',
'models_to_register',
# Service template models
@@ -93,16 +93,25 @@ __all__ = (
)
+def _clean_init_doc(cls):
+ # Make sure Sphinx doesn't grab the base constructor's docstring
+ original_init = cls.__init__
+ def init(*args, **kwargs):
+ original_init(*args, **kwargs)
+ cls.__init__ = init
+ return cls
+
+
def _fix_doc(cls):
+ # Use the last base class's docstring
cls.__doc__ = cls.__bases__[-1].__doc__
- return cls
+ return _clean_init_doc(cls)
# region service template models
@_fix_doc
class ServiceTemplate(aria_declarative_base, service_template.ServiceTemplateBase):
- #__doc__ = service_template.ServiceTemplateBase.__doc__
name = Column(Text, index=True, unique=True)
@@ -249,7 +258,6 @@ class ServiceModification(aria_declarative_base, service_changes.ServiceModifica
# region common service models
-
@_fix_doc
class Input(aria_declarative_base, service_common.InputBase):
pass
@@ -313,7 +321,6 @@ class Log(aria_declarative_base, orchestration.LogBase):
class Argument(aria_declarative_base, orchestration.ArgumentBase):
pass
-
# endregion
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/orchestration.py
----------------------------------------------------------------------
diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py
index 6096fcc..1c94966 100644
--- a/aria/modeling/orchestration.py
+++ b/aria/modeling/orchestration.py
@@ -44,7 +44,7 @@ from . import (
class ExecutionBase(mixins.ModelMixin):
"""
- Execution model representation.
+ Workflow execution.
"""
__tablename__ = 'execution'
@@ -69,56 +69,47 @@ class ExecutionBase(mixins.ModelMixin):
CANCELLED: PENDING
}
- @orm.validates('status')
- def validate_status(self, key, value):
- """Validation function that verifies execution status transitions are OK"""
- try:
- current_status = getattr(self, key)
- except AttributeError:
- return
- valid_transitions = self.VALID_TRANSITIONS.get(current_status, [])
- if all([current_status is not None,
- current_status != value,
- value not in valid_transitions]):
- raise ValueError('Cannot change execution status from {current} to {new}'.format(
- current=current_status,
- new=value))
- return value
-
- created_at = Column(DateTime, index=True)
- started_at = Column(DateTime, nullable=True, index=True)
- ended_at = Column(DateTime, nullable=True, index=True)
- error = Column(Text, nullable=True)
- status = Column(Enum(*STATES, name='execution_status'), default=PENDING)
- workflow_name = Column(Text)
-
- def has_ended(self):
- return self.status in self.END_STATES
-
- def is_active(self):
- return not self.has_ended() and self.status != self.PENDING
+ # region one_to_many relationships
@declared_attr
- def logs(cls):
- return relationship.one_to_many(cls, 'log')
+ def inputs(cls):
+ """
+ Execution parameters.
- @declared_attr
- def service(cls):
- return relationship.many_to_one(cls, 'service')
+ :type: {:obj:`basestring`: :class:`Input`}
+ """
+ return relationship.one_to_many(cls, 'input', dict_key='name')
@declared_attr
def tasks(cls):
+ """
+ Tasks.
+
+ :type: [:class:`Task`]
+ """
return relationship.one_to_many(cls, 'task')
@declared_attr
- def inputs(cls):
- return relationship.one_to_many(cls, 'input', dict_key='name')
+ def logs(cls):
+ """
+ General log messages for the execution (not for its tasks).
- # region foreign keys
+ :type: [:class:`Log`]
+ """
+ return relationship.one_to_many(cls, 'log')
+
+ # endregion
+
+ # region many_to_one relationships
@declared_attr
- def service_fk(cls):
- return relationship.foreign_key('service')
+ def service(cls):
+ """
+ Associated service.
+
+ :type: :class:`Service`
+ """
+ return relationship.many_to_one(cls, 'service')
# endregion
@@ -141,73 +132,78 @@ class ExecutionBase(mixins.ModelMixin):
# endregion
- def __str__(self):
- return '<{0} id=`{1}` (status={2})>'.format(
- self.__class__.__name__,
- getattr(self, self.name_column_name()),
- self.status
- )
+ # region foreign keys
+
+ @declared_attr
+ def service_fk(cls):
+ return relationship.foreign_key('service')
+ # endregion
-class PluginBase(mixins.ModelMixin):
- """
- An installed plugin.
+ created_at = Column(DateTime, index=True, doc="""
+ Creation timestamp.
- Plugins are usually packaged as `wagons <https://github.com/cloudify-cosmo/wagon>`__, which
- are archives of one or more `wheels <https://packaging.python.org/distributing/#wheels>`__.
- Most of these fields are indeed extracted from the installed wagon's metadata.
+ :type: :class:`~datetime.datetime`
+ """)
- :ivar archive_name: filename (not the full path) of the wagon's archive, often with a ".wgn"
- extension
- :vartype archive_name: basestring
- :ivar distribution: name of the operating system on which the wagon was installed (e.g.
- "ubuntu")
- :vartype distribution: basestring
- :ivar distribution_release: release of the operating system on which the wagon was installed
- (e.g. "trusty")
- :vartype distribution_release: basestring
- :ivar distribution_version: version of the operating system on which the wagon was installed
- (e.g. "14.04")
- :vartype distribution_version: basestring
- :ivar package_name: primary Python package name used when the wagon was installed, which is one
- of the wheels in the wagon (e.g. "cloudify-script-plugin")
- :vartype package_name: basestring
- :ivar package_source: full install string for the primary Python package name used when the
- wagon was installed (e.g. "cloudify-script-plugin==1.2")
- :vartype package_source: basestring
- :ivar package_version: version for the primary Python package name used when the wagon was
- installed (e.g. "1.2")
- :vartype package_version: basestring
- :ivar supported_platform: if the wheels are *all* pure Python then this would be "any",
- otherwise it would be the installed platform name (e.g.
- "linux_x86_64")
- :vartype supported_platform: basestring
- :ivar supported_py_versions: Python versions supported by all the wheels (e.g. ["py26",
- "py27"])
- :vartype supported_py_versions: [basestring]
- :ivar wheels: filenames of the wheels archived in the wagon, often with a ".whl" extension
- :vartype wheels: [basestring]
- :ivar uploaded_at: timestamp for when the wagon was installed
- :vartype uploaded_at: basestring
- """
+ started_at = Column(DateTime, nullable=True, index=True, doc="""
+ Started timestamp.
- __tablename__ = 'plugin'
+ :type: :class:`~datetime.datetime`
+ """)
- @declared_attr
- def tasks(cls):
- return relationship.one_to_many(cls, 'task')
+ ended_at = Column(DateTime, nullable=True, index=True, doc="""
+ Ended timestamp.
+
+ :type: :class:`~datetime.datetime`
+ """)
- archive_name = Column(Text, nullable=False, index=True)
- distribution = Column(Text)
- distribution_release = Column(Text)
- distribution_version = Column(Text)
- package_name = Column(Text, nullable=False, index=True)
- package_source = Column(Text)
- package_version = Column(Text)
- supported_platform = Column(Text)
- supported_py_versions = Column(modeling_types.StrictList(basestring))
- wheels = Column(modeling_types.StrictList(basestring), nullable=False)
- uploaded_at = Column(DateTime, nullable=False, index=True)
+ error = Column(Text, nullable=True, doc="""
+ Error message.
+
+ :type: :obj:`basestring`
+ """)
+
+ status = Column(Enum(*STATES, name='execution_status'), default=PENDING, doc="""
+ Status.
+
+ :type: :obj:`basestring`
+ """)
+
+ workflow_name = Column(Text, doc="""
+ Workflow name.
+
+ :type: :obj:`basestring`
+ """)
+
+ @orm.validates('status')
+ def validate_status(self, key, value):
+ """Validation function that verifies execution status transitions are OK"""
+ try:
+ current_status = getattr(self, key)
+ except AttributeError:
+ return
+ valid_transitions = self.VALID_TRANSITIONS.get(current_status, [])
+ if all([current_status is not None,
+ current_status != value,
+ value not in valid_transitions]):
+ raise ValueError('Cannot change execution status from {current} to {new}'.format(
+ current=current_status,
+ new=value))
+ return value
+
+ def has_ended(self):
+ return self.status in self.END_STATES
+
+ def is_active(self):
+ return not self.has_ended() and self.status != self.PENDING
+
+ def __str__(self):
+ return '<{0} id=`{1}` (status={2})>'.format(
+ self.__class__.__name__,
+ getattr(self, self.name_column_name()),
+ self.status
+ )
class TaskBase(mixins.ModelMixin):
@@ -216,40 +212,14 @@ class TaskBase(mixins.ModelMixin):
outputs, as well as an atomic status, ensuring that the task can only be running once at any
given time.
+ The Python :attr:`function` is usually provided by an associated :class:`Plugin`. The
+ :attr:`arguments` of the function should be set according to the specific signature of the
+ function.
+
Tasks may be "one shot" or may be configured to run repeatedly in the case of failure.
Tasks are often based on :class:`Operation`, and thus act on either a :class:`Node` or a
:class:`Relationship`, however this is not required.
-
- :ivar node: node actor (optional)
- :vartype node: Node
- :ivar relationship: relationship actor (optional)
- :vartype relationship: Relationship
- :ivar plugin: implementing plugin (set to None for default execution plugin)
- :vartype plugin: Plugin
- :ivar function: Python path to an ``@operation`` function
- :vartype function: basestring
- :ivar arguments: arguments that can be used by this task
- :vartype arguments: {:obj:`basestring`: :class:`Argument`}
- :ivar max_attempts: maximum number of retries allowed in case of failure
- :vartype max_attempts: int
- :ivar retry_interval: interval between retries (in seconds)
- :vartype retry_interval: int
- :ivar ignore_failure: set to ``True`` to ignore failures
- :vartype ignore_failure: bool
- :ivar due_at: timestamp to start the task
- :vartype due_at: datetime
- :ivar execution: assigned execution
- :vartype execution: Execution
- :ivar status: current atomic status ('pending', 'retrying', 'sent', 'started', 'success',
- 'failed')
- :vartype status: basestring
- :ivar started_at: timestamp for when task started
- :vartype started_at: datetime
- :ivar ended_at: timestamp for when task ended
- :vartype ended_at: datetime
- :ivar attempts_count: how many attempts occurred
- :vartype attempts_count: int
"""
__tablename__ = 'task'
@@ -289,71 +259,94 @@ class TaskBase(mixins.ModelMixin):
)
INFINITE_RETRIES = -1
+ # region one_to_many relationships
+
@declared_attr
- def execution(cls):
- return relationship.many_to_one(cls, 'execution')
+ def logs(cls):
+ """
+ Log messages.
+
+ :type: [:class:`Log`]
+ """
+ return relationship.one_to_many(cls, 'log')
@declared_attr
- def execution_fk(cls):
- return relationship.foreign_key('execution', nullable=True)
+ def arguments(cls):
+ """
+ Arguments sent to the Python :attr:`function``.
- status = Column(Enum(*STATES, name='status'), default=PENDING)
- due_at = Column(DateTime, nullable=False, index=True, default=datetime.utcnow())
- started_at = Column(DateTime, default=None)
- ended_at = Column(DateTime, default=None)
- attempts_count = Column(Integer, default=1)
+ :type: {:obj:`basestring`: :class:`Argument`}
+ """
+ return relationship.one_to_many(cls, 'argument', dict_key='name')
- _api_id = Column(String)
- _executor = Column(PickleType)
- _context_cls = Column(PickleType)
- _stub_type = Column(Enum(*STUB_TYPES))
+ # endregion
+
+ # region many_one relationships
@declared_attr
- def logs(cls):
- return relationship.one_to_many(cls, 'log')
+ def execution(cls):
+ """
+ Containing execution.
+
+ :type: :class:`Execution`
+ """
+ return relationship.many_to_one(cls, 'execution')
@declared_attr
def node(cls):
+ """
+ Node actor (can be ``None``).
+
+ :type: :class:`Node`
+ """
return relationship.many_to_one(cls, 'node')
@declared_attr
def relationship(cls):
+ """
+ Relationship actor (can be ``None``).
+
+ :type: :class:`Relationship`
+ """
return relationship.many_to_one(cls, 'relationship')
@declared_attr
def plugin(cls):
+ """
+ Associated plugin.
+
+ :type: :class:`Plugin`
+ """
return relationship.many_to_one(cls, 'plugin')
+ # endregion
+
+ # region association proxies
+
@declared_attr
- def arguments(cls):
- return relationship.one_to_many(cls, 'argument', dict_key='name')
+ def node_name(cls):
+ """Required for use by SQLAlchemy queries"""
+ return association_proxy('node', cls.name_column_name())
- function = Column(String)
- max_attempts = Column(Integer, default=1)
- retry_interval = Column(Float, default=0)
- ignore_failure = Column(Boolean, default=False)
- interface_name = Column(String)
- operation_name = Column(String)
+ @declared_attr
+ def relationship_name(cls):
+ """Required for use by SQLAlchemy queries"""
+ return association_proxy('relationship', cls.name_column_name())
- @property
- def actor(self):
- """
- Return the actor of the task
- :return:
- """
- return self.node or self.relationship
+ @declared_attr
+ def execution_name(cls):
+ """Required for use by SQLAlchemy queries"""
+ return association_proxy('execution', cls.name_column_name())
- @orm.validates('max_attempts')
- def validate_max_attempts(self, _, value): # pylint: disable=no-self-use
- """Validates that max attempts is either -1 or a positive number"""
- if value < 1 and value != TaskBase.INFINITE_RETRIES:
- raise ValueError('Max attempts can be either -1 (infinite) or any positive number. '
- 'Got {value}'.format(value=value))
- return value
+ # endregion
# region foreign keys
@declared_attr
+ def execution_fk(cls):
+ return relationship.foreign_key('execution', nullable=True)
+
+ @declared_attr
def node_fk(cls):
return relationship.foreign_key('node', nullable=True)
@@ -367,24 +360,93 @@ class TaskBase(mixins.ModelMixin):
# endregion
- # region association proxies
+ status = Column(Enum(*STATES, name='status'), default=PENDING, doc="""
+ Current atomic status ('pending', 'retrying', 'sent', 'started', 'success', 'failed').
- @declared_attr
- def node_name(cls):
- """Required for use by SQLAlchemy queries"""
- return association_proxy('node', cls.name_column_name())
+ :type: :obj:`basestring`
+ """)
- @declared_attr
- def relationship_name(cls):
- """Required for use by SQLAlchemy queries"""
- return association_proxy('relationship', cls.name_column_name())
+ due_at = Column(DateTime, nullable=False, index=True, default=datetime.utcnow(), doc="""
+ Timestamp to start the task.
- @declared_attr
- def execution_name(cls):
- """Required for use by SQLAlchemy queries"""
- return association_proxy('execution', cls.name_column_name())
+ :type: :class:`~datetime.datetime`
+ """)
- # endregion
+ started_at = Column(DateTime, default=None, doc="""
+ Started timestamp.
+
+ :type: :class:`~datetime.datetime`
+ """)
+
+ ended_at = Column(DateTime, default=None, doc="""
+ Ended timestamp.
+
+ :type: :class:`~datetime.datetime`
+ """)
+
+ attempts_count = Column(Integer, default=1, doc="""
+ How many attempts occurred.
+
+ :type: :class:`~datetime.datetime`
+ """)
+
+ function = Column(String, doc="""
+ Full path to Python function.
+
+ :type: :obj:`basestring`
+ """)
+
+ max_attempts = Column(Integer, default=1, doc="""
+ Maximum number of attempts allowed in case of task failure.
+
+ :type: :obj:`int`
+ """)
+
+ retry_interval = Column(Float, default=0, doc="""
+ Interval between task retry attemps (in seconds).
+
+ :type: :obj:`float`
+ """)
+
+ ignore_failure = Column(Boolean, default=False, doc="""
+ Set to ``True`` to ignore failures.
+
+ :type: :obj:`bool`
+ """)
+
+ interface_name = Column(String, doc="""
+ Name of interface on node or relationship.
+
+ :type: :obj:`basestring`
+ """)
+
+ operation_name = Column(String, doc="""
+ Name of operation in interface on node or relationship.
+
+ :type: :obj:`basestring`
+ """)
+
+ _api_id = Column(String)
+ _executor = Column(PickleType)
+ _context_cls = Column(PickleType)
+ _stub_type = Column(Enum(*STUB_TYPES))
+
+ @property
+ def actor(self):
+ """
+ Actor of the task (node or relationship).
+ """
+ return self.node or self.relationship
+
+ @orm.validates('max_attempts')
+ def validate_max_attempts(self, _, value): # pylint: disable=no-self-use
+ """
+ Validates that max attempts is either -1 or a positive number.
+ """
+ if value < 1 and value != TaskBase.INFINITE_RETRIES:
+ raise ValueError('Max attempts can be either -1 (infinite) or any positive number. '
+ 'Got {value}'.format(value=value))
+ return value
@staticmethod
def abort(message=None):
@@ -451,26 +513,36 @@ class TaskBase(mixins.ModelMixin):
class LogBase(mixins.ModelMixin):
+ """
+ Single log message.
+ """
__tablename__ = 'log'
__private_fields__ = ('execution_fk',
'task_fk')
+ # region many_to_one relationships
+
@declared_attr
def execution(cls):
+ """
+ Containing execution.
+
+ :type: :class:`Execution`
+ """
return relationship.many_to_one(cls, 'execution')
@declared_attr
def task(cls):
- return relationship.many_to_one(cls, 'task')
+ """
+ Containing task (can be ``None``).
- level = Column(String)
- msg = Column(String)
- created_at = Column(DateTime, index=True)
+ :type: :class:`Task`
+ """
+ return relationship.many_to_one(cls, 'task')
- # In case of failed execution
- traceback = Column(Text)
+ # endregion
# region foreign keys
@@ -484,6 +556,30 @@ class LogBase(mixins.ModelMixin):
# endregion
+ level = Column(String, doc="""
+ Log level.
+
+ :type: :obj:`basestring`
+ """)
+
+ msg = Column(String, doc="""
+ Log message.
+
+ :type: :obj:`basestring`
+ """)
+
+ created_at = Column(DateTime, index=True, doc="""
+ Creation timestamp.
+
+ :type: :class:`~datetime.datetime`
+ """)
+
+ traceback = Column(Text, doc="""
+ Error traceback in case of failure.
+
+ :type: :class:`~datetime.datetime`
+ """)
+
def __str__(self):
return self.msg
@@ -492,30 +588,137 @@ class LogBase(mixins.ModelMixin):
return '{name}: {self.msg}'.format(name=name, self=self)
-class ArgumentBase(mixins.ParameterMixin):
+class PluginBase(mixins.ModelMixin):
+ """
+ Installed plugin.
- __tablename__ = 'argument'
+ Plugins are usually packaged as `wagons <https://github.com/cloudify-cosmo/wagon>`__, which
+ are archives of one or more `wheels <https://packaging.python.org/distributing/#wheels>`__.
+ Most of these fields are indeed extracted from the installed wagon's metadata.
+ """
- # region foreign keys
+ __tablename__ = 'plugin'
- @declared_attr
- def task_fk(cls):
- return relationship.foreign_key('task', nullable=True)
+ # region one_to_many relationships
@declared_attr
- def operation_fk(cls):
- return relationship.foreign_key('operation', nullable=True)
+ def tasks(cls):
+ """
+ Associated Tasks.
+
+ :type: [:class:`Task`]
+ """
+ return relationship.one_to_many(cls, 'task')
# endregion
+ archive_name = Column(Text, nullable=False, index=True, doc="""
+ Filename (not the full path) of the wagon's archive, often with a ``.wgn`` extension.
+
+ :type: :obj:`basestring`
+ """)
+
+ distribution = Column(Text, doc="""
+ Name of the operating system on which the wagon was installed (e.g. ``ubuntu``).
+
+ :type: :obj:`basestring`
+ """)
+
+ distribution_release = Column(Text, doc="""
+ Release of the operating system on which the wagon was installed (e.g. ``trusty``).
+
+ :type: :obj:`basestring`
+ """)
+
+ distribution_version = Column(Text, doc="""
+ Version of the operating system on which the wagon was installed (e.g. ``14.04``).
+
+ :type: :obj:`basestring`
+ """)
+
+ package_name = Column(Text, nullable=False, index=True, doc="""
+ Primary Python package name used when the wagon was installed, which is one of the wheels in the
+ wagon (e.g. ``cloudify-script-plugin``).
+
+ :type: :obj:`basestring`
+ """)
+
+ package_source = Column(Text, doc="""
+ Full install string for the primary Python package name used when the wagon was installed (e.g.
+ ``cloudify-script-plugin==1.2``).
+
+ :type: :obj:`basestring`
+ """)
+
+ package_version = Column(Text, doc="""
+ Version for the primary Python package name used when the wagon was installed (e.g. ``1.2``).
+
+ :type: :obj:`basestring`
+ """)
+
+ supported_platform = Column(Text, doc="""
+ If the wheels are *all* pure Python then this would be "any", otherwise it would be the
+ installed platform name (e.g. ``linux_x86_64``).
+
+ :type: :obj:`basestring`
+ """)
+
+ supported_py_versions = Column(modeling_types.StrictList(basestring), doc="""
+ Python versions supported by all the wheels (e.g. ``["py26", "py27"]``)
+
+ :type: [:obj:`basestring`]
+ """)
+
+ wheels = Column(modeling_types.StrictList(basestring), nullable=False, doc="""
+ Filenames of the wheels archived in the wagon, often with a ``.whl`` extension.
+
+ :type: [:obj:`basestring`]
+ """)
+
+ uploaded_at = Column(DateTime, nullable=False, index=True, doc="""
+ Timestamp for when the wagon was installed.
+
+ :type: :class:`~datetime.datetime`
+ """)
+
+
+class ArgumentBase(mixins.ParameterMixin):
+ """
+ Python function argument parameter.
+ """
+
+ __tablename__ = 'argument'
+
# region many_to_one relationships
@declared_attr
def task(cls):
+ """
+ Containing task (can be ``None``);
+
+ :type: :class:`Task`
+ """
return relationship.many_to_one(cls, 'task')
@declared_attr
def operation(cls):
+ """
+ Containing operation (can be ``None``);
+
+ :type: :class:`Operation`
+ """
return relationship.many_to_one(cls, 'operation')
# endregion
+
+ # region foreign keys
+
+ @declared_attr
+ def task_fk(cls):
+ return relationship.foreign_key('task', nullable=True)
+
+ @declared_attr
+ def operation_fk(cls):
+ return relationship.foreign_key('operation', nullable=True)
+
+ # endregion
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/service_changes.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_changes.py b/aria/modeling/service_changes.py
index 97f8643..b536443 100644
--- a/aria/modeling/service_changes.py
+++ b/aria/modeling/service_changes.py
@@ -52,18 +52,6 @@ class ServiceUpdateBase(ModelMixin):
modified_entity_ids = Column(Dict)
state = Column(Text)
- # region foreign keys
-
- @declared_attr
- def execution_fk(cls):
- return relationship.foreign_key('execution', nullable=True)
-
- @declared_attr
- def service_fk(cls):
- return relationship.foreign_key('service')
-
- # endregion
-
# region association proxies
@declared_attr
@@ -102,6 +90,18 @@ class ServiceUpdateBase(ModelMixin):
# endregion
+ # region foreign keys
+
+ @declared_attr
+ def execution_fk(cls):
+ return relationship.foreign_key('execution', nullable=True)
+
+ @declared_attr
+ def service_fk(cls):
+ return relationship.foreign_key('service')
+
+ # endregion
+
def to_dict(self, suppress_error=False, **kwargs):
dep_update_dict = super(ServiceUpdateBase, self).to_dict(suppress_error) #pylint: disable=no-member
# Taking care of the fact the DeploymentSteps are _BaseModels
@@ -140,14 +140,6 @@ class ServiceUpdateStepBase(ModelMixin):
entity_id = Column(Text, nullable=False)
entity_type = Column(Enum(*ENTITY_TYPES, name='entity_type'), nullable=False)
- # region foreign keys
-
- @declared_attr
- def service_update_fk(cls):
- return relationship.foreign_key('service_update')
-
- # endregion
-
# region association proxies
@declared_attr
@@ -173,6 +165,14 @@ class ServiceUpdateStepBase(ModelMixin):
# endregion
+ # region foreign keys
+
+ @declared_attr
+ def service_update_fk(cls):
+ return relationship.foreign_key('service_update')
+
+ # endregion
+
def __hash__(self):
return hash((getattr(self, self.id_column_name()), self.entity_id))
@@ -224,14 +224,6 @@ class ServiceModificationBase(ModelMixin):
nodes = Column(Dict)
status = Column(Enum(*STATES, name='service_modification_status'))
- # region foreign keys
-
- @declared_attr
- def service_fk(cls):
- return relationship.foreign_key('service')
-
- # endregion
-
# region association proxies
@declared_attr
@@ -250,8 +242,17 @@ class ServiceModificationBase(ModelMixin):
# endregion
# region many_to_one relationships
+
@declared_attr
def service(cls):
return relationship.many_to_one(cls, 'service', back_populates='modifications')
# endregion
+
+ # region foreign keys
+
+ @declared_attr
+ def service_fk(cls):
+ return relationship.foreign_key('service')
+
+ # endregion
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/4ebbbb15/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index 2ba3aa3..850a1ef 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -37,17 +37,33 @@ from . import relationship
class OutputBase(ParameterMixin):
"""
- :ivar name: name
- :vartype name: basestring
- :ivar type_name: type name
- :vartype type_name: basestring
- :ivar value: value
- :ivar description: human-readable description
- :vartype description: basestring
+ Output parameter or declaration for an output parameter.
"""
__tablename__ = 'output'
+ # region many_to_one relationships
+
+ @declared_attr
+ def service_template(cls):
+ """
+ Containing service template (can be ``None``).
+
+ :type: :class:`ServiceTemplate`
+ """
+ return relationship.many_to_one(cls, 'service_template')
+
+ @declared_attr
+ def service(cls):
+ """
+ Containing service (can be ``None``).
+
+ :type: :class:`ServiceTemplate`
+ """
+ return relationship.many_to_one(cls, 'service')
+
+ # endregion
+
# region foreign keys
@declared_attr
@@ -60,31 +76,80 @@ class OutputBase(ParameterMixin):
# endregion
+
+class InputBase(ParameterMixin):
+ """
+ Input parameter or declaration for an input parameter.
+ """
+
+ __tablename__ = 'input'
+
# region many_to_one relationships
@declared_attr
def service_template(cls):
+ """
+ Containing service template (can be ``None``).
+
+ :type: :class:`ServiceTemplate`
+ """
return relationship.many_to_one(cls, 'service_template')
@declared_attr
def service(cls):
+ """
+ Containing service (can be ``None``).
+
+ :type: :class:`Service`
+ """
return relationship.many_to_one(cls, 'service')
- # endregion
+ @declared_attr
+ def interface(cls):
+ """
+ Containing interface (can be ``None``).
+ :type: :class:`Interface`
+ """
+ return relationship.many_to_one(cls, 'interface')
-class InputBase(ParameterMixin):
- """
- :ivar name: name
- :vartype name: basestring
- :ivar type_name: type name
- :vartype type_name: basestring
- :ivar value: value
- :ivar description: human-readable description
- :vartype description: basestring
- """
+ @declared_attr
+ def operation(cls):
+ """
+ Containing operation (can be ``None``).
- __tablename__ = 'input'
+ :type: :class:`Operation`
+ """
+ return relationship.many_to_one(cls, 'operation')
+
+ @declared_attr
+ def interface_template(cls):
+ """
+ Containing interface template (can be ``None``).
+
+ :type: :class:`InterfaceTemplate`
+ """
+ return relationship.many_to_one(cls, 'interface_template')
+
+ @declared_attr
+ def operation_template(cls):
+ """
+ Containing operation template (can be ``None``).
+
+ :type: :class:`OperationTemplate`
+ """
+ return relationship.many_to_one(cls, 'operation_template')
+
+ @declared_attr
+ def execution(cls):
+ """
+ Containing execution (can be ``None``).
+
+ :type: :class:`Execution`
+ """
+ return relationship.many_to_one(cls, 'execution')
+
+ # endregion
# region foreign keys
@@ -122,89 +187,167 @@ class InputBase(ParameterMixin):
# endregion
- # region many_to_one relationships
- @declared_attr
- def service_template(cls):
- return relationship.many_to_one(cls, 'service_template')
+class ConfigurationBase(ParameterMixin):
+ """
+ Configuration parameter.
+ """
- @declared_attr
- def service(cls):
- return relationship.many_to_one(cls, 'service')
+ __tablename__ = 'configuration'
+
+ # region many_to_one relationships
@declared_attr
- def interface(cls):
- return relationship.many_to_one(cls, 'interface')
+ def operation_template(cls):
+ """
+ Containing operation template (can be ``None``).
+
+ :type: :class:`OperationTemplate`
+ """
+ return relationship.many_to_one(cls, 'operation_template')
@declared_attr
def operation(cls):
+ """
+ Containing operation (can be ``None``).
+
+ :type: :class:`Operation`
+ """
return relationship.many_to_one(cls, 'operation')
- @declared_attr
- def interface_template(cls):
- return relationship.many_to_one(cls, 'interface_template')
+ # endregion
+
+ # region foreign keys
@declared_attr
- def operation_template(cls):
- return relationship.many_to_one(cls, 'operation_template')
+ def operation_template_fk(cls):
+ return relationship.foreign_key('operation_template', nullable=True)
@declared_attr
- def execution(cls):
- return relationship.many_to_one(cls, 'execution')
+ def operation_fk(cls):
+ return relationship.foreign_key('operation', nullable=True)
# endregion
-class ConfigurationBase(ParameterMixin):
+class PropertyBase(ParameterMixin):
"""
- :ivar name: name
- :vartype name: basestring
- :ivar type_name: type name
- :vartype type_name: basestring
- :ivar value: value
- :ivar description: human-readable description
- :vartype description: basestring
+ Property parameter or declaration for a property parameter.
"""
- __tablename__ = 'configuration'
+ __tablename__ = 'property'
- # region foreign keys
+ # region many_to_one relationships
@declared_attr
- def operation_template_fk(cls):
- return relationship.foreign_key('operation_template', nullable=True)
+ def node_template(cls):
+ """
+ Containing node template (can be ``None``).
+
+ :type: :class:`NodeTemplate`
+ """
+ return relationship.many_to_one(cls, 'node_template')
@declared_attr
- def operation_fk(cls):
- return relationship.foreign_key('operation', nullable=True)
+ def group_template(cls):
+ """
+ Containing group template (can be ``None``).
- # endregion
+ :type: :class:`GroupTemplate`
+ """
+ return relationship.many_to_one(cls, 'group_template')
- # region many_to_one relationships
+ @declared_attr
+ def policy_template(cls):
+ """
+ Containing policy template (can be ``None``).
+
+ :type: :class:`PolicyTemplate`
+ """
+ return relationship.many_to_one(cls, 'policy_template')
@declared_attr
- def operation_template(cls):
- return relationship.many_to_one(cls, 'operation_template')
+ def relationship_template(cls):
+ """
+ Containing relationship template (can be ``None``).
+
+ :type: :class:`RelationshipTemplate`
+ """
+ return relationship.many_to_one(cls, 'relationship_template')
@declared_attr
- def operation(cls):
- return relationship.many_to_one(cls, 'operation')
+ def capability_template(cls):
+ """
+ Containing capability template (can be ``None``).
- # endregion
+ :type: :class:`CapabilityTemplate`
+ """
+ return relationship.many_to_one(cls, 'capability_template')
+ @declared_attr
+ def artifact_template(cls):
+ """
+ Containing artifact template (can be ``None``).
-class PropertyBase(ParameterMixin):
- """
- :ivar name: name
- :vartype name: basestring
- :ivar type_name: type name
- :vartype type_name: basestring
- :ivar value: value
- :ivar description: human-readable description
- :vartype description: basestring
- """
+ :type: :class:`ArtifactTemplate`
+ """
+ return relationship.many_to_one(cls, 'artifact_template')
- __tablename__ = 'property'
+ @declared_attr
+ def node(cls):
+ """
+ Containing node (can be ``None``).
+
+ :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 policy(cls):
+ """
+ Containing policy (can be ``None``).
+
+ :type: :class:`Policy`
+ """
+ return relationship.many_to_one(cls, 'policy')
+
+ @declared_attr
+ def relationship(cls):
+ """
+ Containing relationship (can be ``None``).
+
+ :type: :class:`Relationship`
+ """
+ return relationship.many_to_one(cls, 'relationship')
+
+ @declared_attr
+ def capability(cls):
+ """
+ Containing capability (can be ``None``).
+
+ :type: :class:`Capability`
+ """
+ return relationship.many_to_one(cls, 'capability')
+
+ @declared_attr
+ def artifact(cls):
+ """
+ Containing artifact (can be ``None``).
+
+ :type: :class:`Artifact`
+ """
+ return relationship.many_to_one(cls, 'artifact')
+
+ # endregion
# region foreign keys
@@ -258,72 +401,36 @@ class PropertyBase(ParameterMixin):
# endregion
- # region many_to_one relationships
-
- @declared_attr
- def node_template(cls):
- return relationship.many_to_one(cls, 'node_template')
- @declared_attr
- def group_template(cls):
- return relationship.many_to_one(cls, 'group_template')
+class AttributeBase(ParameterMixin):
+ """
+ Attribute parameter or declaration for an attribute parameter.
+ """
- @declared_attr
- def policy_template(cls):
- return relationship.many_to_one(cls, 'policy_template')
+ __tablename__ = 'attribute'
- @declared_attr
- def relationship_template(cls):
- return relationship.many_to_one(cls, 'relationship_template')
+ # region many_to_one relationships
@declared_attr
- def capability_template(cls):
- return relationship.many_to_one(cls, 'capability_template')
+ def node_template(cls):
+ """
+ Containing node template (can be ``None``).
- @declared_attr
- def artifact_template(cls):
- return relationship.many_to_one(cls, 'artifact_template')
+ :type: :class:`NodeTemplate`
+ """
+ return relationship.many_to_one(cls, 'node_template')
@declared_attr
def node(cls):
- return relationship.many_to_one(cls, 'node')
-
- @declared_attr
- def group(cls):
- return relationship.many_to_one(cls, 'group')
-
- @declared_attr
- def policy(cls):
- return relationship.many_to_one(cls, 'policy')
-
- @declared_attr
- def relationship(cls):
- return relationship.many_to_one(cls, 'relationship')
-
- @declared_attr
- def capability(cls):
- return relationship.many_to_one(cls, 'capability')
+ """
+ Containing node (can be ``None``).
- @declared_attr
- def artifact(cls):
- return relationship.many_to_one(cls, 'artifact')
+ :type: :class:`Node`
+ """
+ return relationship.many_to_one(cls, 'node')
# endregion
-
-class AttributeBase(ParameterMixin):
- """
- :ivar name: name
- :vartype name: basestring
- :ivar type_name: type name
- :vartype type_name: basestring
- :ivar value: value
- :ivar description: human-readable description
- :vartype description: basestring
- """
-
- __tablename__ = 'attribute'
-
# region foreign keys
@declared_attr
@@ -338,25 +445,10 @@ class AttributeBase(ParameterMixin):
# endregion
- # region many_to_one relationships
-
- @declared_attr
- def node_template(cls):
- return relationship.many_to_one(cls, 'node_template')
-
- @declared_attr
- def node(cls):
- return relationship.many_to_one(cls, 'node')
-
- # endregion
-
class TypeBase(InstanceModelMixin):
"""
- Represents a type and its children.
-
- :ivar name: name
- :vartype name: basestring
+ Type and its children. Can serve as the root for a type hierarchy.
"""
__tablename__ = 'type'
@@ -364,17 +456,41 @@ class TypeBase(InstanceModelMixin):
__private_fields__ = ('parent_type_fk',)
variant = Column(Text, nullable=False)
- description = Column(Text)
+
+ description = Column(Text, doc="""
+ Human-readable description.
+
+ :type: :obj:`basestring`
+ """)
+
_role = Column(Text, name='role')
+ # region on_to_one relationships
+
@declared_attr
def parent(cls):
+ """
+ Parent type (will be ``None`` for the root of a type hierarchy).
+
+ :type: :class:`Type`
+ """
return relationship.one_to_one_self(cls, 'parent_type_fk')
+ # endregion
+
+ # region on_to_many relationships
+
@declared_attr
def children(cls):
+ """
+ Children.
+
+ :type: [:class:`Type`]
+ """
return relationship.one_to_many_self(cls, 'parent_type_fk')
+ # endregion
+
# region foreign keys
@declared_attr
@@ -455,8 +571,9 @@ class TypeBase(InstanceModelMixin):
@property
def hierarchy(self):
"""
- Return the type hierarchy.
- :return:
+ Type hierarchy as a list beginning with this type and ending in the root.
+
+ :type: [:class:`Type`]
"""
return [self] + (self.parent.hierarchy if self.parent else [])
[2/3] incubator-ariatosca git commit: Full documentation of models;
fix to subtitution
Posted by em...@apache.org.
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):