diff --git a/modules/billing-account/README.md b/modules/billing-account/README.md
index b3950fa15..5f43ef3d4 100644
--- a/modules/billing-account/README.md
+++ b/modules/billing-account/README.md
@@ -277,17 +277,17 @@ update_rules:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [id](variables.tf#L147) | Billing account id. | string | ✓ | |
+| [id](variables.tf#L148) | Billing account id. | string | ✓ | |
| [budget_notification_channels](variables.tf#L17) | Notification channels used by budget alerts. | map(object({…})) | | {} |
| [budgets](variables.tf#L47) | Billing budgets. Notification channels are either keys in corresponding variable, or external ids. | map(object({…})) | | {} |
-| [context](variables.tf#L122) | Context-specific interpolations. | object({…}) | | {} |
-| [factories_config](variables.tf#L138) | Path to folder containing budget alerts data files. | object({…}) | | {} |
+| [context](variables.tf#L122) | Context-specific interpolations. | object({…}) | | {} |
+| [factories_config](variables.tf#L139) | Path to folder containing budget alerts data files. | object({…}) | | {} |
| [iam](variables-iam.tf#L17) | 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#L54) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | map(list(string)) | | {} |
-| [logging_sinks](variables.tf#L152) | Logging sinks to create for the billing account. | map(object({…})) | | {} |
-| [projects](variables.tf#L185) | Projects associated with this billing account. | list(string) | | [] |
+| [logging_sinks](variables.tf#L153) | Logging sinks to create for the billing account. | map(object({…})) | | {} |
+| [projects](variables.tf#L186) | Projects associated with this billing account. | list(string) | | [] |
## Outputs
diff --git a/modules/billing-account/budgets.tf b/modules/billing-account/budgets.tf
index aaa38ae1a..9fab983c4 100644
--- a/modules/billing-account/budgets.tf
+++ b/modules/billing-account/budgets.tf
@@ -98,8 +98,9 @@ resource "google_billing_budget" "default" {
}
projects = concat(
[
- for v in each.value.filter.projects :
- lookup(local.ctx.project_ids, v, v)
+ for v in each.value.filter.projects : try(
+ try("projects/${local.ctx.project_numbers[v]}", v), v
+ )
],
lookup(local.ctx.project_sets, "$project_sets:${each.key}", [])
)
diff --git a/modules/billing-account/variables.tf b/modules/billing-account/variables.tf
index 061767540..6da7c29b6 100644
--- a/modules/billing-account/variables.tf
+++ b/modules/billing-account/variables.tf
@@ -130,6 +130,7 @@ variable "context" {
project_ids = optional(map(string), {})
project_sets = optional(map(list(string)), {})
storage_buckets = optional(map(string), {})
+ project_numbers = optional(map(string), {})
})
default = {}
nullable = false
diff --git a/modules/project-factory/README.md b/modules/project-factory/README.md
index 685cba01a..56c47f0f0 100644
--- a/modules/project-factory/README.md
+++ b/modules/project-factory/README.md
@@ -802,11 +802,11 @@ compute.disableSerialPortAccess:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [factories_config](variables.tf#L161) | Path to folder with YAML resource description data files. | object({…}) | ✓ | |
-| [context](variables.tf#L17) | Context-specific interpolations. | object({…}) | | {} |
-| [data_defaults](variables.tf#L38) | Optional default values used when corresponding project or folder data from files are missing. | object({…}) | | {} |
-| [data_merges](variables.tf#L103) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} |
-| [data_overrides](variables.tf#L122) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} |
+| [factories_config](variables.tf#L162) | Path to folder with YAML resource description data files. | object({…}) | ✓ | |
+| [context](variables.tf#L17) | Context-specific interpolations. | object({…}) | | {} |
+| [data_defaults](variables.tf#L39) | Optional default values used when corresponding project or folder data from files are missing. | object({…}) | | {} |
+| [data_merges](variables.tf#L104) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} |
+| [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({…})) | | {} |
diff --git a/modules/project-factory/budgets.tf b/modules/project-factory/budgets.tf
index c7466a2db..f1648ab12 100644
--- a/modules/project-factory/budgets.tf
+++ b/modules/project-factory/budgets.tf
@@ -50,6 +50,7 @@ module "billing-budgets" {
for v in local.budget_project_sets :
v.budget => "projects/${local.outputs_projects[v.project].number}"...
}
+ project_numbers = local.ctx_project_numbers
})
factories_config = {
budgets_data_path = var.factories_config.budgets.data
diff --git a/modules/project-factory/projects.tf b/modules/project-factory/projects.tf
index 7a06a2102..d2e5abe46 100644
--- a/modules/project-factory/projects.tf
+++ b/modules/project-factory/projects.tf
@@ -48,7 +48,7 @@ locals {
trimsuffix(f, ".yaml") => yamldecode(file("${local._templates_path}/${f}"))
}
ctx_project_ids = merge(local.ctx.project_ids, local.project_ids)
- ctx_project_numbers = merge(local.ctx.project_ids, local.project_numbers)
+ ctx_project_numbers = merge(local.ctx.project_numbers, local.project_numbers)
project_ids = {
for k, v in module.projects : k => v.project_id
}
diff --git a/modules/project-factory/variables.tf b/modules/project-factory/variables.tf
index 6ec7ba406..64b471889 100644
--- a/modules/project-factory/variables.tf
+++ b/modules/project-factory/variables.tf
@@ -27,6 +27,7 @@ variable "context" {
log_buckets = optional(map(string), {})
notification_channels = optional(map(string), {})
project_ids = optional(map(string), {})
+ project_numbers = optional(map(string), {})
tag_values = optional(map(string), {})
vpc_host_projects = optional(map(string), {})
vpc_sc_perimeters = optional(map(string), {})
diff --git a/tests/modules/billing_account/context.tfvars b/tests/modules/billing_account/context.tfvars
index 4749ed4f8..4df134323 100644
--- a/tests/modules/billing_account/context.tfvars
+++ b/tests/modules/billing_account/context.tfvars
@@ -9,7 +9,7 @@ budgets = {
period = {
calendar = "MONTH"
}
- projects = ["$project_ids:foo"]
+ projects = ["$project_numbers:foo"]
resource_ancestors = ["$folder_ids:bar"]
}
threshold_rules = [
@@ -48,6 +48,9 @@ context = {
project_ids = {
foo = "test-prj-foo"
}
+ project_numbers = {
+ foo = 1234567890
+ }
}
iam = {
"$custom_roles:myrole_one" = [
diff --git a/tests/modules/billing_account/context.yaml b/tests/modules/billing_account/context.yaml
index a4626bccb..965b638c6 100644
--- a/tests/modules/billing_account/context.yaml
+++ b/tests/modules/billing_account/context.yaml
@@ -73,7 +73,7 @@ values:
credit_types_treatment: INCLUDE_ALL_CREDITS
custom_period: []
projects:
- - test-prj-foo
+ - projects/1234567890
resource_ancestors:
- folders/1234567890
display_name: 100 dollars in current spend