😀

pre-commitでシンボリックリンク作成し、Terraformで環境ごとの構成を共通化する方法

に公開
2

Terraformを利用してインフラ構築をする際に、異なる環境間(本番環境や開発環境)で構成を同じにしたいケースがあると思います。
しかし、環境ごとにコードを個別に記述してしまうと、重複コードが発生しやすく、保守性や一貫性の面で問題になります。
そこで、shareディレクトリ配下に共通のリソースを格納して、devとprod配下に環境固有のリソースや変数を配置するという構成が有効です。
この際に、devとprod配下にshareの共通リソースのシンボリックリンクを作成し、terraformコマンドを実行する際に、ファイルを認識させる必要があります。

ディレクトリ構成

terraform/
├── dev/
│   ├── terraform.tfvars # dev 環境固有の変数
│   └── (share への symlink がここに作成される)
├── prod/
│   ├── terraform.tfvars # prod 環境固有の変数
│   └── (share への symlink がここに作成される)
└── share/
    ├── network.tf       # 共通リソース
    └── variables.tf     # 共通変数

シンボリックリンクの作成

share配下にファイルを追加、削除した際に、都度シンボリックリンクを貼り直すのは面倒なので、
Gitのpre-commitフックを利用して、コミットの際に自動的にシンボリックリンク貼り直します。

.git/hooks/pre-commit

下記を.git/hooks/pre-commitに下記のカスタムスクリプトを配置します。

# リポジトリのルートのディレクトリを定数として定義
REPO_ROOT=$(git rev-parse --show-toplevel)

# Symlinkの削除
find "$REPO_ROOT/terraform/prod" -type l -exec rm -f {} \;
find "$REPO_ROOT/terraform/dev" -type l -exec rm -f {} \;

# share配下のファイルでSymlinkを作成する
for file in $REPO_ROOT/terraform/share/*; do
	echo $file
	ln -sf "../share/$(basename "$file")" "./terraform/dev/$(basename "$file")"
	ln -sf "../share/$(basename "$file")" "./terraform/prod/$(basename "$file")"
done

# 作成されたSymlinkのステージング
git add -u $REPO_ROOT/terraform/
git add $REPO_ROOT/terraform/prod/
git add $REPO_ROOT/terraform/dev/

Discussion

rakiraki

terraform には module って便利な機能があるので。。。
Windows host なユーザもコレじゃ困るのでは?

永沢永沢

コメントありがとうございます!

今回の構成は個人用途で、ディレクトリを整理するためにシムリンクを使っていました。ただ、ご指摘の通り、Windows環境ではシムリンクの扱いが難しい場合もあり、他のユーザにとって不便になることもあると思います。

チーム開発やクロスプラットフォーム対応を考えるなら、Terraformのmodule機能を使って明示的に構成を分けたほうが良さそうですね。学習も兼ねて改善していきたいと思います!