Skip to content

Commit

Permalink
feat: Add initial support for handlers (#217)
Browse files Browse the repository at this point in the history
Related #214 


- Add the handlers to the graph with `--show-handlers`. **This is the
initial support for handlers.** They are by default added at the end of
the play and roles only. This doesn't reflect Ansible behavior.
- Changes the shape of the graphviz node to make it consistent with
Mermaid. The tasks will be rectangle instead of `octagon`:
https://graphviz.org/doc/info/shapes.html
- Refactor how the node/task index are computed given we can now add
handlers after all the tasks are parsed.
- Add a new `display_name()` method to the node for a friendly name for
the graph. This removes the of passing the `node_label_prefix` in
multiple places.
- Remove the class **CompositeTasksNode** as it is no longer needed
anymore.
- Remove the play name from the edge going from playbook to the plays.
This was not consistent with the other edges.
  • Loading branch information
haidaraM authored Dec 22, 2024
1 parent 5ccfed2 commit df7be04
Show file tree
Hide file tree
Showing 21 changed files with 806 additions and 160 deletions.
27 changes: 18 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ JavaScript:
Lastly, you can provide your own protocol formats
with `--open-protocol-handler custom --open-protocol-custom-formats '{}'`. See the help
and [an example.](https://github.com/haidaraM/ansible-playbook-grapher/blob/34e0aef74b82808dceb6ccfbeb333c0b531eac12/ansibleplaybookgrapher/renderer/__init__.py#L32-L41)
To not confuse with [Ansible Handlers.](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html)
- Export the dot file used to generate the graph with Graphviz.

## Prerequisites
Expand Down Expand Up @@ -79,8 +80,9 @@ At the time of writing, two renderers are supported:
2. `mermaid-flowchart`: Generate the graph in [Mermaid](https://mermaid.js.org/syntax/flowchart.html) format. You can
directly embed the graph in your Markdown and GitHub (
and [other integrations](https://mermaid.js.org/ecosystem/integrations.html)) will render it.
3. `json`: Generate a JSON representation of the graph to be used by other tools. The corresponding JSON schema
is [here.](https://github.com/haidaraM/ansible-playbook-grapher/tree/main/tests/fixtures/json-schemas)
3. `json`: Generate a JSON representation of the graph. The corresponding JSON schema
is [here.](https://github.com/haidaraM/ansible-playbook-grapher/tree/main/tests/fixtures/json-schemas) The JSON
output will give you more flexibility to create your own renderer.

If you are interested to support more renderers, feel free to create an issue or raise a PR based on the existing
renderers.
Expand Down Expand Up @@ -396,11 +398,14 @@ regarding the blocks.
The available options:

```
usage: ansible-playbook-grapher [-h] [-v] [-i INVENTORY] [--include-role-tasks] [-s] [--view] [-o OUTPUT_FILENAME]
[--open-protocol-handler {default,vscode,custom}] [--open-protocol-custom-formats OPEN_PROTOCOL_CUSTOM_FORMATS]
[--group-roles-by-name] [--renderer {graphviz,mermaid-flowchart,json}] [--renderer-mermaid-directive RENDERER_MERMAID_DIRECTIVE]
[--renderer-mermaid-orientation {TD,RL,BT,RL,LR}] [--version] [--hide-plays-without-roles] [--hide-empty-plays] [-t TAGS]
[--skip-tags SKIP_TAGS] [--vault-id VAULT_IDS] [-J | --vault-password-file VAULT_PASSWORD_FILES] [-e EXTRA_VARS]
usage: ansible-playbook-grapher [-h] [-v] [--exclude-roles EXCLUDE_ROLES] [--only-roles] [-i INVENTORY] [--include-role-tasks] [-s]
[--view] [-o OUTPUT_FILENAME] [--open-protocol-handler {default,vscode,custom}]
[--open-protocol-custom-formats OPEN_PROTOCOL_CUSTOM_FORMATS] [--group-roles-by-name]
[--renderer {graphviz,mermaid-flowchart,json}]
[--renderer-mermaid-directive RENDERER_MERMAID_DIRECTIVE]
[--renderer-mermaid-orientation {TD,RL,BT,RL,LR}] [--version] [--hide-plays-without-roles]
[--hide-empty-plays] [--show-handlers] [-t TAGS] [--skip-tags SKIP_TAGS] [--vault-id VAULT_IDS] [-J |
--vault-password-file VAULT_PASSWORD_FILES] [-e EXTRA_VARS]
playbooks [playbooks ...]
Make graphs from your Ansible Playbooks.
Expand All @@ -418,7 +423,7 @@ options:
Hide the plays that end up with no roles in the graph (after applying the tags filter). Only roles at the play level and include_role as tasks are
considered (no import_role).
--include-role-tasks Include the tasks of the roles in the graph. Applied when parsing the playbooks.
--only-roles Ignore all tasks when rendering graphs.
--only-roles Only display the roles in the graph (ignoring the tasks)
--open-protocol-custom-formats OPEN_PROTOCOL_CUSTOM_FORMATS
The custom formats to use as URLs for the nodes in the graph. Required if --open-protocol-handler is set to custom. You should provide a
JSON formatted string like: {"file": "", "folder": ""}. Example: If you want to open folders (roles) inside the browser and files
Expand All @@ -437,12 +442,13 @@ options:
https://mermaid.js.org/config/directives.html. Default: '%%{ init: { "flowchart": { "curve": "bumpX" } } }%%'
--renderer-mermaid-orientation {TD,RL,BT,RL,LR}
The orientation of the flow chart. Default: 'LR'
--show-handlers Show the handlers in the graph. See the limitations in the project README on GitHub.
--skip-tags SKIP_TAGS
only run plays and tasks whose tags do not match these values. This argument may be specified multiple times.
--vault-id VAULT_IDS the vault identity to use. This argument may be specified multiple times.
--vault-password-file VAULT_PASSWORD_FILES, --vault-pass-file VAULT_PASSWORD_FILES
vault password file
--version
--version show program's version number and exit
--view Automatically open the resulting SVG file with your system's default viewer application for the file type
-J, --ask-vault-password, --ask-vault-pass
ask for vault password
Expand Down Expand Up @@ -480,6 +486,9 @@ More information [here](https://docs.ansible.com/ansible/latest/reference_append
Always check the edge label to know the task order.
- The label of the edges may overlap with each other. They are positioned so that they are as close as possible to
the target nodes. If the same role is used in multiple plays or playbooks, the labels can overlap.
- **Ansible Handlers**: The handlers are partially supported for the moment. Their position in the graph doesn't entirely
reflect their real order of execution in the playbook. They are displayed at the end of the play and roles, but they
might be executed before that.

## Contribution

Expand Down
20 changes: 19 additions & 1 deletion ansibleplaybookgrapher/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def run(self):
save_dot_file=self.options.save_dot_file,
hide_empty_plays=self.options.hide_empty_plays,
hide_plays_without_roles=self.options.hide_plays_without_roles,
show_handlers=self.options.show_handlers,
)

case "mermaid-flowchart":
Expand All @@ -113,6 +114,7 @@ def run(self):
orientation=self.options.renderer_mermaid_orientation,
hide_empty_plays=self.options.hide_empty_plays,
hide_plays_without_roles=self.options.hide_plays_without_roles,
show_handlers=self.options.show_handlers,
)

case "json":
Expand All @@ -124,6 +126,7 @@ def run(self):
view=self.options.view,
hide_empty_plays=self.options.hide_empty_plays,
hide_plays_without_roles=self.options.hide_plays_without_roles,
show_handlers=self.options.show_handlers,
)

case _:
Expand Down Expand Up @@ -303,6 +306,14 @@ def _add_my_options(self) -> None:
help="Hide the plays that end up with no tasks in the graph (after applying the tags filter).",
)

self.parser.add_argument(
"--show-handlers",
dest="show_handlers",
action="store_true",
default=False,
help="Show the handlers in the graph. See the limitations in the project README on GitHub.",
)

self.parser.add_argument(
"playbooks",
help="Playbook(s) to graph. You can specify multiple playbooks, separated by spaces and reference playbooks in collections.",
Expand Down Expand Up @@ -357,7 +368,7 @@ def post_process_args(self, options: Namespace) -> Namespace:
if self.options.open_protocol_handler == "custom":
self.validate_open_protocol_custom_formats()

# create list of roles to exclude
# create the list of roles to exclude
if options.exclude_roles:
exclude_roles = set()
for arg in options.exclude_roles:
Expand All @@ -376,6 +387,13 @@ def post_process_args(self, options: Namespace) -> Namespace:

options.exclude_roles = sorted(exclude_roles)

if self.options.show_handlers:
display.warning(
"The handlers are partially supported for the moment. Their position in the graph doesn't entirely reflect "
"their real order of execution in the playbook. They are displayed at the end of the play and roles, "
"but they might be executed before that."
)

return options

def validate_open_protocol_custom_formats(self) -> None:
Expand Down
Loading

0 comments on commit df7be04

Please sign in to comment.