terraform version: 0.12.6
aws version: v2.22.0
new main.tf
resource "aws_instance" "this" {
for_each = {
1: ""
}
ami = var.ami
instance_type = var.instance_type
subnet_id = var.subnet_id
tags = merge(
var.tags,
{
"Name" = format("%s-%s-%s-%s", var.service, var.environment, var.region, each.key)
},
)
......
}
result:
# module.ec2.aws_instance.this[1] will be destroyed
- resource "aws_instance" "this" {
- ami = "ami-**********" -> null
..........
}
# module.ec2.aws_instance.this["1"] will be created
+ resource "aws_instance" "this" {
+ ami = "ami-*********"
..........
}
How can the resources not be recreate? Or how to replace index by string ?
Looking forward to your reply!
Thanks
Hi @lyc0221!
In order to get the benefits of for_each
youâll need to use string keys that are different than the integer indices you had before. Otherwise, for_each
will behave essentially the same as count
, including the issues with adding and removing items in the middle of the sequence.
Because Terraform therefore canât automatically know which indices in your old configuration relate to which string keys in your new configuration, unfortunately a more manual migration process is needed to tell Terraform how to rename each instance.
If you were to use the index and key that you showed in your example output, youâd move the existing object from one address to the other like this:
terraform state mv 'module.ec2.aws_instance.this[1]' 'module.ec2.aws_instance.this["1"]'
(the above uses Unix-style shell quoting syntax. If youâre on Windows then youâll need to use Windows-style escaping instead, like module.ec2.aws_instance.this[\"1\"]
.)
terraform state mv
directly modifies the Terraform state to move the object associated with the first address address to instead be correlated with the second address. Future runs of terraform plan
should therefore see that module.ec2.aws_instance.this["1"]
already exists and either leave it unchanged or plan to update it in-place.
As I mentioned above, in practice youâll likely want to use a more meaningful key to identify each element. Since your question doesnât include context about what real-world concept this instance represents Iâm going to just call it "foo"
for the sake of example:
resource "aws_instance" "this" {
for_each = {
"foo": ""
}
# ...
}
In this case, youâd move to module.ec2.aws_instance.this["foo"]
instead.
1 Like
Hi @apparentlymart
terraform state list
data.aws_ami.ubuntu_xenial
data.aws_subnet_ids.all
data.aws_vpc.default
null_resource.provisioning
module.ec2.data.template_file.userdata
module.ec2.aws_instance.this
module.security_group.aws_security_group.this
module.security_group.aws_security_group_rule.egress_rules
module.security_group.aws_security_group_rule.ingress_rules[0]
module.security_group.aws_security_group_rule.ingress_rules[1]
module.security_group.aws_security_group_rule.ingress_rules[2]
terraform state mv âmodule.ec2.aws_instance.thisâ âmodule.ec2.aws_instance.this[â1â]â
Move "module.ec2.aws_instance.this" to "module.ec2.aws_instance.this[\"1\"]"
Error: Invalid target address
Cannot move to module.ec2.aws_instance.this["1"]: module.ec2.aws_instance.this
does not exist in the current state.
Why can I not move to module.ec2.aws_instance.this
that is exist ?