Skip to content

Commit

Permalink
add support for pick-hostname behaviours (#2658)
Browse files Browse the repository at this point in the history
Hi. Am unsure re policy/naming issues. Figured i'd submit PR and declare up-front that i'm happy to follow any helpful feedback and/or let someone else take it over the line. cheers.
  • Loading branch information
mdsills authored and katbyte committed Jan 18, 2019
1 parent 2bd0ce0 commit 2f58e4d
Show file tree
Hide file tree
Showing 3 changed files with 260 additions and 13 deletions.
61 changes: 49 additions & 12 deletions azurerm/resource_arm_application_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ func resourceArmApplicationGateway() *schema.Resource {
}, true),
},

"pick_host_name_from_backend_address": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},

"request_timeout": {
Type: schema.TypeInt,
Optional: true,
Expand Down Expand Up @@ -499,7 +505,7 @@ func resourceArmApplicationGateway() *schema.Resource {

"host": {
Type: schema.TypeString,
Required: true,
Optional: true,
},

"interval": {
Expand All @@ -517,6 +523,12 @@ func resourceArmApplicationGateway() *schema.Resource {
Required: true,
},

"pick_host_name_from_backend_http_settings": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},

"minimum_servers": {
Type: schema.TypeInt,
Optional: true,
Expand Down Expand Up @@ -789,6 +801,20 @@ func resourceArmApplicationGatewayCreateUpdate(d *schema.ResourceData, meta inte
},
}

for _, probe := range *probes {
probeProperties := *probe.ApplicationGatewayProbePropertiesFormat
host := *probeProperties.Host
pick := *probeProperties.PickHostNameFromBackendHTTPSettings

if host == "" && !pick {
return fmt.Errorf("One of `host` or `pick_host_name_from_backend_http_settings` must be set")
}

if host != "" && pick {
return fmt.Errorf("Only one of `host` or `pick_host_name_from_backend_http_settings` can be set")
}
}

if _, ok := d.GetOk("waf_configuration"); ok {
gateway.ApplicationGatewayPropertiesFormat.WebApplicationFirewallConfiguration = expandApplicationGatewayWafConfig(d)
}
Expand Down Expand Up @@ -1092,15 +1118,17 @@ func expandApplicationGatewayBackendHTTPSettings(d *schema.ResourceData, gateway
port := int32(v["port"].(int))
protocol := v["protocol"].(string)
cookieBasedAffinity := v["cookie_based_affinity"].(string)
pickHostNameFromBackendAddress := v["pick_host_name_from_backend_address"].(bool)
requestTimeout := int32(v["request_timeout"].(int))

setting := network.ApplicationGatewayBackendHTTPSettings{
Name: &name,
ApplicationGatewayBackendHTTPSettingsPropertiesFormat: &network.ApplicationGatewayBackendHTTPSettingsPropertiesFormat{
CookieBasedAffinity: network.ApplicationGatewayCookieBasedAffinity(cookieBasedAffinity),
Port: utils.Int32(port),
Protocol: network.ApplicationGatewayProtocol(protocol),
RequestTimeout: utils.Int32(requestTimeout),
CookieBasedAffinity: network.ApplicationGatewayCookieBasedAffinity(cookieBasedAffinity),
PickHostNameFromBackendAddress: utils.Bool(pickHostNameFromBackendAddress),
Port: utils.Int32(port),
Protocol: network.ApplicationGatewayProtocol(protocol),
RequestTimeout: utils.Int32(requestTimeout),
},
}

Expand Down Expand Up @@ -1158,6 +1186,9 @@ func flattenApplicationGatewayBackendHTTPSettings(input *[]network.ApplicationGa
if port := props.Port; port != nil {
output["port"] = int(*port)
}
if pickHostNameFromBackendAddress := props.PickHostNameFromBackendAddress; pickHostNameFromBackendAddress != nil {
output["pick_host_name_from_backend_address"] = *pickHostNameFromBackendAddress
}
output["protocol"] = string(props.Protocol)
if timeout := props.RequestTimeout; timeout != nil {
output["request_timeout"] = int(*timeout)
Expand Down Expand Up @@ -1549,17 +1580,19 @@ func expandApplicationGatewayProbes(d *schema.ResourceData) *[]network.Applicati
protocol := v["protocol"].(string)
timeout := int32(v["timeout"].(int))
unhealthyThreshold := int32(v["unhealthy_threshold"].(int))
pickHostNameFromBackendHTTPSettings := v["pick_host_name_from_backend_http_settings"].(bool)

output := network.ApplicationGatewayProbe{
Name: utils.String(name),
ApplicationGatewayProbePropertiesFormat: &network.ApplicationGatewayProbePropertiesFormat{
Host: utils.String(host),
Interval: utils.Int32(interval),
MinServers: utils.Int32(minServers),
Path: utils.String(probePath),
Protocol: network.ApplicationGatewayProtocol(protocol),
Timeout: utils.Int32(timeout),
UnhealthyThreshold: utils.Int32(unhealthyThreshold),
Host: utils.String(host),
Interval: utils.Int32(interval),
MinServers: utils.Int32(minServers),
Path: utils.String(probePath),
Protocol: network.ApplicationGatewayProtocol(protocol),
Timeout: utils.Int32(timeout),
UnhealthyThreshold: utils.Int32(unhealthyThreshold),
PickHostNameFromBackendHTTPSettings: utils.Bool(pickHostNameFromBackendHTTPSettings),
},
}

Expand Down Expand Up @@ -1625,6 +1658,10 @@ func flattenApplicationGatewayProbes(input *[]network.ApplicationGatewayProbe) [
output["unhealthy_threshold"] = int(*threshold)
}

if pickHostNameFromBackendHTTPSettings := props.PickHostNameFromBackendHTTPSettings; pickHostNameFromBackendHTTPSettings != nil {
output["pick_host_name_from_backend_http_settings"] = *pickHostNameFromBackendHTTPSettings
}

if minServers := props.MinServers; minServers != nil {
output["minimum_servers"] = int(*minServers)
}
Expand Down
206 changes: 206 additions & 0 deletions azurerm/resource_arm_application_gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,56 @@ func TestAccAzureRMApplicationGateway_probes(t *testing.T) {
})
}

func TestAccAzureRMApplicationGateway_probesPickHostNameFromBackendHTTPSettings(t *testing.T) {
resourceName := "azurerm_application_gateway.test"
ri := tf.AccRandTimeInt()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMApplicationGatewayDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMApplicationGateway_probesPickHostNameFromBackendHTTPSettings(ri, testLocation()),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMApplicationGatewayExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "probe.0.pick_host_name_from_backend_http_settings", "true"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAzureRMApplicationGateway_settingsPickHostNameFromBackendAddress(t *testing.T) {
resourceName := "azurerm_application_gateway.test"
ri := tf.AccRandTimeInt()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMApplicationGatewayDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMApplicationGateway_settingsPickHostNameFromBackendAddress(ri, testLocation()),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMApplicationGatewayExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "backend_http_settings.0.pick_host_name_from_backend_address", "true"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAzureRMApplicationGateway_sslCertificate(t *testing.T) {
resourceName := "azurerm_application_gateway.test"
ri := tf.AccRandTimeInt()
Expand Down Expand Up @@ -837,6 +887,162 @@ resource "azurerm_application_gateway" "test" {
`, template, rInt)
}

func testAccAzureRMApplicationGateway_probesPickHostNameFromBackendHTTPSettings(rInt int, location string) string {
template := testAccAzureRMApplicationGateway_template(rInt, location)
return fmt.Sprintf(`
%s
# since these variables are re-used - a locals block makes this more maintainable
locals {
backend_address_pool_name = "${azurerm_virtual_network.test.name}-beap"
frontend_port_name = "${azurerm_virtual_network.test.name}-feport"
frontend_ip_configuration_name = "${azurerm_virtual_network.test.name}-feip"
http_setting_name = "${azurerm_virtual_network.test.name}-be-htst"
listener_name = "${azurerm_virtual_network.test.name}-httplstn"
probe_name = "${azurerm_virtual_network.test.name}-probe"
request_routing_rule_name = "${azurerm_virtual_network.test.name}-rqrt"
}
resource "azurerm_application_gateway" "test" {
name = "acctestag-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
sku {
name = "Standard_Small"
tier = "Standard"
capacity = 2
}
gateway_ip_configuration {
name = "my-gateway-ip-configuration"
subnet_id = "${azurerm_subnet.test.id}"
}
frontend_port {
name = "${local.frontend_port_name}"
port = 80
}
frontend_ip_configuration {
name = "${local.frontend_ip_configuration_name}"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
backend_address_pool {
name = "${local.backend_address_pool_name}"
}
backend_http_settings {
name = "${local.http_setting_name}"
cookie_based_affinity = "Disabled"
pick_host_name_from_backend_address = true
port = 80
probe_name = "${local.probe_name}"
protocol = "Http"
request_timeout = 1
}
probe {
name = "${local.probe_name}"
protocol = "Http"
path = "/test"
timeout = 120
interval = 300
unhealthy_threshold = 8
pick_host_name_from_backend_http_settings = true
}
http_listener {
name = "${local.listener_name}"
frontend_ip_configuration_name = "${local.frontend_ip_configuration_name}"
frontend_port_name = "${local.frontend_port_name}"
protocol = "Http"
}
request_routing_rule {
name = "${local.request_routing_rule_name}"
rule_type = "Basic"
http_listener_name = "${local.listener_name}"
backend_address_pool_name = "${local.backend_address_pool_name}"
backend_http_settings_name = "${local.http_setting_name}"
}
}
`, template, rInt)
}

func testAccAzureRMApplicationGateway_settingsPickHostNameFromBackendAddress(rInt int, location string) string {
template := testAccAzureRMApplicationGateway_template(rInt, location)
return fmt.Sprintf(`
%s
# since these variables are re-used - a locals block makes this more maintainable
locals {
backend_address_pool_name = "${azurerm_virtual_network.test.name}-beap"
frontend_port_name = "${azurerm_virtual_network.test.name}-feport"
frontend_ip_configuration_name = "${azurerm_virtual_network.test.name}-feip"
http_setting_name = "${azurerm_virtual_network.test.name}-be-htst"
listener_name = "${azurerm_virtual_network.test.name}-httplstn"
request_routing_rule_name = "${azurerm_virtual_network.test.name}-rqrt"
}
resource "azurerm_application_gateway" "test" {
name = "acctestag-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
sku {
name = "Standard_Small"
tier = "Standard"
capacity = 2
}
gateway_ip_configuration {
name = "my-gateway-ip-configuration"
subnet_id = "${azurerm_subnet.test.id}"
}
frontend_port {
name = "${local.frontend_port_name}"
port = 80
}
frontend_ip_configuration {
name = "${local.frontend_ip_configuration_name}"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
backend_address_pool {
name = "${local.backend_address_pool_name}"
}
backend_http_settings {
name = "${local.http_setting_name}"
cookie_based_affinity = "Disabled"
pick_host_name_from_backend_address = true
port = 80
protocol = "Http"
request_timeout = 1
}
http_listener {
name = "${local.listener_name}"
frontend_ip_configuration_name = "${local.frontend_ip_configuration_name}"
frontend_port_name = "${local.frontend_port_name}"
protocol = "Http"
}
request_routing_rule {
name = "${local.request_routing_rule_name}"
rule_type = "Basic"
http_listener_name = "${local.listener_name}"
backend_address_pool_name = "${local.backend_address_pool_name}"
backend_http_settings_name = "${local.http_setting_name}"
}
}
`, template, rInt)
}

func testAccAzureRMApplicationGateway_sslCertificate(rInt int, location string) string {
template := testAccAzureRMApplicationGateway_template(rInt, location)
return fmt.Sprintf(`
Expand Down
6 changes: 5 additions & 1 deletion website/docs/r/application_gateway.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ A `backend_http_settings` block supports the following:

* `request_timeout` - (Required) The request timeout in seconds, which must be between 1 and 86400 seconds.

* `pick_host_name_from_backend_address` - (Optional) Whether host header should be picked from the host name of the backend server. Defaults to `false`.

* `authentication_certificate` - (Optional) One or more `authentication_certificate` blocks.

---
Expand Down Expand Up @@ -267,7 +269,7 @@ A `path_rule` block supports the following:

A `probe` block support the following:

* `host` - (Required) The Hostname used for this Probe. If the Application Gateway is configured for a single site, by default the Host name should be specified as ‘127.0.0.1’, unless otherwise configured in custom probe.
* `host` - (Optional) The Hostname used for this Probe. If the Application Gateway is configured for a single site, by default the Host name should be specified as ‘127.0.0.1’, unless otherwise configured in custom probe. Cannot be set if `pick_host_name_from_backend_http_settings` is set to `true`.

* `interval` - (Required) The Interval between two consecutive probes in seconds. Possible values range from 1 second to a maximum of 86,400 seconds.

Expand All @@ -281,6 +283,8 @@ A `probe` block support the following:

* `unhealthy_threshold` - (Required) The Unhealthy Threshold for this Probe, which indicates the amount of retries which should be attempted before a node is deemed unhealthy. Possible values are from 1 - 20 seconds.

* `pick_host_name_from_backend_http_settings` - (Optional) Whether the host header should be picked from the backend http settings. Defaults to `false`.

* `match` - (Optional) A `match` block as defined above.

* `minimum_servers` - (Optional) The minimum number of servers that are always marked as healthy. Defaults to `0`.
Expand Down

0 comments on commit 2f58e4d

Please sign in to comment.