• terrarorm init で バケットがなければ作成する
  • バケット名は ${project_id}-${app}-tfstate とする
  • project_id, app は Makefile で指定

terraform コマンドをラップした Makefile

app := sample
project_id := project-a

export

init_tfstate_gs:
	@init_gs_tfstate_if_needed

init: init_tfstate_gs
	@echo "==> Initializing terraform..."
	@make _tf cmd=init
init_if_needed:
	@if [[ ! -e envs/$(stage)/.terraform ]]; then \
		make init; \
	fi

login:
	@make _tf cmd=login
init_upgrade:
	@make _tf cmd=init opt="-upgrade=true"
init_migrate_state:
	@make _tf cmd=init opt="-migrate-state"
plan: init_if_needed
	@make _tf cmd=plan
apply: init_if_needed
	@make _tf cmd=apply
apply-auto-approve:
	@make _tf cmd=apply opt=-auto-approve
apply-refresh:
	@make _tf cmd=apply opt=-refresh-only
destroy:
	@make _tf cmd=destroy
refresh:
	@make _tf cmd=refresh
show:
	@make _tf cmd=show
output:
	@make _tf cmd=output opt=-json
console:
	@make _tf cmd=console
validate:
	@make _tf cmd=validate

_check_env:
	@test -e envs/$(stage) || (echo 'No such stage:envs/$(stage) exist.' && exit 1)
_tf: _check_env
	@cd envs/$(stage) && \
		terraform $(tf_opt) $(cmd) $(opt)

バケット作成スクリプト

  • init_gs_tfstate_if_needed
#!/usr/bin/env -S bash -e

app=${app:-""} && readonly app
region=${region:-"us-central1"} && readonly region

main() {
  if [[ -z ${app} ]]; then
    echo "==> app is required."
    exit 1
  fi
  local project_id bucket_tfstate

  project_id=$(gcloud config get-value project)
  if [[ -z ${project_id} ]]; then
    echo "==> project_id is required."
    exit 1
  fi
  bucket_tfstate="${project_id}-${app}-tfstate"

  if gsutil ls | grep "gs://${bucket_tfstate}" &>/dev/null; then
    echo "==> Already tfstate ${bucket_tfstate} exist."
    return
  fi
  echo "==> Creating tfstate ${bucket_tfstate}..."
  gsutil mb -l "${region}" "gs://${bucket_tfstate}"
  gsutil versioning set on "gs://${bucket_tfstate}"
  echo "==> Bucket created!"
}
main "$@"

terraform backend を GCS backet に設定する

terraform {
  backend "gcs" {
    bucket = "project-a-sample-tfstate"
    prefix = "terraform/state"
  }
}