diff --git a/CHANGELOG.md b/CHANGELOG.md
index d7e09079d..10fd3fcf4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,9 @@ All notable changes to this project will be documented in this file.
### BLUEPRINTS
+- [[#2712](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2712)] Add hierarchical namespace support to GCS module ([juliocc](https://github.com/juliocc))
+- [[#2705](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2705)] Added outputs to apigee-x-foundations blueprint (PSC NEGs) ([apichick](https://github.com/apichick))
+- [[#2704](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2704)] Added outputs to apigee-x-foundations blueprint (instances and lbs) ([apichick](https://github.com/apichick))
- [[#2514](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2514)] New SecOps blueprints section and SecOps GKE Forwarder ([simonebruzzechesse](https://github.com/simonebruzzechesse))
- [[#2658](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2658)] Update service agents spec ([juliocc](https://github.com/juliocc))
- [[#2659](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2659)] Fix Vertex MLOps blueprint ([wiktorn](https://github.com/wiktorn))
@@ -15,11 +18,23 @@ All notable changes to this project will be documented in this file.
### FAST
+- [[#2715](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2715)] Allow setting GCS location default/override in project factory ([ludoo](https://github.com/ludoo))
+- [[#2640](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2640)] Add Automation Service Accounts Output ([joshw123](https://github.com/joshw123))
- [[#2681](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2681)] Keeping my contributor status :) ([drebes](https://github.com/drebes))
- [[#2680](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2680)] Swap groups_iam/iam_group for iam_by_principals in bootstrap README ([robrankin](https://github.com/robrankin))
### MODULES
+- [[#2715](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2715)] Allow setting GCS location default/override in project factory ([ludoo](https://github.com/ludoo))
+- [[#2689](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2689)] add GPU options to compute-vm module ([ooshrioo](https://github.com/ooshrioo))
+- [[#2712](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2712)] Add hierarchical namespace support to GCS module ([juliocc](https://github.com/juliocc))
+- [[#2711](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2711)] Allow providing network for Direct VPC access ([wiktorn](https://github.com/wiktorn))
+- [[#2640](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2640)] Add Automation Service Accounts Output ([joshw123](https://github.com/joshw123))
+- [[#2702](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2702)] Move direct vpc out of BETA ([wiktorn](https://github.com/wiktorn))
+- [[#2700](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2700)] Fix non-empty plan after mixing CloudSQL with other mounts ([wiktorn](https://github.com/wiktorn))
+- [[#2699](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2699)] Fix E2E tests ([wiktorn](https://github.com/wiktorn))
+- [[#2692](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2692)] Fix examples for GCS mount ([wiktorn](https://github.com/wiktorn))
+- [[#2687](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2687)] Fix initial user on secondary cluster issue ([simonebruzzechesse](https://github.com/simonebruzzechesse))
- [[#2686](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2686)] Fix gcs & NFS mounts for cloud-run-v2 service ([wiktorn](https://github.com/wiktorn))
- [[#2682](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2682)] Add support for service account in pubsub module bigquery subscriptions ([ludoo](https://github.com/ludoo))
- [[#2676](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2676)] Fix "inconsistent conditional result types" error in `modules/vpc-sc` ([joelvoss](https://github.com/joelvoss))
@@ -34,13 +49,6 @@ All notable changes to this project will be documented in this file.
- [[#2631](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2631)] fix Vertex-ML-Ops e2e tests ([wiktorn](https://github.com/wiktorn))
- [[#2653](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2653)] Add required enabled field introduced in Terraform version 5.41.0 ([jacobmammoliti](https://github.com/jacobmammoliti))
-## [36.0.0-rc1] - 2024-10-31
-
-### FAST
-
-- [[#2649](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2649)] Final fixes for v36.0.0-rc1 ([ludoo](https://github.com/ludoo))
-- [[#2648](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/2648)] **incompatible change:** Refactor of FAST resource management and subsequent stages ([ludoo](https://github.com/ludoo))
-
## [35.0.0] - 2024-10-30
@@ -2571,7 +2579,6 @@ All notable changes to this project will be documented in this file.
[Unreleased]: https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/compare/v35.0.0...HEAD
-[36.0.0-rc1]: https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/compare/v35.0.0...v36.0.0-rc1
[35.0.0]: https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/compare/v34.1.0...v35.0.0
[34.1.0]: https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/compare/v34.0.0...v34.1.0
[34.0.0]: https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/compare/v33.0.0...v34.0.0
@@ -2655,4 +2662,4 @@ All notable changes to this project will be documented in this file.
[1.3.0]: https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/compare/v1.0.0...v1.1.0
-[1.0.0]: https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/compare/v0.1...v1.0.0
\ No newline at end of file
+[1.0.0]: https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/compare/v0.1...v1.0.0
diff --git a/blueprints/cloud-operations/unmanaged-instances-healthcheck/main.tf b/blueprints/cloud-operations/unmanaged-instances-healthcheck/main.tf
index 65aae68c9..33c6654e6 100644
--- a/blueprints/cloud-operations/unmanaged-instances-healthcheck/main.tf
+++ b/blueprints/cloud-operations/unmanaged-instances-healthcheck/main.tf
@@ -172,6 +172,7 @@ module "cf-healthchecker" {
vpc_connector_config = {
ip_cidr_range = "10.132.0.0/28"
network = "vpc"
+ instances = {}
}
iam = {
"roles/cloudfunctions.invoker" = [module.service-account-scheduler.iam_email]
diff --git a/fast/stages/2-project-factory/README.md b/fast/stages/2-project-factory/README.md
index fd7b49211..159fa54fd 100644
--- a/fast/stages/2-project-factory/README.md
+++ b/fast/stages/2-project-factory/README.md
@@ -354,13 +354,14 @@ The approach is not shown here but reasonably easy to implement. The main projec
| name | description | type | required | default | producer |
|---|---|:---:|:---:|:---:|:---:|
| [billing_account](variables-fast.tf#L17) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap |
-| [prefix](variables-fast.tf#L55) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap |
+| [prefix](variables-fast.tf#L65) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap |
| [factories_config](variables.tf#L17) | Configuration for YAML-based factories. | object({…}) | | {} | |
| [folder_ids](variables-fast.tf#L30) | Folders created in the resource management stage. | map(string) | | {} | 1-resman |
| [groups](variables-fast.tf#L38) | Group names or IAM-format principals to grant organization-level permissions. If just the name is provided, the 'group:' principal and organization domain are interpolated. | map(string) | | {} | 0-bootstrap |
| [host_project_ids](variables-fast.tf#L47) | Host project for the shared VPC. | map(string) | | {} | 2-networking |
-| [service_accounts](variables-fast.tf#L65) | Automation service accounts in name => email format. | map(string) | | {} | 1-resman |
-| [tag_values](variables-fast.tf#L73) | FAST-managed resource manager tag values. | map(string) | | {} | 1-resman |
+| [locations](variables-fast.tf#L55) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | 0-bootstrap |
+| [service_accounts](variables-fast.tf#L75) | Automation service accounts in name => email format. | map(string) | | {} | 1-resman |
+| [tag_values](variables-fast.tf#L83) | FAST-managed resource manager tag values. | map(string) | | {} | 1-resman |
## Outputs
diff --git a/fast/stages/2-project-factory/main.tf b/fast/stages/2-project-factory/main.tf
index 0ec6053d3..12fd9f2bd 100644
--- a/fast/stages/2-project-factory/main.tf
+++ b/fast/stages/2-project-factory/main.tf
@@ -20,7 +20,8 @@ module "projects" {
source = "../../../modules/project-factory"
data_defaults = {
# more defaults are available, check the project factory variables
- billing_account = var.billing_account.id
+ billing_account = var.billing_account.id
+ storage_location = var.locations.gcs
}
data_merges = {
services = [
diff --git a/fast/stages/2-project-factory/variables-fast.tf b/fast/stages/2-project-factory/variables-fast.tf
index 9b4c11807..39aac8e46 100644
--- a/fast/stages/2-project-factory/variables-fast.tf
+++ b/fast/stages/2-project-factory/variables-fast.tf
@@ -52,6 +52,16 @@ variable "host_project_ids" {
default = {}
}
+variable "locations" {
+ # tfdoc:variable:source 0-bootstrap
+ description = "Optional locations for GCS, BigQuery, and logging buckets created here."
+ type = object({
+ gcs = optional(string)
+ })
+ nullable = false
+ default = {}
+}
+
variable "prefix" {
# tfdoc:variable:source 0-bootstrap
description = "Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants."
diff --git a/modules/certificate-manager/README.md b/modules/certificate-manager/README.md
index e878609f9..8d1feb950 100644
--- a/modules/certificate-manager/README.md
+++ b/modules/certificate-manager/README.md
@@ -246,11 +246,11 @@ module "certificate-manager" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [project_id](variables.tf#L102) | Project id. | string | ✓ | |
+| [project_id](variables.tf#L103) | Project id. | string | ✓ | |
| [certificates](variables.tf#L17) | Certificates. | map(object({…})) | | {} |
| [dns_authorizations](variables.tf#L53) | DNS authorizations. | map(object({…})) | | {} |
-| [issuance_configs](variables.tf#L66) | Issuance configs. | map(object({…})) | | {} |
-| [map](variables.tf#L80) | Map attributes. | object({…}) | | null |
+| [issuance_configs](variables.tf#L66) | Issuance configs. | map(object({…})) | | {} |
+| [map](variables.tf#L81) | Map attributes. | object({…}) | | null |
## Outputs
diff --git a/modules/certificate-manager/main.tf b/modules/certificate-manager/main.tf
index c990fe852..9b1e7a7b9 100644
--- a/modules/certificate-manager/main.tf
+++ b/modules/certificate-manager/main.tf
@@ -47,7 +47,7 @@ resource "google_certificate_manager_certificate" "certificates" {
content {
domains = each.value.managed.domains
dns_authorizations = each.value.managed.dns_authorizations
- issuance_config = each.value.managed.issuance_config
+ issuance_config = try(google_certificate_manager_certificate_issuance_config.default[each.value.managed.issuance_config].id, null)
}
}
dynamic "self_managed" {
@@ -80,6 +80,7 @@ resource "google_certificate_manager_certificate_issuance_config" "default" {
}
}
lifetime = each.value.lifetime
+ location = each.value.location
rotation_window_percentage = each.value.rotation_window_percentage
key_algorithm = each.value.key_algorithm
labels = each.value.labels
diff --git a/modules/certificate-manager/variables.tf b/modules/certificate-manager/variables.tf
index 05a8f5148..d70169278 100644
--- a/modules/certificate-manager/variables.tf
+++ b/modules/certificate-manager/variables.tf
@@ -71,6 +71,7 @@ variable "issuance_configs" {
key_algorithm = string
labels = optional(map(string), {})
lifetime = string
+ location = optional(string)
rotation_window_percentage = number
}))
default = {}
diff --git a/modules/cloud-function-v1/README.md b/modules/cloud-function-v1/README.md
index b63982e38..ca7f78c16 100644
--- a/modules/cloud-function-v1/README.md
+++ b/modules/cloud-function-v1/README.md
@@ -399,7 +399,7 @@ module "cf-http" {
| [service_account_create](variables.tf#L194) | Auto-create service account. | bool | | false |
| [trigger_config](variables.tf#L200) | Function trigger configuration. Leave null for HTTP trigger. | object({…}) | | null |
| [vpc_connector](variables.tf#L210) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | null |
-| [vpc_connector_config](variables.tf#L220) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null |
+| [vpc_connector_config](variables.tf#L220) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null |
## Outputs
diff --git a/modules/cloud-function-v1/main.tf b/modules/cloud-function-v1/main.tf
index 073f46b3c..e51ded541 100644
--- a/modules/cloud-function-v1/main.tf
+++ b/modules/cloud-function-v1/main.tf
@@ -42,12 +42,16 @@ locals {
}
resource "google_vpc_access_connector" "connector" {
- count = try(var.vpc_connector.create, false) == false ? 0 : 1
- project = var.project_id
- name = var.vpc_connector.name
- region = var.region
- ip_cidr_range = var.vpc_connector_config.ip_cidr_range
- network = var.vpc_connector_config.network
+ count = try(var.vpc_connector.create, false) == true ? 1 : 0
+ project = var.project_id
+ name = var.vpc_connector.name
+ region = var.region
+ ip_cidr_range = var.vpc_connector_config.ip_cidr_range
+ network = var.vpc_connector_config.network
+ max_instances = try(var.vpc_connector_config.instances.max, null)
+ min_instances = try(var.vpc_connector_config.instances.min, null)
+ max_throughput = try(var.vpc_connector_config.throughput.max, null)
+ min_throughput = try(var.vpc_connector_config.throughput.min, null)
}
resource "google_cloudfunctions_function" "function" {
diff --git a/modules/cloud-function-v1/variables.tf b/modules/cloud-function-v1/variables.tf
index d29d5e0cd..98f1f10af 100644
--- a/modules/cloud-function-v1/variables.tf
+++ b/modules/cloud-function-v1/variables.tf
@@ -222,6 +222,22 @@ variable "vpc_connector_config" {
type = object({
ip_cidr_range = string
network = string
+ instances = optional(object({
+ max = optional(number)
+ min = optional(number, 2)
+ }))
+ throughput = optional(object({
+ max = optional(number, 300)
+ min = optional(number, 200)
+ }))
})
default = null
+ validation {
+ condition = (
+ var.vpc_connector_config == null ||
+ try(var.vpc_connector_config.instances, null) != null ||
+ try(var.vpc_connector_config.throughput, null) != null
+ )
+ error_message = "VPC connector must specify either instances or throughput."
+ }
}
diff --git a/modules/cloud-function-v2/README.md b/modules/cloud-function-v2/README.md
index 0fc90148c..2e6c08ce5 100644
--- a/modules/cloud-function-v2/README.md
+++ b/modules/cloud-function-v2/README.md
@@ -332,7 +332,7 @@ module "cf-http" {
| [service_account_create](variables.tf#L191) | Auto-create service account. | bool | | false |
| [trigger_config](variables.tf#L197) | Function trigger configuration. Leave null for HTTP trigger. | object({…}) | | null |
| [vpc_connector](variables.tf#L215) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | object({…}) | | null |
-| [vpc_connector_config](variables.tf#L225) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null |
+| [vpc_connector_config](variables.tf#L225) | VPC connector network configuration. Must be provided if new VPC connector is being created. | object({…}) | | null |
## Outputs
diff --git a/modules/cloud-function-v2/main.tf b/modules/cloud-function-v2/main.tf
index 672591d4d..691720106 100644
--- a/modules/cloud-function-v2/main.tf
+++ b/modules/cloud-function-v2/main.tf
@@ -50,12 +50,16 @@ locals {
}
resource "google_vpc_access_connector" "connector" {
- count = try(var.vpc_connector.create, false) == true ? 1 : 0
- project = var.project_id
- name = var.vpc_connector.name
- region = var.region
- ip_cidr_range = var.vpc_connector_config.ip_cidr_range
- network = var.vpc_connector_config.network
+ count = try(var.vpc_connector.create, false) == true ? 1 : 0
+ project = var.project_id
+ name = var.vpc_connector.name
+ region = var.region
+ ip_cidr_range = var.vpc_connector_config.ip_cidr_range
+ network = var.vpc_connector_config.network
+ max_instances = try(var.vpc_connector_config.instances.max, null)
+ min_instances = try(var.vpc_connector_config.instances.min, null)
+ max_throughput = try(var.vpc_connector_config.throughput.max, null)
+ min_throughput = try(var.vpc_connector_config.throughput.min, null)
}
resource "google_cloudfunctions2_function" "function" {
diff --git a/modules/cloud-function-v2/variables.tf b/modules/cloud-function-v2/variables.tf
index c960aad75..f51ba347d 100644
--- a/modules/cloud-function-v2/variables.tf
+++ b/modules/cloud-function-v2/variables.tf
@@ -227,6 +227,22 @@ variable "vpc_connector_config" {
type = object({
ip_cidr_range = string
network = string
+ instances = optional(object({
+ max = optional(number)
+ min = optional(number, 2)
+ }))
+ throughput = optional(object({
+ max = optional(number, 300)
+ min = optional(number, 200)
+ }))
})
default = null
+ validation {
+ condition = (
+ var.vpc_connector_config == null ||
+ try(var.vpc_connector_config.instances, null) != null ||
+ try(var.vpc_connector_config.throughput, null) != null
+ )
+ error_message = "VPC connector must specify either instances or throughput."
+ }
}
diff --git a/modules/cloudsql-instance/README.md b/modules/cloudsql-instance/README.md
index 50c59cca7..b4fc40cc1 100644
--- a/modules/cloudsql-instance/README.md
+++ b/modules/cloudsql-instance/README.md
@@ -371,7 +371,7 @@ module "db" {
| [network_config](variables.tf#L184) | Network configuration for the instance. Only one between private_network and psc_config can be used. | object({…}) | ✓ | |
| [project_id](variables.tf#L217) | The ID of the project where this instances will be created. | string | ✓ | |
| [region](variables.tf#L222) | Region of the primary instance. | string | ✓ | |
-| [tier](variables.tf#L264) | The machine type to use for the instances. | string | ✓ | |
+| [tier](variables.tf#L265) | The machine type to use for the instances. | string | ✓ | |
| [activation_policy](variables.tf#L16) | This variable specifies when the instance should be active. Can be either ALWAYS, NEVER or ON_DEMAND. Default is ALWAYS. | string | | "ALWAYS" |
| [availability_type](variables.tf#L27) | Availability type for the primary replica. Either `ZONAL` or `REGIONAL`. | string | | "ZONAL" |
| [backup_configuration](variables.tf#L33) | Backup settings for primary instance. Will be automatically enabled if using MySQL with one or more replicas. | object({…}) | | {…} |
@@ -391,11 +391,11 @@ module "db" {
| [maintenance_config](variables.tf#L146) | Set maintenance window configuration and maintenance deny period (up to 90 days). Date format: 'yyyy-mm-dd'. | object({…}) | | {} |
| [prefix](variables.tf#L207) | Optional prefix used to generate instance names. | string | | null |
| [replicas](variables.tf#L227) | Map of NAME=> {REGION, KMS_KEY} for additional read replicas. Set to null to disable replica creation. | map(object({…})) | | {} |
-| [root_password](variables.tf#L236) | Root password of the Cloud SQL instance. Required for MS SQL Server. | string | | null |
-| [ssl](variables.tf#L242) | Setting to enable SSL, set config and certificates. | object({…}) | | {} |
-| [terraform_deletion_protection](variables.tf#L257) | Prevent terraform from deleting instances. | bool | | true |
-| [time_zone](variables.tf#L269) | The time_zone to be used by the database engine (supported only for SQL Server), in SQL Server timezone format. | string | | null |
-| [users](variables.tf#L275) | Map of users to create in the primary instance (and replicated to other replicas). For MySQL, anything after the first `@` (if present) will be used as the user's host. Set PASSWORD to null if you want to get an autogenerated password. The user types available are: 'BUILT_IN', 'CLOUD_IAM_USER' or 'CLOUD_IAM_SERVICE_ACCOUNT'. | map(object({…})) | | null |
+| [root_password](variables.tf#L237) | Root password of the Cloud SQL instance. Required for MS SQL Server. | string | | null |
+| [ssl](variables.tf#L243) | Setting to enable SSL, set config and certificates. | object({…}) | | {} |
+| [terraform_deletion_protection](variables.tf#L258) | Prevent terraform from deleting instances. | bool | | true |
+| [time_zone](variables.tf#L270) | The time_zone to be used by the database engine (supported only for SQL Server), in SQL Server timezone format. | string | | null |
+| [users](variables.tf#L276) | Map of users to create in the primary instance (and replicated to other replicas). For MySQL, anything after the first `@` (if present) will be used as the user's host. Set PASSWORD to null if you want to get an autogenerated password. The user types available are: 'BUILT_IN', 'CLOUD_IAM_USER' or 'CLOUD_IAM_SERVICE_ACCOUNT'. | map(object({…})) | | null |
## Outputs
diff --git a/modules/cloudsql-instance/main.tf b/modules/cloudsql-instance/main.tf
index 52f6ea516..eeb2b4021 100644
--- a/modules/cloudsql-instance/main.tf
+++ b/modules/cloudsql-instance/main.tf
@@ -18,7 +18,7 @@ locals {
prefix = var.prefix == null ? "" : "${var.prefix}-"
is_mysql = can(regex("^MYSQL", var.database_version))
is_postgres = can(regex("^POSTGRES", var.database_version))
- has_replicas = try(length(var.replicas) > 0, false)
+ has_replicas = length(var.replicas) > 0
is_regional = var.availability_type == "REGIONAL" ? true : false
// Enable backup if the user asks for it or if the user is deploying
@@ -30,15 +30,15 @@ locals {
k =>
local.is_mysql ?
{
- name = try(v.type, "BUILT_IN") == "BUILT_IN" ? split("@", k)[0] : k
- host = try(v.type, "BUILT_IN") == "BUILT_IN" ? try(split("@", k)[1], null) : null
- password = try(v.type, "BUILT_IN") == "BUILT_IN" ? try(random_password.passwords[k].result, v.password) : null
- type = try(v.type, "BUILT_IN")
+ name = coalesce(v.type, "BUILT_IN") == "BUILT_IN" ? split("@", k)[0] : k
+ host = coalesce(v.type, "BUILT_IN") == "BUILT_IN" ? try(split("@", k)[1], null) : null
+ password = coalesce(v.type, "BUILT_IN") == "BUILT_IN" ? try(random_password.passwords[k].result, v.password) : null
+ type = coalesce(v.type, "BUILT_IN")
} : {
name = local.is_postgres ? try(trimsuffix(k, ".gserviceaccount.com"), k) : k
host = null
- password = try(v.type, "BUILT_IN") == "BUILT_IN" ? try(random_password.passwords[k].result, v.password) : null
- type = try(v.type, "BUILT_IN")
+ password = coalesce(v.type, "BUILT_IN") == "BUILT_IN" ? try(random_password.passwords[k].result, v.password) : null
+ type = coalesce(v.type, "BUILT_IN")
}
}
diff --git a/modules/cloudsql-instance/variables.tf b/modules/cloudsql-instance/variables.tf
index 83fd8dcff..b1590dc6c 100644
--- a/modules/cloudsql-instance/variables.tf
+++ b/modules/cloudsql-instance/variables.tf
@@ -230,7 +230,8 @@ variable "replicas" {
region = string
encryption_key_name = optional(string)
}))
- default = {}
+ default = {}
+ nullable = false
}
variable "root_password" {
diff --git a/modules/compute-vm/README.md b/modules/compute-vm/README.md
index f934066fb..0942db0ee 100644
--- a/modules/compute-vm/README.md
+++ b/modules/compute-vm/README.md
@@ -850,10 +850,10 @@ module "sole-tenancy" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L235) | Instance name. | string | ✓ | |
-| [network_interfaces](variables.tf#L247) | Network interfaces configuration. Use self links for Shared VPC, set addresses to null if not needed. | list(object({…})) | ✓ | |
-| [project_id](variables.tf#L293) | Project id. | string | ✓ | |
-| [zone](variables.tf#L391) | Compute zone. | string | ✓ | |
+| [name](variables.tf#L264) | Instance name. | string | ✓ | |
+| [network_interfaces](variables.tf#L276) | Network interfaces configuration. Use self links for Shared VPC, set addresses to null if not needed. | list(object({…})) | ✓ | |
+| [project_id](variables.tf#L322) | Project id. | string | ✓ | |
+| [zone](variables.tf#L420) | Compute zone. | string | ✓ | |
| [attached_disk_defaults](variables.tf#L17) | Defaults for attached disks options. | object({…}) | | {…} |
| [attached_disks](variables.tf#L37) | Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null. | list(object({…})) | | [] |
| [boot_disk](variables.tf#L83) | Boot disk properties. | object({…}) | | {…} |
@@ -863,23 +863,24 @@ module "sole-tenancy" {
| [description](variables.tf#L134) | Description of a Compute Instance. | string | | "Managed by the compute-vm Terraform module." |
| [enable_display](variables.tf#L140) | Enable virtual display on the instances. | bool | | false |
| [encryption](variables.tf#L146) | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | object({…}) | | null |
-| [group](variables.tf#L156) | Define this variable to create an instance group for instances. Disabled for template use. | object({…}) | | null |
-| [hostname](variables.tf#L164) | Instance FQDN name. | string | | null |
-| [iam](variables.tf#L170) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
-| [instance_schedule](variables.tf#L176) | Assign or create and assign an instance schedule policy. Either resource policy id or create_config must be specified if not null. Set active to null to dtach a policy from vm before destroying. | object({…}) | | null |
-| [instance_type](variables.tf#L211) | Instance type. | string | | "f1-micro" |
-| [labels](variables.tf#L217) | Instance labels. | map(string) | | {} |
-| [metadata](variables.tf#L223) | Instance metadata. | map(string) | | {} |
-| [min_cpu_platform](variables.tf#L229) | Minimum CPU platform. | string | | null |
-| [network_attached_interfaces](variables.tf#L240) | Network interfaces using network attachments. | list(string) | | [] |
-| [options](variables.tf#L263) | Instance options. | object({…}) | | {…} |
-| [scratch_disks](variables.tf#L298) | Scratch disks configuration. | object({…}) | | {…} |
-| [service_account](variables.tf#L310) | Service account email and scopes. If email is null, the default Compute service account will be used unless auto_create is true, in which case a service account will be created. Set the variable to null to avoid attaching a service account. | object({…}) | | {} |
-| [shielded_config](variables.tf#L320) | Shielded VM configuration of the instances. | object({…}) | | null |
-| [snapshot_schedules](variables.tf#L330) | Snapshot schedule resource policies that can be attached to disks. | map(object({…})) | | {} |
-| [tag_bindings](variables.tf#L373) | Resource manager tag bindings for this instance, in tag key => tag value format. | map(string) | | null |
-| [tag_bindings_firewall](variables.tf#L379) | Firewall (network scoped) tag bindings for this instance, in tag key => tag value format. | map(string) | | null |
-| [tags](variables.tf#L385) | Instance network tags for firewall rule targets. | list(string) | | [] |
+| [gpu](variables.tf#L156) | GPU information. Based on https://cloud.google.com/compute/docs/gpus. | object({…}) | | null |
+| [group](variables.tf#L185) | Define this variable to create an instance group for instances. Disabled for template use. | object({…}) | | null |
+| [hostname](variables.tf#L193) | Instance FQDN name. | string | | null |
+| [iam](variables.tf#L199) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
+| [instance_schedule](variables.tf#L205) | Assign or create and assign an instance schedule policy. Either resource policy id or create_config must be specified if not null. Set active to null to dtach a policy from vm before destroying. | object({…}) | | null |
+| [instance_type](variables.tf#L240) | Instance type. | string | | "f1-micro" |
+| [labels](variables.tf#L246) | Instance labels. | map(string) | | {} |
+| [metadata](variables.tf#L252) | Instance metadata. | map(string) | | {} |
+| [min_cpu_platform](variables.tf#L258) | Minimum CPU platform. | string | | null |
+| [network_attached_interfaces](variables.tf#L269) | Network interfaces using network attachments. | list(string) | | [] |
+| [options](variables.tf#L292) | Instance options. | object({…}) | | {…} |
+| [scratch_disks](variables.tf#L327) | Scratch disks configuration. | object({…}) | | {…} |
+| [service_account](variables.tf#L339) | Service account email and scopes. If email is null, the default Compute service account will be used unless auto_create is true, in which case a service account will be created. Set the variable to null to avoid attaching a service account. | object({…}) | | {} |
+| [shielded_config](variables.tf#L349) | Shielded VM configuration of the instances. | object({…}) | | null |
+| [snapshot_schedules](variables.tf#L359) | Snapshot schedule resource policies that can be attached to disks. | map(object({…})) | | {} |
+| [tag_bindings](variables.tf#L402) | Resource manager tag bindings for this instance, in tag key => tag value format. | map(string) | | null |
+| [tag_bindings_firewall](variables.tf#L408) | Firewall (network scoped) tag bindings for this instance, in tag key => tag value format. | map(string) | | null |
+| [tags](variables.tf#L414) | Instance network tags for firewall rule targets. | list(string) | | [] |
## Outputs
diff --git a/modules/compute-vm/main.tf b/modules/compute-vm/main.tf
index a5a3295d0..56adefae3 100644
--- a/modules/compute-vm/main.tf
+++ b/modules/compute-vm/main.tf
@@ -30,11 +30,12 @@ locals {
k => v if try(v.options.replica_zone, null) == null
}
on_host_maintenance = (
- var.options.spot || var.confidential_compute
+ var.options.spot || var.confidential_compute || local.gpu
? "TERMINATE"
: "MIGRATE"
)
region = join("-", slice(split("-", var.zone), 0, 2))
+ gpu = var.gpu != null
service_account = var.service_account == null ? null : {
email = (
var.service_account.auto_create
@@ -333,6 +334,14 @@ resource "google_compute_instance" "default" {
resource_manager_tags = local.tags_combined
}
}
+
+ dynamic "guest_accelerator" {
+ for_each = local.gpu ? [var.gpu] : []
+ content {
+ type = guest_accelerator.value.type
+ count = guest_accelerator.value.count
+ }
+ }
}
resource "google_compute_instance_iam_binding" "default" {
@@ -376,6 +385,13 @@ resource "google_compute_instance_template" "default" {
}
}
+ dynamic "guest_accelerator" {
+ for_each = local.gpu ? [var.gpu] : []
+ content {
+ type = guest_accelerator.value.type
+ count = guest_accelerator.value.count
+ }
+ }
dynamic "disk" {
for_each = local.attached_disks
iterator = config
diff --git a/modules/compute-vm/variables.tf b/modules/compute-vm/variables.tf
index d11e00ec8..8d6e8bc37 100644
--- a/modules/compute-vm/variables.tf
+++ b/modules/compute-vm/variables.tf
@@ -153,6 +153,35 @@ variable "encryption" {
default = null
}
+variable "gpu" {
+ description = "GPU information. Based on https://cloud.google.com/compute/docs/gpus."
+ type = object({
+ count = number
+ type = string
+ })
+ default = null
+
+ validation {
+ condition = (
+ var.gpu == null ||
+ contains(
+ [
+ "nvidia-tesla-a100",
+ "nvidia-tesla-p100",
+ "nvidia-tesla-v100",
+ "nvidia-tesla-k80",
+ "nvidia-tesla-p4",
+ "nvidia-tesla-t4",
+ "nvidia-l4",
+ "nvidia-a2"
+ ],
+ try(var.gpu.type, "-")
+ )
+ )
+ error_message = "GPU type must be one of the allowed values: nvidia-tesla-a100, nvidia-tesla-p100, nvidia-tesla-v100, nvidia-tesla-k80, nvidia-tesla-p4, nvidia-tesla-t4, nvidia-l4, nvidia-a2."
+ }
+}
+
variable "group" {
description = "Define this variable to create an instance group for instances. Disabled for template use."
type = object({
@@ -392,3 +421,5 @@ variable "zone" {
description = "Compute zone."
type = string
}
+
+
diff --git a/modules/gke-cluster-autopilot/README.md b/modules/gke-cluster-autopilot/README.md
index 708f68fce..44bfe86d0 100644
--- a/modules/gke-cluster-autopilot/README.md
+++ b/modules/gke-cluster-autopilot/README.md
@@ -208,8 +208,8 @@ module "cluster-1" {
|---|---|:---:|:---:|:---:|
| [location](variables.tf#L117) | Autopilot clusters are always regional. | string | ✓ | |
| [name](variables.tf#L194) | Cluster name. | string | ✓ | |
-| [project_id](variables.tf#L230) | Cluster project ID. | string | ✓ | |
-| [vpc_config](variables.tf#L246) | VPC-level configuration. | object({…}) | ✓ | |
+| [project_id](variables.tf#L239) | Cluster project ID. | string | ✓ | |
+| [vpc_config](variables.tf#L255) | VPC-level configuration. | object({…}) | ✓ | |
| [backup_configs](variables.tf#L17) | Configuration for Backup for GKE. | object({…}) | | {} |
| [deletion_protection](variables.tf#L38) | Whether or not to allow Terraform to destroy the cluster. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the cluster will fail. | bool | | true |
| [description](variables.tf#L45) | Cluster description. | string | | null |
@@ -221,10 +221,10 @@ module "cluster-1" {
| [maintenance_config](variables.tf#L133) | Maintenance window configuration. | object({…}) | | {…} |
| [min_master_version](variables.tf#L156) | Minimum version of the master, defaults to the version of the most recent official release. | string | | null |
| [monitoring_config](variables.tf#L162) | Monitoring configuration. System metrics collection cannot be disabled. Control plane metrics are optional. Kube state metrics are optional. Google Cloud Managed Service for Prometheus is enabled by default. | object({…}) | | {} |
-| [node_config](variables.tf#L199) | Configuration for nodes and nodepools. | object({…}) | | {} |
-| [node_locations](variables.tf#L209) | Zones in which the cluster's nodes are located. | list(string) | | [] |
-| [private_cluster_config](variables.tf#L216) | Private cluster configuration. | object({…}) | | null |
-| [release_channel](variables.tf#L235) | Release channel for GKE upgrades. Clusters created in the Autopilot mode must use a release channel. Choose between \"RAPID\", \"REGULAR\", and \"STABLE\". | string | | "REGULAR" |
+| [node_config](variables.tf#L199) | Configuration for nodes and nodepools. | object({…}) | | {} |
+| [node_locations](variables.tf#L218) | Zones in which the cluster's nodes are located. | list(string) | | [] |
+| [private_cluster_config](variables.tf#L225) | Private cluster configuration. | object({…}) | | null |
+| [release_channel](variables.tf#L244) | Release channel for GKE upgrades. Clusters created in the Autopilot mode must use a release channel. Choose between \"RAPID\", \"REGULAR\", and \"STABLE\". | string | | "REGULAR" |
## Outputs
diff --git a/modules/gke-cluster-autopilot/variables.tf b/modules/gke-cluster-autopilot/variables.tf
index da342e027..679ded6ec 100644
--- a/modules/gke-cluster-autopilot/variables.tf
+++ b/modules/gke-cluster-autopilot/variables.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2023 Google LLC
+ * Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -199,11 +199,20 @@ variable "name" {
variable "node_config" {
description = "Configuration for nodes and nodepools."
type = object({
- boot_disk_kms_key = optional(string)
- service_account = optional(string)
- tags = optional(list(string))
+ boot_disk_kms_key = optional(string)
+ service_account = optional(string)
+ tags = optional(list(string))
+ workload_metadata_config_mode = optional(string)
})
- default = {}
+ default = {}
+ nullable = false
+ validation {
+ condition = contains(
+ ["GCE_METADATA", "GKE_METADATA", "null"],
+ coalesce(var.node_config.workload_metadata_config_mode, "null")
+ )
+ error_message = "node_config.workload_metadata_config_mode must be GCE_METADATA or GKE_METADATA."
+ }
}
variable "node_locations" {
diff --git a/modules/gke-cluster-standard/README.md b/modules/gke-cluster-standard/README.md
index beebe43c7..00764e85f 100644
--- a/modules/gke-cluster-standard/README.md
+++ b/modules/gke-cluster-standard/README.md
@@ -354,8 +354,8 @@ module "cluster-1" {
|---|---|:---:|:---:|:---:|
| [location](variables.tf#L242) | Cluster zone or region. | string | ✓ | |
| [name](variables.tf#L354) | Cluster name. | string | ✓ | |
-| [project_id](variables.tf#L393) | Cluster project id. | string | ✓ | |
-| [vpc_config](variables.tf#L404) | VPC-level configuration. | object({…}) | ✓ | |
+| [project_id](variables.tf#L401) | Cluster project id. | string | ✓ | |
+| [vpc_config](variables.tf#L412) | VPC-level configuration. | object({…}) | ✓ | |
| [backup_configs](variables.tf#L18) | Configuration for Backup for GKE. | object({…}) | | {} |
| [cluster_autoscaling](variables.tf#L40) | Enable and configure limits for Node Auto-Provisioning with Cluster Autoscaler. | object({…}) | | null |
| [default_nodepool](variables.tf#L119) | Enable default nodepool. | object({…}) | | {} |
@@ -370,10 +370,10 @@ module "cluster-1" {
| [max_pods_per_node](variables.tf#L291) | Maximum number of pods per node in this cluster. | number | | 110 |
| [min_master_version](variables.tf#L297) | Minimum version of the master, defaults to the version of the most recent official release. | string | | null |
| [monitoring_config](variables.tf#L303) | Monitoring configuration. Google Cloud Managed Service for Prometheus is enabled by default. | object({…}) | | {} |
-| [node_config](variables.tf#L359) | Node-level configuration. | object({…}) | | {} |
-| [node_locations](variables.tf#L372) | Zones in which the cluster's nodes are located. | list(string) | | [] |
-| [private_cluster_config](variables.tf#L379) | Private cluster configuration. | object({…}) | | null |
-| [release_channel](variables.tf#L398) | Release channel for GKE upgrades. | string | | null |
+| [node_config](variables.tf#L359) | Node-level configuration. | object({…}) | | {} |
+| [node_locations](variables.tf#L380) | Zones in which the cluster's nodes are located. | list(string) | | [] |
+| [private_cluster_config](variables.tf#L387) | Private cluster configuration. | object({…}) | | null |
+| [release_channel](variables.tf#L406) | Release channel for GKE upgrades. | string | | null |
## Outputs
diff --git a/modules/gke-cluster-standard/main.tf b/modules/gke-cluster-standard/main.tf
index 835ee85c5..b864af0ae 100644
--- a/modules/gke-cluster-standard/main.tf
+++ b/modules/gke-cluster-standard/main.tf
@@ -71,6 +71,12 @@ resource "google_container_cluster" "cluster" {
enable_integrity_monitoring = true
}
}
+ dynamic "workload_metadata_config" {
+ for_each = var.node_config.workload_metadata_config_mode != null ? [""] : []
+ content {
+ mode = var.node_config.workload_metadata_config_mode
+ }
+ }
}
# gcfs_config deactivation need the block to be defined so it can't be dynamic
node_pool_defaults {
diff --git a/modules/gke-cluster-standard/variables.tf b/modules/gke-cluster-standard/variables.tf
index 33452039f..dd49550fd 100644
--- a/modules/gke-cluster-standard/variables.tf
+++ b/modules/gke-cluster-standard/variables.tf
@@ -359,14 +359,22 @@ variable "name" {
variable "node_config" {
description = "Node-level configuration."
type = object({
- boot_disk_kms_key = optional(string)
- k8s_labels = optional(map(string))
- labels = optional(map(string))
- service_account = optional(string)
- tags = optional(list(string))
+ boot_disk_kms_key = optional(string)
+ k8s_labels = optional(map(string))
+ labels = optional(map(string))
+ service_account = optional(string)
+ tags = optional(list(string))
+ workload_metadata_config_mode = optional(string)
})
default = {}
nullable = false
+ validation {
+ condition = contains(
+ ["GCE_METADATA", "GKE_METADATA", "null"],
+ coalesce(var.node_config.workload_metadata_config_mode, "null")
+ )
+ error_message = "node_config.workload_metadata_config_mode must be GCE_METADATA or GKE_METADATA."
+ }
}
variable "node_locations" {
diff --git a/modules/gke-nodepool/README.md b/modules/gke-nodepool/README.md
index 002bd832e..f83ee0360 100644
--- a/modules/gke-nodepool/README.md
+++ b/modules/gke-nodepool/README.md
@@ -191,23 +191,23 @@ module "cluster-1-nodepool-dws" {
|---|---|:---:|:---:|:---:|
| [cluster_name](variables.tf#L23) | Cluster name. | string | ✓ | |
| [location](variables.tf#L48) | Cluster location. | string | ✓ | |
-| [project_id](variables.tf#L182) | Cluster project id. | string | ✓ | |
+| [project_id](variables.tf#L188) | Cluster project id. | string | ✓ | |
| [cluster_id](variables.tf#L17) | Cluster id. Optional, but providing cluster_id is recommended to prevent cluster misconfiguration in some of the edge cases. | string | | null |
| [gke_version](variables.tf#L28) | Kubernetes nodes version. Ignored if auto_upgrade is set in management_config. | string | | null |
| [k8s_labels](variables.tf#L34) | Kubernetes labels applied to each node. | map(string) | | {} |
| [labels](variables.tf#L41) | The resource labels to be applied each node (vm). | map(string) | | {} |
| [max_pods_per_node](variables.tf#L53) | Maximum number of pods per node. | number | | null |
| [name](variables.tf#L59) | Optional nodepool name. | string | | null |
-| [node_config](variables.tf#L65) | Node-level configuration. | object({…}) | | {…} |
-| [node_count](variables.tf#L124) | Number of nodes per instance group. Initial value can only be changed by recreation, current is ignored when autoscaling is used. | object({…}) | | {…} |
-| [node_locations](variables.tf#L136) | Node locations. | list(string) | | null |
-| [nodepool_config](variables.tf#L142) | Nodepool-level configuration. | object({…}) | | null |
-| [pod_range](variables.tf#L169) | Pod secondary range configuration. | object({…}) | | null |
-| [reservation_affinity](variables.tf#L187) | Configuration of the desired reservation which instances could take capacity from. | object({…}) | | null |
-| [service_account](variables.tf#L197) | Nodepool service account. If this variable is set to null, the default GCE service account will be used. If set and email is null, a service account will be created. If scopes are null a default will be used. | object({…}) | | {} |
-| [sole_tenant_nodegroup](variables.tf#L208) | Sole tenant node group. | string | | null |
-| [tags](variables.tf#L214) | Network tags applied to nodes. | list(string) | | null |
-| [taints](variables.tf#L220) | Kubernetes taints applied to all nodes. | map(object({…})) | | {} |
+| [node_config](variables.tf#L65) | Node-level configuration. | object({…}) | | {} |
+| [node_count](variables.tf#L130) | Number of nodes per instance group. Initial value can only be changed by recreation, current is ignored when autoscaling is used. | object({…}) | | {…} |
+| [node_locations](variables.tf#L142) | Node locations. | list(string) | | null |
+| [nodepool_config](variables.tf#L148) | Nodepool-level configuration. | object({…}) | | null |
+| [pod_range](variables.tf#L175) | Pod secondary range configuration. | object({…}) | | null |
+| [reservation_affinity](variables.tf#L193) | Configuration of the desired reservation which instances could take capacity from. | object({…}) | | null |
+| [service_account](variables.tf#L203) | Nodepool service account. If this variable is set to null, the default GCE service account will be used. If set and email is null, a service account will be created. If scopes are null a default will be used. | object({…}) | | {} |
+| [sole_tenant_nodegroup](variables.tf#L214) | Sole tenant node group. | string | | null |
+| [tags](variables.tf#L220) | Network tags applied to nodes. | list(string) | | null |
+| [taints](variables.tf#L226) | Kubernetes taints applied to all nodes. | map(object({…})) | | {} |
## Outputs
diff --git a/modules/gke-nodepool/variables.tf b/modules/gke-nodepool/variables.tf
index 179667459..59df15650 100644
--- a/modules/gke-nodepool/variables.tf
+++ b/modules/gke-nodepool/variables.tf
@@ -67,7 +67,7 @@ variable "node_config" {
type = object({
boot_disk_kms_key = optional(string)
disk_size_gb = optional(number)
- disk_type = optional(string)
+ disk_type = optional(string, "pd-balanced")
ephemeral_ssd_count = optional(number)
gcfs = optional(bool, false)
guest_accelerator = optional(object({
@@ -105,9 +105,8 @@ variable "node_config" {
spot = optional(bool)
workload_metadata_config_mode = optional(string)
})
- default = {
- disk_type = "pd-balanced"
- }
+ default = {}
+ nullable = false
validation {
condition = (
alltrue([
@@ -119,6 +118,13 @@ variable "node_config" {
)
error_message = "Invalid GPU driver version."
}
+ validation {
+ condition = contains(
+ ["GCE_METADATA", "GKE_METADATA", "null"],
+ coalesce(var.node_config.workload_metadata_config_mode, "null")
+ )
+ error_message = "node_config.workload_metadata_config_mode must be GCE_METADATA or GKE_METADATA."
+ }
}
variable "node_count" {
diff --git a/modules/net-vpc-firewall/main.tf b/modules/net-vpc-firewall/main.tf
index 57e7607bd..cf74a498f 100644
--- a/modules/net-vpc-firewall/main.tf
+++ b/modules/net-vpc-firewall/main.tf
@@ -24,8 +24,8 @@ locals {
# decode rule files and account for optional attributes
_factory_rule_list = flatten([
for f in local._factory_rule_files : [
- for direction, ruleset in yamldecode(file(f)) : [
- for name, rule in ruleset : {
+ for direction, ruleset in coalesce(yamldecode(file(f)), tomap({})) : [
+ for name, rule in coalesce(ruleset, tomap({})) : {
name = name
deny = try(rule.deny, false)
rules = try(rule.rules, [{ protocol = "all", ports = null }])
diff --git a/modules/project-factory/README.md b/modules/project-factory/README.md
index ddb7bba4d..03d47043d 100644
--- a/modules/project-factory/README.md
+++ b/modules/project-factory/README.md
@@ -213,7 +213,8 @@ module "project-factory" {
source = "./fabric/modules/project-factory"
# use a default billing account if none is specified via yaml
data_defaults = {
- billing_account = var.billing_account_id
+ billing_account = var.billing_account_id
+ storage_location = "EU"
}
# make sure the environment label and stackdriver service are always added
data_merges = {
@@ -439,10 +440,10 @@ update_rules:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [factories_config](variables.tf#L98) | Path to folder with YAML resource description data files. | object({…}) | ✓ | |
-| [data_defaults](variables.tf#L17) | Optional default values used when corresponding project data from files are missing. | object({…}) | | {} |
-| [data_merges](variables.tf#L53) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} |
-| [data_overrides](variables.tf#L72) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} |
+| [factories_config](variables.tf#L100) | Path to folder with YAML resource description data files. | object({…}) | ✓ | |
+| [data_defaults](variables.tf#L17) | Optional default values used when corresponding project data from files are missing. | object({…}) | | {} |
+| [data_merges](variables.tf#L54) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} |
+| [data_overrides](variables.tf#L73) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} |
## Outputs
diff --git a/modules/project-factory/automation.tf b/modules/project-factory/automation.tf
index 34a1fd07d..df50c75a3 100644
--- a/modules/project-factory/automation.tf
+++ b/modules/project-factory/automation.tf
@@ -77,8 +77,12 @@ module "automation-buckets" {
)
})
}
- labels = lookup(each.value, "labels", {})
- location = lookup(each.value, "location", "EU")
+ labels = lookup(each.value, "labels", {})
+ location = coalesce(
+ var.data_overrides.storage_location,
+ lookup(each.value, "location", null),
+ var.data_defaults.storage_location
+ )
storage_class = lookup(each.value, "storage_class", "STANDARD")
uniform_bucket_level_access = lookup(each.value, "uniform_bucket_level_access", true)
versioning = lookup(each.value, "versioning", false)
diff --git a/modules/project-factory/variables.tf b/modules/project-factory/variables.tf
index 304685632..bd364e1b4 100644
--- a/modules/project-factory/variables.tf
+++ b/modules/project-factory/variables.tf
@@ -33,7 +33,8 @@ variable "data_defaults" {
service_iam_grants = optional(list(string), [])
network_subnet_users = optional(map(list(string)), {})
}), { host_project = null })
- tag_bindings = optional(map(string), {})
+ storage_location = optional(string)
+ tag_bindings = optional(map(string), {})
# non-project resources
service_accounts = optional(map(object({
display_name = optional(string, "Terraform-managed.")
@@ -77,6 +78,7 @@ variable "data_overrides" {
parent = optional(string)
prefix = optional(string)
service_encryption_key_ids = optional(map(list(string)))
+ storage_location = optional(string)
tag_bindings = optional(map(string))
services = optional(list(string))
# non-project resources
diff --git a/tests/modules/certificate_manager/examples/map-with-managed-cert-ca-service.yaml b/tests/modules/certificate_manager/examples/map-with-managed-cert-ca-service.yaml
index 2a5a07564..9dde520f1 100644
--- a/tests/modules/certificate_manager/examples/map-with-managed-cert-ca-service.yaml
+++ b/tests/modules/certificate_manager/examples/map-with-managed-cert-ca-service.yaml
@@ -96,7 +96,6 @@ values:
- dns_authorizations: null
domains:
- mydomain.mycompany.org
- issuance_config: my-issuance-config
name: my-certificate-1
project: project-id
scope: null
diff --git a/tools/pre-commit-tfdoc.sh b/tools/pre-commit-tfdoc.sh
index b2c5b6764..b0bf072ac 100755
--- a/tools/pre-commit-tfdoc.sh
+++ b/tools/pre-commit-tfdoc.sh
@@ -19,6 +19,9 @@ set -e
SCRIPT_DIR=$(dirname -- "$(readlink -f -- "$0")")
TFDOC_CMD="${SCRIPT_DIR}/tfdoc.py"
CHECKDOC_CMD="${SCRIPT_DIR}/check_documentation.py"
+if [ -z "$PYTHON" ]; then
+ PYTHON=python
+fi
for file in "$@"; do
if [ -d "${file}" ]; then
@@ -30,4 +33,4 @@ for file in "$@"; do
echo "${dir}"
fi
-done | sort | uniq | xargs -I {} /bin/sh -c "echo python \"${TFDOC_CMD}\" {} ; python \"${TFDOC_CMD}\" {} ; echo python \"${CHECKDOC_CMD}\" {} ; python \"${CHECKDOC_CMD}\" {}"
+done | sort | uniq | while read -r line; do /bin/sh -c "echo ${PYTHON} \"${TFDOC_CMD}\" \"$line\" ; ${PYTHON} \"${TFDOC_CMD}\" \"$line\" ; echo ${PYTHON} \"${CHECKDOC_CMD}\" \"$line\" ; ${PYTHON} \"${CHECKDOC_CMD}\" \"$line\""; done