Skip to content

Commit

Permalink
feat: Add support for a JSON renderer (#193)
Browse files Browse the repository at this point in the history
Co-authored-by: haidaraM <[email protected]>
  • Loading branch information
haidaraM and haidaraM authored Sep 5, 2024
1 parent 34e0aef commit 90f5a30
Show file tree
Hide file tree
Showing 18 changed files with 1,065 additions and 185 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:

- uses: psf/black@stable
with:
version: "~= 23.0" # https://black.readthedocs.io/en/stable/integrations/github_actions.html
version: "~= 24.0" # https://black.readthedocs.io/en/stable/integrations/github_actions.html
options: ""

- uses: stefanzweifel/git-auto-commit-action@v5
Expand Down
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ venv.bak/
.idea
.vagrant
Vagrantfile
generated-svgs
generated-mermaids
tests/generated-svgs
tests/generated-mermaids/
tests/generated-jsons
**/.DS_Store
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ deploy_test: clean build
test_install: build
@./tests/test_install.sh $(VIRTUALENV_DIR) $(ANSIBLE_CORE_VERSION)

test:
cd tests && pytest test_cli.py test_utils.py test_parser.py test_graph_model.py test_graphviz_postprocessor.py test_graphviz_renderer.py test_mermaid_renderer.py
fmt:
black .

test: fmt
# Due to some side effects with Ansible, we have to run the tests in a certain order
cd tests && pytest test_cli.py test_utils.py test_parser.py test_graph_model.py test_graphviz_postprocessor.py test_graphviz_renderer.py test_mermaid_renderer.py test_json_renderer.py

clean:
@echo "Cleaning..."
Expand Down
215 changes: 133 additions & 82 deletions README.md

Large diffs are not rendered by default.

93 changes: 56 additions & 37 deletions ansibleplaybookgrapher/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@
from ansible.release import __version__ as ansible_version
from ansible.utils.display import Display

from ansibleplaybookgrapher.grapher import Grapher
from ansibleplaybookgrapher import __prog__, __version__
from ansibleplaybookgrapher.grapher import Grapher
from ansibleplaybookgrapher.renderer import OPEN_PROTOCOL_HANDLERS
from ansibleplaybookgrapher.renderer.graphviz import GraphvizRenderer
from ansibleplaybookgrapher.renderer.json import JSONRenderer
from ansibleplaybookgrapher.renderer.mermaid import (
MermaidFlowChartRenderer,
DEFAULT_DIRECTIVE as MERMAID_DEFAULT_DIRECTIVE,
Expand Down Expand Up @@ -54,6 +55,7 @@ def __init__(self, args, callback=None):
self.options = None

def run(self):
# FIXME: run should not return anything.
super().run()

display.verbosity = self.options.verbosity
Expand All @@ -65,38 +67,54 @@ def run(self):
group_roles_by_name=self.options.group_roles_by_name,
)

if self.options.renderer == "graphviz":
renderer = GraphvizRenderer(
playbook_nodes=playbook_nodes,
roles_usage=roles_usage,
)
output_path = renderer.render(
open_protocol_handler=self.options.open_protocol_handler,
open_protocol_custom_formats=self.options.open_protocol_custom_formats,
output_filename=self.options.output_filename,
view=self.options.view,
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,
)

return output_path
else:
renderer = MermaidFlowChartRenderer(
playbook_nodes=playbook_nodes,
roles_usage=roles_usage,
)
output_path = renderer.render(
open_protocol_handler=self.options.open_protocol_handler,
open_protocol_custom_formats=self.options.open_protocol_custom_formats,
output_filename=self.options.output_filename,
view=self.options.view,
directive=self.options.renderer_mermaid_directive,
orientation=self.options.renderer_mermaid_orientation,
hide_empty_plays=self.options.hide_empty_plays,
hide_plays_without_roles=self.options.hide_plays_without_roles,
)
return output_path
match self.options.renderer:
case "graphviz":
renderer = GraphvizRenderer(
playbook_nodes=playbook_nodes,
roles_usage=roles_usage,
)
return renderer.render(
open_protocol_handler=self.options.open_protocol_handler,
open_protocol_custom_formats=self.options.open_protocol_custom_formats,
output_filename=self.options.output_filename,
view=self.options.view,
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,
)

case "mermaid-flowchart":
renderer = MermaidFlowChartRenderer(
playbook_nodes=playbook_nodes,
roles_usage=roles_usage,
)
return renderer.render(
open_protocol_handler=self.options.open_protocol_handler,
open_protocol_custom_formats=self.options.open_protocol_custom_formats,
output_filename=self.options.output_filename,
view=self.options.view,
directive=self.options.renderer_mermaid_directive,
orientation=self.options.renderer_mermaid_orientation,
hide_empty_plays=self.options.hide_empty_plays,
hide_plays_without_roles=self.options.hide_plays_without_roles,
)

case "json":
renderer = JSONRenderer(playbook_nodes, roles_usage)
return renderer.render(
open_protocol_handler=self.options.open_protocol_handler,
open_protocol_custom_formats=self.options.open_protocol_custom_formats,
output_filename=self.options.output_filename,
view=self.options.view,
hide_empty_plays=self.options.hide_empty_plays,
hide_plays_without_roles=self.options.hide_plays_without_roles,
)

case _:
# Likely a bug if we are here
raise AnsibleOptionsError(
f"Unknown renderer '{self.options.renderer}'. This is likely a bug that should be reported."
)

def _add_my_options(self):
"""
Expand Down Expand Up @@ -141,7 +159,8 @@ def _add_my_options(self):
"-o",
"--output-file-name",
dest="output_filename",
help="Output filename without the '.svg' extension. Default: <playbook>.svg",
help="Output filename without the '.svg' extension (for graphviz), '.mmd' for Mermaid or `.json`. "
"The extension will be added automatically.",
)

self.parser.add_argument(
Expand All @@ -150,7 +169,7 @@ def _add_my_options(self):
choices=list(OPEN_PROTOCOL_HANDLERS.keys()),
default="default",
help="""The protocol to use to open the nodes when double-clicking on them in your SVG
viewer. Your SVG viewer must support double-click and Javascript.
viewer (only for graphviz). Your SVG viewer must support double-click and Javascript.
The supported values are 'default', 'vscode' and 'custom'.
For 'default', the URL will be the path to the file or folders. When using a browser,
it will open or download them.
Expand Down Expand Up @@ -180,12 +199,12 @@ def _add_my_options(self):
"--group-roles-by-name",
action="store_true",
default=False,
help="When rendering the graph, only a single role will be display for all roles having the same names. Default: %(default)s",
help="When rendering the graph (graphviz and mermaid), only a single role will be displayed for all roles having the same names. Default: %(default)s",
)

self.parser.add_argument(
"--renderer",
choices=["graphviz", "mermaid-flowchart"],
choices=["graphviz", "mermaid-flowchart", "json"],
default="graphviz",
help="The renderer to use to generate the graph. Default: %(default)s",
)
Expand Down
Loading

0 comments on commit 90f5a30

Please sign in to comment.