What could be causing that ?
I refactored a module that creates an ec2 instance a lot of supplementary resources
Now I would like those resources to be managed by the new module so I moved them using terraform state move.
Example
Move "module.devops-infrastructure-al2[0].module.kms_keys.aws_kms_alias.this" to "module.aws_instances[0].module.kms_keys.aws_kms_alias.this"
Successfully moved 1 object(s).
The plan says it will be destroying instance 0 (a number) and creating instance “0” (a string). That’s where the mismatch between configuration and state is.
Hmm it is suspiscious and I need to look into it and figure out why one is a string and one is a number. I am using a instance_count variable that is a number for both modules.
Whenever you use for_each, the resource index will always be a string.
For the resource indexes to be numbers, you would need to use count instead:
module "aws_instances" {
count = length(var.ec2_instances)
# You would also need to change each use of:
# each.value
# into
# var.ec2_instances[count.index]
I should add, however, that it is almost always better to use for_each rather than count.
The only time you should use count is when all of the instances are completely identical to each other - however since you’re defining them via var.ec2_instances which seems to be a list, it suggests different items in the list have different properties.
The reason for this, is that if you later need to add/remove items from var.ec2_instances in a way that makes other items shift position in the list, Terraform will want to perform undesirable changes.
Let’s say you have [0], [1], and [2]. You decide to remove [1] but want to keep [2]. Terraform will now either destroy both [1] and [2], and then build a new [1] based on the old definition of [2] - or it will destroy [2] and try to in-place modify the old [1] to be like the definition of [2].
Therefore you should use for_each with meaningful names, unless all of the instantances are equivalent.
No, but why would you even want that? In the earlier part of your message you acknowledged that they are of different types.
If you really want to refer to your for_each instances via strings of “0” ”1” and “2”, then you can - but you’ll need to use terraform state mv again to add in the quotes around the strings.
The thing is I definitely don’t want those instances to go down - my goal after state moves is a plan with no changes
And it seems like the destruction/recreation is forced because of mismatch
The plan says it will be destroying instance 0 (a number) and creating instance “0” (a string). That’s where the mismatch between configuration and state is.
So I thought maybe if I used for each but referred to them via integer somehow I would be able to get a plan that sees no changes rather than forcing the destruction and creation of instances.
Hey Max,
Really appreciate you help here!
I have a module using count attribute
Purpose of module is to first check for user in a gcp group & then add him if not available.
Its working fine when terraform deployment is successful but when I retry terraform deployment, it tries to destroy the resource under that module.
So I put lifecycle (prevent destroy = true) but I am getting below error:
Error: Instance cannot be destroyed
on …/terraform-modules/group_member_addition/main.tf line 12:
Resource module.member_addition[0].googleworkspace_group_member.new_member has lifecycle.prevent_destroy set, but the plan calls for this resource to be destroyed. To avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or reduce the scope of the plan using the -target flag.