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

add support for pick-hostname behaviours #2658

45 changes: 33 additions & 12 deletions azurerm/resource_arm_application_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ func resourceArmApplicationGateway() *schema.Resource {
}, true),
},

"pick_host_name_from_backend_address": {
Type: schema.TypeBool,
Optional: true,
},
metacpp marked this conversation as resolved.
Show resolved Hide resolved

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

"host": {
Type: schema.TypeString,
Required: true,
Optional: true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that this is optional we should probably add validation somewhere to make sure if this is empty, pick_host_name_from_backend_address is true.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also update the documentation with this change

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@katbyte might you have any suggestions re "add validation somewhere"? - it seems like current validation mechanisms are per-property.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mdsills, in the create function you can check both properties and if neither are set return an error.

Something like:

host := v["pick_host_name_from_backend_address"].(string)
pick := v["pick_host_name_from_backend_address"].(bool)
if !pick && host == "" {
return fmt.Errorf("one of `host` or `pick_host_name_from_backend_http_settings` must be set")
}

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

disclaimer that code might not compile 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the pointer. it's ended up looking rather different, but hopefully still acceptable, or at least a step towards acceptable...

},

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

"pick_host_name_from_backend_http_settings": {
Type: schema.TypeBool,
Optional: true,
},
metacpp marked this conversation as resolved.
Show resolved Hide resolved

"minimum_servers": {
Type: schema.TypeInt,
Optional: true,
Expand Down Expand Up @@ -1087,15 +1097,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 @@ -1153,6 +1165,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 @@ -1544,17 +1559,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 @@ -1620,6 +1637,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.TestCheckResourceAttrSet(resourceName, "probe.0.pick_host_name_from_backend_http_settings"),
metacpp marked this conversation as resolved.
Show resolved Hide resolved
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we remove this line because TestCheckResourceAttr will check the existence?

Suggested change
resource.TestCheckResourceAttrSet(resourceName, "probe.0.pick_host_name_from_backend_http_settings"),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

),
},
{
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.TestCheckResourceAttrSet(resourceName, "backend_http_settings.0.pick_host_name_from_backend_address"),
metacpp marked this conversation as resolved.
Show resolved Hide resolved
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we remove this line because TestCheckResourceAttr will check the existence?

Suggested change
resource.TestCheckResourceAttrSet(resourceName, "backend_http_settings.0.pick_host_name_from_backend_address"),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAzureRMApplicationGateway_sslCertificate(t *testing.T) {
resourceName := "azurerm_application_gateway.test"
ri := tf.AccRandTimeInt()
Expand Down Expand Up @@ -836,6 +886,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
Loading