tldr
Github Actions で Terraformを実行してみました。
前提となること
Backend
Terraformでバックエンドをする際に知っておくべきことは以下の2点です。
(※私はGCSにしたので、providerが違うと他に気をつけることがあるかもしれません。)
- ストレージは予め作成しておく必要がある。
バックエンドに指定するストレージはapply
で一緒に作成することはできません。予め作っておく必要があります。 - アクセス権の付与の順番
以下の記事によるとTerraformはmoduleが先に読み込まれるため、クレデンシャルはBackendで指定する必要があります。そこで指定するとproviderでクレデンシャルの指定はいらないそうです。providerで指定してbackendで指定しないとデフォルトサービスアカウントが使われます。なので特殊な場合を除いてあまりやらないと思います。ただ後述するように、環境変数としてクレデンシャルを渡すので今回はどちらもパスを設定する必要はありません。
参考:
https://nickkou.me/2019/04/error-configuring-the-backend-gcs-storage-newclient-failed-dialing-google-could-not-find-default-credentials/
https://www.terraform.io/docs/github-actions/actions/plan.html
HCL -> yaml への文法の変更
Github Actionsワークフローの記法は2019年9月21日時点でyamlに変更されています(まだ使えるがdeprecatedになる)。そのため、以下の記事に従い、migration toolsを実行して HCL -> yaml
へ変換が必要になります。
はじめます
まずはTerraformが提供している公式のワークフローのサンプルをコピペします。
workflow "Terraform Cloud" {
resolves = "terraform-plan"
on = "pull_request"
}
action "filter-to-pr-open-synced" {
uses = "actions/bin/filter@master"
args = "action 'opened|synchronize'"
}
action "terraform-fmt" {
uses = "hashicorp/terraform-github-actions/fmt@<latest tag>"
needs = "filter-to-pr-open-synced"
secrets = ["GITHUB_TOKEN"]
}
action "terraform-init" {
uses = "hashicorp/terraform-github-actions/init@<latest tag>"
needs = "terraform-fmt"
secrets = ["GITHUB_TOKEN", "TF_ACTION_TFE_TOKEN"]
env = {
TF_ACTION_TFE_HOSTNAME = "app.terraform.io"
}
}
action "terraform-validate" {
uses = "hashicorp/terraform-github-actions/validate@<latest tag>"
needs = "terraform-init"
secrets = ["GITHUB_TOKEN"]
}
action "terraform-plan" {
uses = "hashicorp/terraform-github-actions/plan@<latest tag>"
needs = "terraform-validate"
secrets = ["GITHUB_TOKEN", "TF_ACTION_TFE_TOKEN"]
env = {
TF_ACTION_TFE_HOSTNAME = "app.terraform.io"
}
}
やっていることは単純でプルリクに対して fmt
, init
, validate
, plan
を実行しています。
それぞれの実際のスクリプトは uses
で指定しています。
yamlへ書き換え
まずはこれをyamlに書き換えます。
ここから最新のバイナリをダウンロードしてパスを通します。
変換したいHCLのワークフローファイルを リポジトリルート/.github/main.workflow
に置きます。
リポジトリルートで migrate-actions
を実行します。
すると リポジトリルート/.github/workflows/pull_request.yml
に変換後のファイルが作成されます。
こんな感じです。
on: pull_request
name: Terraform Cloud
jobs:
filter-to-pr-open-synced:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: filter-to-pr-open-synced
uses: actions/bin/filter@master
with:
args: action 'opened|synchronize'
- name: terraform-fmt
uses: hashicorp/terraform-github-actions/fmt@<latest tag>
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: terraform-init
uses: hashicorp/terraform-github-actions/init@<latest tag>
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TF_ACTION_TFE_HOSTNAME: app.terraform.io
TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }}
- name: terraform-validate
uses: hashicorp/terraform-github-actions/validate@<latest tag>
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: terraform-plan
uses: hashicorp/terraform-github-actions/plan@<latest tag>
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TF_ACTION_TFE_HOSTNAME: app.terraform.io
TF_ACTION_TFE_TOKEN: ${{ secrets.TF_ACTION_TFE_TOKEN }}
必要事項を埋めていく
あとはGetting Startedを読みながら必要な部分を埋めていくだけです。
クレデンシャルの設定
今回のProviderはGoogleなので、サービスアカウントのシークレットをクレデンシャルに設定します。サービスアカウントを作成し、Terraformに必要なロールを付与します(ここはどんなことをやるかによってそれぞれだと思います)。ダウンロードしたサービスアカウントのシークレットであるjsonファイルをgithubのリポジトリ設定 -> Secretsで 名前を GOOGLE_CREDENTIALS
として追加します。あとはワークフローに環境変数として渡すだけです。
最終的なファイル
最終的なファイルはこれになりました。
ディレクトリやコマンドフラグなど、若干の違いはあると思います。
on: pull_request
name: Terraform
jobs:
filter-to-pr-open-synced:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: filter-to-pr-open-synced
uses: actions/bin/filter@master
with:
args: action 'opened|synchronize'
- name: terraform-fmt
uses: hashicorp/terraform-github-actions/fmt@v0.4.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TF_ACTION_WORKING_DIR: ./main
- name: terraform-init
uses: hashicorp/terraform-github-actions/init@v0.4.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
TF_ACTION_WORKING_DIR: ./main
- name: terraform-validate
uses: hashicorp/terraform-github-actions/validate@v0.4.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TF_ACTION_WORKING_DIR: ./main
- name: terraform-plan
uses: hashicorp/terraform-github-actions/plan@v0.4.0
with:
args: '-var-file=./config.tfvars'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TF_ACTION_WORKING_DIR: ./main
TF_ACTION_WORKSPACE: default
GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }}
あとはこれを リポジトリルート/.github/workflows/pull_request.yml
に置いてプルリクを作れば終わりです。ワークフローが実行されて、結果がコメントとして貼り付けられます。
まとめとこれから
やってみると意外に簡単でした。あとは apply
をissueへのコメント(/apply
とか)をイベントとして発火させたいですね。