hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.46k stars 4.54k forks source link

Feature Request: Support for optionally providing `private_dns_zone_id` instead of `private_dns_zone_name` in `azurerm_private_dns_zone_virtual_network_link` #13503

Open eehret opened 2 years ago

eehret commented 2 years ago

Community Note

Description

I frequently have a need to create a VNET link between a VNET in one subscription and a Private DNS Zone in a different subscription using the azurerm provider. Simultaneously it is also required to allow the configuration to be dynamic such that this code could be put into a module and provided the necessary context information via configuration variables to create the needed linkages.

Currently, this appears not to be possible as far as I can tell; Right now the private_dns_zone_name argument is how one indicates which Private DNS Zone to create the link with, but there is no way to provide the subscription context dynamically.

I thought about specifying a different provider with an alias in order to provide the context of the private DNS zone but this appears to be problematic because we can't set providers dynamically, as I would need to in the case of a completely configuration-driven approach. The approach of setting a different provider for the azurerm_private_dns_zone_virtual_network_link is what was suggested in the referenced Github issue below. Unfortunately that approach doesn't work for my scenario.

New or Affected Resource(s)

Potential Terraform Configuration

I would like to propose that , similar to the way that the VNET context is provided using a full resource ID in the virtual_network_id , the same should be possible for the Private DNS Zone.
In order to provide some backward compatibility in the short term, perhaps two attributes can be supported: 1) The private_dns_zone_name. If used, behaviour would be as it is today - no change; 2) A new attribute in which one may provide the full resource ID of the Private DNS Zone. I would propose the name private_dns_zone_id. If used, the Private DNS Zone would be looked up using the full resource ID from whichever subscription it happens to be in

If both arguments above are used simultaneously, I think an error should be raised informing the user they should only use one of them. Perhaps at some point in the future, the original argument would become deprecated.

Potential new syntax:

resource "azurerm_resource_group" "example" {
  name     = "example-resources"
  location = "West Europe"
}

resource "azurerm_private_dns_zone" "example" {
  name                = "mydomain.com"
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_private_dns_zone_virtual_network_link" "example" {
  name                  = "test"
  resource_group_name   = azurerm_resource_group.example.name
  private_dns_zone_id = azurerm_private_dns_zone.example.id
  virtual_network_id    = azurerm_virtual_network.example.id
}

References

https://github.com/hashicorp/terraform-provider-azurerm/issues/5172

leriksen commented 2 years ago

You can do this from the perspective of the subscription the Private DNS zone is in, as the VNET is a fully qualified ID, with the other subscription in it.

resource "azurerm_private_dns_zone_virtual_network_link" "private_dns_zone_virtual_network_link" { name = "link_name" private_dns_zone_name = "zone_name" resource_group_name = "rg_the_dns_zone_is_in" virtual_network_id = "/subscriptions/XXXXX/resourceGroups/rrrr/..../vnet_id_in_other_subscription" }

eehret commented 2 years ago

@leriksen Thanks for the suggestion. Unfortunately this doesn't solve my particular problem. Using the approach you're suggesting would require there to be some way to pass in providers to the module in a dynamic way.

If you know this is possible, could you please illustrate how that would be done?

Thanks in advance :)

taylorpaul commented 1 week ago

I ran into this same problem when trying to use terraform to provision a private AKS cluster. The problem actually exists in a similar form when you try and do this using only az cli commands (which I did for my first private AKS cluster). I am including a somewhat hacky solution that works if you are already using az login for supplying credentials to terraform.

First, create a simple bash script that resides in the module you are building your private AKS cluster from that contains the following (pull-private-dns-zone-name.sh):

#!/bin/bash

# Take the cluster name as input, find the managed resource group ("MC_*<cluster_name>*"")
AKS_RESOURCE_GROUP_INFRA=$(az group list --query "[?contains(name, '$1')].name" -o tsv)

# Convert to lowercase for final az query below:
AKS_RESOURCE_GROUP_INFRA_LOWER=$(echo $AKS_RESOURCE_GROUP_INFRA | tr '[:upper:]' '[:lower:]' )

# Search for private DNS zone names within the above rg, pipe into proper JSON object (NOT JSON array)
az network private-dns zone list --query "[?resourceGroup=='$AKS_RESOURCE_GROUP_INFRA_LOWER'] | {name: @[0].name, resourceGroup: @[0].resourceGroup}" -o json

Then in the main.tf for your module establishing the cluster you can use hashicorp/external provider to call this script and return the required name for completing the pairing (main.tf):

data "external" "private_dns_zone_name"{
  program = [
    "./modules/tofu-aks-cluster-base/pull-private-dns-zone-name.sh", "${azurerm_kubernetes_cluster.private_aks.name}"
  ]

  # Have to wait until the cluster gets created:
  depends_on = [azurerm_kubernetes_cluster.private_aks]
}

# Create the link:
resource "azurerm_private_dns_zone_virtual_network_link" "dns_devvms_link" {
  ...
  resource_group_name   = data.external.private_dns_zone_name.result.resourceGroup 
  private_dns_zone_name = data.external.private_dns_zone_name.result.name
  ...

  lifecycle { # Have to add because data.external.private_dns_zone_name pulled each apply
    ignore_changes = [
        resource_group_name, private_dns_zone_name
    ]
  } 

  # Have to wait until the cluster gets created:
  depends_on = [azurerm_kubernetes_cluster.private_aks]
}

My google search brought me here, hoping this saves someone an hour or so trying to solve the same problem until azurerm_private_dns_zone_virtual_network_link supports private_dns_zone_id. Also, if there is a better way, I am all ears!