生涯未熟

生涯未熟

プログラミングをちょこちょこと。

Terraformに対応していないRemote ConfigをなんとかIaCしてみた

優先度の関係から長らく着手していなかったIaCタスクを進めていたのですが、開発メンバーと1on1した時に「Remote ConfigをIaCして欲しい」と要望を受けました。
たしかにコンソール上からコンフィグいじるの嫌だよな〜というのは薄っすら感じていたのですが、これを機になんとかしてみることにしました。

google-betaにない!!

Terraformにはproviderがありますが、Firebaseのresourceを扱うためにはgoogle-betaというベータ版のproviderを利用する必要があります。

registry.terraform.io

んじゃこれを使えばめでたしめでたし、とはいかず確認したところFirebaseの対応しているresourceの少ないこと少ないこと。
対応しているのは以下になります。

  • Firebaseプロジェクト
  • プロジェクトのロケーション
  • Firebaseアプリ
  • Firebase Realtime Database
  • Cloud Firestore
  • Cloud Storage for Firebase
  • Firebase セキュリティ ルール

これだけになります。はい、Remote Configがありませんね・・・

無いならなんとかしよう

まず、この時点でTerraform resourceとして管理するのは諦めました。無いなら仕方ない。
ただ、希望の芽としてFirebase CLIの存在があります。次は、こちら確認してみましょう。

firebase.google.com

デプロイはありませんね😇

ここまで調べたところで8割くらい無理なんじゃないか?と思ったところで、monoさんがzennに書かれていたこんな記事を見つけました。

zenn.dev

おぉ!希望の芽が再び!ということで、プログラム経由で更新することになりました。

デプロイパイプラインを作ろう

さて、プログラム経由で更新するということでCloud Functionsを使ってデプロイをするパイプラインを組んでみました。
概念図はこんな感じになります。

  • Remote Configの内容をコードに書き起こしたものを編集し、コミットする
  • コミットが通ればGitHub Actionsが発火し、Cloud Functionsに変更した内容を渡して実行する
  • Cloud Functionsで渡した内容を元にRemote Configへデプロイする

こんな感じの流れになります。

実装

GitHub Actions

まずはGitHub Actionsの実装です。前提として弊チームのRemote ConfigではJSONのみ扱っているため、それに合わせた実装となっています。

JSONを2つに分けている理由ですが、Remote Configのテンプレートを確認するとコンソールでの設定画面と違い、

{
  "parameters": {
    "info": {
      "defaultValue": {
        "value": "[ここがいつも設定しているコンフィグ情報]"
      },
      "description": "",
      "valueType": "JSON"
    }
}

このような形式で、 value にコンソール画面でいつも設定するようなコンフィグ情報が記載しています。
ただし、この value にはJSON文字列が入っており、視認性が悪いため修正するのにコストがかかります。そこで、テンプレートの土台となる部分本来の設定したいJSON文字列の部分とでJSONを分けることにしました。

workflowの中でも書いていますが、プロジェクト配下に github_actions/deploy-firebase-remote-config ディレクトリを置き、その中に config.json , info.json の2ファイルを置いております。 config.json がテンプレートの土台で、 info.json が設定したいJSONとなります。なので、開発チームが触るときには info.json を編集し、コミットするという流れになります。

コード自体は難しいことはしていませんが、jqを使ってゴニョっと2ファイルをくっつけているといったところが全てですね。

Cloud Functions

次に、Cloud Functionsの実装です。こちらはmonoさんのコードから大きくは変わらないのですが、こんな感じになりました。

credential権限を付与したサービスアカウントのJSONファイルの内容を、 databaseURL には https://[プロジェクト名].firebaseio.com を入れてください。前者についてはキチンとSecret Managerで管理するようにしましょう。
あとはよしなにデプロイ結果が分かるようにSlack通知を飛ばすようにしています。

おわり

これでRemote Configへのデプロイパイプラインが組めました。めでたしめでたし。
ありがたいことに開発チームから「便利になった!」という声もいただけて、やってよかったなぁとなったタスクでした。