skip to Main Content

I have a DynamoDB table that is created with some Terraform that starts off like this:

resource "aws_dynamodb_table" "mytable" {
  name         = "${var.environment_name}-mytable"

(let’s say that var.environment name is set to myenvironment)

I need to use terraform to replace it with an empty version of the table, for which I am trying to use the -replace argument, like so:

terraform plan -replace=aws_dynamodb_table.mytable -out plan.bin
terraform apply plan.bin

The problem is that doing this generates a ResourceInUseException:

Error: creating Amazon DynamoDB Table (myenvironment-mytable): ResourceInUseException: Table already exists: myenvironment-mytable

This gives me a double-bind.

If I change the table name in the -replace argument to match the name in the error message (ie. to be prefixed with the environment name) then it doesn’t find the table. Checking the name of the table with terraform state show and terraform state list confirms that indeed, terraform thinks the table name is not prefixed with the environment name, and it wants to operate on the table that way.

However, if I leave the table name alone (ie. don’t prefix the environment name) then I get the error above – it says it can’t replace it because it’s in use. Sure enough, if I look in DynamoDB using the AWS console, the table exists with a name that is prefixed with the environment name.

I found this question with an answer that suggests it maybe can’t cope with being asked to replace a table that already exists and I need to either delete or rename it first, but I’d really prefer not to do that – I want to do a create_before_replace (I’m not there yet!) and surely the whole point of -replace is that the resource must already exist or you wouldn’t be trying to replace it?

I don’t know how to resolve this. How do I tell Terraform which table it is I’m trying to replace without having it either fail to find it or complain that it’s already in use but named differently?

2

Answers


  1. Chosen as BEST ANSWER

    I have not been able to answer the original question (how to get -replace to work with a non-empty DynamoDB table) and my suspicion is that it isn't possible, that Terraform will not do an atomic replace on an existing non-empty table. But I don't know that for sure.

    What I have done is to do this non-atomically instead. This may be of use to some, and to others who want an answer to my original question, it may not be. But here's what I ended up doing.

    terraform plan -destroy -target=aws_dynamodb_table.mytable -out plan.bin
    terraform apply plan.bin
    terraform plan -out plan.bin
    terraform apply plan.bin
    

    This deletes the original table (it looks like it's destroying everything, but it doesn't) and then creates it again from the original plan. Terraform spits out a nasty warning that you shouldn't really use -target (because it leaves your configuration in a state that isn't the same as your configuration files), but as long as you remember it's done that and don't forget to re-create it again, this seems fine to me.

    I'm not accepting this answer because it doesn't answer the original question (it's a partial work-around) so if anyone does have an answer to the original question, I'm all ears!

    EDIT: Oh, noticeably, the table name is the one in the resource declaration (ie. without the environment name prepended) not the one from the "name" attribute.


  2. The commands displayed in the question show that the -replace instructed behavior is not part of the apply command. There are two ways to fix this:

    • Add the -out argument to the plan to capture the plan output as a binary file for use with apply:

      terraform plan -replace=aws_dynamodb_table.mytable -out plan.tfplan
      terraform apply plan.tfplan
      
    • Add the -replace argument to the apply command (which is technically aliased to the plan command with an -apply flag):

      terraform apply -replace=aws_dynamodb_table.mytable
      
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search