diff --git a/fast/stages/0-org-setup/schemas/cicd-workflows.schema.md b/fast/stages/0-org-setup/schemas/cicd-workflows.schema.md
index 2162b4fd9..2b8d78fd2 100644
--- a/fast/stages/0-org-setup/schemas/cicd-workflows.schema.md
+++ b/fast/stages/0-org-setup/schemas/cicd-workflows.schema.md
@@ -27,6 +27,7 @@
- items: *string*
- ⁺**workload_identity**: *object*
*additional properties: false*
+ - ⁺**pool**: *string*
- ⁺**provider**: *string*
- ⁺**iam_principalsets**: *object*
diff --git a/fast/stages/0-org-setup/schemas/defaults.schema.md b/fast/stages/0-org-setup/schemas/defaults.schema.md
index ca59ef456..00eb67e28 100644
--- a/fast/stages/0-org-setup/schemas/defaults.schema.md
+++ b/fast/stages/0-org-setup/schemas/defaults.schema.md
@@ -151,6 +151,8 @@
*additional properties: string*
- **vpc_sc_perimeters**: *object*
*additional properties: string*
+ - **workload_identity_pools**: *object*
+
*additional properties: string*
- **workload_identity_providers**: *object*
*additional properties: string*
- **output_files**: *object*
diff --git a/fast/stages/0-org-setup/schemas/project.schema.json b/fast/stages/0-org-setup/schemas/project.schema.json
index da4e5a3cf..cbb185f8e 100644
--- a/fast/stages/0-org-setup/schemas/project.schema.json
+++ b/fast/stages/0-org-setup/schemas/project.schema.json
@@ -353,6 +353,9 @@
"name": {
"type": "string"
},
+ "descriptive_name": {
+ "type": "string"
+ },
"org_policies": {
"type": "object",
"additionalProperties": false,
diff --git a/fast/stages/0-org-setup/schemas/project.schema.md b/fast/stages/0-org-setup/schemas/project.schema.md
index 1d91c0981..7717152a4 100644
--- a/fast/stages/0-org-setup/schemas/project.schema.md
+++ b/fast/stages/0-org-setup/schemas/project.schema.md
@@ -111,6 +111,7 @@
- **metric_scopes**: *array*
- items: *string*
- **name**: *string*
+- **descriptive_name**: *string*
- **org_policies**: *object*
*additional properties: false*
- **`^[a-z]+\.`**: *object*
diff --git a/fast/stages/2-networking/schemas/project.schema.json b/fast/stages/2-networking/schemas/project.schema.json
index da4e5a3cf..cbb185f8e 100644
--- a/fast/stages/2-networking/schemas/project.schema.json
+++ b/fast/stages/2-networking/schemas/project.schema.json
@@ -353,6 +353,9 @@
"name": {
"type": "string"
},
+ "descriptive_name": {
+ "type": "string"
+ },
"org_policies": {
"type": "object",
"additionalProperties": false,
diff --git a/fast/stages/2-networking/schemas/project.schema.md b/fast/stages/2-networking/schemas/project.schema.md
index 1d91c0981..7717152a4 100644
--- a/fast/stages/2-networking/schemas/project.schema.md
+++ b/fast/stages/2-networking/schemas/project.schema.md
@@ -111,6 +111,7 @@
- **metric_scopes**: *array*
- items: *string*
- **name**: *string*
+- **descriptive_name**: *string*
- **org_policies**: *object*
*additional properties: false*
- **`^[a-z]+\.`**: *object*
diff --git a/fast/stages/2-project-factory/schemas/project.schema.json b/fast/stages/2-project-factory/schemas/project.schema.json
index da4e5a3cf..cbb185f8e 100644
--- a/fast/stages/2-project-factory/schemas/project.schema.json
+++ b/fast/stages/2-project-factory/schemas/project.schema.json
@@ -353,6 +353,9 @@
"name": {
"type": "string"
},
+ "descriptive_name": {
+ "type": "string"
+ },
"org_policies": {
"type": "object",
"additionalProperties": false,
diff --git a/fast/stages/2-project-factory/schemas/project.schema.md b/fast/stages/2-project-factory/schemas/project.schema.md
index 1d91c0981..7717152a4 100644
--- a/fast/stages/2-project-factory/schemas/project.schema.md
+++ b/fast/stages/2-project-factory/schemas/project.schema.md
@@ -111,6 +111,7 @@
- **metric_scopes**: *array*
- items: *string*
- **name**: *string*
+- **descriptive_name**: *string*
- **org_policies**: *object*
*additional properties: false*
- **`^[a-z]+\.`**: *object*
diff --git a/fast/stages/2-security/schemas/project.schema.json b/fast/stages/2-security/schemas/project.schema.json
index da4e5a3cf..cbb185f8e 100644
--- a/fast/stages/2-security/schemas/project.schema.json
+++ b/fast/stages/2-security/schemas/project.schema.json
@@ -353,6 +353,9 @@
"name": {
"type": "string"
},
+ "descriptive_name": {
+ "type": "string"
+ },
"org_policies": {
"type": "object",
"additionalProperties": false,
diff --git a/fast/stages/2-security/schemas/project.schema.md b/fast/stages/2-security/schemas/project.schema.md
index 1d91c0981..7717152a4 100644
--- a/fast/stages/2-security/schemas/project.schema.md
+++ b/fast/stages/2-security/schemas/project.schema.md
@@ -111,6 +111,7 @@
- **metric_scopes**: *array*
- items: *string*
- **name**: *string*
+- **descriptive_name**: *string*
- **org_policies**: *object*
*additional properties: false*
- **`^[a-z]+\.`**: *object*
diff --git a/modules/project-factory/README.md b/modules/project-factory/README.md
index 3982139a4..f1e209b98 100644
--- a/modules/project-factory/README.md
+++ b/modules/project-factory/README.md
@@ -809,7 +809,7 @@ compute.disableSerialPortAccess:
| [data_overrides](variables.tf#L123) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} |
| [folders](variables-folders.tf#L17) | Folders data merged with factory data. | map(object({…})) | | {} |
| [notification_channels](variables-billing.tf#L17) | Notification channels used by budget alerts. | map(object({…})) | | {} |
-| [projects](variables-projects.tf#L17) | Projects data merged with factory data. | map(object({…})) | | {} |
+| [projects](variables-projects.tf#L17) | Projects data merged with factory data. | map(object({…})) | | {} |
## Outputs
@@ -856,7 +856,7 @@ module "project-factory" {
projects = "data/projects"
}
}
-# tftest modules=4 resources=24 files=test-0,test-1,test-2
+# tftest modules=4 resources=24 files=test-0,test-1,test-2 inventory=test-1.yaml
```
```yaml
@@ -870,6 +870,7 @@ services:
```yaml
parent: folders/1234567890
+descriptive_name: "Test Project 1"
services:
- iam.googleapis.com
- contactcenteraiplatform.googleapis.com
diff --git a/modules/project-factory/projects-defaults.tf b/modules/project-factory/projects-defaults.tf
index 1c395e8ee..9ed70f8c7 100644
--- a/modules/project-factory/projects-defaults.tf
+++ b/modules/project-factory/projects-defaults.tf
@@ -68,9 +68,10 @@ locals {
try(v.metric_scopes, null),
local.data_defaults.defaults.metric_scopes
)
- name = lookup(v, "name", basename(k)) # type: string
- org_policies = try(v.org_policies, {}) # type: map(object({...}))
- parent = try( # type: string, nullable
+ descriptive_name = lookup(v, "descriptive_name", null)
+ name = lookup(v, "name", basename(k)) # type: string
+ org_policies = try(v.org_policies, {}) # type: map(object({...}))
+ parent = try( # type: string, nullable
coalesce(
local.data_defaults.overrides.parent,
try(v.parent, null),
diff --git a/modules/project-factory/projects.tf b/modules/project-factory/projects.tf
index d2e5abe46..4dfeb0413 100644
--- a/modules/project-factory/projects.tf
+++ b/modules/project-factory/projects.tf
@@ -86,6 +86,7 @@ module "projects" {
billing_account = each.value.billing_account
deletion_policy = each.value.deletion_policy
name = each.value.name
+ descriptive_name = each.value.descriptive_name
parent = each.value.parent
prefix = each.value.prefix
project_reuse = each.value.project_reuse
@@ -100,7 +101,6 @@ module "projects" {
folder_ids = local.ctx_folder_ids
})
default_service_account = try(each.value.default_service_account, "keep")
- descriptive_name = try(each.value.descriptive_name, null)
factories_config = {
custom_roles = try(each.value.factories_config.custom_roles, null)
org_policies = try(each.value.factories_config.org_policies, null)
diff --git a/modules/project-factory/schemas/project.schema.json b/modules/project-factory/schemas/project.schema.json
index da4e5a3cf..cbb185f8e 100644
--- a/modules/project-factory/schemas/project.schema.json
+++ b/modules/project-factory/schemas/project.schema.json
@@ -353,6 +353,9 @@
"name": {
"type": "string"
},
+ "descriptive_name": {
+ "type": "string"
+ },
"org_policies": {
"type": "object",
"additionalProperties": false,
diff --git a/modules/project-factory/schemas/project.schema.md b/modules/project-factory/schemas/project.schema.md
index 1d91c0981..7717152a4 100644
--- a/modules/project-factory/schemas/project.schema.md
+++ b/modules/project-factory/schemas/project.schema.md
@@ -111,6 +111,7 @@
- **metric_scopes**: *array*
- items: *string*
- **name**: *string*
+- **descriptive_name**: *string*
- **org_policies**: *object*
*additional properties: false*
- **`^[a-z]+\.`**: *object*
diff --git a/modules/project-factory/variables-projects.tf b/modules/project-factory/variables-projects.tf
index 2b46cf23e..3def4b75a 100644
--- a/modules/project-factory/variables-projects.tf
+++ b/modules/project-factory/variables-projects.tf
@@ -308,7 +308,8 @@ variable "projects" {
requester_email_recipients = optional(list(string))
}))
})), {})
- name = optional(string)
+ name = optional(string)
+ descriptive_name = optional(string)
org_policies = optional(map(object({
inherit_from_parent = optional(bool) # for list policies only.
reset = optional(bool)
diff --git a/modules/project/README.md b/modules/project/README.md
index d919d4e38..9b56f81fe 100644
--- a/modules/project/README.md
+++ b/modules/project/README.md
@@ -2117,7 +2117,7 @@ module "project" {
| [default_network_tier](variables.tf#L118) | Default compute network tier for the project. | string | | null |
| [default_service_account](variables.tf#L124) | Project default service account setting: can be one of `delete`, `deprivilege`, `disable`, or `keep`. | string | | "keep" |
| [deletion_policy](variables.tf#L137) | Deletion policy setting for this project. | string | | "DELETE" |
-| [descriptive_name](variables.tf#L148) | Name of the project name. Used for project name instead of `name` variable. | string | | null |
+| [descriptive_name](variables.tf#L148) | Descriptive project name. Set when name differs from project id. | string | | null |
| [factories_config](variables.tf#L154) | 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({…})) | | {} |
diff --git a/modules/project/variables.tf b/modules/project/variables.tf
index 68184405c..e878675e6 100644
--- a/modules/project/variables.tf
+++ b/modules/project/variables.tf
@@ -146,7 +146,7 @@ variable "deletion_policy" {
}
variable "descriptive_name" {
- description = "Name of the project name. Used for project name instead of `name` variable."
+ description = "Descriptive project name. Set when name differs from project id."
type = string
default = null
}
diff --git a/tests/modules/project_factory/examples/test-1.yaml b/tests/modules/project_factory/examples/test-1.yaml
new file mode 100644
index 000000000..4e8ab66bc
--- /dev/null
+++ b/tests/modules/project_factory/examples/test-1.yaml
@@ -0,0 +1,17 @@
+# Copyright 2025 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+values:
+ module.project-factory.module.projects["test-1"].google_project.project[0]:
+ name: Test Project 1