dmytrostriletskyi / diagrams-as-code

Diagrams as code: declarative configurations using YAML for drawing cloud system architectures.
https://pypi.org/project/diagrams-as-code/
MIT License
317 stars 16 forks source link
architecture diagrams diagrams-as-code graphviz python system-design yaml

Diagrams as code: declarative configurations using YAML for drawing cloud system architectures.

Table of content:

Introduction

Diagrams as code is essentially the process of managing diagrams through code rather than interactively drawing them on specific web services such as draw.io. It lets you generate the cloud system architecture in a declarative way with widely used YAML syntax (which is de facto a standard for infrastructure and configurations).

Declarative method of describing things means that a user simply describes the solution they need, how it should look, and everything that would be in the state of the final solution, leaving the process for the software to decide.

Diagrams as code brings you the following benefits compared to drawing architecture on your own, it:

Currently, the following components are provided:

Roadmap

Getting Started

How to install

As the project uses Graphviz to render the diagram, you need to install it:

After, you can install the project itself with the following command using pip3:

$ pip3 install diagrams-as-code

Examples

You can find examples of YAML configurations in the examples folder. Below are placed are few of them (click on the name to redirect to the configurations file).

Web Services on AWS Web Services On-Premise Exposed Pods on Kubernetes
Message Collecting on GCP Events Processing on AWS Workers on AWS

Syntax Highlighting

When you will be writing your own YAML files, you likely need a syntax highlighting. Currently, there is no mapping of the YAML files to a specific schema to enable the syntax highlighting automatically. So, there is a need for manual operation here.

PyCharm

For PyCharm, open the settings and proceed to Languages & Frameworks, then toScheams and DTDs, then to JSON Schema Mappings. After, create a new schema, name itDiagrams as code, choose JSON Schema version 7, pastehttps://raw.githubusercontent.com/dmytrostriletskyi/diagrams-as-code/main/json-schemas/0.0.1.json to theSchema file or URLfield and clickApply`:

Open Illustration ![](./assets/json-schema-settings.png)

Right after then, open a YAML file and click on No JSON schema at to bottom-right corner:

Open Illustration ![](./assets/down-panel-json-schema.png)

It will open a panel where you can choose the newly created schema with the name Diagrams as code:

Open Illustration ![](./assets/panel-json-schema.png)

As a result, you will experience syntax highlighting when typing:

Open Illustration ![](./assets/syntax-highlight.png)

VS Code

For VS Code, install the RedHat YAML extension and include the following line in the top of your diagrams yaml file:

# yaml-language-server: $schema=https://raw.githubusercontent.com/dmytrostriletskyi/diagrams-as-code/main/json-schemas/0.0.1.json

Usage

Command Line Interface

To draw an architecture, call diagrams-as-code command line interface, providing a path to a YAML file with configurations. The drawing will be saved in the folder the command line interface was executed from.

$ diagrams-as-code examples/web-services-aws.yaml

Guide

Please, check all-fields.yaml as the example to see all possible configurations before diving into a detailed explanation about them (and this is the result image).

A YAML file conceptually contains two configurations: generic information such as a name of a diagram, a format of an image to be generated, style and resources themselves such as AWS and Kubernetes resources, Nginx, ElasticSearch and all other things you actually want to draw, and relationships among them.

diagram:
  name: Web Services Architecture on AWS
  file_name: web-services-architecture-aws
  format: jpg
  direction: left-to-right
  style:
    graph:
      splines: ortho
    node:
      shape: circle
    edge:
      color: '#000000'
  label_resources: false
  open: true
  resource:
    ...

Generic information schema looks like this:

Field Type Required Restrictions Default Description
name String Yes - PNG A name of the diagram which is shown in the image.
file_name String No - - A file name of the image that would be created.
format String No png, jpg, svg, pdf, dot png A format of the image that would be created.
direction String No left-to-right, right-to-left, top-to-bottom, bottom-to-top left-to-right A direction of the diagram's resource.
style Object No - - Style of the diagram.
label_resources Boolean No - false Whether to label the diagram's resources such as EC2 or PodConfig.
open Boolean No - false Whether to open the diagram's image after creating it.
resources List Yes - - Resources of the diagram.

style is responsible for styling overall diagram such as a background color or choosing between curvy or straight arrows. It should go as a nested object of parameters as key/value of Graphviz's attributes.

Its schema looks like:

Field Type Required Restrictions Default Description
graph Object No Those parameters as key/value. - A graph styling.
node Object No Those parameters as key/value. - A node styling
edge Object No Those parameters as key/value. - An edge styling.

resources is responsible for specifying a list of resources on a diagram and relationships among them. Each resource has a unique identifier, name and type. Name will be shown on a diagram under the specific resource:

diagram:
  resources:
    - id: elb
      name: ELB
      type: aws.network.ELB
Open Illustration ![](./assets/guide-resource.png)

Identifier will be used by other resources to set a relationship direction's type among them:

diagram:
  resources:
    - id: dns
      name: DNS
      type: aws.network.Route53
      relates:
        - to: elb
          direction: outgoing
    - id: elb
      name: ELB
      type: aws.network.ELB
Open Illustration ![](./assets/guide-resource-relationship.png)

There is also a type named group. It is not a specific resource, it is rather a group of resources. It is needed for other resources to be able to have a relationship with all group's resources at once. Each group's resource can have separate relationships as well:

diagram:
  resources:
    - id: elb
      name: ELB
      type: aws.network.ELB
      relates:
        - to: graphql-api
          direction: outgoing
    - id: graphql-api
      name: GraphQL API
      type: group
      of:
        - id: first-api
          name: GraphQL API №1
          type: aws.compute.ECS
        - id: second-api
          name: GraphQL API №2
          type: aws.compute.ECS
        - id: third-api
          name: GraphQL API №3
          type: aws.compute.ECS
Open Illustration ![](./assets/guide-group.png)

There is also a type named cluster. It is needed to separate multiple resources or groups logically: for instance, there might be a cluster of different APIs composed as groups, a cluster of databases and a cluster of caches.

Pay attention that to refer a cluster resource, there are the following identifiers web-services.graphql-api and web-services.rest-api what means that you need to chain identifiers of nested resources through a dot to identify a resource you build a relationship with.

diagram:
  resources:
    - id: elb
      name: ELB
      type: aws.network.ELB
      relates:
        - to: web-services.graphql-api
          direction: outgoing
        - to: web-services.rest-api
          direction: outgoing
    - id: web-services
      name: Web Services
      type: cluster
      of:
        - id: graphql-api
          name: GraphQL API
          type: group
          of:
            - id: first-api
              name: GraphQL API №1
              type: aws.compute.ECS
            - id: second-api
              name: GraphQL API №2
              type: aws.compute.ECS
            - id: third-api
              name: GraphQL API №3
              type: aws.compute.ECS
        - id: rest-api
          name: REST API
          type: group
          of:
            - id: first-api
              name: REST API №1
              type: aws.compute.EC2
            - id: second-api
              name: REST API №2
              type: aws.compute.EC2
            - id: third-api
              name: REST API №3
              type: aws.compute.EC2
    - id: databases
      name: Databases
      type: cluster
      of:
        - id: leader
          name: Leader
          type: aws.database.RDS
          relates:
            - to: databases.follower
              direction: undirected
        - id: follower
          name: Follower
          type: aws.database.RDS
Open Illustration ![](./assets/guide-cluster.png)

Basically, to recap and also clarify:

resources schema looks like this:

Field Type Required Restrictions Default Description
id String Yes - - A unique identifier of the resource.
name String Yes - - A name of the resource.
type String Yes One of the those. - A type of the resource.
relates Object No - - A relationship to a resource or a group.

This is the table of all available types by a category:

Name Docs
Alibaba Cloud alibaba_cloud.md
AWS aws.md
Azure azure.md
DigitalOcean digital_ocean.md
Elastic elastic.md
Firebase firebase.md
Flowchart flowchart.md
GCP gcp.md
Generic generic.md
IBM ibm.md
Kubernetes kubernetes.md
OCI oci.md
On-Premise on_premise.md
OpenStack open_stack.md
Outscale outscale.md
Programming programming.md
SaaS saas.md

relates schema looks like:

Field Type Required Restrictions Default Description
to String Yes - - A chain of identifiers to a resource via a dot from root.
direction String Yes incoming, outgoing, bidirectional, undirected - A direction of a relationship.
label String No - - A label of a relationship.
color String No Hexadecimal color with the # symbol. #2D3436 A color of a relationship.
style String No - - A style of a relationship.

Disclaimer

diagrams-as-code is a wrapper around the original diagrams. The original diagrams lets you draw the cloud system architecture in Python code. It was born for prototyping a new system architecture design without any design tools. Under the hood, diagrams-as-code parse a YAML file and map to a specific set of diagrams's functions and classes, and execute them in proper order.

But you don't have to worry about diagrams because diagrams-as-code is self-contained and encapsulates it well.