Open samuelkdavis-vector opened 1 year ago
I tried something like this, like mentioned in #111 :
from diagrams import Diagram, Cluster, Edge, Node
#graph_attr = {
# "layout":"neato",
# }
graph_attr = {
"layout":"neato",
"compound":"true",
"splines":"spline",
}
scaling_clus_attr = {
"bgcolor":"transparent",
"pencolor":"blue",
"penwidth":"4.0",
"fillcolor" : "green"
}
with Diagram("\n\nOverlapping Clusters", show=False, graph_attr=graph_attr) as diag:
with Cluster("SubnetA","TB",{"bgcolor": "green"}):
A_UpLf = Node("", shape="plaintext", pin="true", pos="0,4")
A_LwRt = Node("", shape="plaintext", pin="true", pos="4,0")
with Cluster("SubnetB","TB"):
B_UpLf = Node("", shape="plaintext", pin="true", pos="6,4")
B_LwRt = Node("", shape="plaintext", pin="true", pos="10,0")
with Cluster("Scaling Set", "LR", graph_attr=scaling_clus_attr):
SS_UpLf = Node("", shape="plaintext", pin="true", pos="2,3")
SS_LwRt = Node("", shape="plaintext", pin="true", pos="8,1")
n1 = Node("node 1", shape="circle", labelloc="c", pin="true", pos="3,2")
n1 = Node("node 2", shape="box", labelloc="c", pin="true", pos="7,2")
But it doesn't work. I just get a circle, a square and a text, with no background.
@kevinvalleau Your code works on my system. Likely a version difference issue.
$ dot -V
dot - graphviz version 7.1.0 (0)
$ pip freeze | grep -E 'diagrams|graphviz'
diagrams==0.20.0
graphviz==0.16
$ hostnamectl | grep Kernel
Kernel: Linux 6.1.7-arch1-1
dot - graphviz version 7.1.0 (20230121.1956)`
diagrams==0.23.3
graphviz==0.20.1
And it still does not work but I am on Windows. I'll try with WSL2.
=> Works on a WSL2 debian.
=> After a few tests, it seems clusters are not working with neato on Windows with my setup. The pure graphviz code here https://graphviz.readthedocs.io/en/stable/examples.html#cluster-py works. But even a small code with one cluster with diagrams does not work.
Can this only be done with exact positioning?
The reason I wanted to use diagrams as code was to gain the benefit of clusters automatic grouping. Pixel perfect diagramming is quite painful when adding an item into an availability zone in a networking diagram which requires resizing subnets, vpcs, accounts, and any arbitrary cross-cutting grouping.
This solution would remove the need for pixel perfect drag-drop resizing, but would require specifically defining where each individual item appears in a grid.
@samuelkdavis-vector
Can this only be done with exact positioning? I don't think so. I am pretty sure this is not a limitation of this library, but a limitation of the dot rendering engine.
have a look at https://graphviz.org/docs/layouts/
I use a loop to calculate the pos for each subnet, looks fine ... But it's hard to add nodes - you need to calculate the pos as well. π’
I tried 2 ways, both big effort ...
(x,y)
to calculate the relative position for each node inside a clustergraph_attr = {"layout": "neato", "compound": "true", "splines": "spline"}
with Diagram("dist/demo", show=False, graph_attr=graph_attr) as diag:
# input
subnet_area = 3
az_count = 3
az_names = ["1a", "1b", "1c", "1d", "1e", "1f"]
layer_count = 3
layer_types = [Cluster, Cluster, Cluster]
# layer_types = [ClusterPublicSubnet, ClusterPrivateSubnet, ClusterIntraSubnet]
layer_names = ["public", "private", "intra"]
# param
spacer = 2.5 # η΄εΎ 1.9
vpc_padding = 1
az_padding = 0.4
subnet_padding = 0.2
vpc_width = subnet_area * az_count + spacer * (az_count - 1)
vpc_height = subnet_area * layer_count + spacer * (layer_count - 1)
# cluster cache, add nodes later
subnets = [[{}] * layer_count for _ in range(az_count)]
with ClusterVPC("vpc") as vpc:
p_tl = Node("", shape="none", pin="true", pos=f"{-vpc_padding},{vpc_height+vpc_padding}")
p_br = Node("", shape="none", pin="true", pos=f"{vpc_width+vpc_padding},{-vpc_padding}")
for ia in range(az_count):
x = (subnet_area + spacer) * ia
y = 0
for il, type in enumerate(layer_types):
y = (subnet_area + spacer) * il
name = f"sn-{layer_names[il]}-{az_names[ia]}"
with type(name) as instance:
p_tl = Node("", shape="none", pin="true", pos=f"{x},{y+subnet_area}")
p_br = Node("", shape="none", pin="true", pos=f"{x+subnet_area},{y}")
subnets[ia][il] = {"subnet": instance, "x": x + subnet_padding, "y": y + subnet_padding}
with Cluster(
f"az-{az_names[ia]}",
graph_attr={
"bgcolor": "transparent",
"penwidth": "2.0",
"style": "rounded,dashed",
},
):
p_tl = Node("", shape="none", pin="true", pos=f"{x-az_padding},{y+subnet_area+az_padding}")
p_br = Node("", shape="none", pin="true", pos=f"{x+subnet_area+az_padding},{-az_padding}")
optimize a litter bit, looks better π
with vpc:
igw = InternetGateway(pin="true", pos=f"{vpc_width/2},{-3}")
with subnets[1][0]["subnet"]:
x, y = subnets[1][0]["x"], subnets[1][0]["y"]
nat = NATGateway(pin="true", pos=f"{x},{y}")
elb = ElasticLoadBalancing(pin="true", pos=f"{x+spacer},{y}")
with subnets[1][1]["subnet"]:
x, y = subnets[1][1]["x"], subnets[1][1]["y"]
eks = EKS(pin="true", pos=f"{x},{y}")
with subnets[1][2]["subnet"]:
x, y = subnets[1][2]["x"], subnets[1][2]["y"]
rds = RDSInstance(pin="true", pos=f"{x},{y}")
igw >> elb >> eks >> rds
eks >> nat >> igw
I would like to have overlapping groups/clusters. I cannot find an example of how to do this. In the linked example - the Public Subnet is in Availability Zone A, but also in a separate group for all public subnets sharing a route table