You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ariatosca.apache.org by mx...@apache.org on 2017/07/02 18:44:29 UTC
[08/12] incubator-ariatosca git commit: ARIA-286 Sphinx documentation
for code and CLI
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/2ed2e1c2/aria/modeling/mixins.py
----------------------------------------------------------------------
diff --git a/aria/modeling/mixins.py b/aria/modeling/mixins.py
index c98a866..883ff4a 100644
--- a/aria/modeling/mixins.py
+++ b/aria/modeling/mixins.py
@@ -14,9 +14,7 @@
# limitations under the License.
"""
-classes:
- * ModelMixin - abstract model implementation.
- * ModelIDMixin - abstract model implementation with IDs.
+ARIA modeling mix-ins module
"""
from sqlalchemy.ext import associationproxy
@@ -49,11 +47,11 @@ class ModelMixin(object):
def to_dict(self, fields=None, suppress_error=False):
"""
- Return a dict representation of the model
+ Create a dict representation of the model.
- :param suppress_error: If set to True, sets ``None`` to attributes that it's unable to
- retrieve (e.g., if a relationship wasn't established yet, and so it's
- impossible to access a property through it)
+ :param suppress_error: if set to ``True``, sets ``None`` to attributes that it's unable to
+ retrieve (e.g., if a relationship wasn't established yet, and so it's impossible to access
+ a property through it)
"""
res = dict()
@@ -79,14 +77,14 @@ class ModelMixin(object):
@classmethod
def fields(cls):
"""
- Return the list of field names for this table
+ List of field names for this table.
- Mostly for backwards compatibility in the code (that uses ``fields``)
+ Mostly for backwards compatibility in the code (that uses ``fields``).
"""
fields = set(cls._iter_association_proxies())
fields.update(cls.__table__.columns.keys())
- return fields - set(getattr(cls, '__private_fields__', []))
+ return fields - set(getattr(cls, '__private_fields__', ()))
@classmethod
def _iter_association_proxies(cls):
@@ -101,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):
@@ -115,10 +122,10 @@ class ModelIDMixin(object):
class InstanceModelMixin(ModelMixin):
"""
- Mixin for :class:`ServiceInstance` models.
+ Mix-in for service instance models.
- All models support validation, diagnostic dumping, and representation as
- raw data (which can be translated into JSON or YAML) via ``as_raw``.
+ All models support validation, diagnostic dumping, and representation as raw data (which can be
+ translated into JSON or YAML) via :meth:`as_raw`.
"""
@property
@@ -137,9 +144,9 @@ class InstanceModelMixin(ModelMixin):
class TemplateModelMixin(InstanceModelMixin):
"""
- Mixin for :class:`ServiceTemplate` models.
+ Mix-in for service template models.
- All model models can be instantiated into :class:`ServiceInstance` models.
+ All model models can be instantiated into service instance models.
"""
def instantiate(self, container):
@@ -148,24 +155,26 @@ class TemplateModelMixin(InstanceModelMixin):
class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods): #pylint: disable=abstract-method
"""
- Represents a typed value. The value can contain nested intrinsic functions.
+ Mix-in for typed values. The value can contain nested intrinsic functions.
- This model can be used as the ``container_holder`` argument for :func:`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
+ This model can be used as the ``container_holder`` argument for
+ :func:`~aria.modeling.functions.evaluate`.
"""
__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
@@ -187,8 +196,10 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
"""
The sole owner of this parameter, which is another model that relates to it.
- *All* parameters should have an owner model. In case this property method fails to find
- it, it will raise a ValueError, which should signify an abnormal, orphaned parameter.
+ *All* parameters should have an owner model.
+
+ :raises ~exceptions.ValueError: if failed to find an owner, which signifies an abnormal,
+ orphaned parameter
"""
# Find first non-null relationship
@@ -210,8 +221,10 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
The logical container is equivalent to the ``SELF`` keyword used by intrinsic functions in
TOSCA.
- *All* parameters should have a container model. In case this property method fails to find
- it, it will raise a ValueError, which should signify an abnormal, orphaned parameter.
+ *All* parameters should have a container model.
+
+ :raises ~exceptions.ValueError: if failed to find a container model, which signifies an
+ abnormal, orphaned parameter
"""
from . import models
@@ -253,7 +266,11 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
@caching.cachedmethod
def service(self):
"""
- The :class:`Service` containing this parameter, or None if not contained in a service.
+ The :class:`~aria.modeling.models.Service` model containing this parameter, or ``None`` if
+ not contained in a service.
+
+ :raises ~exceptions.ValueError: if failed to find a container model, which signifies an
+ abnormal, orphaned parameter
"""
from . import models
@@ -268,8 +285,11 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
@caching.cachedmethod
def service_template(self):
"""
- The :class:`ServiceTemplate` containing this parameter, or None if not contained in a
- service template.
+ The :class:`~aria.modeling.models.ServiceTemplate` model containing this parameter, or
+ ``None`` if not contained in a service template.
+
+ :raises ~exceptions.ValueError: if failed to find a container model, which signifies an
+ abnormal, orphaned parameter
"""
from . import models
@@ -329,10 +349,10 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods):
cos01 specification <http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/cos01
/TOSCA-Simple-Profile-YAML-v1.0-cos01.html#_Toc373867862>`__
- :param name: Parameter name
+ :param name: parameter name
:type name: basestring
- :param value: Parameter value
- :param description: Description (optional)
+ :param value: parameter value
+ :param description: human-readable description (optional)
:type description: basestring
"""
@@ -345,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/2ed2e1c2/aria/modeling/models.py
----------------------------------------------------------------------
diff --git a/aria/modeling/models.py b/aria/modeling/models.py
index f30b86f..cf84fdb 100644
--- a/aria/modeling/models.py
+++ b/aria/modeling/models.py
@@ -13,6 +13,74 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+"""
+Data models.
+
+Service template models
+-----------------------
+
+.. autosummary::
+ :nosignatures:
+
+ aria.modeling.models.ServiceTemplate
+ aria.modeling.models.NodeTemplate
+ aria.modeling.models.GroupTemplate
+ aria.modeling.models.PolicyTemplate
+ aria.modeling.models.SubstitutionTemplate
+ aria.modeling.models.SubstitutionTemplateMapping
+ aria.modeling.models.RequirementTemplate
+ aria.modeling.models.RelationshipTemplate
+ aria.modeling.models.CapabilityTemplate
+ aria.modeling.models.InterfaceTemplate
+ aria.modeling.models.OperationTemplate
+ aria.modeling.models.ArtifactTemplate
+ aria.modeling.models.PluginSpecification
+
+Service instance models
+-----------------------
+
+.. autosummary::
+ :nosignatures:
+
+ aria.modeling.models.Service
+ aria.modeling.models.Node
+ aria.modeling.models.Group
+ aria.modeling.models.Policy
+ aria.modeling.models.Substitution
+ aria.modeling.models.SubstitutionMapping
+ aria.modeling.models.Relationship
+ aria.modeling.models.Capability
+ aria.modeling.models.Interface
+ aria.modeling.models.Operation
+ aria.modeling.models.Artifact
+
+Common models
+-------------
+
+.. autosummary::
+ :nosignatures:
+
+ aria.modeling.models.Output
+ aria.modeling.models.Input
+ aria.modeling.models.Configuration
+ aria.modeling.models.Property
+ aria.modeling.models.Attribute
+ aria.modeling.models.Type
+ aria.modeling.models.Metadata
+
+Orchestration models
+--------------------
+
+.. autosummary::
+ :nosignatures:
+
+ aria.modeling.models.Execution
+ aria.modeling.models.Task
+ aria.modeling.models.Log
+ aria.modeling.models.Plugin
+ aria.modeling.models.Argument
+"""
+
# pylint: disable=abstract-method
from sqlalchemy.ext.declarative import declarative_base
@@ -28,14 +96,15 @@ from . import (
service_common,
orchestration,
mixins,
+ utils
)
+
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
@@ -91,54 +160,68 @@ __all__ = (
# region service template models
+@utils.fix_doc
class ServiceTemplate(aria_declarative_base, service_template.ServiceTemplateBase):
name = Column(Text, index=True, unique=True)
+@utils.fix_doc
class NodeTemplate(aria_declarative_base, service_template.NodeTemplateBase):
pass
+@utils.fix_doc
class GroupTemplate(aria_declarative_base, service_template.GroupTemplateBase):
pass
+@utils.fix_doc
class PolicyTemplate(aria_declarative_base, service_template.PolicyTemplateBase):
pass
+@utils.fix_doc
class SubstitutionTemplate(aria_declarative_base, service_template.SubstitutionTemplateBase):
pass
+@utils.fix_doc
class SubstitutionTemplateMapping(aria_declarative_base,
service_template.SubstitutionTemplateMappingBase):
pass
+@utils.fix_doc
class RequirementTemplate(aria_declarative_base, service_template.RequirementTemplateBase):
pass
+@utils.fix_doc
class RelationshipTemplate(aria_declarative_base, service_template.RelationshipTemplateBase):
pass
+@utils.fix_doc
class CapabilityTemplate(aria_declarative_base, service_template.CapabilityTemplateBase):
pass
+@utils.fix_doc
class InterfaceTemplate(aria_declarative_base, service_template.InterfaceTemplateBase):
pass
+@utils.fix_doc
class OperationTemplate(aria_declarative_base, service_template.OperationTemplateBase):
pass
+@utils.fix_doc
class ArtifactTemplate(aria_declarative_base, service_template.ArtifactTemplateBase):
pass
+
+@utils.fix_doc
class PluginSpecification(aria_declarative_base, service_template.PluginSpecificationBase):
pass
@@ -147,46 +230,57 @@ class PluginSpecification(aria_declarative_base, service_template.PluginSpecific
# region service instance models
+@utils.fix_doc
class Service(aria_declarative_base, service_instance.ServiceBase):
name = Column(Text, index=True, unique=True)
+@utils.fix_doc
class Node(aria_declarative_base, service_instance.NodeBase):
pass
+@utils.fix_doc
class Group(aria_declarative_base, service_instance.GroupBase):
pass
+@utils.fix_doc
class Policy(aria_declarative_base, service_instance.PolicyBase):
pass
+@utils.fix_doc
class Substitution(aria_declarative_base, service_instance.SubstitutionBase):
pass
+@utils.fix_doc
class SubstitutionMapping(aria_declarative_base, service_instance.SubstitutionMappingBase):
pass
+@utils.fix_doc
class Relationship(aria_declarative_base, service_instance.RelationshipBase):
pass
+@utils.fix_doc
class Capability(aria_declarative_base, service_instance.CapabilityBase):
pass
+@utils.fix_doc
class Interface(aria_declarative_base, service_instance.InterfaceBase):
pass
+@utils.fix_doc
class Operation(aria_declarative_base, service_instance.OperationBase):
pass
+@utils.fix_doc
class Artifact(aria_declarative_base, service_instance.ArtifactBase):
pass
@@ -195,14 +289,17 @@ class Artifact(aria_declarative_base, service_instance.ArtifactBase):
# region service changes models
+@utils.fix_doc
class ServiceUpdate(aria_declarative_base, service_changes.ServiceUpdateBase):
pass
+@utils.fix_doc
class ServiceUpdateStep(aria_declarative_base, service_changes.ServiceUpdateStepBase):
pass
+@utils.fix_doc
class ServiceModification(aria_declarative_base, service_changes.ServiceModificationBase):
pass
@@ -211,31 +308,37 @@ class ServiceModification(aria_declarative_base, service_changes.ServiceModifica
# region common service models
-
+@utils.fix_doc
class Input(aria_declarative_base, service_common.InputBase):
pass
+@utils.fix_doc
class Configuration(aria_declarative_base, service_common.ConfigurationBase):
pass
+@utils.fix_doc
class Output(aria_declarative_base, service_common.OutputBase):
pass
+@utils.fix_doc
class Property(aria_declarative_base, service_common.PropertyBase):
pass
+@utils.fix_doc
class Attribute(aria_declarative_base, service_common.AttributeBase):
pass
+@utils.fix_doc
class Type(aria_declarative_base, service_common.TypeBase):
pass
+@utils.fix_doc
class Metadata(aria_declarative_base, service_common.MetadataBase):
pass
@@ -244,26 +347,30 @@ class Metadata(aria_declarative_base, service_common.MetadataBase):
# region orchestration models
+@utils.fix_doc
class Execution(aria_declarative_base, orchestration.ExecutionBase):
pass
+@utils.fix_doc
class Plugin(aria_declarative_base, orchestration.PluginBase):
pass
+@utils.fix_doc
class Task(aria_declarative_base, orchestration.TaskBase):
pass
+@utils.fix_doc
class Log(aria_declarative_base, orchestration.LogBase):
pass
+@utils.fix_doc
class Argument(aria_declarative_base, orchestration.ArgumentBase):
pass
-
# endregion
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/2ed2e1c2/aria/modeling/orchestration.py
----------------------------------------------------------------------
diff --git a/aria/modeling/orchestration.py b/aria/modeling/orchestration.py
index 829c305..7068557 100644
--- a/aria/modeling/orchestration.py
+++ b/aria/modeling/orchestration.py
@@ -14,10 +14,7 @@
# limitations under the License.
"""
-classes:
- * Execution - execution implementation model.
- * Plugin - plugin implementation model.
- * Task - a task
+ARIA modeling orchestration module
"""
# pylint: disable=no-self-argument, no-member, abstract-method
@@ -34,7 +31,6 @@ from sqlalchemy import (
Float,
orm,
PickleType)
-from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declared_attr
from ..orchestrator.exceptions import (TaskAbortException, TaskRetryException)
@@ -47,13 +43,13 @@ from . import (
class ExecutionBase(mixins.ModelMixin):
"""
- Execution model representation.
+ Workflow execution.
"""
__tablename__ = 'execution'
- __private_fields__ = ['service_fk',
- 'service_template']
+ __private_fields__ = ('service_fk',
+ 'service_template')
SUCCEEDED = 'succeeded'
FAILED = 'failed'
@@ -72,50 +68,65 @@ 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
+ # region one_to_many relationships
- 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)
+ @declared_attr
+ def inputs(cls):
+ """
+ Execution parameters.
- def has_ended(self):
- return self.status in self.END_STATES
+ :type: {:obj:`basestring`: :class:`Input`}
+ """
+ return relationship.one_to_many(cls, 'input', dict_key='name')
- def is_active(self):
- return not self.has_ended() and self.status != self.PENDING
+ @declared_attr
+ def tasks(cls):
+ """
+ Tasks.
+
+ :type: [:class:`Task`]
+ """
+ return relationship.one_to_many(cls, 'task')
@declared_attr
def logs(cls):
+ """
+ Log messages for the execution (including log messages for its tasks).
+
+ :type: [:class:`Log`]
+ """
return relationship.one_to_many(cls, 'log')
+ # endregion
+
+ # region many_to_one relationships
+
@declared_attr
def service(cls):
+ """
+ Associated service.
+
+ :type: :class:`Service`
+ """
return relationship.many_to_one(cls, 'service')
+ # endregion
+
+ # region association proxies
+
@declared_attr
- def tasks(cls):
- return relationship.one_to_many(cls, 'task')
+ def service_name(cls):
+ return relationship.association_proxy('service', cls.name_column_name())
@declared_attr
- def inputs(cls):
- return relationship.one_to_many(cls, 'input', dict_key='name')
+ def service_template(cls):
+ return relationship.association_proxy('service', 'service_template')
+
+ @declared_attr
+ def service_template_name(cls):
+ return relationship.association_proxy('service', 'service_template_name')
+
+ # endregion
# region foreign keys
@@ -125,92 +136,70 @@ class ExecutionBase(mixins.ModelMixin):
# endregion
- # region association proxies
+ created_at = Column(DateTime, index=True, doc="""
+ Creation timestamp.
- @declared_attr
- def service_name(cls):
- """Required for use by SQLAlchemy queries"""
- return association_proxy('service', cls.name_column_name())
+ :type: :class:`~datetime.datetime`
+ """)
- @declared_attr
- def service_template(cls):
- """Required for use by SQLAlchemy queries"""
- return association_proxy('service', 'service_template')
+ started_at = Column(DateTime, nullable=True, index=True, doc="""
+ Started timestamp.
- @declared_attr
- def service_template_name(cls):
- """Required for use by SQLAlchemy queries"""
- return association_proxy('service', 'service_template_name')
+ :type: :class:`~datetime.datetime`
+ """)
- # endregion
+ ended_at = Column(DateTime, nullable=True, index=True, doc="""
+ Ended timestamp.
- def __str__(self):
- return '<{0} id=`{1}` (status={2})>'.format(
- self.__class__.__name__,
- getattr(self, self.name_column_name()),
- self.status
- )
+ :type: :class:`~datetime.datetime`
+ """)
+ error = Column(Text, nullable=True, doc="""
+ Error message.
-class PluginBase(mixins.ModelMixin):
- """
- An installed plugin.
+ :type: :obj:`basestring`
+ """)
- 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.
+ status = Column(Enum(*STATES, name='execution_status'), default=PENDING, doc="""
+ Status.
- :ivar archive_name: Filename (not the full path) of the wagon's archive, often with a ".wgn"
- extension
- :vartype archive_name: basestring
- :ivar distribution: The name of the operating system on which the wagon was installed (e.g.
- "ubuntu")
- :vartype distribution: basestring
- :ivar distribution_release: The release of the operating system on which the wagon was installed
- (e.g. "trusty")
- :vartype distribution_release: basestring
- :ivar distribution_version: The version of the operating system on which the wagon was installed
- (e.g. "14.04")
- :vartype distribution_version: basestring
- :ivar package_name: The 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: The 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: The 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: The Python versions supported by all the wheels (e.g. ["py26",
- "py27"])
- :vartype supported_py_versions: [basestring]
- :ivar wheels: The 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
- """
+ :type: :obj:`basestring`
+ """)
- __tablename__ = 'plugin'
+ workflow_name = Column(Text, doc="""
+ Workflow name.
- @declared_attr
- def tasks(cls):
- return relationship.one_to_many(cls, 'task')
+ :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
- 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)
+ 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):
@@ -219,46 +208,20 @@ 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: The node actor (optional)
- :vartype node: :class:`Node`
- :ivar relationship: The relationship actor (optional)
- :vartype relationship: :class:`Relationship`
- :ivar plugin: The implementing plugin (set to None for default execution plugin)
- :vartype plugin: :class:`Plugin`
- :ivar function: Python path to an ``@operation`` function
- :vartype function: basestring
- :ivar arguments: Arguments that can be used by this task
- :vartype arguments: {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: :class:`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'
- __private_fields__ = ['dependency_operation_task_fk', 'dependency_stub_task_fk', 'node_fk',
- 'relationship_fk', 'plugin_fk', 'execution_fk']
+ __private_fields__ = ('dependency_operation_task_fk', 'dependency_stub_task_fk', 'node_fk',
+ 'relationship_fk', 'plugin_fk', 'execution_fk')
START_WORKFLOW = 'start_workflow'
END_WORKFLOW = 'end_workflow'
@@ -292,70 +255,91 @@ 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')
- _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):
+ return relationship.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):
+ return relationship.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):
+ return relationship.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)
@@ -369,24 +353,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):
@@ -447,26 +500,36 @@ class TaskBase(mixins.ModelMixin):
class LogBase(mixins.ModelMixin):
+ """
+ Single log message.
+ """
__tablename__ = 'log'
- __private_fields__ = ['execution_fk',
- 'task_fk']
+ __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
@@ -480,6 +543,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
@@ -488,30 +575,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/2ed2e1c2/aria/modeling/relationship.py
----------------------------------------------------------------------
diff --git a/aria/modeling/relationship.py b/aria/modeling/relationship.py
index 76ac316..8b6028f 100644
--- a/aria/modeling/relationship.py
+++ b/aria/modeling/relationship.py
@@ -13,9 +13,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+"""
+ARIA modeling relationship module
+"""
+
# pylint: disable=invalid-name, redefined-outer-name
+
from sqlalchemy.orm import relationship, backref
from sqlalchemy.orm.collections import attribute_mapped_collection
+from sqlalchemy.ext.associationproxy import association_proxy as original_association_proxy
from sqlalchemy import (
Column,
ForeignKey,
@@ -43,9 +49,9 @@ def foreign_key(other_table, nullable=False):
*This utility method should only be used during class creation.*
- :param other_table: Other table name
+ :param other_table: other table name
:type other_table: basestring
- :param nullable: True to allow null values (meaning that there is no relationship)
+ :param nullable: ``True`` to allow null values (meaning that there is no relationship)
:type nullable: bool
"""
@@ -63,9 +69,9 @@ def one_to_one_self(model_class, fk):
*This utility method should only be used during class creation.*
- :param model_class: The class in which this relationship will be declared
+ :param model_class: class in which this relationship will be declared
:type model_class: type
- :param fk: Foreign key name
+ :param fk: foreign key name
:type fk: basestring
"""
@@ -105,17 +111,17 @@ def one_to_one(model_class,
*This utility method should only be used during class creation.*
- :param model_class: The class in which this relationship will be declared
+ :param model_class: class in which this relationship will be declared
:type model_class: type
- :param other_table: Other table name
+ :param other_table: other table name
:type other_table: basestring
- :param fk: Foreign key name at our table (no need specify if there's no ambiguity)
+ :param fk: foreign key name at our table (no need specify if there's no ambiguity)
:type fk: basestring
- :param other_fk: Foreign key name at the other table (no need specify if there's no ambiguity)
+ :param other_fk: foreign key name at the other table (no need specify if there's no ambiguity)
:type other_fk: basestring
- :param back_populates: Override name of matching many-to-many property at other table; set to
- false to disable
- :type back_populates: basestring|bool
+ :param back_populates: override name of matching many-to-many property at other table; set to
+ ``False`` to disable
+ :type back_populates: basestring or bool
"""
backref_kwargs = None
if back_populates is not NO_BACK_POP:
@@ -150,18 +156,23 @@ def one_to_many(model_class,
*This utility method should only be used during class creation.*
- :param model_class: The class in which this relationship will be declared
+ :param model_class: class in which this relationship will be declared
:type model_class: type
- :param child_table: Child table name
+ :param other_table: other table name
:type other_table: basestring
- :param other_fk: Foreign key name at the child table (no need specify if there's no ambiguity)
+ :param other_fk: foreign key name at the other table (no need specify if there's no ambiguity)
:type other_fk: basestring
- :param dict_key: If set the value will be a dict with this key as the dict key; otherwise will
- be a list
+ :param dict_key: if set the value will be a dict with this key as the dict key; otherwise will
+ be a list
:type dict_key: basestring
- :param back_populates: Override name of matching many-to-one property at child table; set to
- false to disable
- :type back_populates: basestring|bool
+ :param back_populates: override name of matching many-to-one property at other table; set to
+ ``False`` to disable
+ :type back_populates: basestring or bool
+ :param rel_kwargs: additional relationship kwargs to be used by SQLAlchemy
+ :type rel_kwargs: dict
+ :param self: used for relationships between a table and itself. if set, other_table will
+ become the same as the source table.
+ :type self: bool
"""
relationship_kwargs = rel_kwargs or {}
if self:
@@ -201,19 +212,19 @@ def many_to_one(model_class,
The declaration will automatically create a matching one-to-many property at the child model,
named after the plural form of our table name. Use the ``parent_property`` argument to override
this name. Note: the automatic property will always be a SQLAlchemy query object; if you need a
- Python collection then use :meth:`one_to_many` at that model.
+ Python collection then use :func:`one_to_many` at that model.
*This utility method should only be used during class creation.*
- :param model_class: The class in which this relationship will be declared
+ :param model_class: class in which this relationship will be declared
:type model_class: type
- :param parent_table: Parent table name
+ :param parent_table: parent table name
:type parent_table: basestring
- :param fk: Foreign key name at our table (no need specify if there's no ambiguity)
+ :param fk: foreign key name at our table (no need specify if there's no ambiguity)
:type fk: basestring
- :param back_populates: Override name of matching one-to-many property at parent table; set to
- false to disable
- :type back_populates: basestring|bool
+ :param back_populates: override name of matching one-to-many property at parent table; set to
+ ``False`` to disable
+ :type back_populates: basestring or bool
"""
if back_populates is None:
back_populates = formatting.pluralize(model_class.__tablename__)
@@ -241,22 +252,25 @@ def many_to_many(model_class,
The declaration will automatically create a matching many-to-many property at the other model,
named after the plural form of our table name. Use the ``other_property`` argument to override
this name. Note: the automatic property will always be a SQLAlchemy query object; if you need a
- Python collection then use :meth:`many_to_many` again at that model.
+ Python collection then use :func:`many_to_many` again at that model.
*This utility method should only be used during class creation.*
- :param model_class: The class in which this relationship will be declared
+ :param model_class: class in which this relationship will be declared
:type model_class: type
- :param other_table: Parent table name
+ :param other_table: parent table name
:type other_table: basestring
- :param prefix: Optional prefix for extra table name as well as for ``other_property``
+ :param prefix: optional prefix for extra table name as well as for ``other_property``
:type prefix: basestring
- :param dict_key: If set the value will be a dict with this key as the dict key; otherwise will
- be a list
+ :param dict_key: if set the value will be a dict with this key as the dict key; otherwise will
+ be a list
:type dict_key: basestring
- :param other_property: Override name of matching many-to-many property at other table; set to
- false to disable
- :type other_property: basestring|bool
+ :param other_property: override name of matching many-to-many property at other table; set to
+ ``False`` to disable
+ :type other_property: basestring or bool
+ :param self: used for relationships between a table and itself. if set, other_table will
+ become the same as the source table.
+ :type self: bool
"""
this_table = model_class.__tablename__
@@ -301,6 +315,21 @@ def many_to_many(model_class,
return _relationship(model_class, other_table, **kwargs)
+def association_proxy(*args, **kwargs):
+ if 'type' in kwargs:
+ type_ = kwargs.get('type')
+ del kwargs['type']
+ else:
+ type_ = ':obj:`basestring`'
+ proxy = original_association_proxy(*args, **kwargs)
+ proxy.__doc__ = """
+ Internal. For use in SQLAlchemy queries.
+
+ :type: {0}
+ """.format(type_)
+ return proxy
+
+
def _relationship(model_class,
other_table_name,
back_populates=None,
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/2ed2e1c2/aria/modeling/service_changes.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_changes.py b/aria/modeling/service_changes.py
index f632fef..061262a 100644
--- a/aria/modeling/service_changes.py
+++ b/aria/modeling/service_changes.py
@@ -14,10 +14,7 @@
# limitations under the License.
"""
-classes:
- * ServiceUpdate - service update implementation model.
- * ServiceUpdateStep - service update step implementation model.
- * ServiceModification - service modification implementation model.
+ARIA modeling service changes module
"""
# pylint: disable=no-self-argument, no-member, abstract-method
@@ -30,7 +27,6 @@ from sqlalchemy import (
DateTime,
Enum,
)
-from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declared_attr
from .types import (List, Dict)
@@ -44,8 +40,8 @@ class ServiceUpdateBase(ModelMixin):
"""
__tablename__ = 'service_update'
- __private_fields__ = ['service_fk',
- 'execution_fk']
+ __private_fields__ = ('service_fk',
+ 'execution_fk')
created_at = Column(DateTime, nullable=False, index=True)
service_plan = Column(Dict, nullable=False)
@@ -55,29 +51,15 @@ 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
def execution_name(cls):
- """Required for use by SQLAlchemy queries"""
- return association_proxy('execution', cls.name_column_name())
+ return relationship.association_proxy('execution', cls.name_column_name())
@declared_attr
def service_name(cls):
- """Required for use by SQLAlchemy queries"""
- return association_proxy('service', cls.name_column_name())
+ return relationship.association_proxy('service', cls.name_column_name())
# endregion
@@ -105,6 +87,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
@@ -119,7 +113,7 @@ class ServiceUpdateStepBase(ModelMixin):
__tablename__ = 'service_update_step'
- __private_fields__ = ['service_update_fk']
+ __private_fields__ = ('service_update_fk',)
_action_types = namedtuple('ACTION_TYPES', 'ADD, REMOVE, MODIFY')
ACTION_TYPES = _action_types(ADD='add', REMOVE='remove', MODIFY='modify')
@@ -143,20 +137,11 @@ 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
def service_update_name(cls):
- """Required for use by SQLAlchemy queries"""
- return association_proxy('service_update', cls.name_column_name())
+ return relationship.association_proxy('service_update', cls.name_column_name())
# endregion
@@ -176,6 +161,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))
@@ -211,7 +204,7 @@ class ServiceModificationBase(ModelMixin):
__tablename__ = 'service_modification'
- __private_fields__ = ['service_fk']
+ __private_fields__ = ('service_fk',)
STARTED = 'started'
FINISHED = 'finished'
@@ -227,20 +220,11 @@ 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
def service_name(cls):
- """Required for use by SQLAlchemy queries"""
- return association_proxy('service', cls.name_column_name())
+ return relationship.association_proxy('service', cls.name_column_name())
# endregion
@@ -253,8 +237,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/2ed2e1c2/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index 0bb861f..b533a88 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -13,6 +13,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+"""
+ARIA modeling service common module
+"""
+
# pylint: disable=no-self-argument, no-member, abstract-method
from sqlalchemy import (
@@ -32,9 +36,34 @@ from . import relationship
class OutputBase(ParameterMixin):
+ """
+ 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
@@ -47,22 +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):
+ @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
@@ -100,71 +187,167 @@ class InputBase(ParameterMixin):
# endregion
+
+class ConfigurationBase(ParameterMixin):
+ """
+ Configuration parameter.
+ """
+
+ __tablename__ = 'configuration'
+
# region many_to_one relationships
@declared_attr
- def service_template(cls):
- return relationship.many_to_one(cls, 'service_template')
+ def operation_template(cls):
+ """
+ Containing operation template (can be ``None``).
+
+ :type: :class:`OperationTemplate`
+ """
+ return relationship.many_to_one(cls, 'operation_template')
@declared_attr
- def service(cls):
- return relationship.many_to_one(cls, 'service')
+ 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 interface(cls):
- return relationship.many_to_one(cls, 'interface')
+ def operation_template_fk(cls):
+ return relationship.foreign_key('operation_template', nullable=True)
@declared_attr
- def operation(cls):
- return relationship.many_to_one(cls, 'operation')
+ def operation_fk(cls):
+ return relationship.foreign_key('operation', nullable=True)
+
+ # endregion
+
+
+class PropertyBase(ParameterMixin):
+ """
+ Property parameter or declaration for a property parameter.
+ """
+
+ __tablename__ = 'property'
+
+ # region many_to_one relationships
@declared_attr
- def interface_template(cls):
- return relationship.many_to_one(cls, 'interface_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 operation_template(cls):
- return relationship.many_to_one(cls, 'operation_template')
+ def group_template(cls):
+ """
+ Containing group template (can be ``None``).
+
+ :type: :class:`GroupTemplate`
+ """
+ return relationship.many_to_one(cls, 'group_template')
@declared_attr
- def execution(cls):
- return relationship.many_to_one(cls, 'execution')
+ def policy_template(cls):
+ """
+ Containing policy template (can be ``None``).
- # endregion
+ :type: :class:`PolicyTemplate`
+ """
+ return relationship.many_to_one(cls, 'policy_template')
+ @declared_attr
+ def relationship_template(cls):
+ """
+ Containing relationship template (can be ``None``).
-class ConfigurationBase(ParameterMixin):
+ :type: :class:`RelationshipTemplate`
+ """
+ return relationship.many_to_one(cls, 'relationship_template')
- __tablename__ = 'configuration'
+ @declared_attr
+ def capability_template(cls):
+ """
+ Containing capability template (can be ``None``).
- # region foreign keys
+ :type: :class:`CapabilityTemplate`
+ """
+ return relationship.many_to_one(cls, 'capability_template')
@declared_attr
- def operation_template_fk(cls):
- return relationship.foreign_key('operation_template', nullable=True)
+ def artifact_template(cls):
+ """
+ Containing artifact template (can be ``None``).
+
+ :type: :class:`ArtifactTemplate`
+ """
+ return relationship.many_to_one(cls, 'artifact_template')
@declared_attr
- def operation_fk(cls):
- return relationship.foreign_key('operation', nullable=True)
+ def node(cls):
+ """
+ Containing node (can be ``None``).
- # endregion
+ :type: :class:`Node`
+ """
+ return relationship.many_to_one(cls, 'node')
- # region many_to_one relationships
+ @declared_attr
+ def group(cls):
+ """
+ Containing group (can be ``None``).
+
+ :type: :class:`Group`
+ """
+ return relationship.many_to_one(cls, 'group')
@declared_attr
- def operation_template(cls):
- return relationship.many_to_one(cls, 'operation_template')
+ def policy(cls):
+ """
+ Containing policy (can be ``None``).
+
+ :type: :class:`Policy`
+ """
+ return relationship.many_to_one(cls, 'policy')
@declared_attr
- def operation(cls):
- return relationship.many_to_one(cls, 'operation')
+ def relationship(cls):
+ """
+ Containing relationship (can be ``None``).
- # endregion
+ :type: :class:`Relationship`
+ """
+ return relationship.many_to_one(cls, 'relationship')
+ @declared_attr
+ def capability(cls):
+ """
+ Containing capability (can be ``None``).
-class PropertyBase(ParameterMixin):
+ :type: :class:`Capability`
+ """
+ return relationship.many_to_one(cls, 'capability')
- __tablename__ = 'property'
+ @declared_attr
+ def artifact(cls):
+ """
+ Containing artifact (can be ``None``).
+
+ :type: :class:`Artifact`
+ """
+ return relationship.many_to_one(cls, 'artifact')
+
+ # endregion
# region foreign keys
@@ -215,65 +398,39 @@ class PropertyBase(ParameterMixin):
@declared_attr
def artifact_fk(cls):
return relationship.foreign_key('artifact', nullable=True)
+
# 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):
-
- __tablename__ = 'attribute'
-
# region foreign keys
@declared_attr
@@ -288,40 +445,52 @@ 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.
+ Type and its children. Can serve as the root for a type hierarchy.
"""
__tablename__ = 'type'
- __private_fields__ = ['parent_type_fk']
+ __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 one_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 one_to_many relationships
+
@declared_attr
def children(cls):
+ """
+ Children.
+
+ :type: [:class:`Type`]
+ """
return relationship.one_to_many(cls, other_fk='parent_type_fk', self=True)
+ # endregion
+
# region foreign keys
@declared_attr
@@ -402,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 [])
@@ -414,9 +584,9 @@ class MetadataBase(TemplateModelMixin):
This model is used by both service template and service instance elements.
- :ivar name: Name
+ :ivar name: name
:vartype name: basestring
- :ivar value: Value
+ :ivar value: value
:vartype value: basestring
"""