Closed8

terraform initが面倒でbackend情報の別管理もしたくないのでMakefile化してみる

suzuki-navisuzuki-navi

Terraformで構築するプロジェクトを始めるときに terraform init を実行する必要がある。backendにS3を指定していると、バケット名などを聞かれる。または -backend-config オプションで指定しないといけない。.tfvarsのファイルに書くこともできない。環境に依存する設定情報を集約できない。

もちろん、環境に依存する情報を.tfファイルに直書きしたくもない。

そこで、 terraform.tfvars の内容とbackendの情報の両方を1つの設定ファイルにまとめて、スクリプトで強引に terraform init を自動化してみる。

ここでは、以下のようなTerraformのファイルを対象にする。

variable aws_profile {}
variable aws_region {}
variable resource_prefix {}

terraform {
  backend "s3" { }
}

provider "aws" {
   profile = var.aws_profile
   region = var.aws_region
}

resource "aws_s3_bucket" "static_website" {
  bucket = "${var.resource_prefix}-sample"
}

suzuki-navisuzuki-navi

設定ファイル config は次のように書く。

この設定ファイルから terraform.tfvars を自動作成するのと、 terraform init を自動実行させる。

aws_profile="default"
aws_region="ap-northeast-1"
resource_prefix="foo"

tf_backend_config_bucket="foo-terraform-bucket"
tf_backend_config_key="foo/terraform.tfstate"
tf_backend_config_profile="default"
tf_backend_config_region="ap-northeast-1"
suzuki-navisuzuki-navi

この設定ファイルは .tfvars の形式としてそのまま使える。したがって、terraform.tfvars を自動作成するには cp config terraform.tfvars を実行するだけでよい。

suzuki-navisuzuki-navi

terraform init を自動実行させるスクリプトは以下の通り。

# Load the configuration file and run `terraform init`.

set -Ceu
cd $(dirname $0)
. config

backend_configs=$(
  for key in $(set | sed -E -e 's/^([^=]+)=.*$/\1/g'); do
    if [[ $key =~ ^tf_backend_config_ ]]; then
      key2=$(echo $key | sed 's/tf_backend_config_//g')
      value=$(eval echo \$${key})
      echo -n " -backend-config=${key2}=${value}"
    fi
  done
)

terraform_init_command="terraform init ${backend_configs}"
echo $terraform_init_command
$terraform_init_command

設定ファイル config は .tfvars の形式だけではなく、シェルスクリプトからもそのまま読める形式になっているので、シェルスクリプトから実行して設定値をシェル変数として取り込んでいる。

シェル変数の名前が tf_backend_config_ で始まる変数を -backend-config で渡すようにしている。

この中で前回の以下の記事のワンライナーを使っている。

https://zenn.dev/suzuki_navi/scraps/33633ef72e1a20

suzuki-navisuzuki-navi

必要なソースファイルは以下の5つ。

  • main.tf
  • terraform-init.sh
  • config
  • Makefile
  • .gitignore

上3つはすでにご紹介した。

Makefile は以下の通り。

build: aws-deployed

aws-deployed: .terraform terraform.tfvars
	terraform apply
	touch aws-deployed

.terraform: main.tf terraform-init.sh config
	bash ./terraform-init.sh

terraform.tfvars: config
	cp config terraform.tfvars

.gitignore に書くべき内容は以下の通り。

/aws-deployed
/.terraform
/*.tfvars
/config
suzuki-navisuzuki-navi

この内容で make を実行するだけで、 terraform initterraform apply を実行してくれる。

suzuki-navisuzuki-navi

ここまででやりたいことはできたけど、以下のような警告が出てしまう。

│ Warning: Value for undeclared variable
│
│ The root module does not declare a variable named "tf_backend_config_profile" but a value was found in file "terraform.tfvars". If you meant to use this value, add a "variable" block to the configuration.
│
│ To silence these warnings, use TF_VAR_... environment variables to provide certain "global" settings to all configurations in your organization. To reduce the verbosity of these warnings, use the -compact-warnings option.
╵

terraform init のときにしか利用せず、 main.tf からは参照されていない変数が terraform.tfvars に存在するのが原因。

suzuki-navisuzuki-navi

非常に場当たり的だが、 terraform.tfvars を生成するときに除外することにした。新しい Makefile は以下の通り。

build: aws-deployed

aws-deployed: .terraform terraform.tfvars
	terraform apply
	touch aws-deployed

.terraform: main.tf terraform-init.sh config
	bash ./terraform-init.sh

terraform.tfvars: config
	cat config | grep -v '^tf_backend_config_' > terraform.tfvars
このスクラップは2023/07/08にクローズされました