如何在Terraform模块中动态生成parameters参数以封装通用Dataflow资源?
Terraform 通用pubsub-to-db Dataflow资源最优实现方案
最优实现方案是封装为可复用的Terraform模块,公共逻辑统一维护,参数根据目标数据库类型动态生成,具体实现如下:
1. 定义通用模块结构
首先创建模块目录modules/pubsub-to-db-dataflow,包含三个文件:variables.tf、main.tf、outputs.tf(可选)。
1.1 variables.tf 定义入参
variable "db_type" { type = string description = "目标数据库类型,仅支持 firestore 或 bigquery" validation { condition = contains(["firestore", "bigquery"], var.db_type) error_message = "db_type 只能是 firestore 或者 bigquery。" } } # 通用参数 variable "dataflow_name" { type = string } variable "template_gcs_path" { type = string } variable "dataflow_bucket_name" { type = string } variable "dataflow_bucket_object_path" { type = string } variable "pubsub_subscription_id" { type = string } variable "service_account_email" { type = string } variable "job_region" { type = string } # Firestore专属参数 variable "firestore_collection" { type = string default = null } variable "firestore_collection_keys" { type = string default = null } # BigQuery专属参数 variable "google_project_name" { type = string default = null } variable "bigquery_dataset" { type = string default = null } variable "bigquery_table" { type = string default = null } variable "bigquery_table_error_records" { type = string default = "" } # 可选参数校验,确保对应类型的参数不为空 validation { condition = var.db_type == "firestore" ? (var.firestore_collection != null && var.firestore_collection_keys != null) : true error_message = "选择firestore作为目标库时,firestore_collection和firestore_collection_keys参数不能为空。" } validation { condition = var.db_type == "bigquery" ? (var.google_project_name != null && var.bigquery_dataset != null && var.bigquery_table != null) : true error_message = "选择bigquery作为目标库时,google_project_name、bigquery_dataset、bigquery_table参数不能为空。" }
1.2 main.tf 定义通用资源
resource "google_dataflow_job" "pubsub_to_db" { name = var.dataflow_name template_gcs_path = var.template_gcs_path temp_gcs_location = "gs://${var.dataflow_bucket_name}/${var.dataflow_bucket_object_path}" # 动态生成parameters对象 parameters = merge( # Firestore参数 var.db_type == "firestore" ? { pubSubSubscription = var.pubsub_subscription_id firestoreCollection = var.firestore_collection keys = var.firestore_collection_keys } : {}, # BigQuery参数 var.db_type == "bigquery" ? { inputSubscription = var.pubsub_subscription_id outputTableSpec = "${var.google_project_name}:${var.bigquery_dataset}.${var.bigquery_table}" outputDeadletterTable = var.bigquery_table_error_records != "" ? "${var.google_project_name}:${var.bigquery_dataset}.${var.bigquery_table_error_records}" : null } : {} ) service_account_email = var.service_account_email region = var.job_region on_delete = "cancel" }
2. 模块调用示例
在业务代码中直接传入对应参数即可生成对应类型的资源:
# 生成pubsub到firestore的dataflow任务 module "pubsub_to_firestore" { source = "./modules/pubsub-to-db-dataflow" db_type = "firestore" dataflow_name = var.dataflow_name template_gcs_path = var.template_gcs_path dataflow_bucket_name = google_storage_bucket.dataflow-bucket.name dataflow_bucket_object_path = google_storage_bucket_object.dataflow-bucket-object-path.name pubsub_subscription_id = google_pubsub_subscription.dataflow_subscription.id service_account_email = data.google_service_account.dataflow_account.email job_region = var.job_region firestore_collection = var.firestore_collection firestore_collection_keys = var.firestore_collection_keys } # 生成pubsub到bigquery的dataflow任务 module "pubsub_to_bigquery" { source = "./modules/pubsub-to-db-dataflow" db_type = "bigquery" dataflow_name = var.dataflow_name template_gcs_path = var.template_gcs_path dataflow_bucket_name = google_storage_bucket.dataflow-bucket.name dataflow_bucket_object_path = google_storage_bucket_object.dataflow-bucket-object-path.name pubsub_subscription_id = google_pubsub_subscription.dataflow_subscription.id service_account_email = data.google_service_account.dataflow_account.email job_region = var.job_region google_project_name = var.google_project_name bigquery_dataset = var.bigquery_dataset bigquery_table = var.bigquery_table bigquery_table_error_records = var.bigquery_table_error_records }
轻量实现方案(无需封装模块)
如果只有这两个任务实例、不想单独封装模块,也可以通过本地值+for_each动态生成资源:
# 定义两个任务的配置 locals { dataflow_jobs = { pubsub-to-firestore = { parameters = { pubSubSubscription = google_pubsub_subscription.dataflow_subscription.id firestoreCollection = var.firestore_collection keys = var.firestore_collection_keys } } pubsub-to-bigquery = { parameters = { inputSubscription = google_pubsub_subscription.dataflow_subscription.id outputTableSpec = "${var.google_project_name}:${var.bigquery_dataset}.${var.bigquery_table}" outputDeadletterTable = var.bigquery_table_error_records != "" ? "${var.google_project_name}:${var.bigquery_dataset}.${var.bigquery_table_error_records}" : null } } } } # 循环生成资源 resource "google_dataflow_job" "pubsub_to_db" { for_each = local.dataflow_jobs name = "${var.dataflow_name}-${each.key}" template_gcs_path = var.template_gcs_path temp_gcs_location = "gs://${google_storage_bucket.dataflow-bucket.name}/${google_storage_bucket_object.dataflow-bucket-object-path.name}" parameters = each.value.parameters service_account_email = data.google_service_account.dataflow_account.email region = var.job_region on_delete = "cancel" }
内容的提问来源于stack exchange,提问作者Shamik Mukherjee
相关产品推荐
相关产品推荐

