Diagram as Code(Diagrams)を試す
普段、構成図はCacooなどのオーサリングツールを利用していますが、
Pythonコードで構成図を描画できるというツールを使ってどこまで書けるか試してみました。
結論、所感
- シンプルに書けるので謳われてる通り、新しいシステムのプロトタイプ化が素早くできるのがよい
- 学習コストも低く、Pythonに慣れてさえいればすぐ書き始められる
- フォントサイズの変更属性はあったが、注釈とか書く方法がわからなかった
環境について
- macOS Catalina
- Python 3.6.8
動作要件
- Python 3.6 以上
- Graphviz が必要
事前準備
新しく仮想環境を作りその中にパッケージをインストールしていきます。
この手順は任意です。
python -m venv ~/envs/diagrams
source ~/envs/diagrams/bin/activate
Installation
# Homebrewでインストール
brew install graphviz
# pipでインストール
pip install diagrams
例題
とりあえず例題を使って出力してみました。
from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB
with Diagram("Web Service", show=False):
ELB("lb") >> EC2("web") >> RDS("db")
python diagram.py
2020-05-29 13:50:05.901 +[__NSCFConstantString length]: unrecognized selector sent to class 0x
2020-05-29 13:50:05.905 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[__NSCFConstantString length]: unrecognized selector sent to class 0x'
早速、エラーに遭遇しました。
まったく原因がわからず、issueなど漁りながらとりあえず元々インストール済みだったgraphvizをアップグレードすることにしました。
brew upgrade graphviz
バージョンを 2.40.1 -> 2.44.0 にアップグレードできました。
python diagram.py
無事出力できました。
お試し構成
from diagrams import Cluster, Diagram
from diagrams.aws.compute import EC2, ElasticBeanstalk
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB, Route53
from diagrams.onprem.client import Client
graph_attr = {
}
def draw():
with Diagram("web_service", show=False, graph_attr=graph_attr, direction="TB"):
route53 = Route53('route53')
client = Client('client')
client >> route53
with Cluster("ElasticBeanstalk"):
with Cluster("WEB"):
with Cluster("Subnet1"):
web1 = EC2("web")
lb1 = ELB("lb1")
lb1 >> web1
with Cluster("Subnet2"):
web2 = EC2("web")
lb2 = ELB("lb2")
lb2 >> web2
route53 - [lb1, lb2]
with Cluster("DB"):
db_master = RDS("master")
with Cluster("Subnet3"):
rds1 = RDS("slave1")
with Cluster("Subnet4"):
rds2 = RDS("slave2")
db_master - [rds1, rds2]
[web1, web2] >> db_master
if __name__ == '__main__':
draw()