Diagrams: Diagram as Code

repository·master·Indexed 12 days ago

https://github.com/mingrammer/diagrams

A Python library for 'Diagram as Code' that allows developers to define and visualize cloud system architectures through Python scripts. It uses Graphviz to render diagrams and supports major providers including AWS, Azure, GCP, Kubernetes, Alibaba Cloud, Oracle Cloud, IBM, and DigitalOcean, as well as On-Premises, SaaS, and GIS infrastructure. Version 0.25.1.

Tokens
42.2K
Snippets
157
Records
222
Agent score
98%

What's inside Diagrams

  1. What is Diagrams and how does it work?

    master

    Diagrams is a "Diagram as Code" library that allows you to draw cloud system architecture using Python code. It is designed for prototyping new architectures or visualizing existing ones.

    Key Characteristics:

    • Version Control Friendly: Since diagrams are written in Python, you can track changes using Git or other version control systems.
    • Visualization Only: Diagrams does not control actual cloud resources, nor does it generate CloudFormation or Terraform code. It is strictly for drawing.
    • Supported Providers: Includes major cloud providers like AWS, Azure, GCP, Kubernetes, Alibaba Cloud, Oracle Cloud, IBM, DigitalOcean, and more. It also supports On-Premises, SaaS, and various Programming frameworks/languages.
  2. What is a Node in Diagrams

    master

    A Node is an object representing a single system component. Every node is composed of three parts:

    1. Provider: The cloud or platform provider (e.g., aws, azure, gcp, k8s).
    2. Resource Type: The category of the service (e.g., compute, database, network).
    3. Name: The specific identifier for the resource.

    Nodes are imported from provider-specific modules. For example, an AWS EC2 instance is imported from diagrams.aws.compute and instantiated as EC2("name").

    Available nodes can be found in the documentation sidebar organized by provider.

    from diagrams import Diagram
    from diagrams.aws.compute import EC2
    
    with Diagram("Simple Diagram"):
        EC2("web")
  3. Group nodes using the Cluster class

    master

    The Cluster class allows you to group related nodes visually within a box. You use it as a context manager (with Cluster("name")) to wrap the nodes and connections that belong to that logical group.

    from diagrams import Cluster, Diagram
    from diagrams.aws.compute import ECS
    
    with Diagram("Clustered Services", show=False):
        with Cluster("Services"):
            svc_group = [ECS("web1"), ECS("web2")]
  4. Reduce edge noise using blank Node placeholders

    master

    When diagrams become too cluttered with connections, you can use the Node class to create invisible or blank placeholders. This allows you to point multiple edges to a single 'invisible' point within a Cluster, which then branches out to the actual target nodes, effectively simplifying the visual flow.

    To create a blank placeholder, use Node with the following attributes:

    • shape="plaintext"
    • width="0"
    • height="0"
    from diagrams import Cluster, Diagram, Node
    
    with Diagram("Less Edges Example", show=False) as diag:
        with Cluster(""):
            # Create a blank placeholder
            blankHA = Node("", shape="plaintext", width="0", height="0")
    
            with Cluster("Database HA"):
                db = PostgreSQL("users")
                # Connect the placeholder to the cluster content
                blankHA >> db
    
        # Connect ingress to the placeholder instead of every individual node
        ingress >> blankHA
  5. Connect nodes using operators

    master

    Nodes are connected using directional or non-directional operators:

    • >>: Represents a directed edge (flow from left to right).
    • <<: Represents a directed edge (flow from right to left).
    • -: Represents an undirected edge (no specific direction).
    # Directed flow
    node1 >> node2
    
    # Reverse directed flow
    node2 << node1
    
    # Undirected connection
    node1 - node2
  6. Generate C4 diagrams with the diagrams.c4 package

    master

    You can implement the C4 model for software architecture visualization using the diagrams.c4 package. This package provides specific node classes (Person, Container, Database, System, SystemBoundary) and a Relationship class to define the hierarchy and interactions of a software system.

    Key components include:

    • Person: Represents users or actors.
    • Container: Represents a deployable unit (e.g., a web app, mobile app, or API).
    • Database: Represents data storage.
    • System: Represents a software system (can be marked as external=True).
    • SystemBoundary: Used to group related containers within a specific system context.
    • Relationship: Used to define directed edges between nodes with descriptive text.
    from diagrams import Diagram
    from diagrams.c4 import Person, Container, Database, System, SystemBoundary, Relationship
    
    graph_attr = {
        "splines": "spline",
    }
    
    with Diagram("Container diagram for Internet Banking System", direction="TB", graph_attr=graph_attr):
        customer = Person(
            name="Personal Banking Customer", description="A customer of the bank, with personal bank accounts."
        )
    
        with SystemBoundary("Internet Banking System"):
            webapp = Container(
                name="Web Application",
                technology="Java and Spring MVC",
                description="Delivers the static content and the Internet banking single page application.",
            )
    
            spa = Container(
                name="Single-Page Application",
                technology="Javascript and Angular",
                description="Provides all of the Internet banking functionality to customers via their web browser.",
            )
    
            mobileapp = Container(
                name="Mobile App",
                technology="Xamarin",
                description="Provides a limited subset of the Internet banking functionality to customers via their mobile device.",
            )
    
            api = Container(
                name="API Application",
                technology="Java and Spring MVC",
                description="Provides Internet banking functionality via a JSON/HTTPS API.",
            )
    
            database = Database(
                name="Database",
                technology="Oracle Database Schema",
                description="Stores user registration information, hashed authentication credentials, access logs, etc.",
            )
    
        email = System(name="E-mail System", description="The internal Microsoft Exchange e-mail system.", external=True)
    
        mainframe = System(
            name="Mainframe Banking System",
            description="Stores all of the core banking information about customers, accounts, transactions, etc.",
            external=True,
        )
    
        customer >> Relationship("Visits bigbank.com/ib using [HTTPS]") >> webapp
        customer >> Relationship("Views account balances, and makes payments using") >> [spa, mobileapp]
        webapp >> Relationship("Delivers to the customer's web browser") >> spa
        spa >> Relationship("Make API calls to [JSON/HTTPS]") >> api
        mobileapp >> Relationship("Make API calls to [JSON/HTTPS]") >> api
    
        api >> Relationship("reads from and writes to") >> database
        api >> Relationship("Sends email using [SMTP]") >> email
        api >> Relationship("Makes API calls to [XML/HTTPS]") >> mainframe
        customer << Relationship("Sends e-mails to") << email
  7. Render diagrams in Jupyter Notebooks

    master

    To render a diagram directly within a Jupyter notebook cell, use the as keyword to assign the Diagram instance to a variable. Returning that variable at the end of the cell will display the rendered image.

    from diagrams import Diagram
    from diagrams.aws.compute import EC2
    
    with Diagram("Simple Diagram") as diag:
        EC2("web")
    diag
  8. Represent data flow between nodes

    master

    You can represent relationships and data flow between nodes using Python shift operators.

    • >>: Connects nodes in a left-to-right direction.
    • <<: Connects nodes in a right-to-left direction.
    • -: Connects nodes with no direction (undirected).

    Note on Operator Precedence: When mixing the undirected operator - with shift operators >> or <<, use parentheses to avoid unexpected results caused by Python's operator precedence.

    Note on Rendering Order: The order of rendered diagrams is the reverse of the declaration order in your code.

    from diagrams import Diagram
    from diagrams.aws.compute import EC2
    from diagrams.aws.database import RDS
    from diagrams.aws.network import ELB
    from diagrams.aws.storage import S3
    
    with Diagram("Web Services", show=False):
        ELB("lb") >> EC2("web") >> RDS("userdb") >> S3("store")
        ELB("lb") >> EC2("web") >> RDS("userdb") << EC2("stat")
        (ELB("lb") >> EC2("web")) - EC2("web") >> RDS("userdb")
  9. Create a basic diagram with the Diagram class

    master

    The Diagram class represents the global context for a diagram. When used as a context manager (with Diagram(...)), the first argument provided to the constructor is used to generate the output filename (converted to lowercase and underscores). By default, running a script containing a Diagram block will generate an image file and attempt to open it immediately.

    from diagrams import Diagram
    from diagrams.aws.compute import EC2
    
    with Diagram("Simple Diagram"):
        EC2("web")
  10. Install diagrams

    master

    Install the diagrams package using your preferred Python package manager.

    Prerequisites:

    • Python 3.7 or higher.
    • Graphviz: diagrams requires Graphviz to render diagrams.
      • macOS (Homebrew): brew install graphviz
      • Windows (Chocolatey): choco install graphviz
      • Windows (Winget): winget install Graphviz.Graphviz -i
    # using pip (pip3)
    $ pip install diagrams
    
    # using pipenv
    $ pipenv install diagrams
    
    # using poetry
    $ poetry add diagrams
    
    # using uv
    $ uv tool install diagrams
  11. Set up local development on macOS

    master

    To develop diagrams natively on macOS, you need to install several system and language dependencies. Follow these steps from the diagrams root directory:

    1. Install Python dependencies: Use poetry to manage and install the project's Python environment.
    2. Install binary dependencies: Use brew for image processing tools and go for the round dependency.
    3. Verify the setup: Run unit tests and autogen.sh locally.

    Prerequisites:

    • Python
    • Go
    • Homebrew (brew)
    • poetry (installed via pip)
    # 1. Install poetry and project dependencies
    pip install poetry
    poetry install
    
    # 2. Install binary dependencies via brew and go
    brew install imagemagick inkscape black
    go install github.com/mingrammer/round@latest
    
    # 3. Run unit tests
    python -m unittest tests/*.py -v
    
    # 4. Run the autogen script
    ./autogen.sh
  12. Set up local development using Docker

    master

    If you prefer using Docker for a consistent development environment, follow these steps from the diagrams root directory:

    1. Build the image: Use the development Dockerfile to build the diagrams:1.0 image.
    2. Run the container: Start a background container named diagrams and mount your current directory to /usr/src/diagrams inside the container.
    3. Verify the setup: Run unit tests and the autogen.sh script inside the container to ensure everything is configured correctly.

    Requirements: Docker must be installed on your system.

    # 1. Build the docker image
    docker build --tag diagrams:1.0 -f ./docker/dev/Dockerfile .
    
    # 2. Create and run the container in the background with source code mounted
    docker run -d \
    -it \
    --name diagrams \
    --mount type=bind,source="$(pwd)",target=/usr/src/diagrams \
    diagrams:1.0
    
    # 3. Run unit tests inside the container
    docker exec diagrams python -m unittest tests/*.py -v
    
    # 4. Run the autogen script inside the container
    docker exec diagrams ./autogen.sh