Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws_elb & aws_lb: Add desync_mitigation_mode #14764

Merged
merged 12 commits into from
Nov 22, 2021
15 changes: 15 additions & 0 deletions .changelog/14764.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
```release-note:enhancement
data-source/aws_elb: Add `desync_mitigation_mode` attribute
```

```release-note:enhancement
data-source/aws_lb: Add `desync_mitigation_mode` attribute
```

```release-note:enhancement
resource/aws_elb: Add `desync_mitigation_mode` argument
```

```release-note:enhancement
resource/aws_lb: Add `desync_mitigation_mode` argument
```
26 changes: 25 additions & 1 deletion internal/service/elb/load_balancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,17 @@ func ResourceLoadBalancer() *schema.Resource {
Computed: true,
},

"desync_mitigation_mode": {
Type: schema.TypeString,
Optional: true,
Default: "defensive",
ValidateFunc: validation.StringInSlice([]string{
"monitor",
"defensive",
"strictest",
}, false),
},

"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
},
Expand Down Expand Up @@ -453,6 +464,13 @@ func flattenLoadBalancerEResource(d *schema.ResourceData, ec2conn *ec2.EC2, elbc
}
}

for _, attr := range lbAttrs.AdditionalAttributes {
switch aws.StringValue(attr.Key) {
case "elb.http.desyncmitigationmode":
d.Set("desync_mitigation_mode", aws.StringValue(attr.Value))
}
}

tags, err := ListTags(elbconn, d.Id())

if err != nil {
Expand Down Expand Up @@ -580,10 +598,16 @@ func resourceLoadBalancerUpdate(d *schema.ResourceData, meta interface{}) error
}
}

if d.HasChanges("cross_zone_load_balancing", "idle_timeout", "access_logs") {
if d.HasChanges("cross_zone_load_balancing", "idle_timeout", "access_logs", "desync_mitigation_mode") {
attrs := elb.ModifyLoadBalancerAttributesInput{
LoadBalancerName: aws.String(d.Get("name").(string)),
LoadBalancerAttributes: &elb.LoadBalancerAttributes{
AdditionalAttributes: []*elb.AdditionalAttribute{
{
Key: aws.String("elb.http.desyncmitigationmode"),
Value: aws.String(d.Get("desync_mitigation_mode").(string)),
},
},
CrossZoneLoadBalancing: &elb.CrossZoneLoadBalancing{
Enabled: aws.Bool(d.Get("cross_zone_load_balancing").(bool)),
},
Expand Down
12 changes: 12 additions & 0 deletions internal/service/elb/load_balancer_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ func DataSourceLoadBalancer() *schema.Resource {
Set: schema.HashString,
},

"desync_mitigation_mode": {
Type: schema.TypeString,
Computed: true,
},

"tags": tftags.TagsSchemaComputed(),

"zone_id": {
Expand Down Expand Up @@ -304,6 +309,13 @@ func dataSourceLoadBalancerRead(d *schema.ResourceData, meta interface{}) error
}
}

for _, attr := range lbAttrs.AdditionalAttributes {
switch aws.StringValue(attr.Key) {
case "elb.http.desyncmitigationmode":
d.Set("desync_mitigation_mode", aws.StringValue(attr.Value))
}
}

tags, err := ListTags(conn, d.Id())

if err != nil {
Expand Down
1 change: 1 addition & 0 deletions internal/service/elb/load_balancer_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func TestAccELBLoadBalancerDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttr(dataSourceName, "internal", "true"),
resource.TestCheckResourceAttr(dataSourceName, "subnets.#", "2"),
resource.TestCheckResourceAttr(dataSourceName, "security_groups.#", "1"),
resource.TestCheckResourceAttr(dataSourceName, "desync_mitigation_mode", "defensive"),
resource.TestCheckResourceAttr(dataSourceName, "tags.%", "2"),
resource.TestCheckResourceAttr(dataSourceName, "tags.Name", rName),
resource.TestCheckResourceAttr(dataSourceName, "tags.TestName", t.Name()),
Expand Down
135 changes: 135 additions & 0 deletions internal/service/elb/load_balancer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func TestAccELBLoadBalancer_basic(t *testing.T) {
"lb_protocol": "http",
}),
resource.TestCheckResourceAttr(resourceName, "cross_zone_load_balancing", "true"),
resource.TestCheckResourceAttr(resourceName, "desync_mitigation_mode", "defensive"),
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
),
},
Expand Down Expand Up @@ -667,6 +668,71 @@ func TestAccELBLoadBalancer_securityGroups(t *testing.T) {
})
}

func TestAccELBLoadBalancer_desyncMitigationMode(t *testing.T) {
resourceName := "aws_elb.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, elb.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccLoadBalancerConfigDesyncMitigationMode,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "desync_mitigation_mode", "strictest"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccELBLoadBalancer_desyncMitigationMode_update(t *testing.T) {
resourceName := "aws_elb.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, elb.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckLoadBalancerDestroy,
Steps: []resource.TestStep{
{
Config: testAccLoadBalancerConfigDesyncMitigationMode_update_default,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "desync_mitigation_mode", "defensive"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccLoadBalancerConfigDesyncMitigationMode_update_monitor,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "desync_mitigation_mode", "monitor"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccLoadBalancerConfigDesyncMitigationMode_update_default,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "desync_mitigation_mode", "defensive"),
),
},
},
})
}

// Unit test for listeners hash
func TestLoadBalancerListenerHash(t *testing.T) {
cases := map[string]struct {
Expand Down Expand Up @@ -1839,3 +1905,72 @@ resource "aws_internet_gateway" "gw" {
}
}
`

const testAccLoadBalancerConfigDesyncMitigationMode = `
data "aws_availability_zones" "available" {
state = "available"

filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}

resource "aws_elb" "test" {
availability_zones = [data.aws_availability_zones.available.names[0]]
listener {
instance_port = 8000
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}

desync_mitigation_mode = "strictest"
}
`

const testAccLoadBalancerConfigDesyncMitigationMode_update_default = `
data "aws_availability_zones" "available" {
state = "available"

filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}

resource "aws_elb" "test" {
availability_zones = [data.aws_availability_zones.available.names[0]]

listener {
instance_port = 8000
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}
}
`

const testAccLoadBalancerConfigDesyncMitigationMode_update_monitor = `
data "aws_availability_zones" "available" {
state = "available"

filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}

resource "aws_elb" "test" {
availability_zones = [data.aws_availability_zones.available.names[0]]

listener {
instance_port = 8000
instance_protocol = "http"
lb_port = 80
lb_protocol = "http"
}

desync_mitigation_mode = "monitor"
}
`
29 changes: 29 additions & 0 deletions internal/service/elbv2/load_balancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,18 @@ func ResourceLoadBalancer() *schema.Resource {
Computed: true,
},

"desync_mitigation_mode": {
Type: schema.TypeString,
Optional: true,
Default: "defensive",
ValidateFunc: validation.StringInSlice([]string{
"monitor",
"defensive",
"strictest",
}, false),
DiffSuppressFunc: suppressIfLBTypeNot(elbv2.LoadBalancerTypeEnumApplication),
},

"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
},
Expand All @@ -263,6 +275,12 @@ func suppressIfLBType(t string) schema.SchemaDiffSuppressFunc {
}
}

func suppressIfLBTypeNot(t string) schema.SchemaDiffSuppressFunc {
return func(k string, old string, new string, d *schema.ResourceData) bool {
return d.Get("load_balancer_type").(string) != t
}
}

func resourceLoadBalancerCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).ELBV2Conn
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
Expand Down Expand Up @@ -468,6 +486,13 @@ func resourceLoadBalancerUpdate(d *schema.ResourceData, meta interface{}) error
})
}

if d.HasChange("desync_mitigation_mode") || d.IsNewResource() {
attributes = append(attributes, &elbv2.LoadBalancerAttribute{
Key: aws.String("routing.http.desync_mitigation_mode"),
Value: aws.String(d.Get("desync_mitigation_mode").(string)),
})
}

case elbv2.LoadBalancerTypeEnumGateway, elbv2.LoadBalancerTypeEnumNetwork:
if d.HasChange("enable_cross_zone_load_balancing") || d.IsNewResource() {
attributes = append(attributes, &elbv2.LoadBalancerAttribute{
Expand Down Expand Up @@ -805,6 +830,10 @@ func flattenResource(d *schema.ResourceData, meta interface{}, lb *elbv2.LoadBal
crossZoneLbEnabled := aws.StringValue(attr.Value) == "true"
log.Printf("[DEBUG] Setting NLB Cross Zone Load Balancing Enabled: %t", crossZoneLbEnabled)
d.Set("enable_cross_zone_load_balancing", crossZoneLbEnabled)
case "routing.http.desync_mitigation_mode":
desyncMitigationMode := aws.StringValue(attr.Value)
log.Printf("[DEBUG] Setting ALB Desync Mitigation Mode: %s", desyncMitigationMode)
d.Set("desync_mitigation_mode", desyncMitigationMode)
}
}

Expand Down
8 changes: 8 additions & 0 deletions internal/service/elbv2/load_balancer_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ func DataSourceLoadBalancer() *schema.Resource {
Computed: true,
},

"desync_mitigation_mode": {
Type: schema.TypeString,
Computed: true,
},

"tags": tftags.TagsSchemaComputed(),
},
}
Expand Down Expand Up @@ -290,6 +295,9 @@ func dataSourceLoadBalancerRead(d *schema.ResourceData, meta interface{}) error
case "load_balancing.cross_zone.enabled":
crossZoneLbEnabled := aws.StringValue(attr.Value) == "true"
d.Set("enable_cross_zone_load_balancing", crossZoneLbEnabled)
case "routing.http.desync_mitigation_mode":
desyncMitigationMode := aws.StringValue(attr.Value)
d.Set("desync_mitigation_mode", desyncMitigationMode)
}
}

Expand Down
5 changes: 5 additions & 0 deletions internal/service/elbv2/load_balancer_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func TestAccELBV2LoadBalancerDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "ip_address_type", resourceName, "ip_address_type"),
resource.TestCheckResourceAttrPair(dataSourceName, "subnet_mapping.#", resourceName, "subnet_mapping.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "desync_mitigation_mode", resourceName, "desync_mitigation_mode"),
resource.TestCheckResourceAttrPair(dataSourceName2, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName2, "internal", resourceName, "internal"),
resource.TestCheckResourceAttrPair(dataSourceName2, "subnets.#", resourceName, "subnets.#"),
Expand All @@ -55,6 +56,7 @@ func TestAccELBV2LoadBalancerDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName2, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName2, "ip_address_type", resourceName, "ip_address_type"),
resource.TestCheckResourceAttrPair(dataSourceName2, "subnet_mapping.#", resourceName, "subnet_mapping.#"),
resource.TestCheckResourceAttrPair(dataSourceName2, "desync_mitigation_mode", resourceName, "desync_mitigation_mode"),
resource.TestCheckResourceAttrPair(dataSourceName3, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName3, "internal", resourceName, "internal"),
resource.TestCheckResourceAttrPair(dataSourceName3, "subnets.#", resourceName, "subnets.#"),
Expand All @@ -70,6 +72,7 @@ func TestAccELBV2LoadBalancerDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName3, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName3, "ip_address_type", resourceName, "ip_address_type"),
resource.TestCheckResourceAttrPair(dataSourceName3, "subnet_mapping.#", resourceName, "subnet_mapping.#"),
resource.TestCheckResourceAttrPair(dataSourceName3, "desync_mitigation_mode", resourceName, "desync_mitigation_mode"),
),
},
},
Expand Down Expand Up @@ -197,6 +200,8 @@ resource "aws_lb" "test" {
idle_timeout = 30
enable_deletion_protection = false

desync_mitigation_mode = "defensive"

tags = {
Name = %[1]q
Config = "Basic"
Expand Down
Loading