Thanks, Martin. You are correct. Unfortunately, it seems care must be taken when using a map for my resources. For example, I’m creating security group rules in openstack, and openstack doesn’t allow two identical security group rules to exist at the same time.
Whenever I would change the resource name key in the map I provided to Terraform, Terraform would occasionally try to create a security group rule under the new name before it deleted the old name. Since two identical rules can’t exist at the same time, it fails.
I guess what I am looking for is something to ensure all resources are destroyed first before anything is created, so if a resource is recalculated under a different key in the map, it won’t blow up because the old resource hadn’t been destroyed yet. Like a sort of lifecycle hint like destroy_all_before_create
or something.
Here’s an example:
locals {
sg = "02ef80a2-xxxx"
rulelist = [
{
name = "api"
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 443
port_range_max = 443
remotes = [
"192.168.100.101/32",
"192.168.100.102/32",
"192.168.100.103/32",
"192.168.100.104/32",
"192.168.100.105/32",
"192.168.100.106/32",
"192.168.100.107/32",
"192.168.100.108/32",
"192.168.100.109/32",
"192.168.100.110/32",
"192.168.100.111/32",
"192.168.100.112/32",
"192.168.100.113/32",
"192.168.100.114/32",
"192.168.100.115/32",
"192.168.100.116/32",
"192.168.100.117/32",
]
},
]
}
resource "openstack_networking_secgroup_rule_v2" "rule" {
for_each = {
for r in flatten(
[for rule in local.rulelist :
[for idx, remote in rule.remotes :
{
key = "${rule.name}_${idx}"
direction = rule.direction
ethertype = rule.ethertype
protocol = rule.protocol
port_range_min = rule.port_range_min
port_range_max = rule.port_range_max
remote_ip_prefix = remote
}
]
]
) :
r.key => r
}
security_group_id = local.sg
direction = each.value.direction
ethertype = each.value.ethertype
protocol = each.value.protocol
port_range_min = each.value.port_range_min
port_range_max = each.value.port_range_max
remote_ip_prefix = each.value.remote_ip_prefix
}
If I change the “name” of the rule (from “api” to “https”, for example), the resource names change from api_#
to https_#
. Some of new resources get created (same security group data) before the old ones are destroyed. It’s a bit of a race: the more rules I am creating, the more overlap in the destroy/create, and the greater odds are I’ll try to create a rule before the old one is destroyed:
Error: Error creating openstack_networking_secgroup_rule_v2: Expected HTTP response code [
] when accessing [POST https://myapi:9696/v2.0/security-group-rules], bu
t got 409 instead
{"NeutronError": {"message": "Security group rule already exists. Rule id is be581a65-xxxx.", "type": "SecurityGroupRuleExists", "detail": ""}}
on main.tf line 61, in resource "openstack_networking_secgroup_rule_v2" "rule":
61: resource "openstack_networking_secgroup_rule_v2" "rule" {
Some kind of lifecycle hint to tell Terraform it needs to destroy any old resources before creating any new resources would be very helpful here.