From 4b0c34fe4eb0a5fddd8c0ffe065b62555b17ae95 Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Thu, 26 Mar 2026 16:38:43 +0000 Subject: [PATCH 1/3] fix: align subscription_ids variable across azuredevops, github, and local - Simplify GUID regex in azuredevops to match github/local pattern - Remove identity from required subscription keys (only management and connectivity required) - Fix extra space in local description --- alz/azuredevops/variables.tf | 6 +++--- alz/github/variables.tf | 4 ++-- alz/local/variables.tf | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/alz/azuredevops/variables.tf b/alz/azuredevops/variables.tf index c20ab06..66becbb 100644 --- a/alz/azuredevops/variables.tf +++ b/alz/azuredevops/variables.tf @@ -45,7 +45,7 @@ variable "subscription_ids" { default = {} nullable = false validation { - condition = alltrue([for id in values(var.subscription_ids) : can(regex("^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$", id))]) + condition = alltrue([for id in values(var.subscription_ids) : can(regex("^[0-9a-fA-F-]{36}$", id))]) error_message = "All subscription IDs must be valid GUIDs" } validation { @@ -53,8 +53,8 @@ variable "subscription_ids" { error_message = "The keys of the subscription_ids map must be one of 'management', 'connectivity', 'identity' or 'security'" } validation { - condition = contains(keys(var.subscription_ids), "management") && contains(keys(var.subscription_ids), "connectivity") && contains(keys(var.subscription_ids), "identity") - error_message = "You must provide subscription IDs for: 'management', 'connectivity', and 'identity'" + condition = contains(keys(var.subscription_ids), "management") && contains(keys(var.subscription_ids), "connectivity") + error_message = "You must provide subscription IDs for: 'management', and 'connectivity'" } } diff --git a/alz/github/variables.tf b/alz/github/variables.tf index cbb1d92..4d11c64 100644 --- a/alz/github/variables.tf +++ b/alz/github/variables.tf @@ -53,8 +53,8 @@ variable "subscription_ids" { error_message = "The keys of the subscription_ids map must be one of 'management', 'connectivity', 'identity' or 'security'" } validation { - condition = contains(keys(var.subscription_ids), "management") && contains(keys(var.subscription_ids), "connectivity") && contains(keys(var.subscription_ids), "identity") - error_message = "You must provide subscription IDs for: 'management', 'connectivity', and 'identity'" + condition = contains(keys(var.subscription_ids), "management") && contains(keys(var.subscription_ids), "connectivity") + error_message = "You must provide subscription IDs for: 'management', and 'connectivity'" } } diff --git a/alz/local/variables.tf b/alz/local/variables.tf index fd1152c..7915f3a 100644 --- a/alz/local/variables.tf +++ b/alz/local/variables.tf @@ -28,7 +28,7 @@ variable "root_parent_management_group_id" { variable "subscription_ids" { description = <<-EOT - **(Optional, default: `{}`)** Map of Azure subscription IDs where Platform Landing Zone resources will be deployed. + **(Optional, default: `{}`)** Map of Azure subscription IDs where Platform Landing Zone resources will be deployed. Keys must be one of: 'management', 'connectivity', 'identity', 'security' Values must be valid Azure subscription GUIDs. @@ -53,8 +53,8 @@ variable "subscription_ids" { error_message = "The keys of the subscription_ids map must be one of 'management', 'connectivity', 'identity' or 'security'" } validation { - condition = contains(keys(var.subscription_ids), "management") && contains(keys(var.subscription_ids), "connectivity") && contains(keys(var.subscription_ids), "identity") - error_message = "You must provide subscription IDs for: 'management', 'connectivity', and 'identity'" + condition = contains(keys(var.subscription_ids), "management") && contains(keys(var.subscription_ids), "connectivity") + error_message = "You must provide subscription IDs for: 'management', and 'connectivity'" } } From 3387e453e99d12260b05c5f05c1d2b7f1c985680 Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Fri, 27 Mar 2026 18:57:56 +0000 Subject: [PATCH 2/3] feat: add required_subscription_keys variable and filter empty subscription IDs - Add required_subscription_keys variable to control which subscriptions need valid GUIDs - Update subscription_ids validation to allow null/empty for non-required keys - Filter out null/empty values from target_subscriptions in all locals.tf files --- alz/azuredevops/locals.tf | 2 +- alz/azuredevops/variables.tf | 28 ++++++++++++++++++++++------ alz/github/locals.tf | 2 +- alz/github/variables.tf | 28 ++++++++++++++++++++++------ alz/local/locals.tf | 2 +- alz/local/variables.tf | 28 ++++++++++++++++++++++------ 6 files changed, 69 insertions(+), 21 deletions(-) diff --git a/alz/azuredevops/locals.tf b/alz/azuredevops/locals.tf index f35bd6e..cc9f790 100644 --- a/alz/azuredevops/locals.tf +++ b/alz/azuredevops/locals.tf @@ -34,7 +34,7 @@ locals { } locals { - target_subscriptions = distinct(values(var.subscription_ids)) + target_subscriptions = distinct([for v in values(var.subscription_ids) : v if v != null && v != ""]) } locals { diff --git a/alz/azuredevops/variables.tf b/alz/azuredevops/variables.tf index 66becbb..d6c2736 100644 --- a/alz/azuredevops/variables.tf +++ b/alz/azuredevops/variables.tf @@ -26,12 +26,28 @@ variable "root_parent_management_group_id" { default = "" } +variable "required_subscription_keys" { + description = <<-EOT + **(Optional, default: `["management", "connectivity"]`)** List of subscription keys that must be present with valid GUID values. + + Keys not in this list may have null or empty string values. + Valid keys: 'management', 'connectivity', 'identity', 'security' + EOT + type = list(string) + default = ["management", "connectivity"] + nullable = false + validation { + condition = alltrue([for key in var.required_subscription_keys : contains(["management", "connectivity", "identity", "security"], key)]) + error_message = "The required_subscription_keys must be one of 'management', 'connectivity', 'identity' or 'security'" + } +} + variable "subscription_ids" { description = <<-EOT **(Optional, default: `{}`)** Map of Azure subscription IDs where Platform Landing Zone resources will be deployed. Keys must be one of: 'management', 'connectivity', 'identity', 'security' - Values must be valid Azure subscription GUIDs. + Values must be valid Azure subscription GUIDs, or null/empty for non-required keys. Example: ``` @@ -45,16 +61,16 @@ variable "subscription_ids" { default = {} nullable = false validation { - condition = alltrue([for id in values(var.subscription_ids) : can(regex("^[0-9a-fA-F-]{36}$", id))]) - error_message = "All subscription IDs must be valid GUIDs" + condition = alltrue([for key, id in var.subscription_ids : contains(var.required_subscription_keys, key) ? can(regex("^[0-9a-fA-F-]{36}$", id)) : (id == null || id == "" || can(regex("^[0-9a-fA-F-]{36}$", id)))]) + error_message = "Required subscription IDs must be valid GUIDs. Optional subscription IDs must be valid GUIDs, null, or empty string." } validation { - condition = alltrue([for id in keys(var.subscription_ids) : contains(["management", "connectivity", "identity", "security"], id)]) + condition = alltrue([for key in keys(var.subscription_ids) : contains(["management", "connectivity", "identity", "security"], key)]) error_message = "The keys of the subscription_ids map must be one of 'management', 'connectivity', 'identity' or 'security'" } validation { - condition = contains(keys(var.subscription_ids), "management") && contains(keys(var.subscription_ids), "connectivity") - error_message = "You must provide subscription IDs for: 'management', and 'connectivity'" + condition = alltrue([for key in var.required_subscription_keys : contains(keys(var.subscription_ids), key)]) + error_message = "You must provide subscription IDs for all required subscription keys." } } diff --git a/alz/github/locals.tf b/alz/github/locals.tf index c550139..185b125 100644 --- a/alz/github/locals.tf +++ b/alz/github/locals.tf @@ -41,7 +41,7 @@ locals { } locals { - target_subscriptions = distinct(values(var.subscription_ids)) + target_subscriptions = distinct([for v in values(var.subscription_ids) : v if v != null && v != ""]) } locals { diff --git a/alz/github/variables.tf b/alz/github/variables.tf index 4d11c64..46338e8 100644 --- a/alz/github/variables.tf +++ b/alz/github/variables.tf @@ -26,12 +26,28 @@ variable "root_parent_management_group_id" { default = "" } +variable "required_subscription_keys" { + description = <<-EOT + **(Optional, default: `["management", "connectivity"]`)** List of subscription keys that must be present with valid GUID values. + + Keys not in this list may have null or empty string values. + Valid keys: 'management', 'connectivity', 'identity', 'security' + EOT + type = list(string) + default = ["management", "connectivity"] + nullable = false + validation { + condition = alltrue([for key in var.required_subscription_keys : contains(["management", "connectivity", "identity", "security"], key)]) + error_message = "The required_subscription_keys must be one of 'management', 'connectivity', 'identity' or 'security'" + } +} + variable "subscription_ids" { description = <<-EOT **(Optional, default: `{}`)** Map of Azure subscription IDs where Platform Landing Zone resources will be deployed. Keys must be one of: 'management', 'connectivity', 'identity', 'security' - Values must be valid Azure subscription GUIDs. + Values must be valid Azure subscription GUIDs, or null/empty for non-required keys. Example: ``` @@ -45,16 +61,16 @@ variable "subscription_ids" { default = {} nullable = false validation { - condition = alltrue([for id in values(var.subscription_ids) : can(regex("^[0-9a-fA-F-]{36}$", id))]) - error_message = "All subscription IDs must be valid GUIDs" + condition = alltrue([for key, id in var.subscription_ids : contains(var.required_subscription_keys, key) ? can(regex("^[0-9a-fA-F-]{36}$", id)) : (id == null || id == "" || can(regex("^[0-9a-fA-F-]{36}$", id)))]) + error_message = "Required subscription IDs must be valid GUIDs. Optional subscription IDs must be valid GUIDs, null, or empty string." } validation { - condition = alltrue([for id in keys(var.subscription_ids) : contains(["management", "connectivity", "identity", "security"], id)]) + condition = alltrue([for key in keys(var.subscription_ids) : contains(["management", "connectivity", "identity", "security"], key)]) error_message = "The keys of the subscription_ids map must be one of 'management', 'connectivity', 'identity' or 'security'" } validation { - condition = contains(keys(var.subscription_ids), "management") && contains(keys(var.subscription_ids), "connectivity") - error_message = "You must provide subscription IDs for: 'management', and 'connectivity'" + condition = alltrue([for key in var.required_subscription_keys : contains(keys(var.subscription_ids), key)]) + error_message = "You must provide subscription IDs for all required subscription keys." } } diff --git a/alz/local/locals.tf b/alz/local/locals.tf index 857de2d..3594464 100644 --- a/alz/local/locals.tf +++ b/alz/local/locals.tf @@ -17,7 +17,7 @@ locals { } locals { - target_subscriptions = distinct(values(var.subscription_ids)) + target_subscriptions = distinct([for v in values(var.subscription_ids) : v if v != null && v != ""]) } locals { diff --git a/alz/local/variables.tf b/alz/local/variables.tf index 7915f3a..b2a9816 100644 --- a/alz/local/variables.tf +++ b/alz/local/variables.tf @@ -26,12 +26,28 @@ variable "root_parent_management_group_id" { default = "" } +variable "required_subscription_keys" { + description = <<-EOT + **(Optional, default: `["management", "connectivity"]`)** List of subscription keys that must be present with valid GUID values. + + Keys not in this list may have null or empty string values. + Valid keys: 'management', 'connectivity', 'identity', 'security' + EOT + type = list(string) + default = ["management", "connectivity"] + nullable = false + validation { + condition = alltrue([for key in var.required_subscription_keys : contains(["management", "connectivity", "identity", "security"], key)]) + error_message = "The required_subscription_keys must be one of 'management', 'connectivity', 'identity' or 'security'" + } +} + variable "subscription_ids" { description = <<-EOT **(Optional, default: `{}`)** Map of Azure subscription IDs where Platform Landing Zone resources will be deployed. Keys must be one of: 'management', 'connectivity', 'identity', 'security' - Values must be valid Azure subscription GUIDs. + Values must be valid Azure subscription GUIDs, or null/empty for non-required keys. Example: ``` @@ -45,16 +61,16 @@ variable "subscription_ids" { default = {} nullable = false validation { - condition = alltrue([for id in values(var.subscription_ids) : can(regex("^[0-9a-fA-F-]{36}$", id))]) - error_message = "All subscription IDs must be valid GUIDs" + condition = alltrue([for key, id in var.subscription_ids : contains(var.required_subscription_keys, key) ? can(regex("^[0-9a-fA-F-]{36}$", id)) : (id == null || id == "" || can(regex("^[0-9a-fA-F-]{36}$", id)))]) + error_message = "Required subscription IDs must be valid GUIDs. Optional subscription IDs must be valid GUIDs, null, or empty string." } validation { - condition = alltrue([for id in keys(var.subscription_ids) : contains(["management", "connectivity", "identity", "security"], id)]) + condition = alltrue([for key in keys(var.subscription_ids) : contains(["management", "connectivity", "identity", "security"], key)]) error_message = "The keys of the subscription_ids map must be one of 'management', 'connectivity', 'identity' or 'security'" } validation { - condition = contains(keys(var.subscription_ids), "management") && contains(keys(var.subscription_ids), "connectivity") - error_message = "You must provide subscription IDs for: 'management', and 'connectivity'" + condition = alltrue([for key in var.required_subscription_keys : contains(keys(var.subscription_ids), key)]) + error_message = "You must provide subscription IDs for all required subscription keys." } } From c233f4ea37dc47c363ee8b3643e28c54fcfaf72c Mon Sep 17 00:00:00 2001 From: Jared Holgate Date: Fri, 27 Mar 2026 19:07:17 +0000 Subject: [PATCH 3/3] refactor: remove unused azurerm_client_config data source --- modules/azure/data.tf | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/azure/data.tf b/modules/azure/data.tf index a8c0f35..d998357 100644 --- a/modules/azure/data.tf +++ b/modules/azure/data.tf @@ -1,5 +1,3 @@ -data "azurerm_client_config" "alz" {} - data "azurerm_subscription" "alz" { for_each = local.subscription_ids subscription_id = each.key