こんにちは、SRE所属の @ishii1648 です。
この記事は、All About Group(株式会社オールアバウト) Advent Calendar 2022 19日目の記事です。
はじめに
現在オールアバウトでは Terraform のCI化を進めています。CI の流れとしてはPRの作成・更新をトリガーにざっくり以下のような動作順序になっています。
- 変更対象のディレクトリを検知
- terraform のセットアップ
- terraform init
- terraform plan
- terraform validate
- terraform plan の結果を PR に添付
割とよくある構成だと思いますが、一つ躓くポイントがあるのでその点について解決策を共有できればと思います。
かなりニッチな内容にはなりますが、興味のある方、同じ悩みをお持ちの方の一助になれば幸いです。
躓きポイントについて
terraform validate を利用する場合(conftestを利用する場合も同じです)、terraformのセットアップで以下のようにオプションを設定する必要があります。
- name: Setup terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.x.x
terraform_wrapper: false
注目して頂きたいのは terraform_wrapper
というオプションでデフォルトが true なのですが false に設定してやらないと validate が正常動作しません。
しかしこの設定にすると terraform が標準出力できなくなるためplan結果を PR に添付するのが難しくなります。
例えば validate を省略するようなCIの作りの場合以下のようなコードでplan結果を PR に添付できます。
- name: Setup terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.2.0
- name: Terraform init & plan
id: plan
run: |
terraform init
terraform plan -no-color
working-directory: ${{ matrix.dir }}
continue-on-error: true
- name: Notify
if: steps.plan.outputs.exitcode == 2
uses: actions/github-script@v3.0.0
with:
github-token: ${{ secrets.github_token }}
script: |
const output = `## \`${{ matrix.dir }}\`
<details><summary>Show Plan</summary>
\`\`\`terraform\n${{ steps.plan.outputs.stdout }}\`\`\`
</details>`;
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
terraform plan した結果を次のジョブで標準出力(steps.plan.outputs.stdout)として受け取って通知しています。
ここで validate の処理を追加しようとすると上述の通り標準出力が使えなくなるため困り果ててしまいます。
解消方法
結論以下のようなコードで validate を入れつつ結果を PR に添付できるようになります。
- name: Setup terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.2.0
terraform_wrapper: false
- name: Terraform init & plan
id: plan
run: |
terraform init
terraform plan -no-color -out=tfplan
working-directory: ${{ matrix.dir }}
continue-on-error: true
- name: Terraform show
id: show
run: |
terraform show -no-color tfplan > tfplan.txt
terraform show -no-color -json tfplan > tfplan.json
cat tfplan.txt
working-directory: ${{ matrix.dir }}
- name: Terraform validate
id: validate
run: |
cp ${GITHUB_WORKSPACE}/policies/constraints/* ${GITHUB_WORKSPACE}/policy-library/policies/constraints
gcloud beta terraform vet tfplan.json --policy-library=${GITHUB_WORKSPACE}/policy-library --format=json
- name: Notify
uses: actions/github-script@v3.0.0
with:
github-token: ${{ secrets.github_token }}
script: |
const output = `## \`${{ matrix.dir }}\`
<details><summary>Show Plan</summary>
\`\`\`terraform\n${{ steps.show.outputs.stdout }}\`\`\`
</details>`;
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})
ポイントは terraform plan 実行時にoutオプションを設定する所です。outオプションはplanの実行結果をバイナリ形式でファイル保存してくれます。ここは標準出力を利用していないので terraform_wrapper
が無効化されていても有効に機能します。
バイナリ形式で保存されたplan結果は terraform show を使ってテキスト化できるのでその内容を通知として扱うことができます。
最後に
如何だったでしょうか?
かなりニッチな内容だったかとは思いますが、TerraformをCI化しようとすればvalidate等の静的チェックも併せて入れるのは一般的なことかと思います。私はこのやり方を思いつくまでに1ヶ月以上かかってしまったので同じ悩みの方がいればぜひ参考にして頂けると幸いです。
以上、All About Group(株式会社オールアバウト) Advent Calendar 2022 19日目でした。