You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ariatosca.apache.org by em...@apache.org on 2017/02/21 23:49:38 UTC
incubator-ariatosca git commit: Added RelationshipTemplate;
added one-to-many support
Repository: incubator-ariatosca
Updated Branches:
refs/heads/ARIA-105-integrate-modeling 58e105237 -> f28b0af15
Added RelationshipTemplate; added one-to-many support
Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/f28b0af1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/f28b0af1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/f28b0af1
Branch: refs/heads/ARIA-105-integrate-modeling
Commit: f28b0af157e13c41482921ecba03409c07ca2660
Parents: 58e1052
Author: Tal Liron <ta...@gmail.com>
Authored: Tue Feb 21 17:49:14 2017 -0600
Committer: Tal Liron <ta...@gmail.com>
Committed: Tue Feb 21 17:49:14 2017 -0600
----------------------------------------------------------------------
aria/modeling/instance_elements.py | 42 ++-
aria/modeling/model.py | 10 +-
aria/modeling/structure.py | 24 +-
aria/modeling/template_elements.py | 292 ++++++++++++++++---
aria/modeling/type.py | 2 +-
.../simple_v1_0/modeling/__init__.py | 49 +++-
6 files changed, 354 insertions(+), 65 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f28b0af1/aria/modeling/instance_elements.py
----------------------------------------------------------------------
diff --git a/aria/modeling/instance_elements.py b/aria/modeling/instance_elements.py
index 0666c8a..5ebe692 100644
--- a/aria/modeling/instance_elements.py
+++ b/aria/modeling/instance_elements.py
@@ -33,11 +33,11 @@ from . import (
type as aria_types
)
+
# pylint: disable=no-self-argument, no-member, abstract-method
# region Element instances
-
class ServiceInstanceBase(structure.ModelMixin):
__tablename__ = 'service_instance'
@@ -64,6 +64,7 @@ class ServiceInstanceBase(structure.ModelMixin):
# endregion
# region foreign keys
+
@declared_attr
def substitution_fk(cls):
return cls.foreign_key('substitution', nullable=True)
@@ -75,12 +76,15 @@ class ServiceInstanceBase(structure.ModelMixin):
# endregion
# region one-to-one relationships
+
@declared_attr
def substitution(cls):
return cls.one_to_one_relationship('substitution')
+
# endregion
# region many-to-one relationships
+
@declared_attr
def service_template(cls):
return cls.many_to_one_relationship('service_template')
@@ -184,6 +188,7 @@ class OperationBase(structure.ModelMixin):
return cls.foreign_key('interface', nullable=True)
# endregion
+
description = Column(Text)
implementation = Column(Text)
dependencies = Column(aria_types.StrictList(item_cls=basestring))
@@ -195,6 +200,7 @@ class OperationBase(structure.ModelMixin):
operation = Column(Boolean)
# region many-to-one relationships
+
@declared_attr
def service_instance(cls):
return cls.many_to_one_relationship('service_instance')
@@ -202,6 +208,9 @@ class OperationBase(structure.ModelMixin):
@declared_attr
def interface(cls):
return cls.many_to_one_relationship('interface')
+
+ # endregion
+
# region many-to-many relationships
@declared_attr
@@ -268,6 +277,7 @@ class InterfaceBase(structure.ModelMixin):
# region foreign_keys
+
@declared_attr
def group_fk(cls):
return cls.foreign_key('group', nullable=True)
@@ -363,11 +373,13 @@ class CapabilityBase(structure.ModelMixin):
__private_fields__ = ['node_fk']
# region foreign_keys
+
@declared_attr
def node_fk(cls):
return cls.foreign_key('node')
# endregion
+
type_name = Column(Text)
min_occurrences = Column(Integer, default=None) # optional
@@ -375,14 +387,15 @@ class CapabilityBase(structure.ModelMixin):
occurrences = Column(Integer, default=0)
# region many-to-one relationships
+
@declared_attr
def node(cls):
return cls.many_to_one_relationship('node')
# endregion
-
# region many-to-many relationships
+
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties')
@@ -469,13 +482,13 @@ class ArtifactBase(structure.ModelMixin):
repository_credential = Column(aria_types.StrictDict(basestring, basestring))
# region many-to-one relationships
+
@declared_attr
def node(cls):
return cls.many_to_one_relationship('node')
# endregion
-
# region many-to-many relationships
@declared_attr
@@ -547,11 +560,13 @@ class PolicyBase(structure.ModelMixin):
return cls.foreign_key('service_instance')
# endregion
+
type_name = Column(Text)
target_node_ids = Column(aria_types.StrictList(basestring))
target_group_ids = Column(aria_types.StrictList(basestring))
# region many-to-one relationships
+
@declared_attr
def service_instnce(cls):
return cls.many_to_one_relationship('service_instance')
@@ -629,6 +644,7 @@ class GroupPolicyBase(structure.ModelMixin):
type_name = Column(Text)
# region many-to-one relationships
+
@declared_attr
def group(cls):
return cls.many_to_one_relationship('group')
@@ -636,6 +652,7 @@ class GroupPolicyBase(structure.ModelMixin):
# end region
# region many-to-many relationships
+
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties')
@@ -796,7 +813,6 @@ class SubstitutionBase(structure.ModelMixin):
table_prefix='requirements',
relationship_kwargs=dict(lazy='dynamic'))
-
# endregion
@property
@@ -828,9 +844,9 @@ class SubstitutionBase(structure.ModelMixin):
utils.dump_dict_values(context, self.capabilities, 'Capability mappings')
utils.dump_dict_values(context, self.requirements, 'Requirement mappings')
-
# endregion
+
# region Node instances
class NodeBase(structure.ModelMixin):
@@ -857,6 +873,7 @@ class NodeBase(structure.ModelMixin):
'node_template_fk']
# region foreign_keys
+
@declared_attr
def service_instance_fk(cls):
return cls.foreign_key('service_instance')
@@ -875,6 +892,7 @@ class NodeBase(structure.ModelMixin):
template_name = Column(Text)
# region orchestrator required columns
+
runtime_properties = Column(aria_types.Dict)
scaling_groups = Column(aria_types.List)
state = Column(Text, nullable=False)
@@ -912,9 +930,11 @@ class NodeBase(structure.ModelMixin):
@declared_attr
def service_template(cls):
return association_proxy('service_instance', 'service_template')
+
# endregion
# region many-to-one relationships
+
@declared_attr
def service_instance(cls):
return cls.many_to_one_relationship('service_instance')
@@ -1091,11 +1111,15 @@ class GroupBase(structure.ModelMixin):
member_group_ids = Column(aria_types.StrictList(basestring))
# region many-to-one relationships
+
@declared_attr
def service_instance(cls):
return cls.many_to_one_relationship('service_instance')
+ # endregion
+
# region many-to-many relationships
+
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties')
@@ -1147,8 +1171,8 @@ class GroupBase(structure.ModelMixin):
# endregion
-# region Relationship instances
+# region Relationship instances
class RelationshipBase(structure.ModelMixin):
"""
@@ -1179,7 +1203,8 @@ class RelationshipBase(structure.ModelMixin):
type_name = Column(Text)
template_name = Column(Text)
- # # region orchestrator required columns
+ # region orchestrator required columns
+
source_position = Column(Integer)
target_position = Column(Integer)
@@ -1222,9 +1247,10 @@ class RelationshipBase(structure.ModelMixin):
@declared_attr
def target_node_name(cls):
return association_proxy('target_node', cls.name_column_name())
+
# endregion
- # region many-to-many relationship
+ # region many-to-many relationships
@declared_attr
def properties(cls):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f28b0af1/aria/modeling/model.py
----------------------------------------------------------------------
diff --git a/aria/modeling/model.py b/aria/modeling/model.py
index b16fed0..2777353 100644
--- a/aria/modeling/model.py
+++ b/aria/modeling/model.py
@@ -41,6 +41,7 @@ __all__ = (
'GroupPolicyTriggerTemplate',
'RequirementTemplate',
'CapabilityTemplate',
+ 'RelationshipTemplate',
'Mapping',
'Substitution',
@@ -68,8 +69,8 @@ aria_declarative_base = declarative_base(cls=structure.ModelIDMixin)
# pylint: disable=abstract-method
-# region elements
+# region elements
class Parameter(aria_declarative_base, elements.ParameterBase):
pass
@@ -137,8 +138,12 @@ class CapabilityTemplate(aria_declarative_base, template_elements.CapabilityTemp
pass
+class RelationshipTemplate(aria_declarative_base, template_elements.RelationshipTemplateBase):
+ pass
+
# endregion
+
# region instance models
class Mapping(aria_declarative_base, instance_elements.MappingBase):
@@ -192,9 +197,9 @@ class GroupPolicy(aria_declarative_base, instance_elements.GroupPolicyBase):
class GroupPolicyTrigger(aria_declarative_base, instance_elements.GroupPolicyTriggerBase):
pass
-
# endregion
+
# region orchestrator models
class Execution(aria_declarative_base, orchestrator_elements.Execution):
@@ -222,4 +227,5 @@ class Plugin(aria_declarative_base, orchestrator_elements.PluginBase):
class Task(aria_declarative_base, orchestrator_elements.TaskBase):
pass
+
# endregion
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f28b0af1/aria/modeling/structure.py
----------------------------------------------------------------------
diff --git a/aria/modeling/structure.py b/aria/modeling/structure.py
index eacdb44..8d2401a 100644
--- a/aria/modeling/structure.py
+++ b/aria/modeling/structure.py
@@ -28,6 +28,7 @@ classes:
"""
from sqlalchemy.orm import relationship, backref
+from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.ext import associationproxy
from sqlalchemy import (
Column,
@@ -138,6 +139,17 @@ class ModelMixin(ModelElementBase):
backref=backref(backreference or cls.__tablename__, uselist=False))
@classmethod
+ def one_to_many_relationship(cls, other_table_name, backreference=None, key_column_name=None):
+ # See: http://docs.sqlalchemy.org/en/latest/orm/collections.html
+ collection_class = attribute_mapped_collection(key_column_name) \
+ if key_column_name \
+ else list
+
+ return relationship(lambda: cls._get_cls_by_tablename(other_table_name),
+ backref=backref(backreference or cls.__tablename__, uselist=False),
+ collection_class=collection_class)
+
+ @classmethod
def many_to_one_relationship(cls,
parent_table_name,
foreign_key_column=None,
@@ -184,7 +196,8 @@ class ModelMixin(ModelElementBase):
post_update=True)
@classmethod
- def many_to_many_relationship(cls, other_table_name, table_prefix, relationship_kwargs=None):
+ def many_to_many_relationship(cls, other_table_name, table_prefix, key_column_name=None,
+ relationship_kwargs=None):
"""Return a many-to-many SQL relationship object
Notes:
@@ -194,7 +207,8 @@ class ModelMixin(ModelElementBase):
:param cls: The class of the table we're connecting from
:param other_table_name: The class of the table we're connecting to
:param table_prefix: Custom prefix for the helper table name and the
- backreference name
+ backreference name
+ :param key_column_name: If provided, will use a dict class with this column as the key
"""
current_table_name = cls.__tablename__
current_column_name = '{0}_id'.format(current_table_name)
@@ -219,10 +233,16 @@ class ModelMixin(ModelElementBase):
other_foreign_key
)
+ # See: http://docs.sqlalchemy.org/en/latest/orm/collections.html
+ collection_class = attribute_mapped_collection(key_column_name) \
+ if key_column_name \
+ else list
+
return relationship(
lambda: cls._get_cls_by_tablename(other_table_name),
secondary=secondary_table,
backref=backref(backref_name),
+ collection_class=collection_class,
**(relationship_kwargs or {})
)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f28b0af1/aria/modeling/template_elements.py
----------------------------------------------------------------------
diff --git a/aria/modeling/template_elements.py b/aria/modeling/template_elements.py
index 60e31f8..8d750b1 100644
--- a/aria/modeling/template_elements.py
+++ b/aria/modeling/template_elements.py
@@ -12,6 +12,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
from copy import deepcopy
from types import FunctionType
@@ -25,9 +26,8 @@ from sqlalchemy import (
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declared_attr
-from aria.parser import validation
-from aria.utils import collections, formatting, console
-
+from ..parser import validation
+from ..utils import collections, formatting, console
from . import (
utils,
instance_elements,
@@ -35,13 +35,31 @@ from . import (
type as aria_type
)
-# pylint: disable=no-self-argument, no-member, abstract-method
+# pylint: disable=no-self-argument, no-member, abstract-method
# region Element templates
-
class ServiceTemplateBase(structure.ModelMixin):
+ """
+ A service model is a normalized service template from which :class:`ServiceInstance` instances
+ can be created.
+
+ It is usually created by various DSL parsers, such as ARIA's TOSCA extension. However, it
+ can also be created programmatically.
+
+ Properties:
+
+ * :code:`description`: Human-readable description
+ * :code:`metadata`: :class:`Metadata`
+ * :code:`node_templates`: Dict of :class:`NodeTemplate`
+ * :code:`group_templates`: Dict of :class:`GroupTemplate`
+ * :code:`policy_templates`: Dict of :class:`PolicyTemplate`
+ * :code:`substitution_template`: :class:`SubstituionTemplate`
+ * :code:`inputs`: Dict of :class:`Parameter`
+ * :code:`outputs`: Dict of :class:`Parameter`
+ * :code:`operation_templates`: Dict of :class:`Operation`
+ """
__tablename__ = 'service_template'
@@ -60,6 +78,7 @@ class ServiceTemplateBase(structure.ModelMixin):
# endregion
# region foreign keys
+
@declared_attr
def substitution_template_fk(cls):
return cls.foreign_key('substitution_template', nullable=True)
@@ -67,20 +86,24 @@ class ServiceTemplateBase(structure.ModelMixin):
# endregion
# region one-to-one relationships
+
@declared_attr
def substitution_template(cls):
return cls.one_to_one_relationship('substitution_template')
+
# endregion
# region many-to-many relationships
@declared_attr
def inputs(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='inputs')
+ return cls.many_to_many_relationship('parameter', table_prefix='inputs',
+ key_column_name='name')
@declared_attr
def outputs(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='outputs')
+ return cls.many_to_many_relationship('parameter', table_prefix='outputs',
+ key_column_name='name')
# endregion
@@ -173,10 +196,23 @@ class ServiceTemplateBase(structure.ModelMixin):
class InterfaceTemplateBase(structure.ModelMixin):
+ """
+ A typed set of :class:`OperationTemplate`.
+
+ Properties:
+
+ * :code:`name`: Name
+ * :code:`description`: Description
+ * :code:`type_name`: Must be represented in the :class:`ModelingContext`
+ * :code:`inputs`: Dict of :class:`Parameter`
+ * :code:`operation_templates`: Dict of :class:`OperationTemplate`
+ """
+
__tablename__ = 'interface_template'
__private_fields__ = ['node_template_fk',
- 'group_template_fk']
+ 'group_template_fk',
+ 'relationship_template_fk']
# region foreign keys
@@ -188,15 +224,28 @@ class InterfaceTemplateBase(structure.ModelMixin):
def group_template_fk(cls):
return cls.foreign_key('group_template', nullable=True)
+ @declared_attr
+ def relationship_template_fk(cls):
+ return cls.foreign_key('relationship_template', nullable=True)
+
# endregion
description = Column(Text)
type_name = Column(Text)
- # region many-to-one relationship
+ # region one-to-many relationships
+
@declared_attr
- def node_template(cls):
- return cls.many_to_one_relationship('node_template')
+ def operation_templates(cls):
+ return cls.one_to_many_relationship('operation_template', key_column_name='name')
+
+ # endregion
+
+ # region many-to-one relationships
+
+ #@declared_attr
+ #def node_template(cls):
+ # return cls.many_to_one_relationship('node_template')
@declared_attr
def group_template(cls):
@@ -208,12 +257,13 @@ class InterfaceTemplateBase(structure.ModelMixin):
@declared_attr
def inputs(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='inputs')
+ return cls.many_to_many_relationship('parameter', table_prefix='inputs',
+ key_column_name='name')
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties',
- collection_class=dict)
+ key_column_name='name')
# endregion
@@ -259,6 +309,21 @@ class InterfaceTemplateBase(structure.ModelMixin):
class OperationTemplateBase(structure.ModelMixin):
+ """
+ An operation in a :class:`InterfaceTemplate`.
+
+ Properties:
+
+ * :code:`name`: Name
+ * :code:`description`: Description
+ * :code:`implementation`: Implementation string (interpreted by the orchestrator)
+ * :code:`dependencies`: List of strings (interpreted by the orchestrator)
+ * :code:`executor`: Executor string (interpreted by the orchestrator)
+ * :code:`max_retries`: Maximum number of retries allowed in case of failure
+ * :code:`retry_interval`: Interval between retries
+ * :code:`inputs`: Dict of :class:`Parameter`
+ """
+
__tablename__ = 'operation_template'
__private_fields__ = ['service_template_fk',
@@ -284,24 +349,30 @@ class OperationTemplateBase(structure.ModelMixin):
retry_interval = Column(Integer)
# region orchestrator required columns
+
plugin = Column(Text)
operation = Column(Boolean)
+ # endregion
+
# region many-to-one relationships
+
@declared_attr
def service_template(cls):
return cls.many_to_one_relationship('service_template')
- @declared_attr
- def interface_template(cls):
- return cls.many_to_one_relationship('interface_template')
+ #@declared_attr
+ #def interface_template(cls):
+ # return cls.many_to_one_relationship('interface_template')
+
# endregion
# region many-to-many relationships
@declared_attr
def inputs(cls):
- return cls.many_to_many_relationship('parameter', table_prefix='inputs')
+ return cls.many_to_many_relationship('parameter', table_prefix='inputs',
+ key_column_name='name')
# endregion
@@ -368,6 +439,7 @@ class ArtifactTemplateBase(structure.ModelMixin):
* :code:`repository_credential`: Dict of string
* :code:`properties`: Dict of :class:`Parameter`
"""
+
__tablename__ = 'artifact_template'
__private_fields__ = ['node_template_fk']
@@ -387,10 +459,12 @@ class ArtifactTemplateBase(structure.ModelMixin):
repository_url = Column(Text)
repository_credential = Column(aria_type.StrictDict(basestring, basestring))
- # region many-to-one relationship
- @declared_attr
- def node_template(cls):
- return cls.many_to_one_relationship('node_template')
+ # region many-to-one relationships
+
+ #@declared_attr
+ #def node_template(cls):
+ # return cls.many_to_one_relationship('node_template')
+
# endregion
# region many-to-many relationships
@@ -398,7 +472,7 @@ class ArtifactTemplateBase(structure.ModelMixin):
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties',
- collection_class=dict)
+ key_column_name='name')
# endregion
@@ -487,7 +561,8 @@ class PolicyTemplateBase(structure.ModelMixin):
target_node_template_names = Column(aria_type.StrictList(basestring))
target_group_template_names = Column(aria_type.StrictList(basestring))
- # region many-to-one relationship
+ # region many-to-one relationships
+
@declared_attr
def service_template(cls):
return cls.many_to_one_relationship('service_template')
@@ -503,7 +578,7 @@ class PolicyTemplateBase(structure.ModelMixin):
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties',
- collection_class=dict)
+ key_column_name='name')
# endregion
@@ -572,6 +647,7 @@ class GroupPolicyTemplateBase(structure.ModelMixin):
__private_fields__ = ['group_template_fk']
# region foreign keys
+
@declared_attr
def group_template_fk(cls):
return cls.foreign_key('group_template')
@@ -586,7 +662,7 @@ class GroupPolicyTemplateBase(structure.ModelMixin):
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties',
- collection_class=dict)
+ key_column_name='name')
# endregion
@@ -655,7 +731,8 @@ class GroupPolicyTriggerTemplateBase(structure.ModelMixin):
description = Column(Text)
implementation = Column(Text)
- # region many-to-one relationship
+ # region many-to-one relationships
+
@declared_attr
def group_policy_template(cls):
return cls.many_to_one_relationship('group_policy_template')
@@ -668,7 +745,7 @@ class GroupPolicyTriggerTemplateBase(structure.ModelMixin):
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties',
- collection_class=dict)
+ key_column_name='name')
# endregion
@@ -713,6 +790,7 @@ class MappingTemplateBase(structure.ModelMixin):
* :code:`node_template_name`: Must be represented in the :class:`ServiceModel`
* :code:`name`: Name of capability or requirement at the node template
"""
+
__tablename__ = 'mapping_template'
mapped_name = Column(Text)
@@ -760,6 +838,7 @@ class SubstitutionTemplateBase(structure.ModelMixin):
* :code:`capability_templates`: Dict of :class:`MappingTemplate`
* :code:`requirement_templates`: Dict of :class:`MappingTemplate`
"""
+
__tablename__ = 'substitution_template'
node_type_name = Column(Text)
@@ -822,6 +901,25 @@ class SubstitutionTemplateBase(structure.ModelMixin):
# region Node templates
class NodeTemplateBase(structure.ModelMixin):
+ """
+ A template for creating zero or more :class:`Node` instances.
+
+ Properties:
+
+ * :code:`name`: Name (will be used as a prefix for node IDs)
+ * :code:`description`: Description
+ * :code:`type_name`: Must be represented in the :class:`ModelingContext`
+ * :code:`default_instances`: Default number nodes that will appear in the deployment plan
+ * :code:`min_instances`: Minimum number nodes that will appear in the deployment plan
+ * :code:`max_instances`: Maximum number nodes that will appear in the deployment plan
+ * :code:`properties`: Dict of :class:`Parameter`
+ * :code:`interface_templates`: Dict of :class:`InterfaceTemplate`
+ * :code:`artifact_templates`: Dict of :class:`ArtifactTemplate`
+ * :code:`capability_templates`: Dict of :class:`CapabilityTemplate`
+ * :code:`requirement_templates`: List of :class:`RequirementTemplate`
+ * :code:`target_node_template_constraints`: List of :class:`FunctionType`
+ """
+
__tablename__ = 'node_template'
__private_fields__ = ['service_template_fk',
@@ -861,19 +959,36 @@ class NodeTemplateBase(structure.ModelMixin):
# endregion
- # region many-to-one relationship
+ # region many-to-one relationships
+
@declared_attr
def service_template(cls):
return cls.many_to_one_relationship('service_template')
# endregion
+ # region one-to-many relationships
+
+ @declared_attr
+ def interface_templates(cls):
+ return cls.one_to_many_relationship('interface_template', key_column_name='name')
+
+ @declared_attr
+ def artifact_templates(cls):
+ return cls.one_to_many_relationship('artifact_template', key_column_name='name')
+
+ @declared_attr
+ def capability_templates(cls):
+ return cls.one_to_many_relationship('capability_template', key_column_name='name')
+
+ # endregion
+
# region many-to-many relationships
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties',
- collection_class=dict)
+ key_column_name='name')
# endregion
@@ -964,6 +1079,7 @@ class GroupTemplateBase(structure.ModelMixin):
* :code:`member_node_template_names`: Must be represented in the :class:`ServiceModel`
* :code:`member_group_template_names`: Must be represented in the :class:`ServiceModel`
"""
+
__tablename__ = 'group_template'
__private_fields__ = ['service_template_fk']
@@ -981,7 +1097,8 @@ class GroupTemplateBase(structure.ModelMixin):
member_node_template_names = Column(aria_type.StrictList(basestring))
member_group_template_names = Column(aria_type.StrictList(basestring))
- # region many-to-one relationship
+ # region many-to-one relationships
+
@declared_attr
def service_template(cls):
return cls.many_to_one_relationship('service_template')
@@ -993,7 +1110,7 @@ class GroupTemplateBase(structure.ModelMixin):
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties',
- collection_class=dict)
+ key_column_name='name')
# endregion
@@ -1075,6 +1192,7 @@ class RequirementTemplateBase(structure.ModelMixin):
* :code:`target_capability_name`: Name of capability in target node
* :code:`relationship_template`: :class:`RelationshipTemplate`
"""
+
__tablename__ = 'requirement_template'
__private_fields__ = ['node_template_fk']
@@ -1087,7 +1205,6 @@ class RequirementTemplateBase(structure.ModelMixin):
# endregion
-
target_node_type_name = Column(Text)
target_node_template_name = Column(Text)
target_node_template_constraints = Column(aria_type.StrictList(FunctionType))
@@ -1096,10 +1213,12 @@ class RequirementTemplateBase(structure.ModelMixin):
# CHECK: ???
relationship_template = Column(Text) # optional
- # region many-to-one relationship
+ # region many-to-one relationships
+
@declared_attr
def node_template(cls):
return cls.many_to_one_relationship('node_template')
+
# endregion
def instantiate(self, context, container):
@@ -1237,6 +1356,7 @@ class CapabilityTemplateBase(structure.ModelMixin):
* :code:`valid_source_node_type_names`: Must be represented in the :class:`ModelingContext`
* :code:`properties`: Dict of :class:`Parameter`
"""
+
__tablename__ = 'capability_template'
__private_fields__ = ['node_template_fk']
@@ -1256,10 +1376,12 @@ class CapabilityTemplateBase(structure.ModelMixin):
# CHECK: type?
valid_source_node_type_names = Column(Text)
- # region many-to-one relationship
- @declared_attr
- def node_template(cls):
- return cls.many_to_one_relationship('node_template')
+ # region many-to-one relationships
+
+ #@declared_attr
+ #def node_template(cls):
+ # return cls.many_to_one_relationship('node_template')
+
# endregion
# region many-to-many relationships
@@ -1267,7 +1389,7 @@ class CapabilityTemplateBase(structure.ModelMixin):
@declared_attr
def properties(cls):
return cls.many_to_many_relationship('parameter', table_prefix='properties',
- collection_class=dict)
+ key_column_name='name')
# endregion
@@ -1343,6 +1465,100 @@ class CapabilityTemplateBase(structure.ModelMixin):
for v in self.valid_source_node_type_names)))
dump_parameters(context, self.properties)
+
+class RelationshipTemplateBase(structure.ModelMixin):
+ """
+ Optional addition to a :class:`Requirement` in :class:`NodeTemplate` that can be applied when
+ the requirement is matched with a capability.
+
+ Properties:
+
+ * :code:`type_name`: Must be represented in the :class:`ModelingContext`
+ * :code:`template_name`: Must be represented in the :class:`ServiceModel`
+ * :code:`description`: Description
+ * :code:`properties`: Dict of :class:`Parameter`
+ * :code:`source_interface_templates`: Dict of :class:`InterfaceTemplate`
+ * :code:`target_interface_templates`: Dict of :class:`InterfaceTemplate`
+ """
+
+ __tablename__ = 'relationship_template'
+
+ description = Column(Text)
+ type_name = Column(Text)
+
+ # region many-to-many relationships
+
+ @declared_attr
+ def properties(cls):
+ return cls.many_to_many_relationship('parameter', table_prefix='properties',
+ key_column_name='name')
+
+ # endregion
+
+ # region one-to-many relationships
+
+ @declared_attr
+ def interface_templates(cls):
+ return cls.one_to_many_relationship('interface_template', key_column_name='name')
+
+ # endregion
+
+ @property
+ def as_raw(self):
+ return collections.OrderedDict((
+ ('type_name', self.type_name),
+ ('template_name', self.template_name),
+ ('description', self.description),
+ ('properties', formatting.as_raw_dict(self.properties)),
+ ('source_interface_templates',
+ formatting.as_raw_list(self.source_interface_templates)),
+ ('target_interface_templates',
+ formatting.as_raw_list(self.target_interface_templates))))
+
+ def instantiate(self, context, container):
+ relationship = instance_elements.RelationshipBase(name=self.template_name,
+ type_name=self.type_name)
+ utils.instantiate_dict(context, container,
+ relationship.properties, self.properties)
+ utils.instantiate_dict(context, container,
+ relationship.source_interfaces, self.source_interface_templates)
+ utils.instantiate_dict(context, container,
+ relationship.target_interfaces, self.target_interface_templates)
+ return relationship
+
+ def validate(self, context):
+ if context.modeling.relationship_types.get_descendant(self.type_name) is None:
+ context.validation.report(
+ 'relationship template "{0}" has an unknown type: {1}'.format(
+ self.name,
+ formatting.safe_repr(self.type_name)), # pylint: disable=no-member
+ # TODO fix self.name reference
+ level=validation.Issue.BETWEEN_TYPES)
+
+ utils.validate_dict_values(context, self.properties)
+ utils.validate_dict_values(context, self.source_interface_templates)
+ utils.validate_dict_values(context, self.target_interface_templates)
+
+ def coerce_values(self, context, container, report_issues):
+ utils.coerce_dict_values(context, self, self.properties, report_issues)
+ utils.coerce_dict_values(context, self, self.source_interface_templates, report_issues)
+ utils.coerce_dict_values(context, self, self.target_interface_templates, report_issues)
+
+ def dump(self, context):
+ if self.type_name is not None:
+ console.puts('Relationship type: {0}'.format(context.style.type(self.type_name)))
+ else:
+ console.puts('Relationship template: {0}'.format(
+ context.style.node(self.template_name)))
+ if self.description:
+ console.puts(context.style.meta(self.description))
+ with context.style.indent:
+ utils.dump_parameters(context, self.properties)
+ utils.dump_interfaces(context, self.source_interface_templates,
+ 'Source interface templates')
+ utils.dump_interfaces(context, self.target_interface_templates,
+ 'Target interface templates')
+
# endregion
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f28b0af1/aria/modeling/type.py
----------------------------------------------------------------------
diff --git a/aria/modeling/type.py b/aria/modeling/type.py
index 9e3de3d..2c6453b 100644
--- a/aria/modeling/type.py
+++ b/aria/modeling/type.py
@@ -23,7 +23,7 @@ from sqlalchemy import (
)
from sqlalchemy.ext import mutable
-from .. import exceptions
+from ..storage import exceptions
class _MutableType(TypeDecorator):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/f28b0af1/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 0d33182..9676c0b 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -14,10 +14,12 @@
# limitations under the License.
import re
+from types import FunctionType
-from aria.parser.modeling import Type, RelationshipType, PolicyType, RelationshipTemplate
+from aria.parser.modeling import Type, RelationshipType, PolicyType
+from aria.modeling import type as aria_type
from aria.modeling.model import (ServiceTemplate as ServiceModel, NodeTemplate,
- RequirementTemplate, CapabilityTemplate,
+ RequirementTemplate, RelationshipTemplate, CapabilityTemplate,
GroupTemplate, PolicyTemplate, SubstitutionTemplate,
MappingTemplate, InterfaceTemplate, OperationTemplate,
ArtifactTemplate, Metadata, Parameter)
@@ -31,6 +33,7 @@ from aria.modeling.model import (ServiceTemplate as ServiceModel, NodeTemplate,
from ..data_types import coerce_value
from platform import node
+
def create_service_model(context): # pylint: disable=too-many-locals,too-many-branches
model = ServiceModel()
@@ -80,8 +83,8 @@ def create_service_model(context): # pylint: disable=too-many-locals,too-many-br
node_templates = context.presentation.get('service_template', 'topology_template',
'node_templates')
if node_templates:
- for node_template_name, node_template in node_templates.iteritems():
- model.node_templates[node_template_name] = create_node_template(context, node_template)
+ for node_template in node_templates.itervalues():
+ model.node_templates.append(create_node_template(context, node_template))
groups = context.presentation.get('service_template', 'topology_template', 'groups')
if groups:
@@ -113,6 +116,7 @@ def create_service_model(context): # pylint: disable=too-many-locals,too-many-br
return model
+
def create_node_template(context, node_template):
node_type = node_template._get_type(context)
model = NodeTemplate(name=node_template._name, type_name=node_type._name)
@@ -140,11 +144,13 @@ def create_node_template(context, node_template):
model.capability_templates[capability_name] = create_capability_template(context,
capability)
+ model.target_node_template_constraints = aria_type.StrictList(FunctionType)
create_node_filter_constraint_lambdas(context, node_template.node_filter,
model.target_node_template_constraints)
return model
+
def create_interface_template(context, interface):
interface_type = interface._get_type(context)
model = InterfaceTemplate(name=interface._name, type_name=interface_type._name)
@@ -166,6 +172,7 @@ def create_interface_template(context, interface):
return model if model.operation_templates else None
+
def create_operation_template(context, operation): # pylint: disable=unused-argument
model = OperationTemplate(name=operation._name)
@@ -187,6 +194,7 @@ def create_operation_template(context, operation): # pylint: disable=unused-argu
return model
+
def create_artifact_template(context, artifact):
model = ArtifactTemplate(name=artifact._name, type_name=artifact.type,
source_path=artifact.file)
@@ -208,6 +216,7 @@ def create_artifact_template(context, artifact):
return model
+
def create_requirement_template(context, requirement):
model = {'name': requirement._name}
@@ -236,12 +245,15 @@ def create_requirement_template(context, requirement):
return model
+
def create_relationship_type(context, relationship_type): # pylint: disable=unused-argument
return RelationshipType(relationship_type._name)
+
def create_policy_type(context, policy_type): # pylint: disable=unused-argument
return PolicyType(policy_type._name)
+
def create_relationship_template(context, relationship):
relationship_type, relationship_type_variant = relationship._get_type(context)
if relationship_type_variant == 'relationship_type':
@@ -255,10 +267,11 @@ def create_relationship_template(context, relationship):
model.description = relationship_template.description.value
create_properties_from_assignments(model.properties, relationship.properties)
- create_interface_templates(context, model.source_interface_templates, relationship.interfaces)
+ create_interface_templates(context, model.interface_templates, relationship.interfaces)
return model
+
def create_capability_template(context, capability):
capability_type = capability._get_type(context)
model = CapabilityTemplate(name=capability._name, type_name=capability_type._name)
@@ -280,6 +293,7 @@ def create_capability_template(context, capability):
return model
+
def create_group_template(context, group):
group_type = group._get_type(context)
model = GroupTemplate(name=group._name, type_name=group_type._name)
@@ -297,6 +311,7 @@ def create_group_template(context, group):
return model
+
def create_policy_template(context, policy):
policy_type = policy._get_type(context)
model = PolicyTemplate(name=policy._name, type_name=policy_type._name)
@@ -314,6 +329,7 @@ def create_policy_template(context, policy):
return model
+
#
# Utils
#
@@ -346,19 +362,22 @@ def create_types(context, root, types, normalize=None):
if container is not None:
container.children.append(model)
+
def create_properties_from_values(properties, source_properties):
if source_properties:
for property_name, prop in source_properties.iteritems():
- properties.append(Parameter(name=property_name,
- type=prop.type,
- str_value=prop.value,
- description=prop.description))
+ properties[property_name] = Parameter(type=prop.type,
+ str_value=prop.value,
+ description=prop.description)
+
def create_properties_from_assignments(properties, source_properties):
if source_properties:
for property_name, prop in source_properties.iteritems():
- properties[property_name] = Parameter(prop.value.type, prop.value.value,
- prop.value.description)
+ properties[property_name] = Parameter(type=prop.value.type,
+ str_value=prop.value.value,
+ description=prop.value.description)
+
def create_interface_templates(context, interfaces, source_interfaces):
if source_interfaces:
@@ -367,7 +386,8 @@ def create_interface_templates(context, interfaces, source_interfaces):
if interface is not None:
interfaces[interface_name] = interface
-def create_node_filter_constraint_lambdas(context, node_filter, node_type_constraints):
+
+def create_node_filter_constraint_lambdas(context, node_filter, target_node_template_constraints):
if node_filter is None:
return
@@ -377,7 +397,7 @@ def create_node_filter_constraint_lambdas(context, node_filter, node_type_constr
func = create_constraint_clause_lambda(context, node_filter, constraint_clause,
property_name, None)
if func is not None:
- node_type_constraints.append(func)
+ target_node_template_constraints.append(func)
capabilities = node_filter.capabilities
if capabilities is not None:
@@ -388,7 +408,8 @@ def create_node_filter_constraint_lambdas(context, node_filter, node_type_constr
func = create_constraint_clause_lambda(context, node_filter, constraint_clause,
property_name, capability_name)
if func is not None:
- node_type_constraints.append(func)
+ target_node_template_constraints.append(func)
+
def create_constraint_clause_lambda(context, node_filter, constraint_clause, property_name, # pylint: disable=too-many-return-statements
capability_name):