terraform-provider-openstack: openstack_networking_port_v2 all_fixed_ips is empty after creation (first run) but filled after rm from state (second run)
Terraform Version
Terraform v1.5.5
- provider registry.terraform.io/terraform-provider-openstack/openstack v1.52.1
Affected Resource(s)
Please list the resources as a list, for example:
- openstack_networking_port_v2
Terraform Configuration Files
resource "openstack_networking_port_v2" "vpn" {
name = "vpn"
network_id = var.network_id
admin_state_up = "true"
security_group_ids = [openstack_networking_secgroup_v2.vpn.id]
}
resource "openstack_networking_router_route_v2" "vpn" {
router_id = var.router_id
destination_cidr = var.cidr
next_hop = openstack_networking_port_v2.vpn.all_fixed_ips[0]
}
Debug Output
Panic Output
Expected Behavior
The openstack_networking_port_v2 is used as interface for an instance providing a VPN service. I port is used in order to have a fixed / known IP address. I would expect the IP of the port_v2 to be returned as first element in the all_fixed_ips array to then be used the next_hop for a static route.
In short: I want to route the network behind the VPN to the corresponding instance via a static route.
Actual Behavior
There are two errors thrown in relation to the port just created:
[...]
│ Error: Error creating OpenStack server: Bad request with: [POST https://compute.region.cloud.example.com/v2.1/servers], error message: {"badRequest": {"code": 400, "message": "Port ca6b83fd-e624-4e91-8dac-db291be55a42 requires a FixedIP in order to be used."}}
│
│ with module.vpn-server.openstack_compute_instance_v2.vpn,
│ on .terraform/modules/vpn-server/server/main.tf line 154, in resource "openstack_compute_instance_v2" "vpn":
│ 154: resource "openstack_compute_instance_v2" "vpn" {
│
╵
╷
│ Error: Invalid index
│
│ on .terraform/modules/vpn-server/server/main.tf line 181, in resource "openstack_networking_router_route_v2" "vpn":
│ 181: next_hop = openstack_networking_port_v2.vpn.all_fixed_ips[0]
│ ├────────────────
│ │ openstack_networking_port_v2.vpn.all_fixed_ips is empty list of string
│
│ The given key does not identify an element in this collection value: the collection has no elements.
[...]
causing the terraform run to abort with an error.
Steps to Reproduce
- After a
terraform applythe error is reached - Then
terraform state rm openstack_networking_port_v2.vpn terraform applyagain and things work just fine.
It seems the port resource takes longer to be fully created and initialized and the provider moves on too early. Just a refresh on the just created resource? Or some other indication of the port being actually done provisioning has to be tracked via the API?
Important Factoids
References
- The issue https://github.com/terraform-provider-openstack/terraform-provider-openstack/issues/1384 seems to also target the return addresses.
About this issue
- Original URL
- State: closed
- Created 10 months ago
- Comments: 16
Thank you as well for the patience. I’ve updated the docs so hopefully it will be clear for other users. I’ll close the issue.
I think it will tackle the root cause which based on the neutron people from launchpad is:
I’ve actually had deployments where this behavior occurred.
Explaining:
Currently you have this code:
This only says to TF that the
port resourceis dependent to thenetwork resource, nothing about the subnet. Based on the dependency graph TF will parallelize the creation of the subnet AND port => their creation will be triggered “at the same time” meaning you are in a race condition (which you have noticed). Sometimes it will work because internally on neutron level the subnet creation will be before the port creation and thus you will get an IP, other times it will be the opposite and you wont get an IP. If you look at your terraform apply output you probably will see something like:If you add switch your port resource to:
This will make known to TF that the port resources is dependant of the subnet => the TF depedency graph will force the subnet creation to be done before it triggers the port creation. So this should remove the race condition. Your terraform apply logs will look like:
depends_onwill have the same result but it is a bit more pesky to use when you have for_each etc to create multiple resources.Given the neutron people input, similar behaviors i’ve noticed and your input (race condition + not using
deferred) I am rather certain the above will fix it. I would prefer if you can test the above solution before we consider adding await.@frittentheke are you creating the subnet in the same run? and if so can you add a
depends_onon the port resource for the subnet, or alternatively define subnet_id in the port resource => https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_port_v2#subnet_id (inside thefixed_ipblock)?From their response this is expected if the subnet is not created. the above 2 options should force the port creation to happen after the subnet creation.
In the meantime ill try to find some time to check whether we can/should add a “wait” to the port resource.
The bug you opened is a way. there is already a response. Otherwise IRC channels are also an option: https://docs.openstack.org/contributors/common/irc.html
@nikParasyr thanks for the fast response!
I did run the scenario you asked for. Full disclosure, there are quite a few resources spawned and the port for the instance running the VPN services is created by a terraform module … but here we go:
all_fixed_ipsbeing empty.so
all_fixed_ipsis empty.all_fixed_ipsBut we dug a little deeper:
terraform refreshdoes NOT update theall_fixed_ips(if called implicitly by the apply or explicitly)terraform apply -target module.vpn-server.openstack_networking_port_v2.vpndoes “work”, but finds nothing that needs changing. So also then the field is not populated.terraform state rm module.vpn-server.openstack_networking_port_v2.vpnwhich I did initially of course caused a new port to be created leaving the first one dangling. But thenall_fixed_ipswas set, so the other resource referring that worked fine.This is the terraform debug output / openstack API response to the port creation (initial terraform apply):