From e9e1fa90e908b0ddd66a63c6ebb6b53d5649ff6c Mon Sep 17 00:00:00 2001 From: Neil Ye Date: Mon, 27 Apr 2020 12:54:17 +0800 Subject: [PATCH] azurerm_application_gateway - support `host_names` property (#6630) fixes #6579 --- .../resource_arm_application_gateway.go | 37 ++++++- .../resource_arm_application_gateway_test.go | 100 ++++++++++++++++++ .../docs/r/application_gateway.html.markdown | 4 + 3 files changed, 137 insertions(+), 4 deletions(-) diff --git a/azurerm/internal/services/network/resource_arm_application_gateway.go b/azurerm/internal/services/network/resource_arm_application_gateway.go index 9e22c7bd6ba4..762076f17eef 100644 --- a/azurerm/internal/services/network/resource_arm_application_gateway.go +++ b/azurerm/internal/services/network/resource_arm_application_gateway.go @@ -401,6 +401,15 @@ func resourceArmApplicationGateway() *schema.Resource { Optional: true, }, + "host_names": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringIsNotEmpty, + }, + }, + "ssl_certificate_name": { Type: schema.TypeString, Optional: true, @@ -1348,6 +1357,11 @@ func resourceArmApplicationGatewayCreateUpdate(d *schema.ResourceData, meta inte gatewayIPConfigurations, stopApplicationGateway := expandApplicationGatewayIPConfigurations(d) + httpListeners, err := expandApplicationGatewayHTTPListeners(d, gatewayID) + if err != nil { + return fmt.Errorf("fail to expand `http_listener`: %+v", err) + } + gateway := network.ApplicationGateway{ Location: utils.String(location), Zones: azure.ExpandZones(d.Get("zones").([]interface{})), @@ -1364,7 +1378,7 @@ func resourceArmApplicationGatewayCreateUpdate(d *schema.ResourceData, meta inte FrontendIPConfigurations: expandApplicationGatewayFrontendIPConfigurations(d), FrontendPorts: expandApplicationGatewayFrontendPorts(d), GatewayIPConfigurations: gatewayIPConfigurations, - HTTPListeners: expandApplicationGatewayHTTPListeners(d, gatewayID), + HTTPListeners: httpListeners, Probes: expandApplicationGatewayProbes(d), RequestRoutingRules: requestRoutingRules, RedirectConfigurations: redirectConfigurations, @@ -2171,7 +2185,7 @@ func flattenApplicationGatewaySslPolicy(input *network.ApplicationGatewaySslPoli return results } -func expandApplicationGatewayHTTPListeners(d *schema.ResourceData, gatewayID string) *[]network.ApplicationGatewayHTTPListener { +func expandApplicationGatewayHTTPListeners(d *schema.ResourceData, gatewayID string) (*[]network.ApplicationGatewayHTTPListener, error) { vs := d.Get("http_listener").([]interface{}) results := make([]network.ApplicationGatewayHTTPListener, 0) @@ -2204,10 +2218,21 @@ func expandApplicationGatewayHTTPListeners(d *schema.ResourceData, gatewayID str }, } - if host := v["host_name"].(string); host != "" { + host := v["host_name"].(string) + hosts := v["host_names"].(*schema.Set).List() + + if host != "" && len(hosts) > 0 { + return nil, fmt.Errorf("`host_name` and `host_names` cannot be specified together") + } + + if host != "" { listener.ApplicationGatewayHTTPListenerPropertiesFormat.HostName = &host } + if len(hosts) > 0 { + listener.ApplicationGatewayHTTPListenerPropertiesFormat.Hostnames = utils.ExpandStringSlice(hosts) + } + if sslCertName := v["ssl_certificate_name"].(string); sslCertName != "" { certID := fmt.Sprintf("%s/sslCertificates/%s", gatewayID, sslCertName) listener.ApplicationGatewayHTTPListenerPropertiesFormat.SslCertificate = &network.SubResource{ @@ -2218,7 +2243,7 @@ func expandApplicationGatewayHTTPListeners(d *schema.ResourceData, gatewayID str results = append(results, listener) } - return &results + return &results, nil } func flattenApplicationGatewayHTTPListeners(input *[]network.ApplicationGatewayHTTPListener) ([]interface{}, error) { @@ -2267,6 +2292,10 @@ func flattenApplicationGatewayHTTPListeners(input *[]network.ApplicationGatewayH output["host_name"] = *hostname } + if hostnames := props.Hostnames; hostnames != nil { + output["host_names"] = utils.FlattenStringSlice(hostnames) + } + output["protocol"] = string(props.Protocol) if cert := props.SslCertificate; cert != nil { diff --git a/azurerm/internal/services/network/tests/resource_arm_application_gateway_test.go b/azurerm/internal/services/network/tests/resource_arm_application_gateway_test.go index 5db72587bdb4..d4cbd5072ba9 100644 --- a/azurerm/internal/services/network/tests/resource_arm_application_gateway_test.go +++ b/azurerm/internal/services/network/tests/resource_arm_application_gateway_test.go @@ -497,6 +497,25 @@ func TestAccAzureRMApplicationGateway_backendHttpSettingsHostName(t *testing.T) }) } +func TestAccAzureRMApplicationGateway_withHttpListenerHostNames(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_application_gateway", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMApplicationGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApplicationGateway_withHttpListenerHostNames(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + func TestAccAzureRMApplicationGateway_backendHttpSettingsHostNameAndPick(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_application_gateway", "test") hostName := "example.com" @@ -2880,6 +2899,87 @@ resource "azurerm_application_gateway" "test" { `, template, data.RandomInteger, hostName, pick) } +func testAccAzureRMApplicationGateway_withHttpListenerHostNames(data acceptance.TestData) string { + template := testAccAzureRMApplicationGateway_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_public_ip" "test2" { + name = "acctest-pubip2-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + allocation_method = "Static" + sku = "Standard" + domain_name_label = "testdns-123" +} + +# 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_v2" + tier = "Standard_v2" + 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.test2.id + } + + backend_address_pool { + name = local.backend_address_pool_name + } + + backend_http_settings { + name = local.http_setting_name + cookie_based_affinity = "Disabled" + 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" + host_names = ["testdns-123"] + } + + 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, data.RandomInteger, data.RandomInteger) +} + func testAccAzureRMApplicationGateway_settingsPickHostNameFromBackendAddress(data acceptance.TestData) string { template := testAccAzureRMApplicationGateway_template(data) return fmt.Sprintf(` diff --git a/website/docs/r/application_gateway.html.markdown b/website/docs/r/application_gateway.html.markdown index 2c0b894f5754..5c6f4b5904a6 100644 --- a/website/docs/r/application_gateway.html.markdown +++ b/website/docs/r/application_gateway.html.markdown @@ -288,6 +288,10 @@ A `http_listener` block supports the following: * `host_name` - (Optional) The Hostname which should be used for this HTTP Listener. +* `host_names` - (Optional) A list of Hostname(s) should be used for this HTTP Listener. It allows special wildcard characters. + +-> **NOTE** The `host_names` and `host_name` are mutually exclusive and cannot both be set. + * `protocol` - (Required) The Protocol to use for this HTTP Listener. Possible values are `Http` and `Https`. * `require_sni` - (Optional) Should Server Name Indication be Required? Defaults to `false`.