この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
お疲れ様です。小島です。
terraform のリソースは増えていくにつれ、関係性について把握が難しくなるのではないでしょうか。
その時、依存関係を dot 言語で出力してくれる terraform graph
があります。
しかし、多くのリソースが含まれる図には多くの関係を示す線が含まれており、把握するには一苦労です。
terraform graph
には module-depth
という深さを指定し、出力を絞り込むことができるオプションがあります。
ですが、スモールスタートでの開発で徐々にリソースが増えていくような場合だと、 module のリファクタリングは state も考慮する必要があるので後回しになりがちです。
なので、正規表現に該当するリソースだけ吐き出すようなスクリプトを go で書きました。
スクリプト
スクリプトの使い方
# Glue に関するリソースを絞り込む
terraform graph | go run . -expr "aws_glue_" | dot -Tsvg > graph_sample1.svg
# Tempura に関するリソースを絞り込んだ後、再度 S3 に紐づくリソースを絞り込む
terraform graph | go run . -expr "tempura" | go run . -expr "aws_s3_" | dot -Tsvg > graph_sample2.svg
実行結果
絞り込む前のグラフです。
Glue に関するリソースを絞り込んだ結果です。
はい、ジョブの数は 1 つ、クローラーと S3 バケットが 1-1 になっている構成です。あっています。
Tempura と S3 に紐づくリソースを絞り込んだ結果です。
pheasant_tempura_okonomiyaki
のバケットだけ aws リソースに紐づいていません。
アプリケーションでのみ使っているようです。なるほど。。。
確認した環境
# uname -a
Darwin HL00566.local 19.3.0 Darwin Kernel Version 19.3.0: Thu Jan 9 20:58:23 PST 2020; root:xnu-6153.81.5~1/RELEASE_X86_64 x86_64
# terraform version
Terraform v0.12.6
# go version
go version go1.14 darwin/amd64
# dot -V
dot - graphviz version 2.42.3 (20191010.1750)
スクリプトの解説
dot 言語の解析と出力には https://gonum.org のライブラリを使用しました。
数値計算用ライブラリ、とのことですが、グラフ言語に関するコードも入っていました。
- https://github.com/gonum/gonum/tree/v0.7.0/graph/encoding
- https://github.com/gonum/gonum/tree/v0.7.0/graph/formats
package main
import (
// ...
"gonum.org/v1/gonum/graph/formats/dot"
"gonum.org/v1/gonum/graph/formats/dot/ast"
)
dot.Parse
をすることで AST に解析してくれます。
dast, err := dot.Parse(os.Stdin)
AST を再構築しても良いですが、今回は各要素を直接書き換えることで対応しました。
case *ast.Subgraph:
// ...
xs := xt.Stmts
xsSize := len(xs)
delCnt := 0
for i := 0; i < xsSize; i++ {
xtx := xs[i-delCnt]
err := walk(xtx, f)
// ...
}
xt.Stmts = xs
// ...
type visitor struct {
*regexp.Regexp
}
func (v *visitor) Visit(x ast.Stmt) error {
switch xt := x.(type) {
case *ast.NodeStmt:
if v.MatchString(xt.Node.ID) {
xt.Attrs = append(xt.Attrs, &ast.Attr{Key: "color", Val: "red"})
return nil
}
// ...
}
}
ast.Graph
の String()
で dot 言語形式で出力されます。
for _, g := range dast.Graphs {
err := walk(g, v.Visit)
if err != nil {
log.Fatal(err)
return
}
fmt.Println(g)
}
感想
現状は理解するための可視化が目的だったので、この機能で満足しています。 次のアプローチとして node にアイコンを載せたり、依存関係を辿れるようにしたら楽しそうですね。