Cloud Run ジョブは、実行する際に一部のジョブ構成をオーバーライドすることが可能です。
この機能を Cloud Scheduler から実行するように Terraform で書いていたところ、思うように動作せず苦労する場面がありました。
今回はその際に直面した問題と、解決に至った具体的な書き方について解説します。

オーバーライドとは?

オーバーライドは、ジョブの実行時に以下のパラメータを一時的に変更することができる機能です。
あくまで、その実行にのみ影響するものであり、基になるジョブ定義が変更されるわけではないため、後続の実行には影響しません。

  • ジョブに構成されている引数
  • 環境変数
  • タスク数
  • タスクのタイムアウト

ユースケースとしては、プログラムから実行したり Cloud Scheduler からスケジュールで実行するような場面が多いかと思います。

Cloud Scheduler の Terraform コード

Terrafrom で Cloud Scheduler からオーバーライドを行う際のコード例です。
今回は環境変数をオーバーライドするように設定していますが、他のパラメータについても以下のリファレンスを参考に記述することで実現できます。
Overrides
ContainerOverride

なお、Terraform バージョンは 1.8.3 を使用しています。

resource "google_cloud_scheduler_job" "scheduler" {
  name             = "test-scheduler"
  schedule         = "0 * * * *"
  time_zone        = "Asia/Tokyo"
  attempt_deadline = "320s"
  region           = "asia-northeast1"

  retry_config {
    retry_count = 3
  }

  http_target {
    http_method = "POST"
    uri         = "https://asia-northeast1-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/{project_id}/jobs/{job.name}:run"
    oauth_token {
      service_account_email = google_service_account.scheduler.email
    }
    headers = {
      "Content-Type" = "application/json"
    }
    body = base64encode(<<EOT
    {
      "overrides": {
        "containerOverrides": [
          {
            "env": [
              {
                "name" : "aaa",
                "value": "bbb"
              }
            ]
          }
        ]
      }
    }
    EOT
    )
  }
}

ハマった箇所

ようやく本題となりますが、私がハマったのは body の書き方でした。
当初は公式ドキュメントに載っている例を参考に、ダブルクォーテーションをエスケープするように記述しました。
Example Usage – Scheduler Job Http
また、Cloud Scheduler の API では、ジョブの body フィールドに渡すデータが Base64 形式である必要があるため、base64encode を使用しています。

body = base64encode("
    {
      \"overrides\": {
        \"containerOverrides\": [
          {
            \"env\": [
              {
                \"name\" : \"aaa\",
                \"value\": \"bbb\"
              }
            ]
          }
        ]
      }
    }
    ")

この状態で設定反映しコンソールから確認したところ、以下のようにエスケープ文字がそのまま反映されておりました。
また、ジョブを実行してもオーバーライドされず、通常通りの値で実行されてしまいました。

ポイント①

こちらの記事を参考に以下の観点で修正してみました。

  • base64encode()に渡す内容をダブルクォーテーションで囲わない
  • JSON内のダブルクォーテーションのエスケープは不要

この時点でコードは以下になります。

body = base64encode(
    {
      "overrides": {
        "containerOverrides": [
          {
            "env": [
              {
                "name" : "aaa",
                "value": "bbb"
              }
            ]
          }
        ]
      }
    }
    )

その結果、エスケープ文字やダブルクォーテーションが消え、想定通りの内容が反映されました。

しかし、ジョブを実行しても依然としてオーバーライドは動作しません。
Cloud Scheduler は、このような圧縮形式の JSON 構文でも構文が正しければ動作するはずなのに何故、、、

ポイント②

JSON の形式が圧縮されず、インデントや空白をそのまま保つことで成功するのではないかと考え、今回はヒアドキュメントを利用して以下のようにコードを修正しました。

body = base64encode(<<EOT
    {
      "overrides": {
        "containerOverrides": [
          {
            "env": [
              {
                "name" : "aaa",
                "value": "bbb"
              }
            ]
          }
        ]
      }
    }
    EOT
    )

こちらで試したところ、想定通り圧縮されずにそのままの形式で反映されました。
そして、肝心のオーバーライドも無事動作することを確認できました。

終わりに

Cloud Scheduler から Cloud Run ジョブのオーバーライドを設定する際の、Terraform のコードの書き方について紹介しました。
オーバーライド機能を利用することで動的なパラメータの変更が可能になり、ジョブの運用効率や柔軟性を高めることができるため、オススメしたい機能の 1 つです。
なお、Terraform で JSON 形式のデータを扱う際に、圧縮形式の JSON が正しく動作しなかった理由は正確にはわかりませんでした。
考えられる原因として、Terraform のパースロジックがインデントや空白の有無に影響を受けていた可能性があると推測しています。
参考になれば幸いです!

参考
特定の実行のジョブ構成をオーバーライドする