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 c20ab06..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]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$", 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") && contains(keys(var.subscription_ids), "identity") - error_message = "You must provide subscription IDs for: 'management', 'connectivity', and 'identity'" + 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 cbb1d92..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") && contains(keys(var.subscription_ids), "identity") - error_message = "You must provide subscription IDs for: 'management', 'connectivity', and 'identity'" + 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 fd1152c..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. + **(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") && contains(keys(var.subscription_ids), "identity") - error_message = "You must provide subscription IDs for: 'management', 'connectivity', and 'identity'" + 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/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