Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 06394200CB5 for ; Wed, 28 Jun 2017 04:50:38 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 04BEC160BE9; Wed, 28 Jun 2017 02:50:38 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id CE366160BDC for ; Wed, 28 Jun 2017 04:50:35 +0200 (CEST) Received: (qmail 73518 invoked by uid 500); 28 Jun 2017 02:50:35 -0000 Mailing-List: contact commits-help@ariatosca.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ariatosca.incubator.apache.org Delivered-To: mailing list commits@ariatosca.incubator.apache.org Received: (qmail 73509 invoked by uid 99); 28 Jun 2017 02:50:34 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 28 Jun 2017 02:50:34 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id 637B7188A2B for ; Wed, 28 Jun 2017 02:50:34 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.222 X-Spam-Level: X-Spam-Status: No, score=-4.222 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_PASS=-0.001] autolearn=disabled Received: from mx1-lw-us.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id akFDvcOpOi90 for ; Wed, 28 Jun 2017 02:50:23 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-us.apache.org (ASF Mail Server at mx1-lw-us.apache.org) with SMTP id 97AB35F6D2 for ; Wed, 28 Jun 2017 02:50:21 +0000 (UTC) Received: (qmail 73461 invoked by uid 99); 28 Jun 2017 02:50:20 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 28 Jun 2017 02:50:20 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B2E13DFB92; Wed, 28 Jun 2017 02:50:20 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: emblemparade@apache.org To: commits@ariatosca.incubator.apache.org Date: Wed, 28 Jun 2017 02:50:20 -0000 Message-Id: <1f09ad9a2c6a49f385765691e2be0322@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/3] incubator-ariatosca git commit: Full documentation of models; fix to subtitution archived-at: Wed, 28 Jun 2017 02:50:38 -0000 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