春になったし Cloud Workflows の検証でもしようかと思って、その部品として Cloud Functions を作るぞとなったので、最近入門したGoでやってみようと思いました。しかし、検索してもこの組合せのサンプルが全然出てこなかった。
結論
Terraform では、Go で書いた Cloud Functions を Python や Ruby と同じ方式でデプロイできます。Go のビルドプロセスは隠蔽されています。
実装
terraform のバージョンは 0.13.4、google provider のバージョンは 3.60.0 (公開時点の最新)です。
Go
これはほぼサンプルのままです。リクエストを受けたら返事をするだけです。
package got import ( "encoding/json" "fmt" "html" "net/http" ) func HelloHTTP(w http.ResponseWriter, r *http.Request) { var d struct { Name string `json:"name"` } if err := json.NewDecoder(r.Body).Decode(&d); err != nil { fmt.Fprint(w, "Winter is comming!") return } if d.Name == "" { fmt.Fprint(w, "Winter is comming!") return } fmt.Fprintf(w, "Hello, %s!", html.EscapeString(d.Name)) }
Terraform
cloudfunctions.invoker の権限をもつアカウントだけが、HTTPリクエストを送信できるようにしています。 Goなので、ビルド関連でPythonやRubyと何か違いがあるはずと思ったのですが、そんなことはなく、同じように書けばOKです。この"他の言語と同じように書けばOK"という事実が、検索しても出てこない。初回applyのときはちょっと驚きました。
resource "google_cloudfunctions_function" "got" { name = "got" description = "Game of Thrones" runtime = "go113" source_archive_bucket = google_storage_bucket.zip_bucket.name source_archive_object = google_storage_bucket_object.function_got_packages.name available_memory_mb = 128 timeout = 30 entry_point = "HelloHTTP" trigger_http = true service_account_email = google_service_account.sa_functions_got.email } data "archive_file" "function_got_archive" { type = "zip" source_dir = "src/go/got" output_path = "zip/go/got.zip" } resource "google_storage_bucket_object" "function_got_packages" { name = "packages/go/function_got.${data.archive_file.function_got_archive.output_md5}.zip" bucket = google_storage_bucket.zip_bucket.name source = data.archive_file.function_got_archive.output_path } resource "google_cloudfunctions_function_iam_member" "got_member" { project = google_cloudfunctions_function.got.project region = google_cloudfunctions_function.got.region cloud_function = google_cloudfunctions_function.got.name role = "roles/cloudfunctions.invoker" member = "serviceAccount:${google_service_account.sa_functions_got.email}" } resource "google_project_iam_member" "cloud_storage_admin_got" { role = "roles/storage.objectAdmin" member = "serviceAccount:${google_service_account.sa_functions_got.email}" } output "function_got_url" { value = google_cloudfunctions_function.got.https_trigger_url }
Cloud Run と同じで、ビルドが隠蔽されているのが心地よいです。どの言語を選んだとしても開発のプロセスが変わらないので、とても素敵だなと思いました。