From 515bf150e83ce7c24051b618f6a4eac47f49e12e Mon Sep 17 00:00:00 2001
From: Steve Byerly <steven.j.byerly@gmail.com>
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 <kt@katbyte.me>
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 <steven.j.byerly@gmail.com>
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 <tombuildsstuff@users.noreply.github.com>
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 <tombuildsstuff@users.noreply.github.com>
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 <kt@katbyte.me>
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 {