diff --git a/blueprints/apigee/bigquery-analytics/main.tf b/blueprints/apigee/bigquery-analytics/main.tf
index d1534ad77..51f9a13f2 100644
--- a/blueprints/apigee/bigquery-analytics/main.tf
+++ b/blueprints/apigee/bigquery-analytics/main.tf
@@ -143,6 +143,7 @@ module "bucket_export" {
]
}
notification_config = {
+ create_topic = {}
enabled = true
payload_format = "JSON_API_V1"
sa_email = module.project.service_agents.storage.email
diff --git a/blueprints/data-solutions/vertex-mlops/README.md b/blueprints/data-solutions/vertex-mlops/README.md
index 66ae67567..9caaf0727 100644
--- a/blueprints/data-solutions/vertex-mlops/README.md
+++ b/blueprints/data-solutions/vertex-mlops/README.md
@@ -79,20 +79,21 @@ module "test" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [notebooks](variables.tf#L76) | Vertex AI workbenches to be deployed. Service Account runtime/instances deployed. | map(object({…})) | ✓ | |
-| [project_config](variables.tf#L103) | Provide 'billing_account_id' value if project creation is needed, uses existing 'project_id' if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | object({…}) | ✓ | |
+| [notebooks](variables.tf#L82) | Vertex AI workbenches to be deployed. Service Account runtime/instances deployed. | map(object({…})) | ✓ | |
+| [project_config](variables.tf#L109) | Provide 'billing_account_id' value if project creation is needed, uses existing 'project_id' if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | object({…}) | ✓ | |
| [bucket_name](variables.tf#L18) | GCS bucket name to store the Vertex AI artifacts. | string | | null |
| [dataset_name](variables.tf#L24) | BigQuery Dataset to store the training data. | string | | null |
| [deletion_protection](variables.tf#L30) | Prevent Terraform from destroying data storage resources (storage buckets, GKE clusters, CloudSQL instances) in this blueprint. When this field is set in Terraform state, a terraform destroy or terraform apply that would delete data storage resources will fail. | bool | | false |
| [groups](variables.tf#L37) | Name of the groups (name@domain.org) to apply opinionated IAM permissions. | object({…}) | | {} |
-| [identity_pool_claims](variables.tf#L48) | Claims to be used by Workload Identity Federation (i.e.: attribute.repository/ORGANIZATION/REPO). If a not null value is provided, then google_iam_workload_identity_pool resource will be created. | string | | null |
-| [labels](variables.tf#L54) | Labels to be assigned at project level. | map(string) | | {} |
-| [location](variables.tf#L60) | Location used for multi-regional resources. | string | | "eu" |
-| [network_config](variables.tf#L66) | Shared VPC network configurations to use. If null networks will be created in projects with preconfigured values. | object({…}) | | null |
-| [prefix](variables.tf#L97) | Prefix used for the project id. | string | | null |
-| [region](variables.tf#L117) | Region used for regional resources. | string | | "europe-west4" |
-| [repo_name](variables.tf#L123) | Cloud Source Repository name. null to avoid to create it. | string | | null |
-| [service_encryption_keys](variables.tf#L129) | Cloud KMS to use to encrypt different services. Key location should match service region. | object({…}) | | {} |
+| [identity_pool_assertions](variables.tf#L48) | Assertions to be used by Workload Identityf Federation on tokens, for example: assertion.repository_owner=='ORGANIZATION'. | string | | null |
+| [identity_pool_claims](variables.tf#L54) | Claims to be used by Workload Identity Federation (i.e.: attribute.repository/ORGANIZATION/REPO). If a not null value is provided, then google_iam_workload_identity_pool resource will be created. | string | | null |
+| [labels](variables.tf#L60) | Labels to be assigned at project level. | map(string) | | {} |
+| [location](variables.tf#L66) | Location used for multi-regional resources. | string | | "eu" |
+| [network_config](variables.tf#L72) | Shared VPC network configurations to use. If null networks will be created in projects with preconfigured values. | object({…}) | | null |
+| [prefix](variables.tf#L103) | Prefix used for the project id. | string | | null |
+| [region](variables.tf#L123) | Region used for regional resources. | string | | "europe-west4" |
+| [repo_name](variables.tf#L129) | Cloud Source Repository name. null to avoid to create it. | string | | null |
+| [service_encryption_keys](variables.tf#L135) | Cloud KMS to use to encrypt different services. Key location should match service region. | object({…}) | | {} |
## Outputs
@@ -111,9 +112,10 @@ module "test" {
"env" = "dev",
"team" = "ml"
}
- bucket_name = "gcs-test"
- dataset_name = "bq_test"
- identity_pool_claims = "attribute.repository/ORGANIZATION/REPO"
+ bucket_name = "gcs-test"
+ dataset_name = "bq_test"
+ identity_pool_assertions = "assertion.repository_owner=='ORGANIZATION'"
+ identity_pool_claims = "attribute.repository/ORGANIZATION/REPO"
notebooks = {
"myworkbench" = {
type = "USER_MANAGED"
diff --git a/blueprints/data-solutions/vertex-mlops/ci-cd.tf b/blueprints/data-solutions/vertex-mlops/ci-cd.tf
index e5e728672..84f72087d 100644
--- a/blueprints/data-solutions/vertex-mlops/ci-cd.tf
+++ b/blueprints/data-solutions/vertex-mlops/ci-cd.tf
@@ -33,6 +33,7 @@ resource "google_iam_workload_identity_pool_provider" "github_provider" {
"google.subject" = "assertion.sub"
"attribute.repository" = "assertion.repository"
}
+ attribute_condition = var.identity_pool_assertions
oidc {
issuer_uri = "https://token.actions.githubusercontent.com"
}
diff --git a/blueprints/data-solutions/vertex-mlops/variables.tf b/blueprints/data-solutions/vertex-mlops/variables.tf
index f27318751..2819ca798 100644
--- a/blueprints/data-solutions/vertex-mlops/variables.tf
+++ b/blueprints/data-solutions/vertex-mlops/variables.tf
@@ -45,6 +45,12 @@ variable "groups" {
nullable = false
}
+variable "identity_pool_assertions" {
+ description = "Assertions to be used by Workload Identityf Federation on tokens, for example: assertion.repository_owner=='ORGANIZATION'."
+ type = string
+ default = null
+}
+
variable "identity_pool_claims" {
description = "Claims to be used by Workload Identity Federation (i.e.: attribute.repository/ORGANIZATION/REPO). If a not null value is provided, then google_iam_workload_identity_pool resource will be created."
type = string
diff --git a/modules/gcs/README.md b/modules/gcs/README.md
index 12a71ebf7..2964f73f8 100644
--- a/modules/gcs/README.md
+++ b/modules/gcs/README.md
@@ -311,7 +311,7 @@ module "bucket" {
|---|---|:---:|:---:|:---:|
| [location](variables.tf#L156) | Bucket location. | string | ✓ | |
| [name](variables.tf#L199) | Bucket name suffix. | string | ✓ | |
-| [project_id](variables.tf#L255) | Bucket project id. | string | ✓ | |
+| [project_id](variables.tf#L257) | Bucket project id. | string | ✓ | |
| [autoclass](variables.tf#L17) | Enable autoclass to automatically transition objects to appropriate storage classes based on their access pattern. If set to true, storage_class must be set to STANDARD. Defaults to false. | bool | | null |
| [cors](variables.tf#L23) | CORS configuration for the bucket. Defaults to null. | object({…}) | | null |
| [custom_placement_config](variables.tf#L34) | The bucket's custom location configuration, which specifies the individual regions that comprise a dual-region bucket. If the bucket is designated as REGIONAL or MULTI_REGIONAL, the parameters are empty. | list(string) | | null |
@@ -326,19 +326,19 @@ module "bucket" {
| [lifecycle_rules](variables.tf#L107) | Bucket lifecycle rule. | map(object({…})) | | {} |
| [logging_config](variables.tf#L162) | Bucket logging configuration. | object({…}) | | null |
| [managed_folders](variables.tf#L171) | Managed folders to create within the bucket in {PATH => CONFIG} format. | map(object({…})) | | {} |
-| [notification_config](variables.tf#L204) | GCS Notification configuration. | object({…}) | | null |
-| [objects_to_upload](variables.tf#L219) | Objects to be uploaded to bucket. | map(object({…})) | | {} |
-| [prefix](variables.tf#L245) | Optional prefix used to generate the bucket name. | string | | null |
-| [public_access_prevention](variables.tf#L260) | Prevents public access to the bucket. | string | | null |
-| [requester_pays](variables.tf#L270) | Enables Requester Pays on a storage bucket. | bool | | null |
-| [retention_policy](variables.tf#L276) | Bucket retention policy. | object({…}) | | null |
-| [rpo](variables.tf#L285) | Bucket recovery point objective. | string | | null |
-| [soft_delete_retention](variables.tf#L295) | The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Set to 0 to override the default and disable. | number | | null |
-| [storage_class](variables.tf#L301) | Bucket storage class. | string | | "STANDARD" |
-| [tag_bindings](variables.tf#L311) | Tag bindings for this folder, in key => tag value id format. | map(string) | | {} |
-| [uniform_bucket_level_access](variables.tf#L318) | Allow using object ACLs (false) or not (true, this is the recommended behavior) , defaults to true (which is the recommended practice, but not the behavior of storage API). | bool | | true |
-| [versioning](variables.tf#L324) | Enable versioning, defaults to false. | bool | | null |
-| [website](variables.tf#L330) | Bucket website. | object({…}) | | null |
+| [notification_config](variables.tf#L204) | GCS Notification configuration. | object({…}) | | null |
+| [objects_to_upload](variables.tf#L221) | Objects to be uploaded to bucket. | map(object({…})) | | {} |
+| [prefix](variables.tf#L247) | Optional prefix used to generate the bucket name. | string | | null |
+| [public_access_prevention](variables.tf#L262) | Prevents public access to the bucket. | string | | null |
+| [requester_pays](variables.tf#L272) | Enables Requester Pays on a storage bucket. | bool | | null |
+| [retention_policy](variables.tf#L278) | Bucket retention policy. | object({…}) | | null |
+| [rpo](variables.tf#L287) | Bucket recovery point objective. | string | | null |
+| [soft_delete_retention](variables.tf#L297) | The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Set to 0 to override the default and disable. | number | | null |
+| [storage_class](variables.tf#L303) | Bucket storage class. | string | | "STANDARD" |
+| [tag_bindings](variables.tf#L313) | Tag bindings for this folder, in key => tag value id format. | map(string) | | {} |
+| [uniform_bucket_level_access](variables.tf#L320) | Allow using object ACLs (false) or not (true, this is the recommended behavior) , defaults to true (which is the recommended practice, but not the behavior of storage API). | bool | | true |
+| [versioning](variables.tf#L326) | Enable versioning, defaults to false. | bool | | null |
+| [website](variables.tf#L332) | Bucket website. | object({…}) | | null |
## Outputs
diff --git a/modules/gcs/main.tf b/modules/gcs/main.tf
index aa4258a08..3c1a3ec6b 100644
--- a/modules/gcs/main.tf
+++ b/modules/gcs/main.tf
@@ -17,6 +17,7 @@
locals {
prefix = var.prefix == null ? "" : "${var.prefix}-"
notification = try(var.notification_config.enabled, false)
+ topic_create = try(var.notification_config.create_topic, null) != null
}
resource "google_storage_bucket" "bucket" {
@@ -172,14 +173,15 @@ resource "google_storage_notification" "notification" {
}
resource "google_pubsub_topic_iam_binding" "binding" {
- count = try(var.notification_config.create_topic, null) == true ? 1 : 0
+ count = local.topic_create ? 1 : 0
topic = google_pubsub_topic.topic[0].id
role = "roles/pubsub.publisher"
members = ["serviceAccount:${var.notification_config.sa_email}"]
}
resource "google_pubsub_topic" "topic" {
- count = try(var.notification_config.create_topic, null) == true ? 1 : 0
- project = var.project_id
- name = var.notification_config.topic_name
+ count = local.topic_create ? 1 : 0
+ project = var.project_id
+ name = var.notification_config.topic_name
+ kms_key_name = try(var.notification_config.topic_create.kms_key_id, null)
}
diff --git a/modules/gcs/variables.tf b/modules/gcs/variables.tf
index 49d9fb202..2c81dd169 100644
--- a/modules/gcs/variables.tf
+++ b/modules/gcs/variables.tf
@@ -204,11 +204,13 @@ variable "name" {
variable "notification_config" {
description = "GCS Notification configuration."
type = object({
- enabled = bool
- payload_format = string
- topic_name = string
- sa_email = string
- create_topic = optional(bool, true)
+ enabled = bool
+ payload_format = string
+ sa_email = string
+ topic_name = string
+ create_topic = optional(object({
+ kms_key_id = optional(string)
+ }))
event_types = optional(list(string))
custom_attributes = optional(map(string))
object_name_prefix = optional(string)
diff --git a/modules/spanner-instance/main.tf b/modules/spanner-instance/main.tf
index d35589ec1..26a8e3354 100644
--- a/modules/spanner-instance/main.tf
+++ b/modules/spanner-instance/main.tf
@@ -15,15 +15,21 @@
*/
locals {
- spanner_instance = var.instance_create ? google_spanner_instance.spanner_instance[0] : data.google_spanner_instance.spanner_instance[0]
+ spanner_instance = (
+ var.instance_create
+ ? google_spanner_instance.spanner_instance[0]
+ : data.google_spanner_instance.spanner_instance[0]
+ )
}
resource "google_spanner_instance_config" "spanner_instance_config" {
- count = try(var.instance.config.auto_create, null) == null ? 0 : 1
- name = var.instance.config.name
- project = var.project_id
- display_name = coalesce(var.instance.config.auto_create.display_name, var.instance.config.name)
- base_config = var.instance.config.auto_create.base_config
+ count = try(var.instance.config.auto_create, null) == null ? 0 : 1
+ name = var.instance.config.name
+ project = var.project_id
+ display_name = coalesce(
+ var.instance.config.auto_create.display_name, var.instance.config.name
+ )
+ base_config = var.instance.config.auto_create.base_config
dynamic "replicas" {
for_each = var.instance.config.auto_create.replicas
content {
@@ -42,9 +48,13 @@ data "google_spanner_instance" "spanner_instance" {
}
resource "google_spanner_instance" "spanner_instance" {
- count = var.instance_create ? 1 : 0
- project = var.project_id
- config = var.instance.config.auto_create == null ? var.instance.config.name : google_spanner_instance_config.spanner_instance_config[0].name
+ count = var.instance_create ? 1 : 0
+ project = var.project_id
+ config = (
+ var.instance.config.auto_create == null
+ ? var.instance.config.name
+ : google_spanner_instance_config.spanner_instance_config[0].name
+ )
name = var.instance.name
display_name = coalesce(var.instance.display_name, var.instance.name)
num_nodes = var.instance.num_nodes
@@ -64,8 +74,12 @@ resource "google_spanner_instance" "spanner_instance" {
dynamic "autoscaling_targets" {
for_each = var.instance.autoscaling.targets == null ? [] : [""]
content {
- high_priority_cpu_utilization_percent = var.instance.autoscaling.targets.high_priority_cpu_utilization_percent
- storage_utilization_percent = var.instance.autoscaling.targets.storage_utilization_percent
+ high_priority_cpu_utilization_percent = (
+ var.instance.autoscaling.targets.high_priority_cpu_utilization_percent
+ )
+ storage_utilization_percent = (
+ var.instance.autoscaling.targets.storage_utilization_percent
+ )
}
}
}