使用git的pre-commit来自动化terraform格式检查
首先
在使用Terraform进行基础设施运维时,由于安全策略等原因,可能会存在无法从本地(编码环境)执行Terraform的情况,因为无法将凭据信息存储在本地。
在这种情况下,只有将格式错误或变量引用错误等问题部署到Terraform执行环境中才能知道,这是非常低效的。即使通过管道等自动化部署了部署,在等待管道执行期间也是浪费时间,并且由于拼写错误等愚蠢的错误而弄脏提交历史记录是不好的。
因此,我尝试利用git的pre-commit功能,在提交之前自动执行terraform fmt/init/validate。这样,只有命令成功才会进行提交,若失败则不会提交并输出错误内容。
如果有任何问题使得它无法正常运行,请留下评论。
执行示例
胜利的案例
$ git commit -m "test"
Directory: terraform/ terraform fmt: Passed
Directory: terraform/ terraform init: Passed
Directory: terraform/ terraform validate: Passed
Directory: terraform/environment/iam/ terraform fmt: Passed
Directory: terraform/environment/iam/ terraform init: Passed
Directory: terraform/environment/iam/ terraform validate: Passed
Directory: terraform/environment/lambda/ terraform fmt: Passed
Directory: terraform/environment/lambda/ terraform init: Passed
Directory: terraform/environment/lambda/ terraform validate: Passed
[master 9b47d9e] test
8 files changed, 77 insertions(+), 14 deletions(-)
create mode 100644 terraform/environment/iam/dev.tfvars
create mode 100644 terraform/environment/iam/prd.tfvars
create mode 100644 terraform/environment/iam/variables.tf
create mode 100644 terraform/environment/lambda/variables.tf
失败案例
$ git commit -m "test"
Directory: terraform/ terraform fmt: Passed
Directory: terraform/ terraform init: Passed
Directory: terraform/ terraform validate: Passed
Directory: terraform/environment/iam/ terraform fmt: Passed
Directory: terraform/environment/iam/ terraform init: Passed
Directory: terraform/environment/iam/ terraform validate: Passed
Directory: terraform/environment/lambda/ terraform fmt: Passed
Directory: terraform/environment/lambda/ terraform init: Passed
Error: Missing required argument
on main.tf line 16, in module "get_lambda":
16: module "get_lambda" {
The argument "memory_size" is required, but no definition was found.
Error: Unsupported argument
on main.tf line 23, in module "get_lambda":
23: memory_sze = 256
An argument named "memory_sze" is not expected here. Did you mean
"memory_size"?
Directory: terraform/environment/lambda/ terraform validate: Failed
执行环境
-
- WSL (Ubuntu 18.04)
-
- git version 2.17.1
- Terraform v0.12.19
从准备到执行
准备1. 安装terraform。
根据您当前使用的版本安装与之相应的Terraform(如果已经安装了则不需要)。
在准备阶段, 添加.terraform/到.gitignore文件中。
因为我们将在本地进行terraform init操作,因此插件和模块将被安装在.terraform/目录下。由于这些不需要进行版本控制,所以需要在.gitignore文件中添加以下内容。(如果已经存在,则不需要添加)
.terraform/
准备3. 放置pre-commit文件。
请将以下内容以文件名.pre-commit的形式放置在.git/hooks中。
#!/bin/bash -u
work_dir=`pwd`
# 戻り値チェック
check_return_code() {
cmd_name="$1"
dir_name="$2"
rc=$3
if [ ${rc} -eq 0 ];then
echo "Directory: ${dir_name} terraform ${cmd_name}: Passed"
else
echo "Directory: ${dir_name} terraform ${cmd_name}: Failed"
exit 1
fi
}
# terraform実行ディレクトリを抽出する.
# .tfファイルを含むディレクトリ名を変数target_dirに格納. .tfstate及びmoduleは除外.
target_file=$(git diff --cached --name-only --diff-filter=AMRC | grep -E ".tf$|.tfvars$")
if [ -n "${target_file}" ]; then
target_dir=$(echo ${target_file} | xargs dirname | sort -u)
else
echo "No change in TF file."
exit 0
fi
# terraform init/validate
for dir in ${target_dir}
do
cd ${work_dir}/${dir} || exit 1
# terraform fmt
fmt_file=$(terraform fmt)
check_return_code fmt ${dir} $?
# fmtにより変更されたファイルをstageする.
if [ -n "${fmt_file}" ];then
cd ${work_dir}
for file in ${fmt_file}
do
git add ${dir}/${file}
done
cd ${dir}
fi
# terraform init
terraform init -backend=false 1>/dev/null
check_return_code init ${dir} $?
# terraform validate
terraform validate 1>/dev/null
check_return_code validate ${dir} $?
#exit 1
done
执行
在执行上述操作后,当提交(commit)时,会按照示例中的实际情况对变更目标的每个目录执行terraform fmt/init/validate。
注意要点
如果您在tf版本0.11之前使用tfvars文件,使用terraform validate会出错。
在这种情况下,您需要使用-var-file选项显式地指定tfvars。
请提供一些样例句,以便我能更好地理解您的需求。
-
- https://git-scm.com/docs/git-commit
-
- https://www.terraform.io/docs/commands/index.html
-
- git-commit前にsyntaxチェックする
git commit前にaddしたファイルのみrubocopで検査する