Skip to content

Commit

Permalink
Adding the Match parameter to the Probes to check on the response code (
Browse files Browse the repository at this point in the history
#1446)

* Adding the Match parameter to the Probes to check on the response code

* Added documentation

* Incorporating code review comments from Tom

* Removing an expectation where Match is optional
  • Loading branch information
VaijanathB authored and tombuildsstuff committed Jun 28, 2018
1 parent e5c9421 commit 55c6114
Show file tree
Hide file tree
Showing 3 changed files with 314 additions and 0 deletions.
55 changes: 55 additions & 0 deletions azurerm/resource_arm_application_gateway.go
Expand Up @@ -457,6 +457,29 @@ func resourceArmApplicationGateway() *schema.Resource {
Type: schema.TypeInt,
Required: true,
},

"match": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"body": {
Type: schema.TypeString,
Optional: true,
Default: "*",
},

"status_code": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
},
},
},
Expand Down Expand Up @@ -1162,6 +1185,22 @@ func expandApplicationGatewayProbes(d *schema.ResourceData) *[]network.Applicati
},
}

matchConfigs := data["match"].([]interface{})
if len(matchConfigs) > 0 {
match := matchConfigs[0].(map[string]interface{})
matchBody := match["body"].(string)

statusCodes := make([]string, 0)
for _, statusCode := range match["status_code"].([]interface{}) {
statusCodes = append(statusCodes, statusCode.(string))
}

setting.ApplicationGatewayProbePropertiesFormat.Match = &network.ApplicationGatewayProbeHealthResponseMatch{
Body: &matchBody,
StatusCodes: &statusCodes,
}
}

backendSettings = append(backendSettings, setting)
}

Expand Down Expand Up @@ -1608,6 +1647,22 @@ func flattenApplicationGatewayProbes(input *[]network.ApplicationGatewayProbe) [
if threshold := props.UnhealthyThreshold; threshold != nil {
settings["unhealthy_threshold"] = int(*threshold)
}

if match := props.Match; match != nil {
matchConfig := map[string]interface{}{}
if body := match.Body; body != nil {
matchConfig["body"] = *body
}

statusCodes := make([]interface{}, 0)
if match.StatusCodes != nil {
for _, status := range *match.StatusCodes {
statusCodes = append(statusCodes, status)
}
matchConfig["status_code"] = statusCodes
}
settings["match"] = matchConfig
}
}

result = append(result, settings)
Expand Down
254 changes: 254 additions & 0 deletions azurerm/resource_arm_application_gateway_test.go
Expand Up @@ -198,6 +198,32 @@ func TestAccAzureRMApplicationGateway_waf(t *testing.T) {
})
}

func TestAccAzureRMApplicationGateway_probeResponseMatch(t *testing.T) {
resourceName := "azurerm_application_gateway.test"
ri := acctest.RandInt()

subscriptionID := os.Getenv("ARM_SUBSCRIPTION_ID")
gwID := fmt.Sprintf(
"/subscriptions/%s/resourceGroups/acctestRG-%d/providers/Microsoft.Network/applicationGateways/acctestgw-%d",
subscriptionID, ri, ri)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMApplicationGatewayDestroy,
Steps: []resource.TestStep{
{
Config: testAccAzureRMApplicationGateway_probeResponseMatch(ri, testLocation()),
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMApplicationGatewayExists(resourceName),
testCheckAzureRMApplicationGatewayProbeResponseMatchAssigned(resourceName, "probe-1"),
resource.TestCheckResourceAttr(resourceName, "id", gwID),
),
},
},
})
}

func testCheckAzureRMApplicationGatewayExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
Expand Down Expand Up @@ -325,6 +351,43 @@ func testCheckAzureRMApplicationGatewayAuthenticationCertificateAssigned(name st
}
}

func testCheckAzureRMApplicationGatewayProbeResponseMatchAssigned(name string, probeName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}

gatewayName := rs.Primary.Attributes["name"]
resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
if !hasResourceGroup {
return fmt.Errorf("Bad: no resource group found in state for App Gateway: %q", gatewayName)
}

conn := testAccProvider.Meta().(*ArmClient).applicationGatewayClient
ctx := testAccProvider.Meta().(*ArmClient).StopContext

resp, err := conn.Get(ctx, resourceGroup, gatewayName)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Bad: App Gateway %q (resource group: %q) does not exist", gatewayName, resourceGroup)
}

return fmt.Errorf("Bad: Get on ApplicationGatewayClient: %+v", err)
}

for _, probe := range *resp.Probes {
if *probe.Name == probeName {
if match := probe.Match; match != nil {
return nil
}
}
}

return fmt.Errorf("Bad: Probe Response match was not found: %s", probeName)
}
}

func testCheckAzureRMApplicationGatewayDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*ArmClient).applicationGatewayClient
ctx := testAccProvider.Meta().(*ArmClient).StopContext
Expand Down Expand Up @@ -1310,3 +1373,194 @@ resource "azurerm_application_gateway" "test" {
}
`, rInt, location, rInt, rInt, rInt, rInt)
}

func testAccAzureRMApplicationGateway_probeResponseMatch(rInt int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}
resource "azurerm_virtual_network" "test" {
name = "acctest-vnet-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
address_space = ["10.254.0.0/16"]
location = "${azurerm_resource_group.test.location}"
}
resource "azurerm_subnet" "test" {
name = "subnet-%d"
resource_group_name = "${azurerm_resource_group.test.name}"
virtual_network_name = "${azurerm_virtual_network.test.name}"
address_prefix = "10.254.0.0/24"
}
resource "azurerm_public_ip" "test" {
name = "acctest-pubip-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
public_ip_address_allocation = "dynamic"
}
resource "azurerm_application_gateway" "test" {
name = "acctestgw-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
sku {
name = "Standard_Medium"
tier = "Standard"
capacity = 1
}
disabled_ssl_protocols = [
"TLSv1_0",
]
gateway_ip_configuration {
# id = computed
name = "gw-ip-config1"
subnet_id = "${azurerm_subnet.test.id}"
}
frontend_ip_configuration {
# id = computed
name = "ip-config-public"
public_ip_address_id = "${azurerm_public_ip.test.id}"
}
frontend_ip_configuration {
# id = computed
name = "ip-config-private"
subnet_id = "${azurerm_subnet.test.id}"
# private_ip_address = computed
private_ip_address_allocation = "Dynamic"
}
frontend_port {
# id = computed
name = "port-8080"
port = 8080
}
backend_address_pool {
# id = computed
name = "pool-1"
fqdn_list = [
"terraform.io",
]
}
backend_http_settings {
# id = computed
name = "backend-http-1"
port = 8010
protocol = "Https"
cookie_based_affinity = "Enabled"
request_timeout = 30
# probe_id = computed
probe_name = "probe-1"
}
http_listener {
# id = computed
name = "listener-1"
# frontend_ip_configuration_id = computed
frontend_ip_configuration_name = "ip-config-public"
# frontend_ip_port_id = computed
frontend_port_name = "port-8080"
protocol = "Http"
}
http_listener {
name = "listener-2"
frontend_ip_configuration_name = "ip-config-public"
frontend_port_name = "port-8080"
protocol = "Https"
# ssl_certificate_id = computed
ssl_certificate_name = "ssl-1"
host_name = "terraform.io"
require_sni = true
}
probe {
# id = computed
name = "probe-1"
protocol = "Https"
path = "/test"
host = "azure.com"
timeout = 120
interval = 300
unhealthy_threshold = 8
match = {
body = "*"
status_code = [
"200",
"201",
"205-210",
]
}
}
url_path_map {
# id = computed
name = "path-map-1"
default_backend_address_pool_name = "pool-1"
default_backend_http_settings_name = "backend-http-1"
path_rule {
# id = computed
name = "path-rule-1"
backend_address_pool_name = "pool-1"
backend_http_settings_name = "backend-http-1"
paths = [
"/test",
]
}
}
request_routing_rule {
# id = computed
name = "rule-basic-1"
rule_type = "Basic"
# http_listener_id = computed
http_listener_name = "listener-1"
# backend_address_pool_id = computed
backend_address_pool_name = "pool-1"
# backend_http_settings_id = computed
backend_http_settings_name = "backend-http-1"
}
request_routing_rule {
# id = computed
name = "rule-path-1"
rule_type = "PathBasedRouting"
url_path_map_name = "path-map-1"
# http_listener_id = computed
http_listener_name = "listener-2"
}
ssl_certificate {
# id = computed
name = "ssl-1"
data = "${file("testdata/application_gateway_test.pfx")}"
password = "terraform"
}
tags {
environment = "tf01"
}
}
`, rInt, location, rInt, rInt, rInt, rInt)
}
5 changes: 5 additions & 0 deletions website/docs/r/application_gateway.html.markdown
Expand Up @@ -262,6 +262,11 @@ The `probe` block supports:

* `unhealthy_threshold` - (Required) Probe retry count. Backend server is marked down after consecutive probe failure count reaches UnhealthyThreshold. Minimum 1 second and Maximum 20.

* `match` - (Optional) Probe health response match.

* `body` - (Optional) Body that must be contained in the health response. Defaults to "*"
* `status_code` - (Optional) Allowed health response status codes.

The `request_routing_rule` block supports:

* `name` - (Required) User defined name for a request routing rule.
Expand Down

0 comments on commit 55c6114

Please sign in to comment.