Search code examples
azureazure-devopsterraformterraform-provider-azure

Terraform forcing values to be null without being specified


I have used terraform prior without seeing this unexpected issues, every time I ran plan it says it will replace the resources, hence I added lifecycle to ignore all changes. When I let the plan to apply even though it states it will change the fqdn, ip addresses or guid to null it does not actually do it, but when i ran plan again after the apply finishes the same updates for resources shows. This is happening to other 10s of resources I have, and I am unable to figure out the reason.

Here is snippet of my managed instance config:

  #SQL MANAGED INSTANCE
resource "azurerm_mssql_managed_instance" "main" {
  name                = local.SQLInstanceName
  resource_group_name = var.RG.name
  location            = var.SQLMIInfo.Location



  identity {
    type = "SystemAssigned"
  }


  lifecycle {
    ignore_changes = all
  }

  license_type       = "BasePrice"
  subnet_id          = data.azurerm_subnet.SQL.id
  sku_name           = var.SQLMIInfo.Sku
  storage_size_in_gb = var.SQLMIInfo.StorageGB
  vcores             = var.SQLMIInfo.VCores
  storage_account_type = var.SQLMIInfo.StorageType

  collation = "Latin1_General_CI_AS"

  administrator_login          = var.Secrets.SQLMIAdminAccount
  administrator_login_password = "${data.azurerm_key_vault_secret.SQLAdmin.value}"

  public_data_endpoint_enabled = false

  depends_on = [
    null_resource.delegation,
  ]
}


data "azurerm_subnet" "endpoint" {
  name                 = "Hub-Private-Endpoint-Subnet"
  virtual_network_name = "${var.RGInfo.Env}-01-HUB-VNET"
  resource_group_name  = "RG-${var.RGInfo.Env}-01-HUB"
}


resource "azurerm_private_endpoint" "main" {
  name                = local.PrivateEndpointName
  location            = "West Europe"
  resource_group_name = var.RG.name
  subnet_id           = data.azurerm_subnet.endpoint.id
  custom_network_interface_name  = "${local.PrivateEndpointName}-nic"
  private_service_connection {
    name                           = local.PrivateEndpointName
    is_manual_connection           = false
    private_connection_resource_id = azurerm_mssql_managed_instance.main.id
    subresource_names = ["managedInstance"]
  }

  lifecycle {
    ignore_changes = all
  }
}

Here is the update it shows

# module.WE-DBOU.module.SQLInstances["we-sqlmi-gfndbou-imp-01"].azurerm_mssql_managed_instance.main must be replaced
-/+ resource "azurerm_mssql_managed_instance" "main" {
      ~ administrator_login_password   = (sensitive value)
      - dns_zone_partner_id            = "" -> null
      ~ fqdn                           = "pilot-08-we-sqlmi-gfndbou-imp-01.database.windows.net" -> (known after apply)
      ~ id                             = "/suensitive/resourceGroups/RG-PILOT-08-WE-DBOU/providers/Microsoft.Sql/managedInstances/pilot-08-we-sqlmi-gfndbou-imp-01" -> (known after apply)
        name                           = "pilot-08-we-sqlmi-gfndbou-imp-01"
      ~ subnet_id                      = "sensitive/resourceGroups/RG-PILOT-08-WE-DBOU/providers/Microsoft.Network/virtualNetworks/PILOT-08-WE-DBOU-VNET/subnets/we-sqlmi-gfndbou-imp-01-Subnet" -> (known after apply) # forces replacement
      - tags                           = {} -> null
        # (14 unchanged attributes hidden)

      ~ identity {
          ~ principal_id = "97a84a7b-8u3wu9u9u2-283u82uuu91u2991" -> (known after apply)
          ~ tenant_id    = "97a84a7b-8u3wu9u9u2-283u82uuu91u2991" -> (known after apply)
            # (1 unchanged attribute hidden)
        }
    }

  # module.WE-DBOU.module.SQLInstances["we-sqlmi-gfndbou-imp-01"].azurerm_private_dns_zone.db-dns will be updated in-place
  ~ resource "azurerm_private_dns_zone" "db-dns" {
        id                                                    = "/sensitive/resourceGroups/RG-PILOT-01-HUB/providers/Microsoft.Network/privateDnsZones/privatelink.database.windows.net"
      - max_number_of_record_sets                             = 25000 -> null
      - max_number_of_virtual_network_links                   = 1000 -> null
      - max_number_of_virtual_network_links_with_registration = 100 -> null
        name                                                  = "privatelink.database.windows.net"
      - number_of_record_sets                                 = 1 -> null
        tags                                                  = {}
        # (1 unchanged attribute hidden)

      ~ soa_record {
          - fqdn          = "privatelink.sensitive.database.windows.net." -> null
          - host_name     = "azureprivatedns.net" -> null
          - serial_number = 1 -> null
            tags          = {}
            # (6 unchanged attributes hidden)
        }
    }

  # module.WE-DBOU.module.SQLInstances["we-sqlmi-gfndbou-imp-01"].azurerm_private_endpoint.main must be replaced
-/+ resource "azurerm_private_endpoint" "main" {
      ~ custom_dns_configs            = [
          - {
              - fqdn         = "pilot-08-we-sqlmi-gfndbou-imp-01.database.windows.net"
              - ip_addresses = [
                  - "10.40.6.9",
                ]
            },
        ] -> (known after apply)
      ~ id                            = "/sensitive/sensitive/resourceGroups/RG-PILOT-08-WE-DBOU/providers/Microsoft.Network/privateEndpoints/pilot-08-we-dbou-import-01" -> (known after apply)
        name                          = "pilot-08-we-dbou-import-01"
      ~ network_interface             = [
          - {
              - id   = "/sensitive/sensitive/resourceGroups/RG-PILOT-08-WE-DBOU/providers/Microsoft.Network/networkInterfaces/pilot-08-we-dbou-import-01-nic"
              - name = "pilot-08-we-dbou-import-01-nic"
            },
        ] -> (known after apply)
      ~ private_dns_zone_configs      = [] -> (known after apply)
      ~ subnet_id                     = "/sensitive/sensitive/resourceGroups/RG-PILOT-01-HUB/providers/Microsoft.Network/virtualNetworks/PILOT-01-HUB-VNET/subnets/Hub-Private-Endpoint-Subnet" -> (known after apply) # forces replacement
      - tags                          = {} -> null
        # (3 unchanged attributes hidden)

      ~ private_service_connection {
            name                           = "pilot-08-we-dbou-import-01"
          ~ private_connection_resource_id = "/sensitive/sensitive/resourceGroups/RG-PILOT-08-WE-DBOU/providers/Microsoft.Sql/managedInstances/pilot-08-we-sqlmi-gfndbou-imp-01" -> (known after apply) # forces replacement
          ~ private_ip_address             = "10.40.6.9" -> (known after apply)
            # (2 unchanged attributes hidden)
        }
    }

Hopefully, it makes sense, I have been stuck on this for days and looked every where but could not find anything, feel free to ask if more details required


Solution

  • Terraform detects that the state of the resources in your configuration does not match the state of the resources in Azure when you run terraform plan again.

    ignore_changes = all is not recommended for few terraform resources. Instead of using ignore_changes, use prevent_destroy = true to prevent deletion while running terraform plan & apply.

    terraform state can also be used to check the current state of resources and compare it to the desired state in terraform configuration.

    lifecycle
      { 
          prevent_destroy =  true 
      }
    

    This will keep Terraform from destroying the resource when updating.

    enter image description here

    I tried the same in my environment and terraform plan worked as expected.

    enter image description here