You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ariatosca.apache.org by mx...@apache.org on 2017/07/23 11:38:48 UTC
incubator-ariatosca git commit: fixed small bugs,
moved topolgy to orchestrator [Forced Update!]
Repository: incubator-ariatosca
Updated Branches:
refs/heads/ARIA-174-Refactor-instantiation-phase 67e7f4d74 -> 609d305d7 (forced update)
fixed small bugs, moved topolgy to orchestrator
Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/609d305d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/609d305d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/609d305d
Branch: refs/heads/ARIA-174-Refactor-instantiation-phase
Commit: 609d305d75c07af6d3028ba0cb9a2f98cbe87830
Parents: f31e3ea
Author: max-orlov <ma...@gigaspaces.com>
Authored: Sun Jul 23 14:33:23 2017 +0300
Committer: max-orlov <ma...@gigaspaces.com>
Committed: Sun Jul 23 14:38:43 2017 +0300
----------------------------------------------------------------------
aria/core.py | 4 +-
aria/modeling/service_instance.py | 14 +-
aria/modeling/service_template.py | 3 -
aria/orchestrator/topology/__init__.py | 16 +
aria/orchestrator/topology/topology.py | 293 +++++++++++++++++
aria/orchestrator/topology/utils.py | 48 +++
aria/parser/consumption/modeling.py | 31 +-
aria/parser/reading/__init__.py | 4 +-
aria/parser/reading/locator.py | 33 --
aria/parser/topology/__init__.py | 16 -
aria/parser/topology/topology.py | 319 -------------------
.../simple_v1_0/modeling/__init__.py | 4 +-
tests/instantiation/test_configuration.py | 11 +-
13 files changed, 400 insertions(+), 396 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/core.py
----------------------------------------------------------------------
diff --git a/aria/core.py b/aria/core.py
index a12554e..c3fe96f 100644
--- a/aria/core.py
+++ b/aria/core.py
@@ -17,8 +17,9 @@
ARIA core module.
"""
+from aria.orchestrator import topology
from . import exceptions
-from .parser import consumption, topology
+from .parser import consumption
from .parser.loading.location import UriLocation
@@ -67,7 +68,6 @@ class Core(object):
self.resource_storage.service_template.delete(entry_id=str(service_template.id))
def create_service(self, service_template_id, inputs, service_name=None):
- import pydevd; pydevd.settrace('localhost', suspend=False)
service_template = self.model_storage.service_template.get(service_template_id)
storage_session = self.model_storage._all_api_kwargs['session']
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/modeling/service_instance.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_instance.py b/aria/modeling/service_instance.py
index c34ace0..2eaead2 100644
--- a/aria/modeling/service_instance.py
+++ b/aria/modeling/service_instance.py
@@ -30,6 +30,11 @@ from sqlalchemy import DateTime
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.orderinglist import ordering_list
+from . import (
+ relationship,
+ utils,
+ types as modeling_types
+)
from .mixins import InstanceModelMixin
from ..orchestrator import execution_plugin
from ..parser import validation
@@ -39,11 +44,6 @@ from ..utils import (
formatting,
console
)
-from . import (
- relationship,
- utils,
- types as modeling_types
-)
class ServiceBase(InstanceModelMixin):
@@ -659,7 +659,7 @@ class NodeBase(InstanceModelMixin):
if target_node is not None:
if requirement_template.relationship_template is not None:
- from ..parser import topology
+ from aria.orchestrator import topology
relationship_model = topology.initiator.instantiate(requirement_template.relationship_template)
else:
relationship_model = models.Relationship()
@@ -1945,7 +1945,7 @@ class OperationBase(InstanceModelMixin):
""")
def configure(self):
- from ..parser import topology
+ from aria.orchestrator import topology
if (self.implementation is None) and (self.function is None):
return
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index 8b26d15..0cbfdb6 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -21,8 +21,6 @@ ARIA modeling service template module
from __future__ import absolute_import # so we can import standard 'types'
-from datetime import datetime
-
from sqlalchemy import (
Column,
Text,
@@ -35,7 +33,6 @@ from sqlalchemy.ext.declarative import declared_attr
from ..parser import validation
from ..parser.consumption import ConsumptionContext
-from ..parser.reading import deepcopy_with_locators
from ..utils import (collections, formatting, console)
from ..utils.versions import VersionString
from .mixins import TemplateModelMixin
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/orchestrator/topology/__init__.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/__init__.py b/aria/orchestrator/topology/__init__.py
new file mode 100644
index 0000000..ae9c900
--- /dev/null
+++ b/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 Instantiation, initiator
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/orchestrator/topology/topology.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/topology.py b/aria/orchestrator/topology/topology.py
new file mode 100644
index 0000000..abe8cd6
--- /dev/null
+++ b/aria/orchestrator/topology/topology.py
@@ -0,0 +1,293 @@
+# 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 functools import partial
+from contextlib import contextmanager
+
+
+from ...modeling import (
+ utils as modeling_utils,
+ models
+)
+from ...parser import validation, consumption
+from . import utils
+
+
+class Instantiation(object):
+
+ def __init__(self, context):
+ self._context = context or consumption.ConsumptionContext()
+ self._initiators = {
+ 'meta_data': self._instantiate_metadata,
+ 'node_template': self._instantiate_node,
+ 'substitution_template': self._instantiate_substitution,
+ 'workflow_templates': self._instantiate_operation,
+ 'operation_templates': self._instantiate_operation,
+ 'interface_templates': self._instantiate_interface,
+ 'artifact_templates': self._instantiate_artifact,
+ 'capability_templates': self._instantiate_capability,
+ 'group_templates': self._instantiate_group,
+ 'policy_templates': self._instantiate_policy,
+ 'relationship_template': self._instantiate_relationship,
+
+ # Parameter-Based instantiations
+ 'argument': partial(self._instantiate_parameter, model_cls=models.Argument),
+
+ 'inputs': partial(self._instantiate_parameter, model_cls=models.Input),
+ 'outputs': partial(self._instantiate_parameter, model_cls=models.Output),
+ 'properties': partial(self._instantiate_parameter, model_cls=models.Property),
+ 'attributes': partial(self._instantiate_parameter, model_cls=models.Attribute),
+ 'configurations': partial(self._instantiate_parameter, model_cls=models.Configuration),
+
+ }
+ self._model_storage = None
+
+ @property
+ def _has_model_storage(self):
+ return self._model_storage is not None
+
+ @contextmanager
+ def push_model_storage(self, model_storage):
+ original_model_storage = self._model_storage
+ self._model_storage = model_storage
+ yield self
+ self._model_storage = original_model_storage
+
+ def instantiate_service(self, service_template, inputs=None):
+
+ now = datetime.now()
+ service = models.Service(
+ created_at=now,
+ updated_at=now,
+ description=utils.deepcopy_with_locators(service_template.description),
+ service_template=service_template
+ )
+
+ self._context.modeling.instance = service
+
+ service.inputs = modeling_utils.merge_parameter_values(inputs, service_template.inputs)
+ # TODO: now that we have inputs, we should scan properties and inputs and evaluate functions
+
+ for plugin_specification in service_template.plugin_specifications.itervalues():
+ if plugin_specification.enabled:
+ if plugin_specification.resolve(self._model_storage):
+ plugin = plugin_specification.plugin
+ service.plugins[plugin.name] = plugin
+ else:
+ self._context.validation.report('specified plugin not found: {0}'.format(
+ plugin_specification.name), level=validation.Issue.EXTERNAL)
+
+ service.meta_data = self.instantiate(service_template.meta_data)
+
+ for node_template in service_template.node_templates.itervalues():
+ for _ in range(node_template.scaling['default_instances']):
+ node = self.instantiate(node_template)
+ service.nodes[node.name] = node
+
+ service.groups = self.instantiate(service_template.group_templates)
+ service.policies = self.instantiate(service_template.policy_templates)
+ service.workflows = self.instantiate(service_template.workflow_templates)
+
+ if service_template.substitution_template is not None:
+ service.substitution = self.instantiate(service_template.substitution_template)
+ service.outputs = self.instantiate(service_template.outputs)
+
+ return service
+
+ def instantiate(self, source_template):
+ if isinstance(source_template, (dict, list)):
+ initiator = self._initiators[source_template._sa_adapter.attr.key]
+ if isinstance(source_template, dict):
+ dict_ = {}
+ for name, value in source_template.iteritems():
+ value = initiator(value)
+ if value is not None:
+ dict_[name] = value
+ return dict_
+ elif isinstance(source_template, list):
+ list_ = []
+ for value in source_template:
+ value = initiator(value)
+ if value is not None:
+ list_.append(value)
+ return list_
+ else:
+ return self._initiators[source_template.__tablename__](source_template)
+
+ @staticmethod
+ def _instantiate_artifact(artifact_template):
+ artifact = models.Artifact(
+ name=artifact_template.name,
+ type=artifact_template.type,
+ description=utils.deepcopy_with_locators(artifact_template.description),
+ source_path=artifact_template.source_path,
+ target_path=artifact_template.target_path,
+ repository_url=artifact_template.repository_url,
+ repository_credential=artifact_template.repository_credential,
+ artifact_template=artifact_template)
+ return artifact
+
+ @staticmethod
+ def _instantiate_capability(capability_template):
+ capability = models.Capability(name=capability_template.name,
+ type=capability_template.type,
+ min_occurrences=capability_template.min_occurrences,
+ max_occurrences=capability_template.max_occurrences,
+ occurrences=0,
+ capability_template=capability_template)
+ return capability
+
+ def _instantiate_group(self, group_template):
+ group = models.Group(name=group_template.name,
+ type=group_template.type,
+ description=utils.deepcopy_with_locators(group_template.description),
+ group_template=group_template)
+ group.properties = self.instantiate(group_template.properties)
+ group.interfaces = self.instantiate(group_template.interface_templates)
+ if group_template.node_templates:
+ for node_template in group_template.node_templates:
+ group.nodes += node_template.nodes
+ return group
+
+ def _instantiate_interface(self, interface_template):
+ interface = models.Interface(
+ name=interface_template.name,
+ type=interface_template.type,
+ description=utils.deepcopy_with_locators(interface_template.description),
+ interface_template=interface_template)
+ interface.inputs = self.instantiate(interface_template.inputs)
+ interface.operations = self.instantiate(interface_template.operation_templates)
+ return interface
+
+ def _instantiate_node(self, node_template):
+ node = models.Node(
+ name=node_template._next_name,
+ type=node_template.type,
+ description=utils.deepcopy_with_locators(node_template.description),
+ state=models.Node.INITIAL,
+ node_template=node_template
+ )
+ node.properties = self.instantiate(node_template.properties)
+ node.attributes = self.instantiate(node_template.attributes)
+ node.interfaces = self.instantiate(node_template.interface_templates)
+ node.artifacts = self.instantiate(node_template.artifact_templates)
+ node.capabilities = self.instantiate(node_template.capability_templates)
+
+ # Default attributes
+ if ('tosca_name' in node.attributes) \
+ and (node.attributes['tosca_name'].type_name == 'string'):
+ node.attributes['tosca_name'].value = node_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 _instantiate_policy(self, policy_template):
+ policy = models.Policy(
+ name=policy_template.name,
+ type=policy_template.type,
+ description=utils.deepcopy_with_locators(policy_template.description),
+ policy_template=policy_template)
+ policy.properties = self.instantiate(policy_template.properties)
+ if policy_template.node_templates:
+ for node_template in policy_template.node_templates:
+ policy.nodes += node_template.nodes
+ if policy_template.group_templates:
+ for group_template in policy_template.group_templates:
+ policy.groups += group_template.groups
+ return policy
+
+ @staticmethod
+ def _instantiate_parameter(parameter_template, model_cls):
+ return model_cls(
+ name=parameter_template.name, # pylint: disable=unexpected-keyword-arg
+ type_name=parameter_template.type_name,
+ _value=parameter_template._value,
+ description=parameter_template.description
+ )
+
+ @staticmethod
+ def _instantiate_substitution(substitution_template):
+ substitution = models.Substitution(node_type=substitution_template.node_type,
+ substitution_template=substitution_template)
+ return substitution
+
+ @staticmethod
+ def _instantiate_metadata(metadata_template):
+ return models.Metadata(name=metadata_template.name, value=metadata_template.value)
+
+ def _instantiate_substitution_mapping(self, substitution_mapping):
+ if substitution_mapping.capability_template is not None:
+ node_template = substitution_mapping.capability_template.node_template
+ else:
+ node_template = substitution_mapping.requirement_template.node_template
+ nodes = node_template.nodes
+ if len(nodes) == 0:
+ self._context.validation.report(
+ 'mapping "{0}" refers to node template "{1}" but there are no node instances'.
+ format(substitution_mapping.mapped_name,
+ substitution_mapping.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
+ node = nodes[0]
+ capability = None
+ if substitution_mapping.capability_template:
+ for a_capability in node.capabilities.itervalues():
+ if a_capability.capability_template.name == \
+ substitution_mapping.capability_template.name:
+ capability = a_capability
+ return models.SubstitutionMapping(
+ name=substitution_mapping.name,
+ capability=capability,
+ requirement_template=substitution_mapping.requirement_template,
+ node=node)
+
+ def _instantiate_relationship(self, relationship_template):
+ relationship_model = models.Relationship(name=relationship_template.name,
+ type=relationship_template.type,
+ relationship_template=relationship_template)
+ relationship_model.properties = self.instantiate(relationship_template.properties)
+ relationship_model.interfaces = self.instantiate(relationship_template.interface_templates)
+ return relationship_model
+
+ def _instantiate_operation(self, operation_template):
+ plugin = None
+ if (operation_template.plugin_specification is not None and
+ operation_template.plugin_specification.enabled):
+ plugin = operation_template.plugin_specification.plugin
+
+ operation = models.Operation(
+ name=operation_template.name,
+ description=utils.deepcopy_with_locators(operation_template.description),
+ relationship_edge=operation_template.relationship_edge,
+ implementation=operation_template.implementation,
+ dependencies=operation_template.dependencies,
+ executor=operation_template.executor,
+ plugin=plugin,
+ function=operation_template.function,
+ max_attempts=operation_template.max_attempts,
+ retry_interval=operation_template.retry_interval,
+ operation_template=operation_template)
+
+ operation.inputs = self.instantiate(operation_template.inputs)
+ operation.configurations = self.instantiate(operation_template.configurations)
+
+ return operation
+
+
+initiator = Instantiation(consumption.ConsumptionContext.get_thread_local())
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/orchestrator/topology/utils.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/topology/utils.py b/aria/orchestrator/topology/utils.py
new file mode 100644
index 0000000..ec74391
--- /dev/null
+++ b/aria/orchestrator/topology/utils.py
@@ -0,0 +1,48 @@
+# 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
+
+
+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])
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/parser/consumption/modeling.py
----------------------------------------------------------------------
diff --git a/aria/parser/consumption/modeling.py b/aria/parser/consumption/modeling.py
index 8c46abf..e142327 100644
--- a/aria/parser/consumption/modeling.py
+++ b/aria/parser/consumption/modeling.py
@@ -13,8 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from ...utils.formatting import json_dumps, yaml_dumps
from .consumer import Consumer, ConsumerChain
+from ...utils.formatting import json_dumps, yaml_dumps
+from ... import exceptions
class DeriveServiceTemplate(Consumer):
@@ -105,11 +106,29 @@ class InstantiateServiceInstance(Consumer):
self.context.validation.report('InstantiateServiceInstance consumer: missing service '
'template')
return
- from .. import topology
- topology.initiator.instantiate_service(self.context.modeling.template,
- inputs=dict(self.context.modeling.inputs))
- # TODO: fix this, it looks bad.
- self.context.modeling.instance = self.context.modeling.template.services[None]
+ from aria.orchestrator import topology
+
+ self.context.modeling.instance = topology.Instantiation(self.context).instantiate_service(
+ self.context.modeling.template,
+ inputs=dict(self.context.modeling.inputs)
+ )
+
+ ConsumerChain(
+ self.context,
+ (
+ CoerceServiceInstanceValues,
+ ValidateServiceInstance,
+ SatisfyRequirements,
+ CoerceServiceInstanceValues,
+ ValidateCapabilities,
+ FindHosts,
+ ConfigureOperations,
+ CoerceServiceInstanceValues
+ )).consume()
+
+ if self.context.validation.dump_issues():
+ raise exceptions.InstantiationError('Failed to instantiate service template `{0}`'
+ .format(self.context.modeling.template.name))
class CoerceServiceInstanceValues(Consumer):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/parser/reading/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/reading/__init__.py b/aria/parser/reading/__init__.py
index 065ca56..9fab5df 100644
--- a/aria/parser/reading/__init__.py
+++ b/aria/parser/reading/__init__.py
@@ -36,7 +36,7 @@ Reading package.
from .raw import RawReader
from .reader import Reader
from .yaml import YamlReader
-from .locator import (Locator, deepcopy_with_locators, copy_locators)
+from .locator import Locator
from .json import JsonReader
from .jinja import JinjaReader
from .context import ReadingContext
@@ -57,8 +57,6 @@ __all__ = (
'ReadingContext',
'RawReader',
'Locator',
- 'deepcopy_with_locators',
- 'copy_locators',
'YamlReader',
'JsonReader',
'JinjaReader')
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/parser/reading/locator.py
----------------------------------------------------------------------
diff --git a/aria/parser/reading/locator.py b/aria/parser/reading/locator.py
index 965164d..8bbb178 100644
--- a/aria/parser/reading/locator.py
+++ b/aria/parser/reading/locator.py
@@ -10,9 +10,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from copy import deepcopy
-
-
from ...utils.console import puts, Colored, indent
@@ -122,33 +119,3 @@ class Locator(object):
return '"%s":%d:%d' % (self.location, self.line, self.column)
-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])
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/parser/topology/__init__.py
----------------------------------------------------------------------
diff --git a/aria/parser/topology/__init__.py b/aria/parser/topology/__init__.py
deleted file mode 100644
index 7bc09e7..0000000
--- a/aria/parser/topology/__init__.py
+++ /dev/null
@@ -1,16 +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 .topology import initiator
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/aria/parser/topology/topology.py
----------------------------------------------------------------------
diff --git a/aria/parser/topology/topology.py b/aria/parser/topology/topology.py
deleted file mode 100644
index d91a96f..0000000
--- a/aria/parser/topology/topology.py
+++ /dev/null
@@ -1,319 +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 contextlib import contextmanager
-from datetime import datetime
-from functools import partial
-
-from aria import exceptions
-
-from ... modeling import (
- utils,
- models
-)
-from .. import (
- reading,
- consumption,
- validation,
-)
-
-
-class _Instantiation(object):
-
- def __init__(self):
- self._initiators = {
- 'meta_data': self._instantiate_metadata,
- 'node_template': self._instantiate_node,
- 'substitution_template': self._instantiate_substitution,
- 'workflow_templates': self._instantiate_operation,
- 'operation_templates': self._instantiate_operation,
- 'interface_templates': self._instantiate_interface,
- 'artifact_templates': self._instantiate_artifact,
- 'capability_templates': self._instantiate_capability,
- 'group_templates': self._instantiate_group,
- 'policy_templates': self._instantiate_policy,
- 'relationship_template': self._instantiate_relationship,
-
- # Parameter-Based instantiations
- 'argument': partial(self._instantiate_parameter, model_cls=models.Argument),
-
- 'inputs': partial(self._instantiate_parameter, model_cls=models.Input),
- 'outputs': partial(self._instantiate_parameter, model_cls=models.Output),
- 'properties': partial(self._instantiate_parameter, model_cls=models.Property),
- 'attributes': partial(self._instantiate_parameter, model_cls=models.Attribute),
- 'configurations': partial(self._instantiate_parameter, model_cls=models.Configuration),
-
- }
- self._model_storage = None
-
- @property
- def _has_model_storage(self):
- return self._model_storage is not None
-
- @contextmanager
- def push_model_storage(self, model_storage):
- original_model_storage = self._model_storage
- self._model_storage = model_storage
- yield self
- self._model_storage = original_model_storage
-
- def instantiate_service(self, service_template, inputs=None):
-
- # creating an empty ConsumptionContext, initiating a threadlocal context
- context = consumption.ConsumptionContext(set_thread_local=True)
-
- now = datetime.now()
- service = models.Service(
- created_at=now,
- updated_at=now,
- description=reading.deepcopy_with_locators(service_template.description),
- service_template=service_template
- )
-
- context.modeling.instance = service
-
- service.inputs = utils.merge_parameter_values(inputs, service_template.inputs)
- # TODO: now that we have inputs, we should scan properties and inputs and evaluate functions
-
- for plugin_specification in service_template.plugin_specifications.itervalues():
- if plugin_specification.enabled:
- if plugin_specification.resolve(self._model_storage):
- plugin = plugin_specification.plugin
- service.plugins[plugin.name] = plugin
- else:
- context = consumption.ConsumptionContext.get_thread_local()
- context.validation.report('specified plugin not found: {0}'.format(
- plugin_specification.name), level=validation.Issue.EXTERNAL)
-
- service.meta_data = self.instantiate(service_template.meta_data)
-
- for node_template in service_template.node_templates.itervalues():
- for _ in range(node_template.scaling['default_instances']):
- node = self.instantiate(node_template)
- service.nodes[node.name] = node
-
- service.groups = self.instantiate(service_template.group_templates)
- service.policies = self.instantiate(service_template.policy_templates)
- service.workflows = self.instantiate(service_template.workflow_templates)
-
- if service_template.substitution_template is not None:
- service.substitution = self.instantiate(service_template.substitution_template)
- service.outputs = self.instantiate(service_template.outputs)
-
- 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():
- raise exceptions.InstantiationError('Failed to instantiate service template `{0}`'
- .format(service_template.name))
-
- return service
-
- def instantiate(self, source_template):
- if isinstance(source_template, (dict, list)):
- initiator = self._initiators[source_template._sa_adapter.attr.key]
- if isinstance(source_template, dict):
- dict_ = utils.OrderedDict()
- for name, value in source_template.iteritems():
- value = initiator(value)
- if value is not None:
- dict_[name] = value
- return dict_
- elif isinstance(source_template, list):
- list_ = []
- for value in source_template:
- value = initiator(value)
- if value is not None:
- list_.append(value)
- return list_
- else:
- return self._initiators[source_template.__tablename__](source_template)
-
- @staticmethod
- def _instantiate_artifact(artifact_template):
- artifact = models.Artifact(
- name=artifact_template.name,
- type=artifact_template.type,
- description=reading.deepcopy_with_locators(artifact_template.description),
- source_path=artifact_template.source_path,
- target_path=artifact_template.target_path,
- repository_url=artifact_template.repository_url,
- repository_credential=artifact_template.repository_credential,
- artifact_template=artifact_template)
- return artifact
-
- @staticmethod
- def _instantiate_capability(capability_template):
- capability = models.Capability(name=capability_template.name,
- type=capability_template.type,
- min_occurrences=capability_template.min_occurrences,
- max_occurrences=capability_template.max_occurrences,
- occurrences=0,
- capability_template=capability_template)
- return capability
-
- def _instantiate_group(self, group_template):
- group = models.Group(name=group_template.name,
- type=group_template.type,
- description=reading.deepcopy_with_locators(group_template.description),
- group_template=group_template)
- group.properties = self.instantiate(group_template.properties)
- group.interfaces = self.instantiate(group_template.interface_templates)
- if group_template.node_templates:
- for node_template in group_template.node_templates:
- group.nodes += node_template.nodes
- return group
-
- def _instantiate_interface(self, interface_template):
- interface = models.Interface(
- name=interface_template.name,
- type=interface_template.type,
- description=reading.deepcopy_with_locators(interface_template.description),
- interface_template=interface_template)
- interface.inputs = self.instantiate(interface_template.inputs)
- interface.operations = self.instantiate(interface_template.operation_templates)
- return interface
-
- def _instantiate_node(self, node_template):
- node = models.Node(
- name=node_template._next_name,
- type=node_template.type,
- description=reading.deepcopy_with_locators(node_template.description),
- state=models.Node.INITIAL,
- node_template=node_template
- )
- node.properties = self.instantiate(node_template.properties)
- node.attributes = self.instantiate(node_template.attributes)
- node.interfaces = self.instantiate(node_template.interface_templates)
- node.artifacts = self.instantiate(node_template.artifact_templates)
- node.capabilities = self.instantiate(node_template.capability_templates)
-
- # Default attributes
- if ('tosca_name' in node.attributes) \
- and (node.attributes['tosca_name'].type_name == 'string'):
- node.attributes['tosca_name'].value = node_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 _instantiate_policy(self, policy_template):
- policy = models.Policy(
- name=policy_template.name,
- type=policy_template.type,
- description=reading.deepcopy_with_locators(policy_template.description),
- policy_template=policy_template)
- policy.properties = self.instantiate(policy_template.properties)
- if policy_template.node_templates:
- for node_template in policy_template.node_templates:
- policy.nodes += node_template.nodes
- if policy_template.group_templates:
- for group_template in policy_template.group_templates:
- policy.groups += group_template.groups
- return policy
-
- @staticmethod
- def _instantiate_parameter(parameter_template, model_cls):
- return model_cls(
- name=parameter_template.name, # pylint: disable=unexpected-keyword-arg
- type_name=parameter_template.type_name,
- _value=parameter_template._value,
- description=parameter_template.description
- )
-
- @staticmethod
- def _instantiate_substitution(substitution_template):
- substitution = models.Substitution(node_type=substitution_template.node_type,
- substitution_template=substitution_template)
- return substitution
-
- @staticmethod
- def _instantiate_metadata(metadata_template):
- return models.Metadata(name=metadata_template.name, value=metadata_template.value)
-
- @staticmethod
- def _instantiate_substitution_mapping(substitution_mapping):
- context = consumption.ConsumptionContext.get_thread_local()
- if substitution_mapping.capability_template is not None:
- node_template = substitution_mapping.capability_template.node_template
- else:
- node_template = substitution_mapping.requirement_template.node_template
- nodes = node_template.nodes
- if len(nodes) == 0:
- context.validation.report(
- 'mapping "{0}" refers to node template "{1}" but there are no node instances'.
- format(substitution_mapping.mapped_name,
- substitution_mapping.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
- node = nodes[0]
- capability = None
- if substitution_mapping.capability_template:
- for a_capability in node.capabilities.itervalues():
- if a_capability.capability_template.name == \
- substitution_mapping.capability_template.name:
- capability = a_capability
- return models.SubstitutionMapping(
- name=substitution_mapping.name,
- capability=capability,
- requirement_template=substitution_mapping.requirement_template,
- node=node)
-
- def _instantiate_relationship(self, relationship_template):
- relationship_model = models.Relationship(name=relationship_template.name,
- type=relationship_template.type,
- relationship_template=relationship_template)
- relationship_model.properties = self.instantiate(relationship_template.properties)
- relationship_model.interfaces = self.instantiate(relationship_template.interface_templates)
- return relationship_model
-
- def _instantiate_operation(self, operation_template):
- plugin = None
- if (operation_template.plugin_specification is not None and
- operation_template.plugin_specification.enabled):
- plugin = operation_template.plugin_specification.plugin
-
- operation = models.Operation(
- name=operation_template.name,
- description=reading.deepcopy_with_locators(operation_template.description),
- relationship_edge=operation_template.relationship_edge,
- implementation=operation_template.implementation,
- dependencies=operation_template.dependencies,
- executor=operation_template.executor,
- plugin=plugin,
- function=operation_template.function,
- max_attempts=operation_template.max_attempts,
- retry_interval=operation_template.retry_interval,
- operation_template=operation_template)
-
- operation.inputs = self.instantiate(operation_template.inputs)
- operation.configurations = self.instantiate(operation_template.configurations)
-
- return operation
-
-
-initiator = _Instantiation()
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
----------------------------------------------------------------------
diff --git a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
index 4d8e1db..4704f1b 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -515,8 +515,8 @@ def create_plugin_specification_model(context, policy):
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
if policy.description:
model.description = policy.description.value
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/609d305d/tests/instantiation/test_configuration.py
----------------------------------------------------------------------
diff --git a/tests/instantiation/test_configuration.py b/tests/instantiation/test_configuration.py
index 6ac0c9c..659e334 100644
--- a/tests/instantiation/test_configuration.py
+++ b/tests/instantiation/test_configuration.py
@@ -165,8 +165,9 @@ def test_remote(service):
def test_reserved_arguments(broken_service_issues):
- assert len(broken_service_issues) == 1
- message = broken_service_issues[0].message
- assert message.startswith('using reserved arguments in operation "operation":')
- assert '"ctx"' in message
- assert '"toolbelt"' in message
+ assert len(broken_service_issues) == 2
+ assert any(
+ all([issue.message.startswith('using reserved arguments in operation "operation":'),
+ 'ctx' in issue.message,
+ 'toolbelt' in issue.message])
+ for issue in broken_service_issues)