Merge branch 'dev' of https://github.com/compose-viz/compose-viz into dev-parser
This commit is contained in:
commit
a2dc1fcaed
5 changed files with 97 additions and 2 deletions
|
@ -3,7 +3,7 @@ import typer
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from compose_viz import __app_name__, __version__
|
from compose_viz import __app_name__, __version__
|
||||||
from compose_viz.parser import Parser
|
from compose_viz.parser import Parser
|
||||||
|
from compose_viz.graph import Graph
|
||||||
|
|
||||||
class VisualizationFormats(str, Enum):
|
class VisualizationFormats(str, Enum):
|
||||||
png = "PNG"
|
png = "PNG"
|
||||||
|
@ -54,6 +54,8 @@ def compose_viz(
|
||||||
if compose:
|
if compose:
|
||||||
typer.echo(f"Successfully parsed {input_path}")
|
typer.echo(f"Successfully parsed {input_path}")
|
||||||
|
|
||||||
|
Graph(compose, output_path).render(format)
|
||||||
|
|
||||||
raise typer.Exit()
|
raise typer.Exit()
|
||||||
|
|
||||||
|
|
||||||
|
|
72
compose_viz/graph.py
Normal file
72
compose_viz/graph.py
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import graphviz
|
||||||
|
|
||||||
|
from compose_viz.compose import Compose
|
||||||
|
|
||||||
|
|
||||||
|
def apply_vertex_style(type) -> dict:
|
||||||
|
style = {
|
||||||
|
'service': {
|
||||||
|
'shape': 'component',
|
||||||
|
},
|
||||||
|
'volume': {
|
||||||
|
'shape': 'folder',
|
||||||
|
},
|
||||||
|
'network': {
|
||||||
|
'shape': 'pentagon',
|
||||||
|
},
|
||||||
|
'port': {
|
||||||
|
'shape': 'circle',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return style[type]
|
||||||
|
|
||||||
|
|
||||||
|
def apply_edge_style(type) -> dict:
|
||||||
|
style = {
|
||||||
|
'ports': {
|
||||||
|
'style': 'solid',
|
||||||
|
},
|
||||||
|
'links': {
|
||||||
|
'style': 'solid',
|
||||||
|
},
|
||||||
|
'volumes': {
|
||||||
|
'style': 'dashed',
|
||||||
|
},
|
||||||
|
'depends_on': {
|
||||||
|
'style': 'dotted',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return style[type]
|
||||||
|
|
||||||
|
|
||||||
|
class Graph:
|
||||||
|
def __init__(self, compose: Compose, filename: str) -> None:
|
||||||
|
self.dot = graphviz.Digraph()
|
||||||
|
self.dot.attr('graph', background='#ffffff', pad='0.5', ratio='fill')
|
||||||
|
self.compose = compose
|
||||||
|
self.filename = filename
|
||||||
|
|
||||||
|
def add_vertex(self, name: str, type: str) -> None:
|
||||||
|
self.dot.node(name, **apply_vertex_style(type))
|
||||||
|
|
||||||
|
def add_edge(self, head: str, tail: str, type: str) -> None:
|
||||||
|
self.dot.edge(head, tail, **apply_edge_style(type))
|
||||||
|
|
||||||
|
def render(self, format: str, cleanup: bool = True) -> None:
|
||||||
|
for service in self.compose.services:
|
||||||
|
self.add_vertex(service.name, 'service')
|
||||||
|
for network in service.networks:
|
||||||
|
self.add_vertex("net#" + network, 'network')
|
||||||
|
self.add_edge(service.name, "net#" + network, 'links')
|
||||||
|
for volume in service.volumes:
|
||||||
|
self.add_vertex(volume, 'volume')
|
||||||
|
self.add_edge(service.name, volume, 'links')
|
||||||
|
for port in service.ports:
|
||||||
|
self.add_vertex(port, 'port')
|
||||||
|
self.add_edge(service.name, port, 'ports')
|
||||||
|
for depends_on in service.depends_on:
|
||||||
|
self.dot.edge(depends_on, service.name, 'depends_on')
|
||||||
|
|
||||||
|
self.dot.render(outfile=self.filename, format=format, cleanup=cleanup)
|
19
poetry.lock
generated
19
poetry.lock
generated
|
@ -39,6 +39,19 @@ category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "graphviz"
|
||||||
|
version = "0.20"
|
||||||
|
description = "Simple Python interface for Graphviz"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["tox (>=3)", "flake8", "pep8-naming", "wheel", "twine"]
|
||||||
|
docs = ["sphinx (>=4)", "sphinx-autodoc-typehints", "sphinx-rtd-theme"]
|
||||||
|
test = ["pytest (>=7)", "pytest-mock (>=3)", "mock (>=4)", "pytest-cov", "coverage"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iniconfig"
|
name = "iniconfig"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
|
@ -146,7 +159,7 @@ test = ["shellingham (>=1.3.0,<2.0.0)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "f9abb7a4321c120cbd771d7269efc378a123f9ac9920a9413f3b61f1d6604663"
|
content-hash = "f9f303620dc1f23552238ab8cd7c4db52ef8ee897076bb941866826bc7004dfb"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
atomicwrites = [
|
atomicwrites = [
|
||||||
|
@ -165,6 +178,10 @@ colorama = [
|
||||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||||
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
||||||
]
|
]
|
||||||
|
graphviz = [
|
||||||
|
{file = "graphviz-0.20-py3-none-any.whl", hash = "sha256:62c5f48bcc534a45b4588c548ff75e419c1f1f3a33d31a91796ae80a7f581e4a"},
|
||||||
|
{file = "graphviz-0.20.zip", hash = "sha256:76bdfb73f42e72564ffe9c7299482f9d72f8e6cb8d54bce7b48ab323755e9ba5"},
|
||||||
|
]
|
||||||
iniconfig = [
|
iniconfig = [
|
||||||
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
||||||
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
||||||
|
|
|
@ -15,6 +15,7 @@ include = [
|
||||||
python = "^3.9"
|
python = "^3.9"
|
||||||
typer = "^0.4.1"
|
typer = "^0.4.1"
|
||||||
PyYAML = "^6.0"
|
PyYAML = "^6.0"
|
||||||
|
graphviz = "^0.20"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
pytest = "^7.1.2"
|
pytest = "^7.1.2"
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import os
|
||||||
|
|
||||||
from typer.testing import CliRunner
|
from typer.testing import CliRunner
|
||||||
from compose_viz import cli
|
from compose_viz import cli
|
||||||
|
|
||||||
|
@ -11,3 +13,4 @@ def test_cli():
|
||||||
|
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
assert f"Successfully parsed {input_path}\n" in result.stdout
|
assert f"Successfully parsed {input_path}\n" in result.stdout
|
||||||
|
assert os.path.exists("compose-viz.png")
|
||||||
|
|
Loading…
Reference in a new issue