使用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で検査する

广告
将在 10 秒后关闭
bannerAds