Zenn
😇

Terraform で BigQuery の スケジュールクエリを管理する

2025/03/26に公開

はじめに

  • BigQuery の scheduled query を Terraform で管理してみる話

想定する環境とディレクトリ

.
├── google_bigquery_scheduled_querie.tf
├── scheduled_queries
│   └── foobar_dataset # 書き込み先データセットを表す
│   │   └── foobar_table.sql # 書き込み先テーブルを表す
(省略)
  • 書き込み先データセット : foobar_dataset
  • 書き込み先テーブル : foobar_table
  • スケジュールクエリで実行するSQL : foobar_table.sql

コードのサンプルと解説

google_bigquery_scheduled_querie.tf
resource "google_project_iam_member" "datatransfer_permission" {
  count = var.env == "prod" ? 1 : 0

  project = var.project_id
  role    = "roles/iam.serviceAccountShortTermTokenMinter"
  member  = "serviceAccount:${google_service_account.foobar_user.email}"
}

resource "google_bigquery_data_transfer_config" "scheduled_queries_every_day" {
  depends_on = [google_project_iam_member.datatransfer_permission]

  for_each = var.env == "prod" ? fileset("${path.module}/scheduled_queries", "*/*.sql") : []

  project              = var.project_id
  display_name         = trimsuffix(each.value, ".sql")
  location             = "asia-northeast1"
  data_source_id       = "scheduled_query"
  schedule             = "every day 10:00" # UTC
  service_account_name = google_service_account.foobar_user.email

  destination_dataset_id = split("/", each.value)[0]

  params = {
    destination_table_name_template = trimsuffix(split("/", each.value)[1], ".sql")
    write_disposition               = "WRITE_TRUNCATE"
    query                           = file("${path.module}/scheduled_queries/${each.value}")
  }
}
  • 実行ユーザには、 roles/iam.serviceAccountShortTermTokenMinter が必要
  • for_each と count の併用はできないので、 for_each = var.env == "prod" ? fileset("${path.module}/scheduled_queries", "*/*.sql") : [] で for_each で prod 環境のみを表現

ハマったこと

最初以下のようなSQLだったが

CREATE OR REPLACE TABLE
  foobar_dataset.foobar_table AS
SELECT
  col1,
  col2,
FROM
  foobar_dataset02.foobar_table02
;

以下のようなエラーになった

Error code 3 : Query error: Cannot set destination table in jobs with DDL statements; JobID: xxx

おそらく、destination_table を指定している状態で、CREATE OR REPLACE TABLE してるのが良くないと推測し、以下のようにSQLを修正したらエラーは出なくなった(destination_table_name_template は指定した状態で)

SELECT
  col1,
  col2,
FROM
  foobar_dataset02.foobar_table02
;

参考にしたもの

Discussion

ログインするとコメントできます