💡

Cloud Workflows から外部の JSON データを読み込んでセットする方法

2021/12/09に公開

Google Cloud Platform Advent Calendar 2021 の 11日目の記事です。

前提

Google Cloud リソースは Terraform で管理している

課題

Cloud Workflow で利用する E2E データを JSON で管理したい

  • E2E データの例
{
  "animal-id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
  "animal-kind": "dog",
  "options": {
    "color": "brown",
    "name": "sunndy"
  },
  "created-at": "",
  "updated-at": ""
}

解決法

Terraform の external data source を利用しシェルスクリプト経由で JSON を読み込み

詳細

read-e2e-data.sh

  • JSON データを一行の文字列で扱うために Base64 でエンコーディングを行う
#!/usr/bin/env bash

set -e

eval "$(jq -r '@sh "ENV=\(.env)"')"
printf '{"base64_encoded":"%s"}\n' $(cat ../../../workflow/e2e/data/${ENV}.json | base64 -w 0)

main.tf

  • Base64 でエンコーディングしたデータを Terraform の base64decode 関数でディコーディングを行い e2e_data っていう変数にセットする
local {
  prefix      = "org-srv"
  environment = "dev"
}

data "external" "e2e_data" {
  program = ["bash", "${path.module}/../../../workflow/e2e/read-e2e-data.sh"]
  query = {
    env = local.environment
  }
}

resource "google_service_account" "demo" {
  account_id = "${local.prefix}-demo-workflow"
}

variable "demo_workflow_roles" {
  default = [
    "roles/logging.logWriter",
    "roles/datastore.user"
  ]
}

resource "google_project_iam_member" "demo" {
  for_each = toset(var.demo_workflow_roles)
  role     = each.value
  member   = "serviceAccount:${google_service_account.demo.email}"
}

resource "google_workflows_workflow" "demo" {
  name            = "${local.prefix}-demo-workflow"
  region          = "asia-southeast1"
  service_account = google_service_account.demo.id
  source_contents = templatefile("${path.module}/../../../workflow/demo.yaml", {
    e2e_data      = base64decode(data.external.e2e_data.result["base64_encoded"])
  })
}

demo.yaml

*1) created-at, updated-at

main:
  params:
  - args
  steps:
  - init:
      assign:
        - project_id: $${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
        - current_timestamp: $${time.format(sys.now(), "Asia/Tokyo")}
        - e2e_data: ${e2e_data}

  ...
	
  - register_animal_for_e2e:
      call: googleapis.firestore.v1.projects.databases.documents.createDocument
        args:
          parent: $${"projects/" + project_id + "/databases/(default)/documents/zoo/v0"
            collectionId: animals
            documentId: $${e2e_data["animal-id"]}
            body:
              fields:
	        animal-id:
		  stringValue: $${e2e_data["animal-id"]}
		animal-kind:
		  stringValue: $${e2e_data["animal-kind"]}
		options:
		  mapValue:
		    fields:
		      color:
		        stringValue: $${e2e_data["options"]["color"]}
	              name:
		        stringValue: $${e2e_data["options"]["name"]}
                created-at:
                  timestampValue: $${current_timestamp}
		updated-at:
		  timestampValue: $${current_timestamp}

  ...

参考

Discussion