はじめに
Terraform の管理下から外したいときに使用する removed
ブロックですが、for_each などで作成した際に付与されるインデックスやキーがアドレス中にある場合エラーとなってしまいます。
GitHub の issue にもあがっていて、記事作成時点(2024.11.18)で Open のままです。
https://github.com/hashicorp/terraform/issues/34439
回避策としてワークアラウンド的になりますが、この issue 内にある moved
ブロックを経由してやる方法でうまくいったので、removed
ブロックが対応されるまでこの方法を使用することとしました。
https://github.com/hashicorp/terraform/issues/34439#issuecomment-2178128452
事象を改めて
バージョン関連
terraform {
required_version = "1.9.8"
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.75.0"
}
}
}
削除対象のリソース
variable "vpcs" {
type = map(string)
default = {
"vpc-sample-1" : "10.0.0.0/16"
"vpc-sample-2" : "10.1.0.0/16"
}
}
resource "aws_vpc" "sample" {
for_each = var.vpcs
cidr_block = each.value
instance_tenancy = "default"
tags = {
Name = each.key
}
}
以下のようにそのままアドレスを指定して実行すると
removed {
from = aws_vpc.sample["vpc-sample-1"]
lifecycle {
destroy = false # 実体は残すためのオプション
}
}
エラーとなります
│ Error: Resource instance keys not allowed
│
│ on 4_remove_block_with_for_each.tf line 20, in removed:
│ 20: from = aws_vpc.sample["vpc-sample-1"]
│
│ Resource address must be a resource (e.g. "test_instance.foo"), not a resource instance (e.g. "test_instance.foo[1]").
moved を経由しての回避策
以下の通り修正
# 差分抜粋
### vpc-sample-1
+ # moved ブロックを記載して、インデックスやキーが無いアドレスへ移動させます。
+ moved {
+ from = aws_vpc.sample["vpc-sample-1"]
+ to = aws_vpc.sample_vpc-sample-1
+ }
+
+ # removed ブロックでは上記で移動した先のアドレスを使用します。
removed {
- from = aws_vpc.sample["vpc-sample-1"]
+ from = aws_vpc.sample_vpc-sample-1
lifecycle {
destroy = false # 実体は残すためのオプション
}
}
# 全体
### vpc-sample-1
# moved ブロックを記載して、インデックスやキーが無いアドレスへ移動させます。
moved {
from = aws_vpc.sample["vpc-sample-1"]
to = aws_vpc.sample_vpc-sample-1
}
# removed ブロックでは上記で移動した先のアドレスを使用します。
removed {
from = aws_vpc.sample_vpc-sample-1
lifecycle {
destroy = false # 実体は残すためのオプション
}
}
### vpc-sample-2
moved {
from = aws_vpc.sample["vpc-sample-2"]
to = aws_vpc.sample_vpc-sample-2
}
removed {
from = aws_vpc.sample_vpc-sample-2
lifecycle {
destroy = false
}
}
apply します
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
Terraform will perform the following actions:
# aws_vpc.sample_vpc-sample-1 will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
# (moved from aws_vpc.sample["vpc-sample-1"])
. resource "aws_vpc" "sample_vpc-sample-1" {
id = "vpc-0707284a01204b7d8"
tags = {
"Name" = "vpc-sample-1"
}
# (19 unchanged attributes hidden)
}
# aws_vpc.sample_vpc-sample-2 will no longer be managed by Terraform, but will not be destroyed
# (destroy = false is set in the configuration)
# (moved from aws_vpc.sample["vpc-sample-2"])
. resource "aws_vpc" "sample_vpc-sample-2" {
id = "vpc-04492ed99b35fb8b0"
tags = {
"Name" = "vpc-sample-2"
}
# (19 unchanged attributes hidden)
}
Plan: 0 to add, 0 to change, 0 to destroy.
╷
│ Warning: Some objects will no longer be managed by Terraform
│
│ If you apply this plan, Terraform will discard its tracking information for the following objects, but it will not delete them:
│ - aws_vpc.sample_vpc-sample-1
│ - aws_vpc.sample_vpc-sample-2
│
│ After applying this plan, Terraform will no longer manage these objects. You will need to import them into Terraform to manage them again.
╵
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
moved
で一旦インデックスやキーを持たないアドレスに移動し、その後 removed
ブロックで管理下から外すことが出来ました!
Ref
おわりに
すぐにサポートされる可能性もありますが、ひとまずこの方法で回避可能です。issue の受け売りですが参考になれば幸いです。