You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ariatosca.apache.org by em...@apache.org on 2017/03/03 23:44:30 UTC
[2/2] incubator-ariatosca git commit: Move types into service
template; continue fixing tests
Move types into service template; continue fixing tests
Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/36eb2d24
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/36eb2d24
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/36eb2d24
Branch: refs/heads/ARIA-105-integrate-modeling
Commit: 36eb2d24c2d0791738e6b9f88a81fc5f906745ce
Parents: 091152f
Author: Tal Liron <ta...@gmail.com>
Authored: Fri Mar 3 17:42:53 2017 -0600
Committer: Tal Liron <ta...@gmail.com>
Committed: Fri Mar 3 17:42:53 2017 -0600
----------------------------------------------------------------------
aria/cli/commands.py | 33 +++--
aria/modeling/bases.py | 5 +-
aria/modeling/misc.py | 68 ++++++---
aria/modeling/service.py | 22 +--
aria/modeling/service_template.py | 122 +++++++++++++--
aria/modeling/utils.py | 83 ++++-------
aria/orchestrator/context/common.py | 9 +-
aria/orchestrator/decorators.py | 6 +-
aria/orchestrator/workflows/api/task.py | 29 ++--
aria/orchestrator/workflows/api/task_graph.py | 4 +-
.../orchestrator/workflows/builtin/workflows.py | 21 +--
aria/orchestrator/workflows/core/task.py | 13 +-
aria/orchestrator/workflows/dry.py | 10 +-
aria/parser/modeling/context.py | 69 +--------
aria/parser/modeling/types.py | 146 ------------------
aria/parser/modeling/utils.py | 146 ------------------
aria/utils/formatting.py | 19 ++-
aria/utils/uuid.py | 66 +++++++++
.../simple_v1_0/modeling/__init__.py | 113 ++++++++------
tests/end2end/test_orchestrator.py | 18 ++-
tests/mock/models.py | 147 ++++++++++---------
tests/mock/topology.py | 42 +++---
.../context/test_resource_render.py | 4 +-
tests/orchestrator/context/test_serialize.py | 2 +-
tests/orchestrator/context/test_workflow.py | 12 +-
.../execution_plugin/test_common.py | 4 +-
tests/orchestrator/execution_plugin/test_ssh.py | 6 +-
tests/orchestrator/test_runner.py | 4 +-
tests/orchestrator/workflows/api/test_task.py | 20 +--
.../orchestrator/workflows/core/test_engine.py | 14 +-
.../workflows/executor/test_executor.py | 6 +-
.../workflows/executor/test_process_executor.py | 10 +-
.../tosca-simple-1.0/node-cellar/workflows.py | 18 ++-
tests/storage/test_models.py | 32 ++--
tests/storage/test_structures.py | 2 +-
35 files changed, 596 insertions(+), 729 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/cli/commands.py
----------------------------------------------------------------------
diff --git a/aria/cli/commands.py b/aria/cli/commands.py
index 25a4e0d..52d4f14 100644
--- a/aria/cli/commands.py
+++ b/aria/cli/commands.py
@@ -228,30 +228,35 @@ class WorkflowCommand(BaseCommand):
def _get_workflow(self, context, workflow_name):
if workflow_name in BUILTIN_WORKFLOWS:
- workflow_fn = import_fullname('aria.orchestrator.workflows.builtin.%s' % workflow_name)
+ workflow_fn = import_fullname('aria.orchestrator.workflows.builtin.{0}'.format(
+ workflow_name))
inputs = {}
else:
+ workflow = None
+ for policy in context.modeling.instance.policies:
+ if policy.name == workflow_name:
+ workflow = policy
+ break
+
+ if workflow is None:
+ raise AttributeError('workflow policy does not exist: "{0}"'.format(workflow_name))
+ if workflow.type.role != 'workflow':
+ raise AttributeError('policy is not a workflow: "{0}"'.format(workflow_name))
+
try:
- policy = context.modeling.instance.policies[workflow_name]
- except KeyError:
- raise AttributeError('workflow policy does not exist: "%s"' % workflow_name)
- if context.modeling.policy_types.get_role(policy.type_name) != 'workflow':
- raise AttributeError('policy is not a workflow: "%s"' % workflow_name)
-
- try:
- sys.path.append(policy.properties['implementation'].value)
+ sys.path.append(workflow.properties['implementation'].value)
except KeyError:
pass
- workflow_fn = import_fullname(policy.properties['function'].value)
+ workflow_fn = import_fullname(workflow.properties['function'].value)
- for k in policy.properties:
+ for k in workflow.properties:
if k in WORKFLOW_DECORATOR_RESERVED_ARGUMENTS:
- raise AttributeError('workflow policy "%s" defines a reserved property: "%s"' %
- (workflow_name, k))
+ raise AttributeError('workflow policy "{0}" defines a reserved property: "{1}"'
+ .format(workflow_name, k))
inputs = OrderedDict([
- (k, v.value) for k, v in policy.properties.iteritems()
+ (k, v.value) for k, v in workflow.properties.iteritems()
if k not in WorkflowCommand.WORKFLOW_POLICY_INTERNAL_PROPERTIES
])
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/modeling/bases.py
----------------------------------------------------------------------
diff --git a/aria/modeling/bases.py b/aria/modeling/bases.py
index c1b2f7a..7fe218d 100644
--- a/aria/modeling/bases.py
+++ b/aria/modeling/bases.py
@@ -36,6 +36,7 @@ from sqlalchemy import (
)
from . import utils
+from ..utils import formatting
class ModelMixin(object):
@@ -153,7 +154,7 @@ class ModelMixin(object):
"""
if backreference is None:
- backreference = utils.pluralize(cls.__tablename__)
+ backreference = formatting.pluralize(cls.__tablename__)
backref_kwargs = backref_kwargs or {}
backref_kwargs.setdefault('uselist', True)
@@ -360,7 +361,7 @@ class ModelMixin(object):
class ModelIDMixin(object):
id = Column(Integer, primary_key=True, autoincrement=True)
- name = Column(Text, nullable=True, index=True)
+ name = Column(Text, index=True)
@classmethod
def id_column_name(cls):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/modeling/misc.py
----------------------------------------------------------------------
diff --git a/aria/modeling/misc.py b/aria/modeling/misc.py
index 0b50f9a..b61a787 100644
--- a/aria/modeling/misc.py
+++ b/aria/modeling/misc.py
@@ -14,6 +14,7 @@
# limitations under the License.
import cPickle as pickle
+import logging
from sqlalchemy import (
Column,
@@ -23,9 +24,9 @@ from sqlalchemy import (
from sqlalchemy.ext.declarative import declared_attr
from ..storage import exceptions
-from ..parser.modeling import utils as parser_utils
from ..utils import collections, formatting, console
from .bases import InstanceModelMixin, TemplateModelMixin
+from . import utils
class ParameterBase(TemplateModelMixin):
@@ -42,11 +43,11 @@ class ParameterBase(TemplateModelMixin):
__tablename__ = 'parameter'
- name = Column(Text, nullable=False)
- type_name = Column(Text, nullable=False)
+ name = Column(Text)
+ type_name = Column(Text)
# Check: value type
- _value = Column(Binary, nullable=True)
+ _value = Column(Binary, name='value')
description = Column(Text)
@property
@@ -64,7 +65,7 @@ class ParameterBase(TemplateModelMixin):
try:
return pickle.loads(self._value)
except BaseException:
- raise exceptions.StorageError('Bad format for parameter of type "{0}": {1}'.format(
+ raise exceptions.StorageError('bad format for parameter of type "{0}": {1}'.format(
self.type_name, self._value))
@value.setter
@@ -74,8 +75,9 @@ class ParameterBase(TemplateModelMixin):
else:
try:
self._value = pickle.dumps(value)
- except pickle.PicklingError:
- # TODO debug log
+ except (pickle.PicklingError, TypeError):
+ logging.getLogger('aria').warn('Could not pickle parameter of type "{0}": {1}'
+ .format(self.type_name, value))
self._value = pickle.dumps(str(value))
def instantiate(self, context, container):
@@ -87,8 +89,21 @@ class ParameterBase(TemplateModelMixin):
def coerce_values(self, context, container, report_issues):
if self.value is not None:
- self.value = parser_utils.coerce_value(context, container, self.value,
- report_issues)
+ self.value = utils.coerce_value(context, container, self.value,
+ report_issues)
+
+ def dump(self, context):
+ if self.type_name is not None:
+ console.puts('{0}: {1} ({2})'.format(
+ context.style.property(self.name),
+ context.style.literal(self.value),
+ context.style.type(self.type_name)))
+ else:
+ console.puts('{0}: {1}'.format(
+ context.style.property(self.name),
+ context.style.literal(self.value)))
+ if self.description:
+ console.puts(context.style.meta(self.description))
class TypeBase(InstanceModelMixin):
@@ -98,9 +113,9 @@ class TypeBase(InstanceModelMixin):
__tablename__ = 'type'
- variant = Column(Text)
+ variant = Column(Text, nullable=False)
description = Column(Text)
- role = Column(Text)
+ _role = Column(Text, name='role')
@declared_attr
def parent(cls):
@@ -120,6 +135,21 @@ class TypeBase(InstanceModelMixin):
return cls.foreign_key('type', nullable=True)
# endregion
+
+ @property
+ def role(self):
+ def get_role(the_type):
+ if the_type is None:
+ return None
+ elif the_type._role is None:
+ return get_role(the_type.parent)
+ return the_type._role
+
+ return get_role(self)
+
+ @role.setter
+ def role(self, value):
+ self._role = value
def is_descendant(self, base_name, name):
base = self.get_descendant(base_name)
@@ -143,16 +173,6 @@ class TypeBase(InstanceModelMixin):
for descendant in child.iter_descendants():
yield descendant
- def get_role(self, name):
- def _get_role(the_type):
- if the_type is None:
- return None
- elif the_type.role is None:
- return _get_role(self.parent)
- return the_type.role
-
- return _get_role(self.get_descendant(name))
-
@property
def as_raw(self):
return collections.OrderedDict((
@@ -193,7 +213,6 @@ class MetadataBase(TemplateModelMixin):
__tablename__ = 'metadata'
- name = Column(Text, nullable=False)
value = Column(Text)
@property
@@ -206,3 +225,8 @@ class MetadataBase(TemplateModelMixin):
from . import models
return models.Metadata(name=self.name,
value=self.value)
+
+ def dump(self, context):
+ console.puts('{0}: {1}'.format(
+ context.style.property(self.name),
+ context.style.literal(self.value)))
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/modeling/service.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service.py b/aria/modeling/service.py
index 1309472..e555b70 100644
--- a/aria/modeling/service.py
+++ b/aria/modeling/service.py
@@ -216,7 +216,7 @@ class ServiceBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
def dump(self, context):
if self.description is not None:
console.puts(context.style.meta(self.description))
- utils.dump_parameters(context, self.meta_data, 'Metadata')
+ utils.dump_dict_values(context, self.meta_data, 'Metadata')
for node in self.nodes:
node.dump(context)
for group in self.groups:
@@ -225,8 +225,8 @@ class ServiceBase(InstanceModelMixin): # pylint: disable=too-many-public-methods
policy.dump(context)
if self.substitution is not None:
self.substitution.dump(context)
- utils.dump_parameters(context, self.inputs, 'Inputs')
- utils.dump_parameters(context, self.outputs, 'Outputs')
+ utils.dump_dict_values(context, self.inputs, 'Inputs')
+ utils.dump_dict_values(context, self.outputs, 'Outputs')
utils.dump_dict_values(context, self.operations, 'Operations')
def dump_graph(self, context):
@@ -493,7 +493,7 @@ class NodeBase(InstanceModelMixin):
with context.style.indent:
console.puts('Type: {0}'.format(context.style.type(self.type.name)))
console.puts('Template: {0}'.format(context.style.node(self.node_template.name)))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
utils.dump_interfaces(context, self.interfaces)
utils.dump_dict_values(context, self.artifacts, 'Artifacts')
utils.dump_dict_values(context, self.capabilities, 'Capabilities')
@@ -574,7 +574,7 @@ class GroupBase(InstanceModelMixin):
console.puts('Group: {0}'.format(context.style.node(self.name)))
with context.style.indent:
console.puts('Type: {0}'.format(context.style.type(self.type.name)))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
utils.dump_interfaces(context, self.interfaces)
if self.nodes:
console.puts('Member nodes:')
@@ -654,7 +654,7 @@ class PolicyBase(InstanceModelMixin):
console.puts('Policy: {0}'.format(context.style.node(self.name)))
with context.style.indent:
console.puts('Type: {0}'.format(context.style.type(self.type.name)))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
if self.nodes:
console.puts('Target nodes:')
with context.style.indent:
@@ -914,7 +914,7 @@ class RelationshipBase(InstanceModelMixin):
if (self.relationship_template is not None) and self.relationship_template.name:
console.puts('Relationship template: {0}'.format(
context.style.node(self.relationship_template.name)))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
utils.dump_interfaces(context, self.interfaces, 'Interfaces')
@@ -1008,7 +1008,7 @@ class CapabilityBase(InstanceModelMixin):
' to {0:d}'.format(self.max_occurrences)
if self.max_occurrences is not None
else ' or more'))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
class InterfaceBase(InstanceModelMixin):
@@ -1102,7 +1102,7 @@ class InterfaceBase(InstanceModelMixin):
console.puts(context.style.meta(self.description))
with context.style.indent:
console.puts('Interface type: {0}'.format(context.style.type(self.type.name)))
- utils.dump_parameters(context, self.inputs, 'Inputs')
+ utils.dump_dict_values(context, self.inputs, 'Inputs')
utils.dump_dict_values(context, self.operations, 'Operations')
@@ -1211,7 +1211,7 @@ class OperationBase(InstanceModelMixin):
if self.retry_interval is not None:
console.puts('Retry interval: {0}'.format(
context.style.literal(self.retry_interval)))
- utils.dump_parameters(context, self.inputs, 'Inputs')
+ utils.dump_dict_values(context, self.inputs, 'Inputs')
class ArtifactBase(InstanceModelMixin):
@@ -1307,4 +1307,4 @@ class ArtifactBase(InstanceModelMixin):
if self.repository_credential:
console.puts('Repository credential: {0}'.format(
context.style.literal(self.repository_credential)))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/modeling/service_template.py
----------------------------------------------------------------------
diff --git a/aria/modeling/service_template.py b/aria/modeling/service_template.py
index b4c15bb..1f2d1f3 100644
--- a/aria/modeling/service_template.py
+++ b/aria/modeling/service_template.py
@@ -97,6 +97,34 @@ class ServiceTemplateBase(TemplateModelMixin):
def operation_templates(cls):
return cls.one_to_many_relationship('operation_template', dict_key='name')
+ @declared_attr
+ def node_types(cls):
+ return cls.one_to_one_relationship('type', key='node_type_fk', backreference='')
+
+ @declared_attr
+ def group_types(cls):
+ return cls.one_to_one_relationship('type', key='group_type_fk', backreference='')
+
+ @declared_attr
+ def capability_types(cls):
+ return cls.one_to_one_relationship('type', key='capability_type_fk', backreference='')
+
+ @declared_attr
+ def relationship_types(cls):
+ return cls.one_to_one_relationship('type', key='relationship_type_fk', backreference='')
+
+ @declared_attr
+ def policy_types(cls):
+ return cls.one_to_one_relationship('type', key='policy_type_fk', backreference='')
+
+ @declared_attr
+ def artifact_types(cls):
+ return cls.one_to_one_relationship('type', key='artifact_type_fk', backreference='')
+
+ @declared_attr
+ def interface_types(cls):
+ return cls.one_to_one_relationship('type', key='interface_type_fk', backreference='')
+
# region orchestration
created_at = Column(DateTime, nullable=False, index=True)
@@ -118,6 +146,41 @@ class ServiceTemplateBase(TemplateModelMixin):
def substitution_template_fk(cls):
return cls.foreign_key('substitution_template', nullable=True)
+ # ServiceTemplate one-to-one to Type
+ @declared_attr
+ def node_type_fk(cls):
+ return cls.foreign_key('type', nullable=True)
+
+ # ServiceTemplate one-to-one to Type
+ @declared_attr
+ def group_type_fk(cls):
+ return cls.foreign_key('type', nullable=True)
+
+ # ServiceTemplate one-to-one to Type
+ @declared_attr
+ def capability_type_fk(cls):
+ return cls.foreign_key('type', nullable=True)
+
+ # ServiceTemplate one-to-one to Type
+ @declared_attr
+ def relationship_type_fk(cls):
+ return cls.foreign_key('type', nullable=True)
+
+ # ServiceTemplate one-to-one to Type
+ @declared_attr
+ def policy_type_fk(cls):
+ return cls.foreign_key('type', nullable=True)
+
+ # ServiceTemplate one-to-one to Type
+ @declared_attr
+ def artifact_type_fk(cls):
+ return cls.foreign_key('type', nullable=True)
+
+ # ServiceTemplate one-to-one to Type
+ @declared_attr
+ def interface_type_fk(cls):
+ return cls.foreign_key('type', nullable=True)
+
# endregion
def get_node_template(self, node_template_name):
@@ -147,6 +210,17 @@ class ServiceTemplateBase(TemplateModelMixin):
('outputs', formatting.as_raw_dict(self.outputs)),
('operation_templates', formatting.as_raw_list(self.operation_templates))))
+ @property
+ def types_as_raw(self):
+ return collections.OrderedDict((
+ ('node_types', formatting.as_raw(self.node_types)),
+ ('group_types', formatting.as_raw(self.group_types)),
+ ('capability_types', formatting.as_raw(self.capability_types)),
+ ('relationship_types', formatting.as_raw(self.relationship_types)),
+ ('policy_types', formatting.as_raw(self.policy_types)),
+ ('artifact_types', formatting.as_raw(self.artifact_types)),
+ ('interface_types', formatting.as_raw(self.interface_types))))
+
def instantiate(self, context, container):
from . import models
now = datetime.now()
@@ -208,7 +282,7 @@ class ServiceTemplateBase(TemplateModelMixin):
def dump(self, context):
if self.description is not None:
console.puts(context.style.meta(self.description))
- utils.dump_parameters(context, self.meta_data, 'Metadata')
+ utils.dump_dict_values(context, self.meta_data, 'Metadata')
for node_template in self.node_templates:
node_template.dump(context)
@@ -218,10 +292,36 @@ class ServiceTemplateBase(TemplateModelMixin):
policy_template.dump(context)
if self.substitution_template is not None:
self.substitution_template.dump(context)
- utils.dump_parameters(context, self.inputs, 'Inputs')
- utils.dump_parameters(context, self.outputs, 'Outputs')
+ utils.dump_dict_values(context, self.inputs, 'Inputs')
+ utils.dump_dict_values(context, self.outputs, 'Outputs')
utils.dump_dict_values(context, self.operation_templates, 'Operation templates')
+ def dump_types(self, context):
+ if self.node_types.children:
+ console.puts('Node types:')
+ self.node_types.dump(context)
+ if self.group_types.children:
+ console.puts('Group types:')
+ self.group_types.dump(context)
+ if self.capability_types.children:
+ console.puts('Capability types:')
+ self.capability_types.dump(context)
+ if self.relationship_types.children:
+ console.puts('Relationship types:')
+ self.relationship_types.dump(context)
+ if self.policy_types.children:
+ console.puts('Policy types:')
+ self.policy_types.dump(context)
+ if self.policy_trigger_types.children:
+ console.puts('Policy trigger types:')
+ self.policy_trigger_types.dump(context)
+ if self.artifact_types.children:
+ console.puts('Artifact types:')
+ self.artifact_types.dump(context)
+ if self.interface_types.children:
+ console.puts('Interface types:')
+ self.interface_types.dump(context)
+
class NodeTemplateBase(TemplateModelMixin):
"""
@@ -360,7 +460,7 @@ class NodeTemplateBase(TemplateModelMixin):
' to {0:d}'.format(self.max_instances)
if self.max_instances is not None
else ' or more'))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
utils.dump_interfaces(context, self.interface_templates)
utils.dump_dict_values(context, self.artifact_templates, 'Artifact templates')
utils.dump_dict_values(context, self.capability_templates, 'Capability templates')
@@ -453,7 +553,7 @@ class GroupTemplateBase(TemplateModelMixin):
console.puts(context.style.meta(self.description))
with context.style.indent:
console.puts('Type: {0}'.format(context.style.type(self.type.name)))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
utils.dump_interfaces(context, self.interface_templates)
if self.node_templates:
console.puts('Member node templates: {0}'.format(', '.join(
@@ -542,7 +642,7 @@ class PolicyTemplateBase(TemplateModelMixin):
console.puts(context.style.meta(self.description))
with context.style.indent:
console.puts('Type: {0}'.format(context.style.type(self.type.name)))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
if self.node_templates:
console.puts('Target node templates: {0}'.format(', '.join(
(str(context.style.node(v.name)) for v in self.node_templates))))
@@ -943,7 +1043,7 @@ class RelationshipTemplateBase(TemplateModelMixin):
if self.description:
console.puts(context.style.meta(self.description))
with context.style.indent:
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
utils.dump_interfaces(context, self.interface_templates, 'Interface templates')
@@ -1063,7 +1163,7 @@ class CapabilityTemplateBase(TemplateModelMixin):
console.puts('Valid source node types: {0}'.format(
', '.join((str(context.style.type(v.name))
for v in self.valid_source_node_types))))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
class InterfaceTemplateBase(TemplateModelMixin):
@@ -1155,7 +1255,7 @@ class InterfaceTemplateBase(TemplateModelMixin):
console.puts(context.style.meta(self.description))
with context.style.indent:
console.puts('Interface type: {0}'.format(context.style.type(self.type.name)))
- utils.dump_parameters(context, self.inputs, 'Inputs')
+ utils.dump_dict_values(context, self.inputs, 'Inputs')
utils.dump_dict_values(context, self.operation_templates, 'Operation templates')
@@ -1268,7 +1368,7 @@ class OperationTemplateBase(TemplateModelMixin):
if self.retry_interval is not None:
console.puts('Retry interval: {0}'.format(
context.style.literal(self.retry_interval)))
- utils.dump_parameters(context, self.inputs, 'Inputs')
+ utils.dump_dict_values(context, self.inputs, 'Inputs')
class ArtifactTemplateBase(TemplateModelMixin):
@@ -1364,7 +1464,7 @@ class ArtifactTemplateBase(TemplateModelMixin):
if self.repository_credential:
console.puts('Repository credential: {0}'.format(
context.style.literal(self.repository_credential)))
- utils.dump_parameters(context, self.properties)
+ utils.dump_dict_values(context, self.properties, 'Properties')
def deepcopy_with_locators(value):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/modeling/utils.py
----------------------------------------------------------------------
diff --git a/aria/modeling/utils.py b/aria/modeling/utils.py
index ca418a6..a2f0bfc 100644
--- a/aria/modeling/utils.py
+++ b/aria/modeling/utils.py
@@ -13,37 +13,32 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from random import randrange
-
-from shortuuid import ShortUUID
-
+from ..parser.exceptions import InvalidValueError
+from ..parser.presentation import Value
+from ..utils.collections import OrderedDict
from ..utils.console import puts
-
-
-# UUID = ShortUUID() # default alphabet is base57, which is alphanumeric without visually ambiguous
-# characters; ID length is 22
-UUID = ShortUUID(alphabet='abcdefghijklmnopqrstuvwxyz0123456789') # alphanumeric; ID length is 25
-
-
-def generate_id_string(length=None):
- """
- A random string with a strong guarantee of universal uniqueness (uses ShortUUID).
-
- The default length is 25 characters.
- """
-
- the_id = UUID.uuid()
- if length is not None:
- the_id = the_id[:length]
- return the_id
-
-
-def generate_hex_string():
- """
- A random string of 5 hex digits with no guarantee of universal uniqueness.
- """
-
- return '%05x' % randrange(16 ** 5)
+from .exceptions import CannotEvaluateFunctionException
+
+
+def coerce_value(context, container, value, report_issues=False):
+ if isinstance(value, Value):
+ value = value.value
+
+ if isinstance(value, list):
+ return [coerce_value(context, container, v, report_issues) for v in value]
+ elif isinstance(value, dict):
+ return OrderedDict((k, coerce_value(context, container, v, report_issues))
+ for k, v in value.items())
+ elif hasattr(value, '_evaluate'):
+ try:
+ value = value._evaluate(context, container)
+ value = coerce_value(context, container, value, report_issues)
+ except CannotEvaluateFunctionException:
+ pass
+ except InvalidValueError as e:
+ if report_issues:
+ context.validation.report(e.issue)
+ return value
def validate_dict_values(context, the_dict):
@@ -105,25 +100,6 @@ def dump_dict_values(context, the_dict, name):
dump_list_values(context, the_dict.itervalues(), name)
-def dump_parameters(context, parameters, name='Properties'):
- if not parameters:
- return
- puts('{0}:'.format(name))
- with context.style.indent:
- for parameter_name, parameter in parameters.items():
- if hasattr(parameter, 'type_name') and (parameter.type_name is not None):
- puts('{0} = {1} ({2})'.format(
- context.style.property(parameter_name),
- context.style.literal(parameter.value),
- context.style.type(parameter.type_name)))
- else:
- puts('{0} = {1}'.format(
- context.style.property(parameter_name),
- context.style.literal(parameter.value)))
- if hasattr(parameter, 'description') and parameter.description:
- puts(context.style.meta(parameter.description))
-
-
def dump_interfaces(context, interfaces, name='Interfaces'):
if not interfaces:
return
@@ -133,15 +109,6 @@ def dump_interfaces(context, interfaces, name='Interfaces'):
interface.dump(context)
-def pluralize(noun):
- if noun.endswith('s'):
- return '{0}es'.format(noun)
- elif noun.endswith('y'):
- return '{0}ies'.format(noun[:-1])
- else:
- return '{0}s'.format(noun)
-
-
class classproperty(object): # pylint: disable=invalid-name
def __init__(self, f):
self._func = f
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/orchestrator/context/common.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/context/common.py b/aria/orchestrator/context/common.py
index f0a3b3e..77e5da7 100644
--- a/aria/orchestrator/context/common.py
+++ b/aria/orchestrator/context/common.py
@@ -12,15 +12,16 @@
# 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.
+
"""
A common context for both workflow and operation
"""
-from uuid import uuid4
import jinja2
-from aria import logger
-from aria.storage import exceptions
+from ... import logger
+from ...storage import exceptions
+from ...utils.uuid import generate_uuid
class BaseContext(logger.LoggerMixin):
@@ -38,7 +39,7 @@ class BaseContext(logger.LoggerMixin):
**kwargs):
super(BaseContext, self).__init__(**kwargs)
self._name = name
- self._id = str(uuid4())
+ self._id = generate_uuid(variant='uuid')
self._model = model_storage
self._resource = resource_storage
self._service_id = service_id
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/orchestrator/decorators.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/decorators.py b/aria/orchestrator/decorators.py
index bbe43f4..e90afc7 100644
--- a/aria/orchestrator/decorators.py
+++ b/aria/orchestrator/decorators.py
@@ -17,10 +17,10 @@
Workflow and operation decorators
"""
-from uuid import uuid4
from functools import partial, wraps
-from aria.utils.validation import validate_function_arguments
+from ..utils.validation import validate_function_arguments
+from ..utils.uuid import generate_uuid
from . import context
from .workflows.api import task_graph
@@ -74,4 +74,4 @@ def operation(func=None, toolbelt=False, suffix_template=''):
def _generate_name(func_name, ctx, suffix_template, **custom_kwargs):
return '{func_name}.{suffix}'.format(
func_name=func_name,
- suffix=suffix_template.format(ctx=ctx, **custom_kwargs) or str(uuid4()))
+ suffix=suffix_template.format(ctx=ctx, **custom_kwargs) or generate_uuid(variant='uuid'))
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/orchestrator/workflows/api/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/task.py b/aria/orchestrator/workflows/api/task.py
index 4f35ffc..d90b2b1 100644
--- a/aria/orchestrator/workflows/api/task.py
+++ b/aria/orchestrator/workflows/api/task.py
@@ -16,10 +16,10 @@
"""
Provides the tasks to be entered into the task graph
"""
-from uuid import uuid4
from ....modeling import models
from ....utils.collections import OrderedDict
+from ....utils.uuid import generate_uuid
from ... import context
from .. import exceptions
@@ -34,7 +34,7 @@ class BaseTask(object):
self._workflow_context = ctx
else:
self._workflow_context = context.workflow.current.get()
- self._id = str(uuid4())
+ self._id = generate_uuid(variant='uuid')
@property
def id(self):
@@ -122,7 +122,7 @@ class OperationTask(BaseTask):
"""
assert isinstance(node, models.Node)
- operation = _get_operation(node.interfaces, interface_name, operation_name)
+ operation = cls._get_operation(node.interfaces, interface_name, operation_name)
if operation is None:
raise exceptions.TaskException(
'Could not find operation "{0}" on interface "{1}" for node "{2}"'.format(
@@ -130,7 +130,7 @@ class OperationTask(BaseTask):
return cls(
actor=node,
- name='{0}.{1}@{2}'.format(interface_name, operation_name, node.name),
+ name='{0}.{1}'.format(interface_name, operation_name),
plugin=operation.plugin,
implementation=operation.implementation,
inputs=cls._merge_inputs(operation.inputs, inputs),
@@ -153,7 +153,7 @@ class OperationTask(BaseTask):
assert isinstance(relationship, models.Relationship)
assert runs_on in models.Task.RUNS_ON
- operation = _get_operation(relationship.interfaces, interface_name, operation_name)
+ operation = cls._get_operation(relationship.interfaces, interface_name, operation_name)
if operation is None:
raise exceptions.TaskException(
'Could not find operation "{0}" on interface "{1}" for relationship "{2}"'.format(
@@ -161,10 +161,7 @@ class OperationTask(BaseTask):
return cls(
actor=relationship,
- name='{0}.{1}@{2}->{3}'.format(interface_name,
- operation_name,
- relationship.source_node.name,
- relationship.target_node.name),
+ name='{0}.{1}'.format(interface_name, operation_name),
plugin=operation.plugin,
implementation=operation.implementation,
inputs=cls._merge_inputs(operation.inputs, inputs),
@@ -173,6 +170,13 @@ class OperationTask(BaseTask):
**kwargs)
@classmethod
+ def _get_operation(cls, interfaces, interface_name, operation_name):
+ interface = interfaces.get(interface_name)
+ if interface is not None:
+ return interface.operations.get(operation_name)
+ return None
+
+ @classmethod
def _merge_inputs(cls, operation_inputs, override_inputs=None):
final_inputs = OrderedDict(operation_inputs)
if override_inputs:
@@ -216,10 +220,3 @@ class StubTask(BaseTask):
"""
pass
-
-
-def _get_operation(interfaces, interface_name, operation_name):
- interface = interfaces.get(interface_name)
- if interface is not None:
- return interface.operations.get(operation_name)
- return None
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/orchestrator/workflows/api/task_graph.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/api/task_graph.py b/aria/orchestrator/workflows/api/task_graph.py
index c88d343..2ead4d0 100644
--- a/aria/orchestrator/workflows/api/task_graph.py
+++ b/aria/orchestrator/workflows/api/task_graph.py
@@ -17,7 +17,7 @@
Task graph. Used by users to build workflows
"""
-from uuid import uuid4
+from ....utils.uuid import generate_uuid
from collections import Iterable
from networkx import DiGraph, topological_sort
@@ -49,7 +49,7 @@ class TaskGraph(object):
def __init__(self, name):
self.name = name
- self._id = str(uuid4())
+ self._id = generate_uuid(variant='uuid')
self._graph = DiGraph()
def __repr__(self):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/orchestrator/workflows/builtin/workflows.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/builtin/workflows.py b/aria/orchestrator/workflows/builtin/workflows.py
index b714236..f19c031 100644
--- a/aria/orchestrator/workflows/builtin/workflows.py
+++ b/aria/orchestrator/workflows/builtin/workflows.py
@@ -17,8 +17,9 @@
TSOCA normative lifecycle workflows.
"""
-from .utils import (create_node_task, create_relationship_tasks)
from ... import workflow
+from ....modeling.models import Task
+from .utils import (create_node_task, create_relationship_tasks)
NORMATIVE_STANDARD_INTERFACE = 'Standard' # 'tosca.interfaces.node.lifecycle.Standard'
@@ -81,13 +82,13 @@ def install_node(graph, node, **kwargs):
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_PRE_CONFIGURE_SOURCE,
- 'source',
+ Task.RUNS_ON_SOURCE,
node,
dry)
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_PRE_CONFIGURE_TARGET,
- 'target',
+ Task.RUNS_ON_TARGET,
node,
dry)
sequence.append(
@@ -98,13 +99,13 @@ def install_node(graph, node, **kwargs):
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_POST_CONFIGURE_SOURCE,
- 'source',
+ Task.RUNS_ON_SOURCE,
node,
dry)
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_POST_CONFIGURE_TARGET,
- 'target',
+ Task.RUNS_ON_TARGET,
node,
dry)
@@ -153,19 +154,19 @@ def _create_start_tasks(node, dry):
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_ADD_SOURCE,
- 'source',
+ Task.RUNS_ON_SOURCE,
node,
dry)
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_ADD_TARGET,
- 'target',
+ Task.RUNS_ON_TARGET,
node,
dry)
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_TARGET_CHANGED,
- 'target',
+ Task.RUNS_ON_TARGET,
node,
dry)
return sequence
@@ -176,13 +177,13 @@ def _create_stop_tasks(node, dry):
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_REMOVE_TARGET,
- 'target',
+ Task.RUNS_ON_TARGET,
node,
dry)
sequence += \
create_relationship_tasks(
NORMATIVE_CONFIGURE_INTERFACE, NORMATIVE_TARGET_CHANGED,
- 'target',
+ Task.RUNS_ON_TARGET,
node,
dry)
sequence.append(
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/orchestrator/workflows/core/task.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/core/task.py b/aria/orchestrator/workflows/core/task.py
index 8856b2d..7d8380c 100644
--- a/aria/orchestrator/workflows/core/task.py
+++ b/aria/orchestrator/workflows/core/task.py
@@ -16,6 +16,7 @@
"""
Workflow tasks
"""
+
from contextlib import contextmanager
from datetime import datetime
from functools import (
@@ -37,7 +38,7 @@ def _locked(func=None):
@wraps(func)
def _wrapper(self, value, **kwargs):
if self._update_fields is None:
- raise exceptions.TaskException("Task is not in update mode")
+ raise exceptions.TaskException('Task is not in update mode')
return func(self, value, **kwargs)
return _wrapper
@@ -72,35 +73,35 @@ class StubTask(BaseTask):
class StartWorkflowTask(StubTask):
"""
- Tasks marking a workflow start
+ Task marking a workflow start
"""
pass
class EndWorkflowTask(StubTask):
"""
- Tasks marking a workflow end
+ Task marking a workflow end
"""
pass
class StartSubWorkflowTask(StubTask):
"""
- Tasks marking a subworkflow start
+ Task marking a subworkflow start
"""
pass
class EndSubWorkflowTask(StubTask):
"""
- Tasks marking a subworkflow end
+ Task marking a subworkflow end
"""
pass
class OperationTask(BaseTask):
"""
- Operation tasks
+ Operation task
"""
def __init__(self, api_task, *args, **kwargs):
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/orchestrator/workflows/dry.py
----------------------------------------------------------------------
diff --git a/aria/orchestrator/workflows/dry.py b/aria/orchestrator/workflows/dry.py
index 240a9f2..766ea0c 100644
--- a/aria/orchestrator/workflows/dry.py
+++ b/aria/orchestrator/workflows/dry.py
@@ -35,17 +35,19 @@ def convert_to_dry(plugin, implementation, inputs): # pylint: disable=unused-arg
@operation
def dry_operation(ctx, _plugin, _implementation, **kwargs):
with _TERMINAL_LOCK:
+ print ctx.name
if hasattr(ctx, 'relationship'):
- puts('> relationship instance: %s -> %s' % (
+ puts('> Relationship: {0} -> {1}'.format(
Colored.red(ctx.relationship.source_node.name),
Colored.red(ctx.relationship.target_node.name)))
else:
- puts('> node instance: %s' % Colored.red(ctx.node.name))
+ puts('> Node: {0}'.format(Colored.red(ctx.node.name)))
+ puts(' Operation: {0}'.format(Colored.green(ctx.name)))
_dump_implementation(_plugin, _implementation)
def _dump_implementation(plugin, implementation):
if plugin:
- puts(' plugin: %s' % Colored.magenta(plugin))
+ puts(' Plugin: {0}'.format(Colored.magenta(plugin, bold=True)))
if implementation:
- puts(' implementation: %s' % Colored.yellow(safe_repr(implementation)))
+ puts(' Implementation: {0}'.format(Colored.magenta(safe_repr(implementation))))
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/parser/modeling/context.py
----------------------------------------------------------------------
diff --git a/aria/parser/modeling/context.py b/aria/parser/modeling/context.py
index 81c458b..52e724a 100644
--- a/aria/parser/modeling/context.py
+++ b/aria/parser/modeling/context.py
@@ -18,7 +18,7 @@ import itertools
from ...utils.collections import StrictDict, prune, OrderedDict
from ...utils.formatting import as_raw
from ...utils.console import puts
-from .utils import generate_id_string
+from ...utils.uuid import generate_uuid
class IdType(object):
@@ -34,7 +34,7 @@ class IdType(object):
UNIVERSAL_RANDOM = 2
"""
- Universally unique ID (UUID): 25 random safe characters.
+ Universally unique ID (UUID): 22 random safe characters.
"""
@@ -48,13 +48,6 @@ class ModelingContext(object):
* :code:`id_type`: Type of IDs to use for instances
* :code:`id_max_length`: Maximum allowed instance ID length
* :code:`inputs`: Dict of inputs values
- * :code:`node_types`: The generated hierarchy of node types
- * :code:`group_types`: The generated hierarchy of group types
- * :code:`capability_types`: The generated hierarchy of capability types
- * :code:`relationship_types`: The generated hierarchy of relationship types
- * :code:`policy_types`: The generated hierarchy of policy types
- * :code:`artifact_types`: The generated hierarchy of artifact types
- * :code:`interface_types`: The generated hierarchy of interface types
"""
def __init__(self):
@@ -67,13 +60,6 @@ class ModelingContext(object):
self.id_type = IdType.UNIVERSAL_RANDOM
self.id_max_length = 63 # See: http://www.faqs.org/rfcs/rfc1035.html
self.inputs = StrictDict(key_class=basestring)
- self.node_types = Type()
- self.group_types = Type()
- self.capability_types = Type()
- self.relationship_types = Type()
- self.policy_types = Type()
- self.artifact_types = Type()
- self.interface_types = Type()
self._serial_id_counter = itertools.count(1)
self._locally_unique_ids = set()
@@ -83,13 +69,6 @@ class ModelingContext(object):
model_storage.service_template.put(self.template)
if self.instance is not None:
model_storage.service.put(self.instance)
- model_storage.type.put(self.node_types)
- model_storage.type.put(self.group_types)
- model_storage.type.put(self.capability_types)
- model_storage.type.put(self.relationship_types)
- model_storage.type.put(self.policy_types)
- model_storage.type.put(self.artifact_types)
- model_storage.type.put(self.interface_types)
def generate_node_id(self, template_name):
return self.node_id_format.format(
@@ -101,31 +80,19 @@ class ModelingContext(object):
return self._serial_id_counter.next()
elif self.id_type == IdType.LOCAL_RANDOM:
- the_id = generate_id_string(6)
+ the_id = generate_uuid(6)
while the_id in self._locally_unique_ids:
- the_id = generate_id_string(6)
+ the_id = generate_uuid(6)
self._locally_unique_ids.add(the_id)
return the_id
- return generate_id_string()
+ return generate_uuid()
def set_input(self, name, value):
self.inputs[name] = value
# TODO: coerce to validate type
@property
- def types_as_raw(self):
- return OrderedDict((
- ('node_types', as_raw(self.node_types)),
- ('group_types', as_raw(self.group_types)),
- ('capability_types', as_raw(self.capability_types)),
- ('relationship_types', as_raw(self.relationship_types)),
- ('policy_types', as_raw(self.policy_types)),
- ('policy_trigger_types', as_raw(self.policy_trigger_types)),
- ('artifact_types', as_raw(self.artifact_types)),
- ('interface_types', as_raw(self.interface_types))))
-
- @property
def template_as_raw(self):
raw = self.template.as_raw
prune(raw)
@@ -136,29 +103,3 @@ class ModelingContext(object):
raw = self.instance.as_raw
prune(raw)
return raw
-
- def dump_types(self, context):
- if self.node_types.children:
- puts('Node types:')
- self.node_types.dump(context)
- if self.group_types.children:
- puts('Group types:')
- self.group_types.dump(context)
- if self.capability_types.children:
- puts('Capability types:')
- self.capability_types.dump(context)
- if self.relationship_types.children:
- puts('Relationship types:')
- self.relationship_types.dump(context)
- if self.policy_types.children:
- puts('Policy types:')
- self.policy_types.dump(context)
- if self.policy_trigger_types.children:
- puts('Policy trigger types:')
- self.policy_trigger_types.dump(context)
- if self.artifact_types.children:
- puts('Artifact types:')
- self.artifact_types.dump(context)
- if self.interface_types.children:
- puts('Interface types:')
- self.interface_types.dump(context)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/parser/modeling/types.py
----------------------------------------------------------------------
diff --git a/aria/parser/modeling/types.py b/aria/parser/modeling/types.py
deleted file mode 100644
index 0a232fc..0000000
--- a/aria/parser/modeling/types.py
+++ /dev/null
@@ -1,146 +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 ...utils.collections import StrictList, StrictDict, OrderedDict
-from ...utils.formatting import as_raw
-from ...utils.console import puts
-
-
-class Type(object):
- """
- Represents a type and its children.
- """
-
- def __init__(self, name):
- if not isinstance(name, basestring):
- raise ValueError('must set name (string)')
-
- self.name = name
- self.description = None
- self.role = None
- self.children = StrictList(value_class=Type)
-
- def get_parent(self, name):
- for child in self.children:
- if child.name == name:
- return self
- parent = child.get_parent(name)
- if parent is not None:
- return parent
- return None
-
- def is_descendant(self, base_name, name):
- base = self.get_descendant(base_name)
- if base is not None:
- if base.get_descendant(name) is not None:
- return True
- return False
-
- def get_descendant(self, name):
- if self.name == name:
- return self
- for child in self.children:
- found = child.get_descendant(name)
- if found is not None:
- return found
- return None
-
- def iter_descendants(self):
- for child in self.children:
- yield child
- for descendant in child.iter_descendants():
- yield descendant
-
- def get_role(self, name):
- def _get_role(the_type):
- if the_type is None:
- return None
- elif the_type.role is None:
- return _get_role(self.get_parent(the_type.name))
- return the_type.role
-
- return _get_role(self.get_descendant(name))
-
- @property
- def as_raw(self):
- return OrderedDict((
- ('name', self.name),
- ('description', self.description),
- ('role', self.role)))
-
- def dump(self, context):
- if self.name:
- puts(context.style.type(self.name))
- with context.style.indent:
- for child in self.children:
- child.dump(context)
-
- def append_raw_children(self, types):
- for child in self.children:
- raw_child = as_raw(child)
- raw_child['parent'] = self.name
- types.append(raw_child)
- child.append_raw_children(types)
-
-
-class RelationshipType(Type):
- def __init__(self, name):
- super(RelationshipType, self).__init__(name)
-
- self.properties = StrictDict(key_class=basestring)
- self.source_interfaces = StrictDict(key_class=basestring)
- self.target_interfaces = StrictDict(key_class=basestring)
-
-
-class PolicyType(Type):
- def __init__(self, name):
- super(PolicyType, self).__init__(name)
-
- self.implementation = None
- self.properties = StrictDict(key_class=basestring)
-
-
-class PolicyTriggerType(Type):
- def __init__(self, name):
- super(PolicyTriggerType, self).__init__(name)
-
- self.implementation = None
- self.properties = StrictDict(key_class=basestring)
-
-
-class TypeHierarchy(Type):
- """
- Represents a single-parent derivation :class:`Type` hierarchy.
- """
-
- def __init__(self):
- super(TypeHierarchy, self).__init__(name='')
- self.name = None # TODO Calling the super __init__ with name='' and then setting it to None
- # is an ugly workaround. We need to improve this. here is the reason for the current state:
- # In this module there is a class named `Type`. Its `__init__` gets has a `name` argument
- # that raises an exception of `name` is not an instance of `basestring`. Here are some
- # classes that inherit from `Type`: RelationshipType, PolicyType, PolicyTriggerType.
- # But `TypeHierarchy` also inherits from `Type`. And its `__init__` does not call its super
- # `__init__`, which causes pylint to yell. As you can clearly see, it also sets `name` to
- # None. But calling super __init__ with name=None raises an exception. We tried modifying
- # the Type class hierarchies, but it was not that simple. Also calling with name='' without
- # setting `name` to None later on raises parsing validation issues.
- self.children = StrictList(value_class=Type)
-
- @property
- def as_raw(self):
- types = []
- self.append_raw_children(types)
- return types
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/parser/modeling/utils.py
----------------------------------------------------------------------
diff --git a/aria/parser/modeling/utils.py b/aria/parser/modeling/utils.py
deleted file mode 100644
index 06d5f34..0000000
--- a/aria/parser/modeling/utils.py
+++ /dev/null
@@ -1,146 +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 random import randrange
-
-from shortuuid import ShortUUID
-
-from ...modeling.exceptions import CannotEvaluateFunctionException
-from ...utils.collections import OrderedDict
-from ...utils.console import puts
-from ..exceptions import InvalidValueError
-from ..presentation import Value
-
-# UUID = ShortUUID() # default alphabet is base57, which is alphanumeric without visually ambiguous
-# characters; ID length is 22
-UUID = ShortUUID(alphabet='abcdefghijklmnopqrstuvwxyz0123456789') # alphanumeric; ID length is 25
-
-
-def generate_id_string(length=None):
- """
- A random string with a strong guarantee of universal uniqueness (uses UUID).
-
- The default length is 25 characters.
- """
-
- the_id = UUID.uuid()
- if length is not None:
- the_id = the_id[:length]
- return the_id
-
-
-def generate_hex_string():
- """
- A random string of 5 hex digits with no guarantee of universal uniqueness.
- """
-
- return '%05x' % randrange(16 ** 5)
-
-
-def coerce_value(context, container, value, report_issues=False):
- if isinstance(value, Value):
- value = value.value
-
- if isinstance(value, list):
- return [coerce_value(context, container, v, report_issues) for v in value]
- elif isinstance(value, dict):
- return OrderedDict((k, coerce_value(context, container, v, report_issues))
- for k, v in value.items())
- elif hasattr(value, '_evaluate'):
- try:
- value = value._evaluate(context, container)
- value = coerce_value(context, container, value, report_issues)
- except CannotEvaluateFunctionException:
- pass
- except InvalidValueError as e:
- if report_issues:
- context.validation.report(e.issue)
- return value
-
-
-def validate_dict_values(context, the_dict):
- if not the_dict:
- return
- validate_list_values(context, the_dict.values())
-
-
-def validate_list_values(context, the_list):
- if not the_list:
- return
- for value in the_list:
- value.validate(context)
-
-
-def coerce_dict_values(context, container, the_dict, report_issues=False):
- if not the_dict:
- return
- coerce_list_values(context, container, the_dict.itervalues(), report_issues)
-
-
-def coerce_list_values(context, container, the_list, report_issues=False):
- if not the_list:
- return
- for value in the_list:
- value.coerce_values(context, container, report_issues)
-
-
-def instantiate_dict(context, container, the_dict, from_dict):
- if not from_dict:
- return
- for name, value in from_dict.iteritems():
- value = value.instantiate(context, container)
- if value is not None:
- the_dict[name] = value
-
-
-def dump_list_values(context, the_list, name):
- if not the_list:
- return
- puts('%s:' % name)
- with context.style.indent:
- for value in the_list:
- value.dump(context)
-
-
-def dump_dict_values(context, the_dict, name):
- if not the_dict:
- return
- dump_list_values(context, the_dict.itervalues(), name)
-
-
-def dump_parameters(context, parameters, name='Properties'):
- if not parameters:
- return
- puts('%s:' % name)
- with context.style.indent:
- for parameter_name, parameter in parameters.iteritems():
- if parameter.type_name is not None:
- puts('%s = %s (%s)' % (context.style.property(parameter_name),
- context.style.literal(parameter.value),
- context.style.type(parameter.type_name)))
- else:
- puts('%s = %s' % (context.style.property(parameter_name),
- context.style.literal(parameter.value)))
- if parameter.description:
- puts(context.style.meta(parameter.description))
-
-
-def dump_interfaces(context, interfaces, name='Interfaces'):
- if not interfaces:
- return
- puts('%s:' % name)
- with context.style.indent:
- for interface in interfaces.itervalues():
- interface.dump(context)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/utils/formatting.py
----------------------------------------------------------------------
diff --git a/aria/utils/formatting.py b/aria/utils/formatting.py
index 3725bc7..8a223e9 100644
--- a/aria/utils/formatting.py
+++ b/aria/utils/formatting.py
@@ -13,14 +13,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from __future__ import absolute_import # so we can import standard 'collections'
-
import json
from types import MethodType
+
from ruamel import yaml # @UnresolvedImport
from .collections import FrozenList, FrozenDict, StrictList, StrictDict, OrderedDict
+
+PLURALIZE_EXCEPTIONS = {}
+
+
# Add our types to ruamel.yaml (for round trips)
yaml.representer.RoundTripRepresenter.add_representer(
FrozenList, yaml.representer.RoundTripRepresenter.represent_list)
@@ -108,6 +111,18 @@ def string_list_as_string(strings):
return ', '.join('"%s"' % safe_str(v) for v in strings)
+def pluralize(noun):
+ plural = PLURALIZE_EXCEPTIONS.get(noun)
+ if plural is not None:
+ return plural
+ elif noun.endswith('s'):
+ return '{0}es'.format(noun)
+ elif noun.endswith('y'):
+ return '{0}ies'.format(noun[:-1])
+ else:
+ return '{0}s'.format(noun)
+
+
def as_raw(value):
"""
Converts values using their :code:`as_raw` property, if it exists, recursively.
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/aria/utils/uuid.py
----------------------------------------------------------------------
diff --git a/aria/utils/uuid.py b/aria/utils/uuid.py
new file mode 100644
index 0000000..b5f39f8
--- /dev/null
+++ b/aria/utils/uuid.py
@@ -0,0 +1,66 @@
+# 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 __future__ import absolute_import # so we can import standard 'uuid'
+
+from random import randrange
+from uuid import uuid4
+
+from shortuuid import ShortUUID
+
+
+# Alphanumeric without visually ambiguous characters; default length is 22
+UUID_BASE57 = ShortUUID()
+
+# Lower-case alphanumeric; default length is 25
+UUID_LOWERCASE_ALPHANUMERIC = ShortUUID(alphabet='abcdefghijklmnopqrstuvwxyz0123456789')
+
+
+def generate_uuid(length=None, variant='base57'):
+ """
+ A random string with varying degrees of guarantee of universal uniqueness.
+
+ :param variant: options are:
+ * 'base57' (the default) uses a mix of upper and lowercase alphanumerics ensuring
+ no visually ambiguous characters; default length 22
+ * 'alphanumeric' uses lowercase alphanumeric; default length 25
+ * 'uuid' user lowercase hexadecimal in the classic UUID format, including
+ dashes; length is always 36
+ * 'hex' uses lowercase hexadecimal characters but has no guarantee of
+ uniqueness; default length of 5
+ """
+
+ if variant == 'base57':
+ the_id = UUID_BASE57.uuid()
+ if length is not None:
+ the_id = the_id[:length]
+
+ elif variant == 'alphanumeric':
+ the_id = UUID_LOWERCASE_ALPHANUMERIC.uuid()
+ if length is not None:
+ the_id = the_id[:length]
+
+ elif variant == 'uuid':
+ the_id = str(uuid4())
+
+ elif variant == 'hex':
+ length = length or 5
+ # See: http://stackoverflow.com/a/2782859
+ the_id = ('%0' + str(length) + 'x') % randrange(16 ** length)
+
+ else:
+ raise ValueError('unsupported UUID variant: {0}'.format(variant))
+
+ return the_id
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/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 c55ccdd..959f3c4 100644
--- a/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
+++ b/extensions/aria_extension_tosca/simple_v1_0/modeling/__init__.py
@@ -13,6 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+"""
+Creates ARIA service template models based on the TOSCA presentation.
+
+Relies on many helper methods in the presentation classes.
+"""
+
import re
from types import FunctionType
from datetime import datetime
@@ -35,43 +41,37 @@ def create_service_template_model(context): # pylint: disable=too-many-locals,to
# Metadata
metadata = context.presentation.get('service_template', 'metadata')
if metadata is not None:
- model.meta_data['template_name'] = Metadata(value=metadata.template_name)
- model.meta_data['template_author'] = Metadata(value=metadata.template_author)
- model.meta_data['template_version'] = Metadata(value=metadata.template_version)
- custom = metadata.custom
- if custom:
- for name, v in custom.iteritems():
- model.meta_data[name] = Metadata(value=v)
+ create_metadata_models(context, model, metadata)
# Types
+ model.node_types = Type(variant='node')
create_types(context,
- context.modeling.node_types,
- context.presentation.get('service_template', 'node_types'),
- 'node')
+ model.node_types,
+ context.presentation.get('service_template', 'node_types'))
+ model.group_types = Type(variant='group')
create_types(context,
- context.modeling.group_types,
- context.presentation.get('service_template', 'group_types'),
- 'group')
+ model.group_types,
+ context.presentation.get('service_template', 'group_types'))
+ model.policy_types = Type(variant='policy')
create_types(context,
- context.modeling.policy_types,
- context.presentation.get('service_template', 'policy_types'),
- 'policy')
+ model.policy_types,
+ context.presentation.get('service_template', 'policy_types'))
+ model.relationship_types = Type(variant='relationship')
create_types(context,
- context.modeling.relationship_types,
- context.presentation.get('service_template', 'relationship_types'),
- 'relationship')
+ model.relationship_types,
+ context.presentation.get('service_template', 'relationship_types'))
+ model.capability_types = Type(variant='capability')
create_types(context,
- context.modeling.capability_types,
- context.presentation.get('service_template', 'capability_types'),
- 'capability')
+ model.capability_types,
+ context.presentation.get('service_template', 'capability_types'))
+ model.artifact_types = Type(variant='artifact')
create_types(context,
- context.modeling.interface_types,
- context.presentation.get('service_template', 'interface_types'),
- 'interface')
+ model.artifact_types,
+ context.presentation.get('service_template', 'artifact_types'))
+ model.interface_types = Type(variant='interface')
create_types(context,
- context.modeling.artifact_types,
- context.presentation.get('service_template', 'artifact_types'),
- 'artifact')
+ model.interface_types,
+ context.presentation.get('service_template', 'interface_types'))
# Topology template
topology_template = context.presentation.get('service_template', 'topology_template')
@@ -85,7 +85,7 @@ def create_service_template_model(context): # pylint: disable=too-many-locals,to
policies = context.presentation.get('service_template', 'topology_template', 'policies')
if policies:
for policy in policies.itervalues():
- if context.modeling.policy_types.get_role(policy.type) == 'plugin':
+ if model.policy_types.get_descendant(policy.type).role == 'plugin':
model.plugins[policy._name] = create_plugin_model(context, policy)
# Node templates
@@ -119,9 +119,23 @@ def create_service_template_model(context): # pylint: disable=too-many-locals,to
return model
+def create_metadata_models(context, service_template, metadata):
+ service_template.meta_data['template_name'] = Metadata(name='template_name',
+ value=metadata.template_name)
+ service_template.meta_data['template_author'] = Metadata(name='template_author',
+ value=metadata.template_author)
+ service_template.meta_data['template_version'] = Metadata(name='template_version',
+ value=metadata.template_version)
+ custom = metadata.custom
+ if custom:
+ for name, value in custom.iteritems():
+ service_template.meta_data[name] = Metadata(name=name,
+ value=value)
+
+
def create_node_template_model(context, service_template, node_template):
node_type = node_template._get_type(context)
- node_type = context.modeling.node_types.get_descendant(node_type._name)
+ node_type = service_template.node_types.get_descendant(node_type._name)
model = NodeTemplate(name=node_template._name,
type=node_type)
@@ -139,14 +153,14 @@ def create_node_template_model(context, service_template, node_template):
artifacts = node_template._get_artifacts(context)
if artifacts:
for artifact_name, artifact in artifacts.iteritems():
- model.artifact_templates[artifact_name] = create_artifact_template_model(context,
- artifact)
+ model.artifact_templates[artifact_name] = \
+ create_artifact_template_model(context, service_template, artifact)
capabilities = node_template._get_capabilities(context)
if capabilities:
for capability_name, capability in capabilities.iteritems():
model.capability_templates[capability_name] = \
- create_capability_template_model(context, capability)
+ create_capability_template_model(context, service_template, capability)
if model.target_node_template_constraints:
model.target_node_template_constraints = []
@@ -170,7 +184,7 @@ def fix_node_template_model(context, service_template, node_template):
def create_group_template_model(context, service_template, group):
group_type = group._get_type(context)
- group_type = context.modeling.group_types.get_descendant(group_type._name)
+ group_type = service_template.group_types.get_descendant(group_type._name)
model = GroupTemplate(name=group._name,
type=group_type)
@@ -193,7 +207,7 @@ def create_group_template_model(context, service_template, group):
def create_policy_template_model(context, service_template, policy):
policy_type = policy._get_type(context)
- policy_type = context.modeling.policy_types.get_descendant(policy_type._name)
+ policy_type = service_template.policy_types.get_descendant(policy_type._name)
model = PolicyTemplate(name=policy._name,
type=policy_type)
@@ -223,7 +237,7 @@ def create_requirement_template_model(context, service_template, requirement):
node, node_variant = requirement._get_node(context)
if node is not None:
if node_variant == 'node_type':
- node_type = context.modeling.node_types.get_descendant(node._name)
+ node_type = service_template.node_types.get_descendant(node._name)
model['target_node_type'] = node_type
else:
node_template = service_template.get_node_template(node._name)
@@ -254,13 +268,13 @@ def create_requirement_template_model(context, service_template, requirement):
def create_relationship_template_model(context, service_template, relationship):
relationship_type, relationship_type_variant = relationship._get_type(context)
if relationship_type_variant == 'relationship_type':
- relationship_type = context.modeling.relationship_types.get_descendant(
+ relationship_type = service_template.relationship_types.get_descendant(
relationship_type._name)
model = RelationshipTemplate(type=relationship_type)
else:
relationship_template = relationship_type
relationship_type = relationship_template._get_type(context)
- relationship_type = context.modeling.relationship_types.get_descendant(
+ relationship_type = service_template.relationship_types.get_descendant(
relationship_type._name)
model = RelationshipTemplate(type=relationship_type,
name=relationship_template._name)
@@ -274,9 +288,9 @@ def create_relationship_template_model(context, service_template, relationship):
return model
-def create_capability_template_model(context, capability):
+def create_capability_template_model(context, service_template, capability):
capability_type = capability._get_type(context)
- capability_type = context.modeling.capability_types.get_descendant(capability_type._name)
+ capability_type = service_template.capability_types.get_descendant(capability_type._name)
model = CapabilityTemplate(name=capability._name,
type=capability_type)
@@ -293,7 +307,7 @@ def create_capability_template_model(context, capability):
if valid_source_types:
for valid_source_type in valid_source_types:
# TODO: handle shortcut type names
- node_type = context.modeling.node_types.get_descendant(valid_source_type)
+ node_type = service_template.node_types.get_descendant(valid_source_type)
model.valid_source_node_types.append(node_type)
create_parameter_models_from_assignments(model.properties, capability.properties)
@@ -303,7 +317,7 @@ def create_capability_template_model(context, capability):
def create_interface_template_model(context, service_template, interface):
interface_type = interface._get_type(context)
- interface_type = context.modeling.interface_types.get_descendant(interface_type._name)
+ interface_type = service_template.interface_types.get_descendant(interface_type._name)
model = InterfaceTemplate(name=interface._name,
type=interface_type)
@@ -353,9 +367,9 @@ def create_operation_template_model(context, service_template, operation): # pyl
return model
-def create_artifact_template_model(context, artifact):
+def create_artifact_template_model(context, service_template, artifact):
artifact_type = artifact._get_type(context)
- artifact_type = context.modeling.artifact_types.get_descendant(artifact_type._name)
+ artifact_type = service_template.artifact_types.get_descendant(artifact_type._name)
model = ArtifactTemplate(name=artifact._name,
type=artifact_type,
source_path=artifact.file)
@@ -380,7 +394,7 @@ def create_artifact_template_model(context, artifact):
def create_substitution_template_model(context, service_template, substitution_mappings):
- node_type = context.modeling.node_types.get_descendant(substitution_mappings.node_type)
+ node_type = service_template.node_types.get_descendant(substitution_mappings.node_type)
model = SubstitutionTemplate(node_type=node_type)
capabilities = substitution_mappings.capabilities
@@ -442,7 +456,7 @@ def create_plugin_model(context, policy):
# Utils
#
-def create_types(context, root, types, variant):
+def create_types(context, root, types):
if types is None:
return
@@ -457,15 +471,18 @@ def create_types(context, root, types, variant):
if root.get_descendant(name) is None:
parent_type = the_type._get_parent(context)
model = Type(name=the_type._name,
- variant=variant)
+ role=the_type._get_extension('role'))
if the_type.description:
model.description = the_type.description.value
- model.role = the_type._get_extension('role')
if parent_type is None:
+ model.parent = root
+ model.variant = root.variant
root.children.append(model)
else:
container = root.get_descendant(parent_type._name)
if container is not None:
+ model.parent = container
+ model.variant = container.variant
container.children.append(model)
http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/36eb2d24/tests/end2end/test_orchestrator.py
----------------------------------------------------------------------
diff --git a/tests/end2end/test_orchestrator.py b/tests/end2end/test_orchestrator.py
index f930577..fac6207 100644
--- a/tests/end2end/test_orchestrator.py
+++ b/tests/end2end/test_orchestrator.py
@@ -17,7 +17,6 @@ import sys
from aria.orchestrator.runner import Runner
from aria.orchestrator.workflows.builtin import BUILTIN_WORKFLOWS
-from aria.parser.modeling.storage import initialize_storage
from aria.utils.imports import import_fullname
from aria.utils.collections import OrderedDict
@@ -44,17 +43,22 @@ def _workflow(workflow_name):
workflow_fn = import_fullname('aria.orchestrator.workflows.builtin.' + workflow_name)
inputs = {}
else:
- policy = context.modeling.instance.policies[workflow_name]
- sys.path.append(policy.properties['implementation'].value)
+ workflow = None
+ for policy in context.modeling.instance.policies:
+ if policy.name == workflow_name:
+ workflow = policy
+ break
- workflow_fn = import_fullname(policy.properties['function'].value)
+ sys.path.append(workflow.properties['implementation'].value)
+ workflow_fn = import_fullname(workflow.properties['function'].value)
inputs = OrderedDict([
- (k, v.value) for k, v in policy.properties.iteritems()
+ (k, v.value) for k, v in workflow.properties.iteritems()
if k not in WORKFLOW_POLICY_INTERNAL_PROPERTIES
])
def _initialize_storage(model_storage):
- initialize_storage(context, model_storage, 1)
+ context.modeling.store(model_storage)
- runner = Runner(workflow_name, workflow_fn, inputs, _initialize_storage, 1)
+ runner = Runner(workflow_name, workflow_fn, inputs, _initialize_storage,
+ lambda: context.modeling.instance.id)
runner.run()