Repository: incubator-ariatosca Updated Branches: refs/heads/ARIA-174-Refactor-instantiation-phase 0bc7993f8 -> 8e5fe109d
validate + instantiate and tidy up Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/8e5fe109 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/8e5fe109 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/8e5fe109 Branch: refs/heads/ARIA-174-Refactor-instantiation-phase Commit: 8e5fe109d9f8acb5752f739df1ab47dc4858d3d6 Parents: 0bc7993 Author: max-orlov <[email protected]> Authored: Sun Jul 23 18:58:08 2017 +0300 Committer: max-orlov <[email protected]> Committed: Sun Jul 23 18:58:08 2017 +0300 ---------------------------------------------------------------------- aria/modeling/service_instance.py | 69 ---- aria/modeling/service_template.py | 75 ----- aria/orchestrator/topology/__init__.py | 97 +++++- aria/orchestrator/topology/common.py | 41 +++ aria/orchestrator/topology/instance.py | 208 ++++++++++++ aria/orchestrator/topology/template.py | 383 ++++++++++++++++++++++ aria/orchestrator/topology/topology.py | 476 ---------------------------- 7 files changed, 728 insertions(+), 621 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5fe109/aria/modeling/service_instance.py ---------------------------------------------------------------------- diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py index 58734b2..93d610b 100644 --- a/aria/modeling/service_instance.py +++ b/aria/modeling/service_instance.py @@ -289,17 +289,6 @@ class ServiceBase(InstanceModelMixin): ('outputs', formatting.as_raw_dict(self.outputs)), ('workflows', formatting.as_raw_list(self.workflows)))) - def validate(self): - utils.validate_dict_values(self.meta_data) - utils.validate_dict_values(self.nodes) - utils.validate_dict_values(self.groups) - utils.validate_dict_values(self.policies) - if self.substitution is not None: - self.substitution.validate() - utils.validate_dict_values(self.inputs) - utils.validate_dict_values(self.outputs) - utils.validate_dict_values(self.workflows) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.meta_data, report_issues) utils.coerce_dict_values(self.nodes, report_issues) @@ -741,25 +730,6 @@ class NodeBase(InstanceModelMixin): ('capabilities', formatting.as_raw_list(self.capabilities)), ('relationships', formatting.as_raw_list(self.outbound_relationships)))) - def validate(self): - context = ConsumptionContext.get_thread_local() - if len(self.name) > context.modeling.id_max_length: - context.validation.report('"{0}" has an ID longer than the limit of {1:d} characters: ' - '{2:d}'.format( - self.name, - context.modeling.id_max_length, - len(self.name)), - level=validation.Issue.BETWEEN_INSTANCES) - - # TODO: validate that node template is of type? - - utils.validate_dict_values(self.properties) - utils.validate_dict_values(self.attributes) - utils.validate_dict_values(self.interfaces) - utils.validate_dict_values(self.artifacts) - utils.validate_dict_values(self.capabilities) - utils.validate_list_values(self.outbound_relationships) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) utils.coerce_dict_values(self.attributes, report_issues) @@ -897,10 +867,6 @@ class GroupBase(InstanceModelMixin): ('properties', formatting.as_raw_dict(self.properties)), ('interfaces', formatting.as_raw_list(self.interfaces)))) - def validate(self): - utils.validate_dict_values(self.properties) - utils.validate_dict_values(self.interfaces) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) utils.coerce_dict_values(self.interfaces, report_issues) @@ -1031,9 +997,6 @@ class PolicyBase(InstanceModelMixin): ('type_name', self.type.name), ('properties', formatting.as_raw_dict(self.properties)))) - def validate(self): - utils.validate_dict_values(self.properties) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) @@ -1131,9 +1094,6 @@ class SubstitutionBase(InstanceModelMixin): ('node_type_name', self.node_type.name), ('mappings', formatting.as_raw_dict(self.mappings)))) - def validate(self): - utils.validate_dict_values(self.mappings) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.mappings, report_issues) @@ -1242,15 +1202,6 @@ class SubstitutionMappingBase(InstanceModelMixin): def coerce_values(self, report_issues): pass - def validate(self): - context = ConsumptionContext.get_thread_local() - if (self.capability is None) and (self.requirement_template is None): - context.validation.report('mapping "{0}" refers to neither capability nor a requirement' - ' in node: {1}'.format( - self.name, - formatting.safe_repr(self.node.name)), - level=validation.Issue.BETWEEN_TYPES) - def dump(self): context = ConsumptionContext.get_thread_local() if self.capability is not None: @@ -1453,10 +1404,6 @@ class RelationshipBase(InstanceModelMixin): ('properties', formatting.as_raw_dict(self.properties)), ('interfaces', formatting.as_raw_list(self.interfaces)))) - def validate(self): - utils.validate_dict_values(self.properties) - utils.validate_dict_values(self.interfaces) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) utils.coerce_dict_values(self.interfaces, report_issues) @@ -1596,9 +1543,6 @@ class CapabilityBase(InstanceModelMixin): ('type_name', self.type.name), ('properties', formatting.as_raw_dict(self.properties)))) - def validate(self): - utils.validate_dict_values(self.properties) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) @@ -1752,10 +1696,6 @@ class InterfaceBase(InstanceModelMixin): ('inputs', formatting.as_raw_dict(self.inputs)), ('operations', formatting.as_raw_list(self.operations)))) - def validate(self): - utils.validate_dict_values(self.inputs) - utils.validate_dict_values(self.operations) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.inputs, report_issues) utils.coerce_dict_values(self.operations, report_issues) @@ -1995,12 +1935,6 @@ class OperationBase(InstanceModelMixin): ('dependencies', self.dependencies), ('inputs', formatting.as_raw_dict(self.inputs)))) - def validate(self): - # TODO must be associated with either interface or service - utils.validate_dict_values(self.inputs) - utils.validate_dict_values(self.configurations) - utils.validate_dict_values(self.arguments) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.inputs, report_issues) utils.coerce_dict_values(self.configurations, report_issues) @@ -2154,9 +2088,6 @@ class ArtifactBase(InstanceModelMixin): ('repository_credential', formatting.as_agnostic(self.repository_credential)), ('properties', formatting.as_raw_dict(self.properties)))) - def validate(self): - utils.validate_dict_values(self.properties) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5fe109/aria/modeling/service_template.py ---------------------------------------------------------------------- diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py index 719a221..b505a06 100644 --- a/aria/modeling/service_template.py +++ b/aria/modeling/service_template.py @@ -327,31 +327,6 @@ class ServiceTemplateBase(TemplateModelMixin): ('interface_types', formatting.as_raw(self.interface_types)), ('artifact_types', formatting.as_raw(self.artifact_types)))) - def validate(self): - utils.validate_dict_values(self.meta_data) - utils.validate_dict_values(self.node_templates) - utils.validate_dict_values(self.group_templates) - utils.validate_dict_values(self.policy_templates) - if self.substitution_template is not None: - self.substitution_template.validate() - utils.validate_dict_values(self.inputs) - utils.validate_dict_values(self.outputs) - utils.validate_dict_values(self.workflow_templates) - if self.node_types is not None: - self.node_types.validate() - if self.group_types is not None: - self.group_types.validate() - if self.policy_types is not None: - self.policy_types.validate() - if self.relationship_types is not None: - self.relationship_types.validate() - if self.capability_types is not None: - self.capability_types.validate() - if self.interface_types is not None: - self.interface_types.validate() - if self.artifact_types is not None: - self.artifact_types.validate() - def coerce_values(self, report_issues): utils.coerce_dict_values(self.meta_data, report_issues) utils.coerce_dict_values(self.node_templates, report_issues) @@ -573,14 +548,6 @@ class NodeTemplateBase(TemplateModelMixin): ('capability_templates', formatting.as_raw_list(self.capability_templates)), ('requirement_templates', formatting.as_raw_list(self.requirement_templates)))) - def validate(self): - utils.validate_dict_values(self.properties) - utils.validate_dict_values(self.attributes) - utils.validate_dict_values(self.interface_templates) - utils.validate_dict_values(self.artifact_templates) - utils.validate_dict_values(self.capability_templates) - utils.validate_list_values(self.requirement_templates) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) utils.coerce_dict_values(self.attributes, report_issues) @@ -801,10 +768,6 @@ class GroupTemplateBase(TemplateModelMixin): ('properties', formatting.as_raw_dict(self.properties)), ('interface_templates', formatting.as_raw_list(self.interface_templates)))) - def validate(self): - utils.validate_dict_values(self.properties) - utils.validate_dict_values(self.interface_templates) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) utils.coerce_dict_values(self.interface_templates, report_issues) @@ -934,9 +897,6 @@ class PolicyTemplateBase(TemplateModelMixin): ('type_name', self.type.name), ('properties', formatting.as_raw_dict(self.properties)))) - def validate(self): - utils.validate_dict_values(self.properties) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) @@ -1031,9 +991,6 @@ class SubstitutionTemplateBase(TemplateModelMixin): ('node_type_name', self.node_type.name), ('mappings', formatting.as_raw_dict(self.mappings)))) - def validate(self): - utils.validate_dict_values(self.mappings) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.mappings, report_issues) @@ -1126,15 +1083,6 @@ class SubstitutionTemplateMappingBase(TemplateModelMixin): def coerce_values(self, report_issues): pass - def validate(self): - context = ConsumptionContext.get_thread_local() - if (self.capability_template is None) and (self.requirement_template is None): - context.validation.report('mapping "{0}" refers to neither capability nor a requirement' - ' in node template: {1}'.format( - self.name, - formatting.safe_repr(self.node_template.name)), - level=validation.Issue.BETWEEN_TYPES) - def dump(self): context = ConsumptionContext.get_thread_local() if self.capability_template is not None: @@ -1349,10 +1297,6 @@ class RequirementTemplateBase(TemplateModelMixin): ('target_capability_name', self.target_capability_name), ('relationship_template', formatting.as_raw(self.relationship_template)))) - def validate(self): - if self.relationship_template: - self.relationship_template.validate() - def coerce_values(self, report_issues): if self.relationship_template is not None: self.relationship_template.coerce_values(report_issues) @@ -1468,11 +1412,6 @@ class RelationshipTemplateBase(TemplateModelMixin): ('properties', formatting.as_raw_dict(self.properties)), ('interface_templates', formatting.as_raw_list(self.interface_templates)))) - def validate(self): - # TODO: either type or name must be set - utils.validate_dict_values(self.properties) - utils.validate_dict_values(self.interface_templates) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) utils.coerce_dict_values(self.interface_templates, report_issues) @@ -1626,9 +1565,6 @@ class CapabilityTemplateBase(TemplateModelMixin): ('valid_source_node_types', [v.name for v in self.valid_source_node_types]), ('properties', formatting.as_raw_dict(self.properties)))) - def validate(self): - utils.validate_dict_values(self.properties) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) @@ -1780,10 +1716,6 @@ class InterfaceTemplateBase(TemplateModelMixin): # TODO fix self.properties reference ('operation_templates', formatting.as_raw_list(self.operation_templates)))) - def validate(self): - utils.validate_dict_values(self.inputs) - utils.validate_dict_values(self.operation_templates) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.inputs, report_issues) utils.coerce_dict_values(self.operation_templates, report_issues) @@ -1956,10 +1888,6 @@ class OperationTemplateBase(TemplateModelMixin): ('dependencies', self.dependencies), ('inputs', formatting.as_raw_dict(self.inputs)))) - def validate(self): - utils.validate_dict_values(self.inputs) - utils.validate_dict_values(self.configurations) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.inputs, report_issues) utils.coerce_dict_values(self.configurations, report_issues) @@ -2103,9 +2031,6 @@ class ArtifactTemplateBase(TemplateModelMixin): ('repository_credential', formatting.as_agnostic(self.repository_credential)), ('properties', formatting.as_raw_dict(self.properties)))) - def validate(self): - utils.validate_dict_values(self.properties) - def coerce_values(self, report_issues): utils.coerce_dict_values(self.properties, report_issues) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5fe109/aria/orchestrator/topology/__init__.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/topology/__init__.py b/aria/orchestrator/topology/__init__.py index c90f465..4109af6 100644 --- a/aria/orchestrator/topology/__init__.py +++ b/aria/orchestrator/topology/__init__.py @@ -13,4 +13,99 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .topology import Handler, handler +from ...modeling import models +from . import ( + template, + instance +) + +class Handler(object): + + _handlers = { + # Templates + models.ServiceTemplate: template.ServiceTemplate, + models.ArtifactTemplate: template.ArtifactTemplate, + models.CapabilityTemplate: template.CapabilityTemplate, + models.GroupTemplate: template.GroupTemplate, + models.InterfaceTemplate: template.InterfaceTemplate, + models.NodeTemplate: template.NodeTemplate, + models.PolicyTemplate: template.PolicyTemplate, + models.SubstitutionTemplate: template.SubstitutionTemplate, + models.SubstitutionTemplateMapping: template.SubstitutionMapping, + models.RelationshipTemplate: template.RelationshipTemplate, + models.OperationTemplate: template.OperationTemplate, + models.RequirementTemplate: template.RequirementTemplate, + + # Instances + models.Artifact: instance.Artifact, + models.Capability: instance.Capability, + models.Group: instance.Group, + models.Interface: instance.Interface, + models.Node: instance.Node, + models.Operation: instance.Operation, + models.Policy: instance.Policy, + models.Relationship: instance.Relationship, + models.Service: instance.Service, + models.Substitution: instance.Substitution, + models.SubstitutionMapping: instance.SubstitutionMapping, + models.Metadata: instance.Metadata, + + # Common + models.Attribute: instance.Parameter, + models.Property: instance.Parameter, + models.Input: instance.Parameter, + models.Output: instance.Parameter, + models.Configuration: instance.Parameter, + models.Argument: instance.Parameter, + } + + _instance_mapping = { + # Templates + 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.SubstitutionMapping: models.SubstitutionMapping, + models.RelationshipTemplate: models.Relationship, + models.OperationTemplate: models.Operation, + 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, + } + + def __init__(self, model_storage=None): + # TODO: model storage is required only for the list of plugins, can we get it + # somewhere else? + self._model_storage = model_storage + + def instantiate(self, template, **kwargs): + if isinstance(template, dict): + return dict((name, self.instantiate(value, **kwargs)) + for name, value in template.iteritems()) + elif isinstance(template, list): + return list(self.instantiate(value, **kwargs) for value in template) + elif template is not None: + handler = self._handlers.get(template.__class__) + instance_cls = self._instance_mapping[template.__class__] + return handler(self, template).instantiate(instance_cls, **kwargs) + + def validate(self, template, **kwargs): + if isinstance(template, dict): + return self.validate(template.values()) + elif isinstance(template, list): + return all(self.validate(value) for value in template) + elif template is not None: + handler = self._handlers.get(template.__class__) + return handler(self, template).validate(**kwargs) + + +handler = Handler() http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5fe109/aria/orchestrator/topology/common.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/topology/common.py b/aria/orchestrator/topology/common.py new file mode 100644 index 0000000..fb5cf50 --- /dev/null +++ b/aria/orchestrator/topology/common.py @@ -0,0 +1,41 @@ +# 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 _TemplateEntity(object): + def __init__(self, topology, template): + self._topology = topology + self._template = template + + def instantiate(self, **kwargs): + pass + + def coerce(self): + raise NotImplementedError + + def validate(self, **kwargs): + pass + + def _validate(self, *templates, **kwargs): + for template in templates: + self._topology.validate(template) + + def dump(self): + raise NotImplementedError + + +class _InstanceEntity(_TemplateEntity): + def instantiate(self, **kwargs): + pass http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5fe109/aria/orchestrator/topology/instance.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/topology/instance.py b/aria/orchestrator/topology/instance.py new file mode 100644 index 0000000..337c9d5 --- /dev/null +++ b/aria/orchestrator/topology/instance.py @@ -0,0 +1,208 @@ +# 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 . import common + + +class Artifact(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + self._topology.validate(self._template.properties) + + def dump(self): + pass + + +class Capability(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + self._topology.validate(self._template.properties) + + def dump(self): + pass + + +class Group(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + self._validate(self._template.properties, + self._template.interfaces) + + def dump(self): + pass + + +class Interface(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + self._validate(self._template.inputs, + self._template.operations) + + def dump(self): + pass + + +class Node(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + # TODO: fix the context + # context = ConsumptionContext.get_thread_local() + # if len(self._template.name) > context.modeling.id_max_length: + # pass + # context.validation.report('"{0}" has an ID longer than the limit of {1:d} characters: ' + # '{2:d}'.format( + # self.name, + # context.modeling.id_max_length, + # len(self.name)), + # level=validation.Issue.BETWEEN_INSTANCES) + + self._validate(self._template.properties, + self._template.attributes, + self._template.interfaces, + self._template.artifacts, + self._template.capabilities, + self._template.outbound_relationships) + + def dump(self): + pass + + +class Operation(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + self._validate(self._template.inputs, + self._template.configurations, + self._template.arguments) + + def dump(self): + pass + + +class Policy(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + self._topology.validate(self._template.properties) + + def dump(self): + pass + + +class Relationship(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + self._validate(self._template.properties, + self._template.interfaces) + + def dump(self): + pass + + +class Service(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + self._validate(self._template.meta_data, + self._template.nodes, + self._template.groups, + self._template.policies, + self._template.substituion, + self._template.inputs, + self._template.outputs, + self._template.workflows) + + def dump(self): + pass + + +class Substitution(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + self._topology.validate(self._template.mappings) + + def dump(self): + pass + + +class SubstitutionMapping(common._InstanceEntity): + def coerce(self): + pass + + def validate(self, **kwargs): + # context = ConsumptionContext.get_thread_local() + if (self._template.capability is None) and (self._template.requirement_template is None): + pass + # TODO: handler reports + # context.validation.report('mapping "{0}" refers to neither capability nor a requirement' + # ' in node: {1}'.format( + # self.name, + # formatting.safe_repr(self.node.name)), + # level=validation.Issue.BETWEEN_TYPES) + + def dump(self): + pass + + +class Metadata(common._InstanceEntity): + + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls, **kwargs): + return instance_cls(name=self._template.name, value=self._template.value) + + def validate(self): + pass + + +class Parameter(common._InstanceEntity): + + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls, **kwargs): + return instance_cls( + name=self._template.name, # pylint: disable=unexpected-keyword-arg + type_name=self._template.type_name, + _value=self._template._value, + description=self._template.description + ) + + def validate(self): + pass http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5fe109/aria/orchestrator/topology/template.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/topology/template.py b/aria/orchestrator/topology/template.py new file mode 100644 index 0000000..12fc23e --- /dev/null +++ b/aria/orchestrator/topology/template.py @@ -0,0 +1,383 @@ +# 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 ...modeling import utils as modeling_utils +from . import utils, common + + +class ServiceTemplate(common._TemplateEntity): + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls, inputs=None): + now = datetime.now() + service = instance_cls( + created_at=now, + updated_at=now, + description=utils.deepcopy_with_locators(self._template.description), + service_template=self._template, + inputs=modeling_utils.merge_parameter_values(inputs, self._template.inputs) + ) + + for plugin_specification in self._template.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: + # TODO: fix the context report usage + pass + # self._context.validation.report('specified plugin not found: {0}'.format( + # plugin_specification.name), level=validation.Issue.EXTERNAL) + service.meta_data = self._topology.instantiate(self._template.meta_data) + + for node_template in self._template.node_templates.itervalues(): + for _ in range(node_template.scaling['default_instances']): + node = self._topology.instantiate(node_template) + service.nodes[node.name] = node + + service.groups = self._topology.instantiate(self._template.group_templates) + service.policies = self._topology.instantiate(self._template.policy_templates) + service.workflows = self._topology.instantiate(self._template.workflow_templates) + + if self._template.substitution_template is not None: + service.substitution = self._topology.instantiate(self._template.substitution_template) + service.outputs = self._topology.instantiate(self._template.outputs) + + return service + + def validate(self): + self._topology.validate(self._template.meta_data) + self._topology.validate(self._template.node_templates) + self._topology.validate(self._template.group_templates) + self._topology.validate(self._template.policy_templates) + self._topology.validate(self._template.substitution_template) + self._topology.validate(self._template.inputs) + self._topology.validate(self._template.outputs) + self._topology.validate(self._template.workflow_templates) + self._topology.validate(self._template.node_types) + self._topology.validate(self._template.group_types) + self._topology.validate(self._template.policy_types) + self._topology.validate(self._template.relationship_types) + self._topology.validate(self._template.capability_types) + self._topology.validate(self._template.interface_types) + self._topology.validate(self._template.artifact_types) + + +class ArtifactTemplate(common._TemplateEntity): + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + return instance_cls( + name=self._template.name, + type=self._template.type, + description=utils.deepcopy_with_locators(self._template.description), + source_path=self._template.source_path, + target_path=self._template.target_path, + repository_url=self._template.repository_url, + repository_credential=self._template.repository_credential, + artifact_template=self._template) + + def validate(self): + self._topology.validate(self._template.properties) + + +class CapabilityTemplate(common._TemplateEntity): + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + return instance_cls(name=self._template.name, + type=self._template.type, + min_occurrences=self._template.min_occurrences, + max_occurrences=self._template.max_occurrences, + occurrences=0, + capability_template=self._template) + + def validate(self): + self._topology.validate(self._template.properties) + + +class RequirementTemplate(common._TemplateEntity): + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + return instance_cls(name=self._template.name, + type=self._template.type, + min_occurrences=self._template.min_occurrences, + max_occurrences=self._template.max_occurrences, + occurrences=0, + capability_template=self._template) + + def validate(self): + self._topology.validate(self._template.relationship_template) + + +class GroupTemplate(common._TemplateEntity): + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + group = instance_cls( + name=self._template.name, + type=self._template.type, + description=utils.deepcopy_with_locators(self._template.description), + group_template=self._template) + group.properties = self._topology.instantiate(self._template.properties) + group.interfaces = self._topology.instantiate(self._template.interface_templates) + if self._template.node_templates: + for node_template in self._template.node_templates: + group.nodes += node_template.nodes + return group + + def validate(self): + self._validate(self._template.properties, + self._template.interface_templates) + + +class InterfaceTemplate(common._TemplateEntity): + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + interface = instance_cls( + name=self._template.name, + type=self._template.type, + description=utils.deepcopy_with_locators(self._template.description), + interface_template=self._template) + interface.inputs = self._topology.instantiate(self._template.inputs) + interface.operations = self._topology.instantiate(self._template.operation_templates) + return interface + + def validate(self): + self._validate(self._template.inputs, + self._template.operation_templates) + + +class NodeTemplate(common._TemplateEntity): + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + node = instance_cls( + name=self._template._next_name, + type=self._template.type, + description=utils.deepcopy_with_locators(self._template.description), + node_template=self._template + ) + + node.properties = self._topology.instantiate(self._template.properties) + node.attributes = self._topology.instantiate(self._template.attributes) + node.interfaces = self._topology.instantiate(self._template.interface_templates) + node.artifacts = self._topology.instantiate(self._template.artifact_templates) + node.capabilities = self._topology.instantiate(self._template.capability_templates) + + # Default attributes + if ('tosca_name' in node.attributes) \ + and (node.attributes['tosca_name'].type_name == 'string'): + node.attributes['tosca_name'].value = self._template.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._template.properties, + self._template.attributes, + self._template.interface_templates, + self._template.artifact_templates, + self._template.capability_templates, + self._template.requirement_templates) + + +class PolicyTemplate(common._TemplateEntity): + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + policy = instance_cls( + name=self._template.name, + type=self._template.type, + description=utils.deepcopy_with_locators(self._template.description), + policy_template=self._template) + + policy.properties = self._topology.instantiate(self._template.properties) + if self._template.node_templates: + for node_template in self._template.node_templates: + policy.nodes += node_template.nodes + if self._template.group_templates: + for group_template in self._template.group_templates: + policy.groups += group_template.groups + return policy + + def validate(self): + self._topology.validate(self._template.properties) + + +class SubstitutionTemplate(common._TemplateEntity): + + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + return instance_cls(node_type=self._template.node_type, + substitution_template=self._template) + + def validate(self): + self._topology.validate(self._template.mappings) + + +class SubstitutionMapping(common._TemplateEntity): + + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + substitution_mapping = instance_cls( + name=self._template.name, + requirement_template=self._template.requirement_template) + + if self._template.capability_template is not None: + node_template = self._template.capability_template.node_template + else: + node_template = self._template.requirement_template.node_template + nodes = node_template.nodes + if len(nodes) == 0: + # TODO: manage the context report + # self._context.validation.report( + # 'mapping "{0}" refers to node template "{1}" but there are no node instances'. + # format(self._template.mapped_name, + # self._template.node_template.name), + # level=validation.Issue.BETWEEN_INSTANCES) + return None + # The TOSCA spec does not provide a way to choose the node, + # so we will just pick the first one + substitution_mapping.node = nodes[0] + if self._template.capability_template: + for a_capability in substitution_mapping.node.capabilities.itervalues(): + if a_capability.capability_template.name == \ + self._template.capability_template.name: + substitution_mapping.capability = a_capability + + return substitution_mapping + + def validate(self): + # context = ConsumptionContext.get_thread_local() + if all([ + self._template.capability_template is None, + self._template.requirement_template is None + ]): + pass + # TODO: handle reporting + # context.validation.report('mapping "{0}" refers to neither capability nor a requirement' + # ' in node template: {1}'.format( + # self.name, + # formatting.safe_repr(self.node_template.name)), + # level=validation.Issue.BETWEEN_TYPES) + + +class RelationshipTemplate(common._TemplateEntity): + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + relationship = instance_cls( + name=self._template.name, + type=self._template.type, + relationship_template=self._template) + + relationship.properties = self._topology.instantiate(self._template.properties) + relationship.interfaces = self._topology.instantiate(self._template.interface_templates) + return relationship + + def validate(self): + # TODO: either type or name must be set + self._validate(self._template.properties, + self._template.interface_templates) + + +class OperationTemplate(common._TemplateEntity): + + def dump(self): + pass + + def coerce(self): + pass + + def instantiate(self, instance_cls): + operation = instance_cls( + name=self._template.name, + description=utils.deepcopy_with_locators(self._template.description), + relationship_edge=self._template.relationship_edge, + implementation=self._template.implementation, + dependencies=self._template.dependencies, + executor=self._template.executor, + function=self._template.function, + max_attempts=self._template.max_attempts, + retry_interval=self._template.retry_interval, + operation_template=self._template) + + if (self._template.plugin_specification is not None and + self._template.plugin_specification.enabled): + operation.plugin = self._template.plugin_specification.plugin + + operation.inputs = self._topology.instantiate(self._template.inputs) + operation.configurations = self._topology.instantiate(self._template.configurations) + + return operation + + def validate(self): + self._validate(self._template.inputs, + self._template.configurations) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/8e5fe109/aria/orchestrator/topology/topology.py ---------------------------------------------------------------------- diff --git a/aria/orchestrator/topology/topology.py b/aria/orchestrator/topology/topology.py deleted file mode 100644 index c79c445..0000000 --- a/aria/orchestrator/topology/topology.py +++ /dev/null @@ -1,476 +0,0 @@ -# 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 ...modeling import ( - utils as modeling_utils, - models -) -from . import utils - - -class _Entity(object): - - def __init__(self, topology_initiator, template, _instance_cls): - self._topology = topology_initiator - self._template = template - self._instance_cls = _instance_cls - - def instantiate(self, **kwargs): - raise NotImplementedError - - def coerce(self): - raise NotImplementedError - - def validate(self): - raise NotImplementedError - - def dump(self): - raise NotImplementedError - - -class Handler(object): - def __init__(self, model_storage=None): - # TODO: model storage is required only for the list of plugins, can we get it - # somewhere else? - self._model_storage = model_storage - self._handlers = { - models.ServiceTemplate: ServiceInstance, - models.ArtifactTemplate: Artifact, - models.CapabilityTemplate: Capability, - models.GroupTemplate: Group, - models.InterfaceTemplate: Interface, - models.NodeTemplate: Node, - models.PolicyTemplate: Policy, - models.SubstitutionTemplate: Substitution, - models.SubstitutionMapping: SubstitutionMapping, - models.RelationshipTemplate: Relationship, - models.OperationTemplate: Operation, - models.Metadata: Metadata, - - models.Attribute: Parameter, - models.Property: Parameter, - models.Input: Parameter, - models.Output: Parameter, - models.Configuration: Parameter, - models.Argument: Parameter, - - } - - def instantiate(self, template, **kwargs): - if isinstance(template, dict): - return dict((name, self.instantiate(value, **kwargs)) - for name, value in template.iteritems()) - elif isinstance(template, list): - return list(self.instantiate(value, **kwargs) for value in template) - else: - handler = self._handlers[template.__class__] - return handler(self, template).instantiate(**kwargs) - - -class ServiceInstance(_Entity): - - def __init__(self, *args, **kwargs): - super(ServiceInstance, self).__init__(*args, _instance_cls=models.Service, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self, inputs=None): - now = datetime.now() - service = self._instance_cls( - created_at=now, - updated_at=now, - description=utils.deepcopy_with_locators(self._template.description), - service_template=self._template, - inputs=modeling_utils.merge_parameter_values(inputs, self._template.inputs) - ) - - for plugin_specification in self._template.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: - # TODO: fix the context report usage - pass - # self._context.validation.report('specified plugin not found: {0}'.format( - # plugin_specification.name), level=validation.Issue.EXTERNAL) - service.meta_data = self._topology.instantiate(self._template.meta_data) - - for node_template in self._template.node_templates.itervalues(): - for _ in range(node_template.scaling['default_instances']): - node = self._topology.instantiate(node_template) - service.nodes[node.name] = node - - service.groups = self._topology.instantiate(self._template.group_templates) - service.policies = self._topology.instantiate(self._template.policy_templates) - service.workflows = self._topology.instantiate(self._template.workflow_templates) - - if self._template.substitution_template is not None: - service.substitution = self._topology.instantiate(self._template.substitution_template) - service.outputs = self._topology.instantiate(self._template.outputs) - - return service - - def validate(self): - pass - - -class Artifact(_Entity): - - def __init__(self, *args, **kwargs): - super(Artifact, self).__init__(*args, _instance_cls=models.Artifact, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - return self._instance_cls( - name=self._template.name, - type=self._template.type, - description=utils.deepcopy_with_locators(self._template.description), - source_path=self._template.source_path, - target_path=self._template.target_path, - repository_url=self._template.repository_url, - repository_credential=self._template.repository_credential, - artifact_template=self._template) - - def validate(self): - pass - - -class Capability(_Entity): - def __init__(self, *args, **kwargs): - super(Capability, self).__init__(*args, _instance_cls=models.Capability, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - return self._instance_cls(name=self._template.name, - type=self._template.type, - min_occurrences=self._template.min_occurrences, - max_occurrences=self._template.max_occurrences, - occurrences=0, - capability_template=self._template) - - def validate(self): - pass - - -class Group(_Entity): - - def __init__(self, *args, **kwargs): - super(Group, self).__init__(*args, _instance_cls=models.Group, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - group = self._instance_cls( - name=self._template.name, - type=self._template.type, - description=utils.deepcopy_with_locators(self._template.description), - group_template=self._template) - group.properties = self._topology.instantiate(self._template.properties) - group.interfaces = self._topology.instantiate(self._template.interface_templates) - if self._template.node_templates: - for node_template in self._template.node_templates: - group.nodes += node_template.nodes - return group - - def validate(self): - pass - - -class Interface(_Entity): - - def __init__(self, *args, **kwargs): - super(Interface, self).__init__(*args, _instance_cls=models.Interface, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - interface = self._instance_cls( - name=self._template.name, - type=self._template.type, - description=utils.deepcopy_with_locators(self._template.description), - interface_template=self._template) - interface.inputs = self._topology.instantiate(self._template.inputs) - interface.operations = self._topology.instantiate(self._template.operation_templates) - return interface - - def validate(self): - pass - - -class Node(_Entity): - - def __init__(self, *args, **kwargs): - super(Node, self).__init__(*args, _instance_cls=models.Node, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - node = self._instance_cls( - name=self._template._next_name, - type=self._template.type, - description=utils.deepcopy_with_locators(self._template.description), - state=models.Node.INITIAL, - node_template=self._template - ) - - node.properties = self._topology.instantiate(self._template.properties) - node.attributes = self._topology.instantiate(self._template.attributes) - node.interfaces = self._topology.instantiate(self._template.interface_templates) - node.artifacts = self._topology.instantiate(self._template.artifact_templates) - node.capabilities = self._topology.instantiate(self._template.capability_templates) - - # Default attributes - if ('tosca_name' in node.attributes) \ - and (node.attributes['tosca_name'].type_name == 'string'): - node.attributes['tosca_name'].value = self._template.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): - pass - - -class Policy(_Entity): - - def __init__(self, *args, **kwargs): - super(Policy, self).__init__(*args, _instance_cls=models.Policy, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - policy = self._instance_cls( - name=self._template.name, - type=self._template.type, - description=utils.deepcopy_with_locators(self._template.description), - policy_template=self._template) - - policy.properties = self._topology.instantiate(self._template.properties) - if self._template.node_templates: - for node_template in self._template.node_templates: - policy.nodes += node_template.nodes - if self._template.group_templates: - for group_template in self._template.group_templates: - policy.groups += group_template.groups - return policy - - def validate(self): - pass - - -class Parameter(_Entity): - def __init__(self, topology_initiator, template, *args, **kwargs): - super(Parameter, self).__init__( - topology_initiator, template, *args, _instance_cls=template.__class__, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - return self._instance_cls( - name=self._template.name, # pylint: disable=unexpected-keyword-arg - type_name=self._template.type_name, - _value=self._template._value, - description=self._template.description - ) - - def validate(self): - pass - - -class Substitution(_Entity): - def __init__(self, *args, **kwargs): - super(Substitution, self).__init__(_instance_cls=models.Substitution, *args, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - return self._instance_cls(node_type=self._template.node_type, - substitution_template=self._template) - - def validate(self): - pass - - -class SubstitutionMapping(_Entity): - - def __init__(self, *args, **kwargs): - super(SubstitutionMapping, self).__init__( - _instance_cls=models.SubstitutionMapping, *args, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - substitution_mapping = self._instance_cls( - name=self._template.name, - requirement_template=self._template.requirement_template) - - if self._template.capability_template is not None: - node_template = self._template.capability_template.node_template - else: - node_template = self._template.requirement_template.node_template - nodes = node_template.nodes - if len(nodes) == 0: - # TODO: manage the context report - # self._context.validation.report( - # 'mapping "{0}" refers to node template "{1}" but there are no node instances'. - # format(self._template.mapped_name, - # self._template.node_template.name), - # level=validation.Issue.BETWEEN_INSTANCES) - return None - # The TOSCA spec does not provide a way to choose the node, - # so we will just pick the first one - substitution_mapping.node = nodes[0] - if self._template.capability_template: - for a_capability in substitution_mapping.node.capabilities.itervalues(): - if a_capability.capability_template.name == \ - self._template.capability_template.name: - substitution_mapping.capability = a_capability - - return substitution_mapping - - def validate(self): - pass - - -class Relationship(_Entity): - - def __init__(self, *args, **kwargs): - super(Relationship, self).__init__(_instance_cls=models.Relationship, *args, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - relationship = self._instance_cls( - name=self._template.name, - type=self._template.type, - relationship_template=self._template) - - relationship.properties = self._topology.instantiate(self._template.properties) - relationship.interfaces = self._topology.instantiate(self._template.interface_templates) - return relationship - - def validate(self): - pass - - -class Operation(_Entity): - - def __init__(self, *args, **kwargs): - super(Operation, self).__init__(_instance_cls=models.Operation, *args, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - operation = self._instance_cls( - name=self._template.name, - description=utils.deepcopy_with_locators(self._template.description), - relationship_edge=self._template.relationship_edge, - implementation=self._template.implementation, - dependencies=self._template.dependencies, - executor=self._template.executor, - function=self._template.function, - max_attempts=self._template.max_attempts, - retry_interval=self._template.retry_interval, - operation_template=self._template) - - - if (self._template.plugin_specification is not None and - self._template.plugin_specification.enabled): - operation.plugin = self._template.plugin_specification.plugin - - operation.inputs = self._topology.instantiate(self._template.inputs) - operation.configurations = self._topology.instantiate(self._template.configurations) - - return operation - - def validate(self): - pass - - -class Metadata(_Entity): - - def __init__(self, *args, **kwargs): - super(Metadata, self).__init__(_instance_cls=models.Metadata, *args, **kwargs) - - def dump(self): - pass - - def coerce(self): - pass - - def instantiate(self): - return self._instance_cls(name=self._template.name, value=self._template.value) - - def validate(self): - pass - - -handler = Handler()
