From 36c1b1ad86d5d68d1da524ac7313615d043ea593 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 11:56:05 -0400 Subject: [PATCH 01/12] r/aws_ecs_task_definition: Use AWS SDK for Go v2 serializer for 'container_definitions'. --- internal/service/ecs/task_definition.go | 31 ---------------- .../ecs/task_definition_equivalency.go | 35 +++++++++++++++++++ 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/internal/service/ecs/task_definition.go b/internal/service/ecs/task_definition.go index b087c41fa85..c4e8a50be4c 100644 --- a/internal/service/ecs/task_definition.go +++ b/internal/service/ecs/task_definition.go @@ -26,10 +26,8 @@ import ( "github.com/hashicorp/terraform-provider-aws/internal/errs" "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" "github.com/hashicorp/terraform-provider-aws/internal/flex" - tfjson "github.com/hashicorp/terraform-provider-aws/internal/json" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" - itypes "github.com/hashicorp/terraform-provider-aws/internal/types" "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -1211,35 +1209,6 @@ func flattenFSxWinVolumeAuthorizationConfig(config *awstypes.FSxWindowsFileServe return items } -func flattenContainerDefinitions(apiObjects []awstypes.ContainerDefinition) (string, error) { - json, err := tfjson.EncodeToBytes(apiObjects) - if err != nil { - return "", err - } - - // Remove empty fields and convert first character of keys to lowercase. - json = tfjson.RemoveEmptyFields(json) - json = tfjson.KeyFirstLower(json) - - return string(json), nil -} - -func expandContainerDefinitions(tfString string) ([]awstypes.ContainerDefinition, error) { - var apiObjects []awstypes.ContainerDefinition - - if err := tfjson.DecodeFromString(tfString, &apiObjects); err != nil { - return nil, err - } - - for i, apiObject := range apiObjects { - if itypes.IsZero(&apiObject) { - return nil, fmt.Errorf("invalid container definition supplied at index (%d)", i) - } - } - - return apiObjects, nil -} - func expandTaskDefinitionEphemeralStorage(config []interface{}) *awstypes.EphemeralStorage { configMap := config[0].(map[string]interface{}) diff --git a/internal/service/ecs/task_definition_equivalency.go b/internal/service/ecs/task_definition_equivalency.go index 6947d99a884..3a76ea1c29d 100644 --- a/internal/service/ecs/task_definition_equivalency.go +++ b/internal/service/ecs/task_definition_equivalency.go @@ -4,11 +4,16 @@ package ecs import ( + "fmt" "sort" + _ "unsafe" "github.com/aws/aws-sdk-go-v2/aws" + _ "github.com/aws/aws-sdk-go-v2/service/ecs" awstypes "github.com/aws/aws-sdk-go-v2/service/ecs/types" + smithyjson "github.com/aws/smithy-go/encoding/json" tfjson "github.com/hashicorp/terraform-provider-aws/internal/json" + itypes "github.com/hashicorp/terraform-provider-aws/internal/types" ) func containerDefinitionsAreEquivalent(def1, def2 string, isAWSVPC bool) (bool, error) { @@ -143,3 +148,33 @@ func (cd containerDefinitions) orderContainers() { return aws.ToString(cd[i].Name) < aws.ToString(cd[j].Name) }) } + +//go:linkname serializeContainerDefinitions github.com/aws/aws-sdk-go-v2/service/ecs.awsAwsjson11_serializeDocumentContainerDefinitions +func serializeContainerDefinitions(v []awstypes.ContainerDefinition, value smithyjson.Value) error + +func flattenContainerDefinitions(apiObjects []awstypes.ContainerDefinition) (string, error) { + jsonEncoder := smithyjson.NewEncoder() + err := serializeContainerDefinitions(apiObjects, jsonEncoder.Value) + + if err != nil { + return "", err + } + + return jsonEncoder.String(), nil +} + +func expandContainerDefinitions(tfString string) ([]awstypes.ContainerDefinition, error) { + var apiObjects []awstypes.ContainerDefinition + + if err := tfjson.DecodeFromString(tfString, &apiObjects); err != nil { + return nil, err + } + + for i, apiObject := range apiObjects { + if itypes.IsZero(&apiObject) { + return nil, fmt.Errorf("invalid container definition supplied at index (%d)", i) + } + } + + return apiObjects, nil +} From f5334e57f94f884b1ff691c5e3d7219c9dfe0c9a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 13:19:49 -0400 Subject: [PATCH 02/12] Add 'TestAccECSTaskDefinition_containerDefinitionDockerLabels'. --- internal/service/ecs/task_definition_test.go | 68 ++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/internal/service/ecs/task_definition_test.go b/internal/service/ecs/task_definition_test.go index d4b78e2b316..c2b3c634451 100644 --- a/internal/service/ecs/task_definition_test.go +++ b/internal/service/ecs/task_definition_test.go @@ -1337,6 +1337,43 @@ func TestAccECSTaskDefinition_v5590ContainerDefinitionsRegression(t *testing.T) }) } +// https://github.com/hashicorp/terraform-provider-aws/issues/38782. +func TestAccECSTaskDefinition_containerDefinitionDockerLabels(t *testing.T) { + ctx := acctest.Context(t) + var def awstypes.TaskDefinition + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_ecs_task_definition.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTaskDefinitionDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccTaskDefinitionConfig_containerDefinitionDockerLabels(rName, "alpine"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckTaskDefinitionExists(ctx, resourceName, &def), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", acctest.Ct1), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "keys([0].dockerLabels) | contains(@, 'PROMETHEUS_EXPORTER_JOB_NAME')", acctest.CtTrue), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].dockerLabels.PROMETHEUS_EXPORTER_JOB_NAME", "my-job"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "keys([0].dockerLabels) | contains(@, 'PROMETHEUS_EXPORTER_PATH')", acctest.CtTrue), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].dockerLabels.PROMETHEUS_EXPORTER_PATH", "/prometheus"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "keys([0].dockerLabels) | contains(@, 'PROMETHEUS_EXPORTER_PORT')", acctest.CtTrue), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].dockerLabels.PROMETHEUS_EXPORTER_PORT", "12345"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "keys([0].dockerLabels) | contains(@, 'PROMETHEUS_TARGET')", acctest.CtTrue), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].dockerLabels.PROMETHEUS_TARGET", acctest.CtTrue), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "keys([0].dockerLabels) | contains(@, 'pROMETHEUS_EXPORTER_JOB_NAME')", acctest.CtFalse), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "keys([0].dockerLabels) | contains(@, 'pROMETHEUS_EXPORTER_PATH')", acctest.CtFalse), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "keys([0].dockerLabels) | contains(@, 'pROMETHEUS_EXPORTER_PORT')", acctest.CtFalse), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "keys([0].dockerLabels) | contains(@, 'pROMETHEUS_TARGET')", acctest.CtFalse), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].image", "alpine"), + ), + }, + }, + }) +} + func testAccCheckTaskDefinitionProxyConfiguration(after *awstypes.TaskDefinition, containerName string, proxyType string, ignoredUid string, ignoredGid string, appPorts string, proxyIngressPort string, proxyEgressPort string, egressIgnoredPorts string, egressIgnoredIPs string) resource.TestCheckFunc { @@ -3261,3 +3298,34 @@ resource "aws_ecs_task_definition" "test" { } `, rName, image) } + +func testAccTaskDefinitionConfig_containerDefinitionDockerLabels(rName, image string) string { + return fmt.Sprintf(` +resource "aws_ecs_task_definition" "test" { + family = %[1]q + container_definitions = jsonencode([ + { + name = "first" + image = %[2]q + cpu = 10 + memory = 512 + essential = true + + portMappings = [ + { + containerPort = 80 + hostPort = 80 + } + ] + + dockerLabels = { + "PROMETHEUS_TARGET" = "true" + "PROMETHEUS_EXPORTER_PORT" = "12345" + "PROMETHEUS_EXPORTER_PATH" = "/prometheus" + "PROMETHEUS_EXPORTER_JOB_NAME" = "my-job" + } + } + ]) +} +`, rName, image) +} From 5bf1732e6f906ac03ab53a8d964ce3257f03c6d0 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 13:22:22 -0400 Subject: [PATCH 03/12] Rename source files. --- .../{task_definition_equivalency.go => container_definitions.go} | 0 ...finition_equivalency_test.go => container_definitions_test.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename internal/service/ecs/{task_definition_equivalency.go => container_definitions.go} (100%) rename internal/service/ecs/{task_definition_equivalency_test.go => container_definitions_test.go} (100%) diff --git a/internal/service/ecs/task_definition_equivalency.go b/internal/service/ecs/container_definitions.go similarity index 100% rename from internal/service/ecs/task_definition_equivalency.go rename to internal/service/ecs/container_definitions.go diff --git a/internal/service/ecs/task_definition_equivalency_test.go b/internal/service/ecs/container_definitions_test.go similarity index 100% rename from internal/service/ecs/task_definition_equivalency_test.go rename to internal/service/ecs/container_definitions_test.go From 8418c3d08e34bf5b2263e70ba6857230b2144993 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 13:24:35 -0400 Subject: [PATCH 04/12] Additional comments. --- internal/service/ecs/container_definitions.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/service/ecs/container_definitions.go b/internal/service/ecs/container_definitions.go index 3a76ea1c29d..7b0697e83f0 100644 --- a/internal/service/ecs/container_definitions.go +++ b/internal/service/ecs/container_definitions.go @@ -149,6 +149,9 @@ func (cd containerDefinitions) orderContainers() { }) } +// Dirty hack to avoid any backwards compatibility issues with the AWS SDK for Go v2 migration. +// Reach down into the SDK and use the same serialization function that the SDK uses. +// //go:linkname serializeContainerDefinitions github.com/aws/aws-sdk-go-v2/service/ecs.awsAwsjson11_serializeDocumentContainerDefinitions func serializeContainerDefinitions(v []awstypes.ContainerDefinition, value smithyjson.Value) error From 827f709bd1a2a952d8c6124e0e823ed770242820 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 13:30:06 -0400 Subject: [PATCH 05/12] Add CHANGELOG entry. --- .changelog/#####.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/#####.txt diff --git a/.changelog/#####.txt b/.changelog/#####.txt new file mode 100644 index 00000000000..2417486ac49 --- /dev/null +++ b/.changelog/#####.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_ecs_task_definition: Prevent lowercasing of the first character of JSON keys in `container_definitions.dockerLabels` +``` \ No newline at end of file From 77b93c54bca0c0d59d8d5e35ee33ec3fd94a903b Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 14:37:58 -0400 Subject: [PATCH 06/12] Add 'TestAccECSTaskDefinition_containerDefinitionEmptyPortMappings'. # Conflicts: # internal/service/ecs/task_definition_test.go --- internal/service/ecs/task_definition_test.go | 109 +++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/internal/service/ecs/task_definition_test.go b/internal/service/ecs/task_definition_test.go index c2b3c634451..cf2bbfdad46 100644 --- a/internal/service/ecs/task_definition_test.go +++ b/internal/service/ecs/task_definition_test.go @@ -1337,6 +1337,97 @@ func TestAccECSTaskDefinition_v5590ContainerDefinitionsRegression(t *testing.T) }) } +// https://github.com/hashicorp/terraform-provider-aws/issues/38779. +func TestAccECSTaskDefinition_containerDefinitionEmptyPortMappings(t *testing.T) { + ctx := acctest.Context(t) + var def awstypes.TaskDefinition + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_ecs_task_definition.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID), + CheckDestroy: testAccCheckTaskDefinitionDestroy(ctx), + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "aws": { + Source: "hashicorp/aws", + VersionConstraint: "5.58.0", + }, + }, + Config: testAccTaskDefinitionConfig_containerDefinitionEmptyPortMappings(rName, "alpine"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckTaskDefinitionExists(ctx, resourceName, &def), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", acctest.Ct1), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].cpu", acctest.Ct10), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].essential", acctest.CtTrue), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].image", "alpine"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].memory", "512"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].name", "first"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length([0].portMappings)", acctest.Ct0), + ), + }, + // At v5.59.0 and v5.60.0, an empty port mapping was added. + { + ExternalProviders: map[string]resource.ExternalProvider{ + "aws": { + Source: "hashicorp/aws", + VersionConstraint: "5.60.0", + }, + }, + Config: testAccTaskDefinitionConfig_containerDefinitionEmptyPortMappings(rName, "jenkins"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckTaskDefinitionExists(ctx, resourceName, &def), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", acctest.Ct1), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].Cpu", acctest.Ct10), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].Essential", acctest.CtTrue), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].Image", "jenkins"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].Memory", "512"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].Name", "first"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length([0].PortMappings)", acctest.Ct1), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].PortMappings[0].AppProtocol", ""), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].PortMappings[0].Protocol", "tcp"), + ), + }, + // At v5.61.0, all empty values were removed. + { + ExternalProviders: map[string]resource.ExternalProvider{ + "aws": { + Source: "hashicorp/aws", + VersionConstraint: "5.61.0", + }, + }, + Config: testAccTaskDefinitionConfig_containerDefinitionEmptyPortMappings(rName, "nginx"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckTaskDefinitionExists(ctx, resourceName, &def), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", acctest.Ct1), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].cpu", acctest.Ct10), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].essential", acctest.CtTrue), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].image", "nginx"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].memory", "512"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].name", "first"), + acctest.CheckResourceAttrJMESNotExists(resourceName, "container_definitions", "[0].portMappings"), + ), + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Config: testAccTaskDefinitionConfig_containerDefinitionEmptyPortMappings(rName, "alpine"), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckTaskDefinitionExists(ctx, resourceName, &def), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", acctest.Ct1), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].cpu", acctest.Ct10), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].essential", acctest.CtTrue), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].image", "alpine"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].memory", "512"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].name", "first"), + acctest.CheckResourceAttrJMESNotExists(resourceName, "container_definitions", "[0].portMappings"), + ), + }, + }, + }) +} + // https://github.com/hashicorp/terraform-provider-aws/issues/38782. func TestAccECSTaskDefinition_containerDefinitionDockerLabels(t *testing.T) { ctx := acctest.Context(t) @@ -3299,6 +3390,24 @@ resource "aws_ecs_task_definition" "test" { `, rName, image) } +func testAccTaskDefinitionConfig_containerDefinitionEmptyPortMappings(rName, image string) string { + return fmt.Sprintf(` +resource "aws_ecs_task_definition" "test" { + family = %[1]q + container_definitions = jsonencode([ + { + name = "first" + image = %[2]q + cpu = 10 + memory = 512 + essential = true + portMappings = [] + } + ]) +} +`, rName, image) +} + func testAccTaskDefinitionConfig_containerDefinitionDockerLabels(rName, image string) string { return fmt.Sprintf(` resource "aws_ecs_task_definition" "test" { From 8716e04d5de14a797216c0c7f4d4b01f163f4e69 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 14:53:22 -0400 Subject: [PATCH 07/12] Fix up 'TestAccECSTaskDefinition_containerDefinitionEmptyPortMappings'. --- internal/service/ecs/task_definition_test.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/internal/service/ecs/task_definition_test.go b/internal/service/ecs/task_definition_test.go index cf2bbfdad46..a8351554c32 100644 --- a/internal/service/ecs/task_definition_test.go +++ b/internal/service/ecs/task_definition_test.go @@ -1368,7 +1368,7 @@ func TestAccECSTaskDefinition_containerDefinitionEmptyPortMappings(t *testing.T) acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length([0].portMappings)", acctest.Ct0), ), }, - // At v5.59.0 and v5.60.0, an empty port mapping was added. + // At v5.59.0 and v5.60.0, JSON keys were returned with leading capital letters. { ExternalProviders: map[string]resource.ExternalProvider{ "aws": { @@ -1385,9 +1385,7 @@ func TestAccECSTaskDefinition_containerDefinitionEmptyPortMappings(t *testing.T) acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].Image", "jenkins"), acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].Memory", "512"), acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].Name", "first"), - acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length([0].PortMappings)", acctest.Ct1), - acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].PortMappings[0].AppProtocol", ""), - acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].PortMappings[0].Protocol", "tcp"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length([0].PortMappings)", acctest.Ct0), ), }, // At v5.61.0, all empty values were removed. @@ -1410,6 +1408,7 @@ func TestAccECSTaskDefinition_containerDefinitionEmptyPortMappings(t *testing.T) acctest.CheckResourceAttrJMESNotExists(resourceName, "container_definitions", "[0].portMappings"), ), }, + // At v5.62.0, fidelity with v5.58 was restored. { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, Config: testAccTaskDefinitionConfig_containerDefinitionEmptyPortMappings(rName, "alpine"), @@ -1421,7 +1420,7 @@ func TestAccECSTaskDefinition_containerDefinitionEmptyPortMappings(t *testing.T) acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].image", "alpine"), acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].memory", "512"), acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].name", "first"), - acctest.CheckResourceAttrJMESNotExists(resourceName, "container_definitions", "[0].portMappings"), + acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length([0].portMappings)", acctest.Ct0), ), }, }, From c36a8fec9b72b90ace47e9e62803f55dc8a903be Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 14:55:12 -0400 Subject: [PATCH 08/12] Correct CHANGELOG entry file name. --- .changelog/{#####.txt => 38804.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{#####.txt => 38804.txt} (100%) diff --git a/.changelog/#####.txt b/.changelog/38804.txt similarity index 100% rename from .changelog/#####.txt rename to .changelog/38804.txt From 3754f2c965b1be71a06f18684d229df706a20c04 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 14:57:45 -0400 Subject: [PATCH 09/12] Update container_definitions.go --- internal/service/ecs/container_definitions.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/service/ecs/container_definitions.go b/internal/service/ecs/container_definitions.go index 7b0697e83f0..0e9b66b1da8 100644 --- a/internal/service/ecs/container_definitions.go +++ b/internal/service/ecs/container_definitions.go @@ -151,7 +151,6 @@ func (cd containerDefinitions) orderContainers() { // Dirty hack to avoid any backwards compatibility issues with the AWS SDK for Go v2 migration. // Reach down into the SDK and use the same serialization function that the SDK uses. -// //go:linkname serializeContainerDefinitions github.com/aws/aws-sdk-go-v2/service/ecs.awsAwsjson11_serializeDocumentContainerDefinitions func serializeContainerDefinitions(v []awstypes.ContainerDefinition, value smithyjson.Value) error From 5c7a216d7652d284cdfe14cd0e35a1da1a3ba05a Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 14:58:41 -0400 Subject: [PATCH 10/12] Run 'make fmt'. --- internal/service/ecs/container_definitions.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/service/ecs/container_definitions.go b/internal/service/ecs/container_definitions.go index 0e9b66b1da8..7b0697e83f0 100644 --- a/internal/service/ecs/container_definitions.go +++ b/internal/service/ecs/container_definitions.go @@ -151,6 +151,7 @@ func (cd containerDefinitions) orderContainers() { // Dirty hack to avoid any backwards compatibility issues with the AWS SDK for Go v2 migration. // Reach down into the SDK and use the same serialization function that the SDK uses. +// //go:linkname serializeContainerDefinitions github.com/aws/aws-sdk-go-v2/service/ecs.awsAwsjson11_serializeDocumentContainerDefinitions func serializeContainerDefinitions(v []awstypes.ContainerDefinition, value smithyjson.Value) error From 7ba1d8e4c777b2723a81ca41a7e5980726dc5b78 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 16:35:42 -0400 Subject: [PATCH 11/12] Fix golangci-lint 'revive'. --- internal/service/ecs/container_definitions.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/service/ecs/container_definitions.go b/internal/service/ecs/container_definitions.go index 7b0697e83f0..1dbcbd2bc5d 100644 --- a/internal/service/ecs/container_definitions.go +++ b/internal/service/ecs/container_definitions.go @@ -6,10 +6,10 @@ package ecs import ( "fmt" "sort" - _ "unsafe" + _ "unsafe" // Required for go:linkname "github.com/aws/aws-sdk-go-v2/aws" - _ "github.com/aws/aws-sdk-go-v2/service/ecs" + _ "github.com/aws/aws-sdk-go-v2/service/ecs" // Required for go:linkname awstypes "github.com/aws/aws-sdk-go-v2/service/ecs/types" smithyjson "github.com/aws/smithy-go/encoding/json" tfjson "github.com/hashicorp/terraform-provider-aws/internal/json" From 2ed43f56211641931e5a22227d65ad4795b3a635 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 9 Aug 2024 16:37:40 -0400 Subject: [PATCH 12/12] No longer used. --- internal/json/transform.go | 51 ------------------------- internal/json/transform_test.go | 68 --------------------------------- 2 files changed, 119 deletions(-) delete mode 100644 internal/json/transform.go delete mode 100644 internal/json/transform_test.go diff --git a/internal/json/transform.go b/internal/json/transform.go deleted file mode 100644 index 34ffbe8d551..00000000000 --- a/internal/json/transform.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package json - -import ( - "unicode" - "unicode/utf8" - - "github.com/hashicorp/terraform-provider-aws/internal/json/ujson" -) - -// KeyFirstLower converts the first letter of each key to lowercase. -func KeyFirstLower(in []byte) []byte { - out := make([]byte, 0, len(in)) - - err := ujson.Walk(in, func(_ int, key, value []byte) bool { - // Write to output. - if len(out) != 0 && ujson.ShouldAddComma(value, out[len(out)-1]) { - out = append(out, ',') - } - // key is the raw key of the current object or empty otherwise. - // It can be a double-quoted string or empty. - switch len(key) { - case 0: - case 1, 2: - // Empty key. - out = append(out, key...) - default: - } - if len(key) > 0 { - out = append(out, '"') - r, n := utf8.DecodeRune(key[1:]) - r = unicode.ToLower(r) - low := make([]byte, utf8.RuneLen(r)) - utf8.EncodeRune(low, r) - out = append(out, low...) - out = append(out, key[n+1:]...) - out = append(out, ':') - } - out = append(out, value...) - - return true - }) - - if err != nil { - return nil - } - - return out -} diff --git a/internal/json/transform_test.go b/internal/json/transform_test.go deleted file mode 100644 index e9b311f7f9e..00000000000 --- a/internal/json/transform_test.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package json_test - -import ( - "testing" - - "github.com/hashicorp/terraform-provider-aws/internal/json" -) - -func TestKeyFirstLower(t *testing.T) { - t.Parallel() - - testCases := []struct { - testName string - input string - want string - }{ - { - testName: "empty JSON", - input: "{}", - want: "{}", - }, - { - testName: "single field, lowercase", - input: `{ "key": 42 }`, - want: `{"key":42}`, - }, - { - testName: "single field, uppercase", - input: `{ "Key": 42 }`, - want: `{"key":42}`, - }, - { - testName: "multiple fields", - input: ` -[ - { - "Name": "FIRST", - "Image": "alpine", - "Cpu": 10, - "Memory": 512, - "Essential": true, - "PortMappings": [ - { - "ContainerPort": 80, - "HostPort": 80 - } - ] - } -] - `, - want: `[{"name":"FIRST","image":"alpine","cpu":10,"memory":512,"essential":true,"portMappings":[{"containerPort":80,"hostPort":80}]}]`, - }, - } - - for _, testCase := range testCases { - testCase := testCase - t.Run(testCase.testName, func(t *testing.T) { - t.Parallel() - - if got, want := string(json.KeyFirstLower([]byte(testCase.input))), testCase.want; got != want { - t.Errorf("KeyFirstLower(%q) = %q, want %q", testCase.input, got, want) - } - }) - } -}