def generate_graph(self, rule_links, out_file): graph_label = "Rule based visualizer" graph_attr = { "rankdir": "TD", "labelloc": "t", "fontsize": "15", "label": graph_label, } node_attr = {} dot = Digraph( comment="Rule based links visualization", node_attr=node_attr, graph_attr=graph_attr, format="png", ) nodes = set() for _, rule_link in rule_links: print(rule_link._source_action_ref) if rule_link._source_action_ref not in nodes: nodes.add(rule_link._source_action_ref) dot.add_node(rule_link._source_action_ref) if rule_link._dest_action_ref not in nodes: nodes.add(rule_link._dest_action_ref) dot.add_node(rule_link._dest_action_ref) dot.add_edge( rule_link._source_action_ref, rule_link._dest_action_ref, constraint="true", label=rule_link._rule_ref, ) output_path = os.path.join(os.getcwd(), out_file) dot.format = "png" dot.render(output_path)
def main(metadata_path, output_path, print_source=False): metadata_path = os.path.abspath(metadata_path) metadata_dir = os.path.dirname(metadata_path) meta_loader = MetaLoader() data = meta_loader.load(metadata_path) action_name = data["name"] entry_point = data["entry_point"] workflow_metadata_path = os.path.join(metadata_dir, entry_point) chainspec = meta_loader.load(workflow_metadata_path) chain_holder = ChainHolder(chainspec, "workflow") graph_label = "%s action-chain workflow visualization" % (action_name) graph_attr = { "rankdir": "TD", "labelloc": "t", "fontsize": "15", "label": graph_label, } node_attr = {} dot = Digraph( comment="Action chain work-flow visualization", node_attr=node_attr, graph_attr=graph_attr, format="png", ) # dot.body.extend(['rankdir=TD', 'size="10,5"']) # Add all nodes node = chain_holder.get_next_node() while node: dot.add_node(node.name) node = chain_holder.get_next_node(curr_node_name=node.name) # Add connections node = chain_holder.get_next_node() processed_nodes = set([node.name]) nodes = [node] while nodes: previous_node = nodes.pop() success_node = chain_holder.get_next_node( curr_node_name=previous_node.name, condition="on-success") failure_node = chain_holder.get_next_node( curr_node_name=previous_node.name, condition="on-failure") # Add success node (if any) if success_node: dot.add_edge( previous_node.name, success_node.name, constraint="true", color="green", label="on success", ) if success_node.name not in processed_nodes: nodes.append(success_node) processed_nodes.add(success_node.name) # Add failure node (if any) if failure_node: dot.add_edge( previous_node.name, failure_node.name, constraint="true", color="red", label="on failure", ) if failure_node.name not in processed_nodes: nodes.append(failure_node) processed_nodes.add(failure_node.name) if print_source: print(dot.source) if output_path: output_path = os.path.join(output_path, action_name) else: output_path = output_path or os.path.join(os.getcwd(), action_name) dot.format = "png" dot.render(output_path) print("Graph saved at %s" % (output_path + ".png"))