created: 2022-06-08T14:34:59.234Z
GCP の CloudStorage でオブジェクトの追加/更新イベントを PubSub で拾う
オブジェクトが変更されたら PubSub にメッセージがいくようにする
$ gsutil notification create -t myappb-notification -f json gs://myappb
Created Cloud Pub/Sub topic projects/myapp-123456/topics/myappb-notification
Created notification config projects/_/buckets/myappb/notificationConfigs/1
-t
- PubSubのトピック名(新規に作成される)
-f
format
の略- 通知のデータ形式。
json|none
でnone
を選ぶとpayloadがなくなるらしい
そのほか色々オプションがある。
Funcion をデプロイ
CloudFunctionの仕様は gcloud で関数をデプロイするためのnpmスクリプトでIaC管理するので terraform での管理はしないことにした。
$ gcloud functions deploy FUNC --trigger-topic MY_TOPIC --runtime RUNTIME
作成したリソースを terraform import
$ terraform import google_storage_notification.notification myappb/notificationConfigs/1
$ terraform import google_pubsub_topic.myappb_notification_topic myapp-123456/myappb-notification
実装後の tf ファイル
plan すると create/destroy となったが、まだ使い始める前なので create/destroy にしてもらった。
resource "google_storage_notification" "myappb_storage_notification" {
bucket = google_storage_bucket.myappb.name
topic = google_pubsub_topic.myappb_notification_topic.id
payload_format = "JSON_API_V1"
}
resource "google_pubsub_topic" "myappb_notification_topic" {
name = "myappb-notification"
}
CloudFunction に届く通知
ログを出すだけのコードを書いておく。
import type { EventFunction } from "@google-cloud/functions-framework/build/src/functions";
export const CsvHandler: EventFunction = async (data, event) => {
console.log(JSON.stringify({ data, event }));
return ;
};
たとえば /debug/test.txt
にファイルを配置すると、関数が動いてこんな出力が得られる。
{
"data": {
"@type": "type.googleapis.com/google.pubsub.v1.PubsubMessage",
"attributes": {
"bucketId": "myappb",
"eventTime": "2022-06-07T23:10:26.918668Z",
"eventType": "OBJECT_FINALIZE",
"notificationConfig": "projects/_/buckets/myappb/notificationConfigs/3",
"objectGeneration": "1654643426818516",
"objectId": "debug/test.txt",
"payloadFormat": "JSON_API_V1"
},
"data": "ewogICJraW5kIjogInN0b3JhZ2Ujb2JqZWN0IiwKICAiaWQiOiAia25ldGIvZGVidWcvdGVzdC50eHQvMTY1NDY0MzQyNjgxODUxNiIsCiAgInNlbGZMaW5rIjogImh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9rbmV0Yi9vL2RlYnVnJTJGdGVzdC50eHQiLAogICJuYW1lIjogImRlYnVnL3Rlc3QudHh0IiwKICAiYnVja2V0IjogImtuZXRiIiwKICAiZ2VuZXJhdGlvbiI6ICIxNjU0NjQzNDI2ODE4NTE2IiwKICAibWV0YWdlbmVyYXRpb24iOiAiMSIsCiAgImNvbnRlbnRUeXBlIjogInRleHQvcGxhaW4iLAogICJ0aW1lQ3JlYXRlZCI6ICIyMDIyLTA2LTA3VDIzOjEwOjI2LjkxOFoiLAogICJ1cGRhdGVkIjogIjIwMjItMDYtMDdUMjM6MTA6MjYuOTE4WiIsCiAgInN0b3JhZ2VDbGFzcyI6ICJTVEFOREFSRCIsCiAgInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjogIjIwMjItMDYtMDdUMjM6MTA6MjYuOTE4WiIsCiAgInNpemUiOiAiNSIsCiAgIm1kNUhhc2giOiAiMk9qOG90d1BpVy9YeTB5d0F4dWlTUT09IiwKICAibWVkaWFMaW5rIjogImh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9rbmV0Yi9vL2RlYnVnJTJGdGVzdC50eHQ/Z2VuZXJhdGlvbj0xNjU0NjQzNDI2ODE4NTE2JmFsdD1tZWRpYSIsCiAgImNvbnRlbnRMYW5ndWFnZSI6ICJlbiIsCiAgImNyYzMyYyI6ICIrcFQ5M3c9PSIsCiAgImV0YWciOiAiQ05UenZZMjduUGdDRUFFPSIKfQo="
},
"event": {
"eventId": "4767758010631234",
"eventType": "google.pubsub.topic.publish",
"resource": {
"name": "projects/myapp-123456/topics/myappb-notification",
"service": "pubsub.googleapis.com",
"type": "type.googleapis.com/google.pubsub.v1.PubsubMessage"
},
"timestamp": "2022-06-07T23:10:27.098Z"
}
}
jsonPayload
の中の data
は base64 でエンコードされているJSONである。
$ pbpaste | jq -r .jsonPayload.data.data | base64 -d
{
"kind": "storage#object",
"id": "myapp/debug/test.txt/1654643426818516",
"selfLink": "https://www.googleapis.com/storage/v1/b/myapp/o/debug%2Ftest.txt",
"name": "debug/test.txt",
"bucket": "myapp",
"generation": "1654643426818516",
"metageneration": "1",
"contentType": "text/plain",
"timeCreated": "2022-06-07T23:10:26.918Z",
"updated": "2022-06-07T23:10:26.918Z",
"storageClass": "STANDARD",
"timeStorageClassUpdated": "2022-06-07T23:10:26.918Z",
"size": "5",
"md5Hash": "2Oj8otwPiW/Xy0ywAxuiSQ==",
"mediaLink": "https://www.googleapis.com/download/storage/v1/b/myapp/o/debug%2Ftest.txt?generation=1654643426818516&alt=media",
"contentLanguage": "en",
"crc32c": "+pT93w==",
"etag": "CNTzvY27nPgCEAE="
}