def test_generate_dependencies(self): """ Tests we can generates a list of dependencies for a graph using source nodes""" sources = find_source_nodes(self.graph) actual_dependencies = generate_dependencies(sources, self.graph) expected_dependencies = [ [(1, "1", ["2", "4", "6"]), (2, "2", []), (2, "4", []), (2, "6", [])], [(1, "3", ["5", "6"]), (2, "5", []), (2, "6", [])] ] self.assertEqual(actual_dependencies, expected_dependencies)
def execute_graph(self, num_parallel: int = 4, debug: bool = False, print_only_changes: bool = False): """ Function for executing the graph. Will execute in parallel, up to the limit given in num_parallel. :param num_parallel: The number of pipeline entries to run in parallel. :param debug: True if Terraform debugging should be turned on. :param print_only_changes: True if only directories which contained changes should be printed. """ sources = find_source_nodes(self.graph) futures_to_paths = {} with concurrent.futures.ThreadPoolExecutor( max_workers=num_parallel) as executor: for source in sources: entry = self._get_or_create_entry(source) future = executor.submit(entry.execute, self.command, debug=debug) futures_to_paths[future] = entry.path for future in concurrent.futures.as_completed(futures_to_paths): path = futures_to_paths[future] exit_code, stdout, changes_detected = future.result() if stdout and print_only_changes and not changes_detected: stdout = ["No changes detected.\n"] print(f"Output for {path}:\n\n{''.join(stdout).strip()}\n") if exit_code != 0: self.failures.append(path) successors = list(self.graph.successors(path)) if successors: self.recursive_executor(executor, successors, num_parallel, debug, print_only_changes) for node in self.graph: item = self.graph_dict.get(node) if not item: self.not_applied.add(node) elif item.state == "no-op": self.not_applied.add(item.path) else: self.applied.add(node)
def test_visualizer(self): """ Tests we can print given a list of dependencies""" sources = find_source_nodes(self.graph) dependencies = generate_dependencies(sources, self.graph) visualize(dependencies)
def test_find_source_nodes(self): """Tests we can find source nodes for a given graph""" actual_sources = find_source_nodes(self.graph) expected_sources = ["1", "3"] self.assertEqual(actual_sources, expected_sources)
def execute_graph(self, num_parallel: int = 4, debug: bool = False, print_only_changes: bool = False): """ Function for executing the graph. Will execute in parallel, up to the limit given in num_parallel. :param num_parallel: The number of pipeline entries to run in parallel. :param debug: True if Terraform debugging should be turned on. :param print_only_changes: True if only directories which contained changes should be printed. """ sources = find_source_nodes(self.graph) futures_to_paths = {} with concurrent.futures.ThreadPoolExecutor( max_workers=num_parallel) as executor: for source in sources: entry = self._get_or_create_entry(source) if not self._has_prefix(entry): future = executor.submit(entry.no_op) futures_to_paths[future] = entry.path continue print("Executing %s %s ..." % (entry.path, self.command)) future = executor.submit(entry.execute, self.command, debug=debug) futures_to_paths[future] = entry.path for future in concurrent.futures.as_completed(futures_to_paths): path = futures_to_paths[future] if self._get_or_create_entry(path).state != "no-op": exit_code, stdout, changes_detected = future.result() if print_only_changes and not changes_detected: stdout = ["No changes detected.\n"] print("\nFinished executing %s %s ..." % (path, self.command)) print("Output:\n\n%s\n" % "".join(stdout).strip()) if exit_code != 0: self.failures.append(path) successors = list(self.graph.successors(path)) if successors: self.recursive_executor(executor, successors, num_parallel, debug, print_only_changes) for node in self.graph: item = self.graph_dict.get(node) if not item: self.not_applied.add(node) else: if item.state == "no-op": self.not_applied.add(item.path) if self.not_applied: print( "The following directories have not been run since they are out of scope" ) print(self.not_applied) if self.failures: print("The follow directories failed with command '%s':\n%s" % (self.command, "\n".join(self.failures)))