You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ariatosca.apache.org by mx...@apache.org on 2017/01/23 10:02:11 UTC
incubator-ariatosca git commit: added basic tests and fixed bunch of
bugs [Forced Update!]
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 <mx...@gmail.com>
Authored: Sun Jan 22 18:37:58 2017 +0200
Committer: mxmrlv <mx...@gmail.com>
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