diff --git a/blueprints/apigee/bigquery-analytics/main.tf b/blueprints/apigee/bigquery-analytics/main.tf
index d1534ad77..ef8d65cc3 100644
--- a/blueprints/apigee/bigquery-analytics/main.tf
+++ b/blueprints/apigee/bigquery-analytics/main.tf
@@ -24,8 +24,8 @@ module "project" {
? var.project_create.parent
: null
)
- name = var.project_id
- project_create = var.project_create != null
+ name = var.project_id
+ project_reuse = var.project_create != null ? null : {}
services = [
"apigee.googleapis.com",
"bigquery.googleapis.com",
diff --git a/blueprints/apigee/hybrid-gke/main.tf b/blueprints/apigee/hybrid-gke/main.tf
index 5be174ef5..713670f59 100644
--- a/blueprints/apigee/hybrid-gke/main.tf
+++ b/blueprints/apigee/hybrid-gke/main.tf
@@ -24,8 +24,8 @@ module "project" {
? var.project_create.parent
: null
)
- project_create = var.project_create != null
- name = var.project_id
+ project_reuse = var.project_create != null ? null : {}
+ name = var.project_id
services = [
"apigee.googleapis.com",
"apigeeconnect.googleapis.com",
diff --git a/blueprints/cloud-operations/adfs/main.tf b/blueprints/cloud-operations/adfs/main.tf
index 27286bbfc..3d7adaac9 100644
--- a/blueprints/cloud-operations/adfs/main.tf
+++ b/blueprints/cloud-operations/adfs/main.tf
@@ -24,9 +24,9 @@ module "project" {
? var.project_create.parent
: null
)
- project_create = var.project_create != null
- prefix = var.project_create == null ? null : var.prefix
- name = var.project_id
+ project_reuse = var.project_create != null ? null : {}
+ prefix = var.project_create == null ? null : var.prefix
+ name = var.project_id
services = [
"compute.googleapis.com",
"dns.googleapis.com",
diff --git a/blueprints/cloud-operations/asset-inventory-feed-remediation/main.tf b/blueprints/cloud-operations/asset-inventory-feed-remediation/main.tf
index dab591c59..7c8c56ced 100644
--- a/blueprints/cloud-operations/asset-inventory-feed-remediation/main.tf
+++ b/blueprints/cloud-operations/asset-inventory-feed-remediation/main.tf
@@ -20,9 +20,9 @@ locals {
}
module "project" {
- source = "../../../modules/project"
- name = var.project_id
- project_create = var.project_create
+ source = "../../../modules/project"
+ name = var.project_id
+ project_reuse = var.project_create != true ? {} : null
services = [
"cloudasset.googleapis.com",
"cloudbuild.googleapis.com",
diff --git a/blueprints/cloud-operations/compute-quota-monitoring/main.tf b/blueprints/cloud-operations/compute-quota-monitoring/main.tf
index 0136aa329..84a302691 100644
--- a/blueprints/cloud-operations/compute-quota-monitoring/main.tf
+++ b/blueprints/cloud-operations/compute-quota-monitoring/main.tf
@@ -29,7 +29,7 @@ module "project" {
name = var.project_id
billing_account = try(var.project_create_config.billing_account, null)
parent = try(var.project_create_config.parent, null)
- project_create = var.project_create_config != null
+ project_reuse = var.project_create_config != null ? null : {}
services = [
"cloudasset.googleapis.com",
"cloudbuild.googleapis.com",
diff --git a/blueprints/cloud-operations/dns-fine-grained-iam/main.tf b/blueprints/cloud-operations/dns-fine-grained-iam/main.tf
index fc25b257a..18e030eec 100644
--- a/blueprints/cloud-operations/dns-fine-grained-iam/main.tf
+++ b/blueprints/cloud-operations/dns-fine-grained-iam/main.tf
@@ -22,9 +22,9 @@ locals {
}
module "project" {
- source = "../../../modules/project"
- name = var.project_id
- project_create = var.project_create
+ source = "../../../modules/project"
+ name = var.project_id
+ project_reuse = var.project_create != true ? {} : null
services = [
"compute.googleapis.com",
"dns.googleapis.com",
diff --git a/blueprints/cloud-operations/iam-delegated-role-grants/main.tf b/blueprints/cloud-operations/iam-delegated-role-grants/main.tf
index e835dbb5a..9fc9d6e2b 100644
--- a/blueprints/cloud-operations/iam-delegated-role-grants/main.tf
+++ b/blueprints/cloud-operations/iam-delegated-role-grants/main.tf
@@ -48,9 +48,9 @@ locals {
}
module "project" {
- source = "../../../modules/project"
- name = var.project_id
- project_create = var.project_create
+ source = "../../../modules/project"
+ name = var.project_id
+ project_reuse = var.project_create != true ? {} : null
}
# make direct grants non-authoritative since project administrators
diff --git a/blueprints/cloud-operations/network-quota-monitoring/deploy-cloudrun-job/main.tf b/blueprints/cloud-operations/network-quota-monitoring/deploy-cloudrun-job/main.tf
index cc0b4293e..478e17d54 100644
--- a/blueprints/cloud-operations/network-quota-monitoring/deploy-cloudrun-job/main.tf
+++ b/blueprints/cloud-operations/network-quota-monitoring/deploy-cloudrun-job/main.tf
@@ -25,7 +25,7 @@ module "project" {
name = var.project_id
billing_account = try(var.project_create_config.billing_account_id, null)
parent = try(var.project_create_config.parent_id, null)
- project_create = var.project_create_config != null
+ project_reuse = var.project_create_config != null ? null : {}
services = [
"artifactregistry.googleapis.com",
"cloudasset.googleapis.com",
diff --git a/blueprints/cloud-operations/onprem-sa-key-management/main.tf b/blueprints/cloud-operations/onprem-sa-key-management/main.tf
index 40786ea18..1eec60332 100644
--- a/blueprints/cloud-operations/onprem-sa-key-management/main.tf
+++ b/blueprints/cloud-operations/onprem-sa-key-management/main.tf
@@ -19,10 +19,10 @@ locals {
}
module "project" {
- source = "../../../modules/project"
- name = var.project_id
- project_create = var.project_create
- services = var.services
+ source = "../../../modules/project"
+ name = var.project_id
+ project_reuse = var.project_create != true ? {} : null
+ services = var.services
}
module "integration-sa" {
diff --git a/blueprints/cloud-operations/packer-image-builder/main.tf b/blueprints/cloud-operations/packer-image-builder/main.tf
index 641ebd52d..fccb08128 100644
--- a/blueprints/cloud-operations/packer-image-builder/main.tf
+++ b/blueprints/cloud-operations/packer-image-builder/main.tf
@@ -26,7 +26,7 @@ module "project" {
name = var.project_id
parent = var.root_node
billing_account = var.billing_account
- project_create = var.project_create
+ project_reuse = var.project_create ? null : {}
services = [
"compute.googleapis.com"
]
diff --git a/blueprints/cloud-operations/scheduled-asset-inventory-export-bq/main.tf b/blueprints/cloud-operations/scheduled-asset-inventory-export-bq/main.tf
index ab77d8df9..fa2a3c506 100644
--- a/blueprints/cloud-operations/scheduled-asset-inventory-export-bq/main.tf
+++ b/blueprints/cloud-operations/scheduled-asset-inventory-export-bq/main.tf
@@ -25,7 +25,7 @@ module "project" {
name = var.project_id
parent = var.root_node
billing_account = try(var.billing_account, null)
- project_create = var.project_create
+ project_reuse = var.project_create ? null : {}
services = [
"bigquery.googleapis.com",
"cloudasset.googleapis.com",
diff --git a/blueprints/cloud-operations/terraform-cloud-dynamic-credentials/gcp-workload-identity-provider/main.tf b/blueprints/cloud-operations/terraform-cloud-dynamic-credentials/gcp-workload-identity-provider/main.tf
index ef56a44d6..09057da53 100644
--- a/blueprints/cloud-operations/terraform-cloud-dynamic-credentials/gcp-workload-identity-provider/main.tf
+++ b/blueprints/cloud-operations/terraform-cloud-dynamic-credentials/gcp-workload-identity-provider/main.tf
@@ -20,7 +20,7 @@
module "project" {
source = "../../../../modules/project"
name = var.project_id
- project_create = var.project_create
+ project_reuse = var.project_create ? null : {}
parent = var.parent
billing_account = var.billing_account
services = [
diff --git a/blueprints/cloud-operations/unmanaged-instances-healthcheck/main.tf b/blueprints/cloud-operations/unmanaged-instances-healthcheck/main.tf
index 33c6654e6..c3e37aadc 100644
--- a/blueprints/cloud-operations/unmanaged-instances-healthcheck/main.tf
+++ b/blueprints/cloud-operations/unmanaged-instances-healthcheck/main.tf
@@ -22,7 +22,7 @@ module "project" {
name = var.project_id
parent = var.root_node
billing_account = var.billing_account
- project_create = var.project_create
+ project_reuse = var.project_create ? null : {}
services = [
"vpcaccess.googleapis.com",
"compute.googleapis.com",
diff --git a/blueprints/cloud-operations/vm-migration/host-target-projects/README.md b/blueprints/cloud-operations/vm-migration/host-target-projects/README.md
index a2e9a71d2..831bf0fab 100644
--- a/blueprints/cloud-operations/vm-migration/host-target-projects/README.md
+++ b/blueprints/cloud-operations/vm-migration/host-target-projects/README.md
@@ -57,7 +57,6 @@ module "test-target-project" {
source = "./fabric/modules/project"
billing_account = "1234-ABCD-1234"
name = "test-target-project"
- project_create = true
}
# tftest modules=5 resources=28
diff --git a/blueprints/cloud-operations/vm-migration/host-target-projects/main.tf b/blueprints/cloud-operations/vm-migration/host-target-projects/main.tf
index ffe19839d..ef16ec6a4 100644
--- a/blueprints/cloud-operations/vm-migration/host-target-projects/main.tf
+++ b/blueprints/cloud-operations/vm-migration/host-target-projects/main.tf
@@ -33,7 +33,7 @@ module "host-project" {
"servicecontrol.googleapis.com",
"vmmigration.googleapis.com",
]
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
iam_bindings_additive = {
admin_sa_key_admin = {
role = "roles/iam.serviceAccountKeyAdmin"
@@ -62,10 +62,10 @@ module "m4ce-service-account" {
}
module "target-projects" {
- for_each = toset(var.migration_target_projects)
- source = "../../../../modules/project"
- name = each.key
- project_create = false
+ for_each = toset(var.migration_target_projects)
+ source = "../../../../modules/project"
+ name = each.key
+ project_reuse = {}
services = [
"servicemanagement.googleapis.com",
"servicecontrol.googleapis.com",
diff --git a/blueprints/cloud-operations/vm-migration/host-target-sharedvpc/README.md b/blueprints/cloud-operations/vm-migration/host-target-sharedvpc/README.md
index 3349709ea..72fccbe50 100644
--- a/blueprints/cloud-operations/vm-migration/host-target-sharedvpc/README.md
+++ b/blueprints/cloud-operations/vm-migration/host-target-sharedvpc/README.md
@@ -65,14 +65,12 @@ module "test-target-project" {
source = "./fabric/modules/project"
billing_account = "1234-ABCD-1234"
name = "test-target-project"
- project_create = true
}
module "test-sharedvpc-host-project" {
source = "./fabric/modules/project"
billing_account = "1234-ABCD-1234"
name = "test-sharedvpc-host-project"
- project_create = true
}
# tftest modules=7 resources=29
diff --git a/blueprints/cloud-operations/vm-migration/host-target-sharedvpc/main.tf b/blueprints/cloud-operations/vm-migration/host-target-sharedvpc/main.tf
index 037b8115d..b86d18694 100644
--- a/blueprints/cloud-operations/vm-migration/host-target-sharedvpc/main.tf
+++ b/blueprints/cloud-operations/vm-migration/host-target-sharedvpc/main.tf
@@ -32,7 +32,7 @@ module "host-project" {
"servicecontrol.googleapis.com",
"vmmigration.googleapis.com",
]
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
iam_bindings_additive = {
admin_sa_key_admin = {
role = "roles/iam.serviceAccountKeyAdmin"
@@ -60,10 +60,10 @@ module "m4ce-service-account" {
}
module "target-projects" {
- for_each = toset(var.migration_target_projects)
- source = "../../../../modules/project"
- name = each.key
- project_create = false
+ for_each = toset(var.migration_target_projects)
+ source = "../../../../modules/project"
+ name = each.key
+ project_reuse = {}
services = [
"cloudresourcemanager.googleapis.com",
"compute.googleapis.com",
@@ -84,10 +84,10 @@ module "target-projects" {
}
module "sharedvpc_host_project" {
- for_each = toset(var.sharedvpc_host_projects)
- source = "../../../../modules/project"
- name = each.key
- project_create = false
+ for_each = toset(var.sharedvpc_host_projects)
+ source = "../../../../modules/project"
+ name = each.key
+ project_reuse = {}
iam_bindings_additive = {
admin_compute_viewer = {
role = "roles/compute.viewer"
diff --git a/blueprints/cloud-operations/vm-migration/single-project/main.tf b/blueprints/cloud-operations/vm-migration/single-project/main.tf
index 4b67936e4..94fb70ef5 100644
--- a/blueprints/cloud-operations/vm-migration/single-project/main.tf
+++ b/blueprints/cloud-operations/vm-migration/single-project/main.tf
@@ -33,7 +33,7 @@ module "landing-project" {
"servicecontrol.googleapis.com",
"vmmigration.googleapis.com"
]
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
iam_bindings_additive = {
admin_sa_key_admin = {
role = "roles/iam.serviceAccountKeyAdmin"
diff --git a/blueprints/cloud-operations/workload-identity-federation/google-cloud.tf b/blueprints/cloud-operations/workload-identity-federation/google-cloud.tf
index 0924d08bd..8fb767ef7 100644
--- a/blueprints/cloud-operations/workload-identity-federation/google-cloud.tf
+++ b/blueprints/cloud-operations/workload-identity-federation/google-cloud.tf
@@ -31,7 +31,7 @@ module "prj" {
"iamcredentials.googleapis.com",
"sts.googleapis.com",
]
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
iam_bindings_additive = {
sa_viewer = {
member = module.sa.iam_email
diff --git a/blueprints/data-solutions/bq-ml/main.tf b/blueprints/data-solutions/bq-ml/main.tf
index 6a9ace6e6..a26e8ee5b 100644
--- a/blueprints/data-solutions/bq-ml/main.tf
+++ b/blueprints/data-solutions/bq-ml/main.tf
@@ -34,7 +34,7 @@ module "project" {
name = var.project_id
parent = try(var.project_create.parent, null)
billing_account = try(var.project_create.billing_account_id, null)
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
prefix = var.project_create == null ? null : var.prefix
services = [
"aiplatform.googleapis.com",
diff --git a/blueprints/data-solutions/cloudsql-multiregion/main.tf b/blueprints/data-solutions/cloudsql-multiregion/main.tf
index 855c8685a..af6a7c50d 100644
--- a/blueprints/data-solutions/cloudsql-multiregion/main.tf
+++ b/blueprints/data-solutions/cloudsql-multiregion/main.tf
@@ -47,7 +47,7 @@ module "project" {
name = var.project_id
parent = try(var.project_create.parent, null)
billing_account = try(var.project_create.billing_account_id, null)
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
prefix = var.project_create == null ? null : var.prefix
iam_bindings_additive = merge(
var.data_eng_principal == null ? {} : {
diff --git a/blueprints/data-solutions/cmek-via-centralized-kms/main.tf b/blueprints/data-solutions/cmek-via-centralized-kms/main.tf
index dbb033622..d86f5e9d7 100644
--- a/blueprints/data-solutions/cmek-via-centralized-kms/main.tf
+++ b/blueprints/data-solutions/cmek-via-centralized-kms/main.tf
@@ -29,7 +29,7 @@ module "project-service" {
name = var.project_config.project_ids.service
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.billing_account_id != null
+ project_reuse = var.project_config.billing_account_id != null ? null : {}
prefix = var.project_config.billing_account_id == null ? null : var.prefix
services = [
"compute.googleapis.com",
@@ -54,7 +54,7 @@ module "project-kms" {
name = var.project_config.project_ids.encryption
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.billing_account_id != null
+ project_reuse = var.project_config.billing_account_id != null ? null : {}
prefix = var.project_config.billing_account_id == null ? null : var.prefix
services = [
"cloudkms.googleapis.com",
diff --git a/blueprints/data-solutions/data-platform-foundations/01-dropoff.tf b/blueprints/data-solutions/data-platform-foundations/01-dropoff.tf
index e0d50080a..152d20045 100644
--- a/blueprints/data-solutions/data-platform-foundations/01-dropoff.tf
+++ b/blueprints/data-solutions/data-platform-foundations/01-dropoff.tf
@@ -45,7 +45,7 @@ module "drop-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.project_create
+ project_reuse = var.project_config.project_create ? null : {}
prefix = local.use_projects ? null : var.prefix
name = (
local.use_projects
diff --git a/blueprints/data-solutions/data-platform-foundations/02-load.tf b/blueprints/data-solutions/data-platform-foundations/02-load.tf
index 453003da8..32dfe191e 100644
--- a/blueprints/data-solutions/data-platform-foundations/02-load.tf
+++ b/blueprints/data-solutions/data-platform-foundations/02-load.tf
@@ -39,7 +39,7 @@ module "load-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.project_create
+ project_reuse = var.project_config.project_create ? null : {}
prefix = local.use_projects ? null : var.prefix
name = (
local.use_projects
diff --git a/blueprints/data-solutions/data-platform-foundations/03-orchestration.tf b/blueprints/data-solutions/data-platform-foundations/03-orchestration.tf
index b2976da5d..5663c3b1d 100644
--- a/blueprints/data-solutions/data-platform-foundations/03-orchestration.tf
+++ b/blueprints/data-solutions/data-platform-foundations/03-orchestration.tf
@@ -61,7 +61,7 @@ module "orch-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.project_create
+ project_reuse = var.project_config.project_create ? null : {}
prefix = local.use_projects ? null : var.prefix
name = (
local.use_projects
diff --git a/blueprints/data-solutions/data-platform-foundations/04-transformation.tf b/blueprints/data-solutions/data-platform-foundations/04-transformation.tf
index 2bdf9ee2c..2a45def1a 100644
--- a/blueprints/data-solutions/data-platform-foundations/04-transformation.tf
+++ b/blueprints/data-solutions/data-platform-foundations/04-transformation.tf
@@ -40,7 +40,7 @@ module "transf-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.project_create
+ project_reuse = var.project_config.project_create ? null : {}
prefix = local.use_projects ? null : var.prefix
name = (
local.use_projects
diff --git a/blueprints/data-solutions/data-platform-foundations/05-datawarehouse.tf b/blueprints/data-solutions/data-platform-foundations/05-datawarehouse.tf
index 886100c72..f58dc034a 100644
--- a/blueprints/data-solutions/data-platform-foundations/05-datawarehouse.tf
+++ b/blueprints/data-solutions/data-platform-foundations/05-datawarehouse.tf
@@ -68,7 +68,7 @@ module "dwh-lnd-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.project_create
+ project_reuse = var.project_config.project_create ? null : {}
prefix = local.use_projects ? null : var.prefix
name = (
local.use_projects
@@ -88,7 +88,7 @@ module "dwh-cur-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.project_create
+ project_reuse = var.project_config.project_create ? null : {}
prefix = local.use_projects ? null : var.prefix
name = (
local.use_projects
@@ -108,7 +108,7 @@ module "dwh-conf-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.project_create
+ project_reuse = var.project_config.project_create ? null : {}
prefix = local.use_projects ? null : var.prefix
name = (
local.use_projects
diff --git a/blueprints/data-solutions/data-platform-foundations/06-common.tf b/blueprints/data-solutions/data-platform-foundations/06-common.tf
index 992a6c03c..6ebf2adf1 100644
--- a/blueprints/data-solutions/data-platform-foundations/06-common.tf
+++ b/blueprints/data-solutions/data-platform-foundations/06-common.tf
@@ -50,7 +50,7 @@ module "common-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.project_create
+ project_reuse = var.project_config.project_create ? null : {}
prefix = local.use_projects ? null : var.prefix
name = (
local.use_projects
diff --git a/blueprints/data-solutions/data-platform-foundations/07-exposure.tf b/blueprints/data-solutions/data-platform-foundations/07-exposure.tf
index ad4f39d1a..8418080ff 100644
--- a/blueprints/data-solutions/data-platform-foundations/07-exposure.tf
+++ b/blueprints/data-solutions/data-platform-foundations/07-exposure.tf
@@ -18,7 +18,7 @@ module "exp-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.project_create
+ project_reuse = var.project_config.project_create ? null : {}
prefix = local.use_projects ? null : var.prefix
name = (
local.use_projects
diff --git a/blueprints/data-solutions/data-platform-minimal/01-landing.tf b/blueprints/data-solutions/data-platform-minimal/01-landing.tf
index c2f40303e..e9a036102 100644
--- a/blueprints/data-solutions/data-platform-minimal/01-landing.tf
+++ b/blueprints/data-solutions/data-platform-minimal/01-landing.tf
@@ -44,7 +44,7 @@ module "land-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.billing_account_id != null
+ project_reuse = var.project_config.billing_account_id != null ? null : {}
prefix = (
var.project_config.billing_account_id == null ? null : var.prefix
)
diff --git a/blueprints/data-solutions/data-platform-minimal/02-processing.tf b/blueprints/data-solutions/data-platform-minimal/02-processing.tf
index 47be526f9..d19695f5f 100644
--- a/blueprints/data-solutions/data-platform-minimal/02-processing.tf
+++ b/blueprints/data-solutions/data-platform-minimal/02-processing.tf
@@ -90,7 +90,7 @@ module "processing-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.billing_account_id != null
+ project_reuse = var.project_config.billing_account_id != null ? null : {}
prefix = (
var.project_config.billing_account_id == null ? null : var.prefix
)
diff --git a/blueprints/data-solutions/data-platform-minimal/03-curated.tf b/blueprints/data-solutions/data-platform-minimal/03-curated.tf
index 6888b21cf..f825065a5 100644
--- a/blueprints/data-solutions/data-platform-minimal/03-curated.tf
+++ b/blueprints/data-solutions/data-platform-minimal/03-curated.tf
@@ -84,7 +84,7 @@ module "cur-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.billing_account_id != null
+ project_reuse = var.project_config.billing_account_id != null ? null : {}
prefix = (
var.project_config.billing_account_id == null ? null : var.prefix
)
diff --git a/blueprints/data-solutions/data-platform-minimal/04-common.tf b/blueprints/data-solutions/data-platform-minimal/04-common.tf
index 37699df9f..0431d774c 100644
--- a/blueprints/data-solutions/data-platform-minimal/04-common.tf
+++ b/blueprints/data-solutions/data-platform-minimal/04-common.tf
@@ -59,7 +59,7 @@ module "common-project" {
source = "../../../modules/project"
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.billing_account_id != null
+ project_reuse = var.project_config.billing_account_id != null ? null : {}
prefix = (
var.project_config.billing_account_id == null ? null : var.prefix
)
diff --git a/blueprints/data-solutions/data-playground/main.tf b/blueprints/data-solutions/data-playground/main.tf
index 9662544b3..15e97729a 100644
--- a/blueprints/data-solutions/data-playground/main.tf
+++ b/blueprints/data-solutions/data-playground/main.tf
@@ -56,7 +56,7 @@ module "project" {
name = var.project_id
parent = try(var.project_create.parent, null)
billing_account = try(var.project_create.billing_account_id, null)
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
prefix = var.project_create == null ? null : var.prefix
services = [
"aiplatform.googleapis.com",
diff --git a/blueprints/data-solutions/gcs-to-bq-with-least-privileges/main.tf b/blueprints/data-solutions/gcs-to-bq-with-least-privileges/main.tf
index e79cc72a9..661f98c6b 100644
--- a/blueprints/data-solutions/gcs-to-bq-with-least-privileges/main.tf
+++ b/blueprints/data-solutions/gcs-to-bq-with-least-privileges/main.tf
@@ -69,7 +69,7 @@ module "project" {
name = var.project_config.project_id
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.billing_account_id != null
+ project_reuse = var.project_config.billing_account_id != null ? null : {}
prefix = var.project_config.billing_account_id == null ? null : var.prefix
services = [
"bigquery.googleapis.com",
diff --git a/blueprints/data-solutions/shielded-folder/kms.tf b/blueprints/data-solutions/shielded-folder/kms.tf
index 83f1c5fcb..b0a1da94b 100644
--- a/blueprints/data-solutions/shielded-folder/kms.tf
+++ b/blueprints/data-solutions/shielded-folder/kms.tf
@@ -60,8 +60,10 @@ module "sec-project" {
name = var.project_config.project_ids["sec-core"]
parent = module.folder.id
billing_account = var.project_config.billing_account_id
- project_create = (
+ project_reuse = (
var.project_config.billing_account_id != null && var.enable_features.encryption
+ ? null
+ : {}
)
prefix = (
var.project_config.billing_account_id == null ? null : var.prefix
diff --git a/blueprints/data-solutions/shielded-folder/log-export.tf b/blueprints/data-solutions/shielded-folder/log-export.tf
index 5f8353d2c..fee9b7bd7 100644
--- a/blueprints/data-solutions/shielded-folder/log-export.tf
+++ b/blueprints/data-solutions/shielded-folder/log-export.tf
@@ -61,7 +61,7 @@ module "log-export-project" {
name = var.project_config.project_ids["audit-logs"]
parent = module.folder.id
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.billing_account_id != null
+ project_reuse = var.project_config.billing_account_id != null ? null : {}
prefix = (
var.project_config.billing_account_id == null ? null : var.prefix
)
diff --git a/blueprints/data-solutions/sqlserver-alwayson/main.tf b/blueprints/data-solutions/sqlserver-alwayson/main.tf
index 38486268d..6f7a922c4 100644
--- a/blueprints/data-solutions/sqlserver-alwayson/main.tf
+++ b/blueprints/data-solutions/sqlserver-alwayson/main.tf
@@ -67,7 +67,7 @@ module "project" {
name = var.project_id
parent = try(var.project_create.parent, null)
billing_account = try(var.project_create.billing_account_id, null)
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
prefix = var.project_create == null ? null : var.prefix
services = [
"compute.googleapis.com",
diff --git a/blueprints/data-solutions/vertex-mlops/main.tf b/blueprints/data-solutions/vertex-mlops/main.tf
index cfab4877d..18c01019b 100644
--- a/blueprints/data-solutions/vertex-mlops/main.tf
+++ b/blueprints/data-solutions/vertex-mlops/main.tf
@@ -193,7 +193,7 @@ module "project" {
name = var.project_config.project_id
parent = var.project_config.parent
billing_account = var.project_config.billing_account_id
- project_create = var.project_config.billing_account_id != null
+ project_reuse = var.project_config.billing_account_id != null ? null : {}
prefix = var.prefix
iam_by_principals = local.iam_principals
iam_bindings_additive = {
diff --git a/blueprints/gcve/monitoring/main.tf b/blueprints/gcve/monitoring/main.tf
index 4c5e6789a..efa53ddf4 100644
--- a/blueprints/gcve/monitoring/main.tf
+++ b/blueprints/gcve/monitoring/main.tf
@@ -33,7 +33,7 @@ module "project" {
parent = try(var.project_create.parent, null)
billing_account = try(var.project_create.billing_account, null)
name = var.project_id
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
services = [
"compute.googleapis.com",
"monitoring.googleapis.com",
diff --git a/blueprints/gke/autopilot/main.tf b/blueprints/gke/autopilot/main.tf
index 84b7fe06e..87cfb4e15 100644
--- a/blueprints/gke/autopilot/main.tf
+++ b/blueprints/gke/autopilot/main.tf
@@ -24,8 +24,8 @@ module "project" {
? var.project_create.parent
: null
)
- project_create = var.project_create != null
- name = var.project_id
+ project_reuse = var.project_create != null ? null : {}
+ name = var.project_id
services = [
"artifactregistry.googleapis.com",
"cloudbuild.googleapis.com",
diff --git a/blueprints/gke/binauthz/main.tf b/blueprints/gke/binauthz/main.tf
index 5ee0b59c0..df95ce068 100644
--- a/blueprints/gke/binauthz/main.tf
+++ b/blueprints/gke/binauthz/main.tf
@@ -32,9 +32,9 @@ module "project" {
? var.project_create.parent
: null
)
- project_create = var.project_create != null
- prefix = var.project_create == null ? null : var.prefix
- name = var.project_id
+ project_reuse = var.project_create != null ? null : {}
+ prefix = var.project_create == null ? null : var.prefix
+ name = var.project_id
services = [
"artifactregistry.googleapis.com",
"binaryauthorization.googleapis.com",
diff --git a/blueprints/gke/patterns/autopilot-cluster/main.tf b/blueprints/gke/patterns/autopilot-cluster/main.tf
index 51dd759e5..90d6c76d9 100644
--- a/blueprints/gke/patterns/autopilot-cluster/main.tf
+++ b/blueprints/gke/patterns/autopilot-cluster/main.tf
@@ -130,10 +130,10 @@ module "vpc" {
}
module "fleet-project" {
- source = "../../../../modules/project"
- count = var.fleet_project_id == null ? 0 : 1
- name = var.fleet_project_id
- project_create = false
+ source = "../../../../modules/project"
+ count = var.fleet_project_id == null ? 0 : 1
+ name = var.fleet_project_id
+ project_reuse = {}
}
module "fleet" {
diff --git a/blueprints/networking/glb-and-armor/main.tf b/blueprints/networking/glb-and-armor/main.tf
index 22a7c3c7c..d65de5ce5 100644
--- a/blueprints/networking/glb-and-armor/main.tf
+++ b/blueprints/networking/glb-and-armor/main.tf
@@ -33,7 +33,7 @@ module "project" {
services = [
"compute.googleapis.com"
]
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
}
diff --git a/blueprints/networking/glb-hybrid-neg-internal/main.tf b/blueprints/networking/glb-hybrid-neg-internal/main.tf
index 3a7551ffb..ca4a9513a 100644
--- a/blueprints/networking/glb-hybrid-neg-internal/main.tf
+++ b/blueprints/networking/glb-hybrid-neg-internal/main.tf
@@ -32,8 +32,8 @@ module "project_landing" {
? var.projects_create.parent
: null
)
- prefix = var.prefix
- project_create = var.projects_create != null
+ prefix = var.prefix
+ project_reuse = var.projects_create != null ? null : {}
services = [
"compute.googleapis.com",
diff --git a/blueprints/networking/ilb-next-hop/main.tf b/blueprints/networking/ilb-next-hop/main.tf
index 0f7cfe0e5..66ca6ac4d 100644
--- a/blueprints/networking/ilb-next-hop/main.tf
+++ b/blueprints/networking/ilb-next-hop/main.tf
@@ -23,9 +23,9 @@ locals {
}
module "project" {
- source = "../../../modules/project"
- name = var.project_id
- project_create = var.project_create
+ source = "../../../modules/project"
+ name = var.project_id
+ project_reuse = var.project_create ? null : {}
services = [
"compute.googleapis.com",
"dns.googleapis.com",
diff --git a/blueprints/networking/private-cloud-function-from-onprem/main.tf b/blueprints/networking/private-cloud-function-from-onprem/main.tf
index 377801e00..d11a78cb0 100644
--- a/blueprints/networking/private-cloud-function-from-onprem/main.tf
+++ b/blueprints/networking/private-cloud-function-from-onprem/main.tf
@@ -21,7 +21,7 @@ locals {
module "project" {
source = "../../../modules/project"
name = var.project_id
- project_create = var.project_create == null ? false : true
+ project_reuse = var.project_create == null ? {} : null
billing_account = try(var.project_create.billing_account_id, null)
parent = try(var.project_create.parent, null)
services = [
diff --git a/blueprints/networking/psc-glb-and-armor/consumer.tf b/blueprints/networking/psc-glb-and-armor/consumer.tf
index e525046ca..e1f31fda0 100644
--- a/blueprints/networking/psc-glb-and-armor/consumer.tf
+++ b/blueprints/networking/psc-glb-and-armor/consumer.tf
@@ -15,9 +15,9 @@
*/
module "consumer-project" {
- source = "../../../modules/project"
- name = var.consumer_project_id
- project_create = var.project_create_config != null
+ source = "../../../modules/project"
+ name = var.consumer_project_id
+ project_reuse = var.project_create_config != null ? null : {}
billing_account = try(var.project_create_config.billing_account, null)
parent = try(var.project_create_config.parent, null)
diff --git a/blueprints/networking/psc-glb-and-armor/modules/producer/main.tf b/blueprints/networking/psc-glb-and-armor/modules/producer/main.tf
index dd982e8c9..3e25d9b14 100644
--- a/blueprints/networking/psc-glb-and-armor/modules/producer/main.tf
+++ b/blueprints/networking/psc-glb-and-armor/modules/producer/main.tf
@@ -15,9 +15,9 @@
*/
module "producer-project" {
- source = "../../../../../modules/project"
- name = var.producer_project_id
- project_create = var.project_create_config != null
+ source = "../../../../../modules/project"
+ name = var.producer_project_id
+ project_reuse = var.project_create_config != null ? null : {}
billing_account = try(var.project_create_config.billing_account, null)
parent = try(var.project_create_config.parent, null)
diff --git a/blueprints/networking/psc-hybrid/main.tf b/blueprints/networking/psc-hybrid/main.tf
index 39be8c923..c2f3b9e60 100644
--- a/blueprints/networking/psc-hybrid/main.tf
+++ b/blueprints/networking/psc-hybrid/main.tf
@@ -53,9 +53,9 @@ locals {
}
module "project" {
- source = "../../../modules/project"
- name = var.project_id
- project_create = var.project_create
+ source = "../../../modules/project"
+ name = var.project_id
+ project_reuse = var.project_create ? null : {}
services = [
"compute.googleapis.com"
]
diff --git a/blueprints/networking/vpc-connectivity-lab/main.tf b/blueprints/networking/vpc-connectivity-lab/main.tf
index 92b04da4a..bc99dc601 100644
--- a/blueprints/networking/vpc-connectivity-lab/main.tf
+++ b/blueprints/networking/vpc-connectivity-lab/main.tf
@@ -21,8 +21,12 @@ module "project" {
name = var.project_id
parent = try(var.project_create_config.parent_id, null)
billing_account = try(var.project_create_config.billing_account_id, null)
- project_create = try(var.project_create_config.billing_account_id, null) != null
- prefix = var.prefix
+ project_reuse = (
+ try(var.project_create_config.billing_account_id, null) != null
+ ? null
+ : {}
+ )
+ prefix = var.prefix
services = [
"compute.googleapis.com",
"dns.googleapis.com",
diff --git a/blueprints/secops/bindplane-gke/main.tf b/blueprints/secops/bindplane-gke/main.tf
index 6f84c781d..8c47fe3b1 100644
--- a/blueprints/secops/bindplane-gke/main.tf
+++ b/blueprints/secops/bindplane-gke/main.tf
@@ -32,9 +32,9 @@ module "project" {
? var.project_create.parent
: null
)
- prefix = var.prefix
- project_create = var.project_create != null
- name = var.project_id
+ prefix = var.prefix
+ project_reuse = var.project_create != null ? null : {}
+ name = var.project_id
services = concat([
"compute.googleapis.com",
"iap.googleapis.com",
diff --git a/blueprints/secops/secops-gke-forwarder/main.tf b/blueprints/secops/secops-gke-forwarder/main.tf
index bc3c8e870..0a65090ad 100644
--- a/blueprints/secops/secops-gke-forwarder/main.tf
+++ b/blueprints/secops/secops-gke-forwarder/main.tf
@@ -32,9 +32,9 @@ module "project" {
? var.project_create.parent
: null
)
- prefix = var.prefix
- project_create = var.project_create != null
- name = var.project_id
+ prefix = var.prefix
+ project_reuse = var.project_create != null ? null : {}
+ name = var.project_id
services = concat([
"compute.googleapis.com",
"iap.googleapis.com",
diff --git a/blueprints/serverless/cloud-run-corporate/main.tf b/blueprints/serverless/cloud-run-corporate/main.tf
index ce6e8bb10..cc3b44b15 100644
--- a/blueprints/serverless/cloud-run-corporate/main.tf
+++ b/blueprints/serverless/cloud-run-corporate/main.tf
@@ -46,7 +46,7 @@ locals {
module "project_main" {
source = "../../../modules/project"
name = var.prj_main_id
- project_create = var.prj_main_create != null
+ project_reuse = var.prj_main_create != null ? null : {}
billing_account = try(var.prj_main_create.billing_account_id, null)
parent = try(var.prj_main_create.parent, null)
# Enable Shared VPC by default, some use cases will use this project as host
@@ -67,7 +67,7 @@ module "project_onprem" {
source = "../../../modules/project"
count = var.prj_onprem_id != null ? 1 : 0
name = var.prj_onprem_id
- project_create = var.prj_onprem_create != null
+ project_reuse = var.prj_onprem_create != null ? null : {}
billing_account = try(var.prj_onprem_create.billing_account_id, null)
parent = try(var.prj_onprem_create.parent, null)
services = [
@@ -81,7 +81,7 @@ module "project_prj1" {
source = "../../../modules/project"
count = var.prj_prj1_id != null ? 1 : 0
name = var.prj_prj1_id
- project_create = var.prj_prj1_create != null
+ project_reuse = var.prj_prj1_create != null ? null : {}
billing_account = try(var.prj_prj1_create.billing_account_id, null)
parent = try(var.prj_prj1_create.parent, null)
services = [
@@ -95,7 +95,7 @@ module "project_svc1" {
source = "../../../modules/project"
count = var.prj_svc1_id != null ? 1 : 0
name = var.prj_svc1_id
- project_create = var.prj_svc1_create != null
+ project_reuse = var.prj_svc1_create != null ? null : {}
billing_account = try(var.prj_svc1_create.billing_account_id, null)
parent = try(var.prj_svc1_create.parent, null)
shared_vpc_service_config = {
diff --git a/blueprints/serverless/cloud-run-explore/main.tf b/blueprints/serverless/cloud-run-explore/main.tf
index c32923f86..402cc2f0a 100644
--- a/blueprints/serverless/cloud-run-explore/main.tf
+++ b/blueprints/serverless/cloud-run-explore/main.tf
@@ -35,7 +35,7 @@ module "project" {
"compute.googleapis.com",
"iap.googleapis.com"
]
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
}
# Cloud Run service
diff --git a/blueprints/serverless/cloud-run-microservices/main.tf b/blueprints/serverless/cloud-run-microservices/main.tf
index 0da49b778..aca35cdd9 100644
--- a/blueprints/serverless/cloud-run-microservices/main.tf
+++ b/blueprints/serverless/cloud-run-microservices/main.tf
@@ -29,7 +29,7 @@ module "main-project" {
source = "../../../modules/project"
name = var.project_configs.main.project_id
prefix = var.prefix
- project_create = var.project_configs.main.billing_account_id != null
+ project_reuse = var.project_configs.main.billing_account_id != null ? null : {}
billing_account = try(var.project_configs.main.billing_account_id, null)
parent = try(var.project_configs.main.parent, null)
# Enable Shared VPC by default, a use case will use this project as host
@@ -49,7 +49,7 @@ module "service-project" {
count = local.two_projects == true ? 1 : 0
name = var.project_configs.service.project_id
prefix = var.prefix
- project_create = var.project_configs.service.billing_account_id != null
+ project_reuse = var.project_configs.service.billing_account_id != null ? null : {}
billing_account = try(var.project_configs.service.billing_account_id, null)
parent = try(var.project_configs.service.parent, null)
shared_vpc_service_config = {
diff --git a/blueprints/third-party-solutions/f5-bigip/f5-bigip-ha-active-deployment/main.tf b/blueprints/third-party-solutions/f5-bigip/f5-bigip-ha-active-deployment/main.tf
index a364eab07..ad946906e 100644
--- a/blueprints/third-party-solutions/f5-bigip/f5-bigip-ha-active-deployment/main.tf
+++ b/blueprints/third-party-solutions/f5-bigip/f5-bigip-ha-active-deployment/main.tf
@@ -23,9 +23,9 @@ locals {
}
module "project" {
- source = "../../../../modules/project"
- name = var.project_id
- project_create = var.project_create
+ source = "../../../../modules/project"
+ name = var.project_id
+ project_reuse = var.project_create ? null : {}
services = [
"compute.googleapis.com"
]
diff --git a/blueprints/third-party-solutions/gitlab/main.tf b/blueprints/third-party-solutions/gitlab/main.tf
index aec06222f..1b839d7fd 100644
--- a/blueprints/third-party-solutions/gitlab/main.tf
+++ b/blueprints/third-party-solutions/gitlab/main.tf
@@ -20,7 +20,7 @@ module "project" {
billing_account = try(var.project_create.billing_account_id, null)
prefix = var.project_create == null ? null : var.prefix
name = var.project_id
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
services = [
"compute.googleapis.com",
"memcache.googleapis.com",
diff --git a/blueprints/third-party-solutions/phpipam/main.tf b/blueprints/third-party-solutions/phpipam/main.tf
index 36ee52e3c..0dc826ae0 100644
--- a/blueprints/third-party-solutions/phpipam/main.tf
+++ b/blueprints/third-party-solutions/phpipam/main.tf
@@ -55,7 +55,7 @@ module "project" {
name = var.project_id
parent = try(var.project_create.parent, null)
prefix = var.project_create == null ? null : var.prefix
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
services = [
"iap.googleapis.com",
"logging.googleapis.com",
diff --git a/blueprints/third-party-solutions/wordpress/cloudrun/main.tf b/blueprints/third-party-solutions/wordpress/cloudrun/main.tf
index 7f11359ea..56a7b6bae 100644
--- a/blueprints/third-party-solutions/wordpress/cloudrun/main.tf
+++ b/blueprints/third-party-solutions/wordpress/cloudrun/main.tf
@@ -44,7 +44,7 @@ module "project" {
name = var.project_id
parent = try(var.project_create.parent, null)
billing_account = try(var.project_create.billing_account_id, null)
- project_create = var.project_create != null
+ project_reuse = var.project_create != null ? null : {}
prefix = var.project_create == null ? null : var.prefix
iam = (
var.project_create != true || var.admin_principal == null
diff --git a/fast/addons/1-resman-tenants/tenant-fast-automation.tf b/fast/addons/1-resman-tenants/tenant-fast-automation.tf
index ff9b6aac9..385aa248c 100644
--- a/fast/addons/1-resman-tenants/tenant-fast-automation.tf
+++ b/fast/addons/1-resman-tenants/tenant-fast-automation.tf
@@ -88,10 +88,16 @@ module "tenant-automation-project" {
module "tenant-automation-project-iam" {
- source = "../../../modules/project"
- for_each = local.fast_tenants
- name = module.tenant-automation-project[each.key].project_id
- project_create = false
+ source = "../../../modules/project"
+ for_each = local.fast_tenants
+ name = module.tenant-automation-project[each.key].project_id
+ project_reuse = {
+ use_data_source = false
+ project_attributes = {
+ name = module.tenant-automation-project[each.key].name
+ number = module.tenant-automation-project[each.key].number
+ }
+ }
# human (groups) IAM bindings
iam_by_principals = {
(each.value.principals.gcp-devops) = [
diff --git a/fast/addons/2-networking-ngfw/main.tf b/fast/addons/2-networking-ngfw/main.tf
index 87b03d3cd..16d5a0122 100644
--- a/fast/addons/2-networking-ngfw/main.tf
+++ b/fast/addons/2-networking-ngfw/main.tf
@@ -22,10 +22,10 @@ locals {
}
module "project" {
- source = "../../../modules/project"
- count = var._fast_debug.skip_datasources == true ? 0 : 1
- name = local.aliased_project_id
- project_create = false
+ source = "../../../modules/project"
+ count = var._fast_debug.skip_datasources == true ? 0 : 1
+ name = local.aliased_project_id
+ project_reuse = {}
service_agents_config = {
services_enabled = [
"networksecurity.googleapis.com"
diff --git a/fast/addons/2-networking-swp/main.tf b/fast/addons/2-networking-swp/main.tf
index 105859adf..00b1596b9 100644
--- a/fast/addons/2-networking-swp/main.tf
+++ b/fast/addons/2-networking-swp/main.tf
@@ -36,10 +36,10 @@ locals {
}
module "project" {
- source = "../../../modules/project"
- count = var._fast_debug.skip_datasources == true ? 0 : 1
- name = local.aliased_project_id
- project_create = false
+ source = "../../../modules/project"
+ count = var._fast_debug.skip_datasources == true ? 0 : 1
+ name = local.aliased_project_id
+ project_reuse = {}
service_agents_config = {
services_enabled = [
"networksecurity.googleapis.com"
diff --git a/fast/stages/1-resman/tenant-root.tf b/fast/stages/1-resman/tenant-root.tf
index e5d79c717..38403ff54 100644
--- a/fast/stages/1-resman/tenant-root.tf
+++ b/fast/stages/1-resman/tenant-root.tf
@@ -32,10 +32,10 @@ module "root-folder" {
}
module "automation-project" {
- source = "../../../modules/project"
- count = var.root_node != null ? 1 : 0
- name = var.automation.project_id
- project_create = false
+ source = "../../../modules/project"
+ count = var.root_node != null ? 1 : 0
+ name = var.automation.project_id
+ project_reuse = {}
# do not assign tagViewer or tagUser roles here on tag keys and values as
# they are managed authoritatively and will break multitenant stages
tags = merge(local.tags, {
diff --git a/fast/stages/2-project-factory/README.md b/fast/stages/2-project-factory/README.md
index ba1e8b845..69762c44d 100644
--- a/fast/stages/2-project-factory/README.md
+++ b/fast/stages/2-project-factory/README.md
@@ -370,6 +370,7 @@ The approach is not shown here but reasonably easy to implement. The main projec
| name | description | sensitive | consumers |
|---|---|:---:|---|
-| [projects](outputs.tf#L32) | Created projects. | | |
-| [service_accounts](outputs.tf#L46) | Created service accounts. | | |
+| [buckets](outputs.tf#L32) | Created buckets. | | |
+| [projects](outputs.tf#L39) | Created projects. | | |
+| [service_accounts](outputs.tf#L53) | Created service accounts. | | |
diff --git a/fast/stages/2-project-factory/outputs.tf b/fast/stages/2-project-factory/outputs.tf
index 2ac905c56..dfaa581d2 100644
--- a/fast/stages/2-project-factory/outputs.tf
+++ b/fast/stages/2-project-factory/outputs.tf
@@ -29,6 +29,13 @@ locals {
}
}
+output "buckets" {
+ description = "Created buckets."
+ value = {
+ for k, v in module.projects.buckets : k => v
+ }
+}
+
output "projects" {
description = "Created projects."
value = {
@@ -47,8 +54,8 @@ output "service_accounts" {
description = "Created service accounts."
value = {
for k, v in module.projects.service_accounts : k => {
- email = v.email
- iam_emanil = v.iam_email
+ email = v.email
+ iam_email = v.iam_email
}
}
}
diff --git a/modules/project-factory/README.md b/modules/project-factory/README.md
index 937f5fb79..8ca679382 100644
--- a/modules/project-factory/README.md
+++ b/modules/project-factory/README.md
@@ -6,10 +6,10 @@ It supports
- filesystem-driven folder hierarchy exposing the full configuration options available in the [folder module](../folder/)
- multiple project creation and management exposing the full configuration options available in the [project module](../project/), including KMS key grants and VPC-SC perimeter membership
-- optional per-project [service account management](#service-accounts) including basic IAM grants
+- optional per-project [service account and bucket management](#service-accounts-and-buckets) including basic IAM grants
- optional [billing budgets](#billing-budgets) factory and budget/project associations
- cross-referencing of hierarchy folders in projects
-- optional per-project IaC configuration (TODO)
+- optional per-project IaC configuration
The factory is implemented as a thin data translation layer for the underlying modules, so that no "magic" or hidden side effects are implemented in code, and debugging or integration of new features are simple.
@@ -20,14 +20,16 @@ The code is meant to be executed by a high level service accounts with powerful
- Shared VPC connection if service project attachment is desired
- billing cost manager permissions to manage budgets and monitoring permissions if notifications should also be managed here
+## Contents
+
- [Folder hierarchy](#folder-hierarchy)
- [Projects](#projects)
- [Factory-wide project defaults, merges, optionals](#factory-wide-project-defaults-merges-optionals)
- - [Service accounts](#service-accounts)
+ - [Service accounts and buckets](#service-accounts-and-buckets)
- [Automation project and resources](#automation-project-and-resources)
- [Billing budgets](#billing-budgets)
-- [Substitutions in YAML configurations attributes](#substitutions-in-yaml-configurations-attributes)
+- [Interpolation in YAML configuration attributes](#interpolation-in-yaml-configuration-attributes)
- [Example](#example)
- [Files](#files)
- [Variables](#variables)
@@ -61,11 +63,11 @@ In addition to the YAML-based project configurations, the factory accepts three
Some examples on where to use each of the three sets are [provided below](#example).
-### Service accounts
+### Service accounts and buckets
-Service accounts can be managed as part of each project's YAML configuration. This allows creation of default service accounts used for GCE instances, in firewall rules, or for application-level credentials without resorting to a separate Terraform configuration.
+Service accounts and GCS buckets can be managed as part of each project's YAML configuration. This allows creation of default service accounts used for GCE instances, in firewall rules, or for application-level credentials without resorting to a separate Terraform configuration.
-Each service account is represented by one key and a set of optional key/value pairs in the `service_accounts` top-level YAML map, which exposes most of the variables available in the `iam-service-account` module:
+Each service account is represented by one key and a set of optional key/value pairs in the `service_accounts` top-level YAML map, which exposes most of the variables available in the `iam-service-account` module. Both the `display_name` and `iam_self_roles` attributes are optional.
```yaml
service_accounts:
@@ -77,21 +79,31 @@ service_accounts:
iam_project_roles:
my-host-project:
- roles/compute.networkUser
+ terraform-rw: {}
```
-Both the `display_name` and `iam_self_roles` attributes are optional.
+Each bucket is represented by one key and a set of optional key/value pairs in the `buckets` top-level YAML map, which exposes most of the variables available in the `gcs` module. Bucket location, storage class and a few other attributes can be defaulted/enforced via project factory level variables.
+
+```yaml
+buckets:
+ state:
+ location: europe-west8
+ iam:
+ roles/storage.admin:
+ - terraform-rw
+```
### Automation project and resources
-Project configurations also support defining service accounts and storage buckets to support automation, created in a separate controlling project so as to be outside of the sphere of control of the managed project.
+Other than creating automation resources within the project via the `service_accounts` and `buckets` attributes, this module also support management of automation resources created in a separate controlling project. This allows grating broad roles on the project, while still making sure that the automation resources used for Terraform cannot be manipulated from the same identities.
Automation resources are defined via the `automation` attribute in project configurations, which supports:
-- a mandatory `project` attribute to define the external controlling project
-- an optional `service_accounts` list where each element will define a service account in the controlling project
-- an optional `buckets` map where each key will define a bucket in the controlling project, and the map of roles/principals in the corresponding value assigned on the created bucket; principals can refer to the created service accounts by key
+- a mandatory `project` attribute to define the external controlling project; this attribute does not support interpolation and needs to be explicit
+- an optional `service_accounts` list where each element defines a service account in the controlling project
+- an optional `buckets` map where each key defines a bucket in the controlling project, and the map of roles/principals in the corresponding value assigned on the created bucket; principals can refer to the created service accounts by key
-Service accounts and buckets will be prefixed with the project name, and use the key specified in the YAML file as a suffix.
+Service accounts and buckets are be prefixed with the project name, and use the key specified in the YAML file as a suffix.
```yaml
# file name: prod-app-example-0
@@ -152,16 +164,16 @@ billing_budgets:
A simple billing budget example is show in the [example](#example) below.
-## Substitutions in YAML configurations attributes
+## Interpolation in YAML configuration attributes
-Substitutions allow referring via short mnemonic names to resources which are either created at runtime, or externally manages.
+Interpolation allow referring via short mnemonic names to resources which are either created at runtime, or externally managed.
This feature has two main benefits:
- being able to refer to resource ids which cannot be known before creation, for example project automation service accounts in IAM bindings
- making YAML configuration files more easily readable and portable, by using mnemonic keys which are not specific to an organization or project
-One example of both types of substitutions is in this project snippet. The automation service account is used in IAM bindings via its `rw` key, while the parent folder is set by referring to its path in the hierarchy factory.
+One example of both types of contexts is in this project snippet. The automation service account is used in IAM bindings via its `rw` key, while the parent folder is set by referring to its path in the hierarchy factory.
```yaml
parent: teams/team-a
@@ -181,28 +193,28 @@ automation:
- rw
```
-Substitutions come from two separate context sources: an internal set for resources managed by the project factory (folders, service accounts, etc.), and an external user-defined set passed in via the `factories_config.context` variable.
+Interpolations leverage contexts from two separate sources: an internal set for resources managed by the project factory (folders, service accounts, etc.), and an external user-defined set passed in via the `factories_config.context` variable.
-Internal substitutions are:
+The following table lists the available context interpolations. External contexts are passed in via the `factories_config.contexts` variable. IAM principals are interpolated in all IAM attributes except `iam_by_principal`. First two columns show for which attribute of which resource context is interpolated. `external contexts` column show in which map passed as `var.factories_config.context` key will be looked up.
-- hierarchy folders, used to set project parents via the filesystem path of folders (e.g. `teams/team-a`)
-- automation service accounts, used in project IAM bindings via their keys; this does not work in folder IAM bindings
+* Internally created folders creates keys under `${folder_name_1}[/${folder_name_2}/${folder_name_3}]`
+* IAM principals are resolved within context of managed project
-External substitution are:
-
-- the map of folder ids in `factories_config.context.folder_ids`, used to set top-level folder parents; the `default` key if present is used when no explicit parent has been set in the YAML file
-- the map of IAM principals in `factories_config.context.iam_principals`, used in IAM bindings for folders and projects; the exception is the `iam_by_principals` attribute which uses no interpolation to prevent dynamic cycles
-- the map of tag value ids in `factories_config.context.tag_values` used in tag bindings for folders and projects
-- the map of Shared VPC host project ids in `factories_config.context.vpc_host_projects` used in service project configurations for projects
-
-External substitution maps are optional, and there's no harm in not defining them if not used.
-
-Some caveats on substitutions:
-
-- project-own service accounts are not part of substitutions to prevent cycles, you can use the `iam_project_roles` and `iam_self_roles` attributes for additive IAM on projects
-- project shared vpc configurations and project-own service accounts only support external substitutions to prevent cycles
-- projects for automation service accounts and buckets do not support substitutions to prevent cycles
-- no substitutions are implemented (yet) for budgets
+| resource | attribute | external contexts | internal contexts |
+| ------------------- | --------------- | ------------------- | -------------------------- |
+| folder | parent | `folder_ids` | internally created folders |
+| folder | IAM principals | `iam_principals` | |
+| folder | tag bindings | `tag_values` | |
+| project | parent | `folder_ids` | internally created folders |
+| project | Shared VPC host | `vpc_host_projects` | |
+| project | Shared VPC IAM | `iam_principals` | |
+| project | tag bindings | `tag_values` | |
+| project | IAM principals | `iam_principals` | project service accounts |
+| | | | IaC service accounts |
+| bucket | IAM principals | `iam_principals` | project service accounts |
+| service account | IAM projects | `vpc_host_projects` | |
+| IaC bucket | IAM principals | `iam_principals` | IaC service accounts |
+| IaC service account | IAM principals | `iam_principals` | |
## Example
@@ -266,7 +278,7 @@ module "project-factory" {
}
}
}
-# tftest modules=15 resources=56 files=0,1,2,3,4,5,6,7,8 inventory=example.yaml
+# tftest modules=16 resources=56 files=0,1,2,3,4,5,6,7,8 inventory=example.yaml
```
A simple hierarchy of folders:
@@ -432,7 +444,7 @@ update_rules:
| [factory-folders.tf](./factory-folders.tf) | Folder hierarchy factory locals. | |
| [factory-projects.tf](./factory-projects.tf) | Projects factory locals. | |
| [folders.tf](./folders.tf) | Folder hierarchy factory resources. | folder |
-| [main.tf](./main.tf) | Projects and billing budgets factory resources. | billing-account · iam-service-account · project |
+| [main.tf](./main.tf) | Projects and billing budgets factory resources. | billing-account · gcs · iam-service-account · project |
| [outputs.tf](./outputs.tf) | Module outputs. | |
| [variables.tf](./variables.tf) | Module variables. | |
@@ -449,9 +461,10 @@ update_rules:
| name | description | sensitive |
|---|---|:---:|
-| [folders](outputs.tf#L17) | Folder ids. | |
-| [projects](outputs.tf#L22) | Created projects. | |
-| [service_accounts](outputs.tf#L44) | Service account emails. | |
+| [buckets](outputs.tf#L17) | Bucket names. | |
+| [folders](outputs.tf#L24) | Folder ids. | |
+| [projects](outputs.tf#L29) | Created projects. | |
+| [service_accounts](outputs.tf#L51) | Service account emails. | |
## Tests
diff --git a/modules/project-factory/automation.tf b/modules/project-factory/automation.tf
index 02c4218e4..fd4646cad 100644
--- a/modules/project-factory/automation.tf
+++ b/modules/project-factory/automation.tf
@@ -85,9 +85,15 @@ module "automation-buckets" {
lookup(each.value, "location", null),
var.data_defaults.storage_location
)
- storage_class = lookup(each.value, "storage_class", "STANDARD")
- uniform_bucket_level_access = lookup(each.value, "uniform_bucket_level_access", true)
- versioning = lookup(each.value, "versioning", false)
+ storage_class = lookup(
+ each.value, "storage_class", "STANDARD"
+ )
+ uniform_bucket_level_access = lookup(
+ each.value, "uniform_bucket_level_access", true
+ )
+ versioning = lookup(
+ each.value, "versioning", false
+ )
}
module "automation-service-accounts" {
diff --git a/modules/project-factory/factory-projects.tf b/modules/project-factory/factory-projects.tf
index a204a44a0..5d407111b 100644
--- a/modules/project-factory/factory-projects.tf
+++ b/modules/project-factory/factory-projects.tf
@@ -163,9 +163,40 @@ locals {
var.data_defaults.logging_data_access
)
# non-project resources
+ buckets = try(v.buckets, {})
service_accounts = try(v.service_accounts, {})
})
}
+ buckets = flatten([
+ for k, v in local.projects : [
+ for name, opts in v.buckets : {
+ project = k
+ name = name
+ description = lookup(opts, "description", "Terraform-managed.")
+ encryption_key = lookup(opts, "encryption_key", null)
+ iam = lookup(opts, "iam", {})
+ iam_bindings = lookup(opts, "iam_bindings", {})
+ iam_bindings_additive = lookup(opts, "iam_bindings_additive", {})
+ labels = lookup(opts, "labels", {})
+ location = lookup(opts, "location", null)
+ prefix = coalesce(
+ var.data_overrides.prefix,
+ try(v.prefix, null),
+ var.data_defaults.prefix
+ )
+ storage_class = lookup(
+ opts, "storage_class", "STANDARD"
+ )
+ uniform_bucket_level_access = lookup(
+ opts, "uniform_bucket_level_access", true
+ )
+ versioning = lookup(
+ opts, "versioning", false
+ )
+
+ }
+ ]
+ ])
service_accounts = flatten([
for k, v in local.projects : [
for name, opts in v.service_accounts : {
diff --git a/modules/project-factory/main.tf b/modules/project-factory/main.tf
index f350503f3..8596c828c 100644
--- a/modules/project-factory/main.tf
+++ b/modules/project-factory/main.tf
@@ -59,46 +59,6 @@ module "projects" {
notification_channels = var.factories_config.context.notification_channels
}
}
- iam = {
- for k, v in lookup(each.value, "iam", {}) : k => [
- for vv in v : try(
- # automation service account
- local.context.iam_principals["${each.key}/${vv}"],
- # other context
- local.context.iam_principals[vv],
- # passthrough
- vv
- )
- ]
- }
- iam_bindings = {
- for k, v in lookup(each.value, "iam_bindings", {}) : k => merge(v, {
- members = [
- for vv in v.members : try(
- # automation service account
- local.context.iam_principals["${each.key}/${vv}"],
- # other context
- local.context.iam_principals[vv],
- # passthrough
- vv
- )
- ]
- })
- }
- iam_bindings_additive = {
- for k, v in lookup(each.value, "iam_bindings_additive", {}) : k => merge(v, {
- member = try(
- # automation service account
- local.context.iam_principals["${each.key}/${v.member}"],
- # other context
- local.context.iam_principals[v.member],
- # passthrough
- v.member
- )
- })
- }
- # IAM by principals would trigger dynamic key errors so we don't interpolate
- iam_by_principals = try(each.value.iam_by_principals, {})
labels = merge(
each.value.labels, var.data_merges.labels
)
@@ -145,6 +105,114 @@ module "projects" {
vpc_sc = each.value.vpc_sc
}
+module "projects-iam" {
+ source = "../project"
+ for_each = local.projects
+ name = module.projects[each.key].project_id
+ project_reuse = {
+ use_data_source = false
+ project_attributes = {
+ name = module.projects[each.key].name
+ number = module.projects[each.key].number
+ }
+ }
+ iam = {
+ for k, v in lookup(each.value, "iam", {}) : k => [
+ for vv in v : try(
+ # project service accounts
+ module.service-accounts["${each.key}/${vv}"].iam_email,
+ # automation service account
+ local.context.iam_principals["${each.key}/${vv}"],
+ # other context
+ local.context.iam_principals[vv],
+ # passthrough
+ vv
+ )
+ ]
+ }
+ iam_bindings = {
+ for k, v in lookup(each.value, "iam_bindings", {}) : k => merge(v, {
+ members = [
+ for vv in v.members : try(
+ # project service accounts
+ module.service-accounts["${each.key}/${vv}"].iam_email,
+ # automation service account
+ local.context.iam_principals["${each.key}/${vv}"],
+ # other context
+ local.context.iam_principals[vv],
+ # passthrough
+ vv
+ )
+ ]
+ })
+ }
+ iam_bindings_additive = {
+ for k, v in lookup(each.value, "iam_bindings_additive", {}) : k => merge(v, {
+ member = try(
+ # project service accounts
+ module.service-accounts["${each.key}/${v.member}"].iam_email,
+ # automation service account
+ local.context.iam_principals["${each.key}/${v.member}"],
+ # other context
+ local.context.iam_principals[v.member],
+ # passthrough
+ v.member
+ )
+ })
+ }
+ # IAM by principals would trigger dynamic key errors so we don't interpolate
+ iam_by_principals = try(each.value.iam_by_principals, {})
+}
+
+module "buckets" {
+ source = "../gcs"
+ for_each = {
+ for k in local.buckets : "${k.project}/${k.name}" => k
+ }
+ project_id = module.projects[each.value.project].project_id
+ prefix = each.value.prefix
+ name = "${each.value.project}-${each.value.name}"
+ encryption_key = each.value.encryption_key
+ iam = {
+ for k, v in each.value.iam : k => [
+ for vv in v : try(
+ module.service-accounts["${each.value.project}/${vv}"].iam_email,
+ var.factories_config.context.iam_principals[vv],
+ vv
+ )
+ ]
+ }
+ iam_bindings = {
+ for k, v in each.value.iam_bindings : k => merge(v, {
+ members = [
+ for vv in v.members : try(
+ module.service-accounts["${each.value.project}/${vv}"].iam_email,
+ var.factories_config.context.iam_principals[vv],
+ vv
+ )
+ ]
+ })
+ }
+ iam_bindings_additive = {
+ for k, v in each.value.iam_bindings_additive : k => merge(v, {
+ member = try(
+ module.service-accounts["${each.value.project}/${v.member}"].iam_email,
+ var.factories_config.context.iam_principals[v.member],
+ v.member
+ )
+ })
+ }
+ labels = each.value.labels
+ location = coalesce(
+ var.data_overrides.storage_location,
+ lookup(each.value, "location", null),
+ var.data_defaults.storage_location
+ )
+ storage_class = each.value.storage_class
+ uniform_bucket_level_access = each.value.uniform_bucket_level_access
+ versioning = each.value.versioning
+}
+
module "service-accounts" {
source = "../iam-service-account"
for_each = {
diff --git a/modules/project-factory/outputs.tf b/modules/project-factory/outputs.tf
index 21e4fcd2b..a76c7f880 100644
--- a/modules/project-factory/outputs.tf
+++ b/modules/project-factory/outputs.tf
@@ -14,6 +14,13 @@
* limitations under the License.
*/
+output "buckets" {
+ description = "Bucket names."
+ value = {
+ for k, v in module.buckets : k => v.name
+ }
+}
+
output "folders" {
description = "Folder ids."
value = local.hierarchy
@@ -43,7 +50,5 @@ output "projects" {
output "service_accounts" {
description = "Service account emails."
- value = {
- for k, v in module.service-accounts : k => v.email
- }
+ value = module.service-accounts
}
diff --git a/modules/project-factory/schemas/project.schema.json b/modules/project-factory/schemas/project.schema.json
index 82a2aa16e..1517a8fc8 100644
--- a/modules/project-factory/schemas/project.schema.json
+++ b/modules/project-factory/schemas/project.schema.json
@@ -15,49 +15,7 @@
"type": "string"
},
"buckets": {
- "type": "object",
- "additionalProperties": false,
- "patternProperties": {
- "^[a-z0-9-]+$": {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "description": {
- "type": "string"
- },
- "iam": {
- "$ref": "#/$defs/iam"
- },
- "iam_bindings": {
- "$ref": "#/$defs/iam_bindings"
- },
- "iam_bindings_additive": {
- "$ref": "#/$defs/iam_bindings_additive"
- },
- "labels": {
- "type": "object",
- "additionalProperties": {
- "type": "string"
- }
- },
- "location": {
- "type": "string"
- },
- "prefix": {
- "type": "string"
- },
- "storage_class": {
- "type": "string"
- },
- "uniform_bucket_level_access": {
- "type": "boolean"
- },
- "versioning": {
- "type": "boolean"
- }
- }
- }
- }
+ "$ref": "#/$defs/buckets"
},
"service_accounts": {
"type": "object",
@@ -112,6 +70,9 @@
"type": "string"
}
},
+ "buckets": {
+ "$ref": "#/$defs/buckets"
+ },
"contacts": {
"type": "object",
"additionalProperties": false,
@@ -381,6 +342,51 @@
}
},
"$defs": {
+ "buckets": {
+ "type": "object",
+ "additionalProperties": false,
+ "patternProperties": {
+ "^[a-z0-9-]+$": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "description": {
+ "type": "string"
+ },
+ "iam": {
+ "$ref": "#/$defs/iam"
+ },
+ "iam_bindings": {
+ "$ref": "#/$defs/iam_bindings"
+ },
+ "iam_bindings_additive": {
+ "$ref": "#/$defs/iam_bindings_additive"
+ },
+ "labels": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ }
+ },
+ "location": {
+ "type": "string"
+ },
+ "prefix": {
+ "type": "string"
+ },
+ "storage_class": {
+ "type": "string"
+ },
+ "uniform_bucket_level_access": {
+ "type": "boolean"
+ },
+ "versioning": {
+ "type": "boolean"
+ }
+ }
+ }
+ }
+ },
"iam": {
"type": "object",
"additionalProperties": false,
diff --git a/modules/project/README.md b/modules/project/README.md
index 878b9e4f5..4f3eeb828 100644
--- a/modules/project/README.md
+++ b/modules/project/README.md
@@ -29,7 +29,7 @@ This module implements the creation and management of one GCP project including
- [Quotas factory](#quotas-factory)
- [VPC Service Controls](#vpc-service-controls)
- [Project Related Outputs](#project-related-outputs)
- - [Managing project related configuration without creating it](#managing-project-related-configuration-without-creating-it)
+- [Managing project related configuration without creating it](#managing-project-related-configuration-without-creating-it)
- [Observability](#observability)
- [Observability factory](#observability-factory)
- [Files](#files)
@@ -752,6 +752,7 @@ module "project" {
}
# tftest modules=1 resources=3 inventory=logging-data-access.yaml e2e
```
+
## Log Scopes
```hcl
@@ -1203,9 +1204,14 @@ output "default_service_accounts" {
# tftest modules=1 resources=3 inventory=outputs.yaml e2e
```
-### Managing project related configuration without creating it
+## Managing project related configuration without creating it
-The module offers managing all related resources without ever touching the project itself by using `project_create = false`
+The module also supports configuring an existing project, via the `project_reuse` variable. Two different behaviours are possible when a project is reused:
+
+- using a data source to fetch project data (name and number) dynamically
+- avoiding use of a data source when project data is known
+
+The first use case is the most common one, and is what the module defaults to when the `project_reuse` variable is not null. The second use case is used when project creation and configuration are split in two separate modules in the same Terraform root module, e.g. to avoid dependency cycles.
```hcl
module "create-project" {
@@ -1217,14 +1223,19 @@ module "create-project" {
}
module "project" {
- source = "./fabric/modules/project"
- depends_on = [module.create-project]
- billing_account = var.billing_account_id
- name = "project"
- parent = var.folder_id
- prefix = var.prefix
- project_create = false
-
+ source = "./fabric/modules/project"
+ name = module.create-project.project_id
+ prefix = var.prefix
+ # default behavior, uses a data source internally
+ # project_reuse = {}
+ # avoid use of a data source when project attributes are available
+ project_reuse = {
+ use_data_source = false
+ project_attributes = {
+ name = module.create-project.name
+ number = module.create-project.number
+ }
+ }
iam_by_principals = {
"group:${var.group_email}" = [
"roles/cloudasset.owner",
@@ -1577,7 +1588,6 @@ alerts:
foo: bar
```
-
## Files
@@ -1609,7 +1619,7 @@ alerts:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [name](variables.tf#L110) | Project name and id suffix. | string | ✓ | |
+| [name](variables.tf#L109) | Project name and id suffix. | string | ✓ | |
| [alerts](variables-observability.tf#L17) | Monitoring alerts. | map(object({…})) | | {} |
| [auto_create_network](variables.tf#L17) | Whether to create the default network for the project. | bool | | false |
| [billing_account](variables.tf#L23) | Billing account id. | string | | null |
@@ -1617,16 +1627,16 @@ alerts:
| [contacts](variables.tf#L36) | List of essential contacts for this resource. Must be in the form EMAIL -> [NOTIFICATION_TYPES]. Valid notification types are ALL, SUSPENSION, SECURITY, TECHNICAL, BILLING, LEGAL, PRODUCT_UPDATES. | map(list(string)) | | {} |
| [custom_roles](variables.tf#L43) | Map of role name => list of permissions to create in this project. | map(list(string)) | | {} |
| [default_service_account](variables.tf#L50) | Project default service account setting: can be one of `delete`, `deprivilege`, `disable`, or `keep`. | string | | "keep" |
-| [deletion_policy](variables.tf#L64) | Deletion policy setting for this project. | string | | "DELETE" |
-| [descriptive_name](variables.tf#L75) | Name of the project name. Used for project name instead of `name` variable. | string | | null |
-| [factories_config](variables.tf#L81) | Paths to data files and folders that enable factory functionality. | object({…}) | | {} |
+| [deletion_policy](variables.tf#L63) | Deletion policy setting for this project. | string | | "DELETE" |
+| [descriptive_name](variables.tf#L74) | Name of the project name. Used for project name instead of `name` variable. | string | | null |
+| [factories_config](variables.tf#L80) | Paths to data files and folders that enable factory functionality. | object({…}) | | {} |
| [iam](variables-iam.tf#L17) | Authoritative IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
| [iam_bindings](variables-iam.tf#L24) | Authoritative IAM bindings in {KEY => {role = ROLE, members = [], condition = {}}}. Keys are arbitrary. | map(object({…})) | | {} |
| [iam_bindings_additive](variables-iam.tf#L39) | Individual additive IAM bindings. Keys are arbitrary. | map(object({…})) | | {} |
| [iam_by_principals](variables-iam.tf#L61) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam` variable. | map(list(string)) | | {} |
| [iam_by_principals_additive](variables-iam.tf#L54) | Additive IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid errors. Merged internally with the `iam_bindings_additive` variable. | map(list(string)) | | {} |
-| [labels](variables.tf#L97) | Resource labels. | map(string) | | {} |
-| [lien_reason](variables.tf#L104) | If non-empty, creates a project lien with this description. | string | | null |
+| [labels](variables.tf#L96) | Resource labels. | map(string) | | {} |
+| [lien_reason](variables.tf#L103) | If non-empty, creates a project lien with this description. | string | | null |
| [log_scopes](variables-observability.tf#L117) | Log scopes under this project. | map(object({…})) | | {} |
| [logging_data_access](variables-observability.tf#L127) | Control activation of data access logs. The special 'allServices' key denotes configuration for all services. | map(object({…})) | | {} |
| [logging_exclusions](variables-observability.tf#L138) | Logging exclusions for this project in the form {NAME -> FILTER}. | map(string) | | {} |
@@ -1635,22 +1645,22 @@ alerts:
| [metric_scopes](variables-observability.tf#L216) | List of projects that will act as metric scopes for this project. | list(string) | | [] |
| [network_tags](variables-tags.tf#L17) | Network tags by key name. If `id` is provided, key creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} |
| [notification_channels](variables-observability.tf#L223) | Monitoring notification channels. | map(object({…})) | | {} |
-| [org_policies](variables.tf#L115) | Organization policies applied to this project keyed by policy name. | map(object({…})) | | {} |
-| [parent](variables.tf#L143) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string | | null |
-| [prefix](variables.tf#L153) | Optional prefix used to generate project id and name. | string | | null |
-| [project_create](variables.tf#L163) | Create project. When set to false, uses a data source to reference existing project. | bool | | true |
+| [org_policies](variables.tf#L114) | Organization policies applied to this project keyed by policy name. | map(object({…})) | | {} |
+| [parent](variables.tf#L142) | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string | | null |
+| [prefix](variables.tf#L152) | Optional prefix used to generate project id and name. | string | | null |
+| [project_reuse](variables.tf#L162) | Reuse existing project if not null. If name and number are not passed in, a data source is used. | object({…}) | | null |
| [quotas](variables-quotas.tf#L17) | Service quota configuration. | map(object({…})) | | {} |
-| [service_agents_config](variables.tf#L169) | Automatic service agent configuration options. | object({…}) | | {} |
-| [service_config](variables.tf#L180) | Configure service API activation. | object({…}) | | {…} |
-| [service_encryption_key_ids](variables.tf#L192) | Service Agents to be granted encryption/decryption permissions over Cloud KMS encryption keys. Format {SERVICE_AGENT => [KEY_ID]}. | map(list(string)) | | {} |
-| [services](variables.tf#L199) | Service APIs to enable. | list(string) | | [] |
-| [shared_vpc_host_config](variables.tf#L205) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…}) | | null |
-| [shared_vpc_service_config](variables.tf#L214) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…}) | | {…} |
-| [skip_delete](variables.tf#L242) | Deprecated. Use deletion_policy. | bool | | null |
+| [service_agents_config](variables.tf#L181) | Automatic service agent configuration options. | object({…}) | | {} |
+| [service_config](variables.tf#L192) | Configure service API activation. | object({…}) | | {…} |
+| [service_encryption_key_ids](variables.tf#L204) | Service Agents to be granted encryption/decryption permissions over Cloud KMS encryption keys. Format {SERVICE_AGENT => [KEY_ID]}. | map(list(string)) | | {} |
+| [services](variables.tf#L211) | Service APIs to enable. | list(string) | | [] |
+| [shared_vpc_host_config](variables.tf#L217) | Configures this project as a Shared VPC host project (mutually exclusive with shared_vpc_service_project). | object({…}) | | null |
+| [shared_vpc_service_config](variables.tf#L226) | Configures this project as a Shared VPC service project (mutually exclusive with shared_vpc_host_config). | object({…}) | | {…} |
+| [skip_delete](variables.tf#L254) | Deprecated. Use deletion_policy. | bool | | null |
| [tag_bindings](variables-tags.tf#L81) | Tag bindings for this project, in key => tag value id format. | map(string) | | null |
| [tags](variables-tags.tf#L88) | Tags by key name. If `id` is provided, key or value creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} |
-| [universe](variables.tf#L254) | GCP universe where to deploy the project. The prefix will be prepended to the project id. | object({…}) | | null |
-| [vpc_sc](variables.tf#L263) | VPC-SC configuration for the project, use when `ignore_changes` for resources is set in the VPC-SC module. | object({…}) | | null |
+| [universe](variables.tf#L266) | GCP universe where to deploy the project. The prefix will be prepended to the project id. | object({…}) | | null |
+| [vpc_sc](variables.tf#L275) | VPC-SC configuration for the project, use when `ignore_changes` for resources is set in the VPC-SC module. | object({…}) | | null |
## Outputs
diff --git a/modules/project/main.tf b/modules/project/main.tf
index 8cf3106e9..c789c11a4 100644
--- a/modules/project/main.tf
+++ b/modules/project/main.tf
@@ -26,31 +26,39 @@ locals {
parent_type = var.parent == null ? null : split("/", var.parent)[0]
parent_id = var.parent == null ? null : split("/", var.parent)[1]
prefix = var.prefix == null ? "" : "${var.prefix}-"
- project_id = "${local.universe_prefix}${local.prefix}${var.name}"
project = (
- var.project_create ?
- {
+ var.project_reuse == null
+ ? {
project_id = try(google_project.project[0].project_id, null)
number = try(google_project.project[0].number, null)
name = try(google_project.project[0].name, null)
}
- : {
- project_id = local.project_id
- number = try(data.google_project.project[0].number, null)
- name = try(data.google_project.project[0].name, null)
- }
+ : (
+ try(var.project_reuse.use_data_source, null) == false
+ ? {
+ project_id = local.project_id
+ number = try(var.project_reuse.project_attributes.number, null)
+ name = try(var.project_reuse.project_attributes.name, null)
+ }
+ : {
+ project_id = local.project_id
+ number = try(data.google_project.project[0].number, null)
+ name = try(data.google_project.project[0].name, null)
+ }
+ )
)
+ project_id = "${local.universe_prefix}${local.prefix}${var.name}"
universe_prefix = var.universe == null ? "" : "${var.universe.prefix}:"
available_services = tolist(setsubtract(var.services, try(var.universe.unavailable_services, [])))
}
data "google_project" "project" {
- count = var.project_create ? 0 : 1
+ count = try(var.project_reuse.use_data_source, null) == true ? 1 : 0
project_id = local.project_id
}
resource "google_project" "project" {
- count = var.project_create ? 1 : 0
+ count = var.project_reuse == null ? 1 : 0
org_id = local.parent_type == "organizations" ? local.parent_id : null
folder_id = local.parent_type == "folders" ? local.parent_id : null
project_id = local.project_id
diff --git a/modules/project/variables.tf b/modules/project/variables.tf
index b0e27c928..dd9340907 100644
--- a/modules/project/variables.tf
+++ b/modules/project/variables.tf
@@ -60,7 +60,6 @@ variable "default_service_account" {
}
}
-
variable "deletion_policy" {
description = "Deletion policy setting for this project."
default = "DELETE"
@@ -160,10 +159,23 @@ variable "prefix" {
}
}
-variable "project_create" {
- description = "Create project. When set to false, uses a data source to reference existing project."
- type = bool
- default = true
+variable "project_reuse" {
+ description = "Reuse existing project if not null. If name and number are not passed in, a data source is used."
+ type = object({
+ use_data_source = optional(bool, true)
+ project_attributes = optional(object({
+ name = string
+ number = number
+ }))
+ })
+ default = null
+ validation {
+ condition = (
+ try(var.project_reuse.use_data_source, null) != false ||
+ try(var.project_reuse.project_attributes, null) != null
+ )
+ error_message = "Reuse datasource can be disabled only if project attributes are set."
+ }
}
variable "service_agents_config" {
diff --git a/tests/fast/addons/a1_resman_tenants/simple.yaml b/tests/fast/addons/a1_resman_tenants/simple.yaml
index ce130cbb6..46cb95a94 100644
--- a/tests/fast/addons/a1_resman_tenants/simple.yaml
+++ b/tests/fast/addons/a1_resman_tenants/simple.yaml
@@ -25,7 +25,7 @@ counts:
google_logging_project_bucket_config: 4
google_org_policy_policy: 6
google_organization_iam_member: 6
- google_project: 6
+ google_project: 4
google_project_iam_audit_config: 2
google_project_iam_binding: 32
google_project_iam_member: 34
@@ -43,4 +43,4 @@ counts:
google_tags_tag_key: 1
google_tags_tag_value: 4
modules: 50
- resources: 291
+ resources: 289
diff --git a/tests/modules/project/examples/data.yaml b/tests/modules/project/examples/data.yaml
index bae69bb7c..14f4e0fd8 100644
--- a/tests/modules/project/examples/data.yaml
+++ b/tests/modules/project/examples/data.yaml
@@ -26,11 +26,16 @@ values:
auto_create_network: false
billing_account: 123456-123456-123456
deletion_policy: DELETE
+ effective_labels:
+ goog-terraform-provisioned: 'true'
folder_id: '1122334455'
labels: null
name: test-project
org_id: null
project_id: test-project
+ tags: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
timeouts: null
module.dataset.google_bigquery_dataset.default:
dataset_id: bq_sink
@@ -39,6 +44,8 @@ values:
default_table_expiration_ms: null
delete_contents_on_destroy: true
description: Terraform managed.
+ effective_labels:
+ goog-terraform-provisioned: 'true'
external_dataset_reference: []
friendly_name: null
labels: null
@@ -46,15 +53,20 @@ values:
max_time_travel_hours: '168'
project: project-id
resource_tags: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
timeouts: null
module.gcs.google_storage_bucket.bucket[0]:
autoclass: []
cors: []
custom_placement_config: []
default_event_based_hold: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
enable_object_retention: null
encryption: []
force_destroy: true
+ hierarchical_namespace: []
labels: null
lifecycle_rule: []
location: EU
@@ -64,6 +76,8 @@ values:
requester_pays: null
retention_policy: []
storage_class: STANDARD
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
timeouts: null
uniform_bucket_level_access: true
module.host-project.google_compute_shared_vpc_host_project.shared_vpc_host[0]:
@@ -73,18 +87,27 @@ values:
auto_create_network: false
billing_account: 123456-123456-123456
deletion_policy: DELETE
+ effective_labels:
+ goog-terraform-provisioned: 'true'
folder_id: '1122334455'
labels: null
name: test-host
org_id: null
project_id: test-host
+ tags: null
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
timeouts: null
module.kms.google_kms_crypto_key.default["key-global"]:
+ effective_labels:
+ goog-terraform-provisioned: 'true'
labels: null
name: key-global
purpose: ENCRYPT_DECRYPT
rotation_period: null
skip_initial_version_creation: false
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
timeouts: null
module.kms.google_kms_key_ring.default[0]:
location: global
@@ -95,11 +118,9 @@ values:
condition: []
role: roles/cloudkms.cryptoKeyEncrypterDecrypter
module.project.data.google_bigquery_default_service_account.bq_sa[0]:
- project: test-project
- module.project.data.google_project.project[0]:
- project_id: test-project
+ project: test-test-project
module.project.data.google_storage_project_service_account.gcs_sa[0]:
- project: test-project
+ project: test-test-project
user_project: null
module.project.google_bigquery_dataset_iam_member.bq-sinks-binding["info"]:
condition: []
@@ -107,7 +128,7 @@ values:
module.project.google_compute_shared_vpc_service_project.shared_vpc_service[0]:
deletion_policy: null
host_project: test-host
- service_project: test-project
+ service_project: test-test-project
timeouts: null
module.project.google_kms_crypto_key_iam_member.service_agent_cmek["key-0.compute-system"]:
condition: []
@@ -120,7 +141,7 @@ values:
disabled: null
filter: resource.type=gce_instance
name: no-gce-instances
- project: test-project
+ project: test-test-project
module.project.google_logging_project_sink.sink["debug"]:
custom_writer_identity: null
description: debug (Terraform-managed).
@@ -132,7 +153,7 @@ values:
name: no-compute
filter: severity=DEBUG
name: debug
- project: test-project
+ project: test-test-project
unique_writer_identity: true
module.project.google_logging_project_sink.sink["info"]:
bigquery_options:
@@ -143,7 +164,7 @@ values:
exclusions: []
filter: severity=INFO
name: info
- project: test-project
+ project: test-test-project
unique_writer_identity: true
module.project.google_logging_project_sink.sink["notice"]:
custom_writer_identity: null
@@ -153,7 +174,7 @@ values:
exclusions: []
filter: severity=NOTICE
name: notice
- project: test-project
+ project: test-test-project
unique_writer_identity: true
module.project.google_logging_project_sink.sink["warnings"]:
custom_writer_identity: null
@@ -163,12 +184,12 @@ values:
exclusions: []
filter: severity=WARNING
name: warnings
- project: test-project
+ project: test-test-project
unique_writer_identity: true
module.project.google_org_policy_policy.default["compute.disableGuestAttributesAccess"]:
dry_run_spec: []
- name: projects/test-project/policies/compute.disableGuestAttributesAccess
- parent: projects/test-project
+ name: projects/test-test-project/policies/compute.disableGuestAttributesAccess
+ parent: projects/test-test-project
spec:
- inherit_from_parent: null
reset: null
@@ -177,12 +198,13 @@ values:
condition: []
deny_all: null
enforce: 'TRUE'
+ parameters: null
values: []
timeouts: null
module.project.google_org_policy_policy.default["compute.skipDefaultNetworkCreation"]:
dry_run_spec: []
- name: projects/test-project/policies/compute.skipDefaultNetworkCreation
- parent: projects/test-project
+ name: projects/test-test-project/policies/compute.skipDefaultNetworkCreation
+ parent: projects/test-test-project
spec:
- inherit_from_parent: null
reset: null
@@ -191,12 +213,13 @@ values:
condition: []
deny_all: null
enforce: 'TRUE'
+ parameters: null
values: []
timeouts: null
module.project.google_org_policy_policy.default["compute.trustedImageProjects"]:
dry_run_spec: []
- name: projects/test-project/policies/compute.trustedImageProjects
- parent: projects/test-project
+ name: projects/test-test-project/policies/compute.trustedImageProjects
+ parent: projects/test-test-project
spec:
- inherit_from_parent: null
reset: null
@@ -205,6 +228,7 @@ values:
condition: []
deny_all: null
enforce: null
+ parameters: null
values:
- allowed_values:
- projects/my-project
@@ -212,8 +236,8 @@ values:
timeouts: null
module.project.google_org_policy_policy.default["compute.vmExternalIpAccess"]:
dry_run_spec: []
- name: projects/test-project/policies/compute.vmExternalIpAccess
- parent: projects/test-project
+ name: projects/test-test-project/policies/compute.vmExternalIpAccess
+ parent: projects/test-test-project
spec:
- inherit_from_parent: null
reset: null
@@ -222,12 +246,13 @@ values:
condition: []
deny_all: 'TRUE'
enforce: null
+ parameters: null
values: []
timeouts: null
module.project.google_org_policy_policy.default["iam.allowedPolicyMemberDomains"]:
dry_run_spec: []
- name: projects/test-project/policies/iam.allowedPolicyMemberDomains
- parent: projects/test-project
+ name: projects/test-test-project/policies/iam.allowedPolicyMemberDomains
+ parent: projects/test-test-project
spec:
- inherit_from_parent: null
reset: null
@@ -236,6 +261,7 @@ values:
condition: []
deny_all: null
enforce: null
+ parameters: null
values:
- allowed_values:
- C0xxxxxxx
@@ -244,8 +270,8 @@ values:
timeouts: null
module.project.google_org_policy_policy.default["iam.disableServiceAccountKeyCreation"]:
dry_run_spec: []
- name: projects/test-project/policies/iam.disableServiceAccountKeyCreation
- parent: projects/test-project
+ name: projects/test-test-project/policies/iam.disableServiceAccountKeyCreation
+ parent: projects/test-test-project
spec:
- inherit_from_parent: null
reset: null
@@ -254,12 +280,13 @@ values:
condition: []
deny_all: null
enforce: 'TRUE'
+ parameters: null
values: []
timeouts: null
module.project.google_org_policy_policy.default["iam.disableServiceAccountKeyUpload"]:
dry_run_spec: []
- name: projects/test-project/policies/iam.disableServiceAccountKeyUpload
- parent: projects/test-project
+ name: projects/test-test-project/policies/iam.disableServiceAccountKeyUpload
+ parent: projects/test-test-project
spec:
- inherit_from_parent: null
reset: null
@@ -272,11 +299,13 @@ values:
title: condition
deny_all: null
enforce: 'TRUE'
+ parameters: null
values: []
- allow_all: null
condition: []
deny_all: null
enforce: 'FALSE'
+ parameters: null
values: []
timeouts: null
module.project.google_project_iam_audit_config.default["allServices"]:
@@ -284,7 +313,7 @@ values:
- exempted_members:
- group:organization-admins@example.org
log_type: ADMIN_READ
- project: test-project
+ project: test-test-project
service: allServices
module.project.google_project_iam_audit_config.default["storage.googleapis.com"]:
audit_log_config:
@@ -292,39 +321,39 @@ values:
log_type: DATA_READ
- exempted_members: []
log_type: DATA_WRITE
- project: test-project
+ project: test-test-project
service: storage.googleapis.com
module.project.google_project_iam_binding.authoritative["roles/apigee.serviceAgent"]:
condition: []
- project: test-project
+ project: test-test-project
role: roles/apigee.serviceAgent
module.project.google_project_iam_binding.authoritative["roles/cloudasset.owner"]:
condition: []
members:
- group:organization-admins@example.org
- project: test-project
+ project: test-test-project
role: roles/cloudasset.owner
module.project.google_project_iam_binding.authoritative["roles/cloudsupport.techSupportEditor"]:
condition: []
members:
- group:organization-admins@example.org
- project: test-project
+ project: test-test-project
role: roles/cloudsupport.techSupportEditor
module.project.google_project_iam_binding.authoritative["roles/editor"]:
condition: []
- project: test-project
+ project: test-test-project
role: roles/editor
module.project.google_project_iam_binding.authoritative["roles/iam.securityReviewer"]:
condition: []
members:
- group:organization-admins@example.org
- project: test-project
+ project: test-test-project
role: roles/iam.securityReviewer
module.project.google_project_iam_binding.authoritative["roles/logging.admin"]:
condition: []
members:
- group:organization-admins@example.org
- project: test-project
+ project: test-test-project
role: roles/logging.admin
module.project.google_project_iam_binding.bindings["iam_admin_conditional"]:
condition:
@@ -334,12 +363,12 @@ values:
title: delegated_network_user_one
members:
- group:organization-admins@example.org
- project: test-project
+ project: test-test-project
role: roles/resourcemanager.projectIamAdmin
module.project.google_project_iam_member.bindings["group-owner"]:
condition: []
member: group:organization-admins@example.org
- project: test-project
+ project: test-test-project
role: roles/owner
module.project.google_project_iam_member.bucket-sinks-binding["debug"]:
condition:
@@ -347,23 +376,23 @@ values:
role: roles/logging.bucketWriter
module.project.google_project_iam_member.service_agents["apigee"]:
condition: []
- project: test-project
+ project: test-test-project
role: roles/apigee.serviceAgent
module.project.google_project_iam_member.service_agents["compute-system"]:
condition: []
- project: test-project
+ project: test-test-project
role: roles/compute.serviceAgent
module.project.google_project_iam_member.service_agents["container-engine-robot"]:
condition: []
- project: test-project
+ project: test-test-project
role: roles/container.serviceAgent
module.project.google_project_iam_member.service_agents["gkenode"]:
condition: []
- project: test-project
+ project: test-test-project
role: roles/container.defaultNodeServiceAgent
module.project.google_project_iam_member.service_agents["serverless-robot-prod"]:
condition: []
- project: test-project
+ project: test-test-project
role: roles/run.serviceAgent
module.project.google_project_iam_member.shared_vpc_host_robots["roles/cloudasset.owner:cloudservices"]:
condition: []
@@ -396,55 +425,55 @@ values:
module.project.google_project_service.project_services["apigee.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
- project: test-project
+ project: test-test-project
service: apigee.googleapis.com
timeouts: null
module.project.google_project_service.project_services["bigquery.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
- project: test-project
+ project: test-test-project
service: bigquery.googleapis.com
timeouts: null
module.project.google_project_service.project_services["compute.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
- project: test-project
+ project: test-test-project
service: compute.googleapis.com
timeouts: null
module.project.google_project_service.project_services["container.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
- project: test-project
+ project: test-test-project
service: container.googleapis.com
timeouts: null
module.project.google_project_service.project_services["logging.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
- project: test-project
+ project: test-test-project
service: logging.googleapis.com
timeouts: null
module.project.google_project_service.project_services["run.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
- project: test-project
+ project: test-test-project
service: run.googleapis.com
timeouts: null
module.project.google_project_service.project_services["storage.googleapis.com"]:
disable_dependent_services: false
disable_on_destroy: false
- project: test-project
+ project: test-test-project
service: storage.googleapis.com
timeouts: null
module.project.google_project_service_identity.default["apigee.googleapis.com"]:
- project: test-project
+ project: test-test-project
service: apigee.googleapis.com
timeouts: null
module.project.google_project_service_identity.default["container.googleapis.com"]:
- project: test-project
+ project: test-test-project
service: container.googleapis.com
timeouts: null
module.project.google_project_service_identity.default["run.googleapis.com"]:
- project: test-project
+ project: test-test-project
service: run.googleapis.com
timeouts: null
module.project.google_pubsub_topic_iam_member.pubsub-sinks-binding["notice"]:
@@ -457,12 +486,17 @@ values:
condition: []
role: roles/storage.objectCreator
module.pubsub.google_pubsub_topic.default:
+ effective_labels:
+ goog-terraform-provisioned: 'true'
ingestion_data_source_settings: []
kms_key_name: null
labels: null
message_retention_duration: null
name: pubsub_sink
project: project-id
+ schema_settings: []
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
timeouts: null
counts:
@@ -479,7 +513,7 @@ counts:
google_logging_project_exclusion: 1
google_logging_project_sink: 4
google_org_policy_policy: 7
- google_project: 3
+ google_project: 2
google_project_iam_audit_config: 2
google_project_iam_binding: 7
google_project_iam_member: 14
@@ -491,7 +525,7 @@ counts:
google_storage_bucket_iam_member: 1
google_storage_project_service_account: 1
modules: 8
- resources: 64
+ resources: 63
outputs: {}
diff --git a/tests/modules/project_factory/examples/example.yaml b/tests/modules/project_factory/examples/example.yaml
index 1ddb659de..1eabc1f54 100644
--- a/tests/modules/project_factory/examples/example.yaml
+++ b/tests/modules/project_factory/examples/example.yaml
@@ -12,15 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+values:
values:
module.project-factory.module.automation-buckets["dev-tb-app0-0/state"].google_storage_bucket.bucket[0]:
autoclass: []
cors: []
custom_placement_config: []
default_event_based_hold: null
+ effective_labels:
+ goog-terraform-provisioned: 'true'
enable_object_retention: null
encryption: []
force_destroy: false
+ hierarchical_namespace: []
labels: null
lifecycle_rule: []
location: EU
@@ -30,8 +34,12 @@ values:
requester_pays: null
retention_policy: []
storage_class: STANDARD
+ terraform_labels:
+ goog-terraform-provisioned: 'true'
timeouts: null
uniform_bucket_level_access: true
+ versioning:
+ - enabled: false
? module.project-factory.module.automation-buckets["dev-tb-app0-0/state"].google_storage_bucket_iam_binding.authoritative["roles/storage.objectCreator"]
: bucket: test-pf-dev-tb-app0-0-state
condition: []
@@ -53,6 +61,8 @@ values:
description: Team B app 0 read-only automation sa.
disabled: false
display_name: Service account ro for dev-tb-app0-0.
+ email: test-pf-dev-tb-app0-0-ro@test-pf-teams-iac-0.iam.gserviceaccount.com
+ member: serviceAccount:test-pf-dev-tb-app0-0-ro@test-pf-teams-iac-0.iam.gserviceaccount.com
project: test-pf-teams-iac-0
timeouts: null
module.project-factory.module.automation-service-accounts["dev-tb-app0-0/rw"].google_service_account.service_account[0]:
@@ -61,6 +71,8 @@ values:
description: Team B app 0 read/write automation sa.
disabled: false
display_name: Service account rw for dev-tb-app0-0.
+ email: test-pf-dev-tb-app0-0-rw@test-pf-teams-iac-0.iam.gserviceaccount.com
+ member: serviceAccount:test-pf-dev-tb-app0-0-rw@test-pf-teams-iac-0.iam.gserviceaccount.com
project: test-pf-teams-iac-0
timeouts: null
module.project-factory.module.billing-account[0].google_billing_budget.default["test-100"]:
@@ -102,8 +114,10 @@ values:
type: email
user_labels: null
module.project-factory.module.hierarchy-folder-lvl-1["team-a"].google_folder.folder[0]:
+ deletion_protection: false
display_name: Team A
parent: folders/5678901234
+ tags: null
timeouts: null
module.project-factory.module.hierarchy-folder-lvl-1["team-a"].google_folder_iam_binding.authoritative["roles/viewer"]:
condition: []
@@ -112,22 +126,42 @@ values:
- group:team-a-admins@example.org
role: roles/viewer
module.project-factory.module.hierarchy-folder-lvl-1["team-b"].google_folder.folder[0]:
+ deletion_protection: false
display_name: Team B
parent: folders/5678901234
+ tags: null
timeouts: null
module.project-factory.module.hierarchy-folder-lvl-1["team-c"].google_folder.folder[0]:
+ deletion_protection: false
display_name: Team C
parent: folders/5678901234
+ tags: null
timeouts: null
module.project-factory.module.hierarchy-folder-lvl-2["team-a/app-0"].google_folder.folder[0]:
+ deletion_protection: false
display_name: App 0
+ tags: null
timeouts: null
module.project-factory.module.hierarchy-folder-lvl-2["team-b/app-0"].google_folder.folder[0]:
+ deletion_protection: false
display_name: App 0
+ tags: null
timeouts: null
module.project-factory.module.hierarchy-folder-lvl-2["team-b/app-0"].google_tags_tag_binding.binding["drs-allow-all"]:
tag_value: tagValues/123456
timeouts: null
+ module.project-factory.module.projects-iam["dev-tb-app0-0"].google_project_iam_binding.authoritative["roles/owner"]:
+ condition: []
+ members:
+ - serviceAccount:test-pf-dev-tb-app0-0-rw@test-pf-teams-iac-0.iam.gserviceaccount.com
+ project: test-pf-dev-tb-app0-0
+ role: roles/owner
+ module.project-factory.module.projects-iam["dev-tb-app0-0"].google_project_iam_binding.authoritative["roles/viewer"]:
+ condition: []
+ members:
+ - serviceAccount:test-pf-dev-tb-app0-0-ro@test-pf-teams-iac-0.iam.gserviceaccount.com
+ project: test-pf-dev-tb-app0-0
+ role: roles/viewer
module.project-factory.module.projects["dev-ta-app0-be"].data.google_storage_project_service_account.gcs_sa[0]:
project: test-pf-dev-ta-app0-be
user_project: null
@@ -154,6 +188,7 @@ values:
effective_labels:
app: app-0
environment: test
+ goog-terraform-provisioned: 'true'
team: team-a
labels:
app: app-0
@@ -161,9 +196,11 @@ values:
team: team-a
name: test-pf-dev-ta-app0-be
project_id: test-pf-dev-ta-app0-be
+ tags: null
terraform_labels:
app: app-0
environment: test
+ goog-terraform-provisioned: 'true'
team: team-a
timeouts: null
? module.project-factory.module.projects["dev-ta-app0-be"].google_project_iam_member.service_agents["container-engine-robot"]
@@ -228,25 +265,16 @@ values:
deletion_policy: DELETE
effective_labels:
environment: test
+ goog-terraform-provisioned: 'true'
labels:
environment: test
name: test-pf-dev-tb-app0-0
project_id: test-pf-dev-tb-app0-0
+ tags: null
terraform_labels:
environment: test
+ goog-terraform-provisioned: 'true'
timeouts: null
- module.project-factory.module.projects["dev-tb-app0-0"].google_project_iam_binding.authoritative["roles/owner"]:
- condition: []
- members:
- - serviceAccount:test-pf-dev-tb-app0-0-rw@test-pf-teams-iac-0.iam.gserviceaccount.com
- project: test-pf-dev-tb-app0-0
- role: roles/owner
- module.project-factory.module.projects["dev-tb-app0-0"].google_project_iam_binding.authoritative["roles/viewer"]:
- condition: []
- members:
- - serviceAccount:test-pf-dev-tb-app0-0-ro@test-pf-teams-iac-0.iam.gserviceaccount.com
- project: test-pf-dev-tb-app0-0
- role: roles/viewer
module.project-factory.module.projects["dev-tb-app0-0"].google_project_iam_member.service_agents["serverless-robot-prod"]:
condition: []
project: test-pf-dev-tb-app0-0
@@ -289,14 +317,17 @@ values:
deletion_policy: DELETE
effective_labels:
environment: test
+ goog-terraform-provisioned: 'true'
folder_id: '5678901234'
labels:
environment: test
name: test-pf-teams-iac-0
org_id: null
project_id: test-pf-teams-iac-0
+ tags: null
terraform_labels:
environment: test
+ goog-terraform-provisioned: 'true'
timeouts: null
module.project-factory.module.projects["teams-iac-0"].google_project_iam_member.service_agents["container-engine-robot"]:
condition: []
@@ -346,6 +377,8 @@ values:
description: null
disabled: false
display_name: Backend instances.
+ email: app-0-be@test-pf-dev-ta-app0-be.iam.gserviceaccount.com
+ member: serviceAccount:app-0-be@test-pf-dev-ta-app0-be.iam.gserviceaccount.com
project: test-pf-dev-ta-app0-be
timeouts: null
? module.project-factory.module.service-accounts["dev-ta-app0-be/app-0-fe"].google_project_iam_member.project-roles["test-pf-dev-net-spoke-0-roles/compute.networkUser"]
@@ -366,6 +399,8 @@ values:
description: null
disabled: false
display_name: Frontend instances.
+ email: app-0-fe@test-pf-dev-ta-app0-be.iam.gserviceaccount.com
+ member: serviceAccount:app-0-fe@test-pf-dev-ta-app0-be.iam.gserviceaccount.com
project: test-pf-dev-ta-app0-be
timeouts: null
@@ -388,5 +423,5 @@ counts:
google_storage_bucket_iam_binding: 2
google_storage_project_service_account: 3
google_tags_tag_binding: 1
- modules: 15
+ modules: 16
resources: 56
diff --git a/tools/tfdoc.py b/tools/tfdoc.py
index 04e7db91d..9cbd17d74 100755
--- a/tools/tfdoc.py
+++ b/tools/tfdoc.py
@@ -169,16 +169,19 @@ def _parse(body, enum=VAR_ENUM, re=VAR_RE, template=VAR_TEMPLATE):
item[context].append(data)
-def create_toc(readme):
+def create_toc(readme, skip=['contents']):
'Create a Markdown table of contents a for README.'
doc = marko.parse(readme)
lines = []
headings = [x for x in doc.children if x.get_type() == 'Heading']
+ skip = skip or []
for h in headings[1:]:
title = h.children[0].children
slug = title.lower().strip()
slug = re.sub(r'[^\w\s-]', '', slug)
slug = re.sub(r'[-\s]+', '-', slug)
+ if slug in skip:
+ continue
link = f'- [{title}](#{slug})'
indent = ' ' * (h.level - 2)
lines.append(f'{indent}{link}')
@@ -512,8 +515,9 @@ def render_toc(readme, toc):
@click.option('--replace/--no-replace', default=True)
@click.option('--show-extra/--no-show-extra', default=False)
@click.option('--toc-only', is_flag=True, default=False)
+@click.option('--toc-skip', multiple=True, default=['contents'])
def main(module_path=None, exclude_file=None, files=False, replace=True,
- show_extra=True, toc_only=False):
+ show_extra=True, toc_only=False, toc_skip=['contents']):
'Program entry point.'
if toc_only and module_path.endswith('.md'):
readme_path = module_path
@@ -523,7 +527,7 @@ def main(module_path=None, exclude_file=None, files=False, replace=True,
if not toc_only:
doc = create_tfref(module_path, files, show_extra, exclude_file, readme)
readme = render_tfref(readme, doc.content)
- toc = create_toc(readme)
+ toc = create_toc(readme, toc_skip)
readme = render_toc(readme, toc)
if replace:
try: