From ac57c8e4ef3e19596160911e0f9b218bfa636e9f Mon Sep 17 00:00:00 2001 From: Dave Pirotte Date: Mon, 11 Dec 2023 19:00:47 +0000 Subject: [PATCH 1/4] resource/aws_lb: Enable ALB connection logs --- internal/service/elbv2/load_balancer.go | 109 ++++++++++++ .../elbv2/load_balancer_data_source.go | 24 +++ .../elbv2/load_balancer_data_source_test.go | 3 + internal/service/elbv2/load_balancer_test.go | 161 ++++++++++++++++++ website/docs/r/lb.html.markdown | 7 + 5 files changed, 304 insertions(+) diff --git a/internal/service/elbv2/load_balancer.go b/internal/service/elbv2/load_balancer.go index 5ed5b623a11..728d44303ce 100644 --- a/internal/service/elbv2/load_balancer.go +++ b/internal/service/elbv2/load_balancer.go @@ -99,6 +99,35 @@ func ResourceLoadBalancer() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "connection_logs": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + DiffSuppressFunc: verify.SuppressMissingOptionalConfigurationBlock, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "bucket": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return !d.Get("connection_logs.0.enabled").(bool) + }, + }, + "enabled": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return !d.Get("connection_logs.0.enabled").(bool) + }, + }, + }, + }, + }, "customer_owned_ipv4_pool": { Type: schema.TypeString, Optional: true, @@ -398,6 +427,17 @@ func resourceLoadBalancerCreate(ctx context.Context, d *schema.ResourceData, met } } + if lbType == elbv2.LoadBalancerTypeEnumApplication { + if v, ok := d.GetOk("connection_logs"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + attributes = append(attributes, expandLoadBalancerConnectionLogsAttributes(v.([]interface{})[0].(map[string]interface{}), false)...) + } else { + attributes = append(attributes, &elbv2.LoadBalancerAttribute{ + Key: aws.String(loadBalancerAttributeConnectionLogsS3Enabled), + Value: flex.BoolValueToString(false), + }) + } + } + attributes = append(attributes, loadBalancerAttributes.expand(d, false)...) wait := false @@ -483,6 +523,10 @@ func resourceLoadBalancerRead(ctx context.Context, d *schema.ResourceData, meta return sdkdiag.AppendErrorf(diags, "setting access_logs: %s", err) } + if err := d.Set("connection_logs", []interface{}{flattenLoadBalancerConnectionLogsAttributes(attributes)}); err != nil { + return sdkdiag.AppendErrorf(diags, "setting connection_logs: %s", err) + } + loadBalancerAttributes.flatten(d, attributes) return diags @@ -505,6 +549,17 @@ func resourceLoadBalancerUpdate(ctx context.Context, d *schema.ResourceData, met } } + if d.HasChange("connection_logs") { + if v, ok := d.GetOk("connection_logs"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { + attributes = append(attributes, expandLoadBalancerConnectionLogsAttributes(v.([]interface{})[0].(map[string]interface{}), true)...) + } else { + attributes = append(attributes, &elbv2.LoadBalancerAttribute{ + Key: aws.String(loadBalancerAttributeConnectionLogsS3Enabled), + Value: flex.BoolValueToString(false), + }) + } + } + attributes = append(attributes, loadBalancerAttributes.expand(d, true)...) if len(attributes) > 0 { @@ -1072,6 +1127,39 @@ func expandLoadBalancerAccessLogsAttributes(tfMap map[string]interface{}, update return apiObjects } +func expandLoadBalancerConnectionLogsAttributes(tfMap map[string]interface{}, update bool) []*elbv2.LoadBalancerAttribute { + if tfMap == nil { + return nil + } + + var apiObjects []*elbv2.LoadBalancerAttribute + + if v, ok := tfMap["enabled"].(bool); ok { + apiObjects = append(apiObjects, &elbv2.LoadBalancerAttribute{ + Key: aws.String(loadBalancerAttributeConnectionLogsS3Enabled), + Value: flex.BoolValueToString(v), + }) + + if v { + if v, ok := tfMap["bucket"].(string); ok && (update || v != "") { + apiObjects = append(apiObjects, &elbv2.LoadBalancerAttribute{ + Key: aws.String(loadBalancerAttributeConnectionLogsS3Bucket), + Value: aws.String(v), + }) + } + + if v, ok := tfMap["prefix"].(string); ok && (update || v != "") { + apiObjects = append(apiObjects, &elbv2.LoadBalancerAttribute{ + Key: aws.String(loadBalancerAttributeConnectionLogsS3Prefix), + Value: aws.String(v), + }) + } + } + } + + return apiObjects +} + func flattenLoadBalancerAccessLogsAttributes(apiObjects []*elbv2.LoadBalancerAttribute) map[string]interface{} { if len(apiObjects) == 0 { return nil @@ -1093,6 +1181,27 @@ func flattenLoadBalancerAccessLogsAttributes(apiObjects []*elbv2.LoadBalancerAtt return tfMap } +func flattenLoadBalancerConnectionLogsAttributes(apiObjects []*elbv2.LoadBalancerAttribute) map[string]interface{} { + if len(apiObjects) == 0 { + return nil + } + + tfMap := map[string]interface{}{} + + for _, apiObject := range apiObjects { + switch k, v := aws.StringValue(apiObject.Key), apiObject.Value; k { + case loadBalancerAttributeConnectionLogsS3Enabled: + tfMap["enabled"] = flex.StringToBoolValue(v) + case loadBalancerAttributeConnectionLogsS3Bucket: + tfMap["bucket"] = aws.StringValue(v) + case loadBalancerAttributeConnectionLogsS3Prefix: + tfMap["prefix"] = aws.StringValue(v) + } + } + + return tfMap +} + func expandSubnetMapping(tfMap map[string]interface{}) *elbv2.SubnetMapping { if tfMap == nil { return nil diff --git a/internal/service/elbv2/load_balancer_data_source.go b/internal/service/elbv2/load_balancer_data_source.go index 5f5c7c049d8..256d08fd6f8 100644 --- a/internal/service/elbv2/load_balancer_data_source.go +++ b/internal/service/elbv2/load_balancer_data_source.go @@ -61,6 +61,26 @@ func DataSourceLoadBalancer() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "connection_logs": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "bucket": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "prefix": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, "customer_owned_ipv4_pool": { Type: schema.TypeString, Computed: true, @@ -270,6 +290,10 @@ func dataSourceLoadBalancerRead(ctx context.Context, d *schema.ResourceData, met return sdkdiag.AppendErrorf(diags, "setting access_logs: %s", err) } + if err := d.Set("connection_logs", []interface{}{flattenLoadBalancerConnectionLogsAttributes(attributes)}); err != nil { + return sdkdiag.AppendErrorf(diags, "setting connection_logs: %s", err) + } + loadBalancerAttributes.flatten(d, attributes) tags, err := listTags(ctx, conn, d.Id()) diff --git a/internal/service/elbv2/load_balancer_data_source_test.go b/internal/service/elbv2/load_balancer_data_source_test.go index 0c178097032..5ba6c718b5f 100644 --- a/internal/service/elbv2/load_balancer_data_source_test.go +++ b/internal/service/elbv2/load_balancer_data_source_test.go @@ -161,6 +161,7 @@ func TestAccELBV2LoadBalancerDataSource_backwardsCompatibility(t *testing.T) { resource.TestCheckResourceAttrPair(dataSourceName1, "enable_http2", resourceName, "enable_http2"), resource.TestCheckResourceAttrPair(dataSourceName1, "enable_waf_fail_open", resourceName, "enable_waf_fail_open"), resource.TestCheckResourceAttrPair(dataSourceName1, "access_logs.#", resourceName, "access_logs.#"), + resource.TestCheckResourceAttrPair(dataSourceName1, "connection_logs.#", resourceName, "connection_logs.#"), resource.TestCheckResourceAttrPair(dataSourceName2, "name", resourceName, "name"), resource.TestCheckResourceAttrPair(dataSourceName2, "internal", resourceName, "internal"), resource.TestCheckResourceAttrPair(dataSourceName2, "subnets.#", resourceName, "subnets.#"), @@ -181,6 +182,7 @@ func TestAccELBV2LoadBalancerDataSource_backwardsCompatibility(t *testing.T) { resource.TestCheckResourceAttrPair(dataSourceName2, "enable_http2", resourceName, "enable_http2"), resource.TestCheckResourceAttrPair(dataSourceName2, "enable_waf_fail_open", resourceName, "enable_waf_fail_open"), resource.TestCheckResourceAttrPair(dataSourceName2, "access_logs.#", resourceName, "access_logs.#"), + resource.TestCheckResourceAttrPair(dataSourceName2, "connection_logs.#", resourceName, "connection_logs.#"), resource.TestCheckResourceAttrPair(dataSourceName3, "name", resourceName, "name"), resource.TestCheckResourceAttrPair(dataSourceName3, "internal", resourceName, "internal"), resource.TestCheckResourceAttrPair(dataSourceName3, "subnets.#", resourceName, "subnets.#"), @@ -201,6 +203,7 @@ func TestAccELBV2LoadBalancerDataSource_backwardsCompatibility(t *testing.T) { resource.TestCheckResourceAttrPair(dataSourceName3, "enable_http2", resourceName, "enable_http2"), resource.TestCheckResourceAttrPair(dataSourceName3, "enable_waf_fail_open", resourceName, "enable_waf_fail_open"), resource.TestCheckResourceAttrPair(dataSourceName3, "access_logs.#", resourceName, "access_logs.#"), + resource.TestCheckResourceAttrPair(dataSourceName3, "connection_logs.#", resourceName, "connection_logs.#"), ), }, }, diff --git a/internal/service/elbv2/load_balancer_test.go b/internal/service/elbv2/load_balancer_test.go index 3f5bcae5930..9dab5179d3f 100644 --- a/internal/service/elbv2/load_balancer_test.go +++ b/internal/service/elbv2/load_balancer_test.go @@ -87,6 +87,8 @@ func TestAccELBV2LoadBalancer_ALB_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "access_logs.#", "1"), resource.TestCheckResourceAttr(resourceName, "access_logs.0.enabled", "false"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "elasticloadbalancing", regexache.MustCompile(fmt.Sprintf("loadbalancer/app/%s/.+", rName))), + resource.TestCheckResourceAttr(resourceName, "connection_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.enabled", "false"), resource.TestCheckResourceAttr(resourceName, "desync_mitigation_mode", "defensive"), resource.TestCheckResourceAttrSet(resourceName, "dns_name"), resource.TestCheckResourceAttr(resourceName, "enable_deletion_protection", "false"), @@ -1120,6 +1122,139 @@ func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_accessLogsPrefix(t *testin }) } +func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_connectionLogs(t *testing.T) { + ctx := acctest.Context(t) + var conf elbv2.LoadBalancer + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_lb.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, elbv2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckLoadBalancerDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccLoadBalancerConfig_albConnectionLogs(true, rName, ""), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists(ctx, resourceName, &conf), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.bucket", rName), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.enabled", "true"), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.prefix", ""), + resource.TestCheckResourceAttr(resourceName, "connection_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.bucket", rName), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.prefix", ""), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccLoadBalancerConfig_albConnectionLogs(false, rName, ""), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists(ctx, resourceName, &conf), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.bucket", rName), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.enabled", "false"), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.prefix", ""), + resource.TestCheckResourceAttr(resourceName, "connection_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.bucket", rName), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.prefix", ""), + ), + }, + { + Config: testAccLoadBalancerConfig_albConnectionLogs(true, rName, ""), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists(ctx, resourceName, &conf), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.bucket", rName), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.enabled", "true"), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.prefix", ""), + resource.TestCheckResourceAttr(resourceName, "connection_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.bucket", rName), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.prefix", ""), + ), + }, + { + Config: testAccLoadBalancerConfig_albConnectionLogsNoBlocks(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists(ctx, resourceName, &conf), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.bucket", rName), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.enabled", "false"), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.prefix", ""), + resource.TestCheckResourceAttr(resourceName, "connection_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.bucket", rName), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.prefix", ""), + ), + }, + }, + }) +} + +func TestAccELBV2LoadBalancer_ApplicationLoadBalancer_connectionLogsPrefix(t *testing.T) { + ctx := acctest.Context(t) + var conf elbv2.LoadBalancer + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_lb.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, elbv2.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckLoadBalancerDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccLoadBalancerConfig_albConnectionLogs(true, rName, "prefix1"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists(ctx, resourceName, &conf), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.bucket", rName), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.enabled", "true"), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.prefix", "prefix1"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.bucket", rName), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.prefix", "prefix1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccLoadBalancerConfig_albConnectionLogs(true, rName, ""), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists(ctx, resourceName, &conf), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.bucket", rName), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.enabled", "true"), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.prefix", ""), + resource.TestCheckResourceAttr(resourceName, "connection_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.bucket", rName), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.prefix", ""), + ), + }, + { + Config: testAccLoadBalancerConfig_albConnectionLogs(true, rName, "prefix1"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckLoadBalancerExists(ctx, resourceName, &conf), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.bucket", rName), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.enabled", "true"), + testAccCheckLoadBalancerAttribute(ctx, resourceName, "connection_logs.s3.prefix", "prefix1"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.#", "1"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.bucket", rName), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "connection_logs.0.prefix", "prefix1"), + ), + }, + }, + }) +} + func TestAccELBV2LoadBalancer_NetworkLoadBalancer_accessLogs(t *testing.T) { ctx := acctest.Context(t) var conf elbv2.LoadBalancer @@ -2528,6 +2663,32 @@ resource "aws_lb" "test" { `, rName)) } +func testAccLoadBalancerConfig_albConnectionLogs(enabled bool, rName, bucketPrefix string) string { + return acctest.ConfigCompose(testAccLoadBalancerConfig_baseALBAccessLogs(rName), fmt.Sprintf(` +resource "aws_lb" "test" { + internal = true + name = %[1]q + subnets = aws_subnet.test[*].id + + connection_logs { + bucket = aws_s3_bucket_policy.test.bucket + enabled = %[2]t + prefix = %[3]q + } +} +`, rName, enabled, bucketPrefix)) +} + +func testAccLoadBalancerConfig_albConnectionLogsNoBlocks(rName string) string { + return acctest.ConfigCompose(testAccLoadBalancerConfig_baseALBAccessLogs(rName), fmt.Sprintf(` +resource "aws_lb" "test" { + internal = true + name = %[1]q + subnets = aws_subnet.test[*].id +} +`, rName)) +} + func testAccLoadBalancerConfig_baseNLBAccessLogs(rName string) string { return acctest.ConfigCompose(acctest.ConfigVPCWithSubnets(rName, 2), fmt.Sprintf(` resource "aws_s3_bucket" "test" { diff --git a/website/docs/r/lb.html.markdown b/website/docs/r/lb.html.markdown index fd43f7b625e..67a6ce809d1 100644 --- a/website/docs/r/lb.html.markdown +++ b/website/docs/r/lb.html.markdown @@ -102,6 +102,7 @@ resource "aws_lb" "example" { This resource supports the following arguments: * `access_logs` - (Optional) An Access Logs block. Access Logs documented below. +* `connection_logs` - (Optional) A Connection Logs block. Connection Logs documented below. Only valid for Load Balancers of type `application`. * `customer_owned_ipv4_pool` - (Optional) The ID of the customer owned ipv4 pool to use for this load balancer. * `desync_mitigation_mode` - (Optional) Determines how the load balancer handles requests that might pose a security risk to an application due to HTTP desync. Valid values are `monitor`, `defensive` (default), `strictest`. * `dns_record_client_routing_policy` - (Optional) Indicates how traffic is distributed among the load balancer Availability Zones. Possible values are `any_availability_zone` (default), `availability_zone_affinity`, or `partial_availability_zone_affinity`. See [Availability Zone DNS affinity](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html#zonal-dns-affinity) for additional details. Only valid for `network` type load balancers. @@ -136,6 +137,12 @@ for load balancers of type `network` will force a recreation of the resource. * `enabled` - (Optional) Boolean to enable / disable `access_logs`. Defaults to `false`, even when `bucket` is specified. * `prefix` - (Optional) The S3 bucket prefix. Logs are stored in the root if not configured. +### connection_logs + +* `bucket` - (Required) The S3 bucket name to store the logs in. +* `enabled` - (Optional) Boolean to enable / disable `connection_logs`. Defaults to `false`, even when `bucket` is specified. +* `prefix` - (Optional) The S3 bucket prefix. Logs are stored in the root if not configured. + ### subnet_mapping * `subnet_id` - (Required) ID of the subnet of which to attach to the load balancer. You can specify only one subnet per Availability Zone. From 418ee1390783e326020dc8fe5c762ecec41dc7fa Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 12 Dec 2023 15:34:03 -0500 Subject: [PATCH 2/4] Add CHANGELOG entry. --- .changelog/34864.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/34864.txt diff --git a/.changelog/34864.txt b/.changelog/34864.txt new file mode 100644 index 00000000000..9ea94e6e694 --- /dev/null +++ b/.changelog/34864.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_lb: Add `connection_logs` configuration block +``` + +```release-note:enhancement +data-source/aws_lb: Add `connection_logs` attribute +``` \ No newline at end of file From b7c969617f8bb0222d2ed5cd155cdeb5aaec1463 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 12 Dec 2023 15:40:14 -0500 Subject: [PATCH 3/4] TestAccELBV2LoadBalancer_NLB_basic: Check 'connection_logs'. --- internal/service/elbv2/load_balancer_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/service/elbv2/load_balancer_test.go b/internal/service/elbv2/load_balancer_test.go index 91fbd6f9ceb..207fcc19e0b 100644 --- a/internal/service/elbv2/load_balancer_test.go +++ b/internal/service/elbv2/load_balancer_test.go @@ -131,6 +131,7 @@ func TestAccELBV2LoadBalancer_NLB_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "access_logs.#", "1"), resource.TestCheckResourceAttr(resourceName, "access_logs.0.enabled", "false"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "elasticloadbalancing", regexache.MustCompile(fmt.Sprintf("loadbalancer/net/%s/.+", rName))), + resource.TestCheckResourceAttr(resourceName, "connection_logs.#", "0"), resource.TestCheckResourceAttrSet(resourceName, "dns_name"), resource.TestCheckResourceAttr(resourceName, "dns_record_client_routing_policy", "any_availability_zone"), resource.TestCheckResourceAttr(resourceName, "enable_deletion_protection", "false"), From dc7fbe278f1bc4a23b86ddcf83422a531ac5bd2a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 12 Dec 2023 16:02:45 -0500 Subject: [PATCH 4/4] r/aws_lb: Only flatten 'connection_logs' for ALBs. --- internal/service/elbv2/load_balancer.go | 9 ++++++--- internal/service/elbv2/load_balancer_test.go | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/service/elbv2/load_balancer.go b/internal/service/elbv2/load_balancer.go index d5cf371bd7b..849b31031a7 100644 --- a/internal/service/elbv2/load_balancer.go +++ b/internal/service/elbv2/load_balancer.go @@ -499,7 +499,8 @@ func resourceLoadBalancerRead(ctx context.Context, d *schema.ResourceData, meta d.Set("enforce_security_group_inbound_rules_on_private_link_traffic", lb.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic) d.Set("internal", aws.StringValue(lb.Scheme) == elbv2.LoadBalancerSchemeEnumInternal) d.Set("ip_address_type", lb.IpAddressType) - d.Set("load_balancer_type", lb.Type) + lbType := aws.StringValue(lb.Type) + d.Set("load_balancer_type", lbType) d.Set("name", lb.LoadBalancerName) d.Set("name_prefix", create.NamePrefixFromName(aws.StringValue(lb.LoadBalancerName))) d.Set("security_groups", aws.StringValueSlice(lb.SecurityGroups)) @@ -522,8 +523,10 @@ func resourceLoadBalancerRead(ctx context.Context, d *schema.ResourceData, meta return sdkdiag.AppendErrorf(diags, "setting access_logs: %s", err) } - if err := d.Set("connection_logs", []interface{}{flattenLoadBalancerConnectionLogsAttributes(attributes)}); err != nil { - return sdkdiag.AppendErrorf(diags, "setting connection_logs: %s", err) + if lbType == elbv2.LoadBalancerTypeEnumApplication { + if err := d.Set("connection_logs", []interface{}{flattenLoadBalancerConnectionLogsAttributes(attributes)}); err != nil { + return sdkdiag.AppendErrorf(diags, "setting connection_logs: %s", err) + } } loadBalancerAttributes.flatten(d, attributes) diff --git a/internal/service/elbv2/load_balancer_test.go b/internal/service/elbv2/load_balancer_test.go index 207fcc19e0b..8cab88eca2a 100644 --- a/internal/service/elbv2/load_balancer_test.go +++ b/internal/service/elbv2/load_balancer_test.go @@ -131,7 +131,7 @@ func TestAccELBV2LoadBalancer_NLB_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "access_logs.#", "1"), resource.TestCheckResourceAttr(resourceName, "access_logs.0.enabled", "false"), acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "elasticloadbalancing", regexache.MustCompile(fmt.Sprintf("loadbalancer/net/%s/.+", rName))), - resource.TestCheckResourceAttr(resourceName, "connection_logs.#", "0"), + resource.TestCheckNoResourceAttr(resourceName, "connection_logs.#"), resource.TestCheckResourceAttrSet(resourceName, "dns_name"), resource.TestCheckResourceAttr(resourceName, "dns_record_client_routing_policy", "any_availability_zone"), resource.TestCheckResourceAttr(resourceName, "enable_deletion_protection", "false"),