松田です!
寒すぎる!
ダウンはじめました!
今日はTerraformネタです!
Terraformerなら何千/何万回と実行するterraform plan/applyですが、ファイル単位で実行したいというケースはありませんか?
terraform plan/applyにtargetオプションがあるので、リソース単位で実行することは可能です。ただファイル単位で実行するオプションは用意されていません。
快適なterraform生活を送るためのTipsとして、terraform plan/applyをファイル単位で(スマートに)実行する方法について紹介します。
結論から知りたい人は「結論」から読んでください。
んで、どうやるの?
terraform plan/applyにはファイル単位で対象を指定するオプションがありません。対象を指定するにはtargetオプションでリソースやモジュールを指定するしかありません。
なので、対象のファイル内に定義されているリソースやモジュールを取得して、それをtargetオプションの引数に渡してあげる
と実現できそうです。
リソースとモジュールをフィルタリング
cat sample.tf | grep -E 'resource |module '
このコマンドを実行すると、以下のように指定したファイル内のリソースとモジュールだけを取得できます。
resource "aws_vpc" "sample" { resource "aws_subnet" "sample" { resource "aws_route_table" "sample_public" { resource "aws_route_table" "sample_protected" { resource "aws_route_table" "sample_private" {
apply/planコマンドに渡せる形に整形
targetオプションの引数は1つのリソース/モジュールを指定することができます。複数のリソース/モジュールを指定する場合は-target "aws_vpc.sample -target "aws_subnet.sample"
といった感じでtargetオプションを必要な数呼び出します。またtargetオプションの引数となるリソースとモジュールはダブルクォーテーションで囲う必要があります。
ではgrepの実行結果をtargetオプションに渡せる形に直します。
まずtr -d '"'
でダブルクォーテーションを取りのぞきます。
cat sample.tf | grep -E 'resource |module ' | tr -d '"'
すると
resource aws_vpc sample { resource aws_subnet sample { resource aws_route_table sample_public { resource aws_route_table sample_protected { resource aws_route_table sample_private {
となります。
さらにawk '{printf("-target=%s.%s ",$2,$3);}'
でフォーマットすると
cat sample.tf | grep -E 'resource |module ' | tr -d '"' | awk '{printf("-target=%s.%s ",$2,$3);}'
以下のようにapply/planコマンドに渡せる形になります。
-target=aws_vpc.sample -target=aws_subnet.sample -target=aws_route_table.sample_public -target=aws_route_table.sample_protected -target=aws_route_table.sample_private
apply/planコマンドに渡す
cat sample.tf | grep -E 'resource |module ' | tr -d '"' | awk '{printf("-target=%s.%s ",$2,$3);}'
上記コマンドの結果をterraform apply/planに渡せば良いので、
terraform plan $(cat sample.tf | grep -E 'resource |module ' | tr -d '"' | awk '{printf("-target=%s.%s ",$2,$3);}')
これでファイルを指定でterraform plan/applyを実行することができます。
結論
以下コマンドでterraform plan/applyをファイル単位で実行することができます。
# plan terraform plan $(cat sample.tf | grep -E 'resource |module ' | tr -d '"' | awk '{printf("-target=%s.%s ",$2,$3);}') # apply terraform apply $(cat sample.tf | grep -E 'resource |module ' | tr -d '"' | awk '{printf("-target=%s.%s ",$2,$3);}')
スマートに
上のコマンドをターミナルにコピペして、ファイル名だけ変更して….とやるのはダサい面倒なので、スマートに実行できるようにします。
以下を.zshrcなり.bashrcなりに登録してください。
# Terraform Plan per File function tpf() { if [ $# -eq 0 ]; then echo "terraform plan per file" echo "Usage: tpf <filename.tf>" return 1 fi terraform plan $(cat $1 | grep -E 'resource |module ' | tr -d '"' | awk '{printf("-target=%s.%s ",$2,$3);}') } # Terraform Apply per File function taf() { if [ $# -eq 0 ]; then echo "terraform apply per file" echo "Usage: taf <filename.tf>" return 1 fi terraform apply $(cat $1 | grep -E 'resource |module ' | tr -d '"' | awk '{printf("-target=%s.%s ",$2,$3);}') }
これで
# plan tpf sample.tf # apply taf sample.tf
といったようにスマートに実行することができます。
最後に
結局のところシェル芸でゴリ押しですが、関数化でそれを隠してスマートにファイル単位でterraform plan/applyを実行しましょう!
以上です!