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
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.
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.
The commands displayed in the question show that the
-replace
instructed behavior is not part of theapply
command. There are two ways to fix this:Add the
-out
argument to theplan
to capture the plan output as a binary file for use withapply
:Add the
-replace
argument to theapply
command (which is technically aliased to theplan
command with an-apply
flag):