From d0c2f949245bb4a5f314c3f4ee60ec6b59ee7d18 Mon Sep 17 00:00:00 2001 From: Gonzalo Rojas Date: Tue, 26 May 2026 12:04:07 -0300 Subject: [PATCH] feat(external_dns): support azure-private-dns provider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Accepts dns_provider_name = "azure-private-dns" in addition to "azure". Both providers share the same auth, secret mount, and ServiceAccount wiring — only external-dns chart's `provider.name` differs — so the azure_config block now templates the provider name from the input and provider_configs maps both keys to the same config. Validation preconditions and the kubernetes_secret_v1 count condition were extended from `dns_provider_name == "azure"` to a shared `azure_family_active` local that matches both providers. Unblocks callers managing Azure Private DNS zones (Microsoft.Network/ privateDnsZones), which the upstream external-dns binary handles via a separate provider name from the public DNS one. Previously such callers had to maintain their own helm_release block. --- infrastructure/commons/external_dns/locals.tf | 16 +++++++++---- infrastructure/commons/external_dns/secret.tf | 2 +- .../commons/external_dns/validation.tf | 24 +++++++++---------- .../commons/external_dns/variables.tf | 6 ++--- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/infrastructure/commons/external_dns/locals.tf b/infrastructure/commons/external_dns/locals.tf index 3081d79b..d08d162f 100644 --- a/infrastructure/commons/external_dns/locals.tf +++ b/infrastructure/commons/external_dns/locals.tf @@ -88,8 +88,13 @@ locals { ] } + # Both `azure` (Public DNS zones) and `azure-private-dns` (Private DNS zones) + # share the same auth, secret mount, and ServiceAccount wiring — only the + # external-dns `provider.name` differs. + azure_family_active = contains(["azure", "azure-private-dns"], var.dns_provider_name) + azure_config = { - provider = { name = "azure" } + provider = { name = var.dns_provider_name } serviceAccount = { create = true annotations = var.azure_workload_identity_enabled ? { @@ -117,10 +122,11 @@ locals { } provider_configs = { - cloudflare = local.cloudflare_config - aws = local.route53_config - oci = local.oci_config - azure = local.azure_config + cloudflare = local.cloudflare_config + aws = local.route53_config + oci = local.oci_config + azure = local.azure_config + "azure-private-dns" = local.azure_config } external_dns_values = merge(local.base_config, local.provider_configs[var.dns_provider_name]) diff --git a/infrastructure/commons/external_dns/secret.tf b/infrastructure/commons/external_dns/secret.tf index 934437e3..fca27cbd 100644 --- a/infrastructure/commons/external_dns/secret.tf +++ b/infrastructure/commons/external_dns/secret.tf @@ -11,7 +11,7 @@ resource "kubernetes_secret_v1" "external_dns_cloudflare" { } resource "kubernetes_secret_v1" "external_dns_azure_config" { - count = var.dns_provider_name == "azure" ? 1 : 0 + count = local.azure_family_active ? 1 : 0 metadata { name = "external-dns-azure-config" diff --git a/infrastructure/commons/external_dns/validation.tf b/infrastructure/commons/external_dns/validation.tf index d34cf990..405af91d 100644 --- a/infrastructure/commons/external_dns/validation.tf +++ b/infrastructure/commons/external_dns/validation.tf @@ -29,28 +29,28 @@ resource "terraform_data" "provider_validation" { error_message = "oci_region is required when dns_provider_name is 'oci'." } precondition { - condition = var.dns_provider_name != "azure" || length(var.azure_client_id) > 0 - error_message = "azure_client_id is required when dns_provider_name is 'azure'." + condition = !local.azure_family_active || length(var.azure_client_id) > 0 + error_message = "azure_client_id is required when dns_provider_name is 'azure' or 'azure-private-dns'." } precondition { - condition = var.dns_provider_name != "azure" || !var.azure_workload_identity_enabled || length(var.azure_federated_credential_id) > 0 - error_message = "azure_federated_credential_id is required when dns_provider_name is 'azure' and azure_workload_identity_enabled is true. Use module.iam to create the federated identity credential and pass its id output." + condition = !local.azure_family_active || !var.azure_workload_identity_enabled || length(var.azure_federated_credential_id) > 0 + error_message = "azure_federated_credential_id is required when dns_provider_name is 'azure' or 'azure-private-dns' and azure_workload_identity_enabled is true. Use module.iam to create the federated identity credential and pass its id output." } precondition { - condition = var.dns_provider_name != "azure" || var.azure_workload_identity_enabled || length(var.azure_client_secret) > 0 - error_message = "azure_client_secret is required when dns_provider_name is 'azure' and azure_workload_identity_enabled is false." + condition = !local.azure_family_active || var.azure_workload_identity_enabled || length(var.azure_client_secret) > 0 + error_message = "azure_client_secret is required when dns_provider_name is 'azure' or 'azure-private-dns' and azure_workload_identity_enabled is false." } precondition { - condition = var.dns_provider_name != "azure" || length(var.azure_subscription_id) > 0 - error_message = "azure_subscription_id is required when dns_provider_name is 'azure'." + condition = !local.azure_family_active || length(var.azure_subscription_id) > 0 + error_message = "azure_subscription_id is required when dns_provider_name is 'azure' or 'azure-private-dns'." } precondition { - condition = var.dns_provider_name != "azure" || length(var.azure_resource_group) > 0 - error_message = "azure_resource_group is required when dns_provider_name is 'azure'." + condition = !local.azure_family_active || length(var.azure_resource_group) > 0 + error_message = "azure_resource_group is required when dns_provider_name is 'azure' or 'azure-private-dns'." } precondition { - condition = var.dns_provider_name != "azure" || length(var.azure_tenant_id) > 0 - error_message = "azure_tenant_id is required when dns_provider_name is 'azure'." + condition = !local.azure_family_active || length(var.azure_tenant_id) > 0 + error_message = "azure_tenant_id is required when dns_provider_name is 'azure' or 'azure-private-dns'." } } } diff --git a/infrastructure/commons/external_dns/variables.tf b/infrastructure/commons/external_dns/variables.tf index f89f113c..7fbaceb3 100644 --- a/infrastructure/commons/external_dns/variables.tf +++ b/infrastructure/commons/external_dns/variables.tf @@ -141,10 +141,10 @@ variable "oci_zones_cache_duration" { variable "dns_provider_name" { type = string - description = "The DNS provider to use with ExternalDNS " + description = "The DNS provider to use with ExternalDNS. Use 'azure' for Azure Public DNS zones and 'azure-private-dns' for Azure Private DNS zones — both share the same auth, secret, and ServiceAccount wiring." validation { - condition = contains(["cloudflare", "aws", "oci", "azure"], var.dns_provider_name) - error_message = "dns_provider_name must be either 'cloudflare', 'aws', 'oci', or 'azure'." + condition = contains(["cloudflare", "aws", "oci", "azure", "azure-private-dns"], var.dns_provider_name) + error_message = "dns_provider_name must be one of: 'cloudflare', 'aws', 'oci', 'azure', 'azure-private-dns'." } }