🎨

NW図 as Code(6) drawthe.netを試す

2022/06/16に公開

drawthe.net

drawthe.netはこちらで公開されているツールです。

https://github.com/cidrblock/drawthe.net

ネットワーク図を描くことにフォーカスして作られているみたいです。
ここのSpine-Leaf構成とか、ここのNTPトポロジとか見た目がすごく綺麗です。

結果

作成した物理ネットワーク構成図を示します。

図の元になったコードはこちらです。drawthe.netのインプットデータはYAMLです。

diagram:
  fill: "white"
  gridLines: false
  rows: 4
  columns: 4
title:
  color: black
  text: on-premises datacenter example
  subText: ""
  version: 0.1
  author: takai404
  logoUrl: null
# Set defaults for icons, groups, connections
iconDefaults: &iconDefaults
  color: black
  fill: "none"
  stroke: "none"
connectionDefaults: &connectionDefaults
  color: "red"
  stroke: "orange"
  strokeWidth: 3
icons:
  router0:
    <<: *iconDefaults
    iconFamily: cisco
    icon: router
    x: 1
    y: 3
  router1:
    <<: *iconDefaults
    iconFamily: cisco
    icon: router
    x: "+1"
  l3sw0:
    <<: *iconDefaults
    iconFamily: cisco
    icon: layer3switch
    x: "-1"
    y: "-1"
  firewall0:
    <<: *iconDefaults
    iconFamily: cisco
    icon: firewall
    x: "-1"
  lb0:
    <<: *iconDefaults
    iconFamily: cisco
    icon: localdirector
    y: "-1"
  l3sw1:
    <<: *iconDefaults
    iconFamily: cisco
    icon: layer3switch
    x: "+2"
    y: "+1"
  firewall1:
    <<: *iconDefaults
    iconFamily: cisco
    icon: firewall
    x: "+1"
  lb1:
    <<: *iconDefaults
    iconFamily: cisco
    icon: localdirector
    y: "-1"
  l2sw0:
    <<: *iconDefaults
    iconFamily: cisco
    icon: workgroupswitch
    x: "-2"
  l2sw1:
    <<: *iconDefaults
    iconFamily: cisco
    icon: workgroupswitch
    x: "+1"
  host1:
    <<: *iconDefaults
    iconFamily: cisco
    icon: fileserver
    x: "-1"
    y: "-1"
  host2:
    <<: *iconDefaults
    iconFamily: cisco
    icon: fileserver
    x: "+1"

connections:
  - { <<: *connectionDefaults, endpoints: ["router0:e0", "router1:e0"] }
  - { <<: *connectionDefaults, endpoints: ["router0:e2", "l3sw0:e2"] }
  - { <<: *connectionDefaults, endpoints: ["router1:e2", "l3sw1:e2"] }
  - { <<: *connectionDefaults, endpoints: ["l3sw0:e0,e1", "l3sw1:e0,e1"], strokeWidth: 8 }
  - { <<: *connectionDefaults, endpoints: ["l3sw0:e3", "firewall0:e0"] }
  - { <<: *connectionDefaults, endpoints: ["l3sw1:e3", "firewall1:e0"] }
  - { <<: *connectionDefaults, endpoints: ["l3sw0:e4", "lb0:e0"] }
  - { <<: *connectionDefaults, endpoints: ["l3sw1:e4", "lb1:e0"] }
  - { <<: *connectionDefaults, endpoints: ["l2sw0:e0,e1", "l2sw1:e0,e1"], strokeWidth: 8 }
  - { <<: *connectionDefaults, endpoints: ["l3sw0:e5", "l2sw0:e2"] }
  - { <<: *connectionDefaults, endpoints: ["l3sw1:e5", "l2sw1:e2"] }
  - { <<: *connectionDefaults, endpoints: ["l2sw0:e3", "host1:eth0"] }
  - { <<: *connectionDefaults, endpoints: ["l2sw0:e4", "host2:eth0"] }
  - { <<: *connectionDefaults, endpoints: ["l2sw1:e3", "host1:eth1"] }
  - { <<: *connectionDefaults, endpoints: ["l2sw1:e4", "host2:eth1"] }

利用方法

公開されているファイル群をgit cloneすると使えるようになるみたいなのですが、オンラインで編集できるサイトが提供されているのでこちらを利用させてもらいましょう。

http://go.drawthe.net/

drawthe.netの描き方

drawthe.netはPlauntUMLGraphvizとは違って、以下の特徴があります。

  • アイコンを置いて、アイコン間に線を引く
  • アイコンの配置場所はX座標、Y座標で自分で指定する

アイコンの配置

http://go.drawthe.net/ の右上のiconsボタンを押すと、利用できるアイコンの一覧が見れます。

Ciscoアイコンはこんな感じです。

左ペインの文字列を全部消して、以下を入力してCtrl+Enterを押します。

icons:
  router0:
    color: black
    fill: "none"
    stroke: "none"
    iconFamily: cisco
    icon: router
    x: 1
    y: 3

右ペインが以下のように変わります。

  • 描画エリアはデフォルトでは10マス × 10マスのオレンジ背景です。
  • この描画エリアにciscoのrouterアイコンを座標(X, Y) = (1, 3)に置きます。
  • アイコンには"router0"というラベルを付けます。色はblack。
  • アイコンの周りの枠なし(stroke: "none")、色塗りなし(fill: "none")

アイコンの座標指定

アイコンをもう一個追加します。以下の通り書き足してCtrl+Enterです。

icons:
  router0:
    color: black
    fill: "none"
    stroke: "none"
    iconFamily: cisco
    icon: router
    x: 1
    y: 3
  router1:
    color: black
    fill: "none"
    stroke: "none"
    iconFamily: cisco
    icon: router
    x: "+1"

router0の右にrouter1が追加されているはずです。
router1のX座標は「x: "+1"」としました。これは「さっきのアイコンのX座標に1を加算しろ」という意味です。
router1のY座標は指定していません。これは「さっきのアイコンのY座標と同じ」という意味です。

「x: "+1"」の部分を「x: +1」とすると期待通りの動きをしません。おそらくYAMLパーサがxを整数と判断して「x: 1」と同じ意味(相対座標ではなくて絶対座標)と解釈しているのでしょう。

drawthe.netのオンラインエディタを使う上での注意点は文法エラーがあったときにエラーメッセージが出ないことです。右ペインの図も変化しないので、エラーが起きているのか自分の書き足したコードでは図に変化がないのかが分からないです。
とりあえずちょっとコードを編集したら即座にCtrl+Enterを押しまくって図に反映されるか確認しましょう。

drawthe.netの問題ではないのですが、YAMLはスペース文字が1個多かったり少なかったりするだけで文法エラーになります。

なんかおかしいなと思ったらYAMLの文法チェッカーにかけてみましょう。
http://yaml-online-parser.appspot.com/

YAMLの短縮

このままほかのアイコンを追加していってもいいのですが、colorとかiconFamilyとか同じことをコピペとは言えども何度も書くと面倒くさいし、行が増えて見づらいですよね。

YAMLにはアンカーとエイリアスという仕様があり、繰り返し要素にアンカーで名前を付けて、後からエイリアスで参照することができます。

icons:
  router0:
    color: black
    fill: "none"
    stroke: "none"
    iconFamily: cisco
    icon: router
    x: 1
    y: 3
  router1:
    color: black
    fill: "none"
    stroke: "none"
    iconFamily: cisco
    icon: router
    x: "+1"

上記のYAMLと下記のYAMLは同じ意味です。

iconDefaults: &iconDefaults
  color: black
  fill: "none"
  stroke: "none"
icons:
  router0:
    <<: *iconDefaults
    iconFamily: cisco
    icon: router
    x: 1
    y: 3
  router1:
    <<: *iconDefaults
    iconFamily: cisco
    icon: router
    x: "+1"

color, fill, strokeというキーを持つ「iconDefaults」という名前のマップを定義しています。
「&iconDefaults」でこのマップに「iconDefaults」という名前のアンカーを付けています。

router0, router1では「<<」でマップをマージしています。マージ対象のマップは「*iconDefaults」です。「*iconDefaults」はエイリアス参照で、「iconDefaults」という名前のアンカーを参照する、という意味です。

慣れてくると同じ「iconDefaults」という名前を付けた方が分かりやすいのですが、名前は何でもいいです。以下の書き方の方が理解しやすいかもしれないです。TEKITO_NA_NAMAE(適当な名前)は誰にも使われない名前なので何でもいいです。&KURIKAESHIで繰り返し箇所を定義、*KURIKAESHIでそれを参照です。

TEKITO_NA_NAMAE: &KURIKAESHI
  color: black
  fill: "none"
  stroke: "none"
icons:
  router0:
    <<: *KURIKAESHI
    iconFamily: cisco
    icon: router
    x: 1
    y: 3
  router1:
    <<: *KURIKAESHI
    iconFamily: cisco
    icon: router
    x: "+1"

背景、タイトルの指定

背景がオレンジだと目がチカチカするので、白にします。今回の図は10マスも要らないので4 × 4にしました。
あと、図を描く上で本質的ではないのですが、title(のtext)を定義しないと、オンラインエディタで画像のダウンロードができないので、titleも決めてあげます。

l3sw0アイコンも配置しました。router1の座標と比べてX座標が"-1"(1マス左)、Y座標が"-1"(1マス下)です。

diagram:
  fill: "white"
  rows: 4
  columns: 4
title:
  color: black
  text: on-premises datacenter example
  subText: ""
  version: 0.1
  author: takai404
  logoUrl: null
iconDefaults: &iconDefaults
  color: black
  fill: "none"
  stroke: "none"
icons:
  router0:
    <<: *iconDefaults
    iconFamily: cisco
    icon: router
    x: 1
    y: 3
  router1:
    <<: *iconDefaults
    iconFamily: cisco
    icon: router
    x: "+1"
  l3sw0:
    <<: *iconDefaults
    iconFamily: cisco
    icon: layer3switch
    x: "-1"
    y: "-1"

ケーブル

以下を追加します。

connectionDefaults: &connectionDefaults
  color: "red"
  stroke: "orange"
  strokeWidth: 3
connections:
  - { <<: *connectionDefaults, endpoints: ["router0:e0", "router1:e0"] }
  - { <<: *connectionDefaults, endpoints: ["router0:e2", "l3sw0:e2"] }

「endpoints: ["router0", "router1"]」でrouter0とrouter1の間にケーブルを引くことができます。
「endpoints: ["router0:e0", "router1:e0"]」とすることで、このケーブルの両端に「e0」、「e0」というラベルを付けることができます。

{}と[]はマップとシーケンスを1行で書くYAMLの記法です。以下と同じ意味です。

connections:
  -
   <<: *connectionDefaults
   endpoints:
   - "router0:e0"
   - "router1:e0"
  -
   <<: *connectionDefaults
   endpoints:
   - "router0:e2"
   - "l3sw0:e2"

このままアイコンとケーブルを追加していくと冒頭の「結果」で示したコードとネットワーク図が出来上がります。

制限

アイコン間にケーブルを2本引くことはできないようです。EtherChannelをうまく表現できないですね。
ケーブルを太くしてラベルに["l3sw0:e0,e1", "l3sw1:e0,e1"]と書くことでそれっぽく表現しています。

関連記事

Discussion