diff --git a/fast/stages/0-org-setup/README.md b/fast/stages/0-org-setup/README.md index 7402d7b4f..4eea4a287 100644 --- a/fast/stages/0-org-setup/README.md +++ b/fast/stages/0-org-setup/README.md @@ -96,9 +96,6 @@ The standard datasets use the `gcp-organization-admins` alias to assign administ global: # gcloud beta billing accounts list billing_account: 123456-123456-123456 - locations: - bigquery: europe-west1 - logging: europe-west1 organization: # gcloud organizations list domain: example.org @@ -108,11 +105,16 @@ projects: defaults: # define a unique prefix with a maximum of 9 characters prefix: foo-1 - storage_location: europe-west1 + locations: + bigquery: $locations:primary + logging: $locations:primary + storage: $locations:primary context: iam_principals: # make sure the user running apply is a member of this group gcp-organization-admins: group:fabric-fast-owners@example.com + locations: + primary: europe-west1 ``` A more detailed example containing a few other attributes that can be set in the file is in a [later section](#defaults-configuration) in this document. @@ -660,7 +662,6 @@ Define values for the `var.environments` variable in a tfvars file. | name | description | sensitive | |---|---|:---:| | [iam_principals](outputs.tf#L17) | IAM principals. | | -| [locations](outputs.tf#L22) | Default locations. | | -| [projects](outputs.tf#L27) | Attributes for managed projects. | | -| [tfvars](outputs.tf#L32) | Stage tfvars. | ✓ | +| [projects](outputs.tf#L22) | Attributes for managed projects. | | +| [tfvars](outputs.tf#L27) | Stage tfvars. | ✓ | diff --git a/fast/stages/0-org-setup/data/defaults.yaml b/fast/stages/0-org-setup/data/defaults.yaml index 6512f758a..9c8122b87 100644 --- a/fast/stages/0-org-setup/data/defaults.yaml +++ b/fast/stages/0-org-setup/data/defaults.yaml @@ -17,9 +17,6 @@ global: # use `gcloud beta billing accounts list` to populate billing_account: ABCDEF-0123456-ABCDEF - locations: - bigquery: europe-west1 - logging: europe-west1 organization: # use `gcloud organizations list`` to populate domain: fast-test-00.example.com @@ -29,14 +26,18 @@ projects: defaults: # prefix must be unique and less than 9 characters prefix: test00 - storage_location: europe-west1 - bigquery_location: europe-west1 + locations: + bigquery: $locations:primary + logging: $locations:primary + storage: $locations:primary overrides: {} context: # you can populate context variables here for use in YAML replacements iam_principals: # this is the default group used in boostrap, initial user must be a member gcp-organization-admins: group:gcp-organization-admins@example.com + locations: + primary: europe-west1 output_files: # local path is optional but recommended when starting local_path: ~/fast-config/fast-test-00 diff --git a/fast/stages/0-org-setup/data/organization/.config.yaml b/fast/stages/0-org-setup/data/organization/.config.yaml index 5b522e08f..6ce8bb490 100644 --- a/fast/stages/0-org-setup/data/organization/.config.yaml +++ b/fast/stages/0-org-setup/data/organization/.config.yaml @@ -94,7 +94,7 @@ iam_by_principals: - roles/cloudasset.viewer logging: # disable_default_log_sink: false - storage_location: $locations:default + storage_location: $locations:primary sinks: audit-logs: # description: foo diff --git a/fast/stages/0-org-setup/data/projects/core/billing-0.yaml b/fast/stages/0-org-setup/data/projects/core/billing-0.yaml index fc918affc..78ed0b56e 100644 --- a/fast/stages/0-org-setup/data/projects/core/billing-0.yaml +++ b/fast/stages/0-org-setup/data/projects/core/billing-0.yaml @@ -27,4 +27,3 @@ services: datasets: billing_export: friendly_name: Billing export - location: $locations:bigquery diff --git a/fast/stages/0-org-setup/main.tf b/fast/stages/0-org-setup/main.tf index 04015d1a2..f5ed6c9d3 100644 --- a/fast/stages/0-org-setup/main.tf +++ b/fast/stages/0-org-setup/main.tf @@ -18,23 +18,19 @@ locals { paths = { for k, v in var.factories_config : k => try(pathexpand(v), null) } + _ctx = { + for k, v in var.context : k => merge( + v, + try(local._defaults.context[k], {}) + ) + } # fail if we have no valid defaults _defaults = yamldecode(file(local.paths.defaults)) - ctx = merge(var.context, { - iam_principals = local.iam_principals - locations = { - for k, v in local.defaults.locations : - k => v if k != "pubsub" - } + ctx = merge(local._ctx, { + iam_principals = merge(local.iam_principals, local._ctx.iam_principals) }) defaults = { billing_account = try(local._defaults.global.billing_account, null) - locations = merge({ - bigquery = "eu" - logging = "global" - pubsub = [] - storage = "eu" - }, try(local._defaults.global.locations, {})) organization = ( try(local._defaults.global.organization.id, null) == null ? null @@ -85,12 +81,5 @@ resource "terraform_data" "precondition" { ) error_message = "Prefix must be set in project defaults or overrides." } - precondition { - condition = ( - try(local.project_defaults.defaults.storage_location, null) != null || - try(local.project_defaults.overrides.storage_location, null) != null - ) - error_message = "Storage location must be set in project defaults or overrides." - } } } diff --git a/fast/stages/0-org-setup/organization.tf b/fast/stages/0-org-setup/organization.tf index 79b09ae62..582f67b21 100644 --- a/fast/stages/0-org-setup/organization.tf +++ b/fast/stages/0-org-setup/organization.tf @@ -79,9 +79,7 @@ module "organization" { id = local.organization_id } } - locations = { - default = local.defaults.locations.logging - } + locations = local.ctx.locations } factories_config = { org_policy_custom_constraints = "${local.paths.organization}/custom-constraints" diff --git a/fast/stages/0-org-setup/output-files.tf b/fast/stages/0-org-setup/output-files.tf index 68f542b1b..c3d9f1ba5 100644 --- a/fast/stages/0-org-setup/output-files.tf +++ b/fast/stages/0-org-setup/output-files.tf @@ -43,8 +43,7 @@ locals { billing_account = { id = local.defaults.billing_account } - groups = local.ctx.iam_principals - locations = local.defaults.locations + groups = local.ctx.iam_principals organization = { customer_id = try(local.defaults.organization.customer_id, null) domain = local.organization.domain diff --git a/fast/stages/0-org-setup/outputs.tf b/fast/stages/0-org-setup/outputs.tf index 4b3b5ca12..d4a36a32a 100644 --- a/fast/stages/0-org-setup/outputs.tf +++ b/fast/stages/0-org-setup/outputs.tf @@ -19,11 +19,6 @@ output "iam_principals" { value = local.iam_principals } -output "locations" { - description = "Default locations." - value = local.defaults.locations -} - output "projects" { description = "Attributes for managed projects." value = module.factory.projects diff --git a/fast/stages/0-org-setup/schemas/defaults.schema.json b/fast/stages/0-org-setup/schemas/defaults.schema.json index 98d662589..9720eb96b 100644 --- a/fast/stages/0-org-setup/schemas/defaults.schema.json +++ b/fast/stages/0-org-setup/schemas/defaults.schema.json @@ -11,31 +11,6 @@ "billing_account": { "type": "string" }, - "locations": { - "type": "object", - "additionalProperties": false, - "properties": { - "bigquery": { - "type": "string", - "default": "eu" - }, - "logging": { - "type": "string", - "default": "global" - }, - "pubsub": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - }, - "storage": { - "type": "string", - "default": "eu" - } - } - }, "organization": { "type": "object", "additionalProperties": false, @@ -114,6 +89,21 @@ } } }, + "locations": { + "type": "object", + "additionalProperties": false, + "properties": { + "bigquery": { + "type": "string" + }, + "logging": { + "type": "string" + }, + "storage": { + "type": "string" + } + } + }, "logging_data_access": { "type": "object", "default": {}, @@ -281,9 +271,6 @@ "host_project" ] }, - "storage_location": { - "type": "string" - }, "tag_bindings": { "type": "object", "default": {}, @@ -352,9 +339,6 @@ "required": [ "perimeter_name" ] - }, - "bigquery_location": { - "type": "string" } } }, @@ -395,6 +379,21 @@ "ABANDON" ] }, + "locations": { + "type": "object", + "additionalProperties": false, + "properties": { + "bigquery": { + "type": "string" + }, + "logging": { + "type": "string" + }, + "storage": { + "type": "string" + } + } + }, "logging_data_access": { "type": "object", "default": {}, @@ -456,9 +455,6 @@ } } }, - "storage_location": { - "type": "string" - }, "tag_bindings": { "type": "object", "default": {}, @@ -527,9 +523,6 @@ "required": [ "perimeter_name" ] - }, - "bigquery_location": { - "type": "string" } } } @@ -539,11 +532,77 @@ "type": "object", "additionalProperties": false, "properties": { + "custom_roles": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "folder_ids": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "kms_keys": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, "iam_principals": { "type": "object", "additionalProperties": { "type": "string" } + }, + "locations": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "notification_channels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "project_ids": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "service_account_ids": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "tag_keys": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "tag_values": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "vpc_host_projects": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "vpc_sc_perimeters": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } }, @@ -694,4 +753,4 @@ } } } -} +} \ No newline at end of file diff --git a/fast/stages/2-project-factory/README.md b/fast/stages/2-project-factory/README.md index 8bab44a80..f1170471a 100644 --- a/fast/stages/2-project-factory/README.md +++ b/fast/stages/2-project-factory/README.md @@ -480,25 +480,24 @@ Pattern-based files make specific assumptions: |---|---|:---:|:---:|:---:|:---:| | [automation](variables-fast.tf#L17) | Automation resources created by the bootstrap stage. | object({…}) | ✓ | | 0-org-setup | | [billing_account](variables-fast.tf#L26) | Billing account id. | object({…}) | ✓ | | 0-org-setup | -| [prefix](variables-fast.tf#L92) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-org-setup | +| [prefix](variables-fast.tf#L82) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | ✓ | | 0-org-setup | | [context](variables.tf#L17) | Context-specific interpolations. | object({…}) | | {} | | | [custom_roles](variables-fast.tf#L34) | Custom roles defined at the org level, in key => id format. | map(string) | | {} | 0-org-setup | -| [data_defaults](variables-projects.tf#L17) | Optional default values used when corresponding project or folder data from files are missing. | object({…}) | | {} | | -| [data_merges](variables-projects.tf#L89) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} | | -| [data_overrides](variables-projects.tf#L108) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | | +| [data_defaults](variables-projects.tf#L17) | Optional default values used when corresponding project or folder data from files are missing. | object({…}) | | {} | | +| [data_merges](variables-projects.tf#L93) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} | | +| [data_overrides](variables-projects.tf#L112) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | | | [factories_config](variables.tf#L36) | Path to folder with YAML resource description data files. | object({…}) | | {} | | | [folder_ids](variables-fast.tf#L42) | Folders created in the bootstrap stage. | map(string) | | {} | 0-org-setup | | [host_project_ids](variables-fast.tf#L58) | Host project for the shared VPC. | map(string) | | {} | 2-networking | | [iam_principals](variables-fast.tf#L50) | IAM-format principals. | map(string) | | {} | 0-org-setup | | [kms_keys](variables-fast.tf#L66) | KMS key ids. | map(string) | | {} | 2-security | -| [locations](variables-fast.tf#L74) | Optional locations for GCS, BigQuery, and logging buckets created here. | object({…}) | | {} | 0-org-setup | -| [perimeters](variables-fast.tf#L84) | Optional VPC-SC perimeter ids. | map(string) | | {} | 1-vpcsc | -| [project_ids](variables-fast.tf#L102) | Projects created in the bootstrap stage. | map(string) | | {} | 0-org-setup | -| [service_accounts](variables-fast.tf#L110) | Service accounts created in the bootstrap stage. | map(string) | | {} | 0-org-setup | +| [perimeters](variables-fast.tf#L74) | Optional VPC-SC perimeter ids. | map(string) | | {} | 1-vpcsc | +| [project_ids](variables-fast.tf#L92) | Projects created in the bootstrap stage. | map(string) | | {} | 0-org-setup | +| [service_accounts](variables-fast.tf#L100) | Service accounts created in the bootstrap stage. | map(string) | | {} | 0-org-setup | | [stage_name](variables.tf#L57) | FAST stage name. Used to separate output files across different factories. | string | | "2-project-factory" | | -| [subnet_self_links](variables-fast.tf#L118) | Shared VPC subnet IDs. | map(map(string)) | | {} | 2-networking | -| [tag_values](variables-fast.tf#L126) | FAST-managed resource manager tag values. | map(string) | | {} | 0-org-setup | -| [universe](variables-fast.tf#L134) | GCP universe where to deploy projects. The prefix will be prepended to the project id. | object({…}) | | null | 0-org-setup | +| [subnet_self_links](variables-fast.tf#L108) | Shared VPC subnet IDs. | map(map(string)) | | {} | 2-networking | +| [tag_values](variables-fast.tf#L116) | FAST-managed resource manager tag values. | map(string) | | {} | 0-org-setup | +| [universe](variables-fast.tf#L124) | GCP universe where to deploy projects. The prefix will be prepended to the project id. | object({…}) | | null | 0-org-setup | ## Outputs diff --git a/fast/stages/2-project-factory/data/defaults.yaml b/fast/stages/2-project-factory/data/defaults.yaml index 542f75161..9a77eb222 100644 --- a/fast/stages/2-project-factory/data/defaults.yaml +++ b/fast/stages/2-project-factory/data/defaults.yaml @@ -17,8 +17,9 @@ # environment-specific project defaults, merges and overrides can be defined here projects: - # defaults: - # storage_location: europe-west8 + defaults: + locations: + storage: $locations:primary merges: services: - logging.googleapis.com @@ -28,6 +29,8 @@ projects: # environment-specific static contexts can be defined here -# context: +context: # iam_principals: -# foo: group:foo@example.com \ No newline at end of file +# foo: group:foo@example.com + locations: + primary: europe-west1 \ No newline at end of file diff --git a/fast/stages/2-project-factory/main.tf b/fast/stages/2-project-factory/main.tf index e1f7eb18d..947298f85 100644 --- a/fast/stages/2-project-factory/main.tf +++ b/fast/stages/2-project-factory/main.tf @@ -17,7 +17,9 @@ # tfdoc:file:description Project factory. locals { - context = merge(var.context, lookup(local.defaults, "context", {})) + context = { + for k, v in var.context : k => merge(v, try(local.defaults.context[k], {})) + } defaults = yamldecode(file(pathexpand(var.factories_config.defaults))) fast_defaults = { billing_account = coalesce( @@ -27,9 +29,6 @@ locals { prefix = coalesce( var.data_defaults.prefix, var.prefix ) - storage_location = coalesce( - var.data_defaults.storage_location, var.locations.storage - ) } project_defaults = { defaults = { @@ -83,7 +82,7 @@ module "factory" { local.context.iam_principals ) kms_keys = merge(var.kms_keys, local.context.kms_keys) - locations = merge(var.locations, local.context.locations) + locations = local.context.locations notification_channels = local.context.notification_channels project_ids = merge( var.project_ids, var.host_project_ids, local.context.project_ids diff --git a/fast/stages/2-project-factory/schemas/defaults.schema.json b/fast/stages/2-project-factory/schemas/defaults.schema.json index 482ac4c0a..29b4ab2d8 100644 --- a/fast/stages/2-project-factory/schemas/defaults.schema.json +++ b/fast/stages/2-project-factory/schemas/defaults.schema.json @@ -58,6 +58,21 @@ } } }, + "locations": { + "type": "object", + "additionalProperties": false, + "properties": { + "bigquery": { + "type": "string" + }, + "logging": { + "type": "string" + }, + "storage": { + "type": "string" + } + } + }, "logging_data_access": { "type": "object", "default": {}, @@ -244,9 +259,6 @@ "host_project" ] }, - "storage_location": { - "type": "string" - }, "tag_bindings": { "type": "object", "default": {}, @@ -404,6 +416,21 @@ "ABANDON" ] }, + "locations": { + "type": "object", + "additionalProperties": false, + "properties": { + "bigquery": { + "type": "string" + }, + "logging": { + "type": "string" + }, + "storage": { + "type": "string" + } + } + }, "logging_data_access": { "type": "object", "default": {}, @@ -491,9 +518,6 @@ "type": "string" } }, - "storage_location": { - "type": "string" - }, "tag_bindings": { "type": "object", "default": {}, @@ -542,11 +566,77 @@ "type": "object", "additionalProperties": false, "properties": { + "custom_roles": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "folder_ids": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "kms_keys": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, "iam_principals": { "type": "object", "additionalProperties": { "type": "string" } + }, + "locations": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "notification_channels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "project_ids": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "service_account_ids": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "tag_keys": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "tag_values": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "vpc_host_projects": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "vpc_sc_perimeters": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } }, diff --git a/fast/stages/2-project-factory/variables-fast.tf b/fast/stages/2-project-factory/variables-fast.tf index b227f7747..65bb622f5 100644 --- a/fast/stages/2-project-factory/variables-fast.tf +++ b/fast/stages/2-project-factory/variables-fast.tf @@ -71,16 +71,6 @@ variable "kms_keys" { default = {} } -variable "locations" { - # tfdoc:variable:source 0-org-setup - description = "Optional locations for GCS, BigQuery, and logging buckets created here." - type = object({ - storage = optional(string, "eu") - }) - nullable = false - default = {} -} - variable "perimeters" { # tfdoc:variable:source 1-vpcsc description = "Optional VPC-SC perimeter ids." diff --git a/fast/stages/2-project-factory/variables-projects.tf b/fast/stages/2-project-factory/variables-projects.tf index 815021b1f..b2709b37e 100644 --- a/fast/stages/2-project-factory/variables-projects.tf +++ b/fast/stages/2-project-factory/variables-projects.tf @@ -29,7 +29,17 @@ variable "data_defaults" { org_policies = optional(string) quotas = optional(string) }), {}) - labels = optional(map(string), {}) + labels = optional(map(string), {}) + locations = optional(object({ + bigquery = optional(string) + logging = optional(string) + storage = optional(string) + }), {}) + logging_data_access = optional(map(object({ + 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)) })) + })), {}) metric_scopes = optional(list(string), []) parent = optional(string) prefix = optional(string) @@ -41,6 +51,10 @@ variable "data_defaults" { services_enabled = optional(list(string), []) })) })) + service_accounts = optional(map(object({ + display_name = optional(string, "Terraform-managed.") + iam_self_roles = optional(list(string)) + })), {}) service_encryption_key_ids = optional(map(list(string)), {}) services = optional(list(string), []) shared_vpc_service_config = optional(object({ @@ -60,15 +74,10 @@ variable "data_defaults" { service_iam_grants = optional(list(string), []) network_subnet_users = optional(map(list(string)), {}) })) - storage_location = optional(string) - tag_bindings = optional(map(string), {}) - # non-project resources - service_accounts = optional(map(object({ - display_name = optional(string, "Terraform-managed.") - iam_self_roles = optional(list(string)) - })), {}) + tag_bindings = optional(map(string), {}) universe = optional(object({ prefix = string + forced_jit_service_identities = optional(list(string), []) unavailable_service_identities = optional(list(string), []) unavailable_services = optional(list(string), []) })) @@ -76,11 +85,6 @@ variable "data_defaults" { perimeter_name = string is_dry_run = optional(bool, false) })) - logging_data_access = optional(map(object({ - 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 = {} @@ -121,19 +125,28 @@ variable "data_overrides" { org_policies = optional(string) quotas = optional(string) }), {}) - parent = optional(string) - prefix = optional(string) - service_encryption_key_ids = optional(map(list(string))) - storage_location = optional(string) - tag_bindings = optional(map(string)) - services = optional(list(string)) - # non-project resources + locations = optional(object({ + bigquery = optional(string) + logging = optional(string) + storage = optional(string) + }), {}) + logging_data_access = optional(map(object({ + 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)) })) + }))) + parent = optional(string) + prefix = optional(string) service_accounts = optional(map(object({ display_name = optional(string, "Terraform-managed.") iam_self_roles = optional(list(string)) }))) + service_encryption_key_ids = optional(map(list(string))) + services = optional(list(string)) + tag_bindings = optional(map(string)) universe = optional(object({ prefix = string + forced_jit_service_identities = optional(list(string), []) unavailable_service_identities = optional(list(string), []) unavailable_services = optional(list(string), []) })) @@ -141,13 +154,7 @@ variable "data_overrides" { perimeter_name = string is_dry_run = optional(bool, false) })) - logging_data_access = optional(map(object({ - 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 = {} } - diff --git a/fast/stages/2-security/data/defaults.yaml b/fast/stages/2-security/data/defaults.yaml index ecf913d2c..30ba51145 100644 --- a/fast/stages/2-security/data/defaults.yaml +++ b/fast/stages/2-security/data/defaults.yaml @@ -18,6 +18,8 @@ context: locations: primary: europe-west1 secondary: europe-west3 + storage-default: eu projects: defaults: - storage_location: eu \ No newline at end of file + locations: + storage: $locations:storage-default \ No newline at end of file diff --git a/fast/stages/2-security/main.tf b/fast/stages/2-security/main.tf index 9e55a5a8e..58efbae82 100644 --- a/fast/stages/2-security/main.tf +++ b/fast/stages/2-security/main.tf @@ -18,11 +18,14 @@ locals { paths = { for k, v in var.factories_config : k => try(pathexpand(v), null) } + _ctx = { + for k, v in var.context : k => merge(v, try(local._defaults.context[k], {})) + } # fail if we have no valid defaults _defaults = yamldecode(file(local.paths.defaults)) - ctx = merge(var.context, { + ctx = merge(local._ctx, { folder_ids = merge( - var.folder_ids, var.context.folder_ids + var.folder_ids, local._ctx.folder_ids ) iam_principals = merge( var.iam_principals, @@ -30,17 +33,13 @@ locals { for k, v in var.service_accounts : "service_accounts/${k}" => "serviceAccount:${v}" }, - var.context.iam_principals, - try(local._defaults.context.iam_principals, {}) + local._ctx.iam_principals ) - locations = merge( - var.context.locations, - try(local._defaults.context.locations, {}) - ) - perimeters = merge(var.perimeters, var.context.vpc_sc_perimeters) - project_ids = merge(var.project_ids, var.context.project_ids) - tag_keys = merge(var.tag_keys, var.context.tag_keys) - tag_values = merge(var.tag_values, var.context.tag_values) + locations = local._ctx.locations + perimeters = merge(var.perimeters, local._ctx.vpc_sc_perimeters) + project_ids = merge(var.project_ids, local._ctx.project_ids) + tag_keys = merge(var.tag_keys, local._ctx.tag_keys) + tag_values = merge(var.tag_values, local._ctx.tag_values) }) defaults = { folder_name = try(local._defaults.global.folder_id, "security") diff --git a/fast/stages/2-security/schemas/defaults.schema.json b/fast/stages/2-security/schemas/defaults.schema.json index b8889686e..f7ae98763 100644 --- a/fast/stages/2-security/schemas/defaults.schema.json +++ b/fast/stages/2-security/schemas/defaults.schema.json @@ -73,6 +73,63 @@ } } }, + "locations": { + "type": "object", + "additionalProperties": false, + "properties": { + "bigquery": { + "type": "string" + }, + "logging": { + "type": "string" + }, + "storage": { + "type": "string" + } + } + }, + "logging_data_access": { + "type": "object", + "default": {}, + "additionalProperties": { + "type": "object", + "properties": { + "ADMIN_READ": { + "type": "object", + "properties": { + "exempted_members": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "DATA_READ": { + "type": "object", + "properties": { + "exempted_members": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "DATA_WRITE": { + "type": "object", + "properties": { + "exempted_members": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } + }, "metric_scopes": { "type": "array", "default": [], @@ -198,9 +255,6 @@ "host_project" ] }, - "storage_location": { - "type": "string" - }, "tag_bindings": { "type": "object", "default": {}, @@ -227,6 +281,34 @@ } } }, + "universe": { + "type": "object", + "additionalProperties": false, + "required": [ + "domain", + "prefix" + ], + "properties": { + "domain": { + "type": "string" + }, + "forced_jit_service_identities": { + "type": "array", + "items": { + "type": "string" + } + }, + "prefix": { + "type": "string" + }, + "unavailable_service_identities": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "vpc_sc": { "type": "object", "properties": { @@ -241,48 +323,6 @@ "required": [ "perimeter_name" ] - }, - "logging_data_access": { - "type": "object", - "default": {}, - "additionalProperties": { - "type": "object", - "properties": { - "ADMIN_READ": { - "type": "object", - "properties": { - "exempted_members": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "DATA_READ": { - "type": "object", - "properties": { - "exempted_members": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "DATA_WRITE": { - "type": "object", - "properties": { - "exempted_members": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - } } } }, @@ -323,68 +363,20 @@ "ABANDON" ] }, - "parent": { - "type": "string" - }, - "prefix": { - "type": "string" - }, - "service_encryption_key_ids": { + "locations": { "type": "object", - "default": {}, "additionalProperties": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "storage_location": { - "type": "string" - }, - "tag_bindings": { - "type": "object", - "default": {}, - "additionalProperties": { - "type": "string" - } - }, - "service_accounts": { - "type": "object", - "default": {}, - "additionalProperties": { - "type": "object", - "properties": { - "display_name": { - "type": "string", - "default": "Terraform-managed." - }, - "iam_self_roles": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "vpc_sc": { - "type": "object", "properties": { - "perimeter_name": { + "bigquery": { "type": "string" }, - "is_dry_run": { - "type": "boolean", - "default": false + "logging": { + "type": "string" + }, + "storage": { + "type": "string" } - }, - "required": [ - "perimeter_name" - ] + } }, "logging_data_access": { "type": "object", @@ -427,6 +419,94 @@ } } } + }, + "parent": { + "type": "string" + }, + "prefix": { + "type": "string" + }, + "service_encryption_key_ids": { + "type": "object", + "default": {}, + "additionalProperties": false, + "patternProperties": { + "^[a-z0-9_-]+$": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "tag_bindings": { + "type": "object", + "default": {}, + "additionalProperties": { + "type": "string" + } + }, + "service_accounts": { + "type": "object", + "default": {}, + "additionalProperties": { + "type": "object", + "properties": { + "display_name": { + "type": "string", + "default": "Terraform-managed." + }, + "iam_self_roles": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "universe": { + "type": "object", + "additionalProperties": false, + "required": [ + "domain", + "prefix" + ], + "properties": { + "domain": { + "type": "string" + }, + "forced_jit_service_identities": { + "type": "array", + "items": { + "type": "string" + } + }, + "prefix": { + "type": "string" + }, + "unavailable_service_identities": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "vpc_sc": { + "type": "object", + "properties": { + "perimeter_name": { + "type": "string" + }, + "is_dry_run": { + "type": "boolean", + "default": false + } + }, + "required": [ + "perimeter_name" + ] } } } @@ -436,6 +516,24 @@ "type": "object", "additionalProperties": false, "properties": { + "custom_roles": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "folder_ids": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "kms_keys": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, "iam_principals": { "type": "object", "additionalProperties": { @@ -447,6 +545,48 @@ "additionalProperties": { "type": "string" } + }, + "notification_channels": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "project_ids": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "service_account_ids": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "tag_keys": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "tag_values": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "vpc_host_projects": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "vpc_sc_perimeters": { + "type": "object", + "additionalProperties": { + "type": "string" + } } } } diff --git a/modules/logging-bucket/main.tf b/modules/logging-bucket/main.tf index 8617fadd9..65178511c 100644 --- a/modules/logging-bucket/main.tf +++ b/modules/logging-bucket/main.tf @@ -27,6 +27,9 @@ locals { } } ctx_p = "$" + location = lookup( + local.ctx.locations, var.location, var.location + ) parent_id = ( var.parent_type == "project" ? lookup(local.ctx.project_ids, var.parent, var.parent) @@ -40,11 +43,9 @@ locals { } resource "google_logging_project_bucket_config" "bucket" { - count = var.parent_type == "project" ? 1 : 0 - project = local.parent_id - location = lookup( - local.ctx.locations, var.location, var.location - ) + count = var.parent_type == "project" ? 1 : 0 + project = local.parent_id + location = local.location retention_days = var.retention bucket_id = var.name description = var.description @@ -58,11 +59,9 @@ resource "google_logging_project_bucket_config" "bucket" { } resource "google_logging_folder_bucket_config" "bucket" { - count = var.parent_type == "folder" ? 1 : 0 - folder = local.parent_id - location = lookup( - local.ctx.locations, var.location, var.location - ) + count = var.parent_type == "folder" ? 1 : 0 + folder = local.parent_id + location = local.location retention_days = var.retention bucket_id = var.name description = var.description @@ -73,16 +72,14 @@ resource "google_logging_linked_dataset" "dataset" { link_id = var.log_analytics.dataset_link_id parent = "projects/${google_logging_project_bucket_config.bucket[0].project}" bucket = google_logging_project_bucket_config.bucket[0].id - location = var.location + location = local.location description = var.log_analytics.description } resource "google_logging_organization_bucket_config" "bucket" { - count = var.parent_type == "organization" ? 1 : 0 - organization = local.parent_id - location = lookup( - local.ctx.locations, var.location, var.location - ) + count = var.parent_type == "organization" ? 1 : 0 + organization = local.parent_id + location = local.location retention_days = var.retention bucket_id = var.name description = var.description @@ -91,12 +88,10 @@ resource "google_logging_organization_bucket_config" "bucket" { resource "google_logging_billing_account_bucket_config" "bucket" { count = var.parent_type == "billing_account" ? 1 : 0 billing_account = local.parent_id - location = lookup( - local.ctx.locations, var.location, var.location - ) - retention_days = var.retention - bucket_id = var.name - description = var.description + location = local.location + retention_days = var.retention + bucket_id = var.name + description = var.description } resource "google_logging_log_view" "views" { diff --git a/modules/project-factory/README.md b/modules/project-factory/README.md index 98337dc2a..906db469f 100644 --- a/modules/project-factory/README.md +++ b/modules/project-factory/README.md @@ -421,8 +421,10 @@ module "project-factory" { } # use a default billing account if none is specified via yaml data_defaults = { - billing_account = var.billing_account_id - storage_location = "EU" + billing_account = var.billing_account_id + locations = { + storage = "EU" + } } # make sure the environment label and stackdriver service are always added data_merges = { @@ -706,14 +708,14 @@ service_accounts: | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [factories_config](variables.tf#L175) | Path to folder with YAML resource description data files. | object({…}) | ✓ | | +| [factories_config](variables.tf#L181) | Path to folder with YAML resource description data files. | object({…}) | ✓ | | | [context](variables.tf#L17) | Context-specific interpolations. | object({…}) | | {} | -| [data_defaults](variables.tf#L36) | Optional default values used when corresponding project or folder data from files are missing. | object({…}) | | {} | -| [data_merges](variables.tf#L109) | 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#L128) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | +| [data_defaults](variables.tf#L36) | Optional default values used when corresponding project or folder data from files are missing. | object({…}) | | {} | +| [data_merges](variables.tf#L112) | 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#L131) | 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 @@ -739,8 +741,10 @@ These tests validate fixes to the project factory. module "project-factory" { source = "./fabric/modules/project-factory" data_defaults = { - billing_account = "012345-67890A-ABCDEF" - storage_location = "eu" + billing_account = "012345-67890A-ABCDEF" + locations = { + storage = "eu" + } } data_merges = { labels = { diff --git a/modules/project-factory/automation.tf b/modules/project-factory/automation.tf index 11a52070f..e503e6310 100644 --- a/modules/project-factory/automation.tf +++ b/modules/project-factory/automation.tf @@ -101,9 +101,9 @@ module "automation-bucket" { labels = lookup(each.value, "labels", {}) managed_folders = lookup(each.value, "managed_folders", {}) location = each.value.create == false ? null : coalesce( - local.data_defaults.overrides.storage_location, + local.data_defaults.overrides.locations.storage, lookup(each.value, "location", null), - local.data_defaults.defaults.storage_location + local.data_defaults.defaults.locations.storage ) storage_class = lookup( each.value, "storage_class", "STANDARD" diff --git a/modules/project-factory/main.tf b/modules/project-factory/main.tf index ea74e1d63..8d6194301 100644 --- a/modules/project-factory/main.tf +++ b/modules/project-factory/main.tf @@ -32,10 +32,10 @@ resource "terraform_data" "defaults_preconditions" { lifecycle { precondition { condition = ( - var.data_defaults.storage_location != null || - var.data_overrides.storage_location != null + var.data_defaults.locations.storage != null || + var.data_overrides.locations.storage != null ) - error_message = "No default storage location defined in defaults or overides variables." + error_message = "No default storage location defined in defaults or overrides variables." } } } diff --git a/modules/project-factory/projects-bigquery.tf b/modules/project-factory/projects-bigquery.tf index 7f88337f8..7e77ef74b 100644 --- a/modules/project-factory/projects-bigquery.tf +++ b/modules/project-factory/projects-bigquery.tf @@ -36,17 +36,18 @@ module "bigquery-datasets" { project_id = module.projects[each.value.project_key].project_id id = each.value.id context = merge(local.ctx, { - project_ids = local.ctx_project_ids iam_principals = merge( local.ctx.iam_principals, local.projects_sas_iam_emails, local.automation_sas_iam_emails ) + locations = local.ctx.locations + project_ids = local.ctx_project_ids }) friendly_name = each.value.friendly_name location = coalesce( - local.data_defaults.overrides.bigquery_location, + local.data_defaults.overrides.locations.bigquery, lookup(each.value, "location", null), - local.data_defaults.defaults.bigquery_location + local.data_defaults.defaults.locations.bigquery ) } diff --git a/modules/project-factory/projects-buckets.tf b/modules/project-factory/projects-buckets.tf index e200c4cd4..91d6d3ac6 100644 --- a/modules/project-factory/projects-buckets.tf +++ b/modules/project-factory/projects-buckets.tf @@ -67,12 +67,13 @@ module "buckets" { encryption_key = each.value.encryption_key force_destroy = each.value.force_destroy context = merge(local.ctx, { - project_ids = local.ctx_project_ids iam_principals = merge( local.ctx.iam_principals, local.projects_sas_iam_emails, local.automation_sas_iam_emails ) + locations = local.ctx.locations + project_ids = local.ctx_project_ids }) iam = each.value.iam iam_bindings = each.value.iam_bindings @@ -80,9 +81,9 @@ module "buckets" { iam_by_principals = each.value.iam_by_principals labels = each.value.labels location = coalesce( - local.data_defaults.overrides.storage_location, + local.data_defaults.overrides.locations.storage, lookup(each.value, "location", null), - local.data_defaults.defaults.storage_location + local.data_defaults.defaults.locations.storage ) managed_folders = each.value.managed_folders storage_class = each.value.storage_class diff --git a/modules/project-factory/projects-defaults.tf b/modules/project-factory/projects-defaults.tf index 42f90801d..09b1ccbfc 100644 --- a/modules/project-factory/projects-defaults.tf +++ b/modules/project-factory/projects-defaults.tf @@ -25,133 +25,6 @@ locals { defaults = try(var.data_defaults, {}) overrides = try(var.data_overrides, {}) } - data_defaults = { - defaults = merge( - { - billing_account = null - contacts = {} - deletion_policy = null - factories_config = merge( - { - custom_roles = null - observability = null - org_policies = null - quotas = null - }, - try(local._data_defaults.defaults.factories_config, { - custom_roles = null - observability = null - org_policies = null - quotas = null - } - ) - ) - labels = {} - metric_scopes = [] - parent = null - prefix = null - project_reuse = merge( - { - use_data_source = true - attributes = null - }, - try(local._data_defaults.defaults.project_reuse, { - use_data_source = true - attributes = null - } - ) - ) - service_encryption_key_ids = {} - services = [] - shared_vpc_service_config = merge( - { - host_project = null - iam_bindings_additive = {} - network_users = [] - service_agent_iam = {} - service_agent_subnet_iam = {} - service_iam_grants = [] - network_subnet_users = {} - }, - try(local._data_defaults.defaults.shared_vpc_service_config, { - host_project = null - iam_bindings_additive = {} - network_users = [] - service_agent_iam = {} - service_agent_subnet_iam = {} - service_iam_grants = [] - network_subnet_users = {} - } - ) - ) - storage_location = null - tag_bindings = {} - service_accounts = {} - universe = null - vpc_sc = merge( - { - perimeter_name = null - is_dry_run = false - }, - try(local._data_defaults.defaults.vpc_sc, { - perimeter_name = null - is_dry_run = false - } - ) - ) - logging_data_access = {} - bigquery_location = null - }, - try( - local._data_defaults.defaults, {} - ) - ) - # data_overrides default to null's, to mark that they should not override - overrides = merge({ - billing_account = null - contacts = null - deletion_policy = null - factories_config = merge( - { - custom_roles = null - observability = null - org_policies = null - quotas = null - }, - try(local._data_defaults.overrides.factories_config, { - custom_roles = null - observability = null - org_policies = null - quotas = null - } - ) - ) - parent = null - prefix = null - service_encryption_key_ids = null - storage_location = null - tag_bindings = null - services = null - service_accounts = null - universe = null - vpc_sc = try( - merge( - { - perimeter_name = null - is_dry_run = false - }, - local._data_defaults.overrides.vpc_sc - ), - null - ) - logging_data_access = null - bigquery_location = null - }, - try( - local._data_defaults.overrides, {} - ) - ) - } _projects_output = { # Semantics of the merges are: # - if data_overrides. is not null, use this value @@ -350,4 +223,137 @@ locals { for k, v in local._projects_output : "${v.prefix != null ? v.prefix : ""}-${v.name}" => k } + data_defaults = { + defaults = merge( + { + billing_account = null + contacts = {} + deletion_policy = null + factories_config = merge( + { + custom_roles = null + observability = null + org_policies = null + quotas = null + }, + try(local._data_defaults.defaults.factories_config, { + custom_roles = null + observability = null + org_policies = null + quotas = null + } + ) + ) + labels = {} + locations = { + bigquery = try(local._data_defaults.defaults.locations.bigquery, null) + logging = try(local._data_defaults.defaults.locations.logging, null) + storage = try(local._data_defaults.defaults.locations.storage, null) + } + logging_data_access = {} + metric_scopes = [] + parent = null + prefix = null + project_reuse = merge( + { + use_data_source = true + attributes = null + }, + try(local._data_defaults.defaults.project_reuse, { + use_data_source = true + attributes = null + } + ) + ) + service_encryption_key_ids = {} + services = [] + shared_vpc_service_config = merge( + { + host_project = null + iam_bindings_additive = {} + network_users = [] + service_agent_iam = {} + service_agent_subnet_iam = {} + service_iam_grants = [] + network_subnet_users = {} + }, + try(local._data_defaults.defaults.shared_vpc_service_config, { + host_project = null + iam_bindings_additive = {} + network_users = [] + service_agent_iam = {} + service_agent_subnet_iam = {} + service_iam_grants = [] + network_subnet_users = {} + } + ) + ) + tag_bindings = {} + service_accounts = {} + universe = null + vpc_sc = merge( + { + perimeter_name = null + is_dry_run = false + }, + try(local._data_defaults.defaults.vpc_sc, { + perimeter_name = null + is_dry_run = false + } + ) + ) + }, + try( + local._data_defaults.defaults, {} + ) + ) + # data_overrides default to null's, to mark that they should not override + overrides = merge({ + billing_account = null + contacts = null + deletion_policy = null + factories_config = merge( + { + custom_roles = null + observability = null + org_policies = null + quotas = null + }, + try(local._data_defaults.overrides.factories_config, { + custom_roles = null + observability = null + org_policies = null + quotas = null + } + ) + ) + locations = { + bigquery = try(local._data_defaults.overrides.locations.bigquery, null) + logging = try(local._data_defaults.overrides.locations.logging, null) + storage = try(local._data_defaults.overrides.locations.storage, null) + } + logging_data_access = null + parent = null + prefix = null + service_encryption_key_ids = null + tag_bindings = null + services = null + service_accounts = null + universe = null + vpc_sc = try( + merge( + { + perimeter_name = null + is_dry_run = false + }, + local._data_defaults.overrides.vpc_sc + ), + null + ) + }, + try( + local._data_defaults.overrides, {} + ) + ) + } } diff --git a/modules/project-factory/projects-log-buckets.tf b/modules/project-factory/projects-log-buckets.tf index 69301f665..ce822fd9d 100644 --- a/modules/project-factory/projects-log-buckets.tf +++ b/modules/project-factory/projects-log-buckets.tf @@ -23,8 +23,10 @@ locals { name = name description = lookup(opts, "description", "Terraform-managed.") kms_key_name = lookup(opts, "kms_key_name", null) - location = try( - lookup(local.ctx.locations, opts.location, opts.location), + location = coalesce( + local.data_defaults.overrides.locations.logging, + lookup(opts, "location", null), + local.data_defaults.defaults.locations.logging, "global" ) retention = lookup(opts, "retention", null) @@ -44,13 +46,14 @@ module "log-buckets" { location = each.value.location kms_key_name = each.value.kms_key_name context = merge(local.ctx, { - folder_ids = local.ctx_folder_ids - project_ids = local.ctx_project_ids + folder_ids = local.ctx_folder_ids iam_principals = merge( local.ctx.iam_principals, local.projects_sas_iam_emails, local.automation_sas_iam_emails ) + locations = local.ctx.locations + project_ids = local.ctx_project_ids }) retention = each.value.retention log_analytics = each.value.log_analytics diff --git a/modules/project-factory/schemas/project.schema.json b/modules/project-factory/schemas/project.schema.json index 6bb9ffe1c..1a326aa52 100644 --- a/modules/project-factory/schemas/project.schema.json +++ b/modules/project-factory/schemas/project.schema.json @@ -88,6 +88,24 @@ } } }, + "datasets": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^[a-z0-9_]+$": { + "type": "object", + "additionalProperties": false, + "properties": { + "friendly_name": { + "type": "string" + }, + "location": { + "type": "string" + } + } + } + } + }, "deletion_policy": { "type": "string", "enum": [ @@ -529,24 +547,6 @@ "type": "boolean" } } - }, - "datasets": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9_]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "friendly_name": { - "type": "string" - }, - "location": { - "type": "string" - } - } - } - } } }, "$defs": { @@ -846,4 +846,4 @@ } } } -} +} \ No newline at end of file diff --git a/modules/project-factory/variables-projects.tf b/modules/project-factory/variables-projects.tf index 9d2b68ea7..4b959a7ae 100644 --- a/modules/project-factory/variables-projects.tf +++ b/modules/project-factory/variables-projects.tf @@ -153,7 +153,11 @@ variable "projects" { })), {}) })), {}) contacts = optional(map(list(string)), {}) - iam = optional(map(list(string)), {}) + datasets = optional(map(object({ + friendly_name = optional(string) + location = optional(string) + })), {}) + iam = optional(map(list(string)), {}) iam_bindings = optional(map(object({ members = list(string) role = string diff --git a/modules/project-factory/variables.tf b/modules/project-factory/variables.tf index bbfa78d76..2e33347b3 100644 --- a/modules/project-factory/variables.tf +++ b/modules/project-factory/variables.tf @@ -49,6 +49,11 @@ variable "data_defaults" { quotas = optional(string) }), {}) labels = optional(map(string), {}) + locations = optional(object({ + bigquery = optional(string) + logging = optional(string) + storage = optional(string) + }), {}) logging_data_access = optional(map(object({ ADMIN_READ = optional(object({ exempted_members = optional(list(string)) })), DATA_READ = optional(object({ exempted_members = optional(list(string)) })), @@ -88,8 +93,7 @@ variable "data_defaults" { service_iam_grants = optional(list(string), []) network_subnet_users = optional(map(list(string)), {}) })) - storage_location = optional(string) - tag_bindings = optional(map(string), {}) + tag_bindings = optional(map(string), {}) universe = optional(object({ prefix = string forced_jit_service_identities = optional(list(string), []) @@ -100,7 +104,6 @@ variable "data_defaults" { perimeter_name = string is_dry_run = optional(bool, false) })) - bigquery_location = optional(string) }) nullable = false default = {} @@ -141,6 +144,11 @@ variable "data_overrides" { org_policies = optional(string) quotas = optional(string) }), {}) + locations = optional(object({ + bigquery = optional(string) + logging = optional(string) + storage = optional(string) + }), {}) logging_data_access = optional(map(object({ ADMIN_READ = optional(object({ exempted_members = optional(list(string)) })), DATA_READ = optional(object({ exempted_members = optional(list(string)) })), @@ -154,7 +162,6 @@ variable "data_overrides" { }))) service_encryption_key_ids = optional(map(list(string))) services = optional(list(string)) - storage_location = optional(string) tag_bindings = optional(map(string)) universe = optional(object({ prefix = string @@ -166,7 +173,6 @@ variable "data_overrides" { perimeter_name = string is_dry_run = optional(bool, false) })) - bigquery_location = optional(string) }) nullable = false default = {} diff --git a/tests/fast/stages/s0_org_setup/data-simple/cicd.yaml b/tests/fast/stages/s0_org_setup/data-simple/cicd.yaml index eef12642a..726c0ff83 100644 --- a/tests/fast/stages/s0_org_setup/data-simple/cicd.yaml +++ b/tests/fast/stages/s0_org_setup/data-simple/cicd.yaml @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# yaml-language-server: $schema=../schemas/cicd.schema.json +# yaml-language-server: $schema=../../../../../fast/stages/0-org-setup/schemas/cicd.schema.json workload_identity_federation: pool_name: iac-0 diff --git a/tests/fast/stages/s0_org_setup/data-simple/defaults.yaml b/tests/fast/stages/s0_org_setup/data-simple/defaults.yaml index c1efefac0..ee5ea6619 100644 --- a/tests/fast/stages/s0_org_setup/data-simple/defaults.yaml +++ b/tests/fast/stages/s0_org_setup/data-simple/defaults.yaml @@ -12,15 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -# yaml-language-server: $schema=../../../../../fast/stages/0-bootstrap-experimental/schemas/defaults.schema.json +# yaml-language-server: $schema=../../../../../fast/stages/0-org-setup/schemas/defaults.schema.json # defaults: # storage_location: europe-west1 global: billing_account: 012345-012345-012345 - locations: - bigquery: europe-west1 - logging: europe-west1 organization: domain: example.org id: 1234567890 @@ -28,8 +25,10 @@ global: projects: defaults: prefix: ft0 - storage_location: europe-west1 - bigquery_location: europe-west1 + locations: + bigquery: $locations:primary + logging: $locations:primary + storage: $locations:primary overrides: {} output_files: local_path: /tmp/fast-config @@ -60,3 +59,5 @@ output_files: context: iam_principals: gcp-organization-admins: group:fabric-fast-owners@google.com + locations: + primary: europe-west1 \ No newline at end of file diff --git a/tests/fast/stages/s0_org_setup/not-simple.yaml b/tests/fast/stages/s0_org_setup/not-simple.yaml index 86c44055b..3f2530c55 100644 --- a/tests/fast/stages/s0_org_setup/not-simple.yaml +++ b/tests/fast/stages/s0_org_setup/not-simple.yaml @@ -243,7 +243,7 @@ values: google_storage_bucket_object.tfvars["globals"]: bucket: ft0-prod-iac-core-0-iac-outputs cache_control: null - content: '{"billing_account":{"id":"012345-012345-012345"},"groups":{"domain":"domain:example.org","gcp-billing-admins":"group:gcp-billing-admins@example.org","gcp-devops":"group:gcp-devops@example.org","gcp-network-admins":"group:gcp-network-admins@example.org","gcp-organization-admins":"group:fabric-fast-owners@google.com","gcp-secops-admins":"group:gcp-secops-admins@example.org","gcp-security-admins":"group:gcp-security-admins@example.org","gcp-support":"group:gcp-support@example.org"},"locations":{"bigquery":"europe-west1","logging":"europe-west1","pubsub":[],"storage":"eu"},"organization":{"customer_id":"abcd123456","domain":"example.org","id":"1234567890"},"prefix":"ft0","universe":null}' + content: '{"billing_account":{"id":"012345-012345-012345"},"groups":{"domain":"domain:example.org","gcp-billing-admins":"group:gcp-billing-admins@example.org","gcp-devops":"group:gcp-devops@example.org","gcp-network-admins":"group:gcp-network-admins@example.org","gcp-organization-admins":"group:fabric-fast-owners@google.com","gcp-secops-admins":"group:gcp-secops-admins@example.org","gcp-security-admins":"group:gcp-security-admins@example.org","gcp-support":"group:gcp-support@example.org"},"organization":{"customer_id":"abcd123456","domain":"example.org","id":"1234567890"},"prefix":"ft0","universe":null}' content_disposition: null content_encoding: null content_language: null @@ -426,7 +426,7 @@ values: sensitive_content: null source: null local_file.tfvars["globals"]: - content: '{"billing_account":{"id":"012345-012345-012345"},"groups":{"domain":"domain:example.org","gcp-billing-admins":"group:gcp-billing-admins@example.org","gcp-devops":"group:gcp-devops@example.org","gcp-network-admins":"group:gcp-network-admins@example.org","gcp-organization-admins":"group:fabric-fast-owners@google.com","gcp-secops-admins":"group:gcp-secops-admins@example.org","gcp-security-admins":"group:gcp-security-admins@example.org","gcp-support":"group:gcp-support@example.org"},"locations":{"bigquery":"europe-west1","logging":"europe-west1","pubsub":[],"storage":"eu"},"organization":{"customer_id":"abcd123456","domain":"example.org","id":"1234567890"},"prefix":"ft0","universe":null}' + content: '{"billing_account":{"id":"012345-012345-012345"},"groups":{"domain":"domain:example.org","gcp-billing-admins":"group:gcp-billing-admins@example.org","gcp-devops":"group:gcp-devops@example.org","gcp-network-admins":"group:gcp-network-admins@example.org","gcp-organization-admins":"group:fabric-fast-owners@google.com","gcp-secops-admins":"group:gcp-secops-admins@example.org","gcp-security-admins":"group:gcp-security-admins@example.org","gcp-support":"group:gcp-support@example.org"},"organization":{"customer_id":"abcd123456","domain":"example.org","id":"1234567890"},"prefix":"ft0","universe":null}' content_base64: null directory_permission: '0777' file_permission: '0644' @@ -1011,7 +1011,7 @@ values: cmek_settings: [] enable_analytics: false index_configs: [] - location: global + location: europe-west1 locked: null project: ft0-prod-audit-logs-0 retention_days: 30 @@ -1020,7 +1020,7 @@ values: cmek_settings: [] enable_analytics: false index_configs: [] - location: global + location: europe-west1 locked: null project: ft0-prod-audit-logs-0 retention_days: 30 @@ -1029,7 +1029,7 @@ values: cmek_settings: [] enable_analytics: true index_configs: [] - location: global + location: europe-west1 locked: null project: ft0-prod-audit-logs-0 retention_days: 31 diff --git a/tests/fast/stages/s2_project_factory/simple.tfvars b/tests/fast/stages/s2_project_factory/simple.tfvars index eaae77f48..70a02d32d 100644 --- a/tests/fast/stages/s2_project_factory/simple.tfvars +++ b/tests/fast/stages/s2_project_factory/simple.tfvars @@ -12,3 +12,8 @@ tag_values = { "environment/development" = "tagValues/1234567890" "environment/production" = "tagValues/2345678901" } +data_defaults = { + locations = { + storage = "europe-west1" + } +} diff --git a/tests/fast/stages/s2_security/data-simple/defaults.yaml b/tests/fast/stages/s2_security/data-simple/defaults.yaml index c674bfe60..070e79741 100644 --- a/tests/fast/stages/s2_security/data-simple/defaults.yaml +++ b/tests/fast/stages/s2_security/data-simple/defaults.yaml @@ -20,4 +20,5 @@ context: secondary: europe-west3 projects: defaults: - storage_location: eu \ No newline at end of file + locations: + storage: eu