You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ariatosca.apache.org by mxmrlv <gi...@git.apache.org> on 2017/07/30 16:13:51 UTC

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

GitHub user mxmrlv opened a pull request:

    https://github.com/apache/incubator-ariatosca/pull/189

    ARIA-174 Refactor instantiation phase

    

You can merge this pull request into a Git repository by running:

    $ git pull https://github.com/apache/incubator-ariatosca ARIA-174-Refactor-instantiation-phase

Alternatively you can review and apply these changes as the patch at:

    https://github.com/apache/incubator-ariatosca/pull/189.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

    This closes #189
    
----
commit 9010784679c291738bba06c70f446b12893cd1df
Author: max-orlov <ma...@gigaspaces.com>
Date:   2017-07-13T13:49:15Z

    wip

----


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132167801
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -550,7 +550,7 @@ def dump(self, out_stream):
             out_stream.write('Substitution:')
             with out_stream.indent():
                 out_stream.write('Node type: {0}'.format(out_stream.type_style(
    -                self._model.node_type.name)))
    --- End diff --
    
    Change to `node`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131087352
  
    --- Diff: aria/orchestrator/topology/template_handler.py ---
    @@ -0,0 +1,597 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from datetime import datetime
    +
    +from ...utils import formatting
    +from ...modeling import utils as modeling_utils
    +from . import utils, common
    +
    +
    +class ServiceTemplate(common._TemplateHandlerMixin):
    +    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')
    +        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')
    +
    +    def coerce(self, **kwargs):
    +        self._coerce(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,
    +                     **kwargs)
    +
    +    def instantiate(self, instance_cls, inputs=None):                                               # pylint: disable=arguments-differ
    +        now = datetime.now()
    +
    +        modeling_utils.validate_no_undeclared_inputs(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +        modeling_utils.validate_required_inputs_are_supplied(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +
    +        service = instance_cls(
    +            created_at=now,
    +            updated_at=now,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            service_template=self._model,
    +            inputs=modeling_utils.merge_parameter_values(inputs, self._model.inputs)
    +        )
    +
    +        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,
    +                                                      self._topology.model_storage.plugin.list()):
    +                    plugin = plugin_specification.plugin
    +                    service.plugins[plugin.name] = plugin
    +                else:
    +                    self._topology.report('specified plugin not found: {0}'.format(
    +                        plugin_specification.name), level=self._topology.Issue.EXTERNAL)
    +        service.meta_data = self._topology.instantiate(self._model.meta_data)
    +
    +        for node_template in self._model.node_templates.itervalues():
    +            for _ in range(self._scaling(node_template)['default_instances']):
    +                node = self._topology.instantiate(node_template)
    +                service.nodes[node.name] = node
    +
    +        service.groups = self._topology.instantiate(self._model.group_templates)
    +        service.policies = self._topology.instantiate(self._model.policy_templates)
    +        service.workflows = self._topology.instantiate(self._model.workflow_templates)
    +        service.substitution = self._topology.instantiate(self._model.substitution_template)
    +        service.outputs = self._topology.instantiate(self._model.outputs)
    +
    +        return service
    +
    +    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']):
    +            self._topology.report(
    +                'invalid scaling parameters for node template "{0}": min={min_instances}, max='
    +                '{max_instances}, default={default_instances}'.format(self._model.name, **scaling),
    +                level=self._topology.Issue.BETWEEN_TYPES)
    +
    +        return scaling
    +
    +    def validate(self):
    +        self._topology.validate(self._model.meta_data)
    --- End diff --
    
    Consider using the `_validate` method.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130828782
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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)
    +
    +    def validate(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).validate(**kwargs)
    +
    +    def dump(self, model, out_stream=None, section_name=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 isinstance(model, dict):
    +            if str(out_stream):
    +                with out_stream.indent():
    +                    return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +            else:
    +                return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +
    +        elif isinstance(model, list):
    +            for value in model:
    +                self.dump(value, out_stream=out_stream, **kwargs)
    +
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            _handler(self, model).dump(out_stream=out_stream, **kwargs)
    +
    +        return out_stream
    +
    +    def dump_graph(self, service, **kwargs):
    +        out_stream = console.TopologyStylizer()
    +        for node in service.nodes.itervalues():
    +            if not node.inbound_relationships:
    +                self._dump_graph_node(out_stream, node)
    +        return out_stream
    +
    +    def _dump_graph_node(self, out_stream, node, capability=None):
    +        out_stream.write(out_stream.node(node.name))
    +        if capability is not None:
    +            out_stream.write('{0} ({1})'.format(out_stream.property(capability.name),
    +                                                out_stream.type(capability.type.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:
    +                        out_stream.write('-> {0} ({1})'.format(
    +                            relationship_name, out_stream.type(relationship_model.type.name)))
    +                    else:
    +                        out_stream.write('-> {0}'.format(relationship_name))
    +                    with out_stream.indent(3):
    +                        self._dump_graph_node(out_stream,
    +                                              relationship_model.target_node,
    +                                              relationship_model.target_capability)
    +
    +    def coerce(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).coerce(**kwargs)
    +
    +    def dump_types(self, service_template, out_stream=None):
    +        out_stream = out_stream or console.TopologyStylizer()
    +        self.dump(service_template.node_types, out_stream, 'Node types')
    +        self.dump(service_template.group_types, out_stream, 'Group types')
    +        self.dump(service_template.capability_types, out_stream, 'Capability types')
    +        self.dump(service_template.relationship_types, out_stream, 'Relationship types')
    +        self.dump(service_template.policy_types, out_stream, 'Policy types')
    +        self.dump(service_template.artifact_types, out_stream, 'Artifact types')
    +        self.dump(service_template.interface_types, out_stream, 'Interface types')
    +
    +        return str(out_stream)
    +
    +    def satisfy_requirements(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.satisfy_requirements(model.values())
    +        elif isinstance(model, list):
    +            return all(self.satisfy_requirements(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(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())
    +        elif isinstance(model, list):
    +            return all(self.validate_capabilities(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(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
    +
    +        for relationship in node.outbound_relationships:
    --- End diff --
    
    `for relationship` --> `for outbound_relationship`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132122736
  
    --- Diff: aria/core.py ---
    @@ -117,8 +118,8 @@ def delete_service(self, service_id, force=False):
         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.
    --- End diff --
    
    the thing is the Consumers mechanism in general, not the use of the ConsumerChain object.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130902625
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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):
    --- End diff --
    
    Does this handle the same requirement defined twice?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130592682
  
    --- Diff: aria/modeling/utils.py ---
    @@ -244,3 +173,9 @@ def init(*args, **kwargs):
         cls.__doc__ = cls.__bases__[-1].__doc__
     
         return cls
    +
    +
    +def get_class_from_relationship(property):
    --- End diff --
    
    `get_class_from_relationship` -> `get_class_from_sql_relationship`, so we don't get confused with TOSCA relationships.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132127314
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -527,78 +539,82 @@ def satisfy_requirements(self):
                        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 coerce(self, **kwargs):
    +        pass
    +
    +    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),
    --- End diff --
    
    Go over all the `node_style`s.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130844470
  
    --- Diff: aria/parser/consumption/modeling.py ---
    @@ -105,9 +106,26 @@ def consume(self):
                 self.context.validation.report('InstantiateServiceInstance consumer: missing service '
                                                'template')
                 return
    -
    -        self.context.modeling.template.instantiate(None, None,
    -                                                   inputs=dict(self.context.modeling.inputs))
    +        self.context.modeling.instance = self.topology.instantiate(
    +            self.context.modeling.template,
    +            inputs=dict(self.context.modeling.inputs)
    +        )
    +        ConsumerChain(
    --- End diff --
    
    Is it even used? Isn't this logic already implemented in `create_service` in `core.py`?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130593153
  
    --- Diff: aria/orchestrator/execution_plugin/instantiation.py ---
    @@ -110,20 +105,17 @@ def _configure_remote(operation):
     
         # Make sure we have a user
         if fabric_env.get('user') is None:
    -        context = ConsumptionContext.get_thread_local()
    -        context.validation.report('must configure "ssh.user" for "{0}"'
    -                                  .format(operation.implementation),
    -                                  level=validation.Issue.BETWEEN_TYPES)
    +        reporter.report('must configure "ssh.user" for "{0}"'.format(operation.implementation),
    --- End diff --
    
    Does `context.validation` get filled?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130599473
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.inputs, self._model.operations, **kwargs)
    +
    +    def validate(self, **kwargs):
    --- End diff --
    
    What is the use of `**kwargs`?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130830529
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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)
    +
    +    def validate(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).validate(**kwargs)
    +
    +    def dump(self, model, out_stream=None, section_name=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 isinstance(model, dict):
    +            if str(out_stream):
    +                with out_stream.indent():
    +                    return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +            else:
    +                return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +
    +        elif isinstance(model, list):
    +            for value in model:
    +                self.dump(value, out_stream=out_stream, **kwargs)
    +
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            _handler(self, model).dump(out_stream=out_stream, **kwargs)
    +
    +        return out_stream
    +
    +    def dump_graph(self, service, **kwargs):
    +        out_stream = console.TopologyStylizer()
    +        for node in service.nodes.itervalues():
    +            if not node.inbound_relationships:
    +                self._dump_graph_node(out_stream, node)
    +        return out_stream
    +
    +    def _dump_graph_node(self, out_stream, node, capability=None):
    +        out_stream.write(out_stream.node(node.name))
    +        if capability is not None:
    +            out_stream.write('{0} ({1})'.format(out_stream.property(capability.name),
    +                                                out_stream.type(capability.type.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:
    +                        out_stream.write('-> {0} ({1})'.format(
    +                            relationship_name, out_stream.type(relationship_model.type.name)))
    +                    else:
    +                        out_stream.write('-> {0}'.format(relationship_name))
    +                    with out_stream.indent(3):
    +                        self._dump_graph_node(out_stream,
    +                                              relationship_model.target_node,
    +                                              relationship_model.target_capability)
    +
    +    def coerce(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).coerce(**kwargs)
    +
    +    def dump_types(self, service_template, out_stream=None):
    +        out_stream = out_stream or console.TopologyStylizer()
    +        self.dump(service_template.node_types, out_stream, 'Node types')
    +        self.dump(service_template.group_types, out_stream, 'Group types')
    +        self.dump(service_template.capability_types, out_stream, 'Capability types')
    +        self.dump(service_template.relationship_types, out_stream, 'Relationship types')
    +        self.dump(service_template.policy_types, out_stream, 'Policy types')
    +        self.dump(service_template.artifact_types, out_stream, 'Artifact types')
    +        self.dump(service_template.interface_types, out_stream, 'Interface types')
    +
    +        return str(out_stream)
    +
    +    def satisfy_requirements(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.satisfy_requirements(model.values())
    +        elif isinstance(model, list):
    +            return all(self.satisfy_requirements(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(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())
    +        elif isinstance(model, list):
    +            return all(self.validate_capabilities(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(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
    +
    +        for relationship in node.outbound_relationships:
    +            if has_role(relationship, 'host'):
    +                host = self._find_host(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)
    +                if host is not None:
    +                    return host
    +        return None
    +
    +    def find_hosts(self, service):
    --- End diff --
    
    should it be `assign_hosts`? Anyways, `find` is not accurate, as hosts are being assigned for the nodes within this method.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132137574
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -50,28 +49,33 @@ class Topology(issue.Reporter):
             models.Type: models.Type
         }
     
    -    def __init__(self, model_storage=None, *args, **kwargs):
    -        # TODO: model storage is required only for the list of plugins, can we get it
    -        # somewhere else?
    +    def __init__(self, *args, **kwargs):
             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),
    --- End diff --
    
    `_models_to_handlers` --> `model_classes_to_handlers` or `model_class_to_handler`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130331416
  
    --- Diff: aria/orchestrator/topology/utils.py ---
    @@ -0,0 +1,67 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from copy import deepcopy
    +
    +from ...utils.versions import VersionString
    +
    +
    +def deepcopy_with_locators(value):
    +    """
    +    Like :func:`deepcopy`, but also copies over locators.
    +    """
    +
    +    res = deepcopy(value)
    +    copy_locators(res, value)
    +    return res
    +
    +
    +def copy_locators(target, source):
    +    """
    +    Copies over ``_locator`` for all elements, recursively.
    +
    +    Assumes that target and source have exactly the same list/dict structure.
    +    """
    +
    +    locator = getattr(source, '_locator', None)
    +    if locator is not None:
    +        try:
    +            setattr(target, '_locator', locator)
    +        except AttributeError:
    +            pass
    +
    +    if isinstance(target, list) and isinstance(source, list):
    +        for i, _ in enumerate(target):
    +            copy_locators(target[i], source[i])
    +    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):
    --- End diff --
    
    is this the right place for this function?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130826916
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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)
    +
    +    def validate(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).validate(**kwargs)
    +
    +    def dump(self, model, out_stream=None, section_name=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 isinstance(model, dict):
    +            if str(out_stream):
    +                with out_stream.indent():
    +                    return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +            else:
    +                return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +
    +        elif isinstance(model, list):
    +            for value in model:
    +                self.dump(value, out_stream=out_stream, **kwargs)
    +
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            _handler(self, model).dump(out_stream=out_stream, **kwargs)
    +
    +        return out_stream
    +
    +    def dump_graph(self, service, **kwargs):
    +        out_stream = console.TopologyStylizer()
    +        for node in service.nodes.itervalues():
    +            if not node.inbound_relationships:
    +                self._dump_graph_node(out_stream, node)
    +        return out_stream
    +
    +    def _dump_graph_node(self, out_stream, node, capability=None):
    +        out_stream.write(out_stream.node(node.name))
    +        if capability is not None:
    +            out_stream.write('{0} ({1})'.format(out_stream.property(capability.name),
    +                                                out_stream.type(capability.type.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:
    +                        out_stream.write('-> {0} ({1})'.format(
    +                            relationship_name, out_stream.type(relationship_model.type.name)))
    +                    else:
    +                        out_stream.write('-> {0}'.format(relationship_name))
    +                    with out_stream.indent(3):
    +                        self._dump_graph_node(out_stream,
    +                                              relationship_model.target_node,
    +                                              relationship_model.target_capability)
    +
    +    def coerce(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).coerce(**kwargs)
    +
    +    def dump_types(self, service_template, out_stream=None):
    +        out_stream = out_stream or console.TopologyStylizer()
    +        self.dump(service_template.node_types, out_stream, 'Node types')
    +        self.dump(service_template.group_types, out_stream, 'Group types')
    +        self.dump(service_template.capability_types, out_stream, 'Capability types')
    +        self.dump(service_template.relationship_types, out_stream, 'Relationship types')
    +        self.dump(service_template.policy_types, out_stream, 'Policy types')
    +        self.dump(service_template.artifact_types, out_stream, 'Artifact types')
    +        self.dump(service_template.interface_types, out_stream, 'Interface types')
    +
    +        return str(out_stream)
    --- End diff --
    
    Why do you return `str(out_stream)` here, and `out_stream` in `dump`?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131133863
  
    --- Diff: aria/utils/__init__.py ---
    @@ -16,3 +16,50 @@
     """
     General-purpose utilities package.
     """
    +
    +from . import (
    +    archive,
    +    argparse,
    +    caching,
    +    collections,
    +    console,
    +    exceptions,
    +    file,
    +    formatting,
    +    http,
    +    imports,
    +    openclose,
    +    plugin,
    +    process,
    +    specification,
    +    threading,
    +    type,
    +    uris,
    +    uuid,
    +    validation,
    +    versions
    +)
    +
    +
    +__all__ = (
    --- End diff --
    
    it isn't, but IMO it's cleaner...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130893648
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    --- End diff --
    
    `kwargs`?
    In all the relevant place.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130844628
  
    --- Diff: aria/parser/consumption/modeling.py ---
    @@ -105,9 +106,26 @@ def consume(self):
                 self.context.validation.report('InstantiateServiceInstance consumer: missing service '
                                                'template')
                 return
    -
    -        self.context.modeling.template.instantiate(None, None,
    -                                                   inputs=dict(self.context.modeling.inputs))
    +        self.context.modeling.instance = self.topology.instantiate(
    +            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():
    --- End diff --
    
    Also this part.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130876338
  
    --- Diff: tests/instantiation/test_configuration.py ---
    @@ -165,8 +165,11 @@ def test_remote(service):
     
     
     def test_reserved_arguments(broken_service_issues):
    --- End diff --
    
    Removing the part that starts [here](https://github.com/apache/incubator-ariatosca/pull/189/files/b729f6349e8b2a5d5270ba2f4608ebbcc18ae956#diff-76248dafd82902b4219068a6e2457c55R113) maybe resolves this.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130829336
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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)
    +
    +    def validate(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).validate(**kwargs)
    +
    +    def dump(self, model, out_stream=None, section_name=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 isinstance(model, dict):
    +            if str(out_stream):
    +                with out_stream.indent():
    +                    return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +            else:
    +                return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +
    +        elif isinstance(model, list):
    +            for value in model:
    +                self.dump(value, out_stream=out_stream, **kwargs)
    +
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            _handler(self, model).dump(out_stream=out_stream, **kwargs)
    +
    +        return out_stream
    +
    +    def dump_graph(self, service, **kwargs):
    +        out_stream = console.TopologyStylizer()
    +        for node in service.nodes.itervalues():
    +            if not node.inbound_relationships:
    +                self._dump_graph_node(out_stream, node)
    +        return out_stream
    +
    +    def _dump_graph_node(self, out_stream, node, capability=None):
    +        out_stream.write(out_stream.node(node.name))
    +        if capability is not None:
    +            out_stream.write('{0} ({1})'.format(out_stream.property(capability.name),
    +                                                out_stream.type(capability.type.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:
    +                        out_stream.write('-> {0} ({1})'.format(
    +                            relationship_name, out_stream.type(relationship_model.type.name)))
    +                    else:
    +                        out_stream.write('-> {0}'.format(relationship_name))
    +                    with out_stream.indent(3):
    +                        self._dump_graph_node(out_stream,
    +                                              relationship_model.target_node,
    +                                              relationship_model.target_capability)
    +
    +    def coerce(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).coerce(**kwargs)
    +
    +    def dump_types(self, service_template, out_stream=None):
    +        out_stream = out_stream or console.TopologyStylizer()
    +        self.dump(service_template.node_types, out_stream, 'Node types')
    +        self.dump(service_template.group_types, out_stream, 'Group types')
    +        self.dump(service_template.capability_types, out_stream, 'Capability types')
    +        self.dump(service_template.relationship_types, out_stream, 'Relationship types')
    +        self.dump(service_template.policy_types, out_stream, 'Policy types')
    +        self.dump(service_template.artifact_types, out_stream, 'Artifact types')
    +        self.dump(service_template.interface_types, out_stream, 'Interface types')
    +
    +        return str(out_stream)
    +
    +    def satisfy_requirements(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.satisfy_requirements(model.values())
    +        elif isinstance(model, list):
    +            return all(self.satisfy_requirements(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(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())
    +        elif isinstance(model, list):
    +            return all(self.validate_capabilities(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(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
    +
    +        for relationship in node.outbound_relationships:
    +            if has_role(relationship, 'host'):
    --- End diff --
    
    Run openstack hello world to check if this `host` finding mechanism is correct.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by asfgit <gi...@git.apache.org>.
Github user asfgit closed the pull request at:

    https://github.com/apache/incubator-ariatosca/pull/189


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132127992
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -527,78 +539,82 @@ def satisfy_requirements(self):
                        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 coerce(self, **kwargs):
    +        pass
    +
    +    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):
    --- End diff --
    
    Rethink about the `**kwargs` here. Considering how it's in all the other `instantiate`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131089434
  
    --- Diff: aria/orchestrator/topology/template_handler.py ---
    @@ -0,0 +1,597 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from datetime import datetime
    +
    +from ...utils import formatting
    +from ...modeling import utils as modeling_utils
    +from . import utils, common
    +
    +
    +class ServiceTemplate(common._TemplateHandlerMixin):
    +    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')
    +        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')
    +
    +    def coerce(self, **kwargs):
    +        self._coerce(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,
    +                     **kwargs)
    +
    +    def instantiate(self, instance_cls, inputs=None):                                               # pylint: disable=arguments-differ
    +        now = datetime.now()
    +
    +        modeling_utils.validate_no_undeclared_inputs(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +        modeling_utils.validate_required_inputs_are_supplied(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +
    +        service = instance_cls(
    +            created_at=now,
    +            updated_at=now,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            service_template=self._model,
    +            inputs=modeling_utils.merge_parameter_values(inputs, self._model.inputs)
    +        )
    +
    +        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,
    +                                                      self._topology.model_storage.plugin.list()):
    +                    plugin = plugin_specification.plugin
    +                    service.plugins[plugin.name] = plugin
    +                else:
    +                    self._topology.report('specified plugin not found: {0}'.format(
    +                        plugin_specification.name), level=self._topology.Issue.EXTERNAL)
    +        service.meta_data = self._topology.instantiate(self._model.meta_data)
    +
    +        for node_template in self._model.node_templates.itervalues():
    +            for _ in range(self._scaling(node_template)['default_instances']):
    +                node = self._topology.instantiate(node_template)
    +                service.nodes[node.name] = node
    +
    +        service.groups = self._topology.instantiate(self._model.group_templates)
    +        service.policies = self._topology.instantiate(self._model.policy_templates)
    +        service.workflows = self._topology.instantiate(self._model.workflow_templates)
    +        service.substitution = self._topology.instantiate(self._model.substitution_template)
    +        service.outputs = self._topology.instantiate(self._model.outputs)
    +
    +        return service
    +
    +    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']):
    +            self._topology.report(
    +                'invalid scaling parameters for node template "{0}": min={min_instances}, max='
    +                '{max_instances}, default={default_instances}'.format(self._model.name, **scaling),
    +                level=self._topology.Issue.BETWEEN_TYPES)
    +
    +        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 dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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)))
    +            if self._model.target_path is not None:
    +                out_stream.write('Target path: {0}'.format(out_stream.literal(
    +                    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)))
    +            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')
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def instantiate(self, instance_cls):
    +        return instance_cls(
    +            name=self._model.name,
    +            type=self._model.type,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            source_path=self._model.source_path,
    +            target_path=self._model.target_path,
    +            repository_url=self._model.repository_url,
    +            repository_credential=self._model.repository_credential,
    +            artifact_template=self._model)
    +
    +    def validate(self):
    +        self._topology.validate(self._model.properties)
    +
    +
    +class CapabilityTemplate(common._TemplateHandlerMixin):
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(self._model.description))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name)))
    +            out_stream.write(
    +                'Occurrences: {0:d}{1}'.format(
    +                    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'))
    +            if self._model.valid_source_node_types:
    +                out_stream.write('Valid source node types: {0}'.format(
    +                    ', '.join((str(out_stream.type(v.name))
    +                               for v in self._model.valid_source_node_types))))
    +            self._topology.dump(self._model.properties, out_stream, 'Properties')
    +
    +    def coerce(self):
    +        self._topology.coerce(self._model.properties)
    +
    +    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)
    +
    +    def validate(self):
    +        self._topology.validate(self._model.properties)
    +
    +
    +class RequirementTemplate(common._TemplateHandlerMixin):
    +    def dump(self, out_stream):
    +        if self._model.name:
    +            out_stream.write(out_stream.node(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)))
    +            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)))
    +            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)))
    +            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)))
    +            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))
    +            if self._model.relationship_template:
    +                out_stream.write('Relationship:')
    +                with out_stream.indent():
    +                    self._topology.dump(self._model.relationship_template, out_stream)
    +
    +    def coerce(self, **kwargs):
    +        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,
    --- End diff --
    
    Should it be 1? This is a requirement template.
    And do we even instantiate this class? In the `_init_map` it is mapped to `None`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131095491
  
    --- Diff: aria/orchestrator/topology/utils.py ---
    @@ -0,0 +1,67 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from copy import deepcopy
    +
    +from ...utils.versions import VersionString
    +
    +
    +def deepcopy_with_locators(value):
    +    """
    +    Like :func:`deepcopy`, but also copies over locators.
    +    """
    +
    +    res = deepcopy(value)
    +    copy_locators(res, value)
    +    return res
    +
    +
    +def copy_locators(target, source):
    +    """
    +    Copies over ``_locator`` for all elements, recursively.
    +
    +    Assumes that target and source have exactly the same list/dict structure.
    +    """
    +
    +    locator = getattr(source, '_locator', None)
    +    if locator is not None:
    +        try:
    +            setattr(target, '_locator', locator)
    +        except AttributeError:
    +            pass
    +
    +    if isinstance(target, list) and isinstance(source, list):
    +        for i, _ in enumerate(target):
    +            copy_locators(target[i], source[i])
    +    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):
    --- End diff --
    
    Maybe in the Service Template Handler.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130900925
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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
    --- End diff --
    
    `r` --> `rel`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130594613
  
    --- Diff: aria/orchestrator/topology/common.py ---
    @@ -0,0 +1,52 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +
    +class _Handler(object):
    +    def __init__(self, topology, template):
    +        self._topology = topology
    +        self._model = template
    +
    +    def _coerce(self, *templates, **kwargs):
    +        for template in templates:
    +            self._topology.coerce(template)
    +
    +    def coerce(self):
    +        pass
    +
    +    def validate(self, **kwargs):
    +        pass
    +
    +    def _validate(self, *templates, **kwargs):
    --- End diff --
    
    maybe `_validate_collection` or `iterable`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130868717
  
    --- Diff: aria/utils/console.py ---
    @@ -19,19 +19,68 @@
     
     import os
     import sys
    +from StringIO import StringIO
     
     from contextlib import contextmanager
     
    -from .formatting import safe_str
     from ..cli import color
    +from . import formatting
     
     
     _indent_string = ''
     
     
    +class TopologyStylizer(object):
    +    def __init__(self, indentation=2):
    +        self._str = StringIO()
    +        self._indentation = indentation
    +
    +    def write(self, str_):
    --- End diff --
    
    `str_` --> `string`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132122306
  
    --- Diff: aria/core.py ---
    @@ -74,18 +74,19 @@ def create_service(self, service_template_id, inputs, service_name=None):
             # setting no autoflush for the duration of instantiation - this helps avoid dependency
             # constraints as they're being set up
             with storage_session.no_autoflush:
    -            topology_ = topology.Topology(self.model_storage)
    -            service = topology_.instantiate(service_template, inputs=inputs)
    -            topology_.coerce(service)
    +            topology_ = topology.Topology()
    +            service = topology_.instantiate(
    --- End diff --
    
    maybe just pass the plugins, as they are the only ones that are actually needed from the model.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131134367
  
    --- Diff: aria/orchestrator/topology/template_handler.py ---
    @@ -0,0 +1,597 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from datetime import datetime
    +
    +from ...utils import formatting
    +from ...modeling import utils as modeling_utils
    +from . import utils, common
    +
    +
    +class ServiceTemplate(common._TemplateHandlerMixin):
    +    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')
    +        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')
    +
    +    def coerce(self, **kwargs):
    +        self._coerce(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,
    +                     **kwargs)
    +
    +    def instantiate(self, instance_cls, inputs=None):                                               # pylint: disable=arguments-differ
    +        now = datetime.now()
    +
    +        modeling_utils.validate_no_undeclared_inputs(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +        modeling_utils.validate_required_inputs_are_supplied(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +
    +        service = instance_cls(
    +            created_at=now,
    +            updated_at=now,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            service_template=self._model,
    +            inputs=modeling_utils.merge_parameter_values(inputs, self._model.inputs)
    +        )
    +
    +        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,
    +                                                      self._topology.model_storage.plugin.list()):
    +                    plugin = plugin_specification.plugin
    +                    service.plugins[plugin.name] = plugin
    +                else:
    +                    self._topology.report('specified plugin not found: {0}'.format(
    +                        plugin_specification.name), level=self._topology.Issue.EXTERNAL)
    +        service.meta_data = self._topology.instantiate(self._model.meta_data)
    +
    +        for node_template in self._model.node_templates.itervalues():
    +            for _ in range(self._scaling(node_template)['default_instances']):
    +                node = self._topology.instantiate(node_template)
    +                service.nodes[node.name] = node
    +
    +        service.groups = self._topology.instantiate(self._model.group_templates)
    +        service.policies = self._topology.instantiate(self._model.policy_templates)
    +        service.workflows = self._topology.instantiate(self._model.workflow_templates)
    +        service.substitution = self._topology.instantiate(self._model.substitution_template)
    +        service.outputs = self._topology.instantiate(self._model.outputs)
    +
    +        return service
    +
    +    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']):
    +            self._topology.report(
    +                'invalid scaling parameters for node template "{0}": min={min_instances}, max='
    +                '{max_instances}, default={default_instances}'.format(self._model.name, **scaling),
    +                level=self._topology.Issue.BETWEEN_TYPES)
    +
    +        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 dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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)))
    +            if self._model.target_path is not None:
    +                out_stream.write('Target path: {0}'.format(out_stream.literal(
    +                    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)))
    +            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')
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def instantiate(self, instance_cls):
    +        return instance_cls(
    +            name=self._model.name,
    +            type=self._model.type,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            source_path=self._model.source_path,
    +            target_path=self._model.target_path,
    +            repository_url=self._model.repository_url,
    +            repository_credential=self._model.repository_credential,
    +            artifact_template=self._model)
    +
    +    def validate(self):
    +        self._topology.validate(self._model.properties)
    +
    +
    +class CapabilityTemplate(common._TemplateHandlerMixin):
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(self._model.description))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name)))
    +            out_stream.write(
    +                'Occurrences: {0:d}{1}'.format(
    +                    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'))
    +            if self._model.valid_source_node_types:
    +                out_stream.write('Valid source node types: {0}'.format(
    +                    ', '.join((str(out_stream.type(v.name))
    +                               for v in self._model.valid_source_node_types))))
    +            self._topology.dump(self._model.properties, out_stream, 'Properties')
    +
    +    def coerce(self):
    +        self._topology.coerce(self._model.properties)
    +
    +    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)
    +
    +    def validate(self):
    +        self._topology.validate(self._model.properties)
    +
    +
    +class RequirementTemplate(common._TemplateHandlerMixin):
    +    def dump(self, out_stream):
    +        if self._model.name:
    +            out_stream.write(out_stream.node(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)))
    +            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)))
    +            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)))
    +            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)))
    +            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))
    +            if self._model.relationship_template:
    +                out_stream.write('Relationship:')
    +                with out_stream.indent():
    +                    self._topology.dump(self._model.relationship_template, out_stream)
    +
    +    def coerce(self, **kwargs):
    +        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,
    --- End diff --
    
    the instantiation was removed.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130870769
  
    --- Diff: aria/utils/console.py ---
    @@ -19,19 +19,68 @@
     
     import os
     import sys
    +from StringIO import StringIO
     
     from contextlib import contextmanager
     
    -from .formatting import safe_str
     from ..cli import color
    +from . import formatting
     
     
     _indent_string = ''
     
     
    +class TopologyStylizer(object):
    +    def __init__(self, indentation=2):
    +        self._str = StringIO()
    +        self._indentation = indentation
    +
    +    def write(self, str_):
    +        puts(str_, stream=self._str)
    +
    +    @contextmanager
    +    def indent(self, indentation=None):
    --- End diff --
    
    This should only affect the calls for `write` and not the module level `puts`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130606598
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    --- End diff --
    
    Maybe document by saying at least what is the return value, and why.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130871342
  
    --- Diff: aria/utils/console.py ---
    @@ -19,19 +19,68 @@
     
     import os
     import sys
    +from StringIO import StringIO
     
     from contextlib import contextmanager
     
    -from .formatting import safe_str
     from ..cli import color
    +from . import formatting
     
     
     _indent_string = ''
     
     
    +class TopologyStylizer(object):
    +    def __init__(self, indentation=2):
    +        self._str = StringIO()
    +        self._indentation = indentation
    +
    +    def write(self, str_):
    +        puts(str_, stream=self._str)
    +
    +    @contextmanager
    +    def indent(self, indentation=None):
    +        with indent(indentation or self._indentation):
    +            yield
    +
    +    @staticmethod
    +    def section(value):
    +        return Colored.cyan(value, bold=True)
    +
    +    @staticmethod
    +    def type(value):
    +        return Colored.blue(value, bold=True)
    +
    +    @staticmethod
    +    def node(value):
    +        return Colored.red(value, bold=True)
    +
    +    @staticmethod
    +    def property(value):
    +        return Colored.magenta(value, bold=True)
    +
    +    @staticmethod
    +    def literal(value):
    +        return Colored.magenta(formatting.safe_repr(value))
    +
    +    @staticmethod
    +    def required(value):
    +        return Colored.white(value)
    +
    +    @staticmethod
    +    def meta(value):
    +        return Colored.green(value)
    +
    +    def __repr__(self):
    --- End diff --
    
    `__repr__` should have a standard implementation.
    So remove this, and just implement `__str__`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131950842
  
    --- Diff: aria/core.py ---
    @@ -117,8 +118,8 @@ def delete_service(self, service_id, force=False):
         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.
    --- End diff --
    
    teh


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132129612
  
    --- Diff: aria/orchestrator/topology/template_handler.py ---
    @@ -61,9 +64,9 @@ def instantiate(self, instance_cls, inputs=None):
             )
     
             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,
    -                                                      self._topology.model_storage.plugin.list()):
    +            if plugin_specification.enabled and model_storage:
    --- End diff --
    
    instead of `model_storage`, something like `plugins`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130593845
  
    --- Diff: aria/orchestrator/topology/common.py ---
    @@ -0,0 +1,52 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +
    +class _Handler(object):
    +    def __init__(self, topology, template):
    --- End diff --
    
    `template` --> `model`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130330770
  
    --- Diff: aria/core.py ---
    @@ -122,6 +118,8 @@ def delete_service(self, service_id, force=False):
         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
    --- End diff --
    
    address that


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130826035
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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)
    +
    +    def validate(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).validate(**kwargs)
    +
    +    def dump(self, model, out_stream=None, section_name=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 isinstance(model, dict):
    +            if str(out_stream):
    +                with out_stream.indent():
    +                    return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +            else:
    +                return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +
    +        elif isinstance(model, list):
    +            for value in model:
    +                self.dump(value, out_stream=out_stream, **kwargs)
    +
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            _handler(self, model).dump(out_stream=out_stream, **kwargs)
    +
    +        return out_stream
    +
    +    def dump_graph(self, service, **kwargs):
    +        out_stream = console.TopologyStylizer()
    +        for node in service.nodes.itervalues():
    +            if not node.inbound_relationships:
    +                self._dump_graph_node(out_stream, node)
    +        return out_stream
    +
    +    def _dump_graph_node(self, out_stream, node, capability=None):
    +        out_stream.write(out_stream.node(node.name))
    +        if capability is not None:
    +            out_stream.write('{0} ({1})'.format(out_stream.property(capability.name),
    +                                                out_stream.type(capability.type.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:
    +                        out_stream.write('-> {0} ({1})'.format(
    +                            relationship_name, out_stream.type(relationship_model.type.name)))
    +                    else:
    +                        out_stream.write('-> {0}'.format(relationship_name))
    +                    with out_stream.indent(3):
    +                        self._dump_graph_node(out_stream,
    +                                              relationship_model.target_node,
    +                                              relationship_model.target_capability)
    +
    +    def coerce(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    --- End diff --
    
    should be `coerce`.
    In all places.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130586353
  
    --- Diff: aria/core.py ---
    @@ -122,6 +118,8 @@ def delete_service(self, service_id, force=False):
         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
    --- End diff --
    
    this comment does not explain that you didn't change this section because it was not in the scope of refactoring instantiation.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131091773
  
    --- Diff: aria/orchestrator/topology/template_handler.py ---
    @@ -0,0 +1,597 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from datetime import datetime
    +
    +from ...utils import formatting
    +from ...modeling import utils as modeling_utils
    +from . import utils, common
    +
    +
    +class ServiceTemplate(common._TemplateHandlerMixin):
    +    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')
    +        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')
    +
    +    def coerce(self, **kwargs):
    +        self._coerce(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,
    +                     **kwargs)
    +
    +    def instantiate(self, instance_cls, inputs=None):                                               # pylint: disable=arguments-differ
    +        now = datetime.now()
    +
    +        modeling_utils.validate_no_undeclared_inputs(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +        modeling_utils.validate_required_inputs_are_supplied(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +
    +        service = instance_cls(
    +            created_at=now,
    +            updated_at=now,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            service_template=self._model,
    +            inputs=modeling_utils.merge_parameter_values(inputs, self._model.inputs)
    +        )
    +
    +        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,
    +                                                      self._topology.model_storage.plugin.list()):
    +                    plugin = plugin_specification.plugin
    +                    service.plugins[plugin.name] = plugin
    +                else:
    +                    self._topology.report('specified plugin not found: {0}'.format(
    +                        plugin_specification.name), level=self._topology.Issue.EXTERNAL)
    +        service.meta_data = self._topology.instantiate(self._model.meta_data)
    +
    +        for node_template in self._model.node_templates.itervalues():
    +            for _ in range(self._scaling(node_template)['default_instances']):
    +                node = self._topology.instantiate(node_template)
    +                service.nodes[node.name] = node
    +
    +        service.groups = self._topology.instantiate(self._model.group_templates)
    +        service.policies = self._topology.instantiate(self._model.policy_templates)
    +        service.workflows = self._topology.instantiate(self._model.workflow_templates)
    +        service.substitution = self._topology.instantiate(self._model.substitution_template)
    +        service.outputs = self._topology.instantiate(self._model.outputs)
    +
    +        return service
    +
    +    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']):
    +            self._topology.report(
    +                'invalid scaling parameters for node template "{0}": min={min_instances}, max='
    +                '{max_instances}, default={default_instances}'.format(self._model.name, **scaling),
    +                level=self._topology.Issue.BETWEEN_TYPES)
    +
    +        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 dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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)))
    +            if self._model.target_path is not None:
    +                out_stream.write('Target path: {0}'.format(out_stream.literal(
    +                    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)))
    +            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')
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def instantiate(self, instance_cls):
    +        return instance_cls(
    +            name=self._model.name,
    +            type=self._model.type,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            source_path=self._model.source_path,
    +            target_path=self._model.target_path,
    +            repository_url=self._model.repository_url,
    +            repository_credential=self._model.repository_credential,
    +            artifact_template=self._model)
    +
    +    def validate(self):
    +        self._topology.validate(self._model.properties)
    +
    +
    +class CapabilityTemplate(common._TemplateHandlerMixin):
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(self._model.description))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.name)))
    +            out_stream.write(
    +                'Occurrences: {0:d}{1}'.format(
    +                    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'))
    +            if self._model.valid_source_node_types:
    +                out_stream.write('Valid source node types: {0}'.format(
    +                    ', '.join((str(out_stream.type(v.name))
    +                               for v in self._model.valid_source_node_types))))
    +            self._topology.dump(self._model.properties, out_stream, 'Properties')
    +
    +    def coerce(self):
    +        self._topology.coerce(self._model.properties)
    +
    +    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)
    +
    +    def validate(self):
    +        self._topology.validate(self._model.properties)
    +
    +
    +class RequirementTemplate(common._TemplateHandlerMixin):
    +    def dump(self, out_stream):
    +        if self._model.name:
    +            out_stream.write(out_stream.node(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)))
    +            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)))
    +            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)))
    +            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)))
    +            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))
    +            if self._model.relationship_template:
    +                out_stream.write('Relationship:')
    +                with out_stream.indent():
    +                    self._topology.dump(self._model.relationship_template, out_stream)
    +
    +    def coerce(self, **kwargs):
    +        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)
    +
    +    def validate(self):
    +        self._topology.validate(self._model.relationship_template)
    +
    +
    +class GroupTemplate(common._TemplateHandlerMixin):
    +    def dump(self, out_stream):
    +        out_stream.write('Group template: {0}'.format(out_stream.node(self._model.name)))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +            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))))
    +
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.interface_templates,
    +                     **kwargs)
    +
    +    def instantiate(self, instance_cls):
    +        group = instance_cls(
    +            name=self._model.name,
    +            type=self._model.type,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            group_template=self._model)
    +        group.properties = self._topology.instantiate(self._model.properties)
    +        group.interfaces = self._topology.instantiate(self._model.interface_templates)
    +        if self._model.node_templates:
    +            for node_template in self._model.node_templates:
    +                group.nodes += node_template.nodes
    +        return group
    +
    +    def validate(self):
    +        self._validate(self._model.properties,
    +                       self._model.interface_templates)
    +
    +
    +class InterfaceTemplate(common._TemplateHandlerMixin):
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.inputs,
    +                     self._model.operation_templates,
    +                     **kwargs)
    +
    +    def instantiate(self, instance_cls):
    +        interface = instance_cls(
    +            name=self._model.name,
    +            type=self._model.type,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            interface_template=self._model)
    +        interface.inputs = self._topology.instantiate(self._model.inputs)
    +        interface.operations = self._topology.instantiate(self._model.operation_templates)
    +        return interface
    +
    +    def validate(self):
    +        self._validate(self._model.inputs,
    +                       self._model.operation_templates)
    +
    +
    +class NodeTemplate(common._TemplateHandlerMixin):
    +    def dump(self, out_stream):
    +        out_stream.write('Node template: {0}'.format(out_stream.node(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')
    +            self._topology.dump(
    +                self._model.interface_templates, out_stream, 'Interface Templates')
    +            self._topology.dump(
    +                self._model.artifact_templates, out_stream, 'Artifact Templates')
    +            self._topology.dump(
    +                self._model.capability_templates, out_stream, 'Capability Templates')
    +            self._topology.dump(
    +                self._model.requirement_templates, out_stream, 'Requirement Templates')
    +
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interface_templates,
    +                     self._model.artifact_templates,
    +                     self._model.capability_templates,
    +                     self._model.requirement_templates,
    +                     **kwargs)
    +
    +    def instantiate(self, instance_cls):
    +        node = instance_cls(
    +            name=self._model._next_name,
    +            type=self._model.type,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            node_template=self._model
    +        )
    +
    +        node.properties = self._topology.instantiate(self._model.properties)
    +        node.attributes = self._topology.instantiate(self._model.attributes)
    +        node.interfaces = self._topology.instantiate(self._model.interface_templates)
    +        node.artifacts = self._topology.instantiate(self._model.artifact_templates)
    +        node.capabilities = self._topology.instantiate(self._model.capability_templates)
    +
    +        # Default attributes
    +        if 'tosca_name' in node.attributes and node.attributes['tosca_name'].type_name == 'string':
    +            node.attributes['tosca_name'].value = self._model.name
    +        if 'tosca_id' in node.attributes and node.attributes['tosca_id'].type_name == 'string':
    +            node.attributes['tosca_id'].value = node.name
    +
    +        return node
    +
    +    def validate(self):
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interface_templates,
    +                       self._model.artifact_templates,
    +                       self._model.capability_templates,
    +                       self._model.requirement_templates)
    +
    +
    +class PolicyTemplate(common._TemplateHandlerMixin):
    +    def dump(self, out_stream):
    +        out_stream.write('Policy template: {0}'.format(out_stream.node(self._model.name)))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +            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))))
    +            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))))
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def instantiate(self, instance_cls):
    +        policy = instance_cls(
    +            name=self._model.name,
    +            type=self._model.type,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            policy_template=self._model)
    +
    +        policy.properties = self._topology.instantiate(self._model.properties)
    +        if self._model.node_templates:
    +            for node_template in self._model.node_templates:
    +                policy.nodes += node_template.nodes
    +        if self._model.group_templates:
    +            for group_template in self._model.group_templates:
    +                policy.groups += group_template.groups
    +        return policy
    +
    +    def validate(self):
    +        self._topology.validate(self._model.properties)
    +
    +
    +class SubstitutionTemplate(common._TemplateHandlerMixin):
    +
    +    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')
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.mappings, **kwargs)
    +
    +    def instantiate(self, instance_cls):
    +        return instance_cls(node_type=self._model.node_type,
    +                            substitution_template=self._model)
    +
    +    def validate(self):
    +        self._topology.validate(self._model.mappings)
    +
    +
    +class SubstitutionTemplateMapping(common._TemplateHandlerMixin):
    +
    +    def dump(self, out_stream):
    +        if self._topology.capability_template is not None:
    --- End diff --
    
    in all of this method: `_topology` --> `_model`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131084313
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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
    +
    +            # Find target template
    +            target_node_template, target_node_capability = self._find_target(requirement_template)
    +            if target_node_template is not None:
    +                satisfied = self._satisfy_capability(
    +                    target_node_capability, target_node_template, requirement_template)
    +            else:
    +                self._topology.report('requirement "{0}" of node "{1}" has no target node template'.
    +                                      format(requirement_template.name, self._model.name),
    +                                      level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def _satisfy_capability(self, target_node_capability, target_node_template,
    +                            requirement_template):
    +        # Find target nodes
    +        target_nodes = target_node_template.nodes
    +        if target_nodes:
    +            target_node = None
    +            target_capability = None
    +
    +            if target_node_capability is not None:
    +                # Relate to the first target node that has capacity
    +                for node in target_nodes:
    +                    a_target_capability = node.capabilities.get(target_node_capability.name)
    +                    if a_target_capability.relate():
    +                        target_node = node
    +                        target_capability = a_target_capability
    +                        break
    +            else:
    +                # Use first target node
    +                target_node = target_nodes[0]
    +
    +            if target_node is not None:
    +                if requirement_template.relationship_template is not None:
    +                    relationship_model = self._topology.instantiate(
    +                        requirement_template.relationship_template)
    +                else:
    +                    relationship_model = models.Relationship()
    +                relationship_model.name = requirement_template.name
    +                relationship_model.requirement_template = requirement_template
    +                relationship_model.target_node = target_node
    +                relationship_model.target_capability = target_capability
    +                self._model.outbound_relationships.append(relationship_model)
    +                return True
    +            else:
    +                self._topology.report(
    +                    'requirement "{0}" of node "{1}" targets node '
    +                    'template "{2}" but its instantiated nodes do not '
    +                    'have enough capacity'.format(
    +                        requirement_template.name, self._model.name, target_node_template.name),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                return False
    +        else:
    +            self._topology.report(
    +                'requirement "{0}" of node "{1}" targets node template '
    +                '"{2}" but it has no instantiated nodes'.format(
    +                    requirement_template.name, self._model.name, target_node_template.name),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +            return False
    +
    +    def _find_target(self, requirement_template):
    +        # We might already have a specific node 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):
    +                self._topology.report(
    +                    'requirement "{0}" of node template "{1}" is for node '
    +                    'template "{2}" but it does not match constraints'.format(
    +                        requirement_template.name,
    +                        requirement_template.target_node_template.name,
    +                        self._model.node_template.name),
    +                    level=self._topology.Issue.BETWEEN_TYPES)
    +            if (requirement_template.target_capability_type is not None or
    +                    requirement_template.target_capability_name is not None):
    +                target_node_capability = self._get_capability(requirement_template)
    +                if target_node_capability is None:
    +                    return None, None
    +            else:
    +                target_node_capability = None
    +
    +            return requirement_template.target_node_template, target_node_capability
    +
    +        # Find first node that matches the type
    +        elif requirement_template.target_node_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                if requirement_template.target_node_type.get_descendant(
    +                        target_node_template.type.name) is None:
    +                    continue
    +
    +                if not self._model.node_template.is_target_node_template_valid(
    +                        target_node_template):
    +                    continue
    +
    +                target_node_capability = self._get_capability(requirement_template,
    +                                                              target_node_template)
    +
    +                if target_node_capability is None:
    +                    continue
    +
    +                return target_node_template, target_node_capability
    +
    +        elif requirement_template.target_capability_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                target_node_capability = \
    +                    self._get_capability(requirement_template, target_node_template)
    +                if target_node_capability:
    +                    return target_node_template, target_node_capability
    +
    +        return None, None
    +
    +    def _get_capability(self, requirement_template, target_node_template=None):
    +        target_node_template = target_node_template or requirement_template.target_node_template
    +
    +        for capability_template in target_node_template.capability_templates.values():
    +            if self._satisfies_requirement(
    +                    capability_template, requirement_template, target_node_template):
    +                return capability_template
    +
    +        return None
    +
    +    def _satisfies_requirement(
    +            self, capability_template, requirement_template, target_node_template):
    +        # Do we match the required capability type?
    +        if (requirement_template.target_capability_type and
    +                requirement_template.target_capability_type.get_descendant(
    +                    capability_template.type.name) is None):
    +            return False
    +
    +        # Are we in valid_source_node_types?
    +        if capability_template.valid_source_node_types:
    +            for valid_source_node_type in capability_template.valid_source_node_types:
    +                if valid_source_node_type.get_descendant(
    +                        self._model.node_template.type.name) is None:
    +                    return False
    +
    +        # Apply requirement constraints
    +        if requirement_template.target_node_template_constraints:
    +            for node_template_constraint in requirement_template.target_node_template_constraints:
    +                if not node_template_constraint.matches(
    +                        self._model.node_template, target_node_template):
    +                    return False
    +
    +        return True
    +
    +
    +class Operation(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.inputs,
    +                     self._model.configurations,
    +                     self._model.arguments,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._validate(self._model.inputs,
    +                       self._model.configurations,
    +                       self._model.arguments)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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)))
    +            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')
    +            if self._model.executor is not None:
    +                out_stream.write('Executor: {0}'.format(out_stream.literal(self._model.executor)))
    +            if self._model.max_attempts is not None:
    +                out_stream.write('Max attempts: {0}'.format(out_stream.literal(
    +                    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)))
    +            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')
    +            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')
    +
    +    def configure_operations(self):
    +        if self._model.implementation is None and self._model.function is None:
    +            return
    +
    +        if (self._model.interface is not None and
    +                self._model.plugin is None and
    +                self._model.function is None):
    +            # ("interface" is None for workflow operations, which do not currently use "plugin")
    +            # The default (None) plugin is the execution plugin
    +            execution_plugin.instantiation.configure_operation(self._model, self._topology)
    +        else:
    +            # In the future plugins may be able to add their own "configure_operation" hook that
    +            # can validate the configuration and otherwise create specially derived arguments. For
    +            # now, we just send all configuration parameters as arguments without validation.
    +            for key, conf in self._model.configurations.items():
    +                self._model.arguments[key] = self._topology.instantiate(conf.as_argument())
    +
    +        if self._model.interface is not None:
    +            # Send all interface inputs as extra arguments
    +            # ("interface" is None for workflow operations)
    +            # Note that they will override existing arguments of the same names
    +            for key, input in self._model.interface.inputs.items():
    +                self._model.arguments[key] = self._topology.instantiate(input.as_argument())
    +
    +        # Send all inputs as extra arguments
    +        # Note that they will override existing arguments of the same names
    +        for key, input in self._model.inputs.items():
    +            self._model.arguments[key] = self._topology.instantiate(input.as_argument())
    +
    +        # Check for reserved arguments
    +        used_reserved_names = set(decorators.OPERATION_DECORATOR_RESERVED_ARGUMENTS).intersection(
    +            self._model.arguments.keys())
    +        if used_reserved_names:
    +            self._topology.report(
    +                'using reserved arguments in operation "{0}": {1}'.format(
    +                    self._model.name, formatting.string_list_as_string(used_reserved_names)),
    +                level=self._topology.Issue.EXTERNAL)
    +
    +
    +class Policy(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Policy: {0}'.format(out_stream.node(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')
    +            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))
    +            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))
    +
    +
    +class Relationship(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        if self._model.name:
    +            out_stream.write('{0} ->'.format(out_stream.node(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)))
    +            if self._model.target_capability:
    +                out_stream.write('Capability: {0}'.format(out_stream.node(
    +                    self._model.target_capability.name)))
    +            if self._model.type is not None:
    +                out_stream.write('Relationship type: {0}'.format(
    +                    out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Service(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.meta_data,
    +                     self._model.nodes,
    +                     self._model.groups,
    +                     self._model.policies,
    +                     self._model.substitution,
    +                     self._model.inputs,
    +                     self._model.outputs,
    +                     self._model.workflows,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._validate(self._model.meta_data,
    +                       self._model.nodes,
    +                       self._model.groups,
    +                       self._model.policies,
    +                       self._model.substitution,
    +                       self._model.inputs,
    +                       self._model.outputs,
    +                       self._model.workflows)
    +
    +    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')
    +        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')
    +
    +    def configure_operations(self):
    +        for node in self._model.nodes.itervalues():
    +            self._topology.configure_operations(node)
    +        for group in self._model.groups.itervalues():
    +            self._topology.configure_operations(group)
    +        for operation in self._model.workflows.itervalues():
    +            self._topology.configure_operations(operation)
    +
    +    def validate_capabilities(self):
    +        satisfied = True
    +        for node in self._model.nodes.values():
    +            if not self._topology.validate_capabilities(node):
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        return all(self._topology.satisfy_requirements(node)
    +                   for node in self._model.nodes.values())
    +
    +
    +class Substitution(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.mappings, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.mappings)
    +
    +    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')
    +
    +
    +class SubstitutionMapping(common._InstanceHandlerMixin):
    +
    +    def validate(self, **kwargs):
    +        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)),
    +                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)))
    +        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)))
    +
    +
    +class Metadata(common._InstanceHandlerMixin):
    +
    +    def dump(self, out_stream):
    +        out_stream.write('{0}: {1}'.format(
    +            out_stream.property(self._topology.name),
    --- End diff --
    
    `_topology` --> `_model`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131132912
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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
    +
    +            # Find target template
    +            target_node_template, target_node_capability = self._find_target(requirement_template)
    +            if target_node_template is not None:
    +                satisfied = self._satisfy_capability(
    +                    target_node_capability, target_node_template, requirement_template)
    +            else:
    +                self._topology.report('requirement "{0}" of node "{1}" has no target node template'.
    +                                      format(requirement_template.name, self._model.name),
    +                                      level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def _satisfy_capability(self, target_node_capability, target_node_template,
    +                            requirement_template):
    +        # Find target nodes
    +        target_nodes = target_node_template.nodes
    +        if target_nodes:
    +            target_node = None
    +            target_capability = None
    +
    +            if target_node_capability is not None:
    +                # Relate to the first target node that has capacity
    +                for node in target_nodes:
    +                    a_target_capability = node.capabilities.get(target_node_capability.name)
    +                    if a_target_capability.relate():
    +                        target_node = node
    +                        target_capability = a_target_capability
    +                        break
    +            else:
    +                # Use first target node
    +                target_node = target_nodes[0]
    +
    +            if target_node is not None:
    +                if requirement_template.relationship_template is not None:
    +                    relationship_model = self._topology.instantiate(
    +                        requirement_template.relationship_template)
    +                else:
    +                    relationship_model = models.Relationship()
    +                relationship_model.name = requirement_template.name
    +                relationship_model.requirement_template = requirement_template
    +                relationship_model.target_node = target_node
    +                relationship_model.target_capability = target_capability
    +                self._model.outbound_relationships.append(relationship_model)
    +                return True
    +            else:
    +                self._topology.report(
    +                    'requirement "{0}" of node "{1}" targets node '
    +                    'template "{2}" but its instantiated nodes do not '
    +                    'have enough capacity'.format(
    +                        requirement_template.name, self._model.name, target_node_template.name),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                return False
    +        else:
    +            self._topology.report(
    +                'requirement "{0}" of node "{1}" targets node template '
    +                '"{2}" but it has no instantiated nodes'.format(
    +                    requirement_template.name, self._model.name, target_node_template.name),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +            return False
    +
    +    def _find_target(self, requirement_template):
    +        # We might already have a specific node 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):
    +                self._topology.report(
    +                    'requirement "{0}" of node template "{1}" is for node '
    +                    'template "{2}" but it does not match constraints'.format(
    +                        requirement_template.name,
    +                        requirement_template.target_node_template.name,
    +                        self._model.node_template.name),
    +                    level=self._topology.Issue.BETWEEN_TYPES)
    +            if (requirement_template.target_capability_type is not None or
    +                    requirement_template.target_capability_name is not None):
    +                target_node_capability = self._get_capability(requirement_template)
    +                if target_node_capability is None:
    +                    return None, None
    +            else:
    +                target_node_capability = None
    +
    +            return requirement_template.target_node_template, target_node_capability
    +
    +        # Find first node that matches the type
    +        elif requirement_template.target_node_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                if requirement_template.target_node_type.get_descendant(
    +                        target_node_template.type.name) is None:
    +                    continue
    +
    +                if not self._model.node_template.is_target_node_template_valid(
    +                        target_node_template):
    +                    continue
    +
    +                target_node_capability = self._get_capability(requirement_template,
    +                                                              target_node_template)
    +
    +                if target_node_capability is None:
    +                    continue
    +
    +                return target_node_template, target_node_capability
    +
    +        elif requirement_template.target_capability_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                target_node_capability = \
    +                    self._get_capability(requirement_template, target_node_template)
    +                if target_node_capability:
    +                    return target_node_template, target_node_capability
    +
    +        return None, None
    +
    +    def _get_capability(self, requirement_template, target_node_template=None):
    +        target_node_template = target_node_template or requirement_template.target_node_template
    +
    +        for capability_template in target_node_template.capability_templates.values():
    +            if self._satisfies_requirement(
    +                    capability_template, requirement_template, target_node_template):
    +                return capability_template
    +
    +        return None
    +
    +    def _satisfies_requirement(
    +            self, capability_template, requirement_template, target_node_template):
    +        # Do we match the required capability type?
    +        if (requirement_template.target_capability_type and
    +                requirement_template.target_capability_type.get_descendant(
    +                    capability_template.type.name) is None):
    +            return False
    +
    +        # Are we in valid_source_node_types?
    +        if capability_template.valid_source_node_types:
    +            for valid_source_node_type in capability_template.valid_source_node_types:
    +                if valid_source_node_type.get_descendant(
    +                        self._model.node_template.type.name) is None:
    +                    return False
    +
    +        # Apply requirement constraints
    +        if requirement_template.target_node_template_constraints:
    +            for node_template_constraint in requirement_template.target_node_template_constraints:
    +                if not node_template_constraint.matches(
    +                        self._model.node_template, target_node_template):
    +                    return False
    +
    +        return True
    +
    +
    +class Operation(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.inputs,
    +                     self._model.configurations,
    +                     self._model.arguments,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._validate(self._model.inputs,
    +                       self._model.configurations,
    +                       self._model.arguments)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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)))
    +            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')
    +            if self._model.executor is not None:
    +                out_stream.write('Executor: {0}'.format(out_stream.literal(self._model.executor)))
    +            if self._model.max_attempts is not None:
    +                out_stream.write('Max attempts: {0}'.format(out_stream.literal(
    +                    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)))
    +            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')
    +            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')
    +
    +    def configure_operations(self):
    +        if self._model.implementation is None and self._model.function is None:
    +            return
    +
    +        if (self._model.interface is not None and
    +                self._model.plugin is None and
    +                self._model.function is None):
    +            # ("interface" is None for workflow operations, which do not currently use "plugin")
    +            # The default (None) plugin is the execution plugin
    +            execution_plugin.instantiation.configure_operation(self._model, self._topology)
    +        else:
    +            # In the future plugins may be able to add their own "configure_operation" hook that
    +            # can validate the configuration and otherwise create specially derived arguments. For
    +            # now, we just send all configuration parameters as arguments without validation.
    +            for key, conf in self._model.configurations.items():
    +                self._model.arguments[key] = self._topology.instantiate(conf.as_argument())
    +
    +        if self._model.interface is not None:
    +            # Send all interface inputs as extra arguments
    +            # ("interface" is None for workflow operations)
    +            # Note that they will override existing arguments of the same names
    +            for key, input in self._model.interface.inputs.items():
    +                self._model.arguments[key] = self._topology.instantiate(input.as_argument())
    +
    +        # Send all inputs as extra arguments
    +        # Note that they will override existing arguments of the same names
    +        for key, input in self._model.inputs.items():
    +            self._model.arguments[key] = self._topology.instantiate(input.as_argument())
    +
    +        # Check for reserved arguments
    +        used_reserved_names = set(decorators.OPERATION_DECORATOR_RESERVED_ARGUMENTS).intersection(
    +            self._model.arguments.keys())
    +        if used_reserved_names:
    +            self._topology.report(
    +                'using reserved arguments in operation "{0}": {1}'.format(
    +                    self._model.name, formatting.string_list_as_string(used_reserved_names)),
    +                level=self._topology.Issue.EXTERNAL)
    +
    +
    +class Policy(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Policy: {0}'.format(out_stream.node(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')
    +            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))
    +            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))
    +
    +
    +class Relationship(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        if self._model.name:
    +            out_stream.write('{0} ->'.format(out_stream.node(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)))
    +            if self._model.target_capability:
    +                out_stream.write('Capability: {0}'.format(out_stream.node(
    +                    self._model.target_capability.name)))
    +            if self._model.type is not None:
    +                out_stream.write('Relationship type: {0}'.format(
    +                    out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Service(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.meta_data,
    +                     self._model.nodes,
    +                     self._model.groups,
    +                     self._model.policies,
    +                     self._model.substitution,
    +                     self._model.inputs,
    +                     self._model.outputs,
    +                     self._model.workflows,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._validate(self._model.meta_data,
    +                       self._model.nodes,
    +                       self._model.groups,
    +                       self._model.policies,
    +                       self._model.substitution,
    +                       self._model.inputs,
    +                       self._model.outputs,
    +                       self._model.workflows)
    +
    +    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')
    +        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')
    +
    +    def configure_operations(self):
    +        for node in self._model.nodes.itervalues():
    +            self._topology.configure_operations(node)
    +        for group in self._model.groups.itervalues():
    +            self._topology.configure_operations(group)
    +        for operation in self._model.workflows.itervalues():
    +            self._topology.configure_operations(operation)
    +
    +    def validate_capabilities(self):
    +        satisfied = True
    +        for node in self._model.nodes.values():
    +            if not self._topology.validate_capabilities(node):
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        return all(self._topology.satisfy_requirements(node)
    +                   for node in self._model.nodes.values())
    +
    +
    +class Substitution(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.mappings, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.mappings)
    +
    +    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')
    +
    +
    +class SubstitutionMapping(common._InstanceHandlerMixin):
    +
    +    def validate(self, **kwargs):
    +        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)),
    +                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)))
    +        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)))
    +
    +
    +class Metadata(common._InstanceHandlerMixin):
    +
    +    def dump(self, out_stream):
    +        out_stream.write('{0}: {1}'.format(
    +            out_stream.property(self._topology.name),
    +            out_stream.literal(self._topology.value)))
    +
    +    def coerce(self):
    +        pass
    +
    +    def instantiate(self, instance_cls, **kwargs):
    +        return instance_cls(name=self._model.name, value=self._model.value)
    +
    +    def validate(self):
    +        pass
    +
    +
    +class _Parameter(common._InstanceHandlerMixin):
    +
    +    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)))
    +        else:
    +            out_stream.write('{0}: {1}'.format(
    +                out_stream.property(self._model.name),
    +                out_stream.literal(formatting.as_raw(self._model.value))))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(self._model.description))
    +
    +    def instantiate(self, instance_cls, **kwargs):
    +        return instance_cls(
    +            name=self._model.name,  # pylint: disable=unexpected-keyword-arg
    +            type_name=self._model.type_name,
    +            _value=self._model._value,
    +            description=self._model.description
    +        )
    +
    +    def validate(self):
    +        pass
    +
    --- End diff --
    
    added


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130331901
  
    --- Diff: extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py ---
    @@ -497,8 +497,8 @@ def get(name, default=None):
     
     
     def create_workflow_operation_template_model(context, service_template, policy):
    -    model = OperationTemplate(name=policy._name,
    -                              service_template=service_template)
    +    model = OperationTemplate(name=policy._name)
    +    service_template.workflow_templates[model.name] = model
    --- End diff --
    
    since we use backpopulates, these fields are populated upon commit, we get a weird (temporary) behavior where in previous code `service_template.workflows` is a dict which has `None` as key for the value of model.
    
    This needs to be addressed throughout the code.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130906157
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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
    +
    +            # Find target template
    +            target_node_template, target_node_capability = self._find_target(requirement_template)
    +            if target_node_template is not None:
    +                satisfied = self._satisfy_capability(
    +                    target_node_capability, target_node_template, requirement_template)
    +            else:
    +                self._topology.report('requirement "{0}" of node "{1}" has no target node template'.
    +                                      format(requirement_template.name, self._model.name),
    +                                      level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def _satisfy_capability(self, target_node_capability, target_node_template,
    +                            requirement_template):
    +        # Find target nodes
    +        target_nodes = target_node_template.nodes
    +        if target_nodes:
    +            target_node = None
    +            target_capability = None
    +
    +            if target_node_capability is not None:
    +                # Relate to the first target node that has capacity
    +                for node in target_nodes:
    +                    a_target_capability = node.capabilities.get(target_node_capability.name)
    +                    if a_target_capability.relate():
    +                        target_node = node
    +                        target_capability = a_target_capability
    +                        break
    +            else:
    +                # Use first target node
    +                target_node = target_nodes[0]
    +
    +            if target_node is not None:
    +                if requirement_template.relationship_template is not None:
    +                    relationship_model = self._topology.instantiate(
    +                        requirement_template.relationship_template)
    +                else:
    +                    relationship_model = models.Relationship()
    +                relationship_model.name = requirement_template.name
    +                relationship_model.requirement_template = requirement_template
    +                relationship_model.target_node = target_node
    +                relationship_model.target_capability = target_capability
    +                self._model.outbound_relationships.append(relationship_model)
    +                return True
    +            else:
    +                self._topology.report(
    +                    'requirement "{0}" of node "{1}" targets node '
    +                    'template "{2}" but its instantiated nodes do not '
    +                    'have enough capacity'.format(
    +                        requirement_template.name, self._model.name, target_node_template.name),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                return False
    +        else:
    +            self._topology.report(
    +                'requirement "{0}" of node "{1}" targets node template '
    +                '"{2}" but it has no instantiated nodes'.format(
    +                    requirement_template.name, self._model.name, target_node_template.name),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +            return False
    +
    +    def _find_target(self, requirement_template):
    +        # We might already have a specific node 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):
    +                self._topology.report(
    +                    'requirement "{0}" of node template "{1}" is for node '
    +                    'template "{2}" but it does not match constraints'.format(
    +                        requirement_template.name,
    +                        requirement_template.target_node_template.name,
    +                        self._model.node_template.name),
    +                    level=self._topology.Issue.BETWEEN_TYPES)
    +            if (requirement_template.target_capability_type is not None or
    +                    requirement_template.target_capability_name is not None):
    +                target_node_capability = self._get_capability(requirement_template)
    +                if target_node_capability is None:
    +                    return None, None
    +            else:
    +                target_node_capability = None
    +
    +            return requirement_template.target_node_template, target_node_capability
    +
    +        # Find first node that matches the type
    +        elif requirement_template.target_node_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                if requirement_template.target_node_type.get_descendant(
    +                        target_node_template.type.name) is None:
    +                    continue
    +
    +                if not self._model.node_template.is_target_node_template_valid(
    +                        target_node_template):
    +                    continue
    +
    +                target_node_capability = self._get_capability(requirement_template,
    +                                                              target_node_template)
    +
    +                if target_node_capability is None:
    +                    continue
    +
    +                return target_node_template, target_node_capability
    +
    --- End diff --
    
    Document this case as well


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130827261
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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)
    +
    +    def validate(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).validate(**kwargs)
    +
    +    def dump(self, model, out_stream=None, section_name=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 isinstance(model, dict):
    +            if str(out_stream):
    +                with out_stream.indent():
    +                    return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +            else:
    +                return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +
    +        elif isinstance(model, list):
    +            for value in model:
    +                self.dump(value, out_stream=out_stream, **kwargs)
    +
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            _handler(self, model).dump(out_stream=out_stream, **kwargs)
    +
    +        return out_stream
    +
    +    def dump_graph(self, service, **kwargs):
    +        out_stream = console.TopologyStylizer()
    +        for node in service.nodes.itervalues():
    +            if not node.inbound_relationships:
    +                self._dump_graph_node(out_stream, node)
    +        return out_stream
    +
    +    def _dump_graph_node(self, out_stream, node, capability=None):
    +        out_stream.write(out_stream.node(node.name))
    +        if capability is not None:
    +            out_stream.write('{0} ({1})'.format(out_stream.property(capability.name),
    +                                                out_stream.type(capability.type.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:
    +                        out_stream.write('-> {0} ({1})'.format(
    +                            relationship_name, out_stream.type(relationship_model.type.name)))
    +                    else:
    +                        out_stream.write('-> {0}'.format(relationship_name))
    +                    with out_stream.indent(3):
    +                        self._dump_graph_node(out_stream,
    +                                              relationship_model.target_node,
    +                                              relationship_model.target_capability)
    +
    +    def coerce(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).coerce(**kwargs)
    +
    +    def dump_types(self, service_template, out_stream=None):
    +        out_stream = out_stream or console.TopologyStylizer()
    +        self.dump(service_template.node_types, out_stream, 'Node types')
    +        self.dump(service_template.group_types, out_stream, 'Group types')
    +        self.dump(service_template.capability_types, out_stream, 'Capability types')
    +        self.dump(service_template.relationship_types, out_stream, 'Relationship types')
    +        self.dump(service_template.policy_types, out_stream, 'Policy types')
    +        self.dump(service_template.artifact_types, out_stream, 'Artifact types')
    +        self.dump(service_template.interface_types, out_stream, 'Interface types')
    +
    +        return str(out_stream)
    +
    +    def satisfy_requirements(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.satisfy_requirements(model.values())
    +        elif isinstance(model, list):
    +            return all(self.satisfy_requirements(value) for value in model)
    --- End diff --
    
    Why the `all` here?
    And the `return`?
    In all relevant places.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130904352
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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
    +
    +            # Find target template
    +            target_node_template, target_node_capability = self._find_target(requirement_template)
    +            if target_node_template is not None:
    +                satisfied = self._satisfy_capability(
    +                    target_node_capability, target_node_template, requirement_template)
    +            else:
    +                self._topology.report('requirement "{0}" of node "{1}" has no target node template'.
    +                                      format(requirement_template.name, self._model.name),
    +                                      level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def _satisfy_capability(self, target_node_capability, target_node_template,
    +                            requirement_template):
    +        # Find target nodes
    +        target_nodes = target_node_template.nodes
    +        if target_nodes:
    +            target_node = None
    +            target_capability = None
    +
    +            if target_node_capability is not None:
    +                # Relate to the first target node that has capacity
    +                for node in target_nodes:
    +                    a_target_capability = node.capabilities.get(target_node_capability.name)
    +                    if a_target_capability.relate():
    +                        target_node = node
    +                        target_capability = a_target_capability
    +                        break
    +            else:
    +                # Use first target node
    +                target_node = target_nodes[0]
    +
    +            if target_node is not None:
    +                if requirement_template.relationship_template is not None:
    +                    relationship_model = self._topology.instantiate(
    +                        requirement_template.relationship_template)
    +                else:
    +                    relationship_model = models.Relationship()
    +                relationship_model.name = requirement_template.name
    +                relationship_model.requirement_template = requirement_template
    +                relationship_model.target_node = target_node
    +                relationship_model.target_capability = target_capability
    +                self._model.outbound_relationships.append(relationship_model)
    +                return True
    +            else:
    +                self._topology.report(
    +                    'requirement "{0}" of node "{1}" targets node '
    +                    'template "{2}" but its instantiated nodes do not '
    +                    'have enough capacity'.format(
    +                        requirement_template.name, self._model.name, target_node_template.name),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                return False
    +        else:
    +            self._topology.report(
    +                'requirement "{0}" of node "{1}" targets node template '
    +                '"{2}" but it has no instantiated nodes'.format(
    +                    requirement_template.name, self._model.name, target_node_template.name),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +            return False
    +
    +    def _find_target(self, requirement_template):
    +        # We might already have a specific node template, so we'll just verify it
    --- End diff --
    
    We might already have a specified node template from the requirement template [...]


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130823646
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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)
    +
    +    def validate(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).validate(**kwargs)
    +
    +    def dump(self, model, out_stream=None, section_name=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 isinstance(model, dict):
    +            if str(out_stream):
    +                with out_stream.indent():
    +                    return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +            else:
    +                return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +
    +        elif isinstance(model, list):
    +            for value in model:
    +                self.dump(value, out_stream=out_stream, **kwargs)
    +
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            _handler(self, model).dump(out_stream=out_stream, **kwargs)
    +
    +        return out_stream
    +
    +    def dump_graph(self, service, **kwargs):
    --- End diff --
    
    no need for `**kwargs`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132140607
  
    --- Diff: aria/utils/console.py ---
    @@ -31,51 +31,51 @@
     
     
     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(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):
    --- End diff --
    
    Is this even used?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130595794
  
    --- Diff: aria/orchestrator/topology/common.py ---
    @@ -0,0 +1,52 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +
    +class _Handler(object):
    +    def __init__(self, topology, template):
    +        self._topology = topology
    +        self._model = template
    +
    +    def _coerce(self, *templates, **kwargs):
    +        for template in templates:
    +            self._topology.coerce(template)
    +
    +    def coerce(self):
    +        pass
    +
    +    def validate(self, **kwargs):
    +        pass
    +
    +    def _validate(self, *templates, **kwargs):
    +        for template in templates:
    +            self._topology.validate(template)
    +
    +    def dump(self, out_stream):
    +        pass
    +
    +
    +class _TemplateHandlerMixin(_Handler):
    +
    +    def instantiate(self, instance_cls):
    +        raise NotImplementedError
    +
    +
    +class _InstanceHandlerMixin(_Handler):
    +    pass
    +
    +
    +class _OperatorHolderHandlerMixin(_Handler):
    --- End diff --
    
    `OperationHolderHandlerMixin`, and please think of a better word than `Holder`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131132996
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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
    +
    +            # Find target template
    +            target_node_template, target_node_capability = self._find_target(requirement_template)
    +            if target_node_template is not None:
    +                satisfied = self._satisfy_capability(
    +                    target_node_capability, target_node_template, requirement_template)
    +            else:
    +                self._topology.report('requirement "{0}" of node "{1}" has no target node template'.
    +                                      format(requirement_template.name, self._model.name),
    +                                      level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def _satisfy_capability(self, target_node_capability, target_node_template,
    +                            requirement_template):
    +        # Find target nodes
    +        target_nodes = target_node_template.nodes
    +        if target_nodes:
    +            target_node = None
    +            target_capability = None
    +
    +            if target_node_capability is not None:
    +                # Relate to the first target node that has capacity
    +                for node in target_nodes:
    +                    a_target_capability = node.capabilities.get(target_node_capability.name)
    +                    if a_target_capability.relate():
    +                        target_node = node
    +                        target_capability = a_target_capability
    +                        break
    +            else:
    +                # Use first target node
    +                target_node = target_nodes[0]
    +
    +            if target_node is not None:
    +                if requirement_template.relationship_template is not None:
    +                    relationship_model = self._topology.instantiate(
    +                        requirement_template.relationship_template)
    +                else:
    +                    relationship_model = models.Relationship()
    +                relationship_model.name = requirement_template.name
    +                relationship_model.requirement_template = requirement_template
    +                relationship_model.target_node = target_node
    +                relationship_model.target_capability = target_capability
    +                self._model.outbound_relationships.append(relationship_model)
    +                return True
    +            else:
    +                self._topology.report(
    +                    'requirement "{0}" of node "{1}" targets node '
    +                    'template "{2}" but its instantiated nodes do not '
    +                    'have enough capacity'.format(
    +                        requirement_template.name, self._model.name, target_node_template.name),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                return False
    +        else:
    +            self._topology.report(
    +                'requirement "{0}" of node "{1}" targets node template '
    +                '"{2}" but it has no instantiated nodes'.format(
    +                    requirement_template.name, self._model.name, target_node_template.name),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +            return False
    +
    +    def _find_target(self, requirement_template):
    +        # We might already have a specific node 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):
    +                self._topology.report(
    +                    'requirement "{0}" of node template "{1}" is for node '
    +                    'template "{2}" but it does not match constraints'.format(
    +                        requirement_template.name,
    +                        requirement_template.target_node_template.name,
    +                        self._model.node_template.name),
    +                    level=self._topology.Issue.BETWEEN_TYPES)
    +            if (requirement_template.target_capability_type is not None or
    +                    requirement_template.target_capability_name is not None):
    +                target_node_capability = self._get_capability(requirement_template)
    +                if target_node_capability is None:
    +                    return None, None
    +            else:
    +                target_node_capability = None
    +
    +            return requirement_template.target_node_template, target_node_capability
    +
    +        # Find first node that matches the type
    +        elif requirement_template.target_node_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                if requirement_template.target_node_type.get_descendant(
    +                        target_node_template.type.name) is None:
    +                    continue
    +
    +                if not self._model.node_template.is_target_node_template_valid(
    +                        target_node_template):
    +                    continue
    +
    +                target_node_capability = self._get_capability(requirement_template,
    +                                                              target_node_template)
    +
    +                if target_node_capability is None:
    +                    continue
    +
    +                return target_node_template, target_node_capability
    +
    --- End diff --
    
    documented


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130597368
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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
    +
    +            # Find target template
    +            target_node_template, target_node_capability = self._find_target(requirement_template)
    +            if target_node_template is not None:
    +                satisfied = self._satisfy_capability(
    +                    target_node_capability, target_node_template, requirement_template)
    +            else:
    +                self._topology.report('requirement "{0}" of node "{1}" has no target node template'.
    +                                      format(requirement_template.name, self._model.name),
    +                                      level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def _satisfy_capability(self, target_node_capability, target_node_template,
    +                            requirement_template):
    +        # Find target nodes
    +        target_nodes = target_node_template.nodes
    +        if target_nodes:
    +            target_node = None
    +            target_capability = None
    +
    +            if target_node_capability is not None:
    +                # Relate to the first target node that has capacity
    +                for node in target_nodes:
    +                    a_target_capability = node.capabilities.get(target_node_capability.name)
    +                    if a_target_capability.relate():
    +                        target_node = node
    +                        target_capability = a_target_capability
    +                        break
    +            else:
    +                # Use first target node
    +                target_node = target_nodes[0]
    +
    +            if target_node is not None:
    +                if requirement_template.relationship_template is not None:
    +                    relationship_model = self._topology.instantiate(
    +                        requirement_template.relationship_template)
    +                else:
    +                    relationship_model = models.Relationship()
    +                relationship_model.name = requirement_template.name
    +                relationship_model.requirement_template = requirement_template
    +                relationship_model.target_node = target_node
    +                relationship_model.target_capability = target_capability
    +                self._model.outbound_relationships.append(relationship_model)
    +                return True
    +            else:
    +                self._topology.report(
    +                    'requirement "{0}" of node "{1}" targets node '
    +                    'template "{2}" but its instantiated nodes do not '
    +                    'have enough capacity'.format(
    +                        requirement_template.name, self._model.name, target_node_template.name),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                return False
    +        else:
    +            self._topology.report(
    +                'requirement "{0}" of node "{1}" targets node template '
    +                '"{2}" but it has no instantiated nodes'.format(
    +                    requirement_template.name, self._model.name, target_node_template.name),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +            return False
    +
    +    def _find_target(self, requirement_template):
    +        # We might already have a specific node 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):
    +                self._topology.report(
    +                    'requirement "{0}" of node template "{1}" is for node '
    +                    'template "{2}" but it does not match constraints'.format(
    +                        requirement_template.name,
    +                        requirement_template.target_node_template.name,
    +                        self._model.node_template.name),
    +                    level=self._topology.Issue.BETWEEN_TYPES)
    +            if (requirement_template.target_capability_type is not None or
    +                    requirement_template.target_capability_name is not None):
    +                target_node_capability = self._get_capability(requirement_template)
    +                if target_node_capability is None:
    +                    return None, None
    +            else:
    +                target_node_capability = None
    +
    +            return requirement_template.target_node_template, target_node_capability
    +
    +        # Find first node that matches the type
    +        elif requirement_template.target_node_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                if requirement_template.target_node_type.get_descendant(
    +                        target_node_template.type.name) is None:
    +                    continue
    +
    +                if not self._model.node_template.is_target_node_template_valid(
    +                        target_node_template):
    +                    continue
    +
    +                target_node_capability = self._get_capability(requirement_template,
    +                                                              target_node_template)
    +
    +                if target_node_capability is None:
    +                    continue
    +
    +                return target_node_template, target_node_capability
    +
    +        elif requirement_template.target_capability_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                target_node_capability = \
    +                    self._get_capability(requirement_template, target_node_template)
    +                if target_node_capability:
    +                    return target_node_template, target_node_capability
    +
    +        return None, None
    +
    +    def _get_capability(self, requirement_template, target_node_template=None):
    +        target_node_template = target_node_template or requirement_template.target_node_template
    +
    +        for capability_template in target_node_template.capability_templates.values():
    +            if self._satisfies_requirement(
    +                    capability_template, requirement_template, target_node_template):
    +                return capability_template
    +
    +        return None
    +
    +    def _satisfies_requirement(
    +            self, capability_template, requirement_template, target_node_template):
    +        # Do we match the required capability type?
    +        if (requirement_template.target_capability_type and
    +                requirement_template.target_capability_type.get_descendant(
    +                    capability_template.type.name) is None):
    +            return False
    +
    +        # Are we in valid_source_node_types?
    +        if capability_template.valid_source_node_types:
    +            for valid_source_node_type in capability_template.valid_source_node_types:
    +                if valid_source_node_type.get_descendant(
    +                        self._model.node_template.type.name) is None:
    +                    return False
    +
    +        # Apply requirement constraints
    +        if requirement_template.target_node_template_constraints:
    +            for node_template_constraint in requirement_template.target_node_template_constraints:
    +                if not node_template_constraint.matches(
    +                        self._model.node_template, target_node_template):
    +                    return False
    +
    +        return True
    +
    +
    +class Operation(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.inputs,
    +                     self._model.configurations,
    +                     self._model.arguments,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._validate(self._model.inputs,
    +                       self._model.configurations,
    +                       self._model.arguments)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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)))
    +            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')
    +            if self._model.executor is not None:
    +                out_stream.write('Executor: {0}'.format(out_stream.literal(self._model.executor)))
    +            if self._model.max_attempts is not None:
    +                out_stream.write('Max attempts: {0}'.format(out_stream.literal(
    +                    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)))
    +            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')
    +            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')
    +
    +    def configure_operations(self):
    +        if self._model.implementation is None and self._model.function is None:
    +            return
    +
    +        if (self._model.interface is not None and
    +                self._model.plugin is None and
    +                self._model.function is None):
    +            # ("interface" is None for workflow operations, which do not currently use "plugin")
    +            # The default (None) plugin is the execution plugin
    +            execution_plugin.instantiation.configure_operation(self._model, self._topology)
    +        else:
    +            # In the future plugins may be able to add their own "configure_operation" hook that
    +            # can validate the configuration and otherwise create specially derived arguments. For
    +            # now, we just send all configuration parameters as arguments without validation.
    +            for key, conf in self._model.configurations.items():
    +                self._model.arguments[key] = self._topology.instantiate(conf.as_argument())
    +
    +        if self._model.interface is not None:
    +            # Send all interface inputs as extra arguments
    +            # ("interface" is None for workflow operations)
    +            # Note that they will override existing arguments of the same names
    +            for key, input in self._model.interface.inputs.items():
    +                self._model.arguments[key] = self._topology.instantiate(input.as_argument())
    +
    +        # Send all inputs as extra arguments
    +        # Note that they will override existing arguments of the same names
    +        for key, input in self._model.inputs.items():
    +            self._model.arguments[key] = self._topology.instantiate(input.as_argument())
    +
    +        # Check for reserved arguments
    +        used_reserved_names = set(decorators.OPERATION_DECORATOR_RESERVED_ARGUMENTS).intersection(
    +            self._model.arguments.keys())
    +        if used_reserved_names:
    +            self._topology.report(
    +                'using reserved arguments in operation "{0}": {1}'.format(
    +                    self._model.name, formatting.string_list_as_string(used_reserved_names)),
    +                level=self._topology.Issue.EXTERNAL)
    +
    +
    +class Policy(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Policy: {0}'.format(out_stream.node(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')
    +            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))
    +            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))
    +
    +
    +class Relationship(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        if self._model.name:
    +            out_stream.write('{0} ->'.format(out_stream.node(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)))
    +            if self._model.target_capability:
    +                out_stream.write('Capability: {0}'.format(out_stream.node(
    +                    self._model.target_capability.name)))
    +            if self._model.type is not None:
    +                out_stream.write('Relationship type: {0}'.format(
    +                    out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Service(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.meta_data,
    +                     self._model.nodes,
    +                     self._model.groups,
    +                     self._model.policies,
    +                     self._model.substitution,
    +                     self._model.inputs,
    +                     self._model.outputs,
    +                     self._model.workflows,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._validate(self._model.meta_data,
    +                       self._model.nodes,
    +                       self._model.groups,
    +                       self._model.policies,
    +                       self._model.substitution,
    +                       self._model.inputs,
    +                       self._model.outputs,
    +                       self._model.workflows)
    +
    +    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')
    +        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')
    +
    +    def configure_operations(self):
    +        for node in self._model.nodes.itervalues():
    +            self._topology.configure_operations(node)
    +        for group in self._model.groups.itervalues():
    +            self._topology.configure_operations(group)
    +        for operation in self._model.workflows.itervalues():
    +            self._topology.configure_operations(operation)
    +
    +    def validate_capabilities(self):
    +        satisfied = True
    +        for node in self._model.nodes.values():
    +            if not self._topology.validate_capabilities(node):
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        return all(self._topology.satisfy_requirements(node)
    +                   for node in self._model.nodes.values())
    +
    +
    +class Substitution(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.mappings, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.mappings)
    +
    +    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')
    +
    +
    +class SubstitutionMapping(common._InstanceHandlerMixin):
    +
    +    def validate(self, **kwargs):
    +        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)),
    +                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)))
    +        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)))
    +
    +
    +class Metadata(common._InstanceHandlerMixin):
    +
    +    def dump(self, out_stream):
    +        out_stream.write('{0}: {1}'.format(
    +            out_stream.property(self._topology.name),
    +            out_stream.literal(self._topology.value)))
    +
    +    def coerce(self):
    +        pass
    +
    +    def instantiate(self, instance_cls, **kwargs):
    +        return instance_cls(name=self._model.name, value=self._model.value)
    +
    +    def validate(self):
    +        pass
    +
    +
    +class _Parameter(common._InstanceHandlerMixin):
    +
    +    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)))
    +        else:
    +            out_stream.write('{0}: {1}'.format(
    +                out_stream.property(self._model.name),
    +                out_stream.literal(formatting.as_raw(self._model.value))))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(self._model.description))
    +
    +    def instantiate(self, instance_cls, **kwargs):
    +        return instance_cls(
    +            name=self._model.name,  # pylint: disable=unexpected-keyword-arg
    +            type_name=self._model.type_name,
    +            _value=self._model._value,
    +            description=self._model.description
    +        )
    +
    +    def validate(self):
    +        pass
    +
    --- End diff --
    
    Missing `coerce_values`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130330669
  
    --- Diff: aria/cli/commands/services.py ---
    @@ -20,6 +20,7 @@
     import os
     from StringIO import StringIO
     
    +from aria.orchestrator.topology import Topology
    --- End diff --
    
    import module


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132123698
  
    --- Diff: aria/modeling/utils.py ---
    @@ -175,7 +175,7 @@ def init(*args, **kwargs):
         return cls
     
     
    -def get_class_from_relationship(property):
    +def _get_class_from_sql_relationship(property):
    --- End diff --
    
    a better name than property, which could be misleading. Maybe `field`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130820499
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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)
    +
    +    def validate(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    --- End diff --
    
    do you need to pass down `**kwargs`?
    Check all relevant places.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132137742
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -50,28 +49,33 @@ class Topology(issue.Reporter):
             models.Type: models.Type
         }
     
    -    def __init__(self, model_storage=None, *args, **kwargs):
    -        # TODO: model storage is required only for the list of plugins, can we get it
    -        # somewhere else?
    +    def __init__(self, *args, **kwargs):
             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
    --- End diff --
    
    modukle --> module.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130601638
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    --- End diff --
    
    issue.Reporter should be a mixin, or `Topology` should hold an instance of this class and not inherit from it.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130604096
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # somewhere else?
    +        super(Topology, self).__init__(*args, **kwargs)
    +        self._model_storage = model_storage
    +        self._handlers = dict(self._init_handlers(instance_handler),
    --- End diff --
    
    maybe name it something in the likes of `models_to_handlers`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130602178
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    --- End diff --
    
    Should it be here if the is no instance model of it?
    Maybe it add redundant `None` checks down the calls...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130585942
  
    --- Diff: aria/core.py ---
    @@ -67,31 +68,25 @@ def delete_service_template(self, service_template_id):
             self.resource_storage.service_template.delete(entry_id=str(service_template.id))
     
         def create_service(self, service_template_id, inputs, service_name=None):
    -
             service_template = self.model_storage.service_template.get(service_template_id)
     
    -        # creating an empty ConsumptionContext, initiating a threadlocal context
    -        context = consumption.ConsumptionContext()
    -
             storage_session = self.model_storage._all_api_kwargs['session']
             # setting no autoflush for the duration of instantiation - this helps avoid dependency
             # constraints as they're being set up
             with storage_session.no_autoflush:
    -            service = service_template.instantiate(None, self.model_storage, inputs=inputs)
    -
    -            consumption.ConsumerChain(
    -                context,
    -                (
    -                    consumption.CoerceServiceInstanceValues,
    --- End diff --
    
    If some of these consumers are not used anymore, add a comment explaining that, or consider removing them.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132127179
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -527,78 +539,82 @@ def satisfy_requirements(self):
                        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 coerce(self, **kwargs):
    +        pass
    +
    +    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),
    --- End diff --
    
    The second `node_style` should be just `node`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132125166
  
    --- Diff: aria/orchestrator/topology/common.py ---
    @@ -14,39 +14,53 @@
     # 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):
    +    """
    +    Base handler for template based models
    +    """
     
    -    def instantiate(self, instance_cls):
    +    def instantiate(self, instance_cls, **kwargs):
             raise NotImplementedError
     
     
    -class _InstanceHandlerMixin(_Handler):
    -    pass
    +class InstanceHandlerBase(HandlerBase):
    +    """
    +    Base handler for instance based models
    +
    +    """
    +    def validate(self, **kwargs):
    +        raise NotImplementedError
    +
    +    def coerce(self, **kwargs):
    +        raise NotImplementedError
    +
    +    def dump(self, out_stream):
    +        raise NotImplementedError
     
     
    -class _OperatorHolderHandlerMixin(_Handler):
    +class ActorHandlerBase(HandlerBase):
    --- End diff --
    
    Explain what Actor mean in this context. Like in the base classes.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130330792
  
    --- Diff: aria/modeling/functions.py ---
    @@ -103,10 +102,12 @@ def evaluate(value, container_holder, report_issues=False): # pylint: disable=to
                         final = False
             except exceptions.CannotEvaluateFunctionException:
                 pass
    -        except InvalidValueError as e:
    +        except InvalidValueError:
    --- End diff --
    
    revert


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca issue #189: ARIA-174 Refactor instantiation phase

Posted by asfgit <gi...@git.apache.org>.
Github user asfgit commented on the issue:

    https://github.com/apache/incubator-ariatosca/pull/189
  
    Can one of the admins verify this patch?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132167947
  
    --- Diff: aria/orchestrator/topology/template_handler.py ---
    @@ -47,7 +47,7 @@ def coerce(self, **kwargs):
                          self._model.workflow_templates,
                          **kwargs)
     
    -    def instantiate(self, instance_cls, inputs=None, model_storage=None):                           # pylint: disable=arguments-differ
    +    def instantiate(self, instance_cls, inputs=None, plugins=None):                                 # pylint: disable=arguments-differ
    --- End diff --
    
    remove the extra whitespaces.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132136296
  
    --- Diff: aria/orchestrator/topology/template_handler.py ---
    @@ -584,13 +588,20 @@ def instantiate(self, instance_cls):
     
             return operation
     
    -    def validate(self):
    +    def validate(self, **kwargs):
             self._validate(self._model.inputs,
    -                       self._model.configurations)
    +                       self._model.configurations,
    +                       **kwargs)
    +
    +
    +class PluginSpecification(common.TemplateHandlerBase):
    --- End diff --
    
    Consider inheriting from `HandlerBase`, since `PluginSpecification` isn't exactly a template.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130868151
  
    --- Diff: aria/utils/__init__.py ---
    @@ -16,3 +16,50 @@
     """
     General-purpose utilities package.
     """
    +
    +from . import (
    +    archive,
    +    argparse,
    +    caching,
    +    collections,
    +    console,
    +    exceptions,
    +    file,
    +    formatting,
    +    http,
    +    imports,
    +    openclose,
    +    plugin,
    +    process,
    +    specification,
    +    threading,
    +    type,
    +    uris,
    +    uuid,
    +    validation,
    +    versions
    +)
    +
    +
    +__all__ = (
    --- End diff --
    
    Do you really need that `__all__`? As far as I know, it is only useful when you do an `import *`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131133331
  
    --- Diff: aria/orchestrator/execution_plugin/instantiation.py ---
    @@ -110,20 +105,17 @@ def _configure_remote(operation):
     
         # Make sure we have a user
         if fabric_env.get('user') is None:
    -        context = ConsumptionContext.get_thread_local()
    -        context.validation.report('must configure "ssh.user" for "{0}"'
    -                                  .format(operation.implementation),
    -                                  level=validation.Issue.BETWEEN_TYPES)
    +        reporter.report('must configure "ssh.user" for "{0}"'.format(operation.implementation),
    --- End diff --
    
    when using the consumer, the issues are appended to the context validation reports


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130858804
  
    --- Diff: aria/parser/consumption/modeling.py ---
    @@ -74,7 +75,7 @@ def dump(self):
                 raw = self.context.modeling.template_as_raw
                 self.context.write(json_dumps(raw, indent=indent))
             else:
    -            self.context.modeling.template.dump()
    +            self.topology.dump(self.context.modeling.template)
    --- End diff --
    
    should there be `context.write` here?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130600048
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    --- End diff --
    
    node --> `node_style`?
    And in other places and model names as well.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132127229
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -527,78 +539,82 @@ def satisfy_requirements(self):
                        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 coerce(self, **kwargs):
    +        pass
    +
    +    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)),
    --- End diff --
    
    `node_style` should be just `node`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131126610
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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
    +
    +            # Find target template
    +            target_node_template, target_node_capability = self._find_target(requirement_template)
    +            if target_node_template is not None:
    +                satisfied = self._satisfy_capability(
    +                    target_node_capability, target_node_template, requirement_template)
    +            else:
    +                self._topology.report('requirement "{0}" of node "{1}" has no target node template'.
    +                                      format(requirement_template.name, self._model.name),
    +                                      level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def _satisfy_capability(self, target_node_capability, target_node_template,
    +                            requirement_template):
    +        # Find target nodes
    +        target_nodes = target_node_template.nodes
    +        if target_nodes:
    +            target_node = None
    +            target_capability = None
    +
    +            if target_node_capability is not None:
    +                # Relate to the first target node that has capacity
    +                for node in target_nodes:
    +                    a_target_capability = node.capabilities.get(target_node_capability.name)
    +                    if a_target_capability.relate():
    +                        target_node = node
    +                        target_capability = a_target_capability
    +                        break
    +            else:
    +                # Use first target node
    +                target_node = target_nodes[0]
    +
    +            if target_node is not None:
    +                if requirement_template.relationship_template is not None:
    +                    relationship_model = self._topology.instantiate(
    +                        requirement_template.relationship_template)
    +                else:
    +                    relationship_model = models.Relationship()
    +                relationship_model.name = requirement_template.name
    +                relationship_model.requirement_template = requirement_template
    +                relationship_model.target_node = target_node
    +                relationship_model.target_capability = target_capability
    +                self._model.outbound_relationships.append(relationship_model)
    +                return True
    +            else:
    +                self._topology.report(
    +                    'requirement "{0}" of node "{1}" targets node '
    +                    'template "{2}" but its instantiated nodes do not '
    +                    'have enough capacity'.format(
    +                        requirement_template.name, self._model.name, target_node_template.name),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                return False
    +        else:
    +            self._topology.report(
    +                'requirement "{0}" of node "{1}" targets node template '
    +                '"{2}" but it has no instantiated nodes'.format(
    +                    requirement_template.name, self._model.name, target_node_template.name),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +            return False
    +
    +    def _find_target(self, requirement_template):
    +        # We might already have a specific node 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):
    +                self._topology.report(
    +                    'requirement "{0}" of node template "{1}" is for node '
    +                    'template "{2}" but it does not match constraints'.format(
    +                        requirement_template.name,
    +                        requirement_template.target_node_template.name,
    +                        self._model.node_template.name),
    +                    level=self._topology.Issue.BETWEEN_TYPES)
    +            if (requirement_template.target_capability_type is not None or
    +                    requirement_template.target_capability_name is not None):
    +                target_node_capability = self._get_capability(requirement_template)
    +                if target_node_capability is None:
    +                    return None, None
    +            else:
    +                target_node_capability = None
    +
    +            return requirement_template.target_node_template, target_node_capability
    +
    +        # Find first node that matches the type
    +        elif requirement_template.target_node_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                if requirement_template.target_node_type.get_descendant(
    +                        target_node_template.type.name) is None:
    +                    continue
    +
    +                if not self._model.node_template.is_target_node_template_valid(
    +                        target_node_template):
    +                    continue
    +
    +                target_node_capability = self._get_capability(requirement_template,
    +                                                              target_node_template)
    +
    +                if target_node_capability is None:
    +                    continue
    +
    +                return target_node_template, target_node_capability
    +
    +        elif requirement_template.target_capability_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                target_node_capability = \
    +                    self._get_capability(requirement_template, target_node_template)
    +                if target_node_capability:
    +                    return target_node_template, target_node_capability
    +
    +        return None, None
    +
    +    def _get_capability(self, requirement_template, target_node_template=None):
    +        target_node_template = target_node_template or requirement_template.target_node_template
    +
    +        for capability_template in target_node_template.capability_templates.values():
    +            if self._satisfies_requirement(
    +                    capability_template, requirement_template, target_node_template):
    +                return capability_template
    +
    +        return None
    +
    +    def _satisfies_requirement(
    +            self, capability_template, requirement_template, target_node_template):
    +        # Do we match the required capability type?
    +        if (requirement_template.target_capability_type and
    +                requirement_template.target_capability_type.get_descendant(
    +                    capability_template.type.name) is None):
    +            return False
    +
    +        # Are we in valid_source_node_types?
    +        if capability_template.valid_source_node_types:
    +            for valid_source_node_type in capability_template.valid_source_node_types:
    +                if valid_source_node_type.get_descendant(
    +                        self._model.node_template.type.name) is None:
    +                    return False
    +
    +        # Apply requirement constraints
    +        if requirement_template.target_node_template_constraints:
    +            for node_template_constraint in requirement_template.target_node_template_constraints:
    +                if not node_template_constraint.matches(
    +                        self._model.node_template, target_node_template):
    +                    return False
    +
    +        return True
    +
    +
    +class Operation(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.inputs,
    +                     self._model.configurations,
    +                     self._model.arguments,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._validate(self._model.inputs,
    +                       self._model.configurations,
    +                       self._model.arguments)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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)))
    +            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')
    +            if self._model.executor is not None:
    +                out_stream.write('Executor: {0}'.format(out_stream.literal(self._model.executor)))
    +            if self._model.max_attempts is not None:
    +                out_stream.write('Max attempts: {0}'.format(out_stream.literal(
    +                    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)))
    +            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')
    +            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')
    +
    +    def configure_operations(self):
    +        if self._model.implementation is None and self._model.function is None:
    +            return
    +
    +        if (self._model.interface is not None and
    +                self._model.plugin is None and
    +                self._model.function is None):
    +            # ("interface" is None for workflow operations, which do not currently use "plugin")
    +            # The default (None) plugin is the execution plugin
    +            execution_plugin.instantiation.configure_operation(self._model, self._topology)
    +        else:
    +            # In the future plugins may be able to add their own "configure_operation" hook that
    +            # can validate the configuration and otherwise create specially derived arguments. For
    +            # now, we just send all configuration parameters as arguments without validation.
    +            for key, conf in self._model.configurations.items():
    +                self._model.arguments[key] = self._topology.instantiate(conf.as_argument())
    +
    +        if self._model.interface is not None:
    +            # Send all interface inputs as extra arguments
    +            # ("interface" is None for workflow operations)
    +            # Note that they will override existing arguments of the same names
    +            for key, input in self._model.interface.inputs.items():
    +                self._model.arguments[key] = self._topology.instantiate(input.as_argument())
    +
    +        # Send all inputs as extra arguments
    +        # Note that they will override existing arguments of the same names
    +        for key, input in self._model.inputs.items():
    +            self._model.arguments[key] = self._topology.instantiate(input.as_argument())
    +
    +        # Check for reserved arguments
    +        used_reserved_names = set(decorators.OPERATION_DECORATOR_RESERVED_ARGUMENTS).intersection(
    +            self._model.arguments.keys())
    +        if used_reserved_names:
    +            self._topology.report(
    +                'using reserved arguments in operation "{0}": {1}'.format(
    +                    self._model.name, formatting.string_list_as_string(used_reserved_names)),
    +                level=self._topology.Issue.EXTERNAL)
    +
    +
    +class Policy(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Policy: {0}'.format(out_stream.node(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')
    +            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))
    +            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))
    +
    +
    +class Relationship(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        if self._model.name:
    +            out_stream.write('{0} ->'.format(out_stream.node(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)))
    +            if self._model.target_capability:
    +                out_stream.write('Capability: {0}'.format(out_stream.node(
    +                    self._model.target_capability.name)))
    +            if self._model.type is not None:
    +                out_stream.write('Relationship type: {0}'.format(
    +                    out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Service(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.meta_data,
    +                     self._model.nodes,
    +                     self._model.groups,
    +                     self._model.policies,
    +                     self._model.substitution,
    +                     self._model.inputs,
    +                     self._model.outputs,
    +                     self._model.workflows,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._validate(self._model.meta_data,
    +                       self._model.nodes,
    +                       self._model.groups,
    +                       self._model.policies,
    +                       self._model.substitution,
    +                       self._model.inputs,
    +                       self._model.outputs,
    +                       self._model.workflows)
    +
    +    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')
    +        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')
    +
    +    def configure_operations(self):
    +        for node in self._model.nodes.itervalues():
    +            self._topology.configure_operations(node)
    +        for group in self._model.groups.itervalues():
    +            self._topology.configure_operations(group)
    +        for operation in self._model.workflows.itervalues():
    +            self._topology.configure_operations(operation)
    +
    +    def validate_capabilities(self):
    +        satisfied = True
    +        for node in self._model.nodes.values():
    +            if not self._topology.validate_capabilities(node):
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        return all(self._topology.satisfy_requirements(node)
    --- End diff --
    
    yup


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130594593
  
    --- Diff: aria/orchestrator/topology/common.py ---
    @@ -0,0 +1,52 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +
    +class _Handler(object):
    +    def __init__(self, topology, template):
    +        self._topology = topology
    +        self._model = template
    +
    +    def _coerce(self, *templates, **kwargs):
    --- End diff --
    
    maybe `_coerce_collection` or `iterable`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131085804
  
    --- Diff: aria/orchestrator/topology/template_handler.py ---
    @@ -0,0 +1,597 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from datetime import datetime
    +
    +from ...utils import formatting
    +from ...modeling import utils as modeling_utils
    +from . import utils, common
    +
    +
    +class ServiceTemplate(common._TemplateHandlerMixin):
    +    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')
    +        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')
    +
    +    def coerce(self, **kwargs):
    +        self._coerce(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,
    +                     **kwargs)
    +
    +    def instantiate(self, instance_cls, inputs=None):                                               # pylint: disable=arguments-differ
    +        now = datetime.now()
    +
    +        modeling_utils.validate_no_undeclared_inputs(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +        modeling_utils.validate_required_inputs_are_supplied(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +
    +        service = instance_cls(
    +            created_at=now,
    +            updated_at=now,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            service_template=self._model,
    +            inputs=modeling_utils.merge_parameter_values(inputs, self._model.inputs)
    +        )
    +
    +        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,
    +                                                      self._topology.model_storage.plugin.list()):
    +                    plugin = plugin_specification.plugin
    +                    service.plugins[plugin.name] = plugin
    +                else:
    +                    self._topology.report('specified plugin not found: {0}'.format(
    +                        plugin_specification.name), level=self._topology.Issue.EXTERNAL)
    +        service.meta_data = self._topology.instantiate(self._model.meta_data)
    +
    +        for node_template in self._model.node_templates.itervalues():
    +            for _ in range(self._scaling(node_template)['default_instances']):
    +                node = self._topology.instantiate(node_template)
    +                service.nodes[node.name] = node
    +
    +        service.groups = self._topology.instantiate(self._model.group_templates)
    +        service.policies = self._topology.instantiate(self._model.policy_templates)
    +        service.workflows = self._topology.instantiate(self._model.workflow_templates)
    +        service.substitution = self._topology.instantiate(self._model.substitution_template)
    +        service.outputs = self._topology.instantiate(self._model.outputs)
    +
    +        return service
    +
    +    def _scaling(self, node_template):
    +        scaling = {}
    --- End diff --
    
    What does it do?
    Document this.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130330688
  
    --- Diff: aria/core.py ---
    @@ -20,6 +20,7 @@
     from . import exceptions
     from .parser import consumption
     from .parser.loading.location import UriLocation
    +from .orchestrator.topology import Topology
    --- End diff --
    
    module...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132137184
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -50,28 +49,33 @@ class Topology(issue.Reporter):
             models.Type: models.Type
         }
     
    -    def __init__(self, model_storage=None, *args, **kwargs):
    -        # TODO: model storage is required only for the list of plugins, can we get it
    -        # somewhere else?
    +    def __init__(self, *args, **kwargs):
             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
    --- End diff --
    
    `from a module` --> `from a handler module`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130593730
  
    --- Diff: aria/orchestrator/topology/common.py ---
    @@ -0,0 +1,52 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +
    +class _Handler(object):
    --- End diff --
    
    `HandlerBase`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131083555
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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
    +
    +            # Find target template
    +            target_node_template, target_node_capability = self._find_target(requirement_template)
    +            if target_node_template is not None:
    +                satisfied = self._satisfy_capability(
    +                    target_node_capability, target_node_template, requirement_template)
    +            else:
    +                self._topology.report('requirement "{0}" of node "{1}" has no target node template'.
    +                                      format(requirement_template.name, self._model.name),
    +                                      level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def _satisfy_capability(self, target_node_capability, target_node_template,
    +                            requirement_template):
    +        # Find target nodes
    +        target_nodes = target_node_template.nodes
    +        if target_nodes:
    +            target_node = None
    +            target_capability = None
    +
    +            if target_node_capability is not None:
    +                # Relate to the first target node that has capacity
    +                for node in target_nodes:
    +                    a_target_capability = node.capabilities.get(target_node_capability.name)
    +                    if a_target_capability.relate():
    +                        target_node = node
    +                        target_capability = a_target_capability
    +                        break
    +            else:
    +                # Use first target node
    +                target_node = target_nodes[0]
    +
    +            if target_node is not None:
    +                if requirement_template.relationship_template is not None:
    +                    relationship_model = self._topology.instantiate(
    +                        requirement_template.relationship_template)
    +                else:
    +                    relationship_model = models.Relationship()
    +                relationship_model.name = requirement_template.name
    +                relationship_model.requirement_template = requirement_template
    +                relationship_model.target_node = target_node
    +                relationship_model.target_capability = target_capability
    +                self._model.outbound_relationships.append(relationship_model)
    +                return True
    +            else:
    +                self._topology.report(
    +                    'requirement "{0}" of node "{1}" targets node '
    +                    'template "{2}" but its instantiated nodes do not '
    +                    'have enough capacity'.format(
    +                        requirement_template.name, self._model.name, target_node_template.name),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                return False
    +        else:
    +            self._topology.report(
    +                'requirement "{0}" of node "{1}" targets node template '
    +                '"{2}" but it has no instantiated nodes'.format(
    +                    requirement_template.name, self._model.name, target_node_template.name),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +            return False
    +
    +    def _find_target(self, requirement_template):
    +        # We might already have a specific node 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):
    +                self._topology.report(
    +                    'requirement "{0}" of node template "{1}" is for node '
    +                    'template "{2}" but it does not match constraints'.format(
    +                        requirement_template.name,
    +                        requirement_template.target_node_template.name,
    +                        self._model.node_template.name),
    +                    level=self._topology.Issue.BETWEEN_TYPES)
    +            if (requirement_template.target_capability_type is not None or
    +                    requirement_template.target_capability_name is not None):
    +                target_node_capability = self._get_capability(requirement_template)
    +                if target_node_capability is None:
    +                    return None, None
    +            else:
    +                target_node_capability = None
    +
    +            return requirement_template.target_node_template, target_node_capability
    +
    +        # Find first node that matches the type
    +        elif requirement_template.target_node_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                if requirement_template.target_node_type.get_descendant(
    +                        target_node_template.type.name) is None:
    +                    continue
    +
    +                if not self._model.node_template.is_target_node_template_valid(
    +                        target_node_template):
    +                    continue
    +
    +                target_node_capability = self._get_capability(requirement_template,
    +                                                              target_node_template)
    +
    +                if target_node_capability is None:
    +                    continue
    +
    +                return target_node_template, target_node_capability
    +
    +        elif requirement_template.target_capability_type is not None:
    +            for target_node_template in \
    +                    self._model.node_template.service_template.node_templates.itervalues():
    +                target_node_capability = \
    +                    self._get_capability(requirement_template, target_node_template)
    +                if target_node_capability:
    +                    return target_node_template, target_node_capability
    +
    +        return None, None
    +
    +    def _get_capability(self, requirement_template, target_node_template=None):
    +        target_node_template = target_node_template or requirement_template.target_node_template
    +
    +        for capability_template in target_node_template.capability_templates.values():
    +            if self._satisfies_requirement(
    +                    capability_template, requirement_template, target_node_template):
    +                return capability_template
    +
    +        return None
    +
    +    def _satisfies_requirement(
    +            self, capability_template, requirement_template, target_node_template):
    +        # Do we match the required capability type?
    +        if (requirement_template.target_capability_type and
    +                requirement_template.target_capability_type.get_descendant(
    +                    capability_template.type.name) is None):
    +            return False
    +
    +        # Are we in valid_source_node_types?
    +        if capability_template.valid_source_node_types:
    +            for valid_source_node_type in capability_template.valid_source_node_types:
    +                if valid_source_node_type.get_descendant(
    +                        self._model.node_template.type.name) is None:
    +                    return False
    +
    +        # Apply requirement constraints
    +        if requirement_template.target_node_template_constraints:
    +            for node_template_constraint in requirement_template.target_node_template_constraints:
    +                if not node_template_constraint.matches(
    +                        self._model.node_template, target_node_template):
    +                    return False
    +
    +        return True
    +
    +
    +class Operation(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.inputs,
    +                     self._model.configurations,
    +                     self._model.arguments,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._validate(self._model.inputs,
    +                       self._model.configurations,
    +                       self._model.arguments)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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)))
    +            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')
    +            if self._model.executor is not None:
    +                out_stream.write('Executor: {0}'.format(out_stream.literal(self._model.executor)))
    +            if self._model.max_attempts is not None:
    +                out_stream.write('Max attempts: {0}'.format(out_stream.literal(
    +                    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)))
    +            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')
    +            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')
    +
    +    def configure_operations(self):
    +        if self._model.implementation is None and self._model.function is None:
    +            return
    +
    +        if (self._model.interface is not None and
    +                self._model.plugin is None and
    +                self._model.function is None):
    +            # ("interface" is None for workflow operations, which do not currently use "plugin")
    +            # The default (None) plugin is the execution plugin
    +            execution_plugin.instantiation.configure_operation(self._model, self._topology)
    +        else:
    +            # In the future plugins may be able to add their own "configure_operation" hook that
    +            # can validate the configuration and otherwise create specially derived arguments. For
    +            # now, we just send all configuration parameters as arguments without validation.
    +            for key, conf in self._model.configurations.items():
    +                self._model.arguments[key] = self._topology.instantiate(conf.as_argument())
    +
    +        if self._model.interface is not None:
    +            # Send all interface inputs as extra arguments
    +            # ("interface" is None for workflow operations)
    +            # Note that they will override existing arguments of the same names
    +            for key, input in self._model.interface.inputs.items():
    +                self._model.arguments[key] = self._topology.instantiate(input.as_argument())
    +
    +        # Send all inputs as extra arguments
    +        # Note that they will override existing arguments of the same names
    +        for key, input in self._model.inputs.items():
    +            self._model.arguments[key] = self._topology.instantiate(input.as_argument())
    +
    +        # Check for reserved arguments
    +        used_reserved_names = set(decorators.OPERATION_DECORATOR_RESERVED_ARGUMENTS).intersection(
    +            self._model.arguments.keys())
    +        if used_reserved_names:
    +            self._topology.report(
    +                'using reserved arguments in operation "{0}": {1}'.format(
    +                    self._model.name, formatting.string_list_as_string(used_reserved_names)),
    +                level=self._topology.Issue.EXTERNAL)
    +
    +
    +class Policy(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Policy: {0}'.format(out_stream.node(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')
    +            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))
    +            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))
    +
    +
    +class Relationship(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        if self._model.name:
    +            out_stream.write('{0} ->'.format(out_stream.node(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)))
    +            if self._model.target_capability:
    +                out_stream.write('Capability: {0}'.format(out_stream.node(
    +                    self._model.target_capability.name)))
    +            if self._model.type is not None:
    +                out_stream.write('Relationship type: {0}'.format(
    +                    out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Service(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.meta_data,
    +                     self._model.nodes,
    +                     self._model.groups,
    +                     self._model.policies,
    +                     self._model.substitution,
    +                     self._model.inputs,
    +                     self._model.outputs,
    +                     self._model.workflows,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._validate(self._model.meta_data,
    +                       self._model.nodes,
    +                       self._model.groups,
    +                       self._model.policies,
    +                       self._model.substitution,
    +                       self._model.inputs,
    +                       self._model.outputs,
    +                       self._model.workflows)
    +
    +    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')
    +        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')
    +
    +    def configure_operations(self):
    +        for node in self._model.nodes.itervalues():
    +            self._topology.configure_operations(node)
    +        for group in self._model.groups.itervalues():
    +            self._topology.configure_operations(group)
    +        for operation in self._model.workflows.itervalues():
    +            self._topology.configure_operations(operation)
    +
    +    def validate_capabilities(self):
    +        satisfied = True
    +        for node in self._model.nodes.values():
    +            if not self._topology.validate_capabilities(node):
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        return all(self._topology.satisfy_requirements(node)
    --- End diff --
    
    is that `all` necessary?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130593980
  
    --- Diff: aria/orchestrator/topology/common.py ---
    @@ -0,0 +1,52 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +
    +class _Handler(object):
    +    def __init__(self, topology, template):
    +        self._topology = topology
    +        self._model = template
    +
    +    def _coerce(self, *templates, **kwargs):
    --- End diff --
    
    `templates` --> `models`
    And everywhere else.
    If it's not always a model, choose better name, not `template`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130876740
  
    --- Diff: tests/parser/service_templates.py ---
    @@ -27,6 +27,7 @@ def consume_literal(literal, consumer_class_name='instance', cache=True, no_issu
         context = create_context(LiteralLocation(literal))
         consumer, dumper = create_consumer(context, consumer_class_name)
         consumer.consume()
    +    consumer.dump()
    --- End diff --
    
    Why was this added?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130879245
  
    --- Diff: tests/parser/test_reqs_caps.py ---
    @@ -0,0 +1,29 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from .service_templates import consume_test_case
    +from ..helpers import get_service_template_uri
    +
    +
    +def test_satisfy_capability_type():
    +    consume_reqs_caps_template('instance')
    +
    +
    +def consume_reqs_caps_template(consumer_class_name, cache=True):
    --- End diff --
    
    `consume_reqs_caps_template1`? Or a name that explains what exactly are we testing here regarding reqs and caps.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130875236
  
    --- Diff: tests/instantiation/test_configuration.py ---
    @@ -165,8 +165,11 @@ def test_remote(service):
     
     
     def test_reserved_arguments(broken_service_issues):
    --- End diff --
    
    I think there should be only one issue created here. The other issue, `0: Failed to instantiate service template `None`, which is a general failure message, shouldn't be modelled as an Issue.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130842710
  
    --- Diff: aria/parser/consumption/modeling.py ---
    @@ -74,7 +75,7 @@ def dump(self):
                 raw = self.context.modeling.template_as_raw
                 self.context.write(json_dumps(raw, indent=indent))
             else:
    -            self.context.modeling.template.dump()
    +            self.topology.dump(self.context.modeling.template)
     
     
     class Types(Consumer):
    --- End diff --
    
    If this class is no longer needed to show ('dump') the types, consider deleting it.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130902831
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    +
    +    def configure_operations(self):
    +        for operation in self._model.operations.values():
    +            self._topology.configure_operations(operation)
    +
    +
    +class Node(common._OperatorHolderHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._coerce(self._model.properties,
    +                     self._model.attributes,
    +                     self._model.interfaces,
    +                     self._model.artifacts,
    +                     self._model.capabilities,
    +                     self._model.outbound_relationships,
    +                     **kwargs)
    +
    +    def validate(self, **kwargs):
    +        if len(self._model.name) > context.ID_MAX_LENGTH:
    +            self._topology.report(
    +                '"{0}" has an ID longer than the limit of {1:d} characters: {2:d}'.format(
    +                    self._model.name, context.ID_MAX_LENGTH, len(self._model.name)),
    +                level=self._topology.Issue.BETWEEN_INSTANCES)
    +
    +        self._validate(self._model.properties,
    +                       self._model.attributes,
    +                       self._model.interfaces,
    +                       self._model.artifacts,
    +                       self._model.capabilities,
    +                       self._model.outbound_relationships)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Node: {0}'.format(out_stream.node(self._model.name)))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +        for relationship in self._model.outbound_relationships:
    +            self._topology.configure_operations(relationship)
    +
    +    def validate_capabilities(self):
    +        satisfied = False
    +        for capability in self._model.capabilities.itervalues():
    +            if not capability.has_enough_relationships:
    +                self._topology.report(
    +                    'capability "{0}" of node "{1}" requires at least {2:d} '
    +                    'relationships but has {3:d}'.format(capability.name,
    +                                                         self._model.name,
    +                                                         capability.min_occurrences,
    +                                                         capability.occurrences),
    +                    level=self._topology.Issue.BETWEEN_INSTANCES)
    +                satisfied = False
    +        return satisfied
    +
    +    def satisfy_requirements(self):
    +        satisfied = True
    +        for requirement_template in self._model.node_template.requirement_templates:
    +
    +            # Since we try and satisfy requirements, which are node template bound, and use that
    +            # 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
    --- End diff --
    
    should be `continue`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130828395
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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)
    +
    +    def validate(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).validate(**kwargs)
    +
    +    def dump(self, model, out_stream=None, section_name=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 isinstance(model, dict):
    +            if str(out_stream):
    +                with out_stream.indent():
    +                    return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +            else:
    +                return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +
    +        elif isinstance(model, list):
    +            for value in model:
    +                self.dump(value, out_stream=out_stream, **kwargs)
    +
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            _handler(self, model).dump(out_stream=out_stream, **kwargs)
    +
    +        return out_stream
    +
    +    def dump_graph(self, service, **kwargs):
    +        out_stream = console.TopologyStylizer()
    +        for node in service.nodes.itervalues():
    +            if not node.inbound_relationships:
    +                self._dump_graph_node(out_stream, node)
    +        return out_stream
    +
    +    def _dump_graph_node(self, out_stream, node, capability=None):
    +        out_stream.write(out_stream.node(node.name))
    +        if capability is not None:
    +            out_stream.write('{0} ({1})'.format(out_stream.property(capability.name),
    +                                                out_stream.type(capability.type.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:
    +                        out_stream.write('-> {0} ({1})'.format(
    +                            relationship_name, out_stream.type(relationship_model.type.name)))
    +                    else:
    +                        out_stream.write('-> {0}'.format(relationship_name))
    +                    with out_stream.indent(3):
    +                        self._dump_graph_node(out_stream,
    +                                              relationship_model.target_node,
    +                                              relationship_model.target_capability)
    +
    +    def coerce(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).coerce(**kwargs)
    +
    +    def dump_types(self, service_template, out_stream=None):
    +        out_stream = out_stream or console.TopologyStylizer()
    +        self.dump(service_template.node_types, out_stream, 'Node types')
    +        self.dump(service_template.group_types, out_stream, 'Group types')
    +        self.dump(service_template.capability_types, out_stream, 'Capability types')
    +        self.dump(service_template.relationship_types, out_stream, 'Relationship types')
    +        self.dump(service_template.policy_types, out_stream, 'Policy types')
    +        self.dump(service_template.artifact_types, out_stream, 'Artifact types')
    +        self.dump(service_template.interface_types, out_stream, 'Interface types')
    +
    +        return str(out_stream)
    +
    +    def satisfy_requirements(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.satisfy_requirements(model.values())
    +        elif isinstance(model, list):
    +            return all(self.satisfy_requirements(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(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())
    +        elif isinstance(model, list):
    +            return all(self.validate_capabilities(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(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: \
    --- End diff --
    
    name it `target_has_role`.
    And consider making it into `def`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132168007
  
    --- Diff: aria/orchestrator/topology/template_handler.py ---
    @@ -431,15 +430,14 @@ def dump(self, out_stream):
             out_stream.write('Substitution template:')
             with out_stream.indent():
                 out_stream.write('Node type: {0}'.format(out_stream.type_style(
    -                self._model.node_type.name)))
    --- End diff --
    
    node_type --> name


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130607886
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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__)
    --- End diff --
    
    `instance_cls` --> `model_instance_cls`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130330616
  
    --- Diff: aria/cli/commands/service_templates.py ---
    @@ -28,7 +28,7 @@
     from ...storage import exceptions as storage_exceptions
     from ...parser import consumption
     from ...utils import (formatting, collections, console)
    -
    +from ... orchestrator.topology import Topology
    --- End diff --
    
    import module


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132123290
  
    --- Diff: aria/modeling/service_template.py ---
    @@ -530,6 +530,43 @@ def _next_name(self):
     
             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)
    --- End diff --
    
    should be `setdefault`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130607151
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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__)
    --- End diff --
    
    `self._handlers[model.__class__]`
    In the other also.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130593564
  
    --- Diff: aria/orchestrator/topology/__init__.py ---
    @@ -0,0 +1,16 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from .topology import Topology
    --- End diff --
    
    Don't see the need for that.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130824971
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    +        :param model:
    +        :param kwargs:
    +        :return:
    +        """
    +        if isinstance(model, dict):
    +            return dict((name, self.instantiate(value, **kwargs))
    +                        for name, value in model.iteritems())
    +        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)
    +
    +    def validate(self, model, **kwargs):
    +        if isinstance(model, dict):
    +            return self.validate(model.values())
    +        elif isinstance(model, list):
    +            return all(self.validate(value) for value in model)
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            return _handler(self, model).validate(**kwargs)
    +
    +    def dump(self, model, out_stream=None, section_name=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 isinstance(model, dict):
    +            if str(out_stream):
    +                with out_stream.indent():
    +                    return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +            else:
    +                return self.dump(model.values(), out_stream=out_stream, **kwargs)
    +
    +        elif isinstance(model, list):
    +            for value in model:
    +                self.dump(value, out_stream=out_stream, **kwargs)
    +
    +        elif model is not None:
    +            _handler = self._handlers.get(model.__class__)
    +            _handler(self, model).dump(out_stream=out_stream, **kwargs)
    +
    +        return out_stream
    +
    +    def dump_graph(self, service, **kwargs):
    +        out_stream = console.TopologyStylizer()
    +        for node in service.nodes.itervalues():
    +            if not node.inbound_relationships:
    +                self._dump_graph_node(out_stream, node)
    +        return out_stream
    +
    +    def _dump_graph_node(self, out_stream, node, capability=None):
    +        out_stream.write(out_stream.node(node.name))
    +        if capability is not None:
    +            out_stream.write('{0} ({1})'.format(out_stream.property(capability.name),
    +                                                out_stream.type(capability.type.name)))
    +        if node.outbound_relationships:
    +            with out_stream.indent():
    +                for relationship_model in node.outbound_relationships:
    +                    relationship_name = out_stream.property(relationship_model.name)
    --- End diff --
    
    `relationship_name` --> `styled_relationship_name`?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130583765
  
    --- Diff: 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 template
    +    Show information for a stored service templates
    --- End diff --
    
    template.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132168198
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -51,17 +51,17 @@ class Topology(issue.ReporterMixin):
     
         def __init__(self, *args, **kwargs):
             super(Topology, self).__init__(*args, **kwargs)
    -        self._models_to_handlers = dict(self._init_handlers(instance_handler),
    -                                        **self._init_handlers(template_handler))
    +        self._model_cls_to_handler = dict(self._init_handlers(instance_handler),
    +                                          **self._init_handlers(template_handler))
     
         @staticmethod
         def _init_handlers(module_):
             """
    -        Register handlers from a module to the models
    +        Register handlers from the handler module to the models
    --- End diff --
    
    a handler


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130606443
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    +        # 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))
    +
    +    @staticmethod
    +    def _init_handlers(module_):
    +        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):
    +                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)
    --- End diff --
    
    This comment is not correct now.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132137988
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -50,28 +49,33 @@ class Topology(issue.Reporter):
             models.Type: models.Type
         }
     
    -    def __init__(self, model_storage=None, *args, **kwargs):
    -        # TODO: model storage is required only for the list of plugins, can we get it
    -        # somewhere else?
    +    def __init__(self, *args, **kwargs):
             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
    --- End diff --
    
    `key` --> `the key`, `models` --> `model's`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130894358
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    --- End diff --
    
    Are those `if`s necessary? Isn't the `write` method smart enough to handle the empty model case?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130331038
  
    --- Diff: aria/core.py ---
    @@ -67,31 +68,26 @@ def delete_service_template(self, service_template_id):
             self.resource_storage.service_template.delete(entry_id=str(service_template.id))
     
         def create_service(self, service_template_id, inputs, service_name=None):
    -
             service_template = self.model_storage.service_template.get(service_template_id)
     
    -        # creating an empty ConsumptionContext, initiating a threadlocal context
    -        context = consumption.ConsumptionContext()
    -
             storage_session = self.model_storage._all_api_kwargs['session']
             # setting no autoflush for the duration of instantiation - this helps avoid dependency
             # constraints as they're being set up
             with storage_session.no_autoflush:
    -            service = service_template.instantiate(None, self.model_storage, inputs=inputs)
    -
    -            consumption.ConsumerChain(
    -                context,
    -                (
    -                    consumption.CoerceServiceInstanceValues,
    -                    consumption.ValidateServiceInstance,
    -                    consumption.SatisfyRequirements,
    -                    consumption.CoerceServiceInstanceValues,
    -                    consumption.ValidateCapabilities,
    -                    consumption.FindHosts,
    -                    consumption.ConfigureOperations,
    -                    consumption.CoerceServiceInstanceValues
    -                )).consume()
    -            if context.validation.dump_issues():
    +            topology = Topology(self.model_storage)
    +            service = topology.instantiate(service_template, inputs=inputs)
    +            topology.coerce(service)
    +
    +            topology.validate(service)
    +            topology.satisfy_requirements(service)
    +            topology.coerce(service)
    +
    +            topology.validate_capabilities(service)
    +            topology.find_hosts(service)
    +            topology.configure_operations(service)
    --- End diff --
    
    is it possible to couple the configure operations with the creation of service?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130600640
  
    --- Diff: aria/orchestrator/topology/instance_handler.py ---
    @@ -0,0 +1,644 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ... parser.modeling import context
    +from ... modeling import models
    +from ... utils import formatting
    +from .. import execution_plugin
    +from .. import decorators
    +from . import common
    +
    +
    +class Artifact(common._InstanceHandlerMixin):
    +
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    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))
    +            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)))
    +                if self._model.target_path is not None:
    +                    out_stream.write('Target path: {0}'.format(
    +                        out_stream.literal(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)))
    +                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')
    +
    +
    +class Capability(common._InstanceHandlerMixin):
    +    def coerce(self, **kwargs):
    +        self._topology.coerce(self._model.properties, **kwargs)
    +
    +    def validate(self, **kwargs):
    +        self._topology.validate(self._model.properties)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        with out_stream.indent():
    +            out_stream.write('Type: {0}'.format(out_stream.type(self._model.type.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')
    +
    +
    +class Group(common._OperatorHolderHandlerMixin):
    +
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write('Group: {0}'.format(out_stream.node(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')
    +            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))
    +
    +    def configure_operations(self):
    +        for interface in self._model.interfaces.values():
    +            self._topology.configure_operations(interface)
    +
    +
    +class Interface(common._OperatorHolderHandlerMixin):
    +    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)
    +
    +    def dump(self, out_stream):
    +        out_stream.write(out_stream.node(self._model.name))
    +        if self._model.description:
    +            out_stream.write(out_stream.meta(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')
    --- End diff --
    
    add the parameter name of `'Inputs'`.
    'title' will be a nice parameter name.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130331316
  
    --- Diff: aria/orchestrator/topology/topology.py ---
    @@ -0,0 +1,217 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from ...parser.validation import issue
    +from ...modeling import models
    +from ...utils import console
    +from . import (
    +    template_handler,
    +    instance_handler,
    +    common
    +)
    +
    +
    +class Topology(issue.Reporter):
    +
    +    _init_map = {
    +        models.ServiceTemplate: models.Service,
    +        models.ArtifactTemplate: models.Artifact,
    +        models.CapabilityTemplate: models.Capability,
    +        models.GroupTemplate: models.Group,
    +        models.InterfaceTemplate: models.Interface,
    +        models.NodeTemplate: models.Node,
    +        models.PolicyTemplate: models.Policy,
    +        models.SubstitutionTemplate: models.Substitution,
    +        models.RelationshipTemplate: models.Relationship,
    +        models.OperationTemplate: models.Operation,
    +        models.RequirementTemplate: None,
    +        models.SubstitutionTemplateMapping: models.SubstitutionMapping,
    +
    +        # Common
    +        models.Metadata: models.Metadata,
    +        models.Attribute: models.Attribute,
    +        models.Property: models.Property,
    +        models.Input: models.Input,
    +        models.Output: models.Output,
    +        models.Configuration: models.Configuration,
    +        models.Argument: models.Argument,
    +        models.Type: models.Type
    +    }
    +
    +    def __init__(self, model_storage=None, *args, **kwargs):
    +        # TODO: model storage is required only for the list of plugins, can we get it
    --- End diff --
    
    probably not =\


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130873555
  
    --- Diff: extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py ---
    @@ -497,8 +497,8 @@ def get(name, default=None):
     
     
     def create_workflow_operation_template_model(context, service_template, policy):
    -    model = OperationTemplate(name=policy._name,
    -                              service_template=service_template)
    +    model = OperationTemplate(name=policy._name)
    +    service_template.workflow_templates[model.name] = model
    --- End diff --
    
    Add your comment as a code comment. `service_template.workflows` --> `service_template.workflow_templates`.
    And if you think this problem is in other places also, open a Jira issue for it.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131086718
  
    --- Diff: aria/orchestrator/topology/template_handler.py ---
    @@ -0,0 +1,597 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from datetime import datetime
    +
    +from ...utils import formatting
    +from ...modeling import utils as modeling_utils
    +from . import utils, common
    +
    +
    +class ServiceTemplate(common._TemplateHandlerMixin):
    +    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')
    +        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')
    +
    +    def coerce(self, **kwargs):
    +        self._coerce(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,
    +                     **kwargs)
    +
    +    def instantiate(self, instance_cls, inputs=None):                                               # pylint: disable=arguments-differ
    +        now = datetime.now()
    +
    +        modeling_utils.validate_no_undeclared_inputs(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +        modeling_utils.validate_required_inputs_are_supplied(
    +            declared_inputs=self._model.inputs, supplied_inputs=inputs or {})
    +
    +        service = instance_cls(
    +            created_at=now,
    +            updated_at=now,
    +            description=utils.deepcopy_with_locators(self._model.description),
    +            service_template=self._model,
    +            inputs=modeling_utils.merge_parameter_values(inputs, self._model.inputs)
    +        )
    +
    +        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,
    +                                                      self._topology.model_storage.plugin.list()):
    +                    plugin = plugin_specification.plugin
    +                    service.plugins[plugin.name] = plugin
    +                else:
    +                    self._topology.report('specified plugin not found: {0}'.format(
    +                        plugin_specification.name), level=self._topology.Issue.EXTERNAL)
    +        service.meta_data = self._topology.instantiate(self._model.meta_data)
    +
    +        for node_template in self._model.node_templates.itervalues():
    +            for _ in range(self._scaling(node_template)['default_instances']):
    +                node = self._topology.instantiate(node_template)
    +                service.nodes[node.name] = node
    +
    +        service.groups = self._topology.instantiate(self._model.group_templates)
    +        service.policies = self._topology.instantiate(self._model.policy_templates)
    +        service.workflows = self._topology.instantiate(self._model.workflow_templates)
    +        service.substitution = self._topology.instantiate(self._model.substitution_template)
    +        service.outputs = self._topology.instantiate(self._model.outputs)
    +
    +        return service
    +
    +    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
    --- End diff --
    
    Consider splitting this function into validation and the rest of the logic, and return the rest of the logic to the model.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130595525
  
    --- Diff: aria/orchestrator/topology/common.py ---
    @@ -0,0 +1,52 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +
    +class _Handler(object):
    +    def __init__(self, topology, template):
    +        self._topology = topology
    +        self._model = template
    +
    +    def _coerce(self, *templates, **kwargs):
    +        for template in templates:
    +            self._topology.coerce(template)
    +
    +    def coerce(self):
    +        pass
    --- End diff --
    
    raise `NotImplementedError`?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r130331174
  
    --- Diff: aria/orchestrator/execution_plugin/instantiation.py ---
    @@ -110,20 +106,24 @@ def _configure_remote(operation):
     
         # Make sure we have a user
         if fabric_env.get('user') is None:
    -        context = ConsumptionContext.get_thread_local()
    -        context.validation.report('must configure "ssh.user" for "{0}"'
    -                                  .format(operation.implementation),
    -                                  level=validation.Issue.BETWEEN_TYPES)
    +        # TODO: fix
    --- End diff --
    
    revert the entire module?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by mxmrlv <gi...@git.apache.org>.
Github user mxmrlv commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r131132744
  
    --- Diff: aria/orchestrator/topology/__init__.py ---
    @@ -0,0 +1,16 @@
    +# Licensed to the Apache Software Foundation (ASF) under one or more
    +# contributor license agreements.  See the NOTICE file distributed with
    +# this work for additional information regarding copyright ownership.
    +# The ASF licenses this file to You under the Apache License, Version 2.0
    +# (the "License"); you may not use this file except in compliance with
    +# the License.  You may obtain a copy of the License at
    +#
    +#     http://www.apache.org/licenses/LICENSE-2.0
    +#
    +# Unless required by applicable law or agreed to in writing, software
    +# distributed under the License is distributed on an "AS IS" BASIS,
    +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    +# See the License for the specific language governing permissions and
    +# limitations under the License.
    +
    +from .topology import Topology
    --- End diff --
    
    there is one


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-ariatosca pull request #189: ARIA-174 Refactor instantiation phase

Posted by AviaE <gi...@git.apache.org>.
Github user AviaE commented on a diff in the pull request:

    https://github.com/apache/incubator-ariatosca/pull/189#discussion_r132167856
  
    --- Diff: aria/core.py ---
    @@ -118,8 +118,8 @@ def delete_service(self, service_id, force=False):
         def _parse_service_template(service_template_path):
             context = consumption.ConsumptionContext()
             context.presentation.location = UriLocation(service_template_path)
    -        # 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.
    +        # Most of the parser uses the topology package in order to manipulate the models.
    +        # However, here we use the Consumer, but this should change in the future.
    --- End diff --
    
    Consumer mechanism


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---