From 31cb391be7848600754d5b5fa5440093240c834d Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 15 Nov 2024 10:22:18 +0100 Subject: [PATCH] Streamline environments variable across stages (#2688) * streamline environments variable across stages * linting * linting --- fast/stages/0-bootstrap/README.md | 56 +++++++++---------- fast/stages/0-bootstrap/outputs.tf | 15 +++-- fast/stages/0-bootstrap/variables.tf | 9 +++ fast/stages/1-resman/README.md | 30 +++++----- fast/stages/1-resman/main.tf | 1 + fast/stages/1-resman/organization.tf | 8 +-- fast/stages/1-resman/outputs.tf | 5 +- fast/stages/1-resman/stage-2-networking.tf | 8 +-- fast/stages/1-resman/stage-2-security.tf | 8 +-- fast/stages/1-resman/stage-3.tf | 6 +- fast/stages/1-resman/variables-fast.tf | 17 ++++++ fast/stages/1-resman/variables.tf | 12 ---- fast/stages/2-networking-a-simple/README.md | 10 ++-- fast/stages/2-networking-a-simple/main.tf | 4 +- fast/stages/2-networking-a-simple/net-dev.tf | 2 +- fast/stages/2-networking-a-simple/net-prod.tf | 2 +- .../2-networking-a-simple/variables-fast.tf | 22 +++++--- fast/stages/2-networking-b-nva/README.md | 10 ++-- fast/stages/2-networking-b-nva/main.tf | 2 +- fast/stages/2-networking-b-nva/net-dev.tf | 2 +- fast/stages/2-networking-b-nva/net-prod.tf | 2 +- .../2-networking-b-nva/variables-fast.tf | 22 +++++--- .../2-networking-c-separate-envs/README.md | 10 ++-- .../2-networking-c-separate-envs/main.tf | 4 +- .../2-networking-c-separate-envs/net-dev.tf | 2 +- .../2-networking-c-separate-envs/net-prod.tf | 2 +- .../variables-fast.tf | 22 +++++--- fast/stages/2-security/README.md | 10 ++-- fast/stages/2-security/core-dev.tf | 2 +- fast/stages/2-security/core-prod.tf | 2 +- fast/stages/2-security/main.tf | 4 +- fast/stages/2-security/variables-fast.tf | 22 +++++--- tests/fast/stages/s1_resman/simple.tfvars | 12 ++++ .../stages/s2_networking_a_simple/ncc.tfvars | 14 ++++- .../s2_networking_a_simple/simple.tfvars | 14 ++++- .../stages/s2_networking_a_simple/vpn.tfvars | 14 ++++- .../stages/s2_networking_b_nva/ncc-ra.tfvars | 14 ++++- .../s2_networking_b_nva/regional.tfvars | 14 ++++- .../stages/s2_networking_b_nva/simple.tfvars | 14 ++++- .../simple.tfvars | 14 ++++- tests/fast/stages/s2_security/simple.tfvars | 14 ++++- tools/changelog.py | 5 +- 42 files changed, 296 insertions(+), 166 deletions(-) diff --git a/fast/stages/0-bootstrap/README.md b/fast/stages/0-bootstrap/README.md index a0e8776187..14f61f818b 100644 --- a/fast/stages/0-bootstrap/README.md +++ b/fast/stages/0-bootstrap/README.md @@ -661,40 +661,40 @@ The remaining configuration is manual, as it regards the repositories themselves | name | description | type | required | default | producer | |---|---|:---:|:---:|:---:|:---:| | [billing_account](variables.tf#L17) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | object({…}) | ✓ | | | -| [organization](variables.tf#L266) | Organization details. | object({…}) | ✓ | | | -| [prefix](variables.tf#L281) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | | +| [organization](variables.tf#L275) | Organization details. | object({…}) | ✓ | | | +| [prefix](variables.tf#L290) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | | | [bootstrap_user](variables.tf#L27) | Email of the nominal user running this stage for the first time. | string | | null | | | [cicd_repositories](variables.tf#L33) | CI/CD repository configuration. Identity providers reference keys in the `federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | object({…}) | | null | | | [custom_roles](variables.tf#L87) | Map of role names => list of permissions to additionally create at the organization level. | map(list(string)) | | {} | | -| [environments](variables.tf#L94) | Environment names. | map(object({…})) | | {…} | | -| [essential_contacts](variables.tf#L118) | Email used for essential contacts, unset if null. | string | | null | | -| [factories_config](variables.tf#L124) | Configuration for the resource factories or external data. | object({…}) | | {} | | -| [groups](variables.tf#L135) | 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. | object({…}) | | {} | | -| [iam](variables.tf#L151) | Organization-level custom IAM settings in role => [principal] format. | map(list(string)) | | {} | | -| [iam_bindings_additive](variables.tf#L158) | Organization-level custom additive IAM bindings. Keys are arbitrary. | map(object({…})) | | {} | | -| [iam_by_principals](variables.tf#L173) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | map(list(string)) | | {} | | -| [locations](variables.tf#L180) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | | -| [log_sinks](variables.tf#L194) | Org-level log sinks, in name => {type, filter} format. | map(object({…})) | | {…} | | -| [org_policies_config](variables.tf#L247) | Organization policies customization. | object({…}) | | {} | | -| [outputs_location](variables.tf#L275) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | -| [project_parent_ids](variables.tf#L290) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the organization as parent. | object({…}) | | {} | | -| [workforce_identity_providers](variables.tf#L301) | Workforce Identity Federation pools. | map(object({…})) | | {} | | -| [workload_identity_providers](variables.tf#L317) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…})) | | {} | | +| [environments](variables.tf#L94) | Environment names. | map(object({…})) | | {…} | | +| [essential_contacts](variables.tf#L127) | Email used for essential contacts, unset if null. | string | | null | | +| [factories_config](variables.tf#L133) | Configuration for the resource factories or external data. | object({…}) | | {} | | +| [groups](variables.tf#L144) | 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. | object({…}) | | {} | | +| [iam](variables.tf#L160) | Organization-level custom IAM settings in role => [principal] format. | map(list(string)) | | {} | | +| [iam_bindings_additive](variables.tf#L167) | Organization-level custom additive IAM bindings. Keys are arbitrary. | map(object({…})) | | {} | | +| [iam_by_principals](variables.tf#L182) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | map(list(string)) | | {} | | +| [locations](variables.tf#L189) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | | +| [log_sinks](variables.tf#L203) | Org-level log sinks, in name => {type, filter} format. | map(object({…})) | | {…} | | +| [org_policies_config](variables.tf#L256) | Organization policies customization. | object({…}) | | {} | | +| [outputs_location](variables.tf#L284) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | +| [project_parent_ids](variables.tf#L299) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the organization as parent. | object({…}) | | {} | | +| [workforce_identity_providers](variables.tf#L310) | Workforce Identity Federation pools. | map(object({…})) | | {} | | +| [workload_identity_providers](variables.tf#L326) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…})) | | {} | | ## Outputs | name | description | sensitive | consumers | |---|---|:---:|---| -| [automation](outputs.tf#L146) | Automation resources. | | | -| [billing_dataset](outputs.tf#L151) | BigQuery dataset prepared for billing export. | | | -| [cicd_repositories](outputs.tf#L156) | CI/CD repository configurations. | | | -| [custom_roles](outputs.tf#L168) | Organization-level custom roles. | | | -| [outputs_bucket](outputs.tf#L173) | GCS bucket where generated output files are stored. | | | -| [project_ids](outputs.tf#L178) | Projects created by this stage. | | | -| [providers](outputs.tf#L188) | Terraform provider files for this stage and dependent stages. | ✓ | stage-01 | -| [service_accounts](outputs.tf#L195) | Automation service accounts created by this stage. | | | -| [tfvars](outputs.tf#L204) | Terraform variable files for the following stages. | ✓ | | -| [tfvars_globals](outputs.tf#L210) | Terraform Globals variable files for the following stages. | ✓ | | -| [workforce_identity_pool](outputs.tf#L216) | Workforce Identity Federation pool. | | | -| [workload_identity_pool](outputs.tf#L225) | Workload Identity Federation pool and providers. | | | +| [automation](outputs.tf#L153) | Automation resources. | | | +| [billing_dataset](outputs.tf#L158) | BigQuery dataset prepared for billing export. | | | +| [cicd_repositories](outputs.tf#L163) | CI/CD repository configurations. | | | +| [custom_roles](outputs.tf#L175) | Organization-level custom roles. | | | +| [outputs_bucket](outputs.tf#L180) | GCS bucket where generated output files are stored. | | | +| [project_ids](outputs.tf#L185) | Projects created by this stage. | | | +| [providers](outputs.tf#L195) | Terraform provider files for this stage and dependent stages. | ✓ | stage-01 | +| [service_accounts](outputs.tf#L202) | Automation service accounts created by this stage. | | | +| [tfvars](outputs.tf#L211) | Terraform variable files for the following stages. | ✓ | | +| [tfvars_globals](outputs.tf#L217) | Terraform Globals variable files for the following stages. | ✓ | | +| [workforce_identity_pool](outputs.tf#L223) | Workforce Identity Federation pool. | | | +| [workload_identity_pool](outputs.tf#L232) | Workload Identity Federation pool and providers. | | | diff --git a/fast/stages/0-bootstrap/outputs.tf b/fast/stages/0-bootstrap/outputs.tf index 9a34a58d7f..29bf4a89f5 100644 --- a/fast/stages/0-bootstrap/outputs.tf +++ b/fast/stages/0-bootstrap/outputs.tf @@ -136,10 +136,17 @@ locals { tfvars_globals = { billing_account = var.billing_account groups = local.principals - environments = var.environments - locations = local.locations - organization = var.organization - prefix = var.prefix + environments = { + for k, v in var.environments : + k => merge(v, { + tag_name = ( + v.tag_name != null ? v.tag_name : lower(replace(v.name, " ", "-")) + ) + }) + } + locations = local.locations + organization = var.organization + prefix = var.prefix } } diff --git a/fast/stages/0-bootstrap/variables.tf b/fast/stages/0-bootstrap/variables.tf index 019c9afc52..b9b30587d3 100644 --- a/fast/stages/0-bootstrap/variables.tf +++ b/fast/stages/0-bootstrap/variables.tf @@ -96,6 +96,7 @@ variable "environments" { type = map(object({ name = string is_default = optional(bool, false) + tag_name = optional(string) })) nullable = false default = { @@ -113,6 +114,14 @@ variable "environments" { ]) error_message = "At least one environment should be marked as default." } + validation { + condition = alltrue([ + for k, v in var.environments : join(" ", regexall( + "[a-zA-Z][a-zA-Z0-9\\s-]+[a-zA-Z0-9]", v.name + )) == v.name + ]) + error_message = "Environment names can only contain letters numbers dashes or spaces." + } } variable "essential_contacts" { diff --git a/fast/stages/1-resman/README.md b/fast/stages/1-resman/README.md index e40aa1fa3f..53ba3316f8 100644 --- a/fast/stages/1-resman/README.md +++ b/fast/stages/1-resman/README.md @@ -267,28 +267,28 @@ terraform apply |---|---|:---:|:---:|:---:|:---:| | [automation](variables-fast.tf#L19) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables-fast.tf#L42) | Billing account id. If billing account is not part of the same org set `is_org_level` to `false`. To disable handling of billing IAM roles set `no_iam` to `true`. | object({…}) | ✓ | | 0-bootstrap | -| [logging](variables-fast.tf#L99) | Logging configuration for tenants. | object({…}) | ✓ | | 1-tenant-factory | -| [organization](variables-fast.tf#L112) | Organization details. | object({…}) | ✓ | | 0-bootstrap | -| [prefix](variables-fast.tf#L130) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | +| [environments](variables-fast.tf#L71) | Environment names. | map(object({…})) | ✓ | | 0-globals | +| [logging](variables-fast.tf#L116) | Logging configuration for tenants. | object({…}) | ✓ | | 1-tenant-factory | +| [organization](variables-fast.tf#L129) | Organization details. | object({…}) | ✓ | | 0-bootstrap | +| [prefix](variables-fast.tf#L147) | Prefix used for resources that need unique names. Use 9 characters or less. | string | ✓ | | 0-bootstrap | | [custom_roles](variables-fast.tf#L53) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | -| [environment_names](variables.tf#L20) | Long environment names. | object({…}) | | {…} | | -| [factories_config](variables.tf#L32) | Configuration for the resource factories or external data. | object({…}) | | {} | | +| [factories_config](variables.tf#L20) | Configuration for the resource factories or external data. | object({…}) | | {} | | | [fast_stage_2](variables-stages.tf#L17) | FAST stages 2 configurations. | object({…}) | | {} | | | [fast_stage_3](variables-stages.tf#L97) | FAST stages 3 configurations. | map(object({…})) | | {} | | -| [groups](variables-fast.tf#L71) | 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. | object({…}) | | {} | 0-bootstrap | -| [locations](variables-fast.tf#L86) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | 0-bootstrap | -| [outputs_location](variables.tf#L43) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | -| [root_node](variables-fast.tf#L136) | Root node for the hierarchy, if running in tenant mode. | string | | null | 0-bootstrap | -| [tag_names](variables.tf#L49) | Customized names for resource management tags. | object({…}) | | {} | | -| [tags](variables.tf#L63) | Custom secure tags by key name. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} | | +| [groups](variables-fast.tf#L88) | 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. | object({…}) | | {} | 0-bootstrap | +| [locations](variables-fast.tf#L103) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | 0-bootstrap | +| [outputs_location](variables.tf#L31) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | string | | null | | +| [root_node](variables-fast.tf#L153) | Root node for the hierarchy, if running in tenant mode. | string | | null | 0-bootstrap | +| [tag_names](variables.tf#L37) | Customized names for resource management tags. | object({…}) | | {} | | +| [tags](variables.tf#L51) | Custom secure tags by key name. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} | | | [top_level_folders](variables-toplevel-folders.tf#L17) | Additional top-level folders. Keys are used for service account and bucket names, values implement the folders module interface with the addition of the 'automation' attribute. | map(object({…})) | | {} | | ## Outputs | name | description | sensitive | consumers | |---|---|:---:|---| -| [cicd_repositories](outputs.tf#L77) | WIF configuration for CI/CD repositories. | | | -| [folder_ids](outputs.tf#L89) | Folder ids. | | | -| [providers](outputs.tf#L95) | Terraform provider files for this stage and dependent stages. | ✓ | | -| [tfvars](outputs.tf#L102) | Terraform variable files for the following stages. | ✓ | | +| [cicd_repositories](outputs.tf#L76) | WIF configuration for CI/CD repositories. | | | +| [folder_ids](outputs.tf#L88) | Folder ids. | | | +| [providers](outputs.tf#L94) | Terraform provider files for this stage and dependent stages. | ✓ | | +| [tfvars](outputs.tf#L101) | Terraform variable files for the following stages. | ✓ | | diff --git a/fast/stages/1-resman/main.tf b/fast/stages/1-resman/main.tf index 84d1db29dd..6d96689bb6 100644 --- a/fast/stages/1-resman/main.tf +++ b/fast/stages/1-resman/main.tf @@ -19,6 +19,7 @@ locals { # automation_resman_sa = try( # data.google_client_openid_userinfo.provider_identity[0].email, null # ) + # tag values use descriptive names gcs_storage_class = ( length(split("-", var.locations.gcs)) < 2 ? "MULTI_REGIONAL" diff --git a/fast/stages/1-resman/organization.tf b/fast/stages/1-resman/organization.tf index 90c69196de..b59b2659d9 100644 --- a/fast/stages/1-resman/organization.tf +++ b/fast/stages/1-resman/organization.tf @@ -44,20 +44,20 @@ locals { ) # environment tag values and their IAM bindings for stage 2 service accounts environment_tag_values = { - for k, v in var.environment_names : v => { + for k, v in var.environments : v.tag_name => { iam = merge( # user-defined configuration - try(local.tags.environment.values[v].iam, {}), + try(local.tags.environment.values[v.tag_name].iam, {}), # stage 2 service accounts { "roles/resourcemanager.tagUser" = distinct(concat( - try(local.tags.environment.values[v].iam["roles/resourcemanager.tagUser"], []), + try(local.tags.environment.values[v.tag_name].iam["roles/resourcemanager.tagUser"], []), !var.fast_stage_2.project_factory.enabled ? [] : [module.pf-sa-rw[0].iam_email], !var.fast_stage_2.networking.enabled ? [] : [module.net-sa-rw[0].iam_email], !var.fast_stage_2.security.enabled ? [] : [module.sec-sa-rw[0].iam_email], )) "roles/resourcemanager.tagViewer" = distinct(concat( - try(local.tags.environment.values[v].iam["roles/resourcemanager.tagViewer"], []), + try(local.tags.environment.values[v.tag_name].iam["roles/resourcemanager.tagViewer"], []), !var.fast_stage_2.project_factory.enabled ? [] : [module.pf-sa-ro[0].iam_email], !var.fast_stage_2.networking.enabled ? [] : [module.net-sa-ro[0].iam_email], !var.fast_stage_2.security.enabled ? [] : [module.sec-sa-ro[0].iam_email], diff --git a/fast/stages/1-resman/outputs.tf b/fast/stages/1-resman/outputs.tf index b771ecff95..0c81523719 100644 --- a/fast/stages/1-resman/outputs.tf +++ b/fast/stages/1-resman/outputs.tf @@ -37,7 +37,6 @@ locals { local.top_level_service_accounts ) tfvars = { - environment_names = var.environment_names stage_config = merge( { for k, v in local.stage3 : k => { @@ -50,14 +49,14 @@ locals { short_name = v.short_name # rw service accounts for stage 3s that need delegated IAM on stage 2s iam_delegated_principals = { - for ek, ev in var.environment_names : ek => [ + for ek, _ in var.environments : ek => [ for sk, sv in local.stage3 : "serviceAccount:${local.stage_service_accounts[sk]}" if sv.environment == ek && try(sv.stage2_iam[k].iam_admin_delegated, false) ] } iam_viewer_principals = { - for ek, ev in var.environment_names : ek => [ + for ek, _ in var.environments : ek => [ for sk, sv in local.stage3 : "serviceAccount:${local.stage_service_accounts["${sk}-r"]}" if sv.environment == ek && try(sv.stage2_iam[k].iam_admin_delegated, false) diff --git a/fast/stages/1-resman/stage-2-networking.tf b/fast/stages/1-resman/stage-2-networking.tf index f4a52601c0..ccdb4d5be8 100644 --- a/fast/stages/1-resman/stage-2-networking.tf +++ b/fast/stages/1-resman/stage-2-networking.tf @@ -157,10 +157,10 @@ module "net-folder-prod" { source = "../../../modules/folder" count = local.net_use_env_folders ? 1 : 0 parent = module.net-folder[0].id - name = title(var.environment_names["prod"]) + name = var.environments["prod"].name tag_bindings = { environment = try( - local.tag_values["${var.tag_names.environment}/${var.environment_names["prod"]}"].id, + local.tag_values["${var.tag_names.environment}/${var.environments["prod"].tag_name}"].id, null ) } @@ -170,10 +170,10 @@ module "net-folder-dev" { source = "../../../modules/folder" count = local.net_use_env_folders ? 1 : 0 parent = module.net-folder[0].id - name = title(var.environment_names["dev"]) + name = var.environments["dev"].name tag_bindings = { environment = try( - local.tag_values["${var.tag_names.environment}/${var.environment_names["dev"]}"].id, + local.tag_values["${var.tag_names.environment}/${var.environments["dev"].tag_name}"].id, null ) } diff --git a/fast/stages/1-resman/stage-2-security.tf b/fast/stages/1-resman/stage-2-security.tf index 36e3d7b656..dce6e0d0dd 100644 --- a/fast/stages/1-resman/stage-2-security.tf +++ b/fast/stages/1-resman/stage-2-security.tf @@ -120,7 +120,7 @@ module "sec-folder-prod" { source = "../../../modules/folder" count = local.sec_use_env_folders ? 1 : 0 parent = module.sec-folder[0].id - name = title(var.environment_names["prod"]) + name = var.environments["prod"].name iam = { # stage 3s service accounts for role, attrs in local.sec_s3_iam.prod : role => [ @@ -133,7 +133,7 @@ module "sec-folder-prod" { } tag_bindings = { environment = try( - local.tag_values["${var.tag_names.environment}/${var.environment_names["prod"]}"].id, + local.tag_values["${var.tag_names.environment}/${var.environments["prod"].tag_name}"].id, null ) } @@ -143,7 +143,7 @@ module "sec-folder-dev" { source = "../../../modules/folder" count = local.sec_use_env_folders ? 1 : 0 parent = module.sec-folder[0].id - name = title(var.environment_names["dev"]) + name = var.environments["dev"].name iam = { # stage 3s service accounts for role, attrs in local.sec_s3_iam.dev : role => [ @@ -156,7 +156,7 @@ module "sec-folder-dev" { } tag_bindings = { environment = try( - local.tag_values["${var.tag_names.environment}/${var.environment_names["dev"]}"].id, + local.tag_values["${var.tag_names.environment}/${var.environments["dev"].tag_name}"].id, null ) } diff --git a/fast/stages/1-resman/stage-3.tf b/fast/stages/1-resman/stage-3.tf index 2776ced6da..2015c61f71 100644 --- a/fast/stages/1-resman/stage-3.tf +++ b/fast/stages/1-resman/stage-3.tf @@ -84,7 +84,7 @@ locals { for sa, roles in try(v.organization_iam.sa_roles, []) : [ for role in roles : { context = try(v.organization_iam.context_tag_value, "") - env = var.environment_names[v.environment] + env = var.environments[v.environment].tag_name role = role sa = sa s3 = k @@ -98,7 +98,7 @@ locals { for s2, attrs in v.stage2_iam : [ for sa, roles in attrs.sa_roles : [ for role in roles : { - env = var.environment_names[v.environment] + env = var.environments[v.environment].tag_name role = lookup(var.custom_roles, role, role) sa = sa s2 = s2 @@ -139,7 +139,7 @@ module "stage3-folder" { iam_by_principals = each.value.folder_config.iam_by_principals tag_bindings = merge( { - environment = local.tag_values["environment/${var.environment_names[each.value.environment]}"].id + environment = local.tag_values["environment/${var.environments[each.value.environment].tag_name}"].id }, { for k, v in each.value.folder_config.tag_bindings : k => try( diff --git a/fast/stages/1-resman/variables-fast.tf b/fast/stages/1-resman/variables-fast.tf index 00df1b5c2e..a35f5eca40 100644 --- a/fast/stages/1-resman/variables-fast.tf +++ b/fast/stages/1-resman/variables-fast.tf @@ -68,6 +68,23 @@ variable "custom_roles" { default = null } +variable "environments" { + # tfdoc:variable:source 0-globals + description = "Environment names." + type = map(object({ + name = string + tag_name = string + is_default = optional(bool, false) + })) + nullable = false + validation { + condition = anytrue([ + for k, v in var.environments : v.is_default == true + ]) + error_message = "At least one environment should be marked as default." + } +} + variable "groups" { # tfdoc:variable:source 0-bootstrap # https://cloud.google.com/docs/enterprise/setup-checklist diff --git a/fast/stages/1-resman/variables.tf b/fast/stages/1-resman/variables.tf index adc6c803b3..6443f02dc8 100644 --- a/fast/stages/1-resman/variables.tf +++ b/fast/stages/1-resman/variables.tf @@ -17,18 +17,6 @@ # defaults for variables marked with global tfdoc annotations, can be set via # the tfvars file generated in stage 00 and stored in its outputs -variable "environment_names" { - description = "Long environment names." - type = object({ - dev = string - prod = string - }) - default = { - dev = "development" - prod = "production" - } -} - variable "factories_config" { description = "Configuration for the resource factories or external data." type = object({ diff --git a/fast/stages/2-networking-a-simple/README.md b/fast/stages/2-networking-a-simple/README.md index a715a9241e..574689ef2d 100644 --- a/fast/stages/2-networking-a-simple/README.md +++ b/fast/stages/2-networking-a-simple/README.md @@ -501,9 +501,9 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables-fast.tf#L19) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables-fast.tf#L27) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [environment_names](variables-fast.tf#L49) | Long environment names. | object({…}) | ✓ | | 1-resman | -| [folder_ids](variables-fast.tf#L58) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. | object({…}) | ✓ | | 1-resman | -| [prefix](variables-fast.tf#L68) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap | +| [environments](variables-fast.tf#L49) | Environment names. | map(object({…})) | ✓ | | 0-globals | +| [folder_ids](variables-fast.tf#L66) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. | object({…}) | ✓ | | 1-resman | +| [prefix](variables-fast.tf#L76) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap | | [alert_config](variables.tf#L17) | Configuration for monitoring alerts. | object({…}) | | {…} | | | [create_test_instances](variables.tf#L42) | Enables the creation of test VMs in each VPC, useful to test and troubleshoot connectivity. | bool | | false | | | [custom_roles](variables-fast.tf#L40) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | @@ -515,8 +515,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [psa_ranges](variables.tf#L98) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | {} | | | [regions](variables.tf#L118) | Region definitions. | object({…}) | | {…} | | | [spoke_configs](variables.tf#L130) | Spoke connectivity configurations. | object({…}) | | {…} | | -| [stage_config](variables-fast.tf#L78) | FAST stage configuration. | object({…}) | | {} | 1-resman | -| [tag_values](variables-fast.tf#L92) | Root-level tag values. | map(string) | | {} | 1-resman | +| [stage_config](variables-fast.tf#L86) | FAST stage configuration. | object({…}) | | {} | 1-resman | +| [tag_values](variables-fast.tf#L100) | Root-level tag values. | map(string) | | {} | 1-resman | | [vpn_onprem_primary_config](variables.tf#L199) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | ## Outputs diff --git a/fast/stages/2-networking-a-simple/main.tf b/fast/stages/2-networking-a-simple/main.tf index 2cd3dcb732..1126bc4917 100644 --- a/fast/stages/2-networking-a-simple/main.tf +++ b/fast/stages/2-networking-a-simple/main.tf @@ -18,8 +18,8 @@ locals { env_tag_values = { - for k, v in var.environment_names : - k => var.tag_values["environment/${v}"] + for k, v in var.environments : + k => var.tag_values["environment/${v.tag_name}"] } has_env_folders = var.folder_ids.networking-dev != null iam_delegated = join(",", formatlist("'%s'", [ diff --git a/fast/stages/2-networking-a-simple/net-dev.tf b/fast/stages/2-networking-a-simple/net-dev.tf index aaa9d76878..ad14b36224 100644 --- a/fast/stages/2-networking-a-simple/net-dev.tf +++ b/fast/stages/2-networking-a-simple/net-dev.tf @@ -52,7 +52,7 @@ module "dev-spoke-project" { members = try(local.iam_delegated_principals["dev"], []) condition = { title = "dev_stage3_sa_delegated_grants" - description = "${var.environment_names["dev"]} host project delegated grants." + description = "${var.environments["dev"].name} host project delegated grants." expression = format( "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", local.iam_delegated diff --git a/fast/stages/2-networking-a-simple/net-prod.tf b/fast/stages/2-networking-a-simple/net-prod.tf index ea5a628782..cfef3f425c 100644 --- a/fast/stages/2-networking-a-simple/net-prod.tf +++ b/fast/stages/2-networking-a-simple/net-prod.tf @@ -52,7 +52,7 @@ module "prod-spoke-project" { members = try(local.iam_delegated_principals["prod"], []) condition = { title = "prod_stage3_sa_delegated_grants" - description = "${var.environment_names["prod"]} host project delegated grants." + description = "${var.environments["prod"].name} host project delegated grants." expression = format( "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", local.iam_delegated diff --git a/fast/stages/2-networking-a-simple/variables-fast.tf b/fast/stages/2-networking-a-simple/variables-fast.tf index b3416f2db1..dd7f96bf58 100644 --- a/fast/stages/2-networking-a-simple/variables-fast.tf +++ b/fast/stages/2-networking-a-simple/variables-fast.tf @@ -46,13 +46,21 @@ variable "custom_roles" { default = null } -variable "environment_names" { - # tfdoc:variable:source 1-resman - description = "Long environment names." - type = object({ - dev = string - prod = string - }) +variable "environments" { + # tfdoc:variable:source 0-globals + description = "Environment names." + type = map(object({ + name = string + tag_name = string + is_default = optional(bool, false) + })) + nullable = false + validation { + condition = anytrue([ + for k, v in var.environments : v.is_default == true + ]) + error_message = "At least one environment should be marked as default." + } } variable "folder_ids" { diff --git a/fast/stages/2-networking-b-nva/README.md b/fast/stages/2-networking-b-nva/README.md index 34243500b7..c8f9b78bb1 100644 --- a/fast/stages/2-networking-b-nva/README.md +++ b/fast/stages/2-networking-b-nva/README.md @@ -562,9 +562,9 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS |---|---|:---:|:---:|:---:|:---:| | [automation](variables-fast.tf#L19) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables-fast.tf#L27) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [environment_names](variables-fast.tf#L49) | Long environment names. | object({…}) | ✓ | | 1-resman | -| [folder_ids](variables-fast.tf#L58) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. | object({…}) | ✓ | | 1-resman | -| [prefix](variables-fast.tf#L68) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap | +| [environments](variables-fast.tf#L49) | Environment names. | map(object({…})) | ✓ | | 0-globals | +| [folder_ids](variables-fast.tf#L66) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. | object({…}) | ✓ | | 1-resman | +| [prefix](variables-fast.tf#L76) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap | | [alert_config](variables.tf#L17) | Configuration for monitoring alerts. | object({…}) | | {…} | | | [create_test_instances](variables.tf#L42) | Enables the creation of test VMs in each VPC, useful to test and troubleshoot connectivity. | bool | | false | | | [custom_roles](variables-fast.tf#L40) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | @@ -577,8 +577,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS | [outputs_location](variables.tf#L120) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | | [psa_ranges](variables.tf#L126) | IP ranges used for Private Service Access (e.g. CloudSQL). Ranges is in name => range format. | object({…}) | | {} | | | [regions](variables.tf#L146) | Region definitions. | object({…}) | | {…} | | -| [stage_config](variables-fast.tf#L78) | FAST stage configuration. | object({…}) | | {} | 1-resman | -| [tag_values](variables-fast.tf#L92) | Root-level tag values. | map(string) | | {} | 1-resman | +| [stage_config](variables-fast.tf#L86) | FAST stage configuration. | object({…}) | | {} | 1-resman | +| [tag_values](variables-fast.tf#L100) | Root-level tag values. | map(string) | | {} | 1-resman | | [vpn_onprem_primary_config](variables.tf#L158) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | | | [vpn_onprem_secondary_config](variables.tf#L201) | VPN gateway configuration for onprem interconnection in the secondary region. | object({…}) | | null | | diff --git a/fast/stages/2-networking-b-nva/main.tf b/fast/stages/2-networking-b-nva/main.tf index b08d4f50cf..179ddbfaf1 100644 --- a/fast/stages/2-networking-b-nva/main.tf +++ b/fast/stages/2-networking-b-nva/main.tf @@ -18,7 +18,7 @@ locals { env_tag_values = { - for k, v in var.environment_names : k => var.tag_values["environment/${v}"] + for k, v in var.environments : k => var.tag_values["environment/${v.tag_name}"] } has_env_folders = var.folder_ids.networking-dev != null iam_delegated = join(",", formatlist("'%s'", [ diff --git a/fast/stages/2-networking-b-nva/net-dev.tf b/fast/stages/2-networking-b-nva/net-dev.tf index 200b1e1487..eec1d55861 100644 --- a/fast/stages/2-networking-b-nva/net-dev.tf +++ b/fast/stages/2-networking-b-nva/net-dev.tf @@ -51,7 +51,7 @@ module "dev-spoke-project" { members = try(local.iam_delegated_principals["dev"], []) condition = { title = "dev_stage3_sa_delegated_grants" - description = "${var.environment_names["dev"]} host project delegated grants." + description = "${var.environments["dev"].name} host project delegated grants." expression = format( "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", local.iam_delegated diff --git a/fast/stages/2-networking-b-nva/net-prod.tf b/fast/stages/2-networking-b-nva/net-prod.tf index 3df55b5031..bb59e58a4d 100644 --- a/fast/stages/2-networking-b-nva/net-prod.tf +++ b/fast/stages/2-networking-b-nva/net-prod.tf @@ -51,7 +51,7 @@ module "prod-spoke-project" { members = try(local.iam_delegated_principals["prod"], []) condition = { title = "prod_stage3_sa_delegated_grants" - description = "${var.environment_names["prod"]} host project delegated grants." + description = "${var.environments["prod"].name} host project delegated grants." expression = format( "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", local.iam_delegated diff --git a/fast/stages/2-networking-b-nva/variables-fast.tf b/fast/stages/2-networking-b-nva/variables-fast.tf index b3416f2db1..dd7f96bf58 100644 --- a/fast/stages/2-networking-b-nva/variables-fast.tf +++ b/fast/stages/2-networking-b-nva/variables-fast.tf @@ -46,13 +46,21 @@ variable "custom_roles" { default = null } -variable "environment_names" { - # tfdoc:variable:source 1-resman - description = "Long environment names." - type = object({ - dev = string - prod = string - }) +variable "environments" { + # tfdoc:variable:source 0-globals + description = "Environment names." + type = map(object({ + name = string + tag_name = string + is_default = optional(bool, false) + })) + nullable = false + validation { + condition = anytrue([ + for k, v in var.environments : v.is_default == true + ]) + error_message = "At least one environment should be marked as default." + } } variable "folder_ids" { diff --git a/fast/stages/2-networking-c-separate-envs/README.md b/fast/stages/2-networking-c-separate-envs/README.md index 56918c38d2..71d8487c66 100644 --- a/fast/stages/2-networking-c-separate-envs/README.md +++ b/fast/stages/2-networking-c-separate-envs/README.md @@ -360,9 +360,9 @@ Regions are defined via the `regions` variable which sets up a mapping between t |---|---|:---:|:---:|:---:|:---:| | [automation](variables-fast.tf#L19) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables-fast.tf#L27) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [environment_names](variables-fast.tf#L49) | Long environment names. | object({…}) | ✓ | | 1-resman | -| [folder_ids](variables-fast.tf#L58) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. | object({…}) | ✓ | | 1-resman | -| [prefix](variables-fast.tf#L68) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap | +| [environments](variables-fast.tf#L49) | Environment names. | map(object({…})) | ✓ | | 0-globals | +| [folder_ids](variables-fast.tf#L66) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. | object({…}) | ✓ | | 1-resman | +| [prefix](variables-fast.tf#L76) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap | | [alert_config](variables.tf#L17) | Configuration for monitoring alerts. | object({…}) | | {…} | | | [custom_roles](variables-fast.tf#L40) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [dns](variables.tf#L42) | DNS configuration. | object({…}) | | {} | | @@ -372,8 +372,8 @@ Regions are defined via the `regions` variable which sets up a mapping between t | [outputs_location](variables.tf#L87) | Path where providers and tfvars files for the following stages are written. Leave empty to disable. | string | | null | | | [psa_ranges](variables.tf#L93) | IP ranges used for Private Service Access (e.g. CloudSQL). | object({…}) | | {} | | | [regions](variables.tf#L113) | Region definitions. | object({…}) | | {…} | | -| [stage_config](variables-fast.tf#L78) | FAST stage configuration. | object({…}) | | {} | 1-resman | -| [tag_values](variables-fast.tf#L92) | Root-level tag values. | map(string) | | {} | 1-resman | +| [stage_config](variables-fast.tf#L86) | FAST stage configuration. | object({…}) | | {} | 1-resman | +| [tag_values](variables-fast.tf#L100) | Root-level tag values. | map(string) | | {} | 1-resman | | [vpn_onprem_dev_primary_config](variables.tf#L123) | VPN gateway configuration for onprem interconnection from dev in the primary region. | object({…}) | | null | | | [vpn_onprem_prod_primary_config](variables.tf#L166) | VPN gateway configuration for onprem interconnection from prod in the primary region. | object({…}) | | null | | diff --git a/fast/stages/2-networking-c-separate-envs/main.tf b/fast/stages/2-networking-c-separate-envs/main.tf index d331caa42b..7497e2d507 100644 --- a/fast/stages/2-networking-c-separate-envs/main.tf +++ b/fast/stages/2-networking-c-separate-envs/main.tf @@ -18,8 +18,8 @@ locals { env_tag_values = { - for k, v in var.environment_names : - k => var.tag_values["environment/${v}"] + for k, v in var.environments : + k => var.tag_values["environment/${v.tag_name}"] } has_env_folders = var.folder_ids.networking-dev != null iam_delegated = join(",", formatlist("'%s'", [ diff --git a/fast/stages/2-networking-c-separate-envs/net-dev.tf b/fast/stages/2-networking-c-separate-envs/net-dev.tf index 4ffd04f677..185db01ff3 100644 --- a/fast/stages/2-networking-c-separate-envs/net-dev.tf +++ b/fast/stages/2-networking-c-separate-envs/net-dev.tf @@ -52,7 +52,7 @@ module "dev-spoke-project" { members = try(local.iam_delegated_principals["dev"], []) condition = { title = "dev_stage3_sa_delegated_grants" - description = "${var.environment_names["dev"]} host project delegated grants." + description = "${var.environments["dev"].name} host project delegated grants." expression = format( "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", local.iam_delegated diff --git a/fast/stages/2-networking-c-separate-envs/net-prod.tf b/fast/stages/2-networking-c-separate-envs/net-prod.tf index 944adb7dbf..f25c9f5560 100644 --- a/fast/stages/2-networking-c-separate-envs/net-prod.tf +++ b/fast/stages/2-networking-c-separate-envs/net-prod.tf @@ -52,7 +52,7 @@ module "prod-spoke-project" { members = try(local.iam_delegated_principals["prod"], []) condition = { title = "prod_stage3_sa_delegated_grants" - description = "${var.environment_names["prod"]} host project delegated grants." + description = "${var.environments["prod"].name} host project delegated grants." expression = format( "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", local.iam_delegated diff --git a/fast/stages/2-networking-c-separate-envs/variables-fast.tf b/fast/stages/2-networking-c-separate-envs/variables-fast.tf index b3416f2db1..dd7f96bf58 100644 --- a/fast/stages/2-networking-c-separate-envs/variables-fast.tf +++ b/fast/stages/2-networking-c-separate-envs/variables-fast.tf @@ -46,13 +46,21 @@ variable "custom_roles" { default = null } -variable "environment_names" { - # tfdoc:variable:source 1-resman - description = "Long environment names." - type = object({ - dev = string - prod = string - }) +variable "environments" { + # tfdoc:variable:source 0-globals + description = "Environment names." + type = map(object({ + name = string + tag_name = string + is_default = optional(bool, false) + })) + nullable = false + validation { + condition = anytrue([ + for k, v in var.environments : v.is_default == true + ]) + error_message = "At least one environment should be marked as default." + } } variable "folder_ids" { diff --git a/fast/stages/2-security/README.md b/fast/stages/2-security/README.md index f93d45f813..aa13a0a152 100644 --- a/fast/stages/2-security/README.md +++ b/fast/stages/2-security/README.md @@ -299,17 +299,17 @@ tls_inspection = { |---|---|:---:|:---:|:---:|:---:| | [automation](variables-fast.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-bootstrap | | [billing_account](variables-fast.tf#L25) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | ✓ | | 0-bootstrap | -| [environment_names](variables-fast.tf#L47) | Long environment names. | object({…}) | ✓ | | 1-resman | -| [folder_ids](variables-fast.tf#L56) | Folder name => id mappings, the 'security' folder name must exist. | object({…}) | ✓ | | 1-resman | -| [prefix](variables-fast.tf#L66) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap | +| [environments](variables-fast.tf#L47) | Environment names. | map(object({…})) | ✓ | | 0-globals | +| [folder_ids](variables-fast.tf#L64) | Folder name => id mappings, the 'security' folder name must exist. | object({…}) | ✓ | | 1-resman | +| [prefix](variables-fast.tf#L74) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-bootstrap | | [cas_configs](variables.tf#L17) | The CAS CAs to add to each environment. | object({…}) | | {…} | | | [custom_roles](variables-fast.tf#L38) | Custom roles defined at the org level, in key => id format. | object({…}) | | null | 0-bootstrap | | [essential_contacts](variables.tf#L178) | Email used for essential contacts, unset if null. | string | | null | | | [kms_keys](variables.tf#L184) | KMS keys to create, keyed by name. | map(object({…})) | | {} | | | [ngfw_tls_configs](variables.tf#L223) | The CAS and trust configurations key names to be used for NGFW Enterprise. | object({…}) | | {…} | | | [outputs_location](variables.tf#L249) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | string | | null | | -| [stage_config](variables-fast.tf#L76) | FAST stage configuration. | object({…}) | | {} | 1-resman | -| [tag_values](variables-fast.tf#L90) | Root-level tag values. | map(string) | | {} | 1-resman | +| [stage_config](variables-fast.tf#L84) | FAST stage configuration. | object({…}) | | {} | 1-resman | +| [tag_values](variables-fast.tf#L98) | Root-level tag values. | map(string) | | {} | 1-resman | | [trust_configs](variables.tf#L255) | The trust configs grouped by environment. | object({…}) | | {…} | | ## Outputs diff --git a/fast/stages/2-security/core-dev.tf b/fast/stages/2-security/core-dev.tf index 6786dad9ee..2c089db122 100644 --- a/fast/stages/2-security/core-dev.tf +++ b/fast/stages/2-security/core-dev.tf @@ -45,7 +45,7 @@ module "dev-sec-project" { members = try(local.iam_delegated_principals["dev"], []) condition = { title = "dev_stage3_sa_delegated_grants" - description = "${var.environment_names["dev"]} project delegated grants." + description = "${var.environments["dev"].name} project delegated grants." expression = format( "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", local.iam_delegated diff --git a/fast/stages/2-security/core-prod.tf b/fast/stages/2-security/core-prod.tf index 7c267c8f2c..b74a5376a2 100644 --- a/fast/stages/2-security/core-prod.tf +++ b/fast/stages/2-security/core-prod.tf @@ -45,7 +45,7 @@ module "prod-sec-project" { members = try(local.iam_delegated_principals["prod"], []) condition = { title = "prod_stage3_sa_delegated_grants" - description = "${var.environment_names["prod"]} project delegated grants." + description = "${var.environments["prod"].name} project delegated grants." expression = format( "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])", local.iam_delegated diff --git a/fast/stages/2-security/main.tf b/fast/stages/2-security/main.tf index af4d0ab735..5aa17e87ef 100644 --- a/fast/stages/2-security/main.tf +++ b/fast/stages/2-security/main.tf @@ -16,8 +16,8 @@ locals { env_tag_values = { - for k, v in var.environment_names : - k => var.tag_values["environment/${v}"] + for k, v in var.environments : + k => var.tag_values["environment/${v.tag_name}"] } has_env_folders = var.folder_ids.security-dev != null iam_delegated = join(",", formatlist("'%s'", [ diff --git a/fast/stages/2-security/variables-fast.tf b/fast/stages/2-security/variables-fast.tf index 3b8c430baf..b8a664e52d 100644 --- a/fast/stages/2-security/variables-fast.tf +++ b/fast/stages/2-security/variables-fast.tf @@ -44,13 +44,21 @@ variable "custom_roles" { default = null } -variable "environment_names" { - # tfdoc:variable:source 1-resman - description = "Long environment names." - type = object({ - dev = string - prod = string - }) +variable "environments" { + # tfdoc:variable:source 0-globals + description = "Environment names." + type = map(object({ + name = string + tag_name = string + is_default = optional(bool, false) + })) + nullable = false + validation { + condition = anytrue([ + for k, v in var.environments : v.is_default == true + ]) + error_message = "At least one environment should be marked as default." + } } variable "folder_ids" { diff --git a/tests/fast/stages/s1_resman/simple.tfvars b/tests/fast/stages/s1_resman/simple.tfvars index 54d6599f14..f6463ade00 100644 --- a/tests/fast/stages/s1_resman/simple.tfvars +++ b/tests/fast/stages/s1_resman/simple.tfvars @@ -65,6 +65,18 @@ custom_roles = { service_project_network_admin = "organizations/123456789012/roles/xpnServiceAdmin" storage_viewer = "organizations/123456789012/roles/storageViewer" } +environments = { + dev = { + is_default = false + name = "Development" + tag_name = "development" + } + prod = { + is_default = true + name = "Production" + tag_name = "production" + } +} logging = { project_id = "fast-prod-log-audit-0" } diff --git a/tests/fast/stages/s2_networking_a_simple/ncc.tfvars b/tests/fast/stages/s2_networking_a_simple/ncc.tfvars index fbeb64edec..ff17f10356 100644 --- a/tests/fast/stages/s2_networking_a_simple/ncc.tfvars +++ b/tests/fast/stages/s2_networking_a_simple/ncc.tfvars @@ -13,9 +13,17 @@ dns = { enable_logging = true } enable_cloud_nat = true -environment_names = { - dev = "development" - prod = "production" +environments = { + dev = { + is_default = false + name = "Development" + tag_name = "development" + } + prod = { + is_default = true + name = "Production" + tag_name = "production" + } } essential_contacts = "gcp-network-admins@fast.example.com" folder_ids = { diff --git a/tests/fast/stages/s2_networking_a_simple/simple.tfvars b/tests/fast/stages/s2_networking_a_simple/simple.tfvars index d30f96002c..99e2cb2cba 100644 --- a/tests/fast/stages/s2_networking_a_simple/simple.tfvars +++ b/tests/fast/stages/s2_networking_a_simple/simple.tfvars @@ -13,9 +13,17 @@ dns = { enable_logging = true } enable_cloud_nat = true -environment_names = { - dev = "development" - prod = "production" +environments = { + dev = { + is_default = false + name = "Development" + tag_name = "development" + } + prod = { + is_default = true + name = "Production" + tag_name = "production" + } } essential_contacts = "gcp-network-admins@fast.example.com" folder_ids = { diff --git a/tests/fast/stages/s2_networking_a_simple/vpn.tfvars b/tests/fast/stages/s2_networking_a_simple/vpn.tfvars index ca1d95f1bc..764902a0a1 100644 --- a/tests/fast/stages/s2_networking_a_simple/vpn.tfvars +++ b/tests/fast/stages/s2_networking_a_simple/vpn.tfvars @@ -13,9 +13,17 @@ dns = { enable_logging = true } enable_cloud_nat = true -environment_names = { - dev = "development" - prod = "production" +environments = { + dev = { + is_default = false + name = "Development" + tag_name = "development" + } + prod = { + is_default = true + name = "Production" + tag_name = "production" + } } essential_contacts = "gcp-network-admins@fast.example.com" folder_ids = { diff --git a/tests/fast/stages/s2_networking_b_nva/ncc-ra.tfvars b/tests/fast/stages/s2_networking_b_nva/ncc-ra.tfvars index 753714600a..a1e74c195c 100644 --- a/tests/fast/stages/s2_networking_b_nva/ncc-ra.tfvars +++ b/tests/fast/stages/s2_networking_b_nva/ncc-ra.tfvars @@ -14,9 +14,17 @@ dns = { } enable_cloud_nat = true enable_test_instances = true -environment_names = { - dev = "development" - prod = "production" +environments = { + dev = { + is_default = false + name = "Development" + tag_name = "development" + } + prod = { + is_default = true + name = "Production" + tag_name = "production" + } } essential_contacts = "gcp-network-admins@fast.example.com" folder_ids = { diff --git a/tests/fast/stages/s2_networking_b_nva/regional.tfvars b/tests/fast/stages/s2_networking_b_nva/regional.tfvars index 4ed15f256f..e8d4e4ce2e 100644 --- a/tests/fast/stages/s2_networking_b_nva/regional.tfvars +++ b/tests/fast/stages/s2_networking_b_nva/regional.tfvars @@ -14,9 +14,17 @@ dns = { } enable_cloud_nat = true enable_test_instances = true -environment_names = { - dev = "development" - prod = "production" +environments = { + dev = { + is_default = false + name = "Development" + tag_name = "development" + } + prod = { + is_default = true + name = "Production" + tag_name = "production" + } } essential_contacts = "gcp-network-admins@fast.example.com" folder_ids = { diff --git a/tests/fast/stages/s2_networking_b_nva/simple.tfvars b/tests/fast/stages/s2_networking_b_nva/simple.tfvars index 60a072595e..d4ca2fa9da 100644 --- a/tests/fast/stages/s2_networking_b_nva/simple.tfvars +++ b/tests/fast/stages/s2_networking_b_nva/simple.tfvars @@ -14,9 +14,17 @@ dns = { } enable_cloud_nat = true enable_test_instances = true -environment_names = { - dev = "development" - prod = "production" +environments = { + dev = { + is_default = false + name = "Development" + tag_name = "development" + } + prod = { + is_default = true + name = "Production" + tag_name = "production" + } } essential_contacts = "gcp-network-admins@fast.example.com" folder_ids = { diff --git a/tests/fast/stages/s2_networking_c_separate_envs/simple.tfvars b/tests/fast/stages/s2_networking_c_separate_envs/simple.tfvars index 6ef02cfcff..74b8a4387b 100644 --- a/tests/fast/stages/s2_networking_c_separate_envs/simple.tfvars +++ b/tests/fast/stages/s2_networking_c_separate_envs/simple.tfvars @@ -14,9 +14,17 @@ dns = { enable_logging = true } enable_cloud_nat = true -environment_names = { - dev = "development" - prod = "production" +environments = { + dev = { + is_default = false + name = "Development" + tag_name = "development" + } + prod = { + is_default = true + name = "Production" + tag_name = "production" + } } essential_contacts = "gcp-network-admins@fast.example.com" folder_ids = { diff --git a/tests/fast/stages/s2_security/simple.tfvars b/tests/fast/stages/s2_security/simple.tfvars index 5fa1b94baa..8713d2693d 100644 --- a/tests/fast/stages/s2_security/simple.tfvars +++ b/tests/fast/stages/s2_security/simple.tfvars @@ -8,9 +8,17 @@ custom_roles = { project_iam_viewer = "organizations/123456789012/roles/bar" service_project_network_admin = "organizations/123456789012/roles/foo" } -environment_names = { - dev = "development" - prod = "production" +environments = { + dev = { + is_default = false + name = "Development" + tag_name = "development" + } + prod = { + is_default = true + name = "Production" + tag_name = "production" + } } essential_contacts = "gcp-security-admins@fast.example.com" folder_ids = { diff --git a/tools/changelog.py b/tools/changelog.py index d7f071245f..ef24066e56 100755 --- a/tools/changelog.py +++ b/tools/changelog.py @@ -275,8 +275,9 @@ def write_changelog(releases, links, rel_changes, release_as, release_to, rel_buffer.append('\n'.join(rel.content)) link_buffer.append(rel_link) open(filename, 'w').write( - '\n'.join([HEADING] + rel_buffer + - [''] + link_buffer)) + '\n'.join([HEADING] + rel_buffer + + [''] + link_buffer)) + @click.command @click.option('--merged-to', required=False, default=('master',), multiple=True,