terraform-provider-aws: aws_dynamodb_table - with ttl disabled, can't "terraform apply" twice

This issue was originally opened by @nunoperalta as hashicorp/terraform#22942. It was migrated here as a result of the provider split. The original body of the issue is below.


Terraform Version

Terraform v0.12.9
+ provider.aws v2.30.0

Terraform Configuration Files

resource "aws_dynamodb_table" "dynamodb-testdb" {
  name           = "TestDb"
  billing_mode   = "PAY_PER_REQUEST"
  hash_key       = "PriKey"
  range_key      = "Quantity"

  attribute {
    name = "PriKey"
    type = "S"
  }

  attribute {
    name = "Quantity"
    type = "N"
  }

  ttl {
    attribute_name = "TimeToExist"
    enabled        = false
  }
}

Expected Behavior

When doing “terraform apply” twice, there should be no changes to make.

Actual Behavior

First “terraform apply” will create the DynamoDB table. However, second time, there will be a change at:

      ~ ttl {
          + attribute_name = "TimeToExist"
            enabled        = false
        }

If I confirm the change, I get this crash:

Error: error updating DynamoDB Table (TestDb) time to live: error updating DynamoDB Table (TestDb) Time To Live: ValidationException: TimeToLive is already disabled status code: 400, request id: XXXXXX

If I remove the “attribute_name”, I get this error:

The argument “attribute_name” is required, but no definition was found.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 42
  • Comments: 28 (1 by maintainers)

Most upvoted comments

The “ValidationException: TimeToLive is already disabled” error is quite annoying if you are trying to modularize this. As a work around, consider using a dynamic block.

credit: https://www.reddit.com/r/Terraform/comments/d1va2o/terrfaorm_support_null_block/

locals {
  ttl = (var.ttl_enable == true ? [
    {
      ttl_enable = var.ttl_enable
      ttl_attribute : var.ttl_attribute
    }
  ] : [])
}

...

  dynamic "ttl" {
    for_each = local.ttl
    content {
      enabled        = local.ttl[0].ttl_enable
      attribute_name = local.ttl[0].ttl_attribute
    }
  }

Curious, was there an actual fix to this?

still happening

Still happening.

The issue is still happening. I looked at the tfstate and the attribute name is not set if it is disabled.

This problem has existed for years on this thread alone and this is the new issue for this problem. This is just one of dozens of open bugs annoying my team with terraform at this juncture.

still happening

@kennethjmyers I have tried setting attribute_name to an empty string as suggested, but the apply gets rejected by AWS with a validation error:

Error: updating Amazon DynamoDB Table (ronnies-component-RonnieDB-sandbox): updating Time To Live: InvalidParameter: 1 validation error(s) found.
│ - minimum field size of 1, UpdateTimeToLiveInput.TimeToLiveSpecification.AttributeName.

Looking at the plan, it seems like terraform is taking a blank string in the table config and turning that into null:

      ~ ttl {
          - attribute_name = "ttl_field" -> null
          ~ enabled        = true -> false
        }

I’m using the typescript CDK @cdktf/provider-aws module 16.03 which is provider version 5.8.0

Steps to reproduce:

  1. create a table with ttl.enabled = true and ttl.attribute_name whatever
  2. set ttl.enabled = false and tt.attribute_name = ''
  3. terraform apply results in minimum field size of 1 validation error as above

In order to actually disable the TTL and have terraform stop trying to re-add attribute_name as in the OP of this issue, I need to follow these steps:

  1. create a table with ttl.enabled = true and ttl.attribute_name whatever
  2. set ttl.enabled = false and leave ttl.attribute_name unchanged
  3. terraform apply results in correct update to DynamoDB table
  4. now set ttl.attribute_name to empty string
  5. subsequent terraform plan/apply shows no changes required, as desired

Still happening

Sadly a dynamic block doesn’t work, with a block like

dynamic "ttl" {
    for_each = var.ttl_enabled ? [1] : []
    content {
      attribute_name = var.ttl_attribute
      enabled        = var.ttl_enabled
    }
  }

If you enable ttl it work, but then if you disable it, the block disappear and terraform doesn’t see you want a enabled=false and it doesn’t report any change and AWS keep the ttl settings.

I see that as a bug.

  • allow enable = false and no attribute_name, and/or
  • enforce enable = false when the ttl block isn’t present.

Still happening

still happening

Still happening…

^ +1

still happening in 4.9.0

Still happening with provider version 4.10.0

Still happening here ✋

As per this doc page

It can take up to one hour for the change to fully process. Any additional UpdateTimeToLive calls for the same table during this one hour duration result in a ValidationException. 

so we can’t really have this state reconciliation loop in Terraform…