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.52k stars 4.6k forks source link

azurerm_subnet_route_table_association wants to destroy and recreate on subsequent 'apply' #20678

Open eehret opened 1 year ago

eehret commented 1 year ago

Is there an existing issue for this?

Community Note

Terraform Version

1.3.7

AzureRM Provider Version

3.45.0

Affected Resource(s)/Data Source(s)

azurerm_subnet_route_table_association

Terraform Configuration Files

### Note that in my tenant the existing route table in azure has a mixed-case resource group name
data "azurerm_route_table" "route_table" {
  name                = "myRouteTable"
  resource_group_name = "myResourceGroup"
}

resource "azurerm_virtual_network" "vnet" {
  name                = "myVnet"
  resource_group_name = "myResourceGroup"
  address_space       = ["10.0.0.0/8"]
  location            = "CanadaCentral"
}

resource "azurerm_subnet" "sn_smax_pgsql" {
  name                 = "sn-pgsql-subnet"
  resource_group_name  = "myResourceGroup"
  virtual_network_name = "myVnet"
  address_prefixes     = ["10.0.0.0/24"]

  delegation {
    name = "Microsoft.DBforPostgreSQL.flexibleServers"

    service_delegation {
      name    = "Microsoft.DBforPostgreSQL/flexibleServers"
      actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
    }
  }

  private_endpoint_network_policies_enabled = true
}

### Note that after creation, the route_table_id in the state becomes all lowercase, leading to the destroy and recreate issue
resource "azurerm_subnet_route_table_association" "snrt_pgsql" {
  route_table_id = data.azurerm_route_table.route_table.id
  subnet_id      = azurerm_subnet.sn_smax_pgsql.id
}

Debug Output/Panic Output

n/a

Expected Behaviour

azurerm_subnet_route_table_association gets created successfully.

Attempting another subsequent terraform apply without making any change to the configuration does not result in Terraform suggesting to destroy and recreate the resource.

Actual Behaviour

Terraform is noticing the discrepancy in the resource group name of the azurerm_route_table and thinks that a destroy and recreate of the azurerm_subnet_route_table_association is required.

Note my comments above in the example code. Terraform is doing this because of a discrepancy in the case of the resource group of the route table resource.

Steps to Reproduce

  1. terraform apply
  2. terraform apply

Important Factoids

No response

References

No response

neil-yechenwei commented 1 year ago

Thanks for raising this issue. Seems I cannot repro this issue with below tf config that is similar with yours. Could you double check if the resource group name has been changed on the outside of TF?

tf config:

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "test" {
  name     = "myResourceGroup"
  location = "CanadaCentral"
}

resource "azurerm_route_table" "test" {
  name                = "myRouteTable"
  location            = azurerm_resource_group.test.location
  resource_group_name = azurerm_resource_group.test.name

  route {
    name                   = "first"
    address_prefix         = "10.100.0.0/14"
    next_hop_type          = "VirtualAppliance"
    next_hop_in_ip_address = "10.10.1.1"
  }
}

data "azurerm_route_table" "test" {
  name                = azurerm_route_table.test.name
  resource_group_name = azurerm_resource_group.test.name
}

resource "azurerm_virtual_network" "test" {
  name                = "myVnet-test01"
  resource_group_name = azurerm_resource_group.test.name
  location            = azurerm_resource_group.test.location
  address_space       = ["10.0.0.0/8"]
}

resource "azurerm_subnet" "test" {
  name                 = "mysubnet-test01"
  resource_group_name  = azurerm_resource_group.test.name
  virtual_network_name = azurerm_virtual_network.test.name
  address_prefixes     = ["10.0.0.0/24"]

  delegation {
    name = "Microsoft.DBforPostgreSQL.flexibleServers"

    service_delegation {
      name    = "Microsoft.DBforPostgreSQL/flexibleServers"
      actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
    }
  }

  private_endpoint_network_policies_enabled = true
}

resource "azurerm_subnet_route_table_association" "test" {
  route_table_id = data.azurerm_route_table.test.id
  subnet_id      = azurerm_subnet.test.id
}

image

eehret commented 1 year ago

@neil-yechenwei Yes. In order to observe this issue you need to have a route table with a resource ID that is being returned as mixed-case by the data provider. If terraform always converted resource IDs to lowercase, this problem would not happen.

eehret commented 1 year ago

Additional information:

If I look at the route table in Azure portal, its resource ID is all lowercase. However, if I look at the Terraform state for the exact same route table , when fetched by the data provider (e.g. data "azurerm_route_table" "route_table") , the resource ID shown in that state is mixed-case.

So it appears that while Azure itself is happy to present the resource ID as all lowercase, for some reason Terraform sometimes presents it in mixed case. But not always. The discrepancy leads to the problem reported in this issue.

neiser commented 1 year ago

@eehret Thanks for raising this issue. Our team recently came across the same bug (unnecessary re-creation of azurerm_subnet_route_table_association) and your analysis is spot-on!

@neil-yechenwei The Azure documentation states:

When using various APIs to retrieve the name for a resource or resource group, the returned value may have different casing than what you originally specified for the name. The returned value may even display different case values than what is listed in the valid characters table.

Always perform a case-insensitive comparison of names.

In #5455 and #1386 your colleague @tombuildsstuff already explained that there's no simple fix tackling all issues consistently. But maybe in the case for azurerm_subnet_route_table_association, this spot could be changed to become case-insensitive?

Also #20138 seems related (no comment from your side yet)

I'd appreciate some effort from your side to fix this at least partially (so far, issues addressing this seem to be just closed or stale) or at least document a warning to all resources that one should create all resources within azurerm_ with lower-case letters only. The current situation is unfortunately quite undesirable in my opinion, as we unfortunately were not aware of this and now have resources with lower- and upper-case letters, and there seems no way to fix this except a change in this provider.

Let me know if you need any further information.

twexler commented 1 year ago

Also https://github.com/hashicorp/terraform-provider-azurerm/issues/20138 seems related (no comment from your side yet)

Reporter of #20138 here. @eehret's experience directly matches ours. This doesn't happen only on azurerm_subnet_route_table_associations either, we've also observed it with azurerm_network_security_group, and azurerm_network_security_rule as well.

It would be awesome if this could be addressed, as it effects us pretty commonly in at least one of our resource groups.

jlogel90 commented 1 year ago

I ran into the same error today.

Terraform 1.3.9 Azurerm 3.55.0

I used practically same code as documentation example here

I noticed that when I use route_table_id = azurerm_route_table.example.id terraform sent back a "/" at the end of the id but route table Ressource ID (and probably for all Azure resources) doesn't finish with a "/" in properties in Azure Portal

Hope it will help.