diff --git a/internal/services/network/application_gateway_resource.go b/internal/services/network/application_gateway_resource.go index 47ab875139f9..7a36a2a08d67 100644 --- a/internal/services/network/application_gateway_resource.go +++ b/internal/services/network/application_gateway_resource.go @@ -409,6 +409,24 @@ func resourceApplicationGateway() *pluginsdk.Resource { }, }, + "global": { + Type: pluginsdk.TypeList, + MaxItems: 1, + Optional: true, + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "request_buffering_enabled": { + Type: pluginsdk.TypeBool, + Required: true, + }, + "response_buffering_enabled": { + Type: pluginsdk.TypeBool, + Required: true, + }, + }, + }, + }, + //lintignore:S016,S023 "http_listener": { Type: pluginsdk.TypeSet, @@ -1561,6 +1579,11 @@ func resourceApplicationGatewayCreate(d *pluginsdk.ResourceData, meta interface{ gatewayIPConfigurations, stopApplicationGateway := expandApplicationGatewayIPConfigurations(d) + globalConfiguration, err := expandApplicationGatewayGlobalConfiguration(d.Get("global").([]interface{})) + if err != nil { + return fmt.Errorf("expanding `global`: %+v", err) + } + httpListeners, err := expandApplicationGatewayHTTPListeners(d, id.ID()) if err != nil { return fmt.Errorf("fail to expand `http_listener`: %+v", err) @@ -1585,6 +1608,7 @@ func resourceApplicationGatewayCreate(d *pluginsdk.ResourceData, meta interface{ FrontendIPConfigurations: expandApplicationGatewayFrontendIPConfigurations(d, id.ID()), FrontendPorts: expandApplicationGatewayFrontendPorts(d), GatewayIPConfigurations: gatewayIPConfigurations, + GlobalConfiguration: globalConfiguration, HTTPListeners: httpListeners, PrivateLinkConfigurations: expandApplicationGatewayPrivateLinkConfigurations(d), Probes: expandApplicationGatewayProbes(d), @@ -1793,6 +1817,15 @@ func resourceApplicationGatewayUpdate(d *pluginsdk.ResourceData, meta interface{ applicationGateway.ApplicationGatewayPropertiesFormat.GatewayIPConfigurations = gatewayIPConfigurations } + if d.HasChange("global") { + globalConfiguration, err := expandApplicationGatewayGlobalConfiguration(d.Get("global").([]interface{})) + if err != nil { + return fmt.Errorf("expanding `global`: %+v", err) + } + + applicationGateway.ApplicationGatewayPropertiesFormat.GlobalConfiguration = globalConfiguration + } + if d.HasChange("http_listener") { httpListeners, err := expandApplicationGatewayHTTPListeners(d, id.ID()) if err != nil { @@ -2052,6 +2085,10 @@ func resourceApplicationGatewayRead(d *pluginsdk.ResourceData, meta interface{}) return fmt.Errorf("setting `gateway_ip_configuration`: %+v", setErr) } + if setErr := d.Set("global", flattenApplicationGatewayGlobalConfiguration(props.GlobalConfiguration)); setErr != nil { + return fmt.Errorf("setting `global`: %+v", setErr) + } + if setErr := d.Set("private_endpoint_connection", flattenApplicationGatewayPrivateEndpoints(props.PrivateEndpointConnections)); setErr != nil { return fmt.Errorf("setting `private_endpoint_connection`: %+v", setErr) } @@ -2966,6 +3003,36 @@ func flattenApplicationGatewayIPConfigurations(input *[]network.ApplicationGatew return results } +func expandApplicationGatewayGlobalConfiguration(input []interface{}) (*network.ApplicationGatewayGlobalConfiguration, error) { + if len(input) == 0 { + return nil, nil + } + + v := input[0].(map[string]interface{}) + return &network.ApplicationGatewayGlobalConfiguration{ + EnableRequestBuffering: utils.Bool(v["request_buffering_enabled"].(bool)), + EnableResponseBuffering: utils.Bool(v["response_buffering_enabled"].(bool)), + }, nil +} + +func flattenApplicationGatewayGlobalConfiguration(input *network.ApplicationGatewayGlobalConfiguration) []interface{} { + if input == nil { + return nil + } + + output := make(map[string]interface{}) + + if input.EnableRequestBuffering != nil { + output["request_buffering_enabled"] = *input.EnableRequestBuffering + } + + if input.EnableResponseBuffering != nil { + output["response_buffering_enabled"] = *input.EnableResponseBuffering + } + + return []interface{}{output} +} + func expandApplicationGatewayFrontendPorts(d *pluginsdk.ResourceData) *[]network.ApplicationGatewayFrontendPort { vs := d.Get("frontend_port").(*pluginsdk.Set).List() results := make([]network.ApplicationGatewayFrontendPort, 0) diff --git a/internal/services/network/application_gateway_resource_test.go b/internal/services/network/application_gateway_resource_test.go index 68f1e833d7fd..f972e8f8e13c 100644 --- a/internal/services/network/application_gateway_resource_test.go +++ b/internal/services/network/application_gateway_resource_test.go @@ -89,6 +89,36 @@ func TestAccApplicationGateway_autoscaleConfigurationNoMaxCapacity(t *testing.T) }) } +func TestAccApplicationGateway_globalConfiguration(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_application_gateway", "test") + r := ApplicationGatewayResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.createGlobalConfiguration(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("sku.0.name").HasValue("Standard_v2"), + check.That(data.ResourceName).Key("sku.0.tier").HasValue("Standard_v2"), + check.That(data.ResourceName).Key("global.0.request_buffering_enabled").HasValue("true"), + check.That(data.ResourceName).Key("global.0.response_buffering_enabled").HasValue("true"), + ), + }, + data.ImportStep(), + { + Config: r.updateGlobalConfiguration(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("sku.0.name").HasValue("Standard_v2"), + check.That(data.ResourceName).Key("sku.0.tier").HasValue("Standard_v2"), + check.That(data.ResourceName).Key("global.0.request_buffering_enabled").HasValue("false"), + check.That(data.ResourceName).Key("global.0.response_buffering_enabled").HasValue("false"), + ), + }, + data.ImportStep(), + }) +} + func TestAccApplicationGateway_zones(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_application_gateway", "test") r := ApplicationGatewayResource{} @@ -1380,6 +1410,174 @@ resource "azurerm_application_gateway" "test" { `, r.template(data), data.RandomInteger, data.RandomInteger) } +func (r ApplicationGatewayResource) createGlobalConfiguration(data acceptance.TestData) string { + 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_public_ip" "test_standard" { + name = "acctest-pubip-standard-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + allocation_method = "Static" + sku = "Standard" +} + +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.test_standard.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 + } + + global { + request_buffering_enabled = true + response_buffering_enabled = 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 + priority = 10 + } +} +`, r.template(data), data.RandomInteger, data.RandomInteger) +} + +func (r ApplicationGatewayResource) updateGlobalConfiguration(data acceptance.TestData) string { + 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_public_ip" "test_standard" { + name = "acctest-pubip-standard-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + allocation_method = "Static" + sku = "Standard" +} + +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.test_standard.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 + } + + global { + request_buffering_enabled = false + response_buffering_enabled = false + } + + 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 + priority = 10 + } +} +`, r.template(data), data.RandomInteger, data.RandomInteger) +} + func (r ApplicationGatewayResource) UserDefinedIdentity(data acceptance.TestData) string { return fmt.Sprintf(` %s diff --git a/website/docs/r/application_gateway.html.markdown b/website/docs/r/application_gateway.html.markdown index edb1ef1a7ce9..946f55bffabd 100644 --- a/website/docs/r/application_gateway.html.markdown +++ b/website/docs/r/application_gateway.html.markdown @@ -137,6 +137,8 @@ The following arguments are supported: * `fips_enabled` - (Optional) Is FIPS enabled on the Application Gateway? +* `global` - (Optional) A `global` block as defined below. + * `identity` - (Optional) An `identity` block as defined below. * `private_link_configuration` - (Optional) One or more `private_link_configuration` blocks as defined below. @@ -437,6 +439,14 @@ A `request_routing_rule` block supports the following: --- +A `global` block supports the following: + +* `request_buffering_enabled` - (Required) Whether Application Gateway's Request buffer is enabled. + +* `response_buffering_enabled` - (Required) Whether Application Gateway's Response buffer is enabled. + +--- + A `sku` block supports the following: * `name` - (Required) The Name of the SKU to use for this Application Gateway. Possible values are `Standard_Small`, `Standard_Medium`, `Standard_Large`, `Standard_v2`, `WAF_Medium`, `WAF_Large`, and `WAF_v2`.