Add command line parameters

This commit is contained in:
LeoVerto 2018-08-31 04:50:58 +02:00
parent f715389aa6
commit ab88c610e1
5 changed files with 100 additions and 81 deletions

5
.gitignore vendored
View file

@ -1,4 +1,3 @@
/sandbox *.gv
/*.gv *.pdf
/*.pdf
.idea .idea

View file

@ -10,4 +10,4 @@ graphviz = "*"
[dev-packages] [dev-packages]
[requires] [requires]
python_version = "3.7" python_version = "3"

4
Pipfile.lock generated
View file

@ -1,11 +1,11 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "dd7e5eeba8f90bf7a95640eb165b90b96af947ddf7220542916f95709f01f14d" "sha256": "b980cd984b5794dc93711b11dcaadee33a6ee25a811c7aa8c8a6c7db32a78204"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
"python_version": "3.7" "python_version": "3"
}, },
"sources": [ "sources": [
{ {

View file

@ -1,13 +1,23 @@
Docker Network Graph # Docker Network Graph
--------------------
Sample python script to draw graph of Docker networks and containers Sample python script to draw graph of Docker networks and containers
Install/run ## Usage
=========== usage: docker-net-graph.py [-h] [-v] [-o OUT]
#> git clone https://github.com/LeoVerto/docker-network-graph-poc.git Generate docker network graph.
#> cd docker-network-graph-poc
#> pipenv install optional arguments:
#> pipenv run python docker-net-graph.py -h, --help show this help message and exit
-v, --verbose Verbose output
-o OUT, --out OUT Write output to file
In most cases what you want to run are the following couple commands:
git clone https://github.com/LeoVerto/docker-network-graph-poc.git
cd docker-network-graph-poc
pipenv install
pipenv run python docker-net-graph.py -o output.gv
This will end up generating a .pdf file containing the graph.

140
docker-net-graph.py Normal file → Executable file
View file

@ -1,80 +1,90 @@
from docker import Client #!/usr/bin/python3
import os import os
import pprint
import json import json
import argparse
from docker import Client
from graphviz import Graph from graphviz import Graph
dot = Graph(comment='Docker Network Graph',
graph_attr=dict( rankdir="TB", packmode='graph', pack='true')
)
docker_client = Client(os.environ.get("DOCKER_HOST", "unix:///var/run/docker.sock")) def generate_graph(verbose: bool, file: str):
dot = Graph(comment='Docker Network Graph',
graph_attr=dict(rankdir="TB", packmode='graph', pack='true')
)
def dump_json(obj): docker_client = Client(os.environ.get("DOCKER_HOST", "unix:///var/run/docker.sock"))
print(json.dumps(obj, indent=4))
for c in sorted(docker_client.containers()): def dump_json(obj):
name = c['Names'][0] print(json.dumps(obj, indent=4))
container_id = c['Id']
node_id = 'container_%s' % container_id for c in docker_client.containers():
name = c['Names'][0]
container_id = c['Id']
iface_labels = [] node_id = 'container_%s' % container_id
for net_name, net_info in c['NetworkSettings']['Networks'].items(): iface_labels = []
label_iface = "<%s> %s" % (net_info['EndpointID'], net_info['IPAddress'])
iface_labels.append(label_iface) for net_name, net_info in c['NetworkSettings']['Networks'].items():
label_iface = "<%s> %s" % (net_info['EndpointID'], net_info['IPAddress'])
print('|'.join(iface_labels)) iface_labels.append(label_iface)
if verbose:
print('|'.join(iface_labels))
dot.node(node_id,
shape='record',
label="{ %s | { %s } }" % (name, '|'.join(iface_labels)),
fillcolor='#ff9999',
style='filled')
for net in docker_client.networks():
net_name = net['Name']
try:
gateway = net['IPAM']['Config'][0]['Gateway']
except IndexError:
gateway = None
try:
subnet = net['IPAM']['Config'][0]['Subnet']
except IndexError:
subnet = None
if verbose:
print("Network: %s %s gw:%s" % (net_name, subnet, gateway))
net_node_id = "net_%s" % (net_name,)
net_label_html = '<br/>'.join([s for s in ['<font color="#777777"><i>network</i></font>', net_name, subnet, gateway] if s is not None])
dot.node(net_node_id,
shape='record',
label="{<gw_iface> %s| %s }" % (gateway, net_name),
fillcolor='#99ff99',
style='filled')
for container_id, container in sorted(net['Containers'].items()):
if verbose:
dump_json(container)
if verbose:
print(" * ", container['Name'], container['IPv4Address'], container['IPv6Address'])
container_node_id = 'container_%s' % container_id
container_iface_ref = "%s:%s" % (container_node_id, container['EndpointID'])
dot.edge(container_iface_ref, net_node_id+":gw_iface")
print(dot.source)
if file:
dot.render(file)
dot.node(node_id, if __name__ == "__main__":
shape='record', parser = argparse.ArgumentParser(description="Generate docker network graph.")
label="{ %s | { %s } }" % (name, '|'.join(iface_labels)), parser.add_argument("-v", "--verbose", help="Verbose output", action="store_true")
fillcolor='#ff9999', parser.add_argument("-o", "--out", help="Write output to file", type=str)
style='filled') args = parser.parse_args()
for net in docker_client.networks():
net_name = net['Name']
try:
gateway = net['IPAM']['Config'][0]['Gateway']
except IndexError:
gateway = None
try:
subnet = net['IPAM']['Config'][0]['Subnet']
except IndexError:
subnet = None
print("Network: %s %s gw:%s" % ( net_name, subnet,gateway))
net_node_id = "net_%s" % (net_name,)
net_label_html = '<br/>'.join([s for s in ['<font color="#777777"><i>network</i></font>', net_name, subnet, gateway] if s != None])
dot.node(net_node_id,
shape='record',
label="{<gw_iface> %s| %s }" % (gateway, net_name),
fillcolor='#99ff99',
style='filled')
for container_id, container in sorted(net['Containers'].items()):
dump_json(container)
print(" * ", container['Name'], container['IPv4Address'], container['IPv6Address'])
container_node_id = 'container_%s' % container_id
container_iface_ref = "%s:%s" % (container_node_id, container['EndpointID'])
dot.edge(container_iface_ref, net_node_id+":gw_iface")
print(dot.source)
dot.render('dng.gv')
generate_graph(args.verbose, args.out)