はじめに
Terraform用のGitHub Actionsは2018/10くらいからあるようなのですが、考えてみると今回自作した Terraform provider for Enterprise Cloud に使えるのだろうか・・・とちょっと検証してみて、比較的すぐだめだとわかりました。
理由は Community Provider の場合、そのバイナリを挿入する方法がないこと。
基本GitHub ActionsはDockerイメージの上で動くわけですが、そこから呼ばれている entrypoint.sh
にはそのバイナリをプラグインパスに対して送り込む方法がないんですよね・・・。
このへんとか見るとそういう事がわかります。
しょうがないんで勉強も兼ねて自作することにしました。
やってみたこと
今回は以下の思想で自作Provider用のGitHub Actionsを準備することにしました。
- GitHub Actionsから呼び出されるイメージは、基本hashicorp/terraformベースのものにする
- イメージビルド時は、Dockerfile内で、コンパイル済みの自作プロバイダのバイナリを
/
においておくように処理をしておく- GitHub Actions経由で上記イメージがrunされる際、どうやら
/github
が-v
経由でマウントされている。かつ、ここが$HOME
相当になってしまうため、イメージビルドの段階で~/.terraform.d/
配下にプロバイダのバイナリをおいておく意味がないように見える(実際の挙動はコードレベルでちゃんと確認しておきたいが・・・)
- GitHub Actions経由で上記イメージがrunされる際、どうやら
- GitHub Actionsの各サブコマンド(
plan
,validate
...)毎にentrypoint.shを作っておき、その中で、事前に/
においておいたバイナリをプラグインの所定のディレクトリである、~/.terraform.d/plugins/linux_amd64
にコピーする
という処理を毎回入れる - その後に
terraform init
やterraform apply
等が動くようにすることで、プロバイダが見つからない問題を回避する
改善点は多々ありますが、一旦これで実現してみようかと思います。
ベースのイメージを作るためのDockerfileを用意
まず ここ にベースのイメージ用のDockerfileとentrypoint.shを作ります。
(FROM:
) は hashicorp/terraform:0.12.3
にしてます。
実際にGitHub Actions側に仕込むイメージは、さらにこれを継承して作るイメージですね。
それ用のイメージにLABELを付与することでworkflowのアイコンがそれっぽくなるので。
ということで、繰り返しになりますがこれはベース用です。
Docker Hubと連携
このリポジトリを Docker Hubと連携しておき、ビルドは自動化します。
まずGitHub AccountとConnectして、その後リポジトリを作ります。
今回は、 keiichihikita/terraform-ecl
という形にしました。
次にこのリポジトリに対してビルドの設定を追加します。
とりあえず↑のような感じにしました。
で Save
して、手動で Trigger
してみます。
どうやら上手く作れたようです。 SUCCESS
となりました。
GitHub Actionsのリポジトリを用意
GitHub Actionsの各アクションはつまるところリポジトリです。
こんな 感じで作ってみました。
ほとんど本家のパクリですが。
変えたのは大きく2点です
- ベースのイメージを変えてます。例えば こんな 感じです。
- 最初に書いた、プロバイダのバイナリを
$HOME/.terraform.d/plugins/linux_amd64
配下に持ってくる処理を追記しています。こんな 感じです。
このアクションを使ってみる
特にwebhookとかが存在していないリポジトリを別に作って、そこにPRを投げて動作確認をします。
(これはプライベートリポジトリで準備してますので、構成はなんとなく以下から推測していただければ・・・)
main.workflowの準備
GitHub Actionsを動かすためには、 .github/main.workflow
をおいておく必要があるようで。
これはブラウザからGUIでも作れますし、普通にファイルを HCL
で作るのでもどちらでもOKです。
(以外だったのはHCLで書かれている点でしたね)
基本的な流れは、こちらにかかれているのですが、ちょっと考えるべき点だけを引用しながら以下に書いておきます。
Find the latest version from https://github.com/hashicorp/terraform-github-actions/releases and replace all instances of @v. For example: uses = "hashicorp/terraform-github-actions/plan@v3.0".
自分の場合は、自分の用意したGitHub Actions のmasterを見るように変更しています
Directories — If your Terraform configuration is not in the root of your repo, replace all instances of
自分の場合は、tf
ファイル群をおいている(要はGitHub Actionsを適用しているリポジトリが)トップレベルに tf
ファイルがある構成になっているので特に考慮は不要です。
実際、以下のような形です。
% tree . .
├── main.tf
├── provider.tf
└── terraform.tf
Workspaces — If your Terraform runs in a different Terraform workspace than default, change the TF_ACTION_WORKSPACE environment variable in the terraform-plan action.
Terraform Cloud Free Tier
の場合、workspaceは使えませんのでこれもdefaultのままにしてあります。
ということで、最終的に main.workflow
はこうなりました。
workflow "Terraform" {
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 = "keiichi-hikita/terraform-ecl-github-actions/fmt@master"
needs = "filter-to-pr-open-synced"
secrets = ["GITHUB_TOKEN"]
env = {
TF_ACTION_WORKING_DIR = "."
}
}
action "terraform-init" {
uses = "keiichi-hikita/terraform-ecl-github-actions/init@master"
needs = "terraform-fmt"
secrets = ["GITHUB_TOKEN", "TF_ACTION_TFE_TOKEN"]
env = {
TF_ACTION_WORKING_DIR = "."
}
}
action "terraform-validate" {
uses = "keiichi-hikita/terraform-ecl-github-actions/validate@master"
needs = "terraform-init"
secrets = ["GITHUB_TOKEN", "TF_ACTION_TFE_TOKEN"]
env = {
TF_ACTION_WORKING_DIR = "."
}
}
action "terraform-plan" {
uses = "keiichi-hikita/terraform-ecl-github-actions/plan@master"
needs = "terraform-validate"
secrets = ["GITHUB_TOKEN", "TF_ACTION_TFE_TOKEN"]
env = {
TF_ACTION_WORKING_DIR = "."
# If you're using Terraform workspaces, set this to the workspace name.
TF_ACTION_WORKSPACE = "default"
}
}
図にするとこんな形になっています。(途中までしか見えない)
アイコンを青くしています(本家のは紫)が、これは各アクションのDockerfileのLABELで変えてます。
実際にPull Requestを投げてみる
main.tf
に以下のような変更を加えてPRします。
resource "ecl_compute_keypair_v2" "kp1" {
name = "kp1"
}
うまくいくと、以下のような感じで処理が順次流れていきます、。
で、最終的にコメント欄がこうなります。
はい、無事Planまでたどり着くことができました
感想
GitHub Actionsのdeveloper向けドキュメントをもっと読みたい。
個人的には純正アクションにプロバイダのバイナリを放り込む入り口があればいいなぁと思いますね。
ただ entorypoint.sh
で毎回wgetとかしちゃうといちいち遅いので、本体のイメージには組み込めないだろうし難しいところだなぁと思います。
どういう方法がベストなのだろうか・・・。
多分Officialではないプロバイダをお持ちの方は同じ悩みを持っているのではないでしょうか。
この感じだと、前回書いた のですが、Atlantisのほうが環境は準備しやすかったし、使い勝手も良さそう。
まぁ、そのうち Terraform Cloud Free Tier
から出来るようになるはずなので、そうなれば多分それが最強なんじゃないかなと思ったり。
ということで、かなりレアだとは思いますが、
- Enterprise CloudをTerraformで構築したい
- そのCIをGitHubだけで完結させたい
という方は是非お使いください。
・・・考えてみるとstateがTerraform Cloudな状態でしか試験してないけど・・・。
多分大丈夫!