Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application Gateway with multiple request_routing_rule behaviour #13878

Open
mne-unitn opened this issue Oct 25, 2021 · 3 comments
Open

Application Gateway with multiple request_routing_rule behaviour #13878

mne-unitn opened this issue Oct 25, 2021 · 3 comments

Comments

@mne-unitn
Copy link

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform (and AzureRM Provider) Version

Terraform v1.0.8
provider registry.terraform.io/hashicorp/azurerm v2.82.0

Affected Resource(s)

  • azurerm_application_gateway

Terraform Configuration Files

resource "azurerm_resource_group" "rg" {
  name      = "rg-appgw-test"
  location  = "westeurope"
}

resource "azurerm_virtual_network" "myvnet" {
  name                = "test-vnet"
  resource_group_name = azurerm_resource_group.rg.name
  location            = "westeurope"
  address_space       = [ "10.255.0.0/23" ] 
}

resource "azurerm_subnet" "mysubnet" {
  name                 = "mysubnet-test-appgw"
  virtual_network_name = azurerm_virtual_network.myvnet.name
  resource_group_name  = azurerm_resource_group.rg.name

  address_prefixes = [ "10.255.0.0/24" ]
}

resource "azurerm_public_ip" "pip-appgw" {
  name                = "pip-myappgw-test"
  resource_group_name = azurerm_resource_group.rg.name
  location            = "westeurope"
  allocation_method   = "Static"
  sku                 = "Standard"
}

resource "azurerm_application_gateway" "myappgw" {
    location            = "westeurope"
    name                = "myappgw-test"
    resource_group_name = azurerm_resource_group.rg.name
    enable_http2        = true

    sku {
        name = "Standard_v2"
        tier = "Standard_v2"
        capacity = 1
    }
    frontend_ip_configuration {
        name                          = "MyAppGW-IP-Config"
        private_ip_address_allocation = "Dynamic"
        public_ip_address_id          = azurerm_public_ip.pip-appgw.id
    }
    frontend_port {
        name = "port_80"
        port = 80
    }
    frontend_port {
        name = "port_443"
        port = 443
    }
    gateway_ip_configuration {
        name = "myappgw-ip"
        subnet_id = azurerm_subnet.mysubnet.id
    }

    backend_address_pool {
        name = "TestPool1"
        ip_addresses = [ "1.2.3.4", "1.2.3.5" ]    
    }
    backend_address_pool {
        name ="TestPool2"
        ip_addresses = [ "2.3.4.5", "2.3.4.6" ]
    }
    backend_address_pool {
        name ="TestPool3"
        ip_addresses = [ "3.4.5.6", "3.4.5.7" ]
    }

    backend_http_settings {
        name = "Test-http-setting"
        affinity_cookie_name = "Test-affinity-1"
        cookie_based_affinity = "Enabled"
        port = 80
        protocol = "HTTP"
        request_timeout = 120
    }
    http_listener {
        name = "HttpListener1"
        frontend_ip_configuration_name = "MyAppGW-IP-Config"
        frontend_port_name = "port_80"
        protocol = "Http"
        host_name = "test1.com"
    }
    http_listener {
        name = "HttpListener2"
        frontend_ip_configuration_name = "MyAppGW-IP-Config"
        frontend_port_name = "port_80"
        protocol = "Http"
        host_name = "test2.com"
    }
    http_listener {
        name = "HttpListener3"
        frontend_ip_configuration_name = "MyAppGW-IP-Config"
        frontend_port_name = "port_80"
        protocol = "Http"
        host_name = "test3.com"
    }
    
    request_routing_rule {
        name = "RoutingRule1"
        rule_type = "Basic"
        http_listener_name = "HttpListener1"
        backend_address_pool_name = "TestPool1"
        backend_http_settings_name = "Test-http-setting"
    }
#    request_routing_rule {
#        name = "RoutingRule2"
#        rule_type = "Basic"
#        http_listener_name = "HttpListener2"
#        backend_address_pool_name = "TestPool2"
#        backend_http_settings_name = "Test-http-setting"
#    }
}

Debug Output

Panic Output

Expected Behaviour

When I enable the second request_routing_rule (the one commented out), I would expect terraform to just add that specific rule.

Actual Behaviour

When I enable the second request_routing_rule (the one commented out), terraform destroys all the request_routing_rules and recreates them.

Steps to Reproduce

  1. terraform apply
  2. uncomment the last rows with the second request_routing_rule
  3. terraform apply

Important Factoids

References

  • #0000
@aristosvo
Copy link
Collaborator

aristosvo commented Oct 25, 2021

Hi @mne-unitn, thanks for this issue. Do you experience this on a functional level as well?

To be honest, I think this might be a technical issue with the plan construction rather than that it's impacting the request_routing_rule itself (which already existed on Azure) and its behaviour. When the resource is updated, all rules are expanded for the Azure API at once, and send to the Azure API combined with all other settings. Azure takes care of the updates on the resource, and I expect that only the second rule is added and the first remains functional during that period.

To fix the plan, we'd have to make sure that the items are stored in state with an index value calculated by the hash of the attributes of the set which are retrieved upon a plan. I'm unsure whether and how we can make this work, but wanted to give you already a heads-up that it might not influence the behaviour with Azure.

@tombuildsstuff Do you think we'd be able to fix this, or are we limited by the Terraform core? I'm not familiar enough with the TypeSet to know on first sight if this is possible or not for a complicated schema like this:

"request_routing_rule": {
	Type:     pluginsdk.TypeSet,

	Required: true,
	MinItems: 1,
	Elem: &pluginsdk.Resource{
		Schema: map[string]*pluginsdk.Schema{
			"name": {
				Type:     pluginsdk.TypeString,
				Required: true,
			},

			"rule_type": {
				Type:     pluginsdk.TypeString,
				Required: true,
				ValidateFunc: validation.StringInSlice([]string{
					string(network.ApplicationGatewayRequestRoutingRuleTypeBasic),
					string(network.ApplicationGatewayRequestRoutingRuleTypePathBasedRouting),
				}, false),
			},

			"http_listener_name": {
				Type:     pluginsdk.TypeString,
				Required: true,
			},

			"backend_address_pool_name": {
				Type:     pluginsdk.TypeString,
				Optional: true,
			},

			"backend_http_settings_name": {
				Type:     pluginsdk.TypeString,
				Optional: true,
			},

			"url_path_map_name": {
				Type:     pluginsdk.TypeString,
				Optional: true,
			},

			"redirect_configuration_name": {
				Type:         pluginsdk.TypeString,
				Optional:     true,
				ValidateFunc: validation.StringIsNotEmpty,
			},

			"rewrite_rule_set_name": {
				Type:         pluginsdk.TypeString,
				Optional:     true,
				ValidateFunc: validation.StringIsNotEmpty,
			},

			"backend_address_pool_id": {
				Type:     pluginsdk.TypeString,
				Computed: true,
			},

			"backend_http_settings_id": {
				Type:     pluginsdk.TypeString,
				Computed: true,
			},

			"http_listener_id": {
				Type:     pluginsdk.TypeString,
				Computed: true,
			},

			"id": {
				Type:     pluginsdk.TypeString,
				Computed: true,
			},

			"url_path_map_id": {
				Type:     pluginsdk.TypeString,
				Computed: true,
			},

			"redirect_configuration_id": {
				Type:     pluginsdk.TypeString,
				Computed: true,
			},

			"rewrite_rule_set_id": {
				Type:     pluginsdk.TypeString,
				Computed: true,
			},
		},
	},
},

@mne-unitn
Copy link
Author

Hi @mne-unitn, thanks for this issue. Do you experience this on a functional level as well?

I think you are right. Looking at the logs on the Azure side, it seems the api recognizes the correct diff and applies only the different configuration parts.

thank you

@eissko
Copy link

eissko commented Jul 8, 2022

Hello @mne-unitn, @aristosvo please any update on this?

I know there are related issues and some statements there promised this being fixed with coming 3.x release which apparently didn't happen. The problem still persists with even newest AzureRM provider and terraform core.

It behaves as described here #16136

Type result
backend_address_pool ✔ works, only one change detected
backend_http_settings ❌ does NOT work, all settings deleted and readded
http_listener ❌ does NOT work, all settings deleted and readded
probe ✔ works, only one change detected
redirect_configuration ❌ does NOT work, all settings deleted and readded
request_routing_rule ❌ does NOT work, all settings deleted and readded
url_path_map ❌ does NOT work, all settings deleted and readded

Also related - #6896 (comment)

Thank you for any answer...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants