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