diff --git a/awx/main/scheduler/dag_simple.py b/awx/main/scheduler/dag_simple.py index fd54b6a34f..2ebda0375b 100644 --- a/awx/main/scheduler/dag_simple.py +++ b/awx/main/scheduler/dag_simple.py @@ -1,3 +1,5 @@ +from collections import deque + class SimpleDAG(object): ''' A simple implementation of a directed acyclic graph ''' @@ -198,3 +200,26 @@ class SimpleDAG(object): node_objs_visited.add(node_obj) path.discard(node_obj) return res + + def sort_nodes_topological(self): + nodes_sorted = deque() + obj_ids_processed = set([]) + + def visit(node): + obj = node['node_object'] + if obj.id in obj_ids_processed: + return + + for child in self.get_dependencies(obj): + visit(child) + obj_ids_processed.add(obj.id) + nodes_sorted.appendleft(node) + + for node in self.nodes: + obj = node['node_object'] + if obj.id in obj_ids_processed: + continue + + visit(node) + + return nodes_sorted diff --git a/awx/main/scheduler/dag_workflow.py b/awx/main/scheduler/dag_workflow.py index b405262218..41aba609b7 100644 --- a/awx/main/scheduler/dag_workflow.py +++ b/awx/main/scheduler/dag_workflow.py @@ -1,6 +1,5 @@ # Python -import copy from awx.main.models import ( WorkflowJobTemplateNode, WorkflowJobNode, @@ -201,10 +200,9 @@ class WorkflowDAG(SimpleDAG): def mark_dnr_nodes(self): root_nodes = self.get_root_nodes() - nodes = copy.copy(root_nodes) nodes_marked_do_not_run = [] - for index, node in enumerate(nodes): + for node in self.sort_nodes_topological(): obj = node['node_object'] if obj.do_not_run is False and not obj.job: @@ -217,7 +215,4 @@ class WorkflowDAG(SimpleDAG): obj.do_not_run = True nodes_marked_do_not_run.append(node) - nodes.extend(self.get_dependencies(obj, 'success_nodes') + - self.get_dependencies(obj, 'failure_nodes') + - self.get_dependencies(obj, 'always_nodes')) return [n['node_object'] for n in nodes_marked_do_not_run]