diff --git a/fast/stages/00-bootstrap/README.md b/fast/stages/00-bootstrap/README.md
index 7280a34bf1..5b7f495d79 100644
--- a/fast/stages/00-bootstrap/README.md
+++ b/fast/stages/00-bootstrap/README.md
@@ -461,31 +461,32 @@ 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 and organization id ('nnnnnnnn' or null). | object({…})
| ✓ | | |
-| [organization](variables.tf#L162) | Organization details. | object({…})
| ✓ | | |
-| [prefix](variables.tf#L177) | Prefix used for resources that need unique names. Use 9 characters or less. | string
| ✓ | | |
+| [organization](variables.tf#L179) | Organization details. | object({…})
| ✓ | | |
+| [prefix](variables.tf#L194) | Prefix used for resources that need unique names. Use 9 characters or less. | string
| ✓ | | |
| [bootstrap_user](variables.tf#L25) | Email of the nominal user running this stage for the first time. | string
| | null
| |
| [cicd_repositories](variables.tf#L31) | 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_role_names](variables.tf#L83) | Names of custom roles defined at the org level. | object({…})
| | {…}
| |
-| [federated_identity_providers](variables.tf#L95) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…}))
| | {}
| |
-| [groups](variables.tf#L109) | Group names to grant organization-level permissions. | map(string)
| | {…}
| |
-| [iam](variables.tf#L123) | Organization-level custom IAM settings in role => [principal] format. | map(list(string))
| | {}
| |
-| [iam_additive](variables.tf#L129) | Organization-level custom IAM settings in role => [principal] format for non-authoritative bindings. | map(list(string))
| | {}
| |
-| [log_sinks](variables.tf#L137) | Org-level log sinks, in name => {type, filter} format. | map(object({…}))
| | {…}
| |
-| [outputs_location](variables.tf#L171) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable | string
| | null
| |
+| [fast_features](variables.tf#L95) | Selective control for top-level FAST features. | object({…})
| | {…}
| |
+| [federated_identity_providers](variables.tf#L112) | Workload Identity Federation pools. The `cicd_repositories` variable references keys here. | map(object({…}))
| | {}
| |
+| [groups](variables.tf#L126) | Group names to grant organization-level permissions. | map(string)
| | {…}
| |
+| [iam](variables.tf#L140) | Organization-level custom IAM settings in role => [principal] format. | map(list(string))
| | {}
| |
+| [iam_additive](variables.tf#L146) | Organization-level custom IAM settings in role => [principal] format for non-authoritative bindings. | map(list(string))
| | {}
| |
+| [log_sinks](variables.tf#L154) | Org-level log sinks, in name => {type, filter} format. | map(object({…}))
| | {…}
| |
+| [outputs_location](variables.tf#L188) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable | string
| | null
| |
## Outputs
| name | description | sensitive | consumers |
|---|---|:---:|---|
-| [automation](outputs.tf#L87) | Automation resources. | | |
-| [billing_dataset](outputs.tf#L92) | BigQuery dataset prepared for billing export. | | |
-| [cicd_repositories](outputs.tf#L97) | CI/CD repository configurations. | | |
-| [custom_roles](outputs.tf#L109) | Organization-level custom roles. | | |
-| [federated_identity](outputs.tf#L114) | Workload Identity Federation pool and providers. | | |
-| [outputs_bucket](outputs.tf#L124) | GCS bucket where generated output files are stored. | | |
-| [project_ids](outputs.tf#L129) | Projects created by this stage. | | |
-| [providers](outputs.tf#L149) | Terraform provider files for this stage and dependent stages. | ✓ | stage-01
|
-| [service_accounts](outputs.tf#L138) | Automation service accounts created by this stage. | | |
-| [tfvars](outputs.tf#L158) | Terraform variable files for the following stages. | ✓ | |
+| [automation](outputs.tf#L88) | Automation resources. | | |
+| [billing_dataset](outputs.tf#L93) | BigQuery dataset prepared for billing export. | | |
+| [cicd_repositories](outputs.tf#L98) | CI/CD repository configurations. | | |
+| [custom_roles](outputs.tf#L110) | Organization-level custom roles. | | |
+| [federated_identity](outputs.tf#L115) | Workload Identity Federation pool and providers. | | |
+| [outputs_bucket](outputs.tf#L125) | GCS bucket where generated output files are stored. | | |
+| [project_ids](outputs.tf#L130) | Projects created by this stage. | | |
+| [providers](outputs.tf#L150) | Terraform provider files for this stage and dependent stages. | ✓ | stage-01
|
+| [service_accounts](outputs.tf#L139) | Automation service accounts created by this stage. | | |
+| [tfvars](outputs.tf#L159) | Terraform variable files for the following stages. | ✓ | |
diff --git a/fast/stages/00-bootstrap/outputs.tf b/fast/stages/00-bootstrap/outputs.tf
index eceb5f8202..28e0e4d776 100644
--- a/fast/stages/00-bootstrap/outputs.tf
+++ b/fast/stages/00-bootstrap/outputs.tf
@@ -68,6 +68,7 @@ locals {
}
tfvars_globals = {
billing_account = var.billing_account
+ fast_features = var.fast_features
groups = var.groups
organization = var.organization
prefix = var.prefix
diff --git a/fast/stages/00-bootstrap/variables.tf b/fast/stages/00-bootstrap/variables.tf
index f2f1edcd57..e9cc26e352 100644
--- a/fast/stages/00-bootstrap/variables.tf
+++ b/fast/stages/00-bootstrap/variables.tf
@@ -92,6 +92,23 @@ variable "custom_role_names" {
}
}
+variable "fast_features" {
+ description = "Selective control for top-level FAST features."
+ type = object({
+ data_platform = bool
+ project_factory = bool
+ sandbox = bool
+ teams = bool
+ })
+ default = {
+ data_platform = true
+ project_factory = true
+ sandbox = true
+ teams = true
+ }
+ nullable = false
+}
+
variable "federated_identity_providers" {
description = "Workload Identity Federation pools. The `cicd_repositories` variable references keys here."
type = map(object({
diff --git a/fast/stages/00-cicd/README.md b/fast/stages/00-cicd/README.md
index 54c2b7241b..a0b9273352 100644
--- a/fast/stages/00-cicd/README.md
+++ b/fast/stages/00-cicd/README.md
@@ -1,11 +1,10 @@
# CI/CD bootstrap
-The primary purpose of this stage is to set up your CI/CD project structure automatically, with most of the
-necessary configuration to run the pipelines out of the box.
+The primary purpose of this stage is to set up your CI/CD project structure automatically, with most of the necessary configuration to run the pipelines out of the box.
## How to run this stage
-This stage is meant to be executed after the [bootstrap](../00-bootstrap) stage has run, as it leverages the automation service account and bucket created there.
+This stage is meant to be executed after the [bootstrap](../00-bootstrap) stage has run, as it leverages the automation service account and bucket created there.
The entire stage is optional, you may also choose to create your repositories manually.
### Providers configuration
@@ -51,7 +50,7 @@ cp ../00-bootstrap/terraform.tfvars .
A second set of variables is specific to this stage, they are all optional so if you need to customize them, create an extra `terraform.tfvars` file or add them to the file copied from bootstrap.
-Refer to the [Variables](#variables) table at the bottom of this document, for a full list of variables, their origin (e.g. a stage or specific to this one), and descriptions explaining their meaning. The sections below also describe some of the possible customizations.
+Refer to the [Variables](#variables) table at the bottom of this document, for a full list of variables, their origin (e.g. a stage or specific to this one), and descriptions explaining their meaning. The sections below also describe some of the possible customizations.
### CI/CD systems
@@ -89,7 +88,7 @@ and such, the `00-cicd` stage creates all the repositories in your CI/CD system
configuration is essentially a combination of all the `cicd_repositories` variables of the other stages
plus additional CI/CD system specific configuration information.
-This is an example of configuring the repositories in this stage.
+This is an example of configuring the repositories in this stage.
```hcl
cicd_repositories = {
@@ -163,7 +162,6 @@ The `type` attribute can be set to one of the supported repository types: `githu
Once the stage is applied the generated output files will contain pre-configured workflow files for each repository, that will use Workload Identity Federation via a dedicated service account for each repository to impersonate the automation service account for the stage.
-
Once done, you can run this stage:
```bash
diff --git a/fast/stages/01-resman/README.md b/fast/stages/01-resman/README.md
index a054106f61..60e429d744 100644
--- a/fast/stages/01-resman/README.md
+++ b/fast/stages/01-resman/README.md
@@ -160,13 +160,14 @@ Due to its simplicity, this stage lends itself easily to customizations: adding
| [billing.tf](./billing.tf) | Billing resources for external billing use cases. | organization
| google_billing_account_iam_member
|
| [branch-data-platform.tf](./branch-data-platform.tf) | Data Platform stages resources. | folder
· gcs
· iam-service-account
| |
| [branch-networking.tf](./branch-networking.tf) | Networking stage resources. | folder
· gcs
· iam-service-account
| |
+| [branch-project-factory.tf](./branch-project-factory.tf) | Project factory stage resources. | gcs
· iam-service-account
| |
| [branch-sandbox.tf](./branch-sandbox.tf) | Sandbox stage resources. | folder
· gcs
· iam-service-account
| |
| [branch-security.tf](./branch-security.tf) | Security stage resources. | folder
· gcs
· iam-service-account
| |
| [branch-teams.tf](./branch-teams.tf) | Team stage resources. | folder
· gcs
· iam-service-account
| |
| [cicd-data-platform.tf](./cicd-data-platform.tf) | CI/CD resources for the data platform branch. | iam-service-account
· source-repository
| |
| [cicd-networking.tf](./cicd-networking.tf) | CI/CD resources for the networking branch. | iam-service-account
· source-repository
| |
+| [cicd-project-factory.tf](./cicd-project-factory.tf) | CI/CD resources for the teams branch. | iam-service-account
· source-repository
| |
| [cicd-security.tf](./cicd-security.tf) | CI/CD resources for the security branch. | iam-service-account
· source-repository
| |
-| [cicd-teams.tf](./cicd-teams.tf) | CI/CD resources for the teams branch. | iam-service-account
· source-repository
| |
| [main.tf](./main.tf) | Module-level locals and resources. | | |
| [organization.tf](./organization.tf) | Organization policies. | organization
| google_organization_iam_member
|
| [outputs-files.tf](./outputs-files.tf) | Output files persistence to local filesystem. | | local_file
|
@@ -180,28 +181,29 @@ Due to its simplicity, this stage lends itself easily to customizations: adding
|---|---|:---:|:---:|:---:|:---:|
| [automation](variables.tf#L20) | Automation resources created by the bootstrap stage. | object({…})
| ✓ | | 00-bootstrap
|
| [billing_account](variables.tf#L38) | Billing account id and organization id ('nnnnnnnn' or null). | object({…})
| ✓ | | 00-bootstrap
|
-| [organization](variables.tf#L141) | Organization details. | object({…})
| ✓ | | 00-bootstrap
|
-| [prefix](variables.tf#L165) | Prefix used for resources that need unique names. Use 9 characters or less. | string
| ✓ | | 00-bootstrap
|
+| [organization](variables.tf#L159) | Organization details. | object({…})
| ✓ | | 00-bootstrap
|
+| [prefix](variables.tf#L183) | Prefix used for resources that need unique names. Use 9 characters or less. | string
| ✓ | | 00-bootstrap
|
| [cicd_repositories](variables.tf#L47) | CI/CD repository configuration. Identity providers reference keys in the `automation.federated_identity_providers` variable. Set to null to disable, or set individual repositories to null if not needed. | object({…})
| | null
| |
| [custom_roles](variables.tf#L117) | Custom roles defined at the org level, in key => id format. | object({…})
| | null
| 00-bootstrap
|
-| [groups](variables.tf#L126) | Group names to grant organization-level permissions. | map(string)
| | {…}
| 00-bootstrap
|
-| [organization_policy_configs](variables.tf#L151) | Organization policies customization. | object({…})
| | null
| |
-| [outputs_location](variables.tf#L159) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable | string
| | null
| |
-| [tag_names](variables.tf#L176) | Customized names for resource management tags. | object({…})
| | {…}
| |
-| [team_folders](variables.tf#L193) | Team folders to be created. Format is described in a code comment. | map(object({…}))
| | null
| |
+| [fast_features](variables.tf#L126) | Selective control for top-level FAST features. | object({…})
| | {…}
| 00-bootstrap
|
+| [groups](variables.tf#L144) | Group names to grant organization-level permissions. | map(string)
| | {…}
| 00-bootstrap
|
+| [organization_policy_configs](variables.tf#L169) | Organization policies customization. | object({…})
| | null
| |
+| [outputs_location](variables.tf#L177) | Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable | string
| | null
| |
+| [tag_names](variables.tf#L194) | Customized names for resource management tags. | object({…})
| | {…}
| |
+| [team_folders](variables.tf#L211) | Team folders to be created. Format is described in a code comment. | map(object({…}))
| | null
| |
## Outputs
| name | description | sensitive | consumers |
|---|---|:---:|---|
-| [cicd_repositories](outputs.tf#L145) | WIF configuration for CI/CD repositories. | | |
-| [dataplatform](outputs.tf#L159) | Data for the Data Platform stage. | | |
-| [networking](outputs.tf#L175) | Data for the networking stage. | | |
-| [project_factories](outputs.tf#L184) | Data for the project factories stage. | | |
-| [providers](outputs.tf#L200) | Terraform provider files for this stage and dependent stages. | ✓ | 02-networking
· 02-security
· 03-dataplatform
· xx-sandbox
· xx-teams
|
-| [sandbox](outputs.tf#L207) | Data for the sandbox stage. | | xx-sandbox
|
-| [security](outputs.tf#L217) | Data for the networking stage. | | 02-security
|
-| [teams](outputs.tf#L227) | Data for the teams stage. | | |
-| [tfvars](outputs.tf#L240) | Terraform variable files for the following stages. | ✓ | |
+| [cicd_repositories](outputs.tf#L154) | WIF configuration for CI/CD repositories. | | |
+| [dataplatform](outputs.tf#L168) | Data for the Data Platform stage. | | |
+| [networking](outputs.tf#L184) | Data for the networking stage. | | |
+| [project_factories](outputs.tf#L193) | Data for the project factories stage. | | |
+| [providers](outputs.tf#L209) | Terraform provider files for this stage and dependent stages. | ✓ | 02-networking
· 02-security
· 03-dataplatform
· xx-sandbox
· xx-teams
|
+| [sandbox](outputs.tf#L216) | Data for the sandbox stage. | | xx-sandbox
|
+| [security](outputs.tf#L230) | Data for the networking stage. | | 02-security
|
+| [teams](outputs.tf#L240) | Data for the teams stage. | | |
+| [tfvars](outputs.tf#L253) | Terraform variable files for the following stages. | ✓ | |
diff --git a/fast/stages/01-resman/branch-data-platform.tf b/fast/stages/01-resman/branch-data-platform.tf
index 84e6d81ee2..237f8fb173 100644
--- a/fast/stages/01-resman/branch-data-platform.tf
+++ b/fast/stages/01-resman/branch-data-platform.tf
@@ -16,8 +16,14 @@
# tfdoc:file:description Data Platform stages resources.
+moved {
+ from = module.branch-dp-folder
+ to = module.branch-dp-folder.0
+}
+
module "branch-dp-folder" {
source = "../../../modules/folder"
+ count = var.fast_features.data_platform ? 1 : 0
parent = "organizations/${var.organization.id}"
name = "Data Platform"
tag_bindings = {
@@ -27,18 +33,26 @@ module "branch-dp-folder" {
}
}
+moved {
+ from = module.branch-dp-dev-folder
+ to = module.branch-dp-dev-folder.0
+}
+
module "branch-dp-dev-folder" {
source = "../../../modules/folder"
- parent = module.branch-dp-folder.id
+ count = var.fast_features.data_platform ? 1 : 0
+ parent = module.branch-dp-folder.0.id
name = "Development"
group_iam = {}
iam = {
- (local.custom_roles.service_project_network_admin) = [module.branch-dp-dev-sa.iam_email]
+ (local.custom_roles.service_project_network_admin) = [
+ module.branch-dp-dev-sa.0.iam_email
+ ]
# remove owner here and at project level if SA does not manage project resources
- "roles/owner" = [module.branch-dp-dev-sa.iam_email]
- "roles/logging.admin" = [module.branch-dp-dev-sa.iam_email]
- "roles/resourcemanager.folderAdmin" = [module.branch-dp-dev-sa.iam_email]
- "roles/resourcemanager.projectCreator" = [module.branch-dp-dev-sa.iam_email]
+ "roles/owner" = [module.branch-dp-dev-sa.0.iam_email]
+ "roles/logging.admin" = [module.branch-dp-dev-sa.0.iam_email]
+ "roles/resourcemanager.folderAdmin" = [module.branch-dp-dev-sa.0.iam_email]
+ "roles/resourcemanager.projectCreator" = [module.branch-dp-dev-sa.0.iam_email]
}
tag_bindings = {
context = try(
@@ -47,18 +61,24 @@ module "branch-dp-dev-folder" {
}
}
+moved {
+ from = module.branch-dp-prod-folder
+ to = module.branch-dp-prod-folder.0
+}
+
module "branch-dp-prod-folder" {
source = "../../../modules/folder"
- parent = module.branch-dp-folder.id
+ count = var.fast_features.data_platform ? 1 : 0
+ parent = module.branch-dp-folder.0.id
name = "Production"
group_iam = {}
iam = {
- (local.custom_roles.service_project_network_admin) = [module.branch-dp-prod-sa.iam_email]
+ (local.custom_roles.service_project_network_admin) = [module.branch-dp-prod-sa.0.iam_email]
# remove owner here and at project level if SA does not manage project resources
- "roles/owner" = [module.branch-dp-prod-sa.iam_email]
- "roles/logging.admin" = [module.branch-dp-prod-sa.iam_email]
- "roles/resourcemanager.folderAdmin" = [module.branch-dp-prod-sa.iam_email]
- "roles/resourcemanager.projectCreator" = [module.branch-dp-prod-sa.iam_email]
+ "roles/owner" = [module.branch-dp-prod-sa.0.iam_email]
+ "roles/logging.admin" = [module.branch-dp-prod-sa.0.iam_email]
+ "roles/resourcemanager.folderAdmin" = [module.branch-dp-prod-sa.0.iam_email]
+ "roles/resourcemanager.projectCreator" = [module.branch-dp-prod-sa.0.iam_email]
}
tag_bindings = {
context = try(
@@ -69,8 +89,14 @@ module "branch-dp-prod-folder" {
# automation service accounts and buckets
+moved {
+ from = module.branch-dp-dev-sa
+ to = module.branch-dp-dev-sa.0
+}
+
module "branch-dp-dev-sa" {
source = "../../../modules/iam-service-account"
+ count = var.fast_features.data_platform ? 1 : 0
project_id = var.automation.project_id
name = "dev-resman-dp-0"
description = "Terraform data platform development service account."
@@ -85,8 +111,14 @@ module "branch-dp-dev-sa" {
}
}
+moved {
+ from = module.branch-dp-prod-sa
+ to = module.branch-dp-prod-sa.0
+}
+
module "branch-dp-prod-sa" {
source = "../../../modules/iam-service-account"
+ count = var.fast_features.data_platform ? 1 : 0
project_id = var.automation.project_id
name = "prod-resman-dp-0"
description = "Terraform data platform production service account."
@@ -101,24 +133,36 @@ module "branch-dp-prod-sa" {
}
}
+moved {
+ from = module.branch-dp-dev-gcs
+ to = module.branch-dp-dev-gcs.0
+}
+
module "branch-dp-dev-gcs" {
source = "../../../modules/gcs"
+ count = var.fast_features.data_platform ? 1 : 0
project_id = var.automation.project_id
name = "dev-resman-dp-0"
prefix = var.prefix
versioning = true
iam = {
- "roles/storage.objectAdmin" = [module.branch-dp-dev-sa.iam_email]
+ "roles/storage.objectAdmin" = [module.branch-dp-dev-sa.0.iam_email]
}
}
+moved {
+ from = module.branch-dp-prod-gcs
+ to = module.branch-dp-prod-gcs.0
+}
+
module "branch-dp-prod-gcs" {
source = "../../../modules/gcs"
+ count = var.fast_features.data_platform ? 1 : 0
project_id = var.automation.project_id
name = "prod-resman-dp-0"
prefix = var.prefix
versioning = true
iam = {
- "roles/storage.objectAdmin" = [module.branch-dp-prod-sa.iam_email]
+ "roles/storage.objectAdmin" = [module.branch-dp-prod-sa.0.iam_email]
}
}
diff --git a/fast/stages/01-resman/branch-networking.tf b/fast/stages/01-resman/branch-networking.tf
index 8757e7f894..684079fad9 100644
--- a/fast/stages/01-resman/branch-networking.tf
+++ b/fast/stages/01-resman/branch-networking.tf
@@ -50,10 +50,10 @@ module "branch-network-prod-folder" {
parent = module.branch-network-folder.id
name = "Production"
iam = {
- "roles/compute.xpnAdmin" = [
- module.branch-dp-prod-sa.iam_email,
- module.branch-teams-prod-pf-sa.iam_email
- ]
+ "roles/compute.xpnAdmin" = compact([
+ try(module.branch-dp-prod-sa.0.iam_email, ""),
+ try(module.branch-pf-prod-sa.0.iam_email, ""),
+ ])
}
tag_bindings = {
environment = try(
@@ -67,10 +67,10 @@ module "branch-network-dev-folder" {
parent = module.branch-network-folder.id
name = "Development"
iam = {
- (local.custom_roles.service_project_network_admin) = [
- module.branch-dp-dev-sa.iam_email,
- module.branch-teams-dev-pf-sa.iam_email
- ]
+ (local.custom_roles.service_project_network_admin) = compact([
+ try(module.branch-dp-dev-sa.0.iam_email, ""),
+ try(module.branch-pf-dev-sa.0.iam_email, ""),
+ ])
}
tag_bindings = {
environment = try(
diff --git a/fast/stages/01-resman/branch-project-factory.tf b/fast/stages/01-resman/branch-project-factory.tf
new file mode 100644
index 0000000000..819fbcb85d
--- /dev/null
+++ b/fast/stages/01-resman/branch-project-factory.tf
@@ -0,0 +1,97 @@
+/**
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+# tfdoc:file:description Project factory stage resources.
+
+moved {
+ from = module.branch-teams-dev-pf-sa
+ to = module.branch-pf-dev-sa.0
+}
+
+module "branch-pf-dev-sa" {
+ source = "../../../modules/iam-service-account"
+ count = var.fast_features.project_factory ? 1 : 0
+ project_id = var.automation.project_id
+ name = "dev-resman-pf-0"
+ # naming: environment in description
+ description = "Terraform project factory development service account."
+ prefix = var.prefix
+ iam = {
+ "roles/iam.serviceAccountTokenCreator" = compact([
+ try(module.branch-pf-dev-sa-cicd.0.iam_email, null)
+ ])
+ }
+ iam_storage_roles = {
+ (var.automation.outputs_bucket) = ["roles/storage.admin"]
+ }
+}
+
+moved {
+ from = module.branch-teams-prod-pf-sa
+ to = module.branch-pf-prod-sa.0
+}
+
+module "branch-pf-prod-sa" {
+ source = "../../../modules/iam-service-account"
+ count = var.fast_features.project_factory ? 1 : 0
+ project_id = var.automation.project_id
+ name = "prod-resman-pf-0"
+ # naming: environment in description
+ description = "Terraform project factory production service account."
+ prefix = var.prefix
+ iam = {
+ "roles/iam.serviceAccountTokenCreator" = compact([
+ try(module.branch-pf-prod-sa-cicd.0.iam_email, null)
+ ])
+ }
+ iam_storage_roles = {
+ (var.automation.outputs_bucket) = ["roles/storage.admin"]
+ }
+}
+
+moved {
+ from = module.branch-teams-dev-pf-gcs
+ to = module.branch-pf-dev-gcs.0
+}
+
+module "branch-pf-dev-gcs" {
+ source = "../../../modules/gcs"
+ count = var.fast_features.project_factory ? 1 : 0
+ project_id = var.automation.project_id
+ name = "dev-resman-pf-0"
+ prefix = var.prefix
+ versioning = true
+ iam = {
+ "roles/storage.objectAdmin" = [module.branch-pf-dev-sa.0.iam_email]
+ }
+}
+
+moved {
+ from = module.branch-teams-prod-pf-gcs
+ to = module.branch-pf-prod-gcs.0
+}
+
+module "branch-pf-prod-gcs" {
+ source = "../../../modules/gcs"
+ count = var.fast_features.project_factory ? 1 : 0
+ project_id = var.automation.project_id
+ name = "prod-resman-pf-0"
+ prefix = var.prefix
+ versioning = true
+ iam = {
+ "roles/storage.objectAdmin" = [module.branch-pf-prod-sa.0.iam_email]
+ }
+}
diff --git a/fast/stages/01-resman/branch-sandbox.tf b/fast/stages/01-resman/branch-sandbox.tf
index f2ba0bfb14..06624ec783 100644
--- a/fast/stages/01-resman/branch-sandbox.tf
+++ b/fast/stages/01-resman/branch-sandbox.tf
@@ -16,15 +16,21 @@
# tfdoc:file:description Sandbox stage resources.
+moved {
+ from = module.branch-sandbox-folder
+ to = module.branch-sandbox-folder.0
+}
+
module "branch-sandbox-folder" {
source = "../../../modules/folder"
+ count = var.fast_features.sandbox ? 1 : 0
parent = "organizations/${var.organization.id}"
name = "Sandbox"
iam = {
- "roles/logging.admin" = [module.branch-sandbox-sa.iam_email]
- "roles/owner" = [module.branch-sandbox-sa.iam_email]
- "roles/resourcemanager.folderAdmin" = [module.branch-sandbox-sa.iam_email]
- "roles/resourcemanager.projectCreator" = [module.branch-sandbox-sa.iam_email]
+ "roles/logging.admin" = [module.branch-sandbox-sa.0.iam_email]
+ "roles/owner" = [module.branch-sandbox-sa.0.iam_email]
+ "roles/resourcemanager.folderAdmin" = [module.branch-sandbox-sa.0.iam_email]
+ "roles/resourcemanager.projectCreator" = [module.branch-sandbox-sa.0.iam_email]
}
policy_boolean = {
"constraints/sql.restrictPublicIp" = false
@@ -44,19 +50,31 @@ module "branch-sandbox-folder" {
}
}
+moved {
+ from = module.branch-sandbox-gcs
+ to = module.branch-sandbox-gcs.0
+}
+
module "branch-sandbox-gcs" {
source = "../../../modules/gcs"
+ count = var.fast_features.sandbox ? 1 : 0
project_id = var.automation.project_id
name = "dev-resman-sbox-0"
prefix = var.prefix
versioning = true
iam = {
- "roles/storage.objectAdmin" = [module.branch-sandbox-sa.iam_email]
+ "roles/storage.objectAdmin" = [module.branch-sandbox-sa.0.iam_email]
}
}
+moved {
+ from = module.branch-sandbox-sa
+ to = module.branch-sandbox-sa.0
+}
+
module "branch-sandbox-sa" {
source = "../../../modules/iam-service-account"
+ count = var.fast_features.sandbox ? 1 : 0
project_id = var.automation.project_id
name = "dev-resman-sbox-0"
description = "Terraform resman sandbox service account."
diff --git a/fast/stages/01-resman/branch-teams.tf b/fast/stages/01-resman/branch-teams.tf
index 465255be63..3c9a2d6968 100644
--- a/fast/stages/01-resman/branch-teams.tf
+++ b/fast/stages/01-resman/branch-teams.tf
@@ -16,8 +16,14 @@
# tfdoc:file:description Team stage resources.
+moved {
+ from = module.branch-teams-folder
+ to = module.branch-teams-folder.0
+}
+
module "branch-teams-folder" {
source = "../../../modules/folder"
+ count = var.fast_features.teams ? 1 : 0
parent = "organizations/${var.organization.id}"
name = "Teams"
tag_bindings = {
@@ -27,8 +33,14 @@ module "branch-teams-folder" {
}
}
+moved {
+ from = module.branch-teams-prod-sa
+ to = module.branch-teams-prod-sa.0
+}
+
module "branch-teams-prod-sa" {
source = "../../../modules/iam-service-account"
+ count = var.fast_features.teams ? 1 : 0
project_id = var.automation.project_id
name = "prod-resman-teams-0"
description = "Terraform resman production service account."
@@ -39,15 +51,15 @@ module "branch-teams-prod-sa" {
module "branch-teams-team-folder" {
source = "../../../modules/folder"
- for_each = coalesce(var.team_folders, {})
- parent = module.branch-teams-folder.id
+ for_each = var.fast_features.teams ? coalesce(var.team_folders, {}) : {}
+ parent = module.branch-teams-folder.0.id
name = each.value.descriptive_name
group_iam = each.value.group_iam == null ? {} : each.value.group_iam
}
module "branch-teams-team-sa" {
source = "../../../modules/iam-service-account"
- for_each = coalesce(var.team_folders, {})
+ for_each = var.fast_features.teams ? coalesce(var.team_folders, {}) : {}
project_id = var.automation.project_id
name = "prod-teams-${each.key}-0"
description = "Terraform team ${each.key} service account."
@@ -63,7 +75,7 @@ module "branch-teams-team-sa" {
module "branch-teams-team-gcs" {
source = "../../../modules/gcs"
- for_each = coalesce(var.team_folders, {})
+ for_each = var.fast_features.teams ? coalesce(var.team_folders, {}) : {}
project_id = var.automation.project_id
name = "prod-teams-${each.key}-0"
prefix = var.prefix
@@ -77,19 +89,19 @@ module "branch-teams-team-gcs" {
module "branch-teams-team-dev-folder" {
source = "../../../modules/folder"
- for_each = coalesce(var.team_folders, {})
+ for_each = var.fast_features.teams ? coalesce(var.team_folders, {}) : {}
parent = module.branch-teams-team-folder[each.key].id
# naming: environment descriptive name
name = "Development"
# environment-wide human permissions on the whole teams environment
group_iam = {}
iam = {
- (local.custom_roles.service_project_network_admin) = [module.branch-teams-dev-pf-sa.iam_email]
+ (local.custom_roles.service_project_network_admin) = [module.branch-pf-dev-sa.0.iam_email]
# remove owner here and at project level if SA does not manage project resources
- "roles/owner" = [module.branch-teams-dev-pf-sa.iam_email]
- "roles/logging.admin" = [module.branch-teams-dev-pf-sa.iam_email]
- "roles/resourcemanager.folderAdmin" = [module.branch-teams-dev-pf-sa.iam_email]
- "roles/resourcemanager.projectCreator" = [module.branch-teams-dev-pf-sa.iam_email]
+ "roles/owner" = [module.branch-pf-dev-sa.0.iam_email]
+ "roles/logging.admin" = [module.branch-pf-dev-sa.0.iam_email]
+ "roles/resourcemanager.folderAdmin" = [module.branch-pf-dev-sa.0.iam_email]
+ "roles/resourcemanager.projectCreator" = [module.branch-pf-dev-sa.0.iam_email]
}
tag_bindings = {
environment = try(
@@ -100,19 +112,19 @@ module "branch-teams-team-dev-folder" {
module "branch-teams-team-prod-folder" {
source = "../../../modules/folder"
- for_each = coalesce(var.team_folders, {})
+ for_each = var.fast_features.teams ? coalesce(var.team_folders, {}) : {}
parent = module.branch-teams-team-folder[each.key].id
# naming: environment descriptive name
name = "Production"
# environment-wide human permissions on the whole teams environment
group_iam = {}
iam = {
- (local.custom_roles.service_project_network_admin) = [module.branch-teams-prod-pf-sa.iam_email]
+ (local.custom_roles.service_project_network_admin) = [module.branch-pf-prod-sa.0.iam_email]
# remove owner here and at project level if SA does not manage project resources
- "roles/owner" = [module.branch-teams-prod-pf-sa.iam_email]
- "roles/logging.admin" = [module.branch-teams-prod-pf-sa.iam_email]
- "roles/resourcemanager.folderAdmin" = [module.branch-teams-prod-pf-sa.iam_email]
- "roles/resourcemanager.projectCreator" = [module.branch-teams-prod-pf-sa.iam_email]
+ "roles/owner" = [module.branch-pf-prod-sa.0.iam_email]
+ "roles/logging.admin" = [module.branch-pf-prod-sa.0.iam_email]
+ "roles/resourcemanager.folderAdmin" = [module.branch-pf-prod-sa.0.iam_email]
+ "roles/resourcemanager.projectCreator" = [module.branch-pf-prod-sa.0.iam_email]
}
tag_bindings = {
environment = try(
@@ -120,63 +132,3 @@ module "branch-teams-team-prod-folder" {
)
}
}
-
-# project factory per-team environment service accounts
-
-module "branch-teams-dev-pf-sa" {
- source = "../../../modules/iam-service-account"
- project_id = var.automation.project_id
- name = "dev-resman-pf-0"
- # naming: environment in description
- description = "Terraform project factory development service account."
- prefix = var.prefix
- iam = {
- "roles/iam.serviceAccountTokenCreator" = compact([
- try(module.branch-teams-dev-pf-sa-cicd.0.iam_email, null)
- ])
- }
- iam_storage_roles = {
- (var.automation.outputs_bucket) = ["roles/storage.admin"]
- }
-}
-
-module "branch-teams-prod-pf-sa" {
- source = "../../../modules/iam-service-account"
- project_id = var.automation.project_id
- name = "prod-resman-pf-0"
- # naming: environment in description
- description = "Terraform project factory production service account."
- prefix = var.prefix
- iam = {
- "roles/iam.serviceAccountTokenCreator" = compact([
- try(module.branch-teams-prod-pf-sa-cicd.0.iam_email, null)
- ])
- }
- iam_storage_roles = {
- (var.automation.outputs_bucket) = ["roles/storage.admin"]
- }
-}
-
-# project factory per-team environment GCS buckets
-
-module "branch-teams-dev-pf-gcs" {
- source = "../../../modules/gcs"
- project_id = var.automation.project_id
- name = "dev-resman-pf-0"
- prefix = var.prefix
- versioning = true
- iam = {
- "roles/storage.objectAdmin" = [module.branch-teams-dev-pf-sa.iam_email]
- }
-}
-
-module "branch-teams-prod-pf-gcs" {
- source = "../../../modules/gcs"
- project_id = var.automation.project_id
- name = "prod-resman-pf-0"
- prefix = var.prefix
- versioning = true
- iam = {
- "roles/storage.objectAdmin" = [module.branch-teams-prod-pf-sa.iam_email]
- }
-}
diff --git a/fast/stages/01-resman/cicd-data-platform.tf b/fast/stages/01-resman/cicd-data-platform.tf
index 4a5c6d3f59..51adb33b2c 100644
--- a/fast/stages/01-resman/cicd-data-platform.tf
+++ b/fast/stages/01-resman/cicd-data-platform.tf
@@ -28,8 +28,12 @@ module "branch-dp-dev-cicd-repo" {
project_id = var.automation.project_id
name = each.value.name
iam = {
- "roles/source.admin" = [module.branch-dp-dev-sa.iam_email]
- "roles/source.reader" = [module.branch-dp-dev-sa-cicd.0.iam_email]
+ "roles/source.admin" = compact([
+ try(module.branch-dp-dev-sa.0.iam_email, "")
+ ])
+ "roles/source.reader" = compact([
+ try(module.branch-dp-dev-sa-cicd.0.iam_email, "")
+ ])
}
triggers = {
fast-03-dp-dev = {
@@ -60,7 +64,7 @@ module "branch-dp-prod-cicd-repo" {
project_id = var.automation.project_id
name = each.value.name
iam = {
- "roles/source.admin" = [module.branch-dp-prod-sa.iam_email]
+ "roles/source.admin" = [module.branch-dp-prod-sa.0.iam_email]
"roles/source.reader" = [module.branch-dp-prod-sa-cicd.0.iam_email]
}
triggers = {
diff --git a/fast/stages/01-resman/cicd-teams.tf b/fast/stages/01-resman/cicd-project-factory.tf
similarity index 82%
rename from fast/stages/01-resman/cicd-teams.tf
rename to fast/stages/01-resman/cicd-project-factory.tf
index f5e81fd3f2..62f36f9da7 100644
--- a/fast/stages/01-resman/cicd-teams.tf
+++ b/fast/stages/01-resman/cicd-project-factory.tf
@@ -18,7 +18,12 @@
# source repositories
-module "branch-teams-dev-pf-cicd-repo" {
+moved {
+ from = module.branch-teams-dev-pf-cicd-repo
+ to = module.branch-pf-dev-cicd-repo
+}
+
+module "branch-pf-dev-cicd-repo" {
source = "../../../modules/source-repository"
for_each = (
try(local.cicd_repositories.project_factory_dev.type, null) == "sourcerepo"
@@ -28,8 +33,8 @@ module "branch-teams-dev-pf-cicd-repo" {
project_id = var.automation.project_id
name = each.value.name
iam = {
- "roles/source.admin" = [module.branch-teams-dev-pf-sa.iam_email]
- "roles/source.reader" = [module.branch-teams-dev-pf-sa-cicd.0.iam_email]
+ "roles/source.admin" = [module.branch-pf-dev-sa.0.iam_email]
+ "roles/source.reader" = [module.branch-pf-dev-sa-cicd.0.iam_email]
}
triggers = {
fast-03-pf-dev = {
@@ -37,7 +42,7 @@ module "branch-teams-dev-pf-cicd-repo" {
included_files = [
"**/*json", "**/*tf", "**/*yaml", ".cloudbuild/workflow.yaml"
]
- service_account = module.branch-teams-dev-pf-sa-cicd.0.id
+ service_account = module.branch-pf-dev-sa-cicd.0.id
substitutions = {}
template = {
project_id = null
@@ -47,10 +52,15 @@ module "branch-teams-dev-pf-cicd-repo" {
}
}
}
- depends_on = [module.branch-teams-dev-pf-sa-cicd]
+ depends_on = [module.branch-pf-dev-sa-cicd]
+}
+
+moved {
+ from = module.branch-teams-prod-pf-cicd-repo
+ to = module.branch-pf-prod-cicd-repo
}
-module "branch-teams-prod-pf-cicd-repo" {
+module "branch-pf-prod-cicd-repo" {
source = "../../../modules/source-repository"
for_each = (
try(local.cicd_repositories.project_factory_prod.type, null) == "sourcerepo"
@@ -60,8 +70,8 @@ module "branch-teams-prod-pf-cicd-repo" {
project_id = var.automation.project_id
name = each.value.name
iam = {
- "roles/source.admin" = [module.branch-teams-prod-pf-sa.iam_email]
- "roles/source.reader" = [module.branch-teams-prod-pf-sa-cicd.0.iam_email]
+ "roles/source.admin" = [module.branch-pf-prod-sa.0.iam_email]
+ "roles/source.reader" = [module.branch-pf-prod-sa-cicd.0.iam_email]
}
triggers = {
fast-03-pf-prod = {
@@ -69,7 +79,7 @@ module "branch-teams-prod-pf-cicd-repo" {
included_files = [
"**/*json", "**/*tf", "**/*yaml", ".cloudbuild/workflow.yaml"
]
- service_account = module.branch-teams-prod-pf-sa-cicd.0.id
+ service_account = module.branch-pf-prod-sa-cicd.0.id
substitutions = {}
template = {
project_id = null
@@ -79,12 +89,17 @@ module "branch-teams-prod-pf-cicd-repo" {
}
}
}
- depends_on = [module.branch-teams-prod-pf-sa-cicd]
+ depends_on = [module.branch-pf-prod-sa-cicd]
}
# SAs used by CI/CD workflows to impersonate automation SAs
-module "branch-teams-dev-pf-sa-cicd" {
+moved {
+ from = module.branch-teams-dev-pf-sa-cicd
+ to = module.branch-pf-dev-sa-cicd
+}
+
+module "branch-pf-dev-sa-cicd" {
source = "../../../modules/iam-service-account"
for_each = (
try(local.cicd_repositories.project_factory_dev.name, null) != null
@@ -125,7 +140,12 @@ module "branch-teams-dev-pf-sa-cicd" {
}
}
-module "branch-teams-prod-pf-sa-cicd" {
+moved {
+ from = module.branch-teams-prod-pf-sa-cicd
+ to = module.branch-pf-prod-sa-cicd
+}
+
+module "branch-pf-prod-sa-cicd" {
source = "../../../modules/iam-service-account"
for_each = (
try(local.cicd_repositories.project_factory_prod.name, null) != null
diff --git a/fast/stages/01-resman/organization.tf b/fast/stages/01-resman/organization.tf
index 6ce4e9ced3..1c012caadf 100644
--- a/fast/stages/01-resman/organization.tf
+++ b/fast/stages/01-resman/organization.tf
@@ -18,16 +18,23 @@
locals {
- # set to the empty list if you remove the data platform branch
- branch_dataplatform_sa_iam_emails = [
- module.branch-dp-dev-sa.iam_email,
- module.branch-dp-prod-sa.iam_email
- ]
+ branch_dataplatform_sa_iam_emails = (
+ var.fast_features.data_platform
+ ? [
+ module.branch-dp-dev-sa.0.iam_email,
+ module.branch-dp-prod-sa.0.iam_email
+ ]
+ : []
+ )
# set to the empty list if you remove the teams branch
- branch_teams_pf_sa_iam_emails = [
- module.branch-teams-dev-pf-sa.iam_email,
- module.branch-teams-prod-pf-sa.iam_email
- ]
+ branch_teams_pf_sa_iam_emails = (
+ var.fast_features.project_factory
+ ? [
+ module.branch-pf-dev-sa.0.iam_email,
+ module.branch-pf-prod-sa.0.iam_email
+ ]
+ : []
+ )
list_allow = {
inherit_from_parent = false
suggested_value = null
@@ -176,18 +183,16 @@ module "organization" {
# organization policy admin role assigned with a condition on tags
-resource "google_organization_iam_member" "org_policy_admin" {
- for_each = {
- data-dev = ["data", "development", module.branch-dp-dev-sa.iam_email]
- data-prod = ["data", "production", module.branch-dp-prod-sa.iam_email]
- pf-dev = ["teams", "development", module.branch-teams-dev-pf-sa.iam_email]
- pf-prod = ["teams", "production", module.branch-teams-prod-pf-sa.iam_email]
+resource "google_organization_iam_member" "org_policy_admin_dp" {
+ for_each = !var.fast_features.data_platform ? {} : {
+ data-dev = ["data", "development", module.branch-dp-dev-sa.0.iam_email]
+ data-prod = ["data", "production", module.branch-dp-prod-sa.0.iam_email]
}
org_id = var.organization.id
role = "roles/orgpolicy.policyAdmin"
member = each.value.2
condition {
- title = "org_policy_tag_scoped"
+ title = "org_policy_tag_dp_scoped"
description = "Org policy tag scoped grant for ${each.value.0}/${each.value.1}."
expression = <<-END
resource.matchTag('${var.organization.id}/${var.tag_names.context}', '${each.value.0}')
@@ -197,3 +202,21 @@ resource "google_organization_iam_member" "org_policy_admin" {
}
}
+resource "google_organization_iam_member" "org_policy_admin_pf" {
+ for_each = !var.fast_features.project_factory ? {} : {
+ pf-dev = ["teams", "development", module.branch-pf-dev-sa.0.iam_email]
+ pf-prod = ["teams", "production", module.branch-pf-prod-sa.0.iam_email]
+ }
+ org_id = var.organization.id
+ role = "roles/orgpolicy.policyAdmin"
+ member = each.value.2
+ condition {
+ title = "org_policy_tag_pf_scoped"
+ description = "Org policy tag scoped grant for ${each.value.0}/${each.value.1}."
+ expression = <<-END
+ resource.matchTag('${var.organization.id}/${var.tag_names.context}', '${each.value.0}')
+ &&
+ resource.matchTag('${var.organization.id}/${var.tag_names.environment}', '${each.value.1}')
+ END
+ }
+}
diff --git a/fast/stages/01-resman/outputs.tf b/fast/stages/01-resman/outputs.tf
index 73ed2eedd5..9e0b6a17ba 100644
--- a/fast/stages/01-resman/outputs.tf
+++ b/fast/stages/01-resman/outputs.tf
@@ -33,12 +33,12 @@ locals {
tf_var_files = local.cicd_workflow_var_files.stage_2
}
project_factory_dev = {
- service_account = try(module.branch-teams-dev-pf-sa-cicd.0.email, null)
+ service_account = try(module.branch-pf-dev-sa-cicd.0.email, null)
tf_providers_file = "03-project-factory-dev-providers.tf"
tf_var_files = local.cicd_workflow_var_files.stage_3
}
project_factory_prod = {
- service_account = try(module.branch-teams-prod-pf-sa-cicd.0.email, null)
+ service_account = try(module.branch-pf-prod-sa-cicd.0.email, null)
tf_providers_file = "03-project-factory-prod-providers.tf"
tf_var_files = local.cicd_workflow_var_files.stage_3
}
@@ -62,13 +62,14 @@ locals {
}
folder_ids = merge(
{
- data-platform = module.branch-dp-dev-folder.id
- networking = module.branch-network-folder.id
- networking-dev = module.branch-network-dev-folder.id
- networking-prod = module.branch-network-prod-folder.id
- sandbox = module.branch-sandbox-folder.id
- security = module.branch-security-folder.id
- teams = module.branch-teams-folder.id
+ data-platform-dev = try(module.branch-dp-dev-folder.0.id, null)
+ data-platform-prod = try(module.branch-dp-prod-folder.0.id, null)
+ networking = module.branch-network-folder.id
+ networking-dev = module.branch-network-dev-folder.id
+ networking-prod = module.branch-network-prod-folder.id
+ sandbox = try(module.branch-sandbox-folder.0.id, null)
+ security = module.branch-security-folder.id
+ teams = try(module.branch-teams-folder.0.id, null)
},
{
for k, v in module.branch-teams-team-folder :
@@ -83,53 +84,61 @@ locals {
"team-${k}-prod" => v.id
}
)
- providers = {
- "02-networking" = templatefile(local._tpl_providers, {
- bucket = module.branch-network-gcs.name
- name = "networking"
- sa = module.branch-network-sa.email
- })
- "02-security" = templatefile(local._tpl_providers, {
- bucket = module.branch-security-gcs.name
- name = "security"
- sa = module.branch-security-sa.email
- })
- "03-data-platform-dev" = templatefile(local._tpl_providers, {
- bucket = module.branch-dp-dev-gcs.name
- name = "dp-dev"
- sa = module.branch-dp-dev-sa.email
- })
- "03-data-platform-prod" = templatefile(local._tpl_providers, {
- bucket = module.branch-dp-prod-gcs.name
- name = "dp-prod"
- sa = module.branch-dp-prod-sa.email
- })
- "03-project-factory-dev" = templatefile(local._tpl_providers, {
- bucket = module.branch-teams-dev-pf-gcs.name
- name = "team-dev"
- sa = module.branch-teams-dev-pf-sa.email
- })
- "03-project-factory-prod" = templatefile(local._tpl_providers, {
- bucket = module.branch-teams-prod-pf-gcs.name
- name = "team-prod"
- sa = module.branch-teams-prod-pf-sa.email
- })
- "99-sandbox" = templatefile(local._tpl_providers, {
- bucket = module.branch-sandbox-gcs.name
- name = "sandbox"
- sa = module.branch-sandbox-sa.email
- })
- }
+ providers = merge(
+ {
+ "02-networking" = templatefile(local._tpl_providers, {
+ bucket = module.branch-network-gcs.name
+ name = "networking"
+ sa = module.branch-network-sa.email
+ })
+ "02-security" = templatefile(local._tpl_providers, {
+ bucket = module.branch-security-gcs.name
+ name = "security"
+ sa = module.branch-security-sa.email
+ })
+ },
+ !var.fast_features.data_platform ? {} : {
+ "03-data-platform-dev" = templatefile(local._tpl_providers, {
+ bucket = module.branch-dp-dev-gcs.0.name
+ name = "dp-dev"
+ sa = module.branch-dp-dev-sa.0.email
+ })
+ "03-data-platform-prod" = templatefile(local._tpl_providers, {
+ bucket = module.branch-dp-prod-gcs.0.name
+ name = "dp-prod"
+ sa = module.branch-dp-prod-sa.0.email
+ })
+ },
+ !var.fast_features.project_factory ? {} : {
+ "03-project-factory-dev" = templatefile(local._tpl_providers, {
+ bucket = module.branch-pf-dev-gcs.0.name
+ name = "team-dev"
+ sa = module.branch-pf-dev-sa.0.email
+ })
+ "03-project-factory-prod" = templatefile(local._tpl_providers, {
+ bucket = module.branch-pf-prod-gcs.0.name
+ name = "team-prod"
+ sa = module.branch-pf-prod-sa.0.email
+ })
+ },
+ !var.fast_features.sandbox ? {} : {
+ "99-sandbox" = templatefile(local._tpl_providers, {
+ bucket = module.branch-sandbox-gcs.0.name
+ name = "sandbox"
+ sa = module.branch-sandbox-sa.0.email
+ })
+ }
+ )
service_accounts = merge(
{
- data-platform-dev = module.branch-dp-dev-sa.email
- data-platform-prod = module.branch-dp-prod-sa.email
+ data-platform-dev = try(module.branch-dp-dev-sa.0.email, null)
+ data-platform-prod = try(module.branch-dp-prod-sa.0.email, null)
networking = module.branch-network-sa.email
- project-factory-dev = module.branch-teams-dev-pf-sa.email
- project-factory-prod = module.branch-teams-prod-pf-sa.email
- sandbox = module.branch-sandbox-sa.email
+ project-factory-dev = try(module.branch-pf-dev-sa.0.email, null)
+ project-factory-prod = try(module.branch-pf-prod-sa.0.email, null)
+ sandbox = try(module.branch-sandbox-sa.0.email, null)
security = module.branch-security-sa.email
- teams = module.branch-teams-prod-sa.email
+ teams = try(module.branch-teams-prod-sa.0.email, null)
},
{
for k, v in module.branch-teams-team-sa : "team-${k}" => v.email
@@ -158,16 +167,16 @@ output "cicd_repositories" {
output "dataplatform" {
description = "Data for the Data Platform stage."
- value = {
+ value = !var.fast_features.data_platform ? {} : {
dev = {
- folder = module.branch-dp-dev-folder.id
- gcs_bucket = module.branch-dp-dev-gcs.name
- service_account = module.branch-dp-dev-sa.email
+ folder = module.branch-dp-dev-folder.0.id
+ gcs_bucket = module.branch-dp-dev-gcs.0.name
+ service_account = module.branch-dp-dev-sa.0.email
}
prod = {
- folder = module.branch-dp-prod-folder.id
- gcs_bucket = module.branch-dp-prod-gcs.name
- service_account = module.branch-dp-prod-sa.email
+ folder = module.branch-dp-prod-folder.0.id
+ gcs_bucket = module.branch-dp-prod-gcs.0.name
+ service_account = module.branch-dp-prod-sa.0.email
}
}
}
@@ -183,14 +192,14 @@ output "networking" {
output "project_factories" {
description = "Data for the project factories stage."
- value = {
+ value = !var.fast_features.project_factory ? {} : {
dev = {
- bucket = module.branch-teams-dev-pf-gcs.name
- sa = module.branch-teams-dev-pf-sa.email
+ bucket = module.branch-pf-dev-gcs.0.name
+ sa = module.branch-pf-dev-sa.0.email
}
prod = {
- bucket = module.branch-teams-prod-pf-gcs.name
- sa = module.branch-teams-prod-pf-sa.email
+ bucket = module.branch-pf-prod-gcs.0.name
+ sa = module.branch-pf-prod-sa.0.email
}
}
}
@@ -207,11 +216,15 @@ output "providers" {
output "sandbox" {
# tfdoc:output:consumers xx-sandbox
description = "Data for the sandbox stage."
- value = {
- folder = module.branch-sandbox-folder.id
- gcs_bucket = module.branch-sandbox-gcs.name
- service_account = module.branch-sandbox-sa.email
- }
+ value = (
+ var.fast_features.sandbox
+ ? {
+ folder = module.branch-sandbox-folder.0.id
+ gcs_bucket = module.branch-sandbox-gcs.0.name
+ service_account = module.branch-sandbox-sa.0.email
+ }
+ : null
+ )
}
output "security" {
diff --git a/fast/stages/01-resman/variables.tf b/fast/stages/01-resman/variables.tf
index c1d534bca6..35a05efedb 100644
--- a/fast/stages/01-resman/variables.tf
+++ b/fast/stages/01-resman/variables.tf
@@ -123,6 +123,24 @@ variable "custom_roles" {
default = null
}
+variable "fast_features" {
+ # tfdoc:variable:source 00-bootstrap
+ description = "Selective control for top-level FAST features."
+ type = object({
+ data_platform = bool
+ project_factory = bool
+ sandbox = bool
+ teams = bool
+ })
+ default = {
+ data_platform = true
+ project_factory = true
+ sandbox = true
+ teams = true
+ }
+ # nullable = false
+}
+
variable "groups" {
# tfdoc:variable:source 00-bootstrap
description = "Group names to grant organization-level permissions."
diff --git a/fast/stages/02-networking-nva/spoke-dev.tf b/fast/stages/02-networking-nva/spoke-dev.tf
index 843d544fdb..d6da279d76 100644
--- a/fast/stages/02-networking-nva/spoke-dev.tf
+++ b/fast/stages/02-networking-nva/spoke-dev.tf
@@ -40,7 +40,7 @@ module "dev-spoke-project" {
}
metric_scopes = [module.landing-project.project_id]
iam = {
- "roles/dns.admin" = [local.service_accounts.project-factory-dev]
+ "roles/dns.admin" = compact([local.service_accounts.project-factory-dev])
}
}
@@ -123,10 +123,10 @@ module "peering-dev" {
resource "google_project_iam_binding" "dev_spoke_project_iam_delegated" {
project = module.dev-spoke-project.project_id
role = "roles/resourcemanager.projectIamAdmin"
- members = [
+ members = compact([
local.service_accounts.data-platform-dev,
local.service_accounts.project-factory-dev,
- ]
+ ])
condition {
title = "dev_stage3_sa_delegated_grants"
description = "Development host project delegated grants."
diff --git a/fast/stages/02-networking-nva/spoke-prod.tf b/fast/stages/02-networking-nva/spoke-prod.tf
index d0a22dc98a..6f0e4edb0e 100644
--- a/fast/stages/02-networking-nva/spoke-prod.tf
+++ b/fast/stages/02-networking-nva/spoke-prod.tf
@@ -40,7 +40,7 @@ module "prod-spoke-project" {
}
metric_scopes = [module.landing-project.project_id]
iam = {
- "roles/dns.admin" = [local.service_accounts.project-factory-prod]
+ "roles/dns.admin" = compact([local.service_accounts.project-factory-prod])
}
}
@@ -123,10 +123,10 @@ module "peering-prod" {
resource "google_project_iam_binding" "prod_spoke_project_iam_delegated" {
project = module.prod-spoke-project.project_id
role = "roles/resourcemanager.projectIamAdmin"
- members = [
+ members = compact([
local.service_accounts.data-platform-prod,
local.service_accounts.project-factory-prod,
- ]
+ ])
condition {
title = "prod_stage3_sa_delegated_grants"
description = "Production host project delegated grants."
diff --git a/fast/stages/02-networking-peering/spoke-dev.tf b/fast/stages/02-networking-peering/spoke-dev.tf
index a6713eaf77..69c5b8eb23 100644
--- a/fast/stages/02-networking-peering/spoke-dev.tf
+++ b/fast/stages/02-networking-peering/spoke-dev.tf
@@ -41,7 +41,7 @@ module "dev-spoke-project" {
}
metric_scopes = [module.landing-project.project_id]
iam = {
- "roles/dns.admin" = [local.service_accounts.project-factory-dev]
+ "roles/dns.admin" = compact([local.service_accounts.project-factory-dev])
}
}
@@ -100,10 +100,10 @@ module "dev-spoke-cloudnat" {
resource "google_project_iam_binding" "dev_spoke_project_iam_delegated" {
project = module.dev-spoke-project.project_id
role = "roles/resourcemanager.projectIamAdmin"
- members = [
+ members = compact([
local.service_accounts.data-platform-dev,
local.service_accounts.project-factory-dev,
- ]
+ ])
condition {
title = "dev_stage3_sa_delegated_grants"
description = "Development host project delegated grants."
diff --git a/fast/stages/02-networking-peering/spoke-prod.tf b/fast/stages/02-networking-peering/spoke-prod.tf
index 401a08563f..c8ded75b14 100644
--- a/fast/stages/02-networking-peering/spoke-prod.tf
+++ b/fast/stages/02-networking-peering/spoke-prod.tf
@@ -41,7 +41,7 @@ module "prod-spoke-project" {
}
metric_scopes = [module.landing-project.project_id]
iam = {
- "roles/dns.admin" = [local.service_accounts.project-factory-prod]
+ "roles/dns.admin" = compact([local.service_accounts.project-factory-prod])
}
}
@@ -100,10 +100,10 @@ module "prod-spoke-cloudnat" {
resource "google_project_iam_binding" "prod_spoke_project_iam_delegated" {
project = module.prod-spoke-project.project_id
role = "roles/resourcemanager.projectIamAdmin"
- members = [
+ members = compact([
local.service_accounts.data-platform-prod,
local.service_accounts.project-factory-prod,
- ]
+ ])
condition {
title = "prod_stage3_sa_delegated_grants"
description = "Production host project delegated grants."
diff --git a/fast/stages/02-networking-vpn/spoke-dev.tf b/fast/stages/02-networking-vpn/spoke-dev.tf
index a6713eaf77..69c5b8eb23 100644
--- a/fast/stages/02-networking-vpn/spoke-dev.tf
+++ b/fast/stages/02-networking-vpn/spoke-dev.tf
@@ -41,7 +41,7 @@ module "dev-spoke-project" {
}
metric_scopes = [module.landing-project.project_id]
iam = {
- "roles/dns.admin" = [local.service_accounts.project-factory-dev]
+ "roles/dns.admin" = compact([local.service_accounts.project-factory-dev])
}
}
@@ -100,10 +100,10 @@ module "dev-spoke-cloudnat" {
resource "google_project_iam_binding" "dev_spoke_project_iam_delegated" {
project = module.dev-spoke-project.project_id
role = "roles/resourcemanager.projectIamAdmin"
- members = [
+ members = compact([
local.service_accounts.data-platform-dev,
local.service_accounts.project-factory-dev,
- ]
+ ])
condition {
title = "dev_stage3_sa_delegated_grants"
description = "Development host project delegated grants."
diff --git a/fast/stages/02-networking-vpn/spoke-prod.tf b/fast/stages/02-networking-vpn/spoke-prod.tf
index 401a08563f..c8ded75b14 100644
--- a/fast/stages/02-networking-vpn/spoke-prod.tf
+++ b/fast/stages/02-networking-vpn/spoke-prod.tf
@@ -41,7 +41,7 @@ module "prod-spoke-project" {
}
metric_scopes = [module.landing-project.project_id]
iam = {
- "roles/dns.admin" = [local.service_accounts.project-factory-prod]
+ "roles/dns.admin" = compact([local.service_accounts.project-factory-prod])
}
}
@@ -100,10 +100,10 @@ module "prod-spoke-cloudnat" {
resource "google_project_iam_binding" "prod_spoke_project_iam_delegated" {
project = module.prod-spoke-project.project_id
role = "roles/resourcemanager.projectIamAdmin"
- members = [
+ members = compact([
local.service_accounts.data-platform-prod,
local.service_accounts.project-factory-prod,
- ]
+ ])
condition {
title = "prod_stage3_sa_delegated_grants"
description = "Production host project delegated grants."
diff --git a/fast/stages/02-security/core-dev.tf b/fast/stages/02-security/core-dev.tf
index b917a5cc25..c6b9ba01bf 100644
--- a/fast/stages/02-security/core-dev.tf
+++ b/fast/stages/02-security/core-dev.tf
@@ -16,8 +16,10 @@
locals {
dev_kms_restricted_admins = [
- "serviceAccount:${var.service_accounts.project-factory-dev}",
- "serviceAccount:${var.service_accounts.data-platform-dev}"
+ for sa in compact([
+ var.service_accounts.project-factory-dev,
+ var.service_accounts.data-platform-dev
+ ]) : "serviceAccount:${sa}"
]
}
diff --git a/fast/stages/02-security/core-prod.tf b/fast/stages/02-security/core-prod.tf
index f792671fe3..b21547607a 100644
--- a/fast/stages/02-security/core-prod.tf
+++ b/fast/stages/02-security/core-prod.tf
@@ -16,8 +16,10 @@
locals {
prod_kms_restricted_admins = [
- "serviceAccount:${var.service_accounts.project-factory-prod}",
- "serviceAccount:${var.service_accounts.data-platform-prod}"
+ for sa in compact([
+ var.service_accounts.project-factory-prod,
+ var.service_accounts.data-platform-prod
+ ]) : "serviceAccount:${sa}"
]
}