Repository: incubator-ariatosca
Updated Branches:
  refs/heads/ARIA-92-plugin-in-implementation-string a062d12f9 -> 08ecf43e5


Final changes


Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/08ecf43e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/08ecf43e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/08ecf43e

Branch: refs/heads/ARIA-92-plugin-in-implementation-string
Commit: 08ecf43e534d5dc2efe3861710430a5bff94f36f
Parents: a062d12
Author: Tal Liron <tal.li...@gmail.com>
Authored: Thu Apr 13 10:55:55 2017 -0500
Committer: Tal Liron <tal.li...@gmail.com>
Committed: Thu Apr 13 12:30:03 2017 -0500

----------------------------------------------------------------------
 aria/modeling/models.py                         | 11 +--
 aria/modeling/service_common.py                 | 56 -----------
 aria/modeling/service_instance.py               | 14 +--
 aria/modeling/service_template.py               | 97 ++++++++++++++++----
 .../execution_plugin/instantiation.py           |  1 +
 .../profiles/aria-1.0/aria-1.0.yaml             |  5 +
 .../simple_v1_0/modeling/__init__.py            |  7 +-
 tests/modeling/test_models.py                   |  2 +-
 .../node-cellar/node-cellar.yaml                |  7 +-
 9 files changed, 107 insertions(+), 93 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/08ecf43e/aria/modeling/models.py
----------------------------------------------------------------------
diff --git a/aria/modeling/models.py b/aria/modeling/models.py
index a01783b..170efb2 100644
--- a/aria/modeling/models.py
+++ b/aria/modeling/models.py
@@ -48,6 +48,7 @@ __all__ = (
     'InterfaceTemplate',
     'OperationTemplate',
     'ArtifactTemplate',
+    'PluginSpecification',
 
     # Service instance models
     'Service',
@@ -71,7 +72,6 @@ __all__ = (
     'Parameter',
     'Type',
     'Metadata',
-    'PluginSpecification',
 
     # Orchestration models
     'Execution',
@@ -131,6 +131,9 @@ class OperationTemplate(aria_declarative_base, 
service_template.OperationTemplat
 class ArtifactTemplate(aria_declarative_base, 
service_template.ArtifactTemplateBase):
     pass
 
+class PluginSpecification(aria_declarative_base, 
service_template.PluginSpecificationBase):
+    pass
+
 # endregion
 
 
@@ -211,10 +214,6 @@ class Type(aria_declarative_base, service_common.TypeBase):
 class Metadata(aria_declarative_base, service_common.MetadataBase):
     pass
 
-
-class PluginSpecification(aria_declarative_base, 
service_common.PluginSpecificationBase):
-    pass
-
 # endregion
 
 
@@ -253,6 +252,7 @@ models_to_register = [
     InterfaceTemplate,
     OperationTemplate,
     ArtifactTemplate,
+    PluginSpecification,
 
     # Service instance models
     Service,
@@ -276,7 +276,6 @@ models_to_register = [
     Parameter,
     Type,
     Metadata,
-    PluginSpecification,
 
     # Orchestration models
     Execution,

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/08ecf43e/aria/modeling/service_common.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_common.py b/aria/modeling/service_common.py
index 2accbf9..1fcbc5f 100644
--- a/aria/modeling/service_common.py
+++ b/aria/modeling/service_common.py
@@ -249,59 +249,3 @@ class MetadataBase(TemplateModelMixin):
         console.puts('{0}: {1}'.format(
             context.style.property(self.name),
             context.style.literal(self.value)))
-
-
-class PluginSpecificationBase(TemplateModelMixin):
-    """
-    Plugin specification.
-
-    :ivar name: Required plugin name
-    :vartype name: basestring
-    :ivar version: Minimum plugin version
-    :vartype version: basestring
-    """
-
-    __tablename__ = 'plugin_specification'
-
-    __private_fields__ = ['service_template_fk']
-
-    version = Column(Text, nullable=True)
-
-    # region foreign keys
-
-    @declared_attr
-    def service_template_fk(cls):
-        """For ServiceTemplate one-to-many to PluginSpecification"""
-        return relationship.foreign_key('service_template', nullable=True)
-
-    # endregion
-
-    @declared_attr
-    def service_template(cls):
-        return relationship.many_to_one(cls, 'service_template')
-
-    @property
-    def as_raw(self):
-        return collections.OrderedDict((
-            ('name', self.name),
-            ('version', self.version)))
-
-    def coerce_values(self, container, report_issues):
-        pass
-
-    def instantiate(self, container):
-        from . import models
-        return models.PluginSpecification(name=self.name,
-                                          version=self.version)
-
-    def find_plugin(self, plugins):
-        matching_plugins = []
-        for plugin in plugins:
-            # TODO: we need to use a version comparator
-            if (plugin.name == self.name) and \
-                ((self.version is None) or (plugin.package_version >= 
self.version)):
-                matching_plugins.append(plugin)
-        if matching_plugins:
-            # Return highest version of plugin
-            return sorted(matching_plugins, key=lambda plugin: 
plugin.package_version)[-1]
-        return None

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/08ecf43e/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py 
b/aria/modeling/service_instance.py
index 4dba99e..40d43fa 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -67,8 +67,8 @@ class ServiceBase(InstanceModelMixin):
     :vartype outputs: {basestring: :class:`Parameter`}
     :ivar workflows: Custom workflows that can be performed on the service
     :vartype workflows: {basestring: :class:`Operation`}
-    :ivar plugin_specifications: Plugins used by the service
-    :vartype plugin_specifications: {basestring: :class:`PluginSpecification`}
+    :ivar plugins: Plugins used by the service
+    :vartype plugins: {basestring: :class:`Plugin`}
     :ivar created_at: Creation timestamp
     :vartype created_at: :class:`datetime.datetime`
     :ivar updated_at: Update timestamp
@@ -178,8 +178,8 @@ class ServiceBase(InstanceModelMixin):
         return relationship.many_to_many(cls, 'parameter', prefix='outputs', 
dict_key='name')
 
     @declared_attr
-    def plugin_specifications(cls):
-        return relationship.many_to_many(cls, 'plugin_specification', 
dict_key='name')
+    def plugins(cls):
+        return relationship.many_to_many(cls, 'plugin', dict_key='name')
 
     # endregion
 
@@ -525,9 +525,8 @@ class NodeBase(InstanceModelMixin):
 
     @property
     def host_address(self):
-        if self.host:
-            if self.host.runtime_properties:
-                return self.host.runtime_properties.get('host_address')
+        if self.host and self.host.runtime_properties:
+            return self.host.runtime_properties.get('ip')
         return None
 
     def satisfy_requirements(self):
@@ -1735,6 +1734,7 @@ class OperationBase(InstanceModelMixin):
 
     def configure(self):
         from . import models
+        # Note: for workflows (operations attached directly to the service) 
"interface" will be None
         if (self.implementation is None) or (self.interface is None):
             return
 

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/08ecf43e/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py 
b/aria/modeling/service_template.py
index 041ba3d..6bd92b3 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -292,6 +292,15 @@ class ServiceTemplateBase(TemplateModelMixin):
 
         context.modeling.instance = service
 
+        for plugin_specification in self.plugin_specifications.itervalues():
+            plugin = plugin_specification.find_plugin()
+            if plugin is not None:
+                service.plugins[plugin.name] = plugin
+            elif plugin_specification.required:
+                context = ConsumptionContext.get_thread_local()
+                context.validation.report('plugin not found for specification: 
{0}'.format(
+                    plugin_specification.name), 
level=validation.Issue.EXTERNAL)
+
         utils.instantiate_dict(self, service.meta_data, self.meta_data)
 
         for node_template in self.node_templates.itervalues():
@@ -302,7 +311,6 @@ class ServiceTemplateBase(TemplateModelMixin):
         utils.instantiate_dict(self, service.groups, self.group_templates)
         utils.instantiate_dict(self, service.policies, self.policy_templates)
         utils.instantiate_dict(self, service.workflows, 
self.workflow_templates)
-        utils.instantiate_dict(self, service.plugin_specifications, 
self.plugin_specifications)
 
         if self.substitution_template is not None:
             service.substitution = 
self.substitution_template.instantiate(container)
@@ -1856,22 +1864,8 @@ class OperationTemplateBase(TemplateModelMixin):
 
     def instantiate(self, container):
         from . import models
-        from ..orchestrator import context
-        plugin = None
-        if self.plugin_specification is not None:
-            # TODO: we are planning a separate "instantiation" module where 
this will be called or
-            # moved to. There, we will probably have a context with a storage 
manager. Until then,
-            # this is the only potentially available context, which of course 
will only be available
-            # if we're in a workflow.
-            try:
-                workflow_context = context.workflow.current.get()
-                plugin = 
self.plugin_specification.find_plugin(workflow_context.model.plugin.list())
-            except context.exceptions.ContextException:
-                pass
-            if plugin is None:
-                context = ConsumptionContext.get_thread_local()
-                context.validation.report('plugin not found for specification: 
{0}'.format(
-                    self.plugin_specification.name), 
level=validation.Issue.EXTERNAL)
+        plugin = self.plugin_specification.find_plugin() \
+            if self.plugin_specification is not None else None
         operation = models.Operation(name=self.name,
                                      
description=deepcopy_with_locators(self.description),
                                      relationship_edge=self.relationship_edge,
@@ -2057,3 +2051,72 @@ class ArtifactTemplateBase(TemplateModelMixin):
                 console.puts('Repository credential: {0}'.format(
                     context.style.literal(self.repository_credential)))
             utils.dump_dict_values(self.properties, 'Properties')
+
+
+class PluginSpecificationBase(TemplateModelMixin):
+    """
+    Plugin specification.
+
+    :ivar name: Required plugin name
+    :vartype name: basestring
+    :ivar version: Minimum plugin version
+    :vartype version: basestring
+    """
+
+    __tablename__ = 'plugin_specification'
+
+    __private_fields__ = ['service_template_fk']
+
+    version = Column(Text)
+    required = Column(Boolean, nullable=False, default=True)
+
+    # region foreign keys
+
+    @declared_attr
+    def service_template_fk(cls):
+        """For ServiceTemplate one-to-many to PluginSpecification"""
+        return relationship.foreign_key('service_template', nullable=True)
+
+    # endregion
+
+    @declared_attr
+    def service_template(cls):
+        return relationship.many_to_one(cls, 'service_template')
+
+    @property
+    def as_raw(self):
+        return collections.OrderedDict((
+            ('name', self.name),
+            ('version', self.version)))
+
+    def coerce_values(self, container, report_issues):
+        pass
+
+    def instantiate(self, container):
+        from . import models
+        return models.PluginSpecification(name=self.name,
+                                          version=self.version)
+
+    def find_plugin(self):
+        # TODO: we are planning a separate "instantiation" module where this 
will be called or
+        # moved to. There, we will probably have a context with a storage 
manager. Until then,
+        # this is the only potentially available context, which of course will 
only be available
+        # if we're in a workflow.
+        from ..orchestrator import context
+        try:
+            workflow_context = context.workflow.current.get()
+            plugins = workflow_context.model.plugin.list()
+        except context.exceptions.ContextException:
+            plugins = None
+
+        matching_plugins = []
+        if plugins:
+            for plugin in plugins:
+                # TODO: we need to use a version comparator
+                if (plugin.name == self.name) and \
+                    ((self.version is None) or (plugin.package_version >= 
self.version)):
+                    matching_plugins.append(plugin)
+        if matching_plugins:
+            # Return highest version of plugin
+            return sorted(matching_plugins, key=lambda plugin: 
plugin.package_version)[-1]
+        return None

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/08ecf43e/aria/orchestrator/execution_plugin/instantiation.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/execution_plugin/instantiation.py 
b/aria/orchestrator/execution_plugin/instantiation.py
index c784d20..960835c 100644
--- a/aria/orchestrator/execution_plugin/instantiation.py
+++ b/aria/orchestrator/execution_plugin/instantiation.py
@@ -161,6 +161,7 @@ def _validate_type(value, the_type, name):
                                   .format(name, full_type_name(the_type)),
                                   level=validation.Issue.BETWEEN_TYPES)
 
+
 def _str_to_bool(value, name):
     if value is None:
         return None

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/08ecf43e/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml 
b/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml
index 43a193c..a16e4af 100644
--- a/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml
+++ b/extensions/aria_extension_tosca/profiles/aria-1.0/aria-1.0.yaml
@@ -31,6 +31,11 @@ policy_types:
           Minimum plugin version.
         type: version
         required: false
+      required:
+        description: >-
+          Whether the plugin is required.
+        type: boolean
+        default: true
 
   aria.Workflow:
     _extensions:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/08ecf43e/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 28c3c8e..7a20a2e 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -468,7 +468,8 @@ def create_plugin_specification_model(context, policy):
         return prop.value if prop is not None else None
 
     model = PluginSpecification(name=policy._name,
-                                version=get('version'))
+                                version=get('version'),
+                                required=get('required'))
 
     return model
 
@@ -738,7 +739,7 @@ def parse_implementation_string(context, service_template, 
presentation, model,
         model.plugin_specification = 
service_template.plugin_specifications.get(plugin_name)
         if model.plugin_specification is None:
             context.validation.report(
-                'no policy for plugin "%s" specified in operation 
implementation: %s'
-                % (plugin_name, implementation),
+                'no policy for plugin "{0}" specified in operation 
implementation: {1}'
+                .format(plugin_name, implementation),
                 locator=presentation._get_child_locator('properties', 
'implementation'),
                 level=Issue.BETWEEN_TYPES)

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/08ecf43e/tests/modeling/test_models.py
----------------------------------------------------------------------
diff --git a/tests/modeling/test_models.py b/tests/modeling/test_models.py
index 7599402..bd4eba4 100644
--- a/tests/modeling/test_models.py
+++ b/tests/modeling/test_models.py
@@ -656,7 +656,7 @@ class TestNodeHostAddress(object):
             if host_address is not None:
                 host_address = host_address.value
         if host_address:
-            kwargs['runtime_properties']['host_address'] = host_address
+            kwargs['runtime_properties']['ip'] = host_address
         if is_host:
             kwargs['host_fk'] = 1
         elif host_fk:

http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/08ecf43e/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
----------------------------------------------------------------------
diff --git 
a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
 
b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
index 2dcf0ec..e21e1f0 100644
--- 
a/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
+++ 
b/tests/resources/service-templates/tosca-simple-1.0/node-cellar/node-cellar.yaml
@@ -98,8 +98,8 @@ topology_template:
               #token: { get_property: [ HOST, flavor_name ] }
       interfaces:
         Maintenance:
-          enable: juju \> charm.maintenance_on
-          disable: juju \> charm.maintenance_off
+          enable: juju > charm.maintenance_on
+          disable: juju > charm.maintenance_off
       requirements:
         - database: node_cellar_database
       capabilities:
@@ -198,7 +198,7 @@ topology_template:
             openstack_credential: { get_input: openstack_credential }
           configure:
             implementation:
-              primary: juju \> run_charm
+              primary: juju > run_charm
               dependencies:
                 - charm > loadbalancer
 
@@ -276,6 +276,7 @@ topology_template:
       type: aria.Plugin
       properties:
         version: 1.0
+        required: false
 
     maintenance_on:
       type: MaintenanceWorkflow

Reply via email to