1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

自作Terraform Provider用のGitHub Actionsを自作して公開してみた

Last updated at Posted at 2019-06-28

はじめに

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の各サブコマンド(plan , validate ...)毎にentrypoint.shを作っておき、その中で、事前に / においておいたバイナリをプラグインの所定のディレクトリである、 ~/.terraform.d/plugins/linux_amd64コピーする という処理を毎回入れる
  • その後に terraform initterraform 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 という形にしました。

次にこのリポジトリに対してビルドの設定を追加します。

スクリーンショット 2019-06-28 10.26.59.png

とりあえず↑のような感じにしました。

Save して、手動で Trigger してみます。
どうやら上手く作れたようです。 SUCCESS となりました。

スクリーンショット 2019-06-28 10.27.44.png

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で変えてます。

スクリーンショット 2019-06-28 13.46.16.png

実際にPull Requestを投げてみる

main.tf に以下のような変更を加えてPRします。

resource "ecl_compute_keypair_v2" "kp1" {
  name = "kp1"
}

うまくいくと、以下のような感じで処理が順次流れていきます、。

スクリーンショット 2019-06-28 13.41.31.png

で、最終的にコメント欄がこうなります。

スクリーンショット 2019-06-28 13.41.25.png

はい、無事Planまでたどり着くことができました :tada:

感想

GitHub Actionsのdeveloper向けドキュメントをもっと読みたい。

個人的には純正アクションにプロバイダのバイナリを放り込む入り口があればいいなぁと思いますね。
ただ entorypoint.sh で毎回wgetとかしちゃうといちいち遅いので、本体のイメージには組み込めないだろうし難しいところだなぁと思います。
どういう方法がベストなのだろうか・・・。
多分Officialではないプロバイダをお持ちの方は同じ悩みを持っているのではないでしょうか。

この感じだと、前回書いた のですが、Atlantisのほうが環境は準備しやすかったし、使い勝手も良さそう。

まぁ、そのうち Terraform Cloud Free Tier から出来るようになるはずなので、そうなれば多分それが最強なんじゃないかなと思ったり。

ということで、かなりレアだとは思いますが、

  • Enterprise CloudをTerraformで構築したい
  • そのCIをGitHubだけで完結させたい

という方は是非お使いください。

・・・考えてみるとstateがTerraform Cloudな状態でしか試験してないけど・・・。
多分大丈夫!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?