terraform-provider-azurerm: Azure FrontDoor : Caching issue - Unexpected resource modifying

Terraform (and AzureRM Provider) Version

terraform -v
Terraform v0.12.9
+ provider.azurerm v1.34.0

Affected Resource(s)

  • azurerm_frontdoor

Terraform Configuration Files

- module – frontdoor

- – main.tf

// Manage Azure FrontDoor
resource "azurerm_frontdoor" "traffic_gateway" {
  name                                         = local.frontdoor_name
  friendly_name                                = local.frontdoor_name
  location                                     = var.location
  resource_group_name                          = var.resource_group
  enforce_backend_pools_certificate_name_check = var.backend_certificate_check # false

  routing_rule {
      name                    = var.routing_rule_name
      accepted_protocols      = ["Https"]
      patterns_to_match       = ["/*"]
      frontend_endpoints      = [var.frontend_endpoint_name]
      forwarding_configuration {
        forwarding_protocol   = var.forwarding_protocol
        backend_pool_name     = var.backend_pool_name
      }
  }

  backend_pool_load_balancing {
    name                            = var.balancing_name
    sample_size                     = local.backand_balancer.sample_size
    successful_samples_required     = local.backand_balancer.successful_samples_required
    additional_latency_milliseconds = local.backend_balancer.additional_latency_milliseconds
  }

  backend_pool_health_probe {
    name                  = var.liveness_probe_name
    path                  = var.healthcheck_api_path
    interval_in_seconds   = 255
    protocol              = "Https"
  }

  backend_pool {
      name            = var.backend_pool_name
      backend {
          host_header = "${var.backend_name}.azure-api.net"
          address     = "${var.backend_name}.azure-api.net"
          http_port   = 80
          https_port  = 443
      }

      load_balancing_name = var.balancing_name
      health_probe_name   = var.liveness_probe_name
  }

  frontend_endpoint {
    name                                      = var.frontend_endpoint_name
    host_name                                 = var.backend_host_name
    web_application_firewall_policy_link_id   = var.waf_enabled != false ? azurerm_frontdoor_firewall_policy.waf_assigned_policy[0].id : null
    custom_https_provisioning_enabled         = false
  }

  tags = {
    environment = var.environment_prefix
  }
}

// Manage FrontDoor firewall policy
resource "azurerm_frontdoor_firewall_policy" "waf_assigned_policy" {

Expected Behavior

terraform plan 
OR 
terraform apply

TERRAFORM SHOULD NOTIFY ABOUT ANY CHANGES

Actual Behavior

terraform plan
OR
terraform apply
  • Operation result: “Apply complete! Resources: 0 added, 0 changed, 0 destroyed.”
  • UNEXPECTED ACTION: TERRAFORM SILENTLY UPDATED FRONTDOOR WITH ENABLED CACHING

Steps to Reproduce

  1. terraform import azurerm_frontdoor.traffic_gateway /subscriptions/...

  2. terraform apply

  3. Check Caching option on frontDoor servire [Azure Portal]

Important Factoids

References

https://docs.microsoft.com/en-us/azure/frontdoor/front-door-caching

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 15
  • Comments: 20 (2 by maintainers)

Commits related to this issue

Most upvoted comments

Looking closer at this I see what the real issue is, I have opened the above PR to fix this issue completly.

@devblackops, looking at this closer I am going to implement your suggestion of exposing a cache_enabled feild. This issue is caused by the API overloading the cache_use_dynamic_compression field to be a value and a conditional. If the cache_use_dynamic_compression is set to false the REST API expects the caller to not pass any of the cache values, but if it is set to true then the other cache values are then required. By implementing your suggestion this will make the fix easier and will not introduce a breaking change.

forwarding_configuration {
  forwarding_protocol = "MatchRequest"
  backend_pool_name   = "backend"

  cache_enabled                         = true
  cache_query_parameter_strip_directive = "StripAll"
  cache_use_dynamic_compression         = true  
}

I agree. We should be able to control caching directly. I think it would make sense to have a cache_enabled property. If that was set to true, then cache_query_parameter_strip_directive and cache_use_dynamic_compression would be optional. If cache_enabled is false, the other properties become invalid.

forwarding_configuration {
  forwarding_protocol = "MatchRequest"
  backend_pool_name   = "backend"

  cache_enabled                         = true
  cache_query_parameter_strip_directive = "StripAll"
  cache_use_dynamic_compression         = true  
}

Ignoring changes on the routing rule isn’t working for me. It still enables caching. This is my config:

resource "azurerm_frontdoor" "fd" {
  name                = "${var.prefix}-fd1"
  friendly_name       = "${var.prefix}-fd1"
  location            = var.location
  resource_group_name = var.resource_group_name
  tags                = var.tags

  routing_rule {
    name               = "routing-rule"
    accepted_protocols = ["Http", "Https"]
    patterns_to_match  = ["/*"]
    frontend_endpoints = [
      "custom-name"
    ]

    forwarding_configuration {
      forwarding_protocol = "MatchRequest"
      backend_pool_name   = "backend"
    }
  }

  enforce_backend_pools_certificate_name_check = true

  backend_pool_load_balancing {
    name = "loadbalancing-settings"
  }

  backend_pool_health_probe {
    name                = "health-probe"
    path                = "/_azure/hadr/ping?key=xxxxxx"
    protocol            = "Https"
    interval_in_seconds = 30
  }

  backend_pool {
    name = "backend"
    backend {
      host_header = var.site_fqdn
      address     = var.appgw_fqdn
      http_port   = 80
      https_port  = 443
    }

    load_balancing_name = "loadbalancing-settings"
    health_probe_name   = "health-probe"
  }

  frontend_endpoint {
    name                              = "custom-name"
    host_name                         = var.site_fqdn
    custom_https_provisioning_enabled = true

    custom_https_configuration {
      certificate_source                         = "AzureKeyVault"
      azure_key_vault_certificate_vault_id       = var.certificate_keyvault_id
      azure_key_vault_certificate_secret_name    = var.certificate_keyvault_secret_name
      azure_key_vault_certificate_secret_version = var.certificate_keyvault_secret_version
    }
  }

  lifecycle {
    ignore_changes = [
      "routing_rule[0].forwarding_configuration[0].cache_query_parameter_strip_directive"
    ]
  }
}

That’s the worst thing. As far as I understand the resource isn’t added in a state file yet, that’s why the lifecycle rule isn’t working.

In this case, there 2 crutches ways to solve the issue.

  1. Add lifecycle rule to FrontDoor configuration:
lifecycle {
  ignore_changes = [
    routing_rule
  ]
}

BTW: just try to plan your configuration after that, 50% it can solve the issue, if not: 2) You should apply your configuration first, and disable caching manually in Azure Portal. It shouldn’t modify the resource then. 3) Add the resource to your state file and try to terraform plan

I also want to admit that since FrontDoor exist in state file and caching block ignored, terraform shouldn’t enable it even if you change FrontDoor configuration (any other configuration setting)

I can’t get this to work either. Tried variations of ignore_changes but each time Terraform runs it re-enables the caching, which is the only change I make over in Azure. I’ve included the plan of what Terraform suggests the changes will be, but like I said the only actual change is caching gets turned back on after manually being turned off.

At the very least the default should be cache off, as per creating it through the portal. But better yet the ability to control whether it’s on or off rather than just it’s settings.

I’m running azurerm 1.37.0

   ~ routing_rule {
            accepted_protocols = [
                "Https",
            ]
            enabled            = true
          ~ frontend_endpoints = [
                "azureEndpoint",
              - "",
              + "customEndpoint",
            ]
            id                 = "/subscriptions/.../RoutingRules/defaultForwardingRoute"
            name               = "defaultForwardingRoute"
            patterns_to_match  = [
                "/*",
            ]

            forwarding_configuration {
                backend_pool_name                     = "appService"
                cache_query_parameter_strip_directive = "StripAll"
                cache_use_dynamic_compression         = true
                forwarding_protocol                   = "HttpsOnly"
            }
        }

Ignoring changes on the routing rule isn’t working for me. It still enables caching. This is my config:

resource "azurerm_frontdoor" "fd" {
  name                = "${var.prefix}-fd1"
  friendly_name       = "${var.prefix}-fd1"
  location            = var.location
  resource_group_name = var.resource_group_name
  tags                = var.tags

  routing_rule {
    name               = "routing-rule"
    accepted_protocols = ["Http", "Https"]
    patterns_to_match  = ["/*"]
    frontend_endpoints = [
      "custom-name"
    ]

    forwarding_configuration {
      forwarding_protocol = "MatchRequest"
      backend_pool_name   = "backend"
    }
  }

  enforce_backend_pools_certificate_name_check = true

  backend_pool_load_balancing {
    name = "loadbalancing-settings"
  }

  backend_pool_health_probe {
    name                = "health-probe"
    path                = "/_azure/hadr/ping?key=xxxxxx"
    protocol            = "Https"
    interval_in_seconds = 30
  }

  backend_pool {
    name = "backend"
    backend {
      host_header = var.site_fqdn
      address     = var.appgw_fqdn
      http_port   = 80
      https_port  = 443
    }

    load_balancing_name = "loadbalancing-settings"
    health_probe_name   = "health-probe"
  }

  frontend_endpoint {
    name                              = "custom-name"
    host_name                         = var.site_fqdn
    custom_https_provisioning_enabled = true

    custom_https_configuration {
      certificate_source                         = "AzureKeyVault"
      azure_key_vault_certificate_vault_id       = var.certificate_keyvault_id
      azure_key_vault_certificate_secret_name    = var.certificate_keyvault_secret_name
      azure_key_vault_certificate_secret_version = var.certificate_keyvault_secret_version
    }
  }

  lifecycle {
    ignore_changes = [
      "routing_rule[0].forwarding_configuration[0].cache_query_parameter_strip_directive"
    ]
  }
}