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 246EB200C05 for ; Mon, 23 Jan 2017 11:02:23 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 22CE2160B49; Mon, 23 Jan 2017 10:02:23 +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 9A542160B3E for ; Mon, 23 Jan 2017 11:02:21 +0100 (CET) Received: (qmail 96467 invoked by uid 500); 23 Jan 2017 10:02:20 -0000 Mailing-List: contact dev-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 dev@ariatosca.incubator.apache.org Received: (qmail 96456 invoked by uid 99); 23 Jan 2017 10:02:20 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 23 Jan 2017 10:02:20 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id 4992CC0118 for ; Mon, 23 Jan 2017 10:02:20 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -5.22 X-Spam-Level: X-Spam-Status: No, score=-5.22 tagged_above=-999 required=6.31 tests=[HK_RANDOM_FROM=0.999, KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-2.999] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id BpaKs9nO2MXp for ; Mon, 23 Jan 2017 10:02:14 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 81C7D5FAD8 for ; Mon, 23 Jan 2017 10:02:12 +0000 (UTC) Received: (qmail 96406 invoked by uid 99); 23 Jan 2017 10:02:11 -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; Mon, 23 Jan 2017 10:02:11 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 9D57BDFBE7; Mon, 23 Jan 2017 10:02:11 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: mxmrlv@apache.org To: dev@ariatosca.incubator.apache.org Message-Id: <5b36f6137cdd48829260f931e54e3ae8@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: incubator-ariatosca git commit: added basic tests and fixed bunch of bugs [Forced Update!] Date: Mon, 23 Jan 2017 10:02:11 +0000 (UTC) archived-at: Mon, 23 Jan 2017 10:02:23 -0000 Repository: incubator-ariatosca Updated Branches: refs/heads/ARIA-44-Merge-parser-and-storage-models fc6b9820c -> 5dac33458 (forced update) added basic tests and fixed bunch of bugs Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/5dac3345 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/5dac3345 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/5dac3345 Branch: refs/heads/ARIA-44-Merge-parser-and-storage-models Commit: 5dac33458fc81c66d37cc031647c51a4361bbe74 Parents: 5e5000e Author: mxmrlv Authored: Sun Jan 22 18:37:58 2017 +0200 Committer: mxmrlv Committed: Mon Jan 23 12:02:01 2017 +0200 ---------------------------------------------------------------------- aria/modeling/elements.py | 8 +- aria/modeling/instance_elements.py | 125 ++++++++++++++++++------------ aria/modeling/model_elements.py | 109 +++++++++++++++++--------- aria/modeling/models.py | 127 +++++++++++++++++++++++++++++++ aria/storage/structure.py | 22 ++++-- tests/storage/__init__.py | 6 +- tests/storage/test_model_storage.py | 6 +- tests/storage/test_new_modelling.py | 66 ++++++++++++++++ 8 files changed, 367 insertions(+), 102 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5dac3345/aria/modeling/elements.py ---------------------------------------------------------------------- diff --git a/aria/modeling/elements.py b/aria/modeling/elements.py index bb4359a..af9ee36 100644 --- a/aria/modeling/elements.py +++ b/aria/modeling/elements.py @@ -15,7 +15,7 @@ from sqlalchemy import ( Column, - Text + Text, ) from ..utils.collections import OrderedDict @@ -84,11 +84,11 @@ class Parameter(ModelElement, structure.ModelMixin): This class is used by both service model and service instance elements. """ - + __tablename__ = 'parameter' type_name = Column(Text) - value = Column() + # Check: value type + value = Column(Text) description = Column(Text) - # NOTE: there is no need to hold an owner. (prob no backtracking to the owner is needed) @property def as_raw(self): http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5dac3345/aria/modeling/instance_elements.py ---------------------------------------------------------------------- diff --git a/aria/modeling/instance_elements.py b/aria/modeling/instance_elements.py index 240fc76..5af244f 100644 --- a/aria/modeling/instance_elements.py +++ b/aria/modeling/instance_elements.py @@ -3,7 +3,6 @@ from sqlalchemy import ( Column, Text, Integer, - ForeignKey ) from sqlalchemy.ext.declarative import declared_attr @@ -15,11 +14,12 @@ from ..parser import validation # region Element instances -class ServiceInstance(elements.Element, structure.ModelMixin): +class ServiceInstance(structure.ModelMixin): __tablename__ = 'service_instance' description = Column(Text) - metadata = Column() - substitution = Column() + # Check: type + metadata = Column(Text) + substitution = Column(Text) # region one-to-many relationships @declared_attr @@ -53,21 +53,21 @@ class ServiceInstance(elements.Element, structure.ModelMixin): def satisfy_requirements(self, context): satisfied = True - for node in self.nodes.values(): + for node in self.nodes.itervalues(): if not node.satisfy_requirements(context): satisfied = False return satisfied def validate_capabilities(self, context): satisfied = True - for node in self.nodes.values(): + for node in self.nodes.itervalues(): if not node.validate_capabilities(context): satisfied = False return satisfied def find_nodes(self, node_template_name): nodes = [] - for node in self.nodes.values(): + for node in self.nodes.itervalues(): if node.template_name == node_template_name: nodes.append(node) return collections.FrozenList(nodes) @@ -77,7 +77,7 @@ class ServiceInstance(elements.Element, structure.ModelMixin): def find_groups(self, group_template_name): groups = [] - for group in self.groups.values(): + for group in self.groups.itervalues(): if group.template_name == group_template_name: groups.append(group) return collections.FrozenList(groups) @@ -86,7 +86,7 @@ class ServiceInstance(elements.Element, structure.ModelMixin): return collections.FrozenList((group.id for group in self.find_groups(group_template_name))) def is_node_a_target(self, context, target_node): - for node in self.nodes.values(): + for node in self.nodes.itervalues(): if self._is_node_a_target(context, node, target_node): return True return False @@ -104,7 +104,7 @@ class ServiceInstance(elements.Element, structure.ModelMixin): return False -class Operation(elements.Element, structure.ModelMixin): +class Operation(structure.ModelMixin): """ An operation in a :class:`Interface`. @@ -121,15 +121,21 @@ class Operation(elements.Element, structure.ModelMixin): """ __tablename__ = 'operation' # region foreign_keys - service_instance_fk = Column(Integer, ForeignKey('service_instance.id')) - interface_instance_fk = Column(Integer, ForeignKey('interface.id')) + @declared_attr + def service_instance_fk(cls): + return cls.foreign_key(ServiceInstance) + + @declared_attr + def interface_instance_fk(cls): + return cls.foreign_key(Interface) # endregion description = Column(Text) # Check: what's this for? - implementation = Column() + implementation = Column(Text) dependencies = Column(type.StrictList(item_cls=basestring)) - executor = Column() + + executor = Column(Text) max_retries = Column(Integer, default=None) retry_interval = Column(Integer, default=None) @@ -178,7 +184,7 @@ class Operation(elements.Element, structure.ModelMixin): utils.dump_parameters(context, self.inputs, 'Inputs') -class Interface(elements.Element, structure.ModelMixin): +class Interface(structure.ModelMixin): """ A typed set of :class:`Operation`. @@ -192,8 +198,13 @@ class Interface(elements.Element, structure.ModelMixin): """ __tablename__ = 'interface' # region foreign_keys - group_fk = Column(Integer, ForeignKey('group.id')) - node_fk = Column(Integer, ForeignKey('node.id')) + @declared_attr + def group_fk(cls): + return cls.foreign_key(Group) + + @declared_attr + def node_fk(cls): + return cls.foreign_key(Node) # endregion @@ -249,7 +260,7 @@ class Interface(elements.Element, structure.ModelMixin): utils.dump_dict_values(context, self.operations, 'Operations') -class Capability(elements.Element, structure.ModelMixin): +class Capability(structure.ModelMixin): """ A capability of a :class:`Node`. @@ -265,7 +276,9 @@ class Capability(elements.Element, structure.ModelMixin): """ __tablename__ = 'capability' # region foreign_keys - node_fk = Column(Integer, ForeignKey('node.id')) + @declared_attr + def node_fk(cls): + return cls.foreign_key(Node) # endregion type_name = Column(Text) @@ -326,7 +339,7 @@ class Capability(elements.Element, structure.ModelMixin): utils.dump_parameters(context, self.properties) -class Artifact(elements.Element, structure.ModelMixin): +class Artifact(structure.ModelMixin): """ A file associated with a :class:`Node`. @@ -343,15 +356,18 @@ class Artifact(elements.Element, structure.ModelMixin): """ __tablename__ = 'artifact' # region foreign_keys - node_fk = Column(Integer, ForeignKey('node.id')) + + @declared_attr + def node_fk(cls): + return cls.foreign_key(Node) # endregion description = Column(Text) type_name = Column(Text) # Check: what's that? - source_path = Column() - target_path = Column() + source_path = Column(Text) + target_path = Column(Text) repository_url = Column(Text) repository_credential = Column(type.StrictDict(basestring, basestring)) @@ -403,7 +419,7 @@ class Artifact(elements.Element, structure.ModelMixin): utils.dump_parameters(context, self.properties) -class Policy(elements.Element, structure.ModelMixin): +class Policy(structure.ModelMixin): """ An instance of a :class:`PolicyTemplate`. @@ -417,7 +433,9 @@ class Policy(elements.Element, structure.ModelMixin): """ __tablename__ = 'policy' # region foreign_keys - service_instance_fk = Column(Integer, ForeignKey('service_instance.id')) + @declared_attr + def service_instance_fk(cls): + return cls.foreign_key(ServiceInstance) # endregion type_name = Column(Text) @@ -470,7 +488,7 @@ class Policy(elements.Element, structure.ModelMixin): console.puts(context.style.node(group_id)) -class GroupPolicy(elements.Element, structure.ModelMixin): +class GroupPolicy(structure.ModelMixin): """ Policies applied to groups. @@ -484,7 +502,9 @@ class GroupPolicy(elements.Element, structure.ModelMixin): """ __tablename__ = 'group_policy' # region foreign_keys - group_fk = Column(Integer, ForeignKey('group.id')) + @declared_attr + def group_fk(cls): + return cls.foreign_key(Group) # endregion @@ -540,7 +560,7 @@ class GroupPolicy(elements.Element, structure.ModelMixin): utils.dump_dict_values(context, self.triggers, 'Triggers') -class GroupPolicyTrigger(elements.Element, structure.ModelMixin): +class GroupPolicyTrigger(structure.ModelMixin): """ Triggers for :class:`GroupPolicy`. @@ -551,14 +571,18 @@ class GroupPolicyTrigger(elements.Element, structure.ModelMixin): * :code:`implementation`: Implementation string (interpreted by the orchestrator) * :code:`properties`: Dict of :class:`Parameter` """ - # section foregin keys - group_policy_fk = Column(Integer, ForeignKey('group_policy.id')) + __tablename__ = 'group_policy_trigger' + # region foreign keys + + @declared_attr + def group_policy_fk(cls): + return cls.foreign_key(GroupPolicy) - # endsection + # endregion description = Column(Text) # Check: what's that? - implementation = Column() + implementation = Column(Text) # region many-to-many relationships @@ -591,7 +615,7 @@ class GroupPolicyTrigger(elements.Element, structure.ModelMixin): utils.dump_parameters(context, self.properties) -class Mapping(elements.Element, structure.ModelMixin): +class Mapping(structure.ModelMixin): """ An instance of a :class:`MappingTemplate`. @@ -601,6 +625,7 @@ class Mapping(elements.Element, structure.ModelMixin): * :code:`node_id`: Must be represented in the :class:`ServiceInstance` * :code:`name`: Name of capability or requirement at the node """ + __tablename__ = 'mapping' mapped_name = Column(Text) node_id = Column(Text) @@ -619,7 +644,7 @@ class Mapping(elements.Element, structure.ModelMixin): context.style.node(self.name))) -class Substitution(elements.Element, structure.ModelMixin): +class Substitution(structure.ModelMixin): """ An instance of a :class:`SubstitutionTemplate`. @@ -629,7 +654,7 @@ class Substitution(elements.Element, structure.ModelMixin): * :code:`capabilities`: Dict of :class:`Mapping` * :code:`requirements`: Dict of :class:`Mapping` """ - + __tablename__ = 'substitution' node_type_name = Column(Text) # region many-to-many relationships @@ -678,7 +703,7 @@ class Substitution(elements.Element, structure.ModelMixin): # region Node instances -class Node(elements.Element, structure.ModelMixin): +class Node(structure.ModelMixin): """ An instance of a :class:`NodeTemplate`. @@ -698,7 +723,9 @@ class Node(elements.Element, structure.ModelMixin): __tablename__ = 'node' # region foreign_keys - service_instance_fk = Column(Integer, ForeignKey('service_instance.id')) + @declared_attr + def service_instance_fk(cls): + return cls.foreign_key(ServiceInstance) # endregion @@ -806,7 +833,7 @@ class Node(elements.Element, structure.ModelMixin): def validate_capabilities(self, context): satisfied = False - for capability in self.capabilities.values(): + for capability in self.capabilities.itervalues(): if not capability.has_enough_relationships: context.validation.report('capability "%s" of node "%s" requires at least %d ' 'relationships but has %d' @@ -865,7 +892,7 @@ class Node(elements.Element, structure.ModelMixin): utils.dump_list_values(context, self.relationships, 'Relationships') -class Group(elements.Element, structure.ModelMixin): +class Group(structure.ModelMixin): """ An instance of a :class:`GroupTemplate`. @@ -882,7 +909,9 @@ class Group(elements.Element, structure.ModelMixin): """ __tablename__ = 'group' # region foreign_keys - service_instance_fk = Column(Integer, ForeignKey('service_instance.id')) + @declared_attr + def service_instance_fk(cls): + return cls.foreign_key(ServiceInstance) # endregion @@ -957,7 +986,7 @@ class Group(elements.Element, structure.ModelMixin): # region Relationship instances -class Relationship(elements.Element, structure.ModelMixin): +class Relationship(structure.ModelMixin): """ Connects :class:`Node` to another node. @@ -977,7 +1006,9 @@ class Relationship(elements.Element, structure.ModelMixin): """ __tablename__ = 'relationship' # region foreign_keys - node_fk = Column(Integer, ForeignKey('node.id')) + @declared_attr + def node_fk(cls): + return cls.foreign_key(Node) # endregion @@ -987,7 +1018,7 @@ class Relationship(elements.Element, structure.ModelMixin): type_name = Column(Text) template_name = Column(Text) - # region many-to-many relationships + # region many-to-many relationsh @declared_attr def properties(cls): @@ -995,15 +1026,11 @@ class Relationship(elements.Element, structure.ModelMixin): @declared_attr def source_interfaces(cls): - return utils.many_to_many_relationship( - cls, elements.Parameter, table_prefix='source_interfaces') + return cls.many_to_many_relationship(elements.Parameter, table_prefix='source_interfaces') @declared_attr def target_interfaces(cls): - return utils.many_to_many_relationship( - cls, elements.Parameter, table_prefix='target_interfaces') - - # endregion + return cls.many_to_many_relationship(elements.Parameter, table_prefix='target_interfaces') @property def as_raw(self): http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5dac3345/aria/modeling/model_elements.py ---------------------------------------------------------------------- diff --git a/aria/modeling/model_elements.py b/aria/modeling/model_elements.py index 034337a..94ba6cb 100644 --- a/aria/modeling/model_elements.py +++ b/aria/modeling/model_elements.py @@ -19,7 +19,6 @@ from sqlalchemy import ( Column, Text, Integer, - ForeignKey ) from sqlalchemy.ext.declarative import declared_attr @@ -34,13 +33,14 @@ from ..parser import validation # note: has multiple values with the same key? maybe could be fixed via unique id? -class ServiceTemplate(elements.ModelElement, structure.ModelMixin): +class ServiceTemplate(structure.ModelMixin): __tablename__ = 'service_template' description = Column(Text) metadata = Column(Text) - substitution_template = Column() + # Check type + substitution_template = Column(Text) # region one-to-many relationships @declared_attr @@ -161,11 +161,17 @@ class ServiceTemplate(elements.ModelElement, structure.ModelMixin): utils.dump_dict_values(context, self.operation_templates, 'Operation templates') -class InterfaceTemplate(elements.ModelElement, structure.ModelMixin): +class InterfaceTemplate(structure.ModelMixin): __tablename__ = 'interface_template' # region foreign keys - node_template_fk = Column(Integer, ForeignKey('node_template.id')) - group_template_fk = Column(Integer, ForeignKey('group_template.id')) + + @declared_attr + def node_template_fk(cls): + return cls.foreign_key(NodeTemplate) + + @declared_attr + def group_template_fk(cls): + return cls.foreign_key(GroupTemplate) # endregion @@ -183,6 +189,9 @@ class InterfaceTemplate(elements.ModelElement, structure.ModelMixin): def inputs(cls): return cls.many_to_many_relationship(elements.Parameter, table_prefix='inputs') + @declared_attr + def properties(cls): + return cls.many_to_many_relationship(elements.Parameter, table_prefix='properties') # endregion @property @@ -226,18 +235,25 @@ class InterfaceTemplate(elements.ModelElement, structure.ModelMixin): utils.dump_dict_values(context, self.operation_templates, 'Operation templates') -class OperationTemplate(elements.ModelElement, structure.ModelMixin): +class OperationTemplate(structure.ModelMixin): __tablename__ = 'operation_template' # region foreign keys - service_template_fk = Column(Integer, ForeignKey('service_template.id')) - interface_template_fk = Column(Integer, ForeignKey('interface_template.id')) + @declared_attr + def service_template_fk(cls): + return cls.foreign_key(ServiceTemplate) + + @declared_attr + def interface_template_fk(cls): + return cls.foreign_key(InterfaceTemplate) # endregion description = Column(Text) - implementation = Column() + # Check: type + implementation = Column(Text) dependencies = Column(type.StrictList(item_cls=basestring)) - executor = Column() + # Check + executor = Column(Text) max_retries = Column(Integer) retry_interval = Column(Integer) @@ -297,7 +313,7 @@ class OperationTemplate(elements.ModelElement, structure.ModelMixin): dump_parameters(context, self.inputs, 'Inputs') -class ArtifactTemplate(elements.ModelElement, structure.ModelMixin): +class ArtifactTemplate(structure.ModelMixin): """ A file associated with a :class:`NodeTemplate`. @@ -314,7 +330,9 @@ class ArtifactTemplate(elements.ModelElement, structure.ModelMixin): """ __tablename__ = 'artifact_template' # region foreign keys - node_template_fk = Column(Integer, ForeignKey('node_template.id')) + @declared_attr + def node_template_fk(cls): + return cls.foreign_key(NodeTemplate) # endregion @@ -322,7 +340,7 @@ class ArtifactTemplate(elements.ModelElement, structure.ModelMixin): type_name = Column(Text) source_path = Column(Text) # Check: what the hell is target path? - target_path = Column() + target_path = Column(Text) repository_url = Column(Text) repository_credential = Column(type.StrictDict(basestring, basestring)) @@ -383,7 +401,7 @@ class ArtifactTemplate(elements.ModelElement, structure.ModelMixin): dump_parameters(context, self.properties) -class PolicyTemplate(elements.ModelElement, structure.ModelMixin): +class PolicyTemplate(structure.ModelMixin): """ Policies can be applied to zero or more :class:`NodeTemplate` or :class:`GroupTemplate` instances. @@ -399,7 +417,13 @@ class PolicyTemplate(elements.ModelElement, structure.ModelMixin): """ __tablename__ = 'policy_template' # region foreign keys - service_template_fk = Column(Integer, ForeignKey('service_template.id')) + @declared_attr + def service_template_fk(cls): + return cls.foreign_key(ServiceTemplate) + + @declared_attr + def group_template_fk(cls): + return cls.foreign_key(GroupTemplate) # endregion @@ -463,7 +487,7 @@ class PolicyTemplate(elements.ModelElement, structure.ModelMixin): (str(context.style.node(v)) for v in self.target_group_template_names))) -class GroupPolicyTemplate(elements.ModelElement, structure.ModelMixin): +class GroupPolicyTemplate(structure.ModelMixin): """ Policies applied to groups. @@ -478,7 +502,9 @@ class GroupPolicyTemplate(elements.ModelElement, structure.ModelMixin): __tablename__ = 'group_policy_template' # region foreign keys - group_template_fk = Column(Integer, ForeignKey('group_template.id')) + @declared_attr + def group_template_fk(cls): + return cls.foreign_key(GroupTemplate) # endregion @@ -539,7 +565,7 @@ class GroupPolicyTemplate(elements.ModelElement, structure.ModelMixin): utils.dump_dict_values(context, self.triggers, 'Triggers') -class GroupPolicyTriggerTemplate(elements.ModelElement, structure.ModelMixin): +class GroupPolicyTriggerTemplate(structure.ModelMixin): """ Triggers for :class:`GroupPolicyTemplate`. @@ -552,13 +578,15 @@ class GroupPolicyTriggerTemplate(elements.ModelElement, structure.ModelMixin): """ __tablename__ = 'group_policy_trigger_template' # region foreign keys - group_policy_template_fk = Column(Integer, ForeignKey('group_policy_template.id')) + @declared_attr + def group_policy_template_fk(cls): + return cls.foreign_key(GroupPolicyTemplate) # endregion description = Column(Text) # Check: ??? - implementation = Column() + implementation = Column(Text) # region many-to-many relationships @@ -598,7 +626,7 @@ class GroupPolicyTriggerTemplate(elements.ModelElement, structure.ModelMixin): dump_parameters(context, self.properties) -class MappingTemplate(elements.ModelElement, structure.ModelMixin): +class MappingTemplate(structure.ModelMixin): """ Used by :class:`SubstitutionTemplate` to map a capability or a requirement to a node. @@ -645,7 +673,7 @@ class MappingTemplate(elements.ModelElement, structure.ModelMixin): context.style.node(self.name))) -class SubstitutionTemplate(elements.ModelElement, structure.ModelMixin): +class SubstitutionTemplate(structure.ModelMixin): """ Used to substitute a single node for the entire deployment. @@ -662,13 +690,11 @@ class SubstitutionTemplate(elements.ModelElement, structure.ModelMixin): @declared_attr def capability_templates(cls): - return utils.many_to_many_relationship( - cls, MappingTemplate, table_prefix='capability_templates') + return cls.many_to_many_relationship(MappingTemplate, table_prefix='capability_templates') @declared_attr def requirement_templates(cls): - return utils.many_to_many_relationship( - cls, MappingTemplate, table_prefix='requirement_templates') + return cls.many_to_many_relationship(MappingTemplate, table_prefix='requirement_templates') # endregion @@ -714,11 +740,13 @@ class SubstitutionTemplate(elements.ModelElement, structure.ModelMixin): # region Node templates -class NodeTemplate(elements.ModelElement, structure.ModelMixin): +class NodeTemplate(structure.ModelMixin): __tablename__ = 'node_template' # region foreign_keys - service_template_fk = Column(Integer, ForeignKey('service_template.id')) + @declared_attr + def service_template_fk(cls): + return cls.foreign_key(ServiceTemplate) # endregion @@ -825,7 +853,7 @@ class NodeTemplate(elements.ModelElement, structure.ModelMixin): utils.dump_list_values(context, self.requirement_templates, 'Requirement templates') -class GroupTemplate(elements.ModelElement, structure.ModelMixin): +class GroupTemplate(structure.ModelMixin): """ A template for creating zero or more :class:`Group` instances. @@ -845,7 +873,10 @@ class GroupTemplate(elements.ModelElement, structure.ModelMixin): """ __tablename__ = 'group_template' # region foreign keys - service_template_fk = Column(Integer, ForeignKey('service_template.id')) + + @declared_attr + def service_template_fk(cls): + return cls.foreign_key(ServiceTemplate) # endregion @@ -932,7 +963,7 @@ class GroupTemplate(elements.ModelElement, structure.ModelMixin): # region Relationship templates -class RequirementTemplate(elements.ModelElement, structure.ModelMixin): +class RequirementTemplate(structure.ModelMixin): """ A requirement for a :class:`NodeTemplate`. During instantiation will be matched with a capability of another @@ -953,7 +984,9 @@ class RequirementTemplate(elements.ModelElement, structure.ModelMixin): """ __tablename__ = 'requirement_template' # region foreign keys - node_template_fk = Column(Integer, ForeignKey('node_template.id')) + @declared_attr + def node_template_fk(cls): + return cls.foreign_key(NodeTemplate) # endregion @@ -963,7 +996,7 @@ class RequirementTemplate(elements.ModelElement, structure.ModelMixin): target_capability_type_name = Column(Text) target_capability_name = Column(Text) # CHECK: ??? - relationship_template = Column() # optional + relationship_template = Column(Text) # optional def instantiate(self, context, container): raise NotImplementedError @@ -1085,7 +1118,7 @@ class RequirementTemplate(elements.ModelElement, structure.ModelMixin): self.relationship_template.dump(context) -class CapabilityTemplate(elements.ModelElement, structure.ModelMixin): +class CapabilityTemplate(structure.ModelMixin): """ A capability of a :class:`NodeTemplate`. Nodes expose zero or more capabilities that can be matched with :class:`Requirement` instances of other nodes. @@ -1102,7 +1135,9 @@ class CapabilityTemplate(elements.ModelElement, structure.ModelMixin): """ __tablename__ = 'capability_template' # region foreign keys - node_template_fk = Column(Integer, ForeignKey('node_template.id')) + @declared_attr + def node_template_fk(cls): + return cls.foreign_key(NodeTemplate) # endregion @@ -1111,7 +1146,7 @@ class CapabilityTemplate(elements.ModelElement, structure.ModelMixin): min_occurrences = Column(Integer, default=None) # optional max_occurrences = Column(Integer, default=None) # optional # CHECK: type? - valid_source_node_type_names = Column() + valid_source_node_type_names = Column(Text) # region many-to-many relationships http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5dac3345/aria/modeling/models.py ---------------------------------------------------------------------- diff --git a/aria/modeling/models.py b/aria/modeling/models.py new file mode 100644 index 0000000..95978bb --- /dev/null +++ b/aria/modeling/models.py @@ -0,0 +1,127 @@ +from sqlalchemy.ext.declarative import declarative_base + +from ..storage import structure +from . import elements, model_elements, instance_elements + +DB = declarative_base(cls=structure.ModelIDMixin) + +# region elements + + +class Parameter(DB, elements.Parameter): + pass + +# endregion + +# region template models + + +class ServiceTemplate(DB, model_elements.ServiceTemplate): + pass + + +class NodeTemplate(DB, model_elements.NodeTemplate): + pass + + +class GroupTemplate(DB, model_elements.GroupTemplate): + pass + + +class InterfaceTemplate(DB, model_elements.InterfaceTemplate): + pass + + +class OperationTemplate(DB, model_elements.OperationTemplate): + pass + + +class ArtifactTemplate(DB, model_elements.ArtifactTemplate): + pass + + +class PolicyTemplate(DB, model_elements.PolicyTemplate): + pass + + +class GroupPolicyTemplate(DB, model_elements.GroupPolicyTemplate): + pass + + +class GroupPolicyTriggerTemplate(DB, model_elements.GroupPolicyTriggerTemplate): + pass + + +class MappingTemplate(DB, model_elements.MappingTemplate): + pass + + +class SubstitutionTemplate(DB, model_elements.SubstitutionTemplate): + pass + + +class RequirementTemplate(DB, model_elements.RequirementTemplate): + pass + + +class CapabilityTemplate(DB, model_elements.CapabilityTemplate): + pass + + +# endregion + +# region instance models + +class ServiceInstance(DB, instance_elements.ServiceInstance): + pass + + +class Node(DB, instance_elements.Node): + pass + + +class Artifact(DB, instance_elements.Artifact): + pass + + +class Group(DB, instance_elements.Group): + pass + + +class Interface(DB, instance_elements.Interface): + pass + + +class Operation(DB, instance_elements.Operation): + pass + + +class Capability(DB, instance_elements.Capability): + pass + + + +class Policy(DB, instance_elements.Policy): + pass + + +class GroupPolicy(DB, instance_elements.GroupPolicy): + pass + + +class GroupPolicyTrigger(DB, instance_elements.GroupPolicyTrigger): + pass + + +class Mapping(DB, instance_elements.Mapping): + pass + + +class Substitution(DB, instance_elements.Substitution): + pass + + +class Relationship(DB, instance_elements.Relationship): + pass + +# endregion \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5dac3345/aria/storage/structure.py ---------------------------------------------------------------------- diff --git a/aria/storage/structure.py b/aria/storage/structure.py index 326fe59..de14747 100644 --- a/aria/storage/structure.py +++ b/aria/storage/structure.py @@ -37,8 +37,11 @@ from sqlalchemy import ( Table ) +from ..parser.modeling.elements import Element -class ModelMixin(object): + +# TODO: models should inherit for model_element +class ModelMixin(Element): @classmethod def id_column_name(cls): @@ -115,7 +118,8 @@ class ModelMixin(object): @classmethod def one_to_many_relationship(cls, table, backrefernce=None): - return relationship(table, backref=backrefernce or cls.__tablename__) + return relationship(table.__name__, + backref=backrefernce or cls.__tablename__) @classmethod def relationship_to_self(cls, local_column): @@ -147,17 +151,18 @@ class ModelMixin(object): backreference name """ current_table_name = cls.__tablename__ - current_column_name = '{0}_id'.format(current_table_name[:-1]) + current_column_name = '{0}_id'.format(current_table_name) current_foreign_key = '{0}.{1}'.format( current_table_name, - cls.unique_id() + cls.id_column_name() ) + other_cls = cls._get_cls_by_tablename(other_cls.__tablename__) other_table_name = other_cls.__tablename__ - other_column_name = '{0}_id'.format(other_table_name[:-1]) + other_column_name = '{0}_id'.format(other_table_name) other_foreign_key = '{0}.{1}'.format( other_table_name, - other_cls.unique_id() + other_cls.id_column_name() ) helper_table_name = '{0}_{1}'.format( @@ -171,6 +176,7 @@ class ModelMixin(object): backref_name = '{0}_{1}'.format(table_prefix, backref_name) secondary_table = cls.get_secondary_table( + cls.metadata, helper_table_name, current_column_name, other_column_name, @@ -184,7 +190,8 @@ class ModelMixin(object): ) @staticmethod - def get_secondary_table(helper_table_name, + def get_secondary_table(metadata, + helper_table_name, first_column_name, second_column_name, first_foreign_key, @@ -201,6 +208,7 @@ class ModelMixin(object): """ return Table( helper_table_name, + metadata, Column( first_column_name, Integer, http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5dac3345/tests/storage/__init__.py ---------------------------------------------------------------------- diff --git a/tests/storage/__init__.py b/tests/storage/__init__.py index 9101fd0..1c8b41b 100644 --- a/tests/storage/__init__.py +++ b/tests/storage/__init__.py @@ -34,7 +34,9 @@ class TestFileSystem(object): rmtree(self.path, ignore_errors=True) -def get_sqlite_api_kwargs(base_dir=None, filename='db.sqlite'): +def get_sqlite_api_kwargs(base_dir=None, + filename='db.sqlite', + declarative_base=model.DeclarativeBase): """ Create sql params. works in in-memory and in filesystem mode. If base_dir is passed, the mode will be filesystem mode. while the default mode is in-memory. @@ -59,7 +61,7 @@ def get_sqlite_api_kwargs(base_dir=None, filename='db.sqlite'): session_factory = orm.sessionmaker(bind=engine) session = scoped_session(session_factory=session_factory) if base_dir else session_factory() - model.DeclarativeBase.metadata.create_all(bind=engine) + declarative_base.metadata.create_all(bind=engine) return dict(engine=engine, session=session) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5dac3345/tests/storage/test_model_storage.py ---------------------------------------------------------------------- diff --git a/tests/storage/test_model_storage.py b/tests/storage/test_model_storage.py index 0e8d1a0..ac02cd5 100644 --- a/tests/storage/test_model_storage.py +++ b/tests/storage/test_model_storage.py @@ -112,7 +112,7 @@ def test_inner_list_update(storage): assert storage_mm.model_list[1][0] == 'new_inner_value' assert storage_mm.model_list[0] == 'new_value' - +# TODO: choose a new model to deployment def test_model_to_dict(context): deployment = context.deployment deployment_dict = deployment.to_dict() @@ -137,7 +137,7 @@ def test_model_to_dict(context): assert 'blueprint_fk' not in deployment_dict - +# TODO: change factory to create different models def test_application_storage_factory(): storage = application_model_storage(sql_mapi.SQLAlchemyModelAPI, api_kwargs=get_sqlite_api_kwargs()) @@ -153,7 +153,7 @@ def test_application_storage_factory(): release_sqlite_storage(storage) - +# TODO: support relationship ordering in tosca models def test_relationship_model_ordering(context): deployment = context.model.deployment.get_by_name(models.DEPLOYMENT_NAME) source_node = context.model.node.get_by_name(models.DEPENDENT_NODE_NAME) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/5dac3345/tests/storage/test_new_modelling.py ---------------------------------------------------------------------- diff --git a/tests/storage/test_new_modelling.py b/tests/storage/test_new_modelling.py new file mode 100644 index 0000000..6efeb51 --- /dev/null +++ b/tests/storage/test_new_modelling.py @@ -0,0 +1,66 @@ +import pytest + +from sqlalchemy.ext.declarative import declarative_base +from aria.modeling import models +from aria.storage import ( + ModelStorage, + sql_mapi, + structure, + api +) + +from ..storage import ( + get_sqlite_api_kwargs, + release_sqlite_storage +) + +DB = declarative_base(cls=structure.ModelIDMixin) + +tosca_classes = [ + models.Parameter, + models.ServiceTemplate, + models.NodeTemplate, + models.GroupTemplate, + models.InterfaceTemplate, + models.OperationTemplate, + models.ArtifactTemplate, + models.PolicyTemplate, + models.GroupPolicyTemplate, + models.GroupPolicyTriggerTemplate, + models.MappingTemplate, + models.SubstitutionTemplate, + models.RequirementTemplate, + models.CapabilityTemplate, + models.ServiceInstance, + models.Node, + models.Group, + models.Interface, + models.Operation, + models.Capability, + models.Artifact, + models.Policy, + models.GroupPolicy, + models.GroupPolicyTrigger, + models.Mapping, + models.Substitution, + models.Relationship +] + + +@pytest.fixture +def storage(): + base_storage = ModelStorage(sql_mapi.SQLAlchemyModelAPI, + api_kwargs=get_sqlite_api_kwargs(declarative_base=DB), + items=tosca_classes) + yield base_storage + release_sqlite_storage(base_storage) + + +def test_models_creation(storage): + """ + Tests that the models were created successfully and are accessible through the model api. + :param storage: + :return: + """ + for cls in tosca_classes: + assert len(getattr(storage, api.generate_lower_name(cls)).list()) == 0