How to build a diagram in Python

Anyone who has ever had to build diagrams in draw.io or Google Diagrams remembers the tediousness and slowness of this process. Today we are sharing with you a material that shows step by step how you can build beautiful architectural diagrams using Python. The main convenience is the built-in nodes for the designation of services and programming languages. Just code and no mouse.


Foreword

I stumbled upon a valuable Python library this week. This library is called Diagrams… With the help of this library, beautiful diagrams are quickly created, which I could do awkwardly by inserting images into draw.io or Google Diagrams. I would spend hours getting everything aligned correctly. In addition to this grueling work, when I later needed to update the diagrams, I lifted and moved more than half of the components for the sake of a few architectural changes. After further exploring the library, I could see that it was able to make things easier.

Beginning of work

We need Python 3.6 or higher. We also need GraphViz: it renders charts. The Github repo has a pretty decent section “Beginning of work”… To get started, I needed to execute the following command:

pip install diagrams


The code is located here

Component types

The diagram library provides components from various vendors. Probably something from this list suits your needs.

  • AWS / GCP / Azure – provide official cloud services resources for the chart. My team mostly works in GCP and I would have spent hours creating these diagrams by hand before stumbling upon this library, so I was a little excited when I found nodes at my fingertips.
  • Generic and local – these nodes are most likely to be used together in case you want to illustrate technologies in the cloud independently of it. For example, providing the architecture with a Beam component on top of a Google DataFlow display.
  • Frameworks – these components are useful when you want to show a programming language.
  • SaaS – a collection of SaaS nodes that you can use when you want to show that your architecture has Slack notifications.

Elements of charts

  • Nodes Is an abstract concept that is a single component of the system.
  • Clusters – allow you to organize nodes into groups (or clusters).
  • Ribs – display the connection between nodes.

First diagram

Now that you know the basic concepts, let’s build a very simple code diagram in the order in which we learned the concepts. The diagram will describe a simple AWS load balanced website with PostgreSQL database and Redis cache to show the variety of services.

1. Chart working area

Let’s describe an empty chart with a label:

from diagrams import Diagram

with Diagram("Simple Website Diagram") as diag:
    pass
diag # This will illustrate the diagram if you are using a Google Colab or Jypiter notebook.


The code is located here

2. Adding nodes

Now that we have a workspace, it’s time to add the website nodes. The nodes you add come from different vendors, AWS and OnPrem. Chances are, if you were doing it for real, you would stick with AWS as they have offerings like RDS and ElastiCache that you probably have in your projects.

from diagrams import Diagram, Cluster
from diagrams.aws.compute import EC2
from diagrams.aws.network import ELB
from diagrams.aws.network import Route53
from diagrams.onprem.database import PostgreSQL # Would typically use RDS from aws.database
from diagrams.onprem.inmemory import Redis # Would typically use ElastiCache from aws.database

with Diagram("Simple Website Diagram") as diag:
    dns = Route53("dns")
    load_balancer = ELB("Load Balancer")
    database = PostgreSQL("User Database")
    cache = Redis("Cache")
    svc_group = [EC2("Webserver 1"),
                 EC2("Webserver 2"),
                 EC2("Webserver 3")]
diag # This will illustrate the diagram if you are using a Google Colab or Jypiter notebook.

The nodes displayed are the “ingredients” of the architecture we want to build. The next step is organizing some of the nodes into logical groups, and then connecting the nodes with edges.


The code is located here

3. Grouping of nodes (optional)

In this example, we will simply group the load balanced web servers. In a large number of diagrams I’ve created, this was not always necessary, but as the architecture grows, grouping nodes into clusters usually increases readability. As you can see, we just need to move the nodes to the area of ​​the created cluster.

from diagrams import Diagram, Cluster
from diagrams.aws.compute import EC2
from diagrams.aws.network import ELB
from diagrams.aws.network import Route53
from diagrams.onprem.database import PostgreSQL # Would typically use RDS from aws.database
from diagrams.onprem.inmemory import Redis # Would typically use ElastiCache from aws.database

with Diagram("Simple Website Diagram") as diag:
    dns = Route53("dns")
    load_balancer = ELB("Load Balancer")
    database = PostgreSQL("User Database")
    cache = Redis("Cache")
    with Cluster("Webserver Cluster"):
        svc_group = [EC2("Webserver 1"),
                    EC2("Webserver 2"),
                    EC2("Webserver 3")]
diag # This will illustrate the diagram if you are using a Google Colab or Jypiter notebook.

In the figure, you can see that the diagram is still just a list of nodes, but now we have grouped the corresponding nodes into logical groupings.


The code is located here

4. A single whole of components

We will not link nodes organized for use in architecture here. This task usually took me the most time when I needed to update or tweak the architecture. See below. We just define the flow to each node using the double arrows and you’re done! Here we are linking nodes without labels, but if you look at the documentation, then applying labels to your links, you will see that it is simple.

from diagrams import Diagram, Cluster
from diagrams.aws.compute import EC2
from diagrams.aws.network import ELB
from diagrams.aws.network import Route53
from diagrams.onprem.database import PostgreSQL # Would typically use RDS from aws.database
from diagrams.onprem.inmemory import Redis # Would typically use ElastiCache from aws.database

with Diagram("Simple Website Diagram", direction='LR') as diag: # It's LR by default, but you have a few options with the orientation
    dns = Route53("dns")
    load_balancer = ELB("Load Balancer")
    database = PostgreSQL("User Database")
    cache = Redis("Cache")
    with Cluster("Webserver Cluster"):
        svc_group = [EC2("Webserver 1"),
                    EC2("Webserver 2"),
                    EC2("Webserver 3")]
    dns >> load_balancer >> svc_group
    svc_group >> cache
    svc_group >> database
diag # This will illustrate the diagram if you are using a Google Colab or Jypiter notebook.

The final image can be seen below, and now you can see the logical connection between the diagram nodes. The direction of the link can be expanded by changing the order of the nodes. In addition to customizing the flow, you can change other things as well: the edge object contains three attributes: label, color, and style. I will not describe how this is done here. If you’re curious, there is a link to the documentation at the end of this article, these attributes reflect the corresponding GraphViz attributes, which makes things easier if you’ve worked with graphviz edges.


The code is located here

Conclusion

This workflow has a lot of potential when it comes to automation capabilities and time savings in overall architectural diagram maintenance. The time saved by this tool encourages you to use this approach in the future. Of course, I will miss the effort of manually adjusting the diagram, carefully aligning the components and arrows with each iteration of my architecture.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *