Skip to content

Commit

Permalink
Merge pull request #40046 from hashicorp/b-dynamodb-table-ttl
Browse files Browse the repository at this point in the history
dynamodb/table: Fix ability to disable dynamodb table ttl
  • Loading branch information
YakDriver authored Nov 8, 2024
2 parents e7577bb + 2c5cfdc commit bd70cee
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 9 deletions.
3 changes: 3 additions & 0 deletions .changelog/40046.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/aws_dynamodb_table: Allow table TTL to be disabled by allowing `ttl[0].attribute_name` to be set when `ttl[0].enabled` is false
```
20 changes: 12 additions & 8 deletions internal/service/dynamodb/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,14 @@ func resourceTable() *schema.Resource {
"attribute_name": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
// AWS requires the attribute name to be set when disabling TTL but
// does not return it so it causes a diff.
if old == "" && new != "" && !d.Get("ttl.0.enabled").(bool) {
return true
}
return false
},
},
names.AttrEnabled: {
Type: schema.TypeBool,
Expand Down Expand Up @@ -2628,13 +2636,9 @@ func ttlPlantimeValidate(ttlPath cty.Path, ttl cty.Value, diags *diag.Diagnostic
errs.PathString(ttlPath.GetAttr("attribute_name")),
))
}
} else {
if !(attribute.IsNull() || attribute.AsString() == "") {
*diags = append(*diags, errs.NewAttributeConflictsWhenError(
ttlPath.GetAttr("attribute_name"),
ttlPath.GetAttr(names.AttrEnabled),
"false",
))
}
}

// !! Not a validation error for attribute_name to be set when enabled is false !!
// AWS *requires* attribute_name to be set when disabling TTL but does not return it, causing a diff.
// The diff is handled by DiffSuppressFunc of attribute_name.
}
80 changes: 79 additions & 1 deletion internal/service/dynamodb/table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"reflect"
"regexp"
"testing"
"time"

"github.com/YakDriver/regexache"
"github.com/aws/aws-sdk-go-v2/aws"
Expand Down Expand Up @@ -1557,7 +1558,7 @@ func TestAccDynamoDBTable_TTL_disabled(t *testing.T) {

// TTL tests must be split since it can only be updated once per hour
// ValidationException: Time to live has been modified multiple times within a fixed interval
func TestAccDynamoDBTable_TTL_update(t *testing.T) {
func TestAccDynamoDBTable_TTL_updateEnable(t *testing.T) {
ctx := acctest.Context(t)
var table awstypes.TableDescription
resourceName := "aws_dynamodb_table.test"
Expand Down Expand Up @@ -1606,6 +1607,83 @@ func TestAccDynamoDBTable_TTL_update(t *testing.T) {
})
}

// TestAccDynamoDBTable_TTL_updateDisable takes an hour because AWS does not allow disabling TTL
// for an hour after it was enabled. Otherwise, it will return the following error:
// ValidationException: Time to live has been modified multiple times within a fixed interval
// https://github.com/hashicorp/terraform-provider-aws/issues/39195
func TestAccDynamoDBTable_TTL_updateDisable(t *testing.T) {
ctx := acctest.Context(t)
if testing.Short() {
t.Skip("skipping long-running test in short mode")
}

var table awstypes.TableDescription
resourceName := "aws_dynamodb_table.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.DynamoDBServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckTableDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccTableConfig_timeToLive(rName, rName, true),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckInitialTableExists(ctx, resourceName, &table),
),
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("ttl"), knownvalue.ListExact([]knownvalue.Check{
knownvalue.ObjectExact(map[string]knownvalue.Check{
"attribute_name": knownvalue.StringExact(rName),
names.AttrEnabled: knownvalue.Bool(true),
}),
})),
},
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
PreConfig: func() {
// AWS does not allow disabling TTL for an hour after it was enabled. Otherwise, it
// will return the following error: ValidationException: Time to live has been
// modified multiple times within a fixed interval
time.Sleep(60 * time.Minute)
},
Config: testAccTableConfig_timeToLive(rName, rName, false), // can't disable without attribute_name (2nd arg)
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckInitialTableExists(ctx, resourceName, &table),
),
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("ttl"), knownvalue.ListExact([]knownvalue.Check{
knownvalue.ObjectExact(map[string]knownvalue.Check{
"attribute_name": knownvalue.StringExact(""), // set attribute_name, but returned empty; diff suppressed
names.AttrEnabled: knownvalue.Bool(false),
}),
})),
},
},
{
Config: testAccTableConfig_timeToLive(rName, rName, false),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckInitialTableExists(ctx, resourceName, &table),
),
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue(resourceName, tfjsonpath.New("ttl"), knownvalue.ListExact([]knownvalue.Check{
knownvalue.ObjectExact(map[string]knownvalue.Check{
"attribute_name": knownvalue.StringExact(""),
names.AttrEnabled: knownvalue.Bool(false),
}),
})),
},
},
},
})
}

func TestAccDynamoDBTable_TTL_validate(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand Down

0 comments on commit bd70cee

Please sign in to comment.