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