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

resource/aws_ecs_service: Add versionConsistency support to container_definitions #40216

Merged
merged 6 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/40216.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_ecs_task_definition: Add `versionConsistency` argument to `container_definitions`
```
18 changes: 18 additions & 0 deletions internal/service/ecs/container_definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
_ "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"
"github.com/hashicorp/terraform-provider-aws/internal/enum"
tfjson "github.com/hashicorp/terraform-provider-aws/internal/json"
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
itypes "github.com/hashicorp/terraform-provider-aws/internal/types"
Expand Down Expand Up @@ -223,9 +224,26 @@ func expandContainerDefinitions(tfString string) ([]awstypes.ContainerDefinition
if itypes.IsZero(&apiObject) {
return nil, fmt.Errorf("invalid container definition supplied at index (%d)", i)
}
if !isValidVersionConsistency(apiObject) {
return nil, fmt.Errorf("invalid version consistency value (%[1]s) for container definition supplied at index (%[2]d)", apiObject.VersionConsistency, i)
}
}

containerDefinitions(apiObjects).compactArrays()

return apiObjects, nil
}

func isValidVersionConsistency(cd awstypes.ContainerDefinition) bool {
if cd.VersionConsistency == "" {
return true
}

for _, v := range enum.EnumValues[awstypes.VersionConsistency]() {
if cd.VersionConsistency == v {
return true
}
}

return false
}
30 changes: 30 additions & 0 deletions internal/service/ecs/container_definitions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -697,3 +697,33 @@ func TestContainerDefinitionsAreEquivalent_healthCheck(t *testing.T) {
t.Fatal("Expected definitions to be equal.")
}
}

func TestExpandContainerDefinitions_InvalidVersionConsistency(t *testing.T) {
t.Parallel()

cfgRepresention := `
[
{
"name": "wordpress",
"image": "wordpress",
"essential": true,
"portMappings": [
{
"containerPort": 80
}
],
"memory": 500,
"cpu": 10,
"versionConsistency": "invalid"
}
]`
_, err := expandContainerDefinitions(cfgRepresention)
if err == nil {
t.Fatal("Expected error")
}

expectedErr := "invalid version consistency value (invalid) for container definition supplied at index (0)"
if err.Error() != expectedErr {
t.Fatalf("Expected message '%[1]s', got '%[2]s'", expectedErr, err.Error())
}
}
144 changes: 144 additions & 0 deletions internal/service/ecs/task_definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func TestAccECSTaskDefinition_basic(t *testing.T) {
testAccCheckTaskDefinitionExists(ctx, resourceName, &def),
acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "ecs", regexache.MustCompile(fmt.Sprintf(`task-definition/%s:%s$`, rName, "1"))),
acctest.MatchResourceAttrRegionalARN(resourceName, "arn_without_revision", "ecs", regexache.MustCompile(fmt.Sprintf(`task-definition/%s$`, rName))),
acctest.CheckResourceAttrJMESNotExists(resourceName, "container_definitions", "[0].versionConsistency"),
resource.TestCheckResourceAttr(resourceName, "revision", "1"),
resource.TestCheckResourceAttr(resourceName, "track_latest", acctest.CtFalse),
),
Expand All @@ -120,6 +121,7 @@ func TestAccECSTaskDefinition_basic(t *testing.T) {
testAccCheckTaskDefinitionExists(ctx, resourceName, &def),
acctest.MatchResourceAttrRegionalARN(resourceName, names.AttrARN, "ecs", regexache.MustCompile(fmt.Sprintf(`task-definition/%s:%s$`, rName, "2"))),
acctest.MatchResourceAttrRegionalARN(resourceName, "arn_without_revision", "ecs", regexache.MustCompile(fmt.Sprintf(`task-definition/%s$`, rName))),
acctest.CheckResourceAttrJMESNotExists(resourceName, "container_definitions", "[0].versionConsistency"),
resource.TestCheckResourceAttr(resourceName, "revision", "2"),
),
},
Expand Down Expand Up @@ -1490,6 +1492,110 @@ func TestAccECSTaskDefinition_containerDefinitionNullPortMapping(t *testing.T) {
})
}

func TestAccECSTaskDefinition_containerDefinitionVersionConsistency(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_containerDefinitionVersionConsistency(rName, awstypes.VersionConsistencyDisabled),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckTaskDefinitionExists(ctx, resourceName, &def),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", "1"),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].versionConsistency", string(awstypes.VersionConsistencyDisabled)),
),
},
{
Config: testAccTaskDefinitionConfig_containerDefinitionVersionConsistency(rName, awstypes.VersionConsistencyEnabled),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckTaskDefinitionExists(ctx, resourceName, &def),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", "1"),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].versionConsistency", string(awstypes.VersionConsistencyEnabled)),
),
},
{
Config: testAccTaskDefinitionConfig_containerDefinitionVersionConsistency(rName, awstypes.VersionConsistencyDisabled),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckTaskDefinitionExists(ctx, resourceName, &def),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", "1"),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].versionConsistency", string(awstypes.VersionConsistencyDisabled)),
),
},
},
})
}

func TestAccECSTaskDefinition_containerDefinitionVersionConsistency_enabledToNull(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_containerDefinitionVersionConsistency(rName, awstypes.VersionConsistencyEnabled),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckTaskDefinitionExists(ctx, resourceName, &def),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", "1"),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].versionConsistency", string(awstypes.VersionConsistencyEnabled)),
),
},
{
Config: testAccTaskDefinitionConfig_containerDefinitionVersionConsistency_Null(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckTaskDefinitionExists(ctx, resourceName, &def),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", "1"),
acctest.CheckResourceAttrJMESNotExists(resourceName, "container_definitions", "[0].versionConsistency"),
),
},
},
})
}

func TestAccECSTaskDefinition_containerDefinitionVersionConsistency_nullToEnabled(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_containerDefinitionVersionConsistency_Null(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckTaskDefinitionExists(ctx, resourceName, &def),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", "1"),
acctest.CheckResourceAttrJMESNotExists(resourceName, "container_definitions", "[0].versionConsistency"),
),
},
{
Config: testAccTaskDefinitionConfig_containerDefinitionVersionConsistency(rName, awstypes.VersionConsistencyEnabled),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckTaskDefinitionExists(ctx, resourceName, &def),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "length(@)", "1"),
acctest.CheckResourceAttrJMES(resourceName, "container_definitions", "[0].versionConsistency", string(awstypes.VersionConsistencyEnabled)),
),
},
},
})
}

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 {
Expand Down Expand Up @@ -3471,3 +3577,41 @@ resource "aws_ecs_task_definition" "test" {
}
`, rName, image)
}

func testAccTaskDefinitionConfig_containerDefinitionVersionConsistency(rName string, versionConsistency awstypes.VersionConsistency) string {
return fmt.Sprintf(`
resource "aws_ecs_task_definition" "test" {
family = %[1]q
container_definitions = <<TASK_DEFINITION
[
{
"cpu": 10,
"image": "jenkins",
"memory": 128,
"name": "jenkins",
"versionConsistency": %[2]q
}
]
TASK_DEFINITION
}
`, rName, versionConsistency)
}

func testAccTaskDefinitionConfig_containerDefinitionVersionConsistency_Null(rName string) string {
return fmt.Sprintf(`
resource "aws_ecs_task_definition" "test" {
family = %[1]q
container_definitions = <<TASK_DEFINITION
[
{
"cpu": 10,
"image": "jenkins",
"essential": true,
"memory": 128,
"name": "jenkins"
}
]
TASK_DEFINITION
}
`, rName)
}
Loading