Repository: incubator-ariatosca Updated Branches: refs/heads/ARIA-3-api-for-creating-workflows d4247cf0d -> 137e80cb3 (forced update)
ARIA-5-Adapt-workflow-API-users-to-modified-API Project: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/commit/137e80cb Tree: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/tree/137e80cb Diff: http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/diff/137e80cb Branch: refs/heads/ARIA-3-api-for-creating-workflows Commit: 137e80cb3fb00ce2a670b3cf0769ae1aa5789d5f Parents: 0bdfbcb Author: mxmrlv <mxm...@gmail.com> Authored: Sun Oct 23 20:13:44 2016 +0300 Committer: mxmrlv <mxm...@gmail.com> Committed: Wed Oct 26 12:56:44 2016 +0300 ---------------------------------------------------------------------- aria/workflows/api/task_graph.py | 19 +- aria/workflows/builtin/execute_operation.py | 7 +- aria/workflows/builtin/heal.py | 88 +++++---- aria/workflows/builtin/install.py | 10 +- aria/workflows/builtin/uninstall.py | 5 +- aria/workflows/builtin/workflows.py | 77 ++++---- aria/workflows/core/translation.py | 19 +- tests/workflows/builtin/__init__.py | 177 +++++++++++++++++++ .../workflows/builtin/test_execute_operation.py | 45 +++++ tests/workflows/builtin/test_heal.py | 82 +++++++++ tests/workflows/builtin/test_install.py | 36 ++++ tests/workflows/builtin/test_uninstall.py | 36 ++++ .../test_task_graph_into_exececution_graph.py | 18 +- 13 files changed, 498 insertions(+), 121 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/aria/workflows/api/task_graph.py ---------------------------------------------------------------------- diff --git a/aria/workflows/api/task_graph.py b/aria/workflows/api/task_graph.py index fdc4e2b..9c138e0 100644 --- a/aria/workflows/api/task_graph.py +++ b/aria/workflows/api/task_graph.py @@ -19,7 +19,7 @@ Task graph. Used by users to build workflows from uuid import uuid4 -from networkx import DiGraph +from networkx import DiGraph, topological_sort class TaskNotInGraphError(Exception): @@ -55,6 +55,23 @@ class TaskGraph(object): for _, data in self._graph.nodes_iter(data=True): yield data['task'] + @property + def id(self): + """ + Represents the id of the graph + :return: graph id + """ + return self._id + + def topological_order(self, reverse=False): + """ + Returns topological sort on the graph + :param reverse: whether to reverse the sort + :return: a list which represents the topological sort + """ + for task_id in topological_sort(self._graph, reverse=reverse): + yield self.get_task(task_id) + def get_task_dependencies(self, dependent_task): """ Iterates over the task's dependencies http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/aria/workflows/builtin/execute_operation.py ---------------------------------------------------------------------- diff --git a/aria/workflows/builtin/execute_operation.py b/aria/workflows/builtin/execute_operation.py index 9e87c30..a664904 100644 --- a/aria/workflows/builtin/execute_operation.py +++ b/aria/workflows/builtin/execute_operation.py @@ -67,14 +67,13 @@ def execute_operation( # registering actual tasks to sequences for node_instance in filtered_node_instances: - node_instance_sub_workflow = execute_operation_on_instance( + execute_operation_on_instance( context=context, graph=graph, node_instance=node_instance, operation=operation, operation_kwargs=operation_kwargs, allow_kwargs_override=allow_kwargs_override) - subgraphs[node_instance.id] = node_instance_sub_workflow for _, node_instance_sub_workflow in subgraphs.items(): graph.add_task(node_instance_sub_workflow) @@ -83,8 +82,8 @@ def execute_operation( if run_by_dependency_order: for node_instance in context.node_instances: for relationship_instance in node_instance.relationship_instances: - graph.dependency(source_task=subgraphs[node_instance.id], - after=[subgraphs[relationship_instance.target_id]]) + graph.add_dependency(source_task=subgraphs[node_instance.id], + after=[subgraphs[relationship_instance.target_id]]) def _filter_node_instances(context, node_ids=(), node_instance_ids=(), type_names=()): http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/aria/workflows/builtin/heal.py ---------------------------------------------------------------------- diff --git a/aria/workflows/builtin/heal.py b/aria/workflows/builtin/heal.py index cab2e6e..b9c7f8e 100644 --- a/aria/workflows/builtin/heal.py +++ b/aria/workflows/builtin/heal.py @@ -34,28 +34,27 @@ def heal(context, graph, node_instance_id): :param node_instance_id: the id of the node instance to heal :return: """ - failing_node = context.storage.node_instance.get(node_instance_id) - host_node = context.storage.node_instance.get(failing_node.host_id) + failing_node = context.model.node_instance.get(node_instance_id) + host_node = context.model.node_instance.get(failing_node.host_id) failed_node_instance_subgraph = _get_contained_subgraph(context, host_node) failed_node_instance_ids = list(n.id for n in failed_node_instance_subgraph) - targeted_node_instances = [ - context.storage.node_instance.get(relationship_instance.target_id) - for node_instance in failed_node_instance_subgraph - for relationship_instance in node_instance.relationship_instances - if relationship_instance.target_id not in failed_node_instance_ids - ] - - graph.chain([ - heal_uninstall( - context=context, - failing_node_instances=failed_node_instance_subgraph, - targeted_node_instances=targeted_node_instances), - heal_install( - context=context, - failing_node_instances=failed_node_instance_subgraph, - targeted_node_instances=targeted_node_instances) - ]) + targeted_node_instances = [node_instance for node_instance in context.node_instances + if node_instance.id not in failed_node_instance_ids] + + uninstall_subgraph = heal_uninstall( + context=context, + failing_node_instances=failed_node_instance_subgraph, + targeted_node_instances=targeted_node_instances) + + install_subgraph = heal_install( + context=context, + failing_node_instances=failed_node_instance_subgraph, + targeted_node_instances=targeted_node_instances) + + graph.add_task(uninstall_subgraph) + graph.add_task(install_subgraph) + graph.add_dependency(install_subgraph, uninstall_subgraph) @workflow(suffix_template='{failing_node_instances}') @@ -85,27 +84,23 @@ def heal_uninstall(context, graph, failing_node_instances, targeted_node_instanc node_instances=failing_node_instances, node_instance_sub_workflows=node_instance_sub_workflows) - # Add operations for intact nodes depending on a node instance - # belonging to node_instances + # Add operations for intact nodes depending on a node instance belonging to node_instances for node_instance in targeted_node_instances: node_instance_sub_workflow = node_instance_sub_workflows[node_instance.id] for relationship_instance in reversed(node_instance.relationship_instances): - target_node_instance = context.storage.node_instance.get( - relationship_instance.target_id) - if target_node_instance in failing_node_instances: - after_tasks = [node_instance_sub_workflows[relationship.target_id] - for relationship in node_instance.relationship_instances] + target_node_instance = context.model.node_instance.get(relationship_instance.target_id) + target_node_instance_subgraph = node_instance_sub_workflows[target_node_instance.id] + graph.add_dependency(target_node_instance_subgraph, node_instance_sub_workflow) - elif target_node_instance in targeted_node_instances: - after_tasks = [relationship_tasks( + if target_node_instance in failing_node_instances: + dependency = graph.parallel(*relationship_tasks( node_instance=node_instance, relationship_instance=relationship_instance, context=context, - operation_name='aria.interfaces.relationship_lifecycle.unlink')] + operation_name='aria.interfaces.relationship_lifecycle.unlink')) - if after_tasks: - graph.dependency(source_task=node_instance_sub_workflow, after=after_tasks) + graph.add_dependency(node_instance_sub_workflow, dependency) @workflow(suffix_template='{failing_node_instances}') @@ -141,35 +136,32 @@ def heal_install(context, graph, failing_node_instances, targeted_node_instances node_instance_sub_workflow = node_instance_sub_workflows[node_instance.id] for relationship_instance in node_instance.relationship_instances: - target_node_instance = context.storage.node_instance.get( - relationship_instance.target_id) - if target_node_instance in failing_node_instances: - after_tasks = [node_instance_sub_workflows[relationship.target_id] - for relationship in node_instance.relationship_instances] + target_node_instance = context.model.node_instance.get(relationship_instance.target_id) + target_node_instance_subgraph = node_instance_sub_workflows[target_node_instance.id] + graph.add_dependency(node_instance_sub_workflow, target_node_instance_subgraph) - elif target_node_instance in targeted_node_instances: - after_tasks = [relationship_tasks( + if target_node_instance in failing_node_instances: + dependent = graph.parallel(*relationship_tasks( node_instance=node_instance, relationship_instance=relationship_instance, context=context, - operation_name='aria.interfaces.relationship_lifecycle.establish')] + operation_name='aria.interfaces.relationship_lifecycle.establish')) - if after_tasks: - graph.dependency(source_task=node_instance_sub_workflow, after=after_tasks) + graph.add_dependency(dependent, node_instance_sub_workflow) def _get_contained_subgraph(context, host_node_instance): - contained_instances = set(node_instance - for node_instance in context.node_instances - if node_instance.host_id == host_node_instance.id and - node_instance.id != node_instance.host_id) - result = {host_node_instance} + contained_instances = [node_instance + for node_instance in context.node_instances + if node_instance.host_id == host_node_instance.id and + node_instance.id != node_instance.host_id] + result = [host_node_instance] if not contained_instances: return result - result.update(contained_instances) + result.extend(contained_instances) for node_instance in contained_instances: - result.update(_get_contained_subgraph(context, node_instance)) + result.extend(_get_contained_subgraph(context, node_instance)) return result http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/aria/workflows/builtin/install.py ---------------------------------------------------------------------- diff --git a/aria/workflows/builtin/install.py b/aria/workflows/builtin/install.py index 35d2968..552af90 100644 --- a/aria/workflows/builtin/install.py +++ b/aria/workflows/builtin/install.py @@ -47,8 +47,8 @@ def install(context, graph, node_instances=(), node_instance_sub_workflows=None) # create dependencies between the node instance sub workflow for node_instance in node_instances: node_instance_sub_workflow = node_instance_sub_workflows[node_instance.id] - graph.dependency( - source_task=node_instance_sub_workflow, - after=[ - node_instance_sub_workflows[relationship.target_id] - for relationship in node_instance.relationship_instances]) + if node_instance.relationship_instances: + dependencies = \ + graph.parallel(*(node_instance_sub_workflows[relationship.target_id] + for relationship in node_instance.relationship_instances)) + graph.add_dependency(node_instance_sub_workflow, dependencies) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/aria/workflows/builtin/uninstall.py ---------------------------------------------------------------------- diff --git a/aria/workflows/builtin/uninstall.py b/aria/workflows/builtin/uninstall.py index 47c8259..9659cb9 100644 --- a/aria/workflows/builtin/uninstall.py +++ b/aria/workflows/builtin/uninstall.py @@ -48,6 +48,5 @@ def uninstall(context, graph, node_instances=(), node_instance_sub_workflows=Non for node_instance in node_instances: node_instance_sub_workflow = node_instance_sub_workflows[node_instance.id] for relationship_instance in reversed(node_instance.relationship_instances): - graph.dependency( - source_task=node_instance_sub_workflows[relationship_instance.target_id], - after=[node_instance_sub_workflow]) + graph.add_dependency(node_instance_sub_workflows[relationship_instance.target_id], + node_instance_sub_workflow) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/aria/workflows/builtin/workflows.py ---------------------------------------------------------------------- diff --git a/aria/workflows/builtin/workflows.py b/aria/workflows/builtin/workflows.py index b6fbb94..5fc9ec8 100644 --- a/aria/workflows/builtin/workflows.py +++ b/aria/workflows/builtin/workflows.py @@ -57,18 +57,21 @@ def install_node_instance(context, graph, node_instance): 'aria.interfaces.lifecycle.start'], node_instance=node_instance ) - graph.chain(tasks=[ - create_node_instance, - preconfigure_relationship(context=context, node_instance=node_instance), - configure_node_instance, - postconfigure_relationship(context=context, node_instance=node_instance), - start_node_instance, - establish_relationship(context=context, node_instance=node_instance), - ]) + preconfigure_operations = preconfigure_relationship(context, node_instance) + postconfigure_operations = postconfigure_relationship(context, node_instance) + establish_operations = establish_relationship(context, node_instance) + install_sequence = [create_node_instance] + install_sequence.extend(preconfigure_operations) + install_sequence.append(configure_node_instance) + install_sequence.extend(postconfigure_operations) + install_sequence.append(start_node_instance) + install_sequence.extend(establish_operations) -@workflow(suffix_template='{node_instance.id}') -def preconfigure_relationship(context, graph, node_instance): + graph.sequence(*install_sequence) + + +def preconfigure_relationship(context, node_instance): """ :param context: @@ -76,14 +79,13 @@ def preconfigure_relationship(context, graph, node_instance): :param node_instance: :return: """ - graph.chain(tasks=relationships_tasks( + return relationships_tasks( operation_name='aria.interfaces.relationship_lifecycle.preconfigure', context=context, - node_instance=node_instance)) + node_instance=node_instance) -@workflow(suffix_template='{node_instance.id}') -def postconfigure_relationship(context, graph, node_instance): +def postconfigure_relationship(context, node_instance): """ :param context: @@ -91,14 +93,13 @@ def postconfigure_relationship(context, graph, node_instance): :param node_instance: :return: """ - graph.chain(tasks=relationships_tasks( + return relationships_tasks( operation_name='aria.interfaces.relationship_lifecycle.postconfigure', context=context, - node_instance=node_instance)) + node_instance=node_instance) -@workflow(suffix_template='{node_instance.id}') -def establish_relationship(context, graph, node_instance): +def establish_relationship(context, node_instance): """ :param context: @@ -106,10 +107,10 @@ def establish_relationship(context, graph, node_instance): :param node_instance: :return: """ - graph.chain(tasks=relationships_tasks( + return relationships_tasks( operation_name='aria.interfaces.relationship_lifecycle.establish', context=context, - node_instance=node_instance)) + node_instance=node_instance) # Uninstall node instance workflow and subworkflows @@ -135,16 +136,15 @@ def uninstall_node_instance(graph, context, node_instance): 'aria.interfaces.lifecycle.delete'], node_instance=node_instance ) + unlink_operations = unlink_relationship(context, node_instance) - graph.chain(tasks=[ - stop_node_instance, - unlink_relationship(context=context, node_instance=node_instance), - delete_node_instance, - ]) + uninstall_sequence = [stop_node_instance] + uninstall_sequence.extend(unlink_operations) + uninstall_sequence.append(delete_node_instance) + graph.sequence(*uninstall_sequence) -@workflow(suffix_template='{node_instance.id}') -def unlink_relationship(context, graph, node_instance): +def unlink_relationship(context, node_instance): """ :param context: @@ -152,13 +152,11 @@ def unlink_relationship(context, graph, node_instance): :param node_instance: :return: """ - tasks = relationships_tasks( + return relationships_tasks( operation_name='aria.interfaces.relationship_lifecycle.unlink', context=context, node_instance=node_instance ) - graph.chain(tasks=tasks) - return tasks @workflow(suffix_template='{node_instance.id}.{operation}') @@ -192,7 +190,7 @@ def execute_operation_on_instance( name=task_name, operation_details=node_instance.node.operations[operation], node_instance=node_instance, - parameters=operation_kwargs) + inputs=operation_kwargs) ) @@ -211,13 +209,13 @@ def relationships_tasks(operation_name, context, node_instance): sub_tasks = [] for index, (_, relationship_group) in enumerate(relationships_groups): for relationship_instance in relationship_group: - relationship_subgraph = relationship_tasks( + relationship_operations = relationship_tasks( node_instance=node_instance, relationship_instance=relationship_instance, context=context, operation_name=operation_name, index=index) - sub_tasks.append(relationship_subgraph) + sub_tasks.extend(relationship_operations) return sub_tasks @@ -232,11 +230,6 @@ def relationship_tasks(node_instance, relationship_instance, context, operation_ :return: """ index = index or node_instance.relationship_instances.index(relationship_instance) - sub_workflow_name = '{name}.{index}.{node_instance.id}'.format( - name=operation_name, - index=index, - node_instance=node_instance, - ) operation_name_template = '{name}.{index}.{{0}}.<{source_id}, {target_id}>'.format( name=operation_name, index=index, @@ -250,11 +243,7 @@ def relationship_tasks(node_instance, relationship_instance, context, operation_ operation_name]) target_operation = context.operation( name=operation_name_template.format('target'), - node_instance=context.storage.node_instance.get( - relationship_instance.target_id), + node_instance=context.model.node_instance.get(relationship_instance.target_id), operation_details=relationship_instance.relationship.target_operations[ operation_name]) - sub_graph = context.task_graph(name=sub_workflow_name) - sub_graph.add_task(source_operation) - sub_graph.add_task(target_operation) - return sub_graph + return source_operation, target_operation http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/aria/workflows/core/translation.py ---------------------------------------------------------------------- diff --git a/aria/workflows/core/translation.py b/aria/workflows/core/translation.py index dc483c6..451e4e3 100644 --- a/aria/workflows/core/translation.py +++ b/aria/workflows/core/translation.py @@ -44,22 +44,21 @@ def build_execution_graph( context=workflow_context) _add_task_and_dependencies(execution_graph, start_task, depends_on) - for operation_or_workflow, dependencies in task_graph.task_tree(reverse=True): + for task in task_graph.topological_order(reverse=True): + dependencies = task_graph.get_task_dependencies(task) operation_dependencies = _get_tasks_from_dependencies( execution_graph, dependencies, default=[start_task]) - if _is_operation(operation_or_workflow): + if _is_operation(task): # Add the task an the dependencies - operation_task = tasks.OperationTask(id=operation_or_workflow.id, - name=operation_or_workflow.name, - context=operation_or_workflow) + operation_task = tasks.OperationTask(id=task.id, name=task.name, context=task) _add_task_and_dependencies(execution_graph, operation_task, operation_dependencies) else: # Built the graph recursively while adding start and end markers build_execution_graph( - task_graph=operation_or_workflow, + task_graph=task, workflow_context=workflow_context, execution_graph=execution_graph, start_cls=tasks.StartSubWorkflowTask, @@ -70,7 +69,7 @@ def build_execution_graph( # Insert end marker workflow_dependencies = _get_tasks_from_dependencies( execution_graph, - task_graph.leaf_tasks, + _get_non_dependency_tasks(task_graph), default=[start_task]) end_task = end_cls( id=_end_graph_suffix(task_graph.id), @@ -104,3 +103,9 @@ def _start_graph_suffix(id): def _end_graph_suffix(id): return '{0}-End'.format(id) + + +def _get_non_dependency_tasks(graph): + for task in graph.tasks: + if len(list(graph.get_task_dependents(task))) == 0: + yield task http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/tests/workflows/builtin/__init__.py ---------------------------------------------------------------------- diff --git a/tests/workflows/builtin/__init__.py b/tests/workflows/builtin/__init__.py new file mode 100644 index 0000000..d73d6ee --- /dev/null +++ b/tests/workflows/builtin/__init__.py @@ -0,0 +1,177 @@ +# 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. + +import pytest + +from aria import contexts +from aria.storage import ModelStorage, models + +from ...storage import InMemoryModelDriver + +NODE_OPERATIONS_INSTALL = [ + 'aria.interfaces.lifecycle.create', + 'aria.interfaces.lifecycle.configure', + 'aria.interfaces.lifecycle.start', + ] +NODE_OPERATIONS_UNINSTALL = [ + 'aria.interfaces.lifecycle.stop', + 'aria.interfaces.lifecycle.delete', +] +NODE_OPERATIONS = NODE_OPERATIONS_INSTALL + NODE_OPERATIONS_UNINSTALL + +RELATIONSHIP_OPERATIONS_INSTALL = [ + 'aria.interfaces.relationship_lifecycle.preconfigure', + 'aria.interfaces.relationship_lifecycle.postconfigure', + 'aria.interfaces.relationship_lifecycle.establish', + ] +RELATIONSHIP_OPERATIONS_UNINSTALL = ['aria.interfaces.relationship_lifecycle.unlink'] +RELATIONSHIP_OPERATIONS = RELATIONSHIP_OPERATIONS_INSTALL + RELATIONSHIP_OPERATIONS_UNINSTALL + + +def simple_context(): + """ + Create the following graph in storage: + dependency_node <------ dependent_node + :return: + """ + + storage = ModelStorage(InMemoryModelDriver(), + model_classes=[models.NodeInstance, + models.Node, + models.Relationship, + models.RelationshipInstance]) + storage.setup() + + dependency_node = models.Node( + id='dependency_node', + host_id='dependency_node', + blueprint_id='test_blueprint_id', + type='test_node_type', + type_hierarchy=[], + number_of_instances=1, + planned_number_of_instances=1, + deploy_number_of_instances=1, + properties={}, + operations=dict((key, None) for key in NODE_OPERATIONS), + relationships=[], + min_number_of_instances=1, + max_number_of_instances=1, + ) + + dependency_node_instance = models.NodeInstance( + id='dependency_node_instance', + host_id='dependency_node_instance', + deployment_id='test_deployment_id', + runtime_properties={}, + version=None, + relationship_instances=[], + node=dependency_node + ) + + relationship = models.Relationship( + target_id=dependency_node.id, + source_interfaces={}, + source_operations=dict((key, None) for key in RELATIONSHIP_OPERATIONS), + target_interfaces={}, + target_operations=dict((key, None) for key in RELATIONSHIP_OPERATIONS), + type='rel_type', + type_hierarchy=[], + properties={}, + ) + + relationship_instance = models.RelationshipInstance( + target_id=dependency_node_instance.id, + target_name='test_target_name', + type='some_type', + relationship=relationship, + + ) + + dependent_node = models.Node( + id='dependent_node', + host_id='dependent_node', + blueprint_id='test_blueprint_id', + type='test_node_type', + type_hierarchy=[], + number_of_instances=1, + planned_number_of_instances=1, + deploy_number_of_instances=1, + properties={}, + operations=dict((key, None) for key in NODE_OPERATIONS), + relationships=[relationship], + min_number_of_instances=1, + max_number_of_instances=1, + ) + + dependent_node_instance = models.NodeInstance( + id='dependent_node_instance', + host_id='dependent_node_instance', + deployment_id='test_deployment_id', + runtime_properties={}, + version=None, + relationship_instances=[relationship_instance], + node=dependent_node + ) + + storage.node.store(dependency_node) + storage.node.store(dependent_node) + storage.node_instance.store(dependency_node_instance) + storage.node_instance.store(dependent_node_instance) + storage.relationship.store(relationship) + storage.relationship_instance.store(relationship_instance) + + wf_context = contexts.WorkflowContext(name='test_context', + model_storage=storage, + resource_storage=None, + deployment_id='test_deployment_id', + workflow_id='test_workflow_id') + return wf_context + + +def assert_node_install_operations(operations, with_operations=False): + if with_operations: + all_operations = [ + 'aria.interfaces.lifecycle.create', + 'aria.interfaces.relationship_lifecycle.preconfigure.0.source', + 'aria.interfaces.relationship_lifecycle.preconfigure.0.target', + 'aria.interfaces.lifecycle.configure', + 'aria.interfaces.relationship_lifecycle.postconfigure.0.source', + 'aria.interfaces.relationship_lifecycle.postconfigure.0.target', + 'aria.interfaces.lifecycle.start', + 'aria.interfaces.relationship_lifecycle.establish.0.source', + 'aria.interfaces.relationship_lifecycle.establish.0.target', + ] + + for i, operation in enumerate(operations): + assert operation.name.startswith(all_operations[i]) + else: + for i, operation in enumerate(operations): + assert operation.name.startswith(NODE_OPERATIONS_INSTALL[i]) + + +def assert_node_uninstall_operations(operations, with_relationships=False): + if with_relationships: + all_operations = [ + 'aria.interfaces.lifecycle.stop', + 'aria.interfaces.relationship_lifecycle.unlink.0.source', + 'aria.interfaces.relationship_lifecycle.unlink.0.target', + 'aria.interfaces.lifecycle.delete', + ] + + for i, operation in enumerate(operations): + assert operation.name.startswith(all_operations[i]) + else: + for i, operation in enumerate(operations): + assert operation.name.startswith(NODE_OPERATIONS_UNINSTALL[i]) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/tests/workflows/builtin/test_execute_operation.py ---------------------------------------------------------------------- diff --git a/tests/workflows/builtin/test_execute_operation.py b/tests/workflows/builtin/test_execute_operation.py new file mode 100644 index 0000000..457a569 --- /dev/null +++ b/tests/workflows/builtin/test_execute_operation.py @@ -0,0 +1,45 @@ +# 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. + +import pytest + +from aria.workflows.builtin.execute_operation import execute_operation + +from . import simple_context, NODE_OPERATIONS_INSTALL + + +@pytest.fixture +def context(): + return simple_context() + + +def test_execute_operation(context): + operation_name = NODE_OPERATIONS_INSTALL[0] + node_instance_id = 'dependency_node_instance' + execute_operations = list(execute_operation( + context=context, + operation=operation_name, + operation_kwargs={}, + allow_kwargs_override=False, + run_by_dependency_order=False, + type_names=[], + node_ids=[], + node_instance_ids=[node_instance_id] + ).topological_order()) + + assert len(execute_operations) == 1 + assert execute_operations[0].name == '{0}.{1}'.format(node_instance_id, operation_name) + +# TODO: add more scenarios http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/tests/workflows/builtin/test_heal.py ---------------------------------------------------------------------- diff --git a/tests/workflows/builtin/test_heal.py b/tests/workflows/builtin/test_heal.py new file mode 100644 index 0000000..8cea941 --- /dev/null +++ b/tests/workflows/builtin/test_heal.py @@ -0,0 +1,82 @@ +# 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. + +import pytest + +from aria.workflows.builtin.heal import heal + +from . import (simple_context, + assert_node_install_operations, + assert_node_uninstall_operations) + + +@pytest.fixture +def context(): + return simple_context() + + +def test_heal_dependent_node(context): + heal_graph = heal(context=context, node_instance_id='dependent_node_instance') + uninstall_subgraph, install_subgraph = list(heal_graph.topological_order(reverse=True)) + dependent_node_subgraph_uninstall, dependency_node_subgraph_uninstall = \ + list(uninstall_subgraph.topological_order(reverse=True)) + dependency_node_subgraph_install, dependent_node_subgraph_install = \ + list(install_subgraph.topological_order(reverse=True)) + + dependent_node_uninstall_operations = \ + list(dependent_node_subgraph_uninstall.topological_order(reverse=True)) + dependency_node_uninstall_operations = \ + list(dependency_node_subgraph_uninstall.topological_order(reverse=True)) + dependent_node_install_operations = \ + list(dependent_node_subgraph_install.topological_order(reverse=True)) + dependency_node_install_operations = \ + list(dependency_node_subgraph_install.topological_order(reverse=True)) + + assert_node_uninstall_operations(dependent_node_uninstall_operations, with_relationships=True) + assert len(dependency_node_uninstall_operations) == 0 + + assert len(dependency_node_install_operations) == 0 + assert_node_install_operations(dependent_node_install_operations, with_operations=True) + + +def test_heal_dependency_node(context): + heal_graph = heal(context=context, node_instance_id='dependency_node_instance') + uninstall_subgraph, install_subgraph = list(heal_graph.topological_order(reverse=True)) + + uninstall_operations = list(uninstall_subgraph.topological_order(reverse=True)) + unlink_source, unlink_target = uninstall_operations[:2] + dependent_node_subgraph_uninstall, dependency_node_subgraph_uninstall = uninstall_operations[2:] + + install_operations = list(install_subgraph.topological_order(reverse=True)) + dependency_node_subgraph_install, dependent_node_subgraph_install = install_operations[:2] + establish_source, establish_target = install_operations[2:] + + assert len(list(dependent_node_subgraph_uninstall.tasks)) == 0 + dependency_node_uninstall_operations = \ + list(dependency_node_subgraph_uninstall.topological_order(reverse=True)) + assert len(list(dependent_node_subgraph_install.tasks)) == 0 + dependency_node_install_operations = \ + list(dependency_node_subgraph_install.topological_order(reverse=True)) + + assert unlink_source.name.startswith('aria.interfaces.relationship_lifecycle.unlink') + assert unlink_target.name.startswith('aria.interfaces.relationship_lifecycle.unlink') + assert_node_uninstall_operations(dependency_node_uninstall_operations) + + assert_node_install_operations(dependency_node_install_operations) + assert establish_source.name.startswith('aria.interfaces.relationship_lifecycle.establish') + assert establish_target.name.startswith('aria.interfaces.relationship_lifecycle.establish') + + +# TODO: add tests for contained in scenario http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/tests/workflows/builtin/test_install.py ---------------------------------------------------------------------- diff --git a/tests/workflows/builtin/test_install.py b/tests/workflows/builtin/test_install.py new file mode 100644 index 0000000..4cbc1dc --- /dev/null +++ b/tests/workflows/builtin/test_install.py @@ -0,0 +1,36 @@ +# 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. + +import pytest + +from aria.workflows.builtin.install import install + +from . import simple_context, assert_node_install_operations + + +@pytest.fixture +def context(): + return simple_context() + + +def test_install(context): + install_operations = install(context=context).topological_order(reverse=True) + + dependency_node_subgraph, dependent_node_subgraph = list(install_operations) + dependent_node_operations = list(dependent_node_subgraph.topological_order(reverse=True)) + dependency_node_operations = list(dependency_node_subgraph.topological_order(reverse=True)) + + assert_node_install_operations(dependency_node_operations) + assert_node_install_operations(dependent_node_operations, with_operations=True) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/tests/workflows/builtin/test_uninstall.py ---------------------------------------------------------------------- diff --git a/tests/workflows/builtin/test_uninstall.py b/tests/workflows/builtin/test_uninstall.py new file mode 100644 index 0000000..ed4666d --- /dev/null +++ b/tests/workflows/builtin/test_uninstall.py @@ -0,0 +1,36 @@ +# 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. + +import pytest + +from aria.workflows.builtin.uninstall import uninstall + +from . import simple_context, assert_node_uninstall_operations + + +@pytest.fixture +def context(): + return simple_context() + + +def test_uninstall(context): + uninstall_operations = uninstall(context=context).topological_order(reverse=True) + + dependent_node_subgraph, dependency_node_subgraph = list(uninstall_operations) + dependent_node_operations = list(dependent_node_subgraph.topological_order(reverse=True)) + dependency_node_operations = list(dependency_node_subgraph.topological_order(reverse=True)) + + assert_node_uninstall_operations(operations=dependency_node_operations) + assert_node_uninstall_operations(operations=dependent_node_operations, with_relationships=True) http://git-wip-us.apache.org/repos/asf/incubator-ariatosca/blob/137e80cb/tests/workflows/core/test_task_graph_into_exececution_graph.py ---------------------------------------------------------------------- diff --git a/tests/workflows/core/test_task_graph_into_exececution_graph.py b/tests/workflows/core/test_task_graph_into_exececution_graph.py index deab4a3..c6ccda6 100644 --- a/tests/workflows/core/test_task_graph_into_exececution_graph.py +++ b/tests/workflows/core/test_task_graph_into_exececution_graph.py @@ -28,7 +28,7 @@ def no_storage(monkeypatch): def test_task_graph_into_execution_graph(): - task_graph = task_graph.TaskGraph('test_task_graph') + test_task_graph = task_graph.TaskGraph('test_task_graph') simple_before_task = contexts.OperationContext('test_simple_before_task', {}, {}, None) simple_after_task = contexts.OperationContext('test_simple_after_task', {}, {}, None) @@ -36,15 +36,15 @@ def test_task_graph_into_execution_graph(): inner_task = contexts.OperationContext('test_inner_task', {}, {}, None) inner_task_graph.add_task(inner_task) - task_graph.add_task(simple_before_task) - task_graph.add_task(simple_after_task) - task_graph.add_task(inner_task_graph) - task_graph.dependency(inner_task_graph, [simple_before_task]) - task_graph.dependency(simple_after_task, [inner_task_graph]) + test_task_graph.add_task(simple_before_task) + test_task_graph.add_task(simple_after_task) + test_task_graph.add_task(inner_task_graph) + test_task_graph.add_dependency(inner_task_graph, simple_before_task) + test_task_graph.add_dependency(simple_after_task, inner_task_graph) # Direct check execution_graph = DiGraph() - translation.build_execution_graph(task_graph=task_graph, + translation.build_execution_graph(task_graph=test_task_graph, workflow_context=None, execution_graph=execution_graph) execution_tasks = topological_sort(execution_graph) @@ -52,13 +52,13 @@ def test_task_graph_into_execution_graph(): assert len(execution_tasks) == 7 expected_tasks_names = [ - '{0}-Start'.format(task_graph.id), + '{0}-Start'.format(test_task_graph.id), simple_before_task.id, '{0}-Start'.format(inner_task_graph.id), inner_task.id, '{0}-End'.format(inner_task_graph.id), simple_after_task.id, - '{0}-End'.format(task_graph.id) + '{0}-End'.format(test_task_graph.id) ] assert expected_tasks_names == execution_tasks