Skip to content

Commit c8ebcf7

Browse files
julioccludoo
authored andcommitted
Support mulitple universes in bootstrap (GoogleCloudPlatform#2851)
* Initial support for universes in bootstrap * Add var description * Add universe to globals output * Fix typo * Update README * Allow universes to exclude services * Move service exclusion to project module * Move service exclusion loging to the project module --------- Co-authored-by: Ludovico Magnocavallo <[email protected]>
1 parent 4522b5c commit c8ebcf7

File tree

8 files changed

+99
-43
lines changed

8 files changed

+99
-43
lines changed

fast/stages/0-bootstrap/README.md

+15-14
Original file line numberDiff line numberDiff line change
@@ -687,23 +687,24 @@ FAST defines a simple mechanism to extend stage functionality via the use of [ad
687687
| [outputs_location](variables.tf#L286) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. | <code>string</code> | | <code>null</code> | |
688688
| [project_parent_ids](variables.tf#L301) | Optional parents for projects created here in folders/nnnnnnn format. Null values will use the organization as parent. | <code title="object&#40;&#123;&#10; automation &#61; optional&#40;string&#41;&#10; billing &#61; optional&#40;string&#41;&#10; logging &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> | |
689689
| [resource_names](variables.tf#L312) | Resource names overrides for specific resources. Prefix is always set via code, except where noted in the variable type. | <code title="object&#40;&#123;&#10; bq-billing &#61; optional&#40;string, &#34;billing_export&#34;&#41;&#10; bq-logs &#61; optional&#40;string, &#34;logs&#34;&#41;&#10; gcs-bootstrap &#61; optional&#40;string, &#34;prod-iac-core-bootstrap-0&#34;&#41;&#10; gcs-logs &#61; optional&#40;string, &#34;prod-logs&#34;&#41;&#10; gcs-outputs &#61; optional&#40;string, &#34;prod-iac-core-outputs-0&#34;&#41;&#10; gcs-resman &#61; optional&#40;string, &#34;prod-iac-core-resman-0&#34;&#41;&#10; gcs-vpcsc &#61; optional&#40;string, &#34;prod-iac-core-vpcsc-0&#34;&#41;&#10; project-automation &#61; optional&#40;string, &#34;prod-iac-core-0&#34;&#41;&#10; project-billing &#61; optional&#40;string, &#34;prod-billing-exp-0&#34;&#41;&#10; project-logs &#61; optional&#40;string, &#34;prod-audit-logs-0&#34;&#41;&#10; pubsub-logs_template &#61; optional&#40;string, &#34;&#36;&#36;&#123;key&#125;&#34;&#41;&#10; sa-bootstrap &#61; optional&#40;string, &#34;prod-bootstrap-0&#34;&#41;&#10; sa-bootstrap_ro &#61; optional&#40;string, &#34;prod-bootstrap-0r&#34;&#41;&#10; sa-cicd_template &#61; optional&#40;string, &#34;prod-&#36;&#36;&#123;key&#125;-1&#34;&#41;&#10; sa-cicd_template_ro &#61; optional&#40;string, &#34;prod-&#36;&#36;&#123;key&#125;-1r&#34;&#41;&#10; sa-resman &#61; optional&#40;string, &#34;prod-resman-0&#34;&#41;&#10; sa-resman_ro &#61; optional&#40;string, &#34;prod-resman-0r&#34;&#41;&#10; sa-vpcsc &#61; optional&#40;string, &#34;prod-vpcsc-0&#34;&#41;&#10; sa-vpcsc_ro &#61; optional&#40;string, &#34;prod-vpcsc-0r&#34;&#41;&#10; wf-bootstrap &#61; optional&#40;string, &#34;&#36;&#36;&#123;prefix&#125;-bootstrap&#34;&#41;&#10; wf-provider_template &#61; optional&#40;string, &#34;&#36;&#36;&#123;prefix&#125;-bootstrap-&#36;&#36;&#123;key&#125;&#34;&#41;&#10; wif-bootstrap &#61; optional&#40;string, &#34;&#36;&#36;&#123;prefix&#125;-bootstrap&#34;&#41;&#10; wif-provider_template &#61; optional&#40;string, &#34;&#36;&#36;&#123;prefix&#125;-bootstrap-&#36;&#36;&#123;key&#125;&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> | |
690-
| [workforce_identity_providers](variables.tf#L344) | Workforce Identity Federation pools. | <code title="map&#40;object&#40;&#123;&#10; attribute_condition &#61; optional&#40;string&#41;&#10; issuer &#61; string&#10; display_name &#61; string&#10; description &#61; string&#10; disabled &#61; optional&#40;bool, false&#41;&#10; saml &#61; optional&#40;object&#40;&#123;&#10; idp_metadata_xml &#61; string&#10; &#125;&#41;, null&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
691-
| [workload_identity_providers](variables.tf#L360) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | <code title="map&#40;object&#40;&#123;&#10; attribute_condition &#61; optional&#40;string&#41;&#10; issuer &#61; string&#10; custom_settings &#61; optional&#40;object&#40;&#123;&#10; issuer_uri &#61; optional&#40;string&#41;&#10; audiences &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; jwks_json &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
690+
| [universe](variables.tf#L344) | Target GCP universe. | <code title="object&#40;&#123;&#10; domain &#61; string&#10; prefix &#61; string&#10; unavailable_services &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> | |
691+
| [workforce_identity_providers](variables.tf#L354) | Workforce Identity Federation pools. | <code title="map&#40;object&#40;&#123;&#10; attribute_condition &#61; optional&#40;string&#41;&#10; issuer &#61; string&#10; display_name &#61; string&#10; description &#61; string&#10; disabled &#61; optional&#40;bool, false&#41;&#10; saml &#61; optional&#40;object&#40;&#123;&#10; idp_metadata_xml &#61; string&#10; &#125;&#41;, null&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
692+
| [workload_identity_providers](variables.tf#L370) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | <code title="map&#40;object&#40;&#123;&#10; attribute_condition &#61; optional&#40;string&#41;&#10; issuer &#61; string&#10; custom_settings &#61; optional&#40;object&#40;&#123;&#10; issuer_uri &#61; optional&#40;string&#41;&#10; audiences &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; jwks_json &#61; optional&#40;string&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
692693

693694
## Outputs
694695

695696
| name | description | sensitive | consumers |
696697
|---|---|:---:|---|
697-
| [automation](outputs.tf#L112) | Automation resources. | | |
698-
| [billing_dataset](outputs.tf#L117) | BigQuery dataset prepared for billing export. | | |
699-
| [cicd_repositories](outputs.tf#L122) | CI/CD repository configurations. | | |
700-
| [custom_roles](outputs.tf#L134) | Organization-level custom roles. | | |
701-
| [outputs_bucket](outputs.tf#L139) | GCS bucket where generated output files are stored. | | |
702-
| [project_ids](outputs.tf#L144) | Projects created by this stage. | | |
703-
| [providers](outputs.tf#L154) | Terraform provider files for this stage and dependent stages. || <code>stage-01</code> |
704-
| [service_accounts](outputs.tf#L161) | Automation service accounts created by this stage. | | |
705-
| [tfvars](outputs.tf#L170) | Terraform variable files for the following stages. || |
706-
| [tfvars_globals](outputs.tf#L176) | Terraform Globals variable files for the following stages. || |
707-
| [workforce_identity_pool](outputs.tf#L182) | Workforce Identity Federation pool. | | |
708-
| [workload_identity_pool](outputs.tf#L191) | Workload Identity Federation pool and providers. | | |
698+
| [automation](outputs.tf#L113) | Automation resources. | | |
699+
| [billing_dataset](outputs.tf#L118) | BigQuery dataset prepared for billing export. | | |
700+
| [cicd_repositories](outputs.tf#L123) | CI/CD repository configurations. | | |
701+
| [custom_roles](outputs.tf#L135) | Organization-level custom roles. | | |
702+
| [outputs_bucket](outputs.tf#L140) | GCS bucket where generated output files are stored. | | |
703+
| [project_ids](outputs.tf#L145) | Projects created by this stage. | | |
704+
| [providers](outputs.tf#L155) | Terraform provider files for this stage and dependent stages. || <code>stage-01</code> |
705+
| [service_accounts](outputs.tf#L162) | Automation service accounts created by this stage. | | |
706+
| [tfvars](outputs.tf#L171) | Terraform variable files for the following stages. || |
707+
| [tfvars_globals](outputs.tf#L177) | Terraform Globals variable files for the following stages. || |
708+
| [workforce_identity_pool](outputs.tf#L183) | Workforce Identity Federation pool. | | |
709+
| [workload_identity_pool](outputs.tf#L192) | Workload Identity Federation pool and providers. | | |
709710
<!-- END TFDOC -->

fast/stages/0-bootstrap/automation.tf

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ module "automation-project" {
2323
parent = coalesce(
2424
var.project_parent_ids.automation, "organizations/${var.organization.id}"
2525
)
26-
prefix = var.prefix
26+
prefix = var.prefix
27+
universe = var.universe
2728
contacts = (
2829
var.bootstrap_user != null || var.essential_contacts == null
2930
? {}

fast/stages/0-bootstrap/billing.tf

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024 Google LLC
2+
* Copyright 2025 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -47,7 +47,8 @@ module "billing-export-project" {
4747
parent = coalesce(
4848
var.project_parent_ids.billing, "organizations/${var.organization.id}"
4949
)
50-
prefix = var.prefix
50+
prefix = var.prefix
51+
universe = var.universe
5152
contacts = (
5253
var.bootstrap_user != null || var.essential_contacts == null
5354
? {}

fast/stages/0-bootstrap/log-export.tf

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024 Google LLC
2+
* Copyright 2025 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@ module "log-export-project" {
4343
var.project_parent_ids.logging, "organizations/${var.organization.id}"
4444
)
4545
prefix = var.prefix
46+
universe = var.universe
4647
billing_account = var.billing_account.id
4748
contacts = (
4849
var.bootstrap_user != null || var.essential_contacts == null

fast/stages/0-bootstrap/outputs-providers.tf

+55-20
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
# tfdoc:file:description Locals for provider output files.
1818

19+
# TODO: templates should probably use provider::terraform::encode_expr
20+
# (not jsonencode) to encode extras
21+
1922
locals {
2023
_parent_stage_resources = {
2124
"1-resman" = {
@@ -33,62 +36,94 @@ locals {
3336
# this stage's providers
3437
{
3538
"0-bootstrap" = templatefile(local._tpl_providers, {
36-
backend_extra = null
3739
bucket = module.automation-tf-bootstrap-gcs.name
3840
name = "bootstrap"
3941
sa = module.automation-tf-bootstrap-sa.email
42+
backend_extra = null
43+
provider_extra = var.universe == null ? null : {
44+
universe_domain = var.universe.domain
45+
}
4046
})
4147
"0-bootstrap-r" = templatefile(local._tpl_providers, {
42-
backend_extra = null
4348
bucket = module.automation-tf-bootstrap-gcs.name
4449
name = "bootstrap"
4550
sa = module.automation-tf-bootstrap-r-sa.email
51+
backend_extra = null
52+
provider_extra = var.universe == null ? null : {
53+
universe_domain = var.universe.domain
54+
}
4655
})
4756
},
4857
# stage 1 providers
4958
{
5059
"1-resman" = templatefile(local._tpl_providers, {
51-
backend_extra = null
5260
bucket = module.automation-tf-resman-gcs.name
5361
name = "resman"
5462
sa = module.automation-tf-resman-sa.email
63+
backend_extra = null
64+
provider_extra = var.universe == null ? null : {
65+
universe_domain = var.universe.domain
66+
}
5567
})
5668
"1-resman-r" = templatefile(local._tpl_providers, {
57-
backend_extra = null
5869
bucket = module.automation-tf-resman-gcs.name
5970
name = "resman"
6071
sa = module.automation-tf-resman-r-sa.email
72+
backend_extra = null
73+
provider_extra = var.universe == null ? null : {
74+
universe_domain = var.universe.domain
75+
}
6176
})
6277
"1-vpcsc" = templatefile(local._tpl_providers, {
63-
backend_extra = "prefix = \"vpcsc\""
64-
bucket = module.automation-tf-vpcsc-gcs.name
65-
name = "vpcsc"
66-
sa = module.automation-tf-vpcsc-sa.email
78+
bucket = module.automation-tf-vpcsc-gcs.name
79+
name = "vpcsc"
80+
sa = module.automation-tf-vpcsc-sa.email
81+
backend_extra = {
82+
prefix = "vpcsc"
83+
}
84+
provider_extra = var.universe == null ? null : {
85+
universe_domain = var.universe.domain
86+
}
6787
})
6888
"1-vpcsc-r" = templatefile(local._tpl_providers, {
69-
backend_extra = "prefix = \"vpcsc\""
70-
bucket = module.automation-tf-vpcsc-gcs.name
71-
name = "vpcsc"
72-
sa = module.automation-tf-vpcsc-r-sa.email
89+
bucket = module.automation-tf-vpcsc-gcs.name
90+
name = "vpcsc"
91+
sa = module.automation-tf-vpcsc-r-sa.email
92+
backend_extra = {
93+
prefix = "vpcsc"
94+
}
95+
provider_extra = var.universe == null ? null : {
96+
universe_domain = var.universe.domain
97+
}
7398
})
7499
},
75100
# stage 1 addons
76101
{
77102
for k, v in var.fast_addon :
78103
"${v.parent_stage}-${k}" => templatefile(local._tpl_providers, {
79-
backend_extra = "prefix = \"addons/${k}\""
80-
name = "${v.parent_stage}-${k}"
81-
bucket = local._parent_stage_resources[v.parent_stage].bucket
82-
sa = local._parent_stage_resources[v.parent_stage].sa
104+
name = "${v.parent_stage}-${k}"
105+
bucket = local._parent_stage_resources[v.parent_stage].bucket
106+
sa = local._parent_stage_resources[v.parent_stage].sa
107+
backend_extra = {
108+
prefix = "addons/${k}"
109+
}
110+
provider_extra = var.universe == null ? null : {
111+
universe_domain = var.universe.domain
112+
}
83113
})
84114
},
85115
{
86116
for k, v in var.fast_addon :
87117
"${v.parent_stage}-${k}-r" => templatefile(local._tpl_providers, {
88-
backend_extra = "prefix = \"addons/${k}\""
89-
name = "${v.parent_stage}-${k}"
90-
bucket = local._parent_stage_resources[v.parent_stage].bucket
91-
sa = local._parent_stage_resources[v.parent_stage].sa_r
118+
name = "${v.parent_stage}-${k}"
119+
bucket = local._parent_stage_resources[v.parent_stage].bucket
120+
sa = local._parent_stage_resources[v.parent_stage].sa_r
121+
backend_extra = {
122+
prefix = "addons/${k}"
123+
}
124+
provider_extra = var.universe == null ? null : {
125+
universe_domain = var.universe.domain
126+
}
92127
})
93128
}
94129
)

fast/stages/0-bootstrap/outputs.tf

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024 Google LLC
2+
* Copyright 2025 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -90,6 +90,7 @@ locals {
9090
split("/", k)[1] => v.id
9191
}
9292
}
93+
universe = var.universe
9394
}
9495
tfvars_globals = {
9596
billing_account = var.billing_account

fast/stages/0-bootstrap/templates/providers.tf.tpl

+9-3
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,22 @@ terraform {
1818
backend "gcs" {
1919
bucket = "${bucket}"
2020
impersonate_service_account = "${sa}"
21-
%{~ if backend_extra != null ~}
22-
${indent(4, backend_extra)}
23-
%{~ endif ~}
21+
%{~ for k, v in coalesce(backend_extra, {}) ~}
22+
${k} = ${jsonencode(v)}
23+
%{~ endfor ~}
2424
}
2525
}
2626
provider "google" {
2727
impersonate_service_account = "${sa}"
28+
%{~ for k, v in coalesce(provider_extra, {}) ~}
29+
${k} = ${jsonencode(v)}
30+
%{~ endfor ~}
2831
}
2932
provider "google-beta" {
3033
impersonate_service_account = "${sa}"
34+
%{~ for k, v in coalesce(provider_extra, {}) ~}
35+
${k} = ${jsonencode(v)}
36+
%{~ endfor ~}
3137
}
3238

3339
# end provider.tf for ${name}

fast/stages/0-bootstrap/variables.tf

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2024 Google LLC
2+
* Copyright 2025 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -341,6 +341,16 @@ variable "resource_names" {
341341
default = {}
342342
}
343343

344+
variable "universe" {
345+
description = "Target GCP universe."
346+
type = object({
347+
domain = string
348+
prefix = string
349+
unavailable_services = optional(list(string), [])
350+
})
351+
default = null
352+
}
353+
344354
variable "workforce_identity_providers" {
345355
description = "Workforce Identity Federation pools."
346356
type = map(object({

0 commit comments

Comments
 (0)