Cloud Schedulerのジョブからgcloudコマンドでジョブ内のデータを取得してみた

Cloud Schedulerに登録してあるジョブの中でPub/Subターゲットのジョブに登録してあるメッセージ本文を抽出するコマンドやシェルスクリプトを作ってみました。
2024.05.20

データアナリティクス事業本部の根本です。gcloudコマンドで、Cloud Schedulerに設定してあるPub/SubターゲットのジョブでPub/Subメッセージ本文を抽出する機会があり、折角なのでスクリプトなどをまとめて記事にしてみました。

この記事の対象者

  • gcloudコマンドでCloud Schedulerに設定してあるPub/Subターゲットのジョブに設定してあるPub/Subメッセージ本文をシェルスクリプトで抽出したいひと

前提条件

  • gcloudコマンドが使用できること

やりたいこと

  • シェルスクリプトで指定ジョブのPub/Subメッセージ本文を抽出したい

Cloud Schedulerには以下の設定値でジョブが登録されています。

設定項目名 設定値
ジョブ名 test-scheduler
ターゲットタイプ Pub/Sub
リージョン asia-northeast1
メッセージ本文 {"params": {"bucket": "test-bucket", "content": "hello-scheduler"}}

やってみる

まずはリファレンスを参照しました。

リファレンスを見てみると

gcloud scheduler jobs describe

上記コマンドで取得できそうだったので早速叩いてみました。

gcloud scheduler jobs describe "test-scheduler" --location="asia-northeast1" --format="json"

レスポンスは以下でした。

{
  "lastAttemptTime": "2024-05-19T15:00:00.314187Z",
  "name": "projects/プロジェクト名/locations/asia-northeast1/jobs/test-scheduler",
  "pubsubTarget": {
    "data": "eyJwYXJhbXMiOiB7ImJ1Y2tldCI6ICJ0ZXN0LWJ1Y2tldCIsICJjb250ZW50IjogImhlbGxvLXNjaGVkdWxlciJ9fQ==",
    "topicName": "projects/プロジェクト名/topics/トピック名"
  },
  "retryConfig": {
    "maxBackoffDuration": "3600s",
    "maxDoublings": 1,
    "maxRetryDuration": "0s",
    "minBackoffDuration": "5s"
  },
  "schedule": "00 00 * * *",
  "state": "PAUSED",
  "timeZone": "Asia/Tokyo",
  "userUpdateTime": "2024-05-20T07:28:15Z"
}

上記のレスポンスをみると、pubsubTargetのデータがBase64でエンコードされていました。取得項目を見る限り、このpubsubTargetがPub/Sub関連データが入っているのではないかと推測します。Cloud Scheduler上のPub/SubターゲットのデータもBase64にエンコードされているとは思いませんでした。
Cloud Functions関数でPub/Subメッセージからデータ取得するときはBase64をデコードするのはよくやるやつですが、同じことをやってあげる必要がありそうです。
以下のコマンドでデコードしてみました。

gcloud scheduler jobs describe "test-scheduler" --location="asia-northeast1" --format="json" \
| jq -r '.pubsubTarget.data' \
| base64 --decode

以下の結果となり、Cloud Schedulerに登録してあるジョブのPub/Subメッセージ本文と一致していました。

{"params": {"bucket": "test-bucket", "content": "hello-scheduler"}}

コマンドの動作としてはデコードするためにpubsubTargetのデータだけをjqコマンドで取得して、そのデータをbase64コマンドでデコードしています。
上記より、Cloud Schedulerに登録してあるジョブのPub/Subターゲットの本文はBase64でデコードする必要があるとわかりました。

シェルスクリプト化してみた

折角なのでシェルスクリプトにしてみました。

単一のジョブのPub/Subメッセージ本文を取得するシェルスクリプト

#!/bin/bash
# ジョブの名前とリージョンを設定。ジョブ名はコマンドライン引数で取得
JOB_NAME=$1
LOCATION="asia-northeast1"
JOB_DETAILS=$(gcloud scheduler jobs describe "$JOB_NAME" --location="$LOCATION" --format="json")
MESSAGE_BASE64=$(echo "$JOB_DETAILS" | jq -r '.pubsubTarget.data')
echo "$MESSAGE_BASE64" | base64 --decode

上記スクリプトを実行します。処理の流れはコマンドラインでやっていることそのままですが、シェルスクリプトの引数にジョブ名を設定して実行するようにしています。
実行してみます。

sh scheduler_job.sh test-scheduler

実行すると以下が出力されました。

{"params": {"bucket": "test-bucket", "content": "hello-scheduler"}}

問題なく動作しています。

複数のジョブのPub/Subメッセージ本文を取得するシェルスクリプト

折角なので、たくさんジョブがある場合でも使えるようにしてみました。

#!/bin/bash
LOCATION="asia-northeast1"
# ジョブ一覧を取得
JOB_LIST=$(gcloud scheduler jobs list --location="$LOCATION" --format="json")
# すべてのジョブについてループ
for row in $(echo "${JOB_LIST}" | jq -r '.[] | @base64'); do
    _get_job_name() {
        echo "${row}" | base64 --decode | jq -r "${1}"
    }
    JOB_NAME=$(_get_job_name '.name')
    JOB_DETAILS=$(gcloud scheduler jobs describe "$JOB_NAME" --location="$LOCATION" --format="json")
    if echo "$JOB_DETAILS" | jq -e '.pubsubTarget' > /dev/null; then
        MESSAGE_BASE64=$(echo "$JOB_DETAILS" | jq -r '.pubsubTarget.data')
        echo "Job Name: $JOB_NAME"
        echo "Message: $MESSAGE"
        echo "$MESSAGE_BASE64" | base64 --decode
        echo ""
    else
        echo "not Pub/Sub target."
    fi
done

簡単に説明しますと、ジョブ一覧を取得してその一覧を元にループ処理しています。Pub/Subターゲット以外のジョブもあると思うので、
Pub/Subターゲット以外だったら処理をスキップするようにしています。
実行結果はCloud Schedulerに設定してあるジョブによります。以下は2件ジョブを登録していた場合の結果です。

Job Name: projects/プロジェクト名/locations/asia-northeast1/jobs/test-scheduler
Message: 
{"params": {"bucket": "test-bucket", "content": "hello-scheduler"}}
Job Name: projects/プロジェクト名/locations/asia-northeast1/jobs/test-scheduler-2
Message: 
{"params": {"bucket": "test-bucket-2", "content": "this-is-scheduler-2"}}

おわりに

Base64でエンコードされていると思っていなかったので少し驚きましたが、それ以外は特に詰まるところもなくコマンド実行できました。
この記事がどなたかのお役に立てば幸いです。それではまた。