Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 77570200CD9 for ; Thu, 3 Aug 2017 14:55:27 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 75D5716B807; Thu, 3 Aug 2017 12:55:27 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id F175B16B806 for ; Thu, 3 Aug 2017 14:55:24 +0200 (CEST) Received: (qmail 85010 invoked by uid 500); 3 Aug 2017 12:55:24 -0000 Mailing-List: contact commits-help@ariatosca.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ariatosca.incubator.apache.org Delivered-To: mailing list commits@ariatosca.incubator.apache.org Received: (qmail 85001 invoked by uid 99); 3 Aug 2017 12:55:24 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 03 Aug 2017 12:55:24 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id B289C1805A3 for ; Thu, 3 Aug 2017 12:55:23 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -3.721 X-Spam-Level: X-Spam-Status: No, score=-3.721 tagged_above=-999 required=6.31 tests=[HK_RANDOM_FROM=0.001, KAM_ASCII_DIVIDERS=0.8, KAM_NUMSUBJECT=0.5, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_PASS=-0.001] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id fRpXfTFBavHY for ; Thu, 3 Aug 2017 12:55:10 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 30C6B5FB40 for ; Thu, 3 Aug 2017 12:55:08 +0000 (UTC) Received: (qmail 84948 invoked by uid 99); 3 Aug 2017 12:55:07 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 03 Aug 2017 12:55:07 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 7BBEFF3251; Thu, 3 Aug 2017 12:55:06 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: mxmrlv@apache.org To: commits@ariatosca.incubator.apache.org Date: Thu, 03 Aug 2017 12:55:07 -0000 Message-Id: <36881646e8b542e28e34f84c6a9acb05@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [2/2] incubator-ariatosca git commit: review 1 - fixups 1 archived-at: Thu, 03 Aug 2017 12:55:27 -0000 review 1 - fixups 1 Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/a33ba12e Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/a33ba12e Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/a33ba12e Branch: refs/heads/ARIA-174-Refactor-instantiation-phase Commit: a33ba12e158ac88ed0498a8b23854fb6ad11e7c7 Parents: b729f63 Author: max-orlov Authored: Thu Aug 3 15:55:01 2017 +0300 Committer: max-orlov Committed: Thu Aug 3 15:55:01 2017 +0300 ---------------------------------------------------------------------- aria/cli/commands/service_templates.py | 2 +- aria/core.py | 6 +- aria/modeling/mixins.py | 8 - aria/modeling/service_template.py | 37 ++ aria/modeling/utils.py | 4 +- aria/orchestrator/topology/common.py | 32 +- aria/orchestrator/topology/instance_handler.py | 240 +++++++------ aria/orchestrator/topology/template_handler.py | 358 +++++++++---------- aria/orchestrator/topology/topology.py | 100 +++--- aria/orchestrator/topology/utils.py | 19 - aria/parser/consumption/modeling.py | 20 +- aria/parser/presentation/fields.py | 6 +- aria/parser/presentation/presentation.py | 10 +- aria/parser/validation/context.py | 2 +- aria/parser/validation/issue.py | 4 +- aria/utils/console.py | 34 +- .../aria_extension_tosca/simple_v1_0/misc.py | 2 +- .../simple_v1_0/modeling/__init__.py | 5 +- tests/instantiation/test_configuration.py | 13 +- tests/parser/test_reqs_caps.py | 4 +- 20 files changed, 462 insertions(+), 444 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/cli/commands/service_templates.py ---------------------------------------------------------------------- diff --git a/aria/cli/commands/service_templates.py b/aria/cli/commands/service_templates.py index 89662a9..5a7039c 100644 --- a/aria/cli/commands/service_templates.py +++ b/aria/cli/commands/service_templates.py @@ -57,7 +57,7 @@ def service_templates(): def show(service_template_name, model_storage, mode_full, mode_types, format_json, format_yaml, logger): """ - Show information for a stored service templates + Show information for a stored service template SERVICE_TEMPLATE_NAME is the unique name of the stored service template. """ http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/core.py ---------------------------------------------------------------------- diff --git a/aria/core.py b/aria/core.py index a81ae13..ad099be 100644 --- a/aria/core.py +++ b/aria/core.py @@ -83,7 +83,7 @@ class Core(object): topology_.coerce(service) topology_.validate_capabilities(service) - topology_.find_hosts(service) + topology_.assign_hosts(service) topology_.configure_operations(service) topology_.coerce(service) if topology_.dump_issues(): @@ -117,8 +117,8 @@ class Core(object): def _parse_service_template(service_template_path): context = consumption.ConsumptionContext() context.presentation.location = UriLocation(service_template_path) - # TODO: this is the last place which uses the consumer chains (since read is a proper Parser - # todo..based consumer, it has no place in the topology package). + # Most of the parser uses the topology package in order to manipulate teh models. + # However, here we use the ConsumerChain, but this should change in the future. consumption.ConsumerChain( context, ( http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/modeling/mixins.py ---------------------------------------------------------------------- diff --git a/aria/modeling/mixins.py b/aria/modeling/mixins.py index 1a3cb32..d58c25a 100644 --- a/aria/modeling/mixins.py +++ b/aria/modeling/mixins.py @@ -296,14 +296,6 @@ class ParameterMixin(TemplateModelMixin, caching.HasCachedMethods): ('value', self.value), ('description', self.description))) - def coerce_values(self, report_issues): - value = self._value - if value is not None: - evaluation = functions.evaluate(value, self, report_issues) - if (evaluation is not None) and evaluation.final: - # A final evaluation can safely replace the existing value - self._value = evaluation.value - @property def unwrapped(self): return self.name, self.value http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/modeling/service_template.py ---------------------------------------------------------------------- diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py index f2e1e78..aaf88db 100644 --- a/aria/modeling/service_template.py +++ b/aria/modeling/service_template.py @@ -530,6 +530,43 @@ class NodeTemplateBase(TemplateModelMixin): return '{name}_{index}'.format(name=self.name, index=self._next_index) + @property + def scaling(self): + scaling = {} + + def extract_property(properties, name): + if name in scaling: + return + prop = properties.get(name) + if (prop is not None) and (prop.type_name == 'integer') and (prop.value is not None): + scaling[name] = prop.value + + def extract_properties(properties): + extract_property(properties, 'min_instances') + extract_property(properties, 'max_instances') + extract_property(properties, 'default_instances') + + def default_property(name, value): + if name not in scaling: + scaling[name] = value + + # From our scaling capabilities + for capability_template in self.capability_templates.itervalues(): + if capability_template.type.role == 'scaling': + extract_properties(capability_template.properties) + + # From service scaling policies + for policy_template in self.service_template.policy_templates.itervalues(): + if policy_template.type.role == 'scaling': + if policy_template.is_for_node_template(self.name): + extract_properties(policy_template.properties) + + # Defaults + default_property('min_instances', 0) + default_property('max_instances', 1) + default_property('default_instances', 1) + + return scaling class GroupTemplateBase(TemplateModelMixin): """ http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/modeling/utils.py ---------------------------------------------------------------------- diff --git a/aria/modeling/utils.py b/aria/modeling/utils.py index 5218b81..9b64598 100644 --- a/aria/modeling/utils.py +++ b/aria/modeling/utils.py @@ -107,7 +107,7 @@ def merge_parameter_values(provided_values, declared_parameters, model_cls=None) provided_values = provided_values or {} provided_values_of_wrong_type = OrderedDict() model_parameters = OrderedDict() - model_cls = model_cls or get_class_from_relationship(declared_parameters) + model_cls = model_cls or _get_class_from_sql_relationship(declared_parameters) for declared_parameter_name, declared_parameter in declared_parameters.iteritems(): if declared_parameter_name in provided_values: @@ -175,7 +175,7 @@ def fix_doc(cls): return cls -def get_class_from_relationship(property): +def _get_class_from_sql_relationship(property): class_ = property._sa_adapter.owner_state.class_ prop_name = property._sa_adapter.attr.key return getattr(class_, prop_name).property.mapper.class_ http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/orchestrator/topology/common.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/topology/common.py b/aria/orchestrator/topology/common.py index 45e9ab0..7b02fd2 100644 --- a/aria/orchestrator/topology/common.py +++ b/aria/orchestrator/topology/common.py @@ -14,39 +14,39 @@ # limitations under the License. -class _Handler(object): - def __init__(self, topology, template): +class HandlerBase(object): + def __init__(self, topology, model): self._topology = topology - self._model = template + self._model = model - def _coerce(self, *templates, **kwargs): - for template in templates: - self._topology.coerce(template) + def coerce(self, **kwargs): + raise NotImplementedError - def coerce(self): - pass + def _coerce(self, *models, **kwargs): + for template in models: + self._topology.coerce(template, **kwargs) def validate(self, **kwargs): - pass + raise NotImplementedError - def _validate(self, *templates, **kwargs): - for template in templates: - self._topology.validate(template) + def _validate(self, *models, **kwargs): + for template in models: + self._topology.validate(template, **kwargs) def dump(self, out_stream): - pass + raise NotImplementedError -class _TemplateHandlerMixin(_Handler): +class TemplateHandlerBase(HandlerBase): def instantiate(self, instance_cls): raise NotImplementedError -class _InstanceHandlerMixin(_Handler): +class InstanceHandlerBase(HandlerBase): pass -class _OperatorHolderHandlerMixin(_Handler): +class ActorHandlerBase(HandlerBase): def configure_operations(self): raise NotImplementedError http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/orchestrator/topology/instance_handler.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/topology/instance_handler.py b/aria/orchestrator/topology/instance_handler.py index ea58d88..833c3a3 100644 --- a/aria/orchestrator/topology/instance_handler.py +++ b/aria/orchestrator/topology/instance_handler.py @@ -14,111 +14,114 @@ # limitations under the License. from ... parser.modeling import context -from ... modeling import models +from ... modeling import models, functions from ... utils import formatting from .. import execution_plugin from .. import decorators from . import common -class Artifact(common._InstanceHandlerMixin): +class Artifact(common.InstanceHandlerBase): def coerce(self, **kwargs): self._topology.coerce(self._model.properties, **kwargs) def validate(self, **kwargs): - self._topology.validate(self._model.properties) + self._topology.validate(self._model.properties, **kwargs) def dump(self, out_stream): with out_stream.indent(): - out_stream.write(out_stream.node(self._model.name)) - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.node_style(self._model.name)) + out_stream.write(out_stream.meta_style(self._model.description)) with out_stream.indent(): - out_stream.write('Artifact type: {0}'.format(out_stream.type( - self._model.type.name))) + out_stream.write('Artifact type: {0}'.format(out_stream.type_style( + self._model.type_style.name))) out_stream.write('Source path: {0}'.format( - out_stream.literal(self._model.source_path))) + out_stream.literal_style(self._model.source_path))) if self._model.target_path is not None: out_stream.write('Target path: {0}'.format( - out_stream.literal(self._model.target_path))) + out_stream.literal_style(self._model.target_path))) if self._model.repository_url is not None: out_stream.write('Repository URL: {0}'.format( - out_stream.literal(self._model.repository_url))) + out_stream.literal_style(self._model.repository_url))) if self._model.repository_credential: out_stream.write('Repository credential: {0}'.format( - out_stream.literal(self._model.repository_credential))) - self._topology.dump(self._model.properties, out_stream, 'Properties') + out_stream.literal_style(self._model.repository_credential))) + self._topology.dump(self._model.properties, out_stream, title='Properties') -class Capability(common._InstanceHandlerMixin): +class Capability(common.InstanceHandlerBase): def coerce(self, **kwargs): self._topology.coerce(self._model.properties, **kwargs) def validate(self, **kwargs): - self._topology.validate(self._model.properties) + self._topology.validate(self._model.properties, **kwargs) def dump(self, out_stream): - out_stream.write(out_stream.node(self._model.name)) + out_stream.write(out_stream.node_style(self._model.name)) with out_stream.indent(): - out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name))) + out_stream.write('Type: {0}'.format(out_stream.type_style(self._model.type_style.name))) out_stream.write('Occurrences: {0:d} ({1:d}{2})'.format( self._model.occurrences, self._model.min_occurrences or 0, ' to {0:d}'.format(self._model.max_occurrences) if self._model.max_occurrences is not None else ' or more')) - self._topology.dump(self._model.properties, out_stream, 'Properties') + self._topology.dump(self._model.properties, out_stream, title='Properties') -class Group(common._OperatorHolderHandlerMixin): +class Group(common.ActorHandlerBase): def coerce(self, **kwargs): self._coerce(self._model.properties, self._model.interfaces, **kwargs) def validate(self, **kwargs): self._validate(self._model.properties, - self._model.interfaces) + self._model.interfaces, + **kwargs) def dump(self, out_stream): - out_stream.write('Group: {0}'.format(out_stream.node(self._model.name))) + out_stream.write('Group: {0}'.format(out_stream.node_style(self._model.name))) with out_stream.indent(): - out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name))) - self._topology.dump(self._model.properties, out_stream, 'Properties') - self._topology.dump(self._model.interfaces, out_stream, 'Interfaces') + out_stream.write('Type: {0}'.format(out_stream.type_style(self._model.type_style.name))) + self._topology.dump(self._model.properties, out_stream, title='Properties') + self._topology.dump(self._model.interfaces, out_stream, title='Interfaces') if self._model.nodes: out_stream.write('Member nodes:') with out_stream.indent(): for node in self._model.nodes: - out_stream.write(out_stream.node(node.name)) + out_stream.write(out_stream.node_style(node.name)) def configure_operations(self): for interface in self._model.interfaces.values(): self._topology.configure_operations(interface) -class Interface(common._OperatorHolderHandlerMixin): +class Interface(common.ActorHandlerBase): def coerce(self, **kwargs): self._coerce(self._model.inputs, self._model.operations, **kwargs) def validate(self, **kwargs): self._validate(self._model.inputs, - self._model.operations) + self._model.operations, + **kwargs) def dump(self, out_stream): - out_stream.write(out_stream.node(self._model.name)) + out_stream.write(out_stream.node_style(self._model.name)) if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.meta_style(self._model.description)) with out_stream.indent(): - out_stream.write('Interface type: {0}'.format(out_stream.type(self._model.type.name))) - self._topology.dump(self._model.inputs, out_stream, 'Inputs') - self._topology.dump(self._model.operations, out_stream, 'Operations') + out_stream.write('Interface type: {0}'.format( + out_stream.type_style(self._model.type.name))) + self._topology.dump(self._model.inputs, out_stream, title='Inputs') + self._topology.dump(self._model.operations, out_stream, title='Operations') def configure_operations(self): for operation in self._model.operations.values(): self._topology.configure_operations(operation) -class Node(common._OperatorHolderHandlerMixin): +class Node(common.ActorHandlerBase): def coerce(self, **kwargs): self._coerce(self._model.properties, self._model.attributes, @@ -143,17 +146,17 @@ class Node(common._OperatorHolderHandlerMixin): self._model.outbound_relationships) def dump(self, out_stream): - out_stream.write('Node: {0}'.format(out_stream.node(self._model.name))) + out_stream.write('Node: {0}'.format(out_stream.node_style(self._model.name))) with out_stream.indent(): - out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name))) + out_stream.write('Type: {0}'.format(out_stream.type_style(self._model.type_style.name))) out_stream.write('Template: {0}'.format( - out_stream.node(self._model.node_template.name))) - self._topology.dump(self._model.properties, out_stream, 'Properties') - self._topology.dump(self._model.attributes, out_stream, 'Attributes') - self._topology.dump(self._model.interfaces, out_stream, 'Interfaces') - self._topology.dump(self._model.artifacts, out_stream, 'Artifacts') - self._topology.dump(self._model.capabilities, out_stream, 'Capabilities') - self._topology.dump(self._model.outbound_relationships, out_stream, 'Relationships') + out_stream.node_style(self._model.node_template.name))) + self._topology.dump(self._model.properties, out_stream, title='Properties') + self._topology.dump(self._model.attributes, out_stream, title='Attributes') + self._topology.dump(self._model.interfaces, out_stream, title='Interfaces') + self._topology.dump(self._model.artifacts, out_stream, title='Artifacts') + self._topology.dump(self._model.capabilities, out_stream, title='Capabilities') + self._topology.dump(self._model.outbound_relationships, out_stream, title='Relationships') def configure_operations(self): for interface in self._model.interfaces.values(): @@ -183,9 +186,9 @@ class Node(common._OperatorHolderHandlerMixin): # information in the creation of the relationship, Some requirements may have been # satisfied by a previous run on that node template. # The entire mechanism of satisfying requirements needs to be refactored. - if any(r.requirement_template == requirement_template - for r in self._model.outbound_relationships): - return satisfied + if any(rel.requirement_template == requirement_template + for rel in self._model.outbound_relationships): + continue # Find target template target_node_template, target_node_capability = self._find_target(requirement_template) @@ -248,7 +251,8 @@ class Node(common._OperatorHolderHandlerMixin): return False def _find_target(self, requirement_template): - # We might already have a specific node template, so we'll just verify it + # We might already have a specific node template from the requirement template, so + # we'll just verify it if requirement_template.target_node_template is not None: if not self._model.node_template.is_target_node_template_valid( requirement_template.target_node_template): @@ -289,6 +293,7 @@ class Node(common._OperatorHolderHandlerMixin): return target_node_template, target_node_capability + # Find the first node which has a capability of the required type elif requirement_template.target_capability_type is not None: for target_node_template in \ self._model.node_template.service_template.node_templates.itervalues(): @@ -334,7 +339,7 @@ class Node(common._OperatorHolderHandlerMixin): return True -class Operation(common._OperatorHolderHandlerMixin): +class Operation(common.ActorHandlerBase): def coerce(self, **kwargs): self._coerce(self._model.inputs, self._model.configurations, @@ -344,36 +349,37 @@ class Operation(common._OperatorHolderHandlerMixin): def validate(self, **kwargs): self._validate(self._model.inputs, self._model.configurations, - self._model.arguments) + self._model.arguments, + **kwargs) def dump(self, out_stream): - out_stream.write(out_stream.node(self._model.name)) + out_stream.write(out_stream.node_style(self._model.name)) if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.meta_style(self._model.description)) with out_stream.indent(): if self._model.implementation is not None: out_stream.write('Implementation: {0}'.format( - out_stream.literal(self._model.implementation))) + out_stream.literal_style(self._model.implementation))) if self._model.dependencies: out_stream.write( 'Dependencies: {0}'.format( - ', '.join((str(out_stream.literal(v)) for v in self._model.dependencies)))) - self._topology.dump(self._model.inputs, out_stream, 'Inputs') + ', '.join((str(out_stream.literal_style(v)) for v in self._model.dependencies)))) + self._topology.dump(self._model.inputs, out_stream, title='Inputs') if self._model.executor is not None: - out_stream.write('Executor: {0}'.format(out_stream.literal(self._model.executor))) + out_stream.write('Executor: {0}'.format(out_stream.literal_style(self._model.executor))) if self._model.max_attempts is not None: - out_stream.write('Max attempts: {0}'.format(out_stream.literal( + out_stream.write('Max attempts: {0}'.format(out_stream.literal_style( self._model.max_attempts))) if self._model.retry_interval is not None: out_stream.write('Retry interval: {0}'.format( - out_stream.literal(self._model.retry_interval))) + out_stream.literal_style(self._model.retry_interval))) if self._model.plugin is not None: out_stream.write('Plugin: {0}'.format( - out_stream.literal(self._model.plugin.name))) - self._topology.dump(self._model.configurations, out_stream, 'Configuration') + out_stream.literal_style(self._model.plugin.name))) + self._topology.dump(self._model.configurations, out_stream, title='Configuration') if self._model.function is not None: - out_stream.write('Function: {0}'.format(out_stream.literal(self._model.function))) - self._topology.dump(self._model.arguments, out_stream, 'Arguments') + out_stream.write('Function: {0}'.format(out_stream.literal_style(self._model.function))) + self._topology.dump(self._model.arguments, out_stream, title='Arguments') def configure_operations(self): if self._model.implementation is None and self._model.function is None: @@ -414,31 +420,31 @@ class Operation(common._OperatorHolderHandlerMixin): level=self._topology.Issue.EXTERNAL) -class Policy(common._InstanceHandlerMixin): +class Policy(common.InstanceHandlerBase): def coerce(self, **kwargs): self._topology.coerce(self._model.properties, **kwargs) def validate(self, **kwargs): - self._topology.validate(self._model.properties) + self._topology.validate(self._model.properties, **kwargs) def dump(self, out_stream): - out_stream.write('Policy: {0}'.format(out_stream.node(self._model.name))) + out_stream.write('Policy: {0}'.format(out_stream.node_style(self._model.name))) with out_stream.indent(): - out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name))) - self._topology.dump(self._model.properties, out_stream, 'Properties') + out_stream.write('Type: {0}'.format(out_stream.type_style(self._model.type_style.name))) + self._topology.dump(self._model.properties, out_stream, title='Properties') if self._model.nodes: out_stream.write('Target nodes:') with out_stream.indent(): for node in self._model.nodes: - out_stream.write(out_stream.node(node.name)) + out_stream.write(out_stream.node_style(node.name)) if self._model.groups: out_stream.write('Target groups:') with out_stream.indent(): for group in self._model.groups: - out_stream.write(out_stream.node(group.name)) + out_stream.write(out_stream.node_style(group.name)) -class Relationship(common._OperatorHolderHandlerMixin): +class Relationship(common.ActorHandlerBase): def coerce(self, **kwargs): self._coerce(self._model.properties, self._model.interfaces, @@ -446,34 +452,35 @@ class Relationship(common._OperatorHolderHandlerMixin): def validate(self, **kwargs): self._validate(self._model.properties, - self._model.interfaces) + self._model.interfaces, + **kwargs) def dump(self, out_stream): if self._model.name: - out_stream.write('{0} ->'.format(out_stream.node(self._model.name))) + out_stream.write('{0} ->'.format(out_stream.node_style(self._model.name))) else: out_stream.write('->') with out_stream.indent(): - out_stream.write('Node: {0}'.format(out_stream.node(self._model.target_node.name))) + out_stream.write('Node: {0}'.format(out_stream.node_style(self._model.target_node.name))) if self._model.target_capability: - out_stream.write('Capability: {0}'.format(out_stream.node( + out_stream.write('Capability: {0}'.format(out_stream.node_style( self._model.target_capability.name))) - if self._model.type is not None: + if self._model.type_style is not None: out_stream.write('Relationship type: {0}'.format( - out_stream.type(self._model.type.name))) + out_stream.type_style(self._model.type_style.name))) if (self._model.relationship_template is not None and self._model.relationship_template.name): out_stream.write('Relationship template: {0}'.format( - out_stream.node(self._model.relationship_template.name))) - self._topology.dump(self._model.properties, out_stream, 'Properties') - self._topology.dump(self._model.interfaces, out_stream, 'Interfaces') + out_stream.node_style(self._model.relationship_template.name))) + self._topology.dump(self._model.properties, out_stream, title='Properties') + self._topology.dump(self._model.interfaces, out_stream, title='Interfaces') def configure_operations(self): for interface in self._model.interfaces.values(): self._topology.configure_operations(interface) -class Service(common._OperatorHolderHandlerMixin): +class Service(common.ActorHandlerBase): def coerce(self, **kwargs): self._coerce(self._model.meta_data, self._model.nodes, @@ -493,19 +500,20 @@ class Service(common._OperatorHolderHandlerMixin): self._model.substitution, self._model.inputs, self._model.outputs, - self._model.workflows) + self._model.workflows, + **kwargs) def dump(self, out_stream): if self._model.description is not None: - out_stream.write(out_stream.meta(self._model.description)) - self._topology.dump(self._model.meta_data, out_stream, 'Metadata') + out_stream.write(out_stream.meta_style(self._model.description)) + self._topology.dump(self._model.meta_data, out_stream, title='Metadata') self._topology.dump(self._model.nodes, out_stream) self._topology.dump(self._model.groups, out_stream) self._topology.dump(self._model.policies, out_stream) self._topology.dump(self._model.substitution, out_stream) - self._topology.dump(self._model.inputs, out_stream, 'Inputs') - self._topology.dump(self._model.outputs, out_stream, 'Outputs') - self._topology.dump(self._model.workflows, out_stream, 'Workflows') + self._topology.dump(self._model.inputs, out_stream, title='Inputs') + self._topology.dump(self._model.outputs, out_stream, title='Outputs') + self._topology.dump(self._model.workflows, out_stream, title='Workflows') def configure_operations(self): for node in self._model.nodes.itervalues(): @@ -527,74 +535,74 @@ class Service(common._OperatorHolderHandlerMixin): for node in self._model.nodes.values()) -class Substitution(common._InstanceHandlerMixin): +class Substitution(common.InstanceHandlerBase): def coerce(self, **kwargs): self._topology.coerce(self._model.mappings, **kwargs) def validate(self, **kwargs): - self._topology.validate(self._model.mappings) + self._topology.validate(self._model.mappings, **kwargs) def dump(self, out_stream): out_stream.write('Substitution:') with out_stream.indent(): - out_stream.write('Node type: {0}'.format(out_stream.type(self._model.node_type.name))) - self._topology.dump(self._model.mappings, out_stream, 'Mappings') + out_stream.write('Node type: {0}'.format(out_stream.type_style(self._model.node_type.name))) + self._topology.dump(self._model.mappings, out_stream, title='Mappings') -class SubstitutionMapping(common._InstanceHandlerMixin): +class SubstitutionMapping(common.InstanceHandlerBase): - def validate(self, **kwargs): + def validate(self, **_): if (self._model.capability is None) and (self._model.requirement_template is None): self._topology.report( 'mapping "{0}" refers to neither capability nor a requirement' ' in node: {1}'.format( - self._model.name, formatting.safe_repr(self._model.node.name)), + self._model.name, formatting.safe_repr(self._model.node_style.name)), level=self._topology.Issue.BETWEEN_TYPES) def dump(self, out_stream): if self._model.capability is not None: out_stream.write('{0} -> {1}.{2}'.format( - out_stream.node(self._model.name), - out_stream.node(self._model.capability.node.name), - out_stream.node(self._model.capability.name))) + out_stream.node_style(self._model.name), + out_stream.node_style(self._model.capability.node_style.name), + out_stream.node_style(self._model.capability.name))) else: out_stream.write('{0} -> {1}.{2}'.format( - out_stream.node(self._model.name), - out_stream.node(self._model.node.name), - out_stream.node(self._model.requirement_template.name))) + out_stream.node_style(self._model.name), + out_stream.node_style(self._model.node_style.name), + out_stream.node_style(self._model.requirement_template.name))) -class Metadata(common._InstanceHandlerMixin): +class Metadata(common.InstanceHandlerBase): def dump(self, out_stream): out_stream.write('{0}: {1}'.format( - out_stream.property(self._topology.name), - out_stream.literal(self._topology.value))) + out_stream.property_style(self._model.name), + out_stream.literal_style(self._model.value))) - def coerce(self): + def coerce(self, **_): pass - def instantiate(self, instance_cls, **kwargs): + def instantiate(self, instance_cls): return instance_cls(name=self._model.name, value=self._model.value) def validate(self): pass -class _Parameter(common._InstanceHandlerMixin): +class _Parameter(common.InstanceHandlerBase): def dump(self, out_stream): if self._model.type_name is not None: out_stream.write('{0}: {1} ({2})'.format( - out_stream.property(self._model.name), - out_stream.literal(formatting.as_raw(self._model.value)), - out_stream.type(self._model.type_name))) + out_stream.property_style(self._model.name), + out_stream.literal_style(formatting.as_raw(self._model.value)), + out_stream.type_style(self._model.type_name))) else: out_stream.write('{0}: {1}'.format( - out_stream.property(self._model.name), - out_stream.literal(formatting.as_raw(self._model.value)))) + out_stream.property_style(self._model.name), + out_stream.literal_style(formatting.as_raw(self._model.value)))) if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.meta_style(self._model.description)) def instantiate(self, instance_cls, **kwargs): return instance_cls( @@ -607,6 +615,13 @@ class _Parameter(common._InstanceHandlerMixin): def validate(self): pass + def coerce(self, report_issues): + value = self._model._value + if value is not None: + evaluation = functions.evaluate(value, self._model, report_issues) + if (evaluation is not None) and evaluation.final: + # A final evaluation can safely replace the existing value + self._model._value = evaluation.value class Attribute(_Parameter): pass @@ -632,13 +647,16 @@ class Configuration(_Parameter): pass -class Type(common._InstanceHandlerMixin): - def coerce(self): +class Type(common.InstanceHandlerBase): + def coerce(self, **_): pass def dump(self, out_stream): if self._model.name: - out_stream.write(out_stream.type(self._model.name)) + out_stream.write(out_stream.type_style(self._model.name)) with out_stream.indent(): for child in self._model.children: self._topology.dump(child, out_stream) + + def validate(self, **kwargs): + pass http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/orchestrator/topology/template_handler.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/topology/template_handler.py b/aria/orchestrator/topology/template_handler.py index d355e6d..6d52e5d 100644 --- a/aria/orchestrator/topology/template_handler.py +++ b/aria/orchestrator/topology/template_handler.py @@ -15,23 +15,26 @@ from datetime import datetime -from ...utils import formatting +from ...utils import ( + formatting, + versions +) from ...modeling import utils as modeling_utils from . import utils, common -class ServiceTemplate(common._TemplateHandlerMixin): +class ServiceTemplate(common.TemplateHandlerBase): def dump(self, out_stream): if self._model.description is not None: - out_stream.write(out_stream.meta(self._model.description)) - self._topology.dump(self._model.meta_data, out_stream, 'Metadata') + out_stream.write(out_stream.meta_style(self._model.description)) + self._topology.dump(self._model.meta_data, out_stream, title='Metadata') self._topology.dump(self._model.node_templates, out_stream) self._topology.dump(self._model.group_templates, out_stream) self._topology.dump(self._model.policy_templates, out_stream) self._topology.dump(self._model.substitution_template, out_stream) - self._topology.dump(self._model.inputs, out_stream, 'Inputs') - self._topology.dump(self._model.outputs, out_stream, 'Outputs') - self._topology.dump(self._model.workflow_templates, out_stream, 'Workflow templates') + self._topology.dump(self._model.inputs, out_stream, title='Inputs') + self._topology.dump(self._model.outputs, out_stream, title='Outputs') + self._topology.dump(self._model.workflow_templates, out_stream, title='Workflow templates') def coerce(self, **kwargs): self._coerce(self._model.meta_data, @@ -62,7 +65,7 @@ class ServiceTemplate(common._TemplateHandlerMixin): for plugin_specification in self._model.plugin_specifications.itervalues(): if plugin_specification.enabled and self._topology._model_storage: - if utils.resolve_plugin_specification(plugin_specification, + if self._resolve_plugin_specification(plugin_specification, self._topology.model_storage.plugin.list()): plugin = plugin_specification.plugin service.plugins[plugin.name] = plugin @@ -84,45 +87,36 @@ class ServiceTemplate(common._TemplateHandlerMixin): return service + @staticmethod + def _resolve_plugin_specification(plugin_specification, plugins): + matching_plugins = [] + if plugins: + for plugin in plugins: + if (plugin.name == plugin_specification.name and + (plugin_specification.version is None or + versions.VersionString(plugin.package_version) >= + plugin_specification.version) + ): + matching_plugins.append(plugin) + plugin_specification.plugin = None + if matching_plugins: + # Return highest version of plugin + plugin_specification.plugin = \ + max(matching_plugins, + key=lambda plugin: versions.VersionString(plugin.package_version).key) + return plugin_specification.plugin is not None + def _scaling(self, node_template): - scaling = {} - - def extract_property(properties, name): - if name in scaling: - return - prop = properties.get(name) - if (prop is not None) and (prop.type_name == 'integer') and (prop.value is not None): - scaling[name] = prop.value - - def extract_properties(properties): - extract_property(properties, 'min_instances') - extract_property(properties, 'max_instances') - extract_property(properties, 'default_instances') - - # From our scaling capabilities - for capability_template in node_template.capability_templates.itervalues(): - if capability_template.type.role == 'scaling': - extract_properties(capability_template.properties) - - # From service scaling policies - for policy_template in node_template.service_template.policy_templates.itervalues(): - if policy_template.type.role == 'scaling': - if policy_template.is_for_node_template(node_template.name): - extract_properties(policy_template.properties) - - # Defaults - scaling.setdefault('min_instances', 0) - scaling.setdefault('max_instances', 1) - scaling.setdefault('default_instances', 1) - - # Validate - # pylint: disable=too-many-boolean-expressions - if (scaling['min_instances'] < 0 or - scaling['max_instances'] < 0 or - scaling['default_instances'] < 0 or - scaling['max_instances'] < scaling['min_instances'] or - scaling['default_instances'] < scaling['min_instances'] or - scaling['default_instances'] > scaling['max_instances']): + scaling = node_template.scaling + + if any([scaling['min_instances'] < 0, + scaling['max_instances'] < scaling['min_instances'], + scaling['max_instances'] < 0, + + scaling['default_instances'] < 0, + scaling['default_instances'] < scaling['min_instances'], + scaling['default_instances'] > scaling['max_instances'] + ]): self._topology.report( 'invalid scaling parameters for node template "{0}": min={min_instances}, max=' '{max_instances}, default={default_instances}'.format(self._model.name, **scaling), @@ -130,42 +124,45 @@ class ServiceTemplate(common._TemplateHandlerMixin): return scaling - def validate(self): - self._topology.validate(self._model.meta_data) - self._topology.validate(self._model.node_templates) - self._topology.validate(self._model.group_templates) - self._topology.validate(self._model.policy_templates) - self._topology.validate(self._model.substitution_template) - self._topology.validate(self._model.inputs) - self._topology.validate(self._model.outputs) - self._topology.validate(self._model.workflow_templates) - self._topology.validate(self._model.node_types) - self._topology.validate(self._model.group_types) - self._topology.validate(self._model.policy_types) - self._topology.validate(self._model.relationship_types) - self._topology.validate(self._model.capability_types) - self._topology.validate(self._model.interface_types) - self._topology.validate(self._model.artifact_types) - - -class ArtifactTemplate(common._TemplateHandlerMixin): + def validate(self, **kwargs): + self._validate( + self._model.meta_data, + self._model.node_templates, + self._model.group_templates, + self._model.policy_templates, + self._model.substitution_template, + self._model.inputs, + self._model.outputs, + self._model.workflow_templates, + self._model.node_types, + self._model.group_types, + self._model.policy_types, + self._model.relationship_types, + self._model.capability_types, + self._model.interface_types, + self._model.artifact_types, + **kwargs + ) + + +class ArtifactTemplate(common.TemplateHandlerBase): def dump(self, out_stream): - out_stream.write(out_stream.node(self._model.name)) + out_stream.write(out_stream.node_style(self._model.name)) if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.meta_style(self._model.description)) with out_stream.indent(): - out_stream.write('Artifact type: {0}'.format(out_stream.type(self._model.type.name))) - out_stream.write('Source path: {0}'.format(out_stream.literal(self._model.source_path))) + out_stream.write('Artifact type: {0}'.format(out_stream.type_style(self._model.type_style.name))) + out_stream.write('Source path: {0}'.format(out_stream.literal_style(self._model.source_path))) if self._model.target_path is not None: - out_stream.write('Target path: {0}'.format(out_stream.literal( + out_stream.write('Target path: {0}'.format(out_stream.literal_style( self._model.target_path))) if self._model.repository_url is not None: out_stream.write('Repository URL: {0}'.format( - out_stream.literal(self._model.repository_url))) + out_stream.literal_style(self._model.repository_url))) if self._model.repository_credential: out_stream.write('Repository credential: {0}'.format( - out_stream.literal(self._model.repository_credential))) - self._topology.dump(self._model.properties, out_stream, 'Properties') + out_stream.literal_style(self._model.repository_credential))) + self._topology.dump(self._model.properties, out_stream, title='Properties') def coerce(self, **kwargs): self._topology.coerce(self._model.properties, **kwargs) @@ -181,17 +178,17 @@ class ArtifactTemplate(common._TemplateHandlerMixin): repository_credential=self._model.repository_credential, artifact_template=self._model) - def validate(self): - self._topology.validate(self._model.properties) + def validate(self, **kwargs): + self._topology.validate(self._model.properties, **kwargs) -class CapabilityTemplate(common._TemplateHandlerMixin): +class CapabilityTemplate(common.TemplateHandlerBase): def dump(self, out_stream): - out_stream.write(out_stream.node(self._model.name)) + out_stream.write(out_stream.node_style(self._model.name)) if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.meta_style(self._model.description)) with out_stream.indent(): - out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name))) + out_stream.write('Type: {0}'.format(out_stream.type_style(self._model.type_style.name))) out_stream.write( 'Occurrences: {0:d}{1}'.format( self._model.min_occurrences or 0, @@ -200,12 +197,12 @@ class CapabilityTemplate(common._TemplateHandlerMixin): else ' or more')) if self._model.valid_source_node_types: out_stream.write('Valid source node types: {0}'.format( - ', '.join((str(out_stream.type(v.name)) + ', '.join((str(out_stream.type_style(v.name)) for v in self._model.valid_source_node_types)))) - self._topology.dump(self._model.properties, out_stream, 'Properties') + self._topology.dump(self._model.properties, out_stream, title='Properties') - def coerce(self): - self._topology.coerce(self._model.properties) + def coerce(self, **kwargs): + self._topology.coerce(self._model.properties, **kwargs) def instantiate(self, instance_cls): return instance_cls(name=self._model.name, @@ -215,34 +212,34 @@ class CapabilityTemplate(common._TemplateHandlerMixin): occurrences=0, capability_template=self._model) - def validate(self): - self._topology.validate(self._model.properties) + def validate(self, **kwargs): + self._topology.validate(self._model.properties, **kwargs) -class RequirementTemplate(common._TemplateHandlerMixin): +class RequirementTemplate(common.TemplateHandlerBase): def dump(self, out_stream): if self._model.name: - out_stream.write(out_stream.node(self._model.name)) + out_stream.write(out_stream.node_style(self._model.name)) else: out_stream.write('Requirement:') with out_stream.indent(): if self._model.target_node_type is not None: out_stream.write('Target node type: {0}'.format( - out_stream.type(self._model.target_node_type.name))) + out_stream.type_style(self._model.target_node_type.name))) elif self._model.target_node_template is not None: out_stream.write('Target node template: {0}'.format( - out_stream.node(self._model.target_node_template.name))) + out_stream.node_style(self._model.target_node_template.name))) if self._model.target_capability_type is not None: out_stream.write('Target capability type: {0}'.format( - out_stream.type(self._model.target_capability_type.name))) + out_stream.type_style(self._model.target_capability_type.name))) elif self._model.target_capability_name is not None: out_stream.write('Target capability name: {0}'.format( - out_stream.node(self._model.target_capability_name))) + out_stream.node_style(self._model.target_capability_name))) if self._model.target_node_template_constraints: out_stream.write('Target node template constraints:') with out_stream.indent(): for constraint in self._model.target_node_template_constraints: - out_stream.write(out_stream.literal(constraint)) + out_stream.write(out_stream.literal_style(constraint)) if self._model.relationship_template: out_stream.write('Relationship:') with out_stream.indent(): @@ -252,29 +249,24 @@ class RequirementTemplate(common._TemplateHandlerMixin): self._topology.coerce(self._model.relationship_template, **kwargs) def instantiate(self, instance_cls): - return instance_cls(name=self._model.name, - type=self._model.type, - min_occurrences=self._model.min_occurrences, - max_occurrences=self._model.max_occurrences, - occurrences=0, - capability_template=self._model) + pass - def validate(self): - self._topology.validate(self._model.relationship_template) + def validate(self, **kwargs): + self._topology.validate(self._model.relationship_template, **kwargs) -class GroupTemplate(common._TemplateHandlerMixin): +class GroupTemplate(common.TemplateHandlerBase): def dump(self, out_stream): - out_stream.write('Group template: {0}'.format(out_stream.node(self._model.name))) + out_stream.write('Group template: {0}'.format(out_stream.node_style(self._model.name))) if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.meta_style(self._model.description)) with out_stream.indent(): - out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name))) - self._topology.dump(self._model.properties, out_stream, 'Properties') - self._topology.dump(self._model.interface_templates, out_stream, 'Interface Templates') + out_stream.write('Type: {0}'.format(out_stream.type_style(self._model.type_style.name))) + self._topology.dump(self._model.properties, out_stream, title='Properties') + self._topology.dump(self._model.interface_templates, out_stream, title='Interface Templates') if self._model.node_templates: out_stream.write('Member node templates: {0}'.format(', '.join( - (str(out_stream.node(v.name)) for v in self._model.node_templates)))) + (str(out_stream.node_style(v.name)) for v in self._model.node_templates)))) def coerce(self, **kwargs): self._coerce(self._model.properties, @@ -294,20 +286,21 @@ class GroupTemplate(common._TemplateHandlerMixin): group.nodes += node_template.nodes return group - def validate(self): + def validate(self, **kwargs): self._validate(self._model.properties, - self._model.interface_templates) + self._model.interface_templates, + **kwargs) -class InterfaceTemplate(common._TemplateHandlerMixin): +class InterfaceTemplate(common.TemplateHandlerBase): def dump(self, out_stream): - out_stream.write(out_stream.node(self._model.name)) + out_stream.write(out_stream.node_style(self._model.name)) if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.meta_style(self._model.description)) with out_stream.indent(): - out_stream.write('Interface type: {0}'.format(out_stream.type(self._model.type.name))) - self._topology.dump(self._model.inputs, out_stream, 'Inputs') - self._topology.dump(self._model.operation_templates, out_stream, 'Operation templates') + out_stream.write('Interface type: {0}'.format(out_stream.type_style(self._model.type_style.name))) + self._topology.dump(self._model.inputs, out_stream, title='Inputs') + self._topology.dump(self._model.operation_templates, out_stream, title='Operation templates') def coerce(self, **kwargs): self._coerce(self._model.inputs, @@ -324,28 +317,29 @@ class InterfaceTemplate(common._TemplateHandlerMixin): interface.operations = self._topology.instantiate(self._model.operation_templates) return interface - def validate(self): + def validate(self, **kwargs): self._validate(self._model.inputs, - self._model.operation_templates) + self._model.operation_templates, + **kwargs) -class NodeTemplate(common._TemplateHandlerMixin): +class NodeTemplate(common.TemplateHandlerBase): def dump(self, out_stream): - out_stream.write('Node template: {0}'.format(out_stream.node(self._model.name))) + out_stream.write('Node template: {0}'.format(out_stream.node_style(self._model.name))) with out_stream.indent(): if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) - out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name))) - self._topology.dump(self._model.properties, out_stream, 'Properties') - self._topology.dump(self._model.attributes, out_stream, 'Attributes') + out_stream.write(out_stream.meta_style(self._model.description)) + out_stream.write('Type: {0}'.format(out_stream.type_style(self._model.type_style.name))) + self._topology.dump(self._model.properties, out_stream, title='Properties') + self._topology.dump(self._model.attributes, out_stream, title='Attributes') self._topology.dump( - self._model.interface_templates, out_stream, 'Interface Templates') + self._model.interface_templates, out_stream, title='Interface Templates') self._topology.dump( - self._model.artifact_templates, out_stream, 'Artifact Templates') + self._model.artifact_templates, out_stream, title='Artifact Templates') self._topology.dump( - self._model.capability_templates, out_stream, 'Capability Templates') + self._model.capability_templates, out_stream, title='Capability Templates') self._topology.dump( - self._model.requirement_templates, out_stream, 'Requirement Templates') + self._model.requirement_templates, out_stream, title='Requirement Templates') def coerce(self, **kwargs): self._coerce(self._model.properties, @@ -378,29 +372,30 @@ class NodeTemplate(common._TemplateHandlerMixin): return node - def validate(self): + def validate(self, **kwargs): self._validate(self._model.properties, self._model.attributes, self._model.interface_templates, self._model.artifact_templates, self._model.capability_templates, - self._model.requirement_templates) + self._model.requirement_templates, + **kwargs) -class PolicyTemplate(common._TemplateHandlerMixin): +class PolicyTemplate(common.TemplateHandlerBase): def dump(self, out_stream): - out_stream.write('Policy template: {0}'.format(out_stream.node(self._model.name))) + out_stream.write('Policy template: {0}'.format(out_stream.node_style(self._model.name))) if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.meta_style(self._model.description)) with out_stream.indent(): - out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name))) - self._topology.dump(self._model.properties, out_stream, 'Properties') + out_stream.write('Type: {0}'.format(out_stream.type_style(self._model.type_style.name))) + self._topology.dump(self._model.properties, out_stream, title='Properties') if self._model.node_templates: out_stream.write('Target node templates: {0}'.format(', '.join( - (str(out_stream.node(v.name)) for v in self._model.node_templates)))) + (str(out_stream.node_style(v.name)) for v in self._model.node_templates)))) if self._model.group_templates: out_stream.write('Target group templates: {0}'.format(', '.join( - (str(out_stream.node(v.name)) for v in self._model.group_templates)))) + (str(out_stream.node_style(v.name)) for v in self._model.group_templates)))) def coerce(self, **kwargs): self._topology.coerce(self._model.properties, **kwargs) @@ -421,17 +416,17 @@ class PolicyTemplate(common._TemplateHandlerMixin): policy.groups += group_template.groups return policy - def validate(self): - self._topology.validate(self._model.properties) + def validate(self, **kwargs): + self._topology.validate(self._model.properties, **kwargs) -class SubstitutionTemplate(common._TemplateHandlerMixin): +class SubstitutionTemplate(common.TemplateHandlerBase): def dump(self, out_stream): out_stream.write('Substitution template:') with out_stream.indent(): - out_stream.write('Node type: {0}'.format(out_stream.type(self._model.node_type.name))) - self._topology.dump(self._model.mappings, out_stream, 'Mappings') + out_stream.write('Node type: {0}'.format(out_stream.type_style(self._model.node_type.name))) + self._topology.dump(self._model.mappings, out_stream, title='Mappings') def coerce(self, **kwargs): self._topology.coerce(self._model.mappings, **kwargs) @@ -440,25 +435,25 @@ class SubstitutionTemplate(common._TemplateHandlerMixin): return instance_cls(node_type=self._model.node_type, substitution_template=self._model) - def validate(self): - self._topology.validate(self._model.mappings) + def validate(self, **kwargs): + self._topology.validate(self._model.mappings, **kwargs) -class SubstitutionTemplateMapping(common._TemplateHandlerMixin): +class SubstitutionTemplateMapping(common.TemplateHandlerBase): def dump(self, out_stream): if self._topology.capability_template is not None: - node_template = self._topology.capability_template.node_template + node_template = self._model.capability_template.node_template else: - node_template = self._topology.requirement_template.node_template + node_template = self._model.requirement_template.node_template out_stream.write('{0} -> {1}.{2}'.format( - out_stream.node(self._topology.name), - out_stream.node(node_template.name), - out_stream.node(self._topology.capability_template.name - if self._topology.capability_template - else self._topology.requirement_template.name))) + out_stream.node_style(self._model.name), + out_stream.node_style(node_template.name), + out_stream.node_style(self._model.capability_template.name + if self._model.capability_template + else self._model.requirement_template.name))) - def coerce(self): + def coerce(self, **_): pass def instantiate(self, instance_cls): @@ -479,16 +474,16 @@ class SubstitutionTemplateMapping(common._TemplateHandlerMixin): return None # The TOSCA spec does not provide a way to choose the node, # so we will just pick the first one - substitution_mapping.node = nodes[0] + substitution_mapping.node_style = nodes[0] if self._model.capability_template: - for a_capability in substitution_mapping.node.capabilities.itervalues(): + for a_capability in substitution_mapping.node_style.capabilities.itervalues(): if a_capability.capability_template.name == \ self._model.capability_template.name: substitution_mapping.capability = a_capability return substitution_mapping - def validate(self): + def validate(self, **_): if self._model.capability_template is None and self._model.requirement_template is None: self._topology.report( 'mapping "{0}" refers to neither capability nor a requirement ' @@ -497,19 +492,19 @@ class SubstitutionTemplateMapping(common._TemplateHandlerMixin): level=self._topology.Issue.BETWEEN_TYPES) -class RelationshipTemplate(common._TemplateHandlerMixin): +class RelationshipTemplate(common.TemplateHandlerBase): def dump(self, out_stream): - if self._model.type is not None: - out_stream.write('Relationship type: {0}'.format(out_stream.type( - self._model.type.name))) + if self._model.type_style is not None: + out_stream.write('Relationship type: {0}'.format(out_stream.type_style( + self._model.type_style.name))) else: out_stream.write('Relationship template: {0}'.format( - out_stream.node(self._model.name))) + out_stream.node_style(self._model.name))) if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.meta_style(self._model.description)) with out_stream.indent(): - self._topology.dump(self._model.properties, out_stream, 'Properties') - self._topology.dump(self._model.interface_templates, out_stream, 'Interface Templates') + self._topology.dump(self._model.properties, out_stream, title='Properties') + self._topology.dump(self._model.interface_templates, out_stream, title='Interface Templates') def coerce(self, **kwargs): self._coerce(self._model.properties, self._model.interface_templates, **kwargs) @@ -524,38 +519,38 @@ class RelationshipTemplate(common._TemplateHandlerMixin): relationship.interfaces = self._topology.instantiate(self._model.interface_templates) return relationship - def validate(self): - self._validate(self._model.properties, self._model.interface_templates) + def validate(self, **kwargs): + self._validate(self._model.properties, self._model.interface_templates, **kwargs) -class OperationTemplate(common._TemplateHandlerMixin): +class OperationTemplate(common.TemplateHandlerBase): def dump(self, out_stream): - out_stream.write(out_stream.node(self._model.name)) + out_stream.write(out_stream.node_style(self._model.name)) if self._model.description: - out_stream.write(out_stream.meta(self._model.description)) + out_stream.write(out_stream.meta_style(self._model.description)) with out_stream.indent(): if self._model.implementation is not None: out_stream.write('Implementation: {0}'.format( - out_stream.literal(self._model.implementation))) + out_stream.literal_style(self._model.implementation))) if self._model.dependencies: out_stream.write('Dependencies: {0}'.format( - ', '.join((str(out_stream.literal(v)) for v in self._model.dependencies)))) - self._topology.dump(self._model.inputs, out_stream, 'Inputs') + ', '.join((str(out_stream.literal_style(v)) for v in self._model.dependencies)))) + self._topology.dump(self._model.inputs, out_stream, title='Inputs') if self._model.executor is not None: - out_stream.write('Executor: {0}'.format(out_stream.literal(self._model.executor))) + out_stream.write('Executor: {0}'.format(out_stream.literal_style(self._model.executor))) if self._model.max_attempts is not None: - out_stream.write('Max attempts: {0}'.format(out_stream.literal( + out_stream.write('Max attempts: {0}'.format(out_stream.literal_style( self._model.max_attempts))) if self._model.retry_interval is not None: out_stream.write('Retry interval: {0}'.format( - out_stream.literal(self._model.retry_interval))) + out_stream.literal_style(self._model.retry_interval))) if self._model.plugin_specification is not None: out_stream.write('Plugin specification: {0}'.format( - out_stream.literal(self._model.plugin_specification.name))) - self._topology.dump(self._model.configurations, out_stream, 'Configuration') + out_stream.literal_style(self._model.plugin_specification.name))) + self._topology.dump(self._model.configurations, out_stream, title='Configuration') if self._model.function is not None: - out_stream.write('Function: {0}'.format(out_stream.literal(self._model.function))) + out_stream.write('Function: {0}'.format(out_stream.literal_style(self._model.function))) def coerce(self, **kwargs): self._coerce(self._model.inputs, @@ -584,13 +579,14 @@ class OperationTemplate(common._TemplateHandlerMixin): return operation - def validate(self): + def validate(self, **kwargs): self._validate(self._model.inputs, - self._model.configurations) + self._model.configurations, + **kwargs) -class PluginSpecification(common._TemplateHandlerMixin): - def instantiate(self, **kwargs): +class PluginSpecification(common.TemplateHandlerBase): + def instantiate(self, **_): pass def dump(self, out_stream): http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/orchestrator/topology/topology.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/topology/topology.py b/aria/orchestrator/topology/topology.py index 6164a10..b81f61d 100644 --- a/aria/orchestrator/topology/topology.py +++ b/aria/orchestrator/topology/topology.py @@ -23,7 +23,7 @@ from . import ( ) -class Topology(issue.Reporter): +class Topology(issue.ReporterMixin): _init_map = { models.ServiceTemplate: models.Service, @@ -55,23 +55,31 @@ class Topology(issue.Reporter): # somewhere else? super(Topology, self).__init__(*args, **kwargs) self._model_storage = model_storage - self._handlers = dict(self._init_handlers(instance_handler), - **self._init_handlers(template_handler)) + self._models_to_handlers = dict(self._init_handlers(instance_handler), + **self._init_handlers(template_handler)) @staticmethod def _init_handlers(module_): + """ + Register handlers from a module to the models + + :param module_: The module to look for handlers + :return: a dict where key is the models class, and the value is the handler class + associated with it from the provided modukle + """ handlers = {} for attribute_name in dir(module_): if attribute_name.startswith('_'): continue attribute = getattr(module_, attribute_name) - if isinstance(attribute, type) and issubclass(attribute, common._Handler): + if isinstance(attribute, type) and issubclass(attribute, common.HandlerBase): handlers[getattr(models, attribute_name)] = attribute return handlers def instantiate(self, model, **kwargs): """ - all handlers used by instantiate should hold a tuple as value (handler, instnace_cls) + instantiate the provided model + :param model: :param kwargs: :return: @@ -82,25 +90,25 @@ class Topology(issue.Reporter): elif isinstance(model, list): return list(self.instantiate(value, **kwargs) for value in model) elif model is not None: - _handler = self._handlers.get(model.__class__) - instance_cls = self._init_map.get(model.__class__) - return _handler(self, model).instantiate(instance_cls, **kwargs) + _handler = self._models_to_handlers[model.__class__] + model_instance_cls = self._init_map[model.__class__] + return _handler(self, model).instantiate(model_instance_cls, **kwargs) def validate(self, model, **kwargs): if isinstance(model, dict): - return self.validate(model.values()) + return self.validate(model.values(), **kwargs) elif isinstance(model, list): - return all(self.validate(value) for value in model) + return all(self.validate(value, **kwargs) for value in model) elif model is not None: - _handler = self._handlers.get(model.__class__) + _handler = self._models_to_handlers[model.__class__] return _handler(self, model).validate(**kwargs) - def dump(self, model, out_stream=None, section_name=None, **kwargs): + def dump(self, model, out_stream=None, title=None, **kwargs): out_stream = out_stream or console.TopologyStylizer() # if model is empty, no need to print out the section name - if model and section_name: - out_stream.write('{0}:'.format(section_name)) + if model and title: + out_stream.write('{0}:'.format(title)) if isinstance(model, dict): if str(out_stream): @@ -114,12 +122,12 @@ class Topology(issue.Reporter): self.dump(value, out_stream=out_stream, **kwargs) elif model is not None: - _handler = self._handlers.get(model.__class__) + _handler = self._models_to_handlers[model.__class__] _handler(self, model).dump(out_stream=out_stream, **kwargs) return out_stream - def dump_graph(self, service, **kwargs): + def dump_graph(self, service): out_stream = console.TopologyStylizer() for node in service.nodes.itervalues(): if not node.inbound_relationships: @@ -127,19 +135,20 @@ class Topology(issue.Reporter): return out_stream def _dump_graph_node(self, out_stream, node, capability=None): - out_stream.write(out_stream.node(node.name)) + out_stream.write(out_stream.node_style(node.name)) if capability is not None: - out_stream.write('{0} ({1})'.format(out_stream.property(capability.name), - out_stream.type(capability.type.name))) + out_stream.write('{0} ({1})'.format(out_stream.property_style(capability.name), + out_stream.type_style(capability.type_style.name))) if node.outbound_relationships: with out_stream.indent(): for relationship_model in node.outbound_relationships: - relationship_name = out_stream.property(relationship_model.name) - if relationship_model.type is not None: + styled_relationship_name = out_stream.property_style(relationship_model.name) + if relationship_model.type_style is not None: out_stream.write('-> {0} ({1})'.format( - relationship_name, out_stream.type(relationship_model.type.name))) + styled_relationship_name, + out_stream.type_style(relationship_model.type_style.name))) else: - out_stream.write('-> {0}'.format(relationship_name)) + out_stream.write('-> {0}'.format(styled_relationship_name)) with out_stream.indent(3): self._dump_graph_node(out_stream, relationship_model.target_node, @@ -147,11 +156,11 @@ class Topology(issue.Reporter): def coerce(self, model, **kwargs): if isinstance(model, dict): - return self.validate(model.values()) + return self.coerce(model.values(), **kwargs) elif isinstance(model, list): - return all(self.validate(value) for value in model) + return all(self.coerce(value, **kwargs) for value in model) elif model is not None: - _handler = self._handlers.get(model.__class__) + _handler = self._models_to_handlers[model.__class__] return _handler(self, model).coerce(**kwargs) def dump_types(self, service_template, out_stream=None): @@ -164,54 +173,55 @@ class Topology(issue.Reporter): self.dump(service_template.artifact_types, out_stream, 'Artifact types') self.dump(service_template.interface_types, out_stream, 'Interface types') - return str(out_stream) + return out_stream def satisfy_requirements(self, model, **kwargs): if isinstance(model, dict): - return self.satisfy_requirements(model.values()) + return self.satisfy_requirements(model.values(), **kwargs) elif isinstance(model, list): - return all(self.satisfy_requirements(value) for value in model) + return all(self.satisfy_requirements(value, **kwargs) for value in model) elif model is not None: - _handler = self._handlers.get(model.__class__) + _handler = self._models_to_handlers[model.__class__] return _handler(self, model).satisfy_requirements(**kwargs) def validate_capabilities(self, model, **kwargs): if isinstance(model, dict): - return self.validate_capabilities(model.values()) + return self.validate_capabilities(model.values(), **kwargs) elif isinstance(model, list): - return all(self.validate_capabilities(value) for value in model) + return all(self.validate_capabilities(value, **kwargs) for value in model) elif model is not None: - _handler = self._handlers.get(model.__class__) + _handler = self._models_to_handlers[model.__class__] return _handler(self, model).validate_capabilities(**kwargs) def _find_host(self, node): if node.type.role == 'host': return node - has_role = lambda rel, role: \ - rel.target_capability is not None and rel.target_capability.type.role == role + def target_has_role(rel, role): + return (rel.target_capability is not None and + rel.target_capability.type.role == role) - for relationship in node.outbound_relationships: - if has_role(relationship, 'host'): - host = self._find_host(relationship.target_node) + for outbound_relationship in node.outbound_relationships: + if target_has_role(outbound_relationship, 'host'): + host = self._find_host(outbound_relationship.target_node) if host is not None: return host - for relationship in node.inbound_relationships: - if has_role(relationship, 'feature'): - host = self._find_host(relationship.source_node) + for inbound_relationship in node.inbound_relationships: + if target_has_role(inbound_relationship, 'feature'): + host = self._find_host(inbound_relationship.source_node) if host is not None: return host return None - def find_hosts(self, service): + def assign_hosts(self, service): for node in service.nodes.values(): node.host = self._find_host(node) def configure_operations(self, model, **kwargs): if isinstance(model, dict): - return self.configure_operations(model.values()) + return self.configure_operations(model.values(), **kwargs) elif isinstance(model, list): - return all(self.configure_operations(value) for value in model) + return all(self.configure_operations(value, **kwargs) for value in model) elif model is not None: - _handler = self._handlers.get(model.__class__) + _handler = self._models_to_handlers[model.__class__] return _handler(self, model).configure_operations(**kwargs) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/orchestrator/topology/utils.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/topology/utils.py b/aria/orchestrator/topology/utils.py index 47396a5..ec74391 100644 --- a/aria/orchestrator/topology/utils.py +++ b/aria/orchestrator/topology/utils.py @@ -15,8 +15,6 @@ from copy import deepcopy -from ...utils.versions import VersionString - def deepcopy_with_locators(value): """ @@ -48,20 +46,3 @@ def copy_locators(target, source): elif isinstance(target, dict) and isinstance(source, dict): for k, v in target.items(): copy_locators(v, source[k]) - - -def resolve_plugin_specification(plugin_specification, plugins): - matching_plugins = [] - if plugins: - for plugin in plugins: - if (plugin.name == plugin_specification.name and - (plugin_specification.version is None or - VersionString(plugin.package_version) >= plugin_specification.version) - ): - matching_plugins.append(plugin) - plugin_specification.plugin = None - if matching_plugins: - # Return highest version of plugin - plugin_specification.plugin = \ - max(matching_plugins, key=lambda plugin: VersionString(plugin.package_version).key) - return plugin_specification.plugin is not None http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/parser/consumption/modeling.py ---------------------------------------------------------------------- diff --git a/aria/parser/consumption/modeling.py b/aria/parser/consumption/modeling.py index 0afd555..f27216b 100644 --- a/aria/parser/consumption/modeling.py +++ b/aria/parser/consumption/modeling.py @@ -75,7 +75,7 @@ class ServiceTemplate(ConsumerChain): raw = self.context.modeling.template_as_raw self.context.write(json_dumps(raw, indent=indent)) else: - self.topology.dump(self.context.modeling.template) + self.context.write(self.topology.dump(self.context.modeling.template)) class Types(Consumer): @@ -110,22 +110,6 @@ class InstantiateServiceInstance(Consumer): self.context.modeling.template, inputs=dict(self.context.modeling.inputs) ) - ConsumerChain( - self.context, - ( - CoerceServiceInstanceValues, - ValidateServiceInstance, - SatisfyRequirements, - CoerceServiceInstanceValues, - ValidateCapabilities, - FindHosts, - ConfigureOperations, - CoerceServiceInstanceValues - )).consume() - - if self.context.validation.dump_issues(): - raise exceptions.InstantiationError('Failed to instantiate service template `{0}`' - .format(self.context.modeling.template.name)) class CoerceServiceInstanceValues(Consumer): @@ -170,7 +154,7 @@ class FindHosts(Consumer): """ def consume(self): - self.topology.find_hosts(self.context.modeling.instance) + self.topology.assign_hosts(self.context.modeling.instance) class ConfigureOperations(Consumer): http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/parser/presentation/fields.py ---------------------------------------------------------------------- diff --git a/aria/parser/presentation/fields.py b/aria/parser/presentation/fields.py index 9de2f7b..5c08d4a 100644 --- a/aria/parser/presentation/fields.py +++ b/aria/parser/presentation/fields.py @@ -571,7 +571,7 @@ class Field(object): def _dump_primitive(self, context, value): if hasattr(value, 'as_raw'): value = as_raw(value) - puts('%s: %s' % (self.name, context.style.literal(value))) + puts('%s: %s' % (self.name, context.style.literal_style(value))) # primitive list @@ -610,7 +610,7 @@ class Field(object): for primitive in value: if hasattr(primitive, 'as_raw'): primitive = as_raw(primitive) - puts(context.style.literal(primitive)) + puts(context.style.literal_style(primitive)) # primitive dict @@ -639,7 +639,7 @@ class Field(object): for v in value.itervalues(): if hasattr(v, 'as_raw'): v = as_raw(v) - puts(context.style.literal(v)) + puts(context.style.literal_style(v)) # object http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/parser/presentation/presentation.py ---------------------------------------------------------------------- diff --git a/aria/parser/presentation/presentation.py b/aria/parser/presentation/presentation.py index 164d9b2..3f9f86d 100644 --- a/aria/parser/presentation/presentation.py +++ b/aria/parser/presentation/presentation.py @@ -37,13 +37,13 @@ class Value(object): def _dump(self, context): if self.type is not None: - puts(context.style.type(self.type)) + puts(context.style.type_style(self.type)) if self.value is not None: - puts(context.style.literal(self.value)) + puts(context.style.literal_style(self.value)) if self.description is not None: - puts(context.style.meta(self.description)) + puts(context.style.meta_style(self.description)) if self.required is not None: - puts(context.style.required(self.required)) + puts(context.style.required_style(self.required)) class PresentationBase(HasCachedMethods): @@ -162,7 +162,7 @@ class PresentationBase(HasCachedMethods): for field_name in self._iter_field_names(): # pylint: disable=no-member self._dump_field(context, field_name) else: - puts(context.style.literal(self._raw)) + puts(context.style.literal_style(self._raw)) def _dump_field(self, context, field_name): """ http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/parser/validation/context.py ---------------------------------------------------------------------- diff --git a/aria/parser/validation/context.py b/aria/parser/validation/context.py index a245518..da9eef6 100644 --- a/aria/parser/validation/context.py +++ b/aria/parser/validation/context.py @@ -16,7 +16,7 @@ from . import issue -class ValidationContext(issue.Reporter): +class ValidationContext(issue.ReporterMixin): """ Validation context. http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/parser/validation/issue.py ---------------------------------------------------------------------- diff --git a/aria/parser/validation/issue.py b/aria/parser/validation/issue.py index 11ea7f9..42fc580 100644 --- a/aria/parser/validation/issue.py +++ b/aria/parser/validation/issue.py @@ -132,12 +132,12 @@ class Issue(object): return heading_str -class Reporter(object): +class ReporterMixin(object): Issue = Issue def __init__(self, *args, **kwargs): - super(Reporter, self).__init__(*args, **kwargs) + super(ReporterMixin, self).__init__(*args, **kwargs) self._issues = threading.LockedList() self.max_level = self.Issue.ALL http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/aria/utils/console.py ---------------------------------------------------------------------- diff --git a/aria/utils/console.py b/aria/utils/console.py index cd5d480..fa9f873 100644 --- a/aria/utils/console.py +++ b/aria/utils/console.py @@ -31,51 +31,51 @@ _indent_string = '' class TopologyStylizer(object): - def __init__(self, indentation=2): + def __init__(self, indentation=0): self._str = StringIO() self._indentation = indentation - def write(self, str_): - puts(str_, stream=self._str) + def write(self, string): + self._str.write(self._indentation) + self._str.write(formatting.safe_repr(string)) + self._str.write(os.linesep) @contextmanager - def indent(self, indentation=None): - with indent(indentation or self._indentation): - yield + def indent(self, indentation=2): + self._indentation += indentation + yield + self._indentation -= indentation @staticmethod - def section(value): + def section_style(value): return Colored.cyan(value, bold=True) @staticmethod - def type(value): + def type_style(value): return Colored.blue(value, bold=True) @staticmethod - def node(value): + def node_style(value): return Colored.red(value, bold=True) @staticmethod - def property(value): + def property_style(value): return Colored.magenta(value, bold=True) @staticmethod - def literal(value): + def literal_style(value): return Colored.magenta(formatting.safe_repr(value)) @staticmethod - def required(value): + def required_style(value): return Colored.white(value) @staticmethod - def meta(value): + def meta_style(value): return Colored.green(value) - def __repr__(self): - return self._str.getvalue() - def __str__(self): - return repr(self) + return self._str.getvalue() def puts(string='', newline=True, stream=sys.stdout): http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/a33ba12e/extensions/aria_extension_tosca/simple_v1_0/misc.py ---------------------------------------------------------------------- diff --git a/extensions/aria_extension_tosca/simple_v1_0/misc.py b/extensions/aria_extension_tosca/simple_v1_0/misc.py index 23beb3c..a65ff41 100644 --- a/extensions/aria_extension_tosca/simple_v1_0/misc.py +++ b/extensions/aria_extension_tosca/simple_v1_0/misc.py @@ -52,7 +52,7 @@ class Description(AsIsPresentation): def _dump(self, context): value = as_raw(self.value) - puts(context.style.meta(value)) + puts(context.style.meta_style(value)) @allow_unknown_fields