diff --git a/modules/project-factory/README.md b/modules/project-factory/README.md index d3f6de13b..38fc12848 100644 --- a/modules/project-factory/README.md +++ b/modules/project-factory/README.md @@ -484,10 +484,10 @@ service_accounts: | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [factories_config](variables.tf#L120) | Path to folder with YAML resource description data files. | object({…}) | ✓ | | +| [factories_config](variables.tf#L121) | Path to folder with YAML resource description data files. | object({…}) | ✓ | | | [data_defaults](variables.tf#L17) | Optional default values used when corresponding project data from files are missing. | object({…}) | | {} | | [data_merges](variables.tf#L64) | 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#L83) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | +| [data_overrides](variables.tf#L83) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | ## Outputs diff --git a/modules/project-factory/factory-projects-object.tf b/modules/project-factory/factory-projects-object.tf index 582e8256c..b9cc8c60a 100644 --- a/modules/project-factory/factory-projects-object.tf +++ b/modules/project-factory/factory-projects-object.tf @@ -78,9 +78,10 @@ locals { }, try(local._projects_config.data_defaults, {}) ) + # data_overrides default to null's, to mark that they should not override data_overrides = merge({ billing_account = null - contacts = {} + contacts = null factories_config = merge({ custom_roles = null observability = null @@ -95,27 +96,25 @@ locals { ) parent = null prefix = null - service_encryption_key_ids = {} + service_encryption_key_ids = null storage_location = null - tag_bindings = {} - services = [] - service_accounts = {} - vpc_sc = merge({ - perimeter_name = null - perimeter_bridges = [] - is_dry_run = false - }, try(local._projects_config.data_overrides.vpc_sc, { - perimeter_name = null - perimeter_bridges = [] - is_dry_run = false - }) - ) - logging_data_access = {} + tag_bindings = null + services = null + service_accounts = null + vpc_sc = try(local._projects_config.data_overrides.vpc_sc, null) + logging_data_access = null }, try(local._projects_config.data_overrides, {}) ) } _projects_output = { + # Semantics of the merges are: + # * if data_overrides. is not null, use this value + # * if _projects_inputs. is not null, use this value + # * use data_default value, which if not set, will provide "empty" type + # This logic is easily implemented using coalesce, even on maps and list and allows to + # set data_overrides. to "", [] or {} to ensure, that empty value is always passed, or do + # the same in _projects_input to prevent falling back to default value for k, v in local._projects_input : k => merge(v, { billing_account = try(coalesce( # type: string local.__projects_config.data_overrides.billing_account, diff --git a/modules/project-factory/variables.tf b/modules/project-factory/variables.tf index b5bb14812..4f9bb18db 100644 --- a/modules/project-factory/variables.tf +++ b/modules/project-factory/variables.tf @@ -83,6 +83,7 @@ variable "data_merges" { variable "data_overrides" { description = "Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`." type = object({ + # data overrides default to null to mark that they should not override billing_account = optional(string) contacts = optional(map(list(string))) factories_config = optional(object({ @@ -111,7 +112,7 @@ variable "data_overrides" { ADMIN_READ = optional(object({ exempted_members = optional(list(string)) })), DATA_READ = optional(object({ exempted_members = optional(list(string)) })), DATA_WRITE = optional(object({ exempted_members = optional(list(string)) })) - })), {}) + }))) }) nullable = false default = {}