From 515bf150e83ce7c24051b618f6a4eac47f49e12e Mon Sep 17 00:00:00 2001 From: Steve Byerly Date: Sat, 26 Jan 2019 18:03:23 -0800 Subject: [PATCH 1/6] add connection draining to application gateway http settings --- azurerm/resource_arm_application_gateway.go | 75 ++++++++++- .../resource_arm_application_gateway_test.go | 116 ++++++++++++++++++ 2 files changed, 190 insertions(+), 1 deletion(-) diff --git a/azurerm/resource_arm_application_gateway.go b/azurerm/resource_arm_application_gateway.go index 8a85b3323d07..d6275a900b59 100644 --- a/azurerm/resource_arm_application_gateway.go +++ b/azurerm/resource_arm_application_gateway.go @@ -146,6 +146,26 @@ func resourceArmApplicationGateway() *schema.Resource { }, }, + "connection_draining": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + + "drain_timeout_in_sec": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(1, 3600), + }, + }, + }, + }, + "probe_name": { Type: schema.TypeString, Optional: true, @@ -1139,6 +1159,7 @@ func expandApplicationGatewayBackendHTTPSettings(d *schema.ResourceData, gateway Port: utils.Int32(port), Protocol: network.ApplicationGatewayProtocol(protocol), RequestTimeout: utils.Int32(requestTimeout), + ConnectionDraining: expandApplicationGatewayConnectionDraining(v), }, } @@ -1193,13 +1214,17 @@ func flattenApplicationGatewayBackendHTTPSettings(input *[]network.ApplicationGa if props := v.ApplicationGatewayBackendHTTPSettingsPropertiesFormat; props != nil { output["cookie_based_affinity"] = string(props.CookieBasedAffinity) + output["protocol"] = string(props.Protocol) + output["connection_draining"] = flattenApplicationGatewayConnectionDraining(props) + 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) } @@ -1245,6 +1270,54 @@ func flattenApplicationGatewayBackendHTTPSettings(input *[]network.ApplicationGa return results, nil } +func expandApplicationGatewayConnectionDraining(d map[string]interface{}) *network.ApplicationGatewayConnectionDraining { + connectionsRaw := d["connection_draining"].([]interface{}) + + var connectionDraining *network.ApplicationGatewayConnectionDraining + if len(connectionsRaw) > 0 { + connectionRaw := connectionsRaw[0].(map[string]interface{}) + + enabled := connectionRaw["enabled"].(bool) + var drainTimeout int32 + + if enabled { + drainTimeout = int32(connectionRaw["drain_timeout_in_sec"].(int)) + } + + connectionDraining = &network.ApplicationGatewayConnectionDraining{ + Enabled: utils.Bool(enabled), + DrainTimeoutInSec: utils.Int32(drainTimeout), + } + } + + return connectionDraining +} + +func flattenApplicationGatewayConnectionDraining(input *network.ApplicationGatewayBackendHTTPSettingsPropertiesFormat) []interface{} { + results := make([]interface{}, 0) + + if connectionDraining := input.ConnectionDraining; connectionDraining != nil { + enabled := false + if connectionDraining.Enabled != nil { + enabled = *connectionDraining.Enabled + } + + var drainTimeout int32 + if enabled && connectionDraining.DrainTimeoutInSec != nil { + drainTimeout = *connectionDraining.DrainTimeoutInSec + } + + var result = map[string]interface{}{ + "enabled": enabled, + "drain_timeout_in_sec": drainTimeout, + } + + results = append(results, result) + } + + return results +} + func expandApplicationGatewaySslPolicy(d *schema.ResourceData) *network.ApplicationGatewaySslPolicy { vs := d.Get("disabled_ssl_protocols").([]interface{}) results := make([]network.ApplicationGatewaySslProtocol, 0) diff --git a/azurerm/resource_arm_application_gateway_test.go b/azurerm/resource_arm_application_gateway_test.go index 0d39043b490c..d2f9a5b1fb03 100644 --- a/azurerm/resource_arm_application_gateway_test.go +++ b/azurerm/resource_arm_application_gateway_test.go @@ -308,6 +308,34 @@ func TestAccAzureRMApplicationGateway_webApplicationFirewall(t *testing.T) { }) } +func TestAccAzureRMApplicationGateway_connectionDraining(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_connectionDraining(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists(resourceName), + resource.TestCheckNoResourceAttr(resourceName, "backend_http_settings.0.connection_draining.enabled"), + resource.TestCheckNoResourceAttr(resourceName, "backend_http_settings.0.connection_draining.drain_timeout_in_sec"), + resource.TestCheckResourceAttr(resourceName, "backend_http_settings.1.connection_draining.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "backend_http_settings.1.connection_draining.drain_timeout_in_sec", "127"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testCheckAzureRMApplicationGatewayExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] @@ -1320,6 +1348,94 @@ resource "azurerm_application_gateway" "test" { `, template, rInt) } +func testAccAzureRMApplicationGateway_connectionDraining(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" + probe1_name = "${azurerm_virtual_network.test.name}-probe1" + probe2_name = "${azurerm_virtual_network.test.name}-probe2" + 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" + port = 80 + probe_name = "${local.probe1_name}" + protocol = "Http" + request_timeout = 1 + } + + backend_http_settings { + name = "${local.http_setting_name}-2" + cookie_based_affinity = "Disabled" + port = 8080 + probe_name = "${local.probe2_name}" + protocol = "Http" + request_timeout = 1 + + connection_draining { + enabled = true + drain_timeout_in_sec = 127 + } + } + + 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_template(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { From e3228994121bfe2c99cc60739eb55d8ea3979af3 Mon Sep 17 00:00:00 2001 From: kt Date: Fri, 15 Feb 2019 00:44:59 -0800 Subject: [PATCH 2/6] updated schema & flatten/expand & added docs --- azurerm/resource_arm_application_gateway.go | 59 +++++++------------ .../resource_arm_application_gateway_test.go | 39 ++++++------ .../docs/r/application_gateway.html.markdown | 11 ++++ 3 files changed, 53 insertions(+), 56 deletions(-) diff --git a/azurerm/resource_arm_application_gateway.go b/azurerm/resource_arm_application_gateway.go index d6275a900b59..6496daa5212b 100644 --- a/azurerm/resource_arm_application_gateway.go +++ b/azurerm/resource_arm_application_gateway.go @@ -157,9 +157,9 @@ func resourceArmApplicationGateway() *schema.Resource { Required: true, }, - "drain_timeout_in_sec": { + "drain_timeout_sec": { Type: schema.TypeInt, - Optional: true, + Required: true, ValidateFunc: validation.IntBetween(1, 3600), }, }, @@ -1215,7 +1215,7 @@ func flattenApplicationGatewayBackendHTTPSettings(input *[]network.ApplicationGa if props := v.ApplicationGatewayBackendHTTPSettingsPropertiesFormat; props != nil { output["cookie_based_affinity"] = string(props.CookieBasedAffinity) output["protocol"] = string(props.Protocol) - output["connection_draining"] = flattenApplicationGatewayConnectionDraining(props) + output["connection_draining"] = flattenApplicationGatewayConnectionDraining(props.ConnectionDraining) if port := props.Port; port != nil { output["port"] = int(*port) @@ -1273,49 +1273,32 @@ func flattenApplicationGatewayBackendHTTPSettings(input *[]network.ApplicationGa func expandApplicationGatewayConnectionDraining(d map[string]interface{}) *network.ApplicationGatewayConnectionDraining { connectionsRaw := d["connection_draining"].([]interface{}) - var connectionDraining *network.ApplicationGatewayConnectionDraining - if len(connectionsRaw) > 0 { - connectionRaw := connectionsRaw[0].(map[string]interface{}) - - enabled := connectionRaw["enabled"].(bool) - var drainTimeout int32 + if len(connectionsRaw) <= 0 { + return nil + } - if enabled { - drainTimeout = int32(connectionRaw["drain_timeout_in_sec"].(int)) - } + connectionRaw := connectionsRaw[0].(map[string]interface{}) - connectionDraining = &network.ApplicationGatewayConnectionDraining{ - Enabled: utils.Bool(enabled), - DrainTimeoutInSec: utils.Int32(drainTimeout), - } + return &network.ApplicationGatewayConnectionDraining{ + Enabled: utils.Bool(connectionRaw["enabled"].(bool)), + DrainTimeoutInSec: utils.Int32(int32(connectionRaw["drain_timeout_sec"].(int))), } - - return connectionDraining } -func flattenApplicationGatewayConnectionDraining(input *network.ApplicationGatewayBackendHTTPSettingsPropertiesFormat) []interface{} { - results := make([]interface{}, 0) - - if connectionDraining := input.ConnectionDraining; connectionDraining != nil { - enabled := false - if connectionDraining.Enabled != nil { - enabled = *connectionDraining.Enabled - } - - var drainTimeout int32 - if enabled && connectionDraining.DrainTimeoutInSec != nil { - drainTimeout = *connectionDraining.DrainTimeoutInSec - } - - var result = map[string]interface{}{ - "enabled": enabled, - "drain_timeout_in_sec": drainTimeout, - } +func flattenApplicationGatewayConnectionDraining(input *network.ApplicationGatewayConnectionDraining) []interface{} { + result := map[string]interface{}{} + if input == nil { + return []interface{}{} + } - results = append(results, result) + if v := input.Enabled; v != nil { + result["enabled"] = *v + } + if v := input.DrainTimeoutInSec; v != nil { + result["drain_timeout_sec"] = *v } - return results + return []interface{}{result} } func expandApplicationGatewaySslPolicy(d *schema.ResourceData) *network.ApplicationGatewaySslPolicy { diff --git a/azurerm/resource_arm_application_gateway_test.go b/azurerm/resource_arm_application_gateway_test.go index d2f9a5b1fb03..41749e6e7292 100644 --- a/azurerm/resource_arm_application_gateway_test.go +++ b/azurerm/resource_arm_application_gateway_test.go @@ -321,10 +321,24 @@ func TestAccAzureRMApplicationGateway_connectionDraining(t *testing.T) { Config: testAccAzureRMApplicationGateway_connectionDraining(ri, testLocation()), Check: resource.ComposeTestCheckFunc( testCheckAzureRMApplicationGatewayExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "backend_http_settings.0.connection_draining.0.enabled", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAzureRMApplicationGateway_basic(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "sku.0.name", "Standard_Small"), + resource.TestCheckResourceAttr(resourceName, "sku.0.tier", "Standard"), + resource.TestCheckResourceAttr(resourceName, "sku.0.capacity", "2"), + resource.TestCheckResourceAttr(resourceName, "waf_configuration.#", "0"), resource.TestCheckNoResourceAttr(resourceName, "backend_http_settings.0.connection_draining.enabled"), - resource.TestCheckNoResourceAttr(resourceName, "backend_http_settings.0.connection_draining.drain_timeout_in_sec"), - resource.TestCheckResourceAttr(resourceName, "backend_http_settings.1.connection_draining.enabled", "true"), - resource.TestCheckResourceAttr(resourceName, "backend_http_settings.1.connection_draining.drain_timeout_in_sec", "127"), + resource.TestCheckNoResourceAttr(resourceName, "backend_http_settings.0.connection_draining.drain_timeout_sec"), ), }, { @@ -1360,8 +1374,6 @@ locals { 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" - probe1_name = "${azurerm_virtual_network.test.name}-probe1" - probe2_name = "${azurerm_virtual_network.test.name}-probe2" request_routing_rule_name = "${azurerm_virtual_network.test.name}-rqrt" } @@ -1369,6 +1381,7 @@ resource "azurerm_application_gateway" "test" { name = "acctestag-%d" resource_group_name = "${azurerm_resource_group.test.name}" location = "${azurerm_resource_group.test.location}" + enable_http2 = true sku { name = "Standard_Small" @@ -1399,22 +1412,12 @@ resource "azurerm_application_gateway" "test" { name = "${local.http_setting_name}" cookie_based_affinity = "Disabled" port = 80 - probe_name = "${local.probe1_name}" - protocol = "Http" - request_timeout = 1 - } - - backend_http_settings { - name = "${local.http_setting_name}-2" - cookie_based_affinity = "Disabled" - port = 8080 - probe_name = "${local.probe2_name}" protocol = "Http" request_timeout = 1 - connection_draining { - enabled = true - drain_timeout_in_sec = 127 + connection_draining { + enabled = true + drain_timeout_sec = 1984 } } diff --git a/website/docs/r/application_gateway.html.markdown b/website/docs/r/application_gateway.html.markdown index f8fb46713552..41c51b44633a 100644 --- a/website/docs/r/application_gateway.html.markdown +++ b/website/docs/r/application_gateway.html.markdown @@ -195,8 +195,19 @@ A `backend_http_settings` block supports the following: * `authentication_certificate` - (Optional) One or more `authentication_certificate` blocks. +* `connection_draining` - (Optional) One or more `connection_draining` blocks. + +--- + +A `connection_draining` block supports the following: + +* `enabled` - (Required) If connection draining is enabled or not. + +* `drain_timeout_sec` - (Required) The number of seconds connection draining is active. Acceptable values are from `1` second to `3600` seconds. + --- + A `frontend_ip_configuration` block supports the following: * `name` - (Required) The name of the Frontend IP Configuration. From faf96b5cfab3391150b74ac09c625de3b267c07d Mon Sep 17 00:00:00 2001 From: Steve Byerly Date: Sat, 16 Feb 2019 18:39:17 -0800 Subject: [PATCH 3/6] PR fixes --- azurerm/resource_arm_application_gateway_test.go | 4 ++-- website/docs/r/application_gateway.html.markdown | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/azurerm/resource_arm_application_gateway_test.go b/azurerm/resource_arm_application_gateway_test.go index db258b0cb3e3..9a1b2e0bdabb 100644 --- a/azurerm/resource_arm_application_gateway_test.go +++ b/azurerm/resource_arm_application_gateway_test.go @@ -386,8 +386,8 @@ func TestAccAzureRMApplicationGateway_connectionDraining(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "sku.0.tier", "Standard"), resource.TestCheckResourceAttr(resourceName, "sku.0.capacity", "2"), resource.TestCheckResourceAttr(resourceName, "waf_configuration.#", "0"), - resource.TestCheckNoResourceAttr(resourceName, "backend_http_settings.0.connection_draining.enabled"), - resource.TestCheckNoResourceAttr(resourceName, "backend_http_settings.0.connection_draining.drain_timeout_sec"), + resource.TestCheckNoResourceAttr(resourceName, "backend_http_settings.0.connection_draining.0.enabled"), + resource.TestCheckNoResourceAttr(resourceName, "backend_http_settings.0.connection_draining.0.drain_timeout_sec"), ), }, { diff --git a/website/docs/r/application_gateway.html.markdown b/website/docs/r/application_gateway.html.markdown index 33073b2d4d60..411d76cc0708 100644 --- a/website/docs/r/application_gateway.html.markdown +++ b/website/docs/r/application_gateway.html.markdown @@ -206,7 +206,7 @@ A `backend_http_settings` block supports the following: * `authentication_certificate` - (Optional) One or more `authentication_certificate` blocks. -* `connection_draining` - (Optional) One or more `connection_draining` blocks. +* `connection_draining` - (Optional) A `connection_draining` block as defined below. --- From 5ebe6213de5e563f1f17b28d385a90f4362d8dc4 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Thu, 28 Feb 2019 10:21:17 +0100 Subject: [PATCH 4/6] r/application_gateway: ensuring the `protocol` field is set --- azurerm/resource_arm_application_gateway.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azurerm/resource_arm_application_gateway.go b/azurerm/resource_arm_application_gateway.go index f63595762845..276a015296b5 100644 --- a/azurerm/resource_arm_application_gateway.go +++ b/azurerm/resource_arm_application_gateway.go @@ -1335,6 +1335,8 @@ func flattenApplicationGatewayBackendHTTPSettings(input *[]network.ApplicationGa 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) From eda9efec37b5e492fd313eb32ceb70fdfda4e405 Mon Sep 17 00:00:00 2001 From: Tom Harvey Date: Thu, 28 Feb 2019 10:21:35 +0100 Subject: [PATCH 5/6] r/application_gateway: ensuring the `protocol` field is set From 67f85ef433d9650a362b6514de656fd2ae5480ff Mon Sep 17 00:00:00 2001 From: kt Date: Thu, 28 Feb 2019 01:30:35 -0800 Subject: [PATCH 6/6] make fmt --- azurerm/resource_arm_application_gateway.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/resource_arm_application_gateway.go b/azurerm/resource_arm_application_gateway.go index 276a015296b5..ef093d4e4489 100644 --- a/azurerm/resource_arm_application_gateway.go +++ b/azurerm/resource_arm_application_gateway.go @@ -1335,7 +1335,7 @@ func flattenApplicationGatewayBackendHTTPSettings(input *[]network.ApplicationGa 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 {