-
Notifications
You must be signed in to change notification settings - Fork 39
Open
Labels
type/bugSomething isn't working as expectedSomething isn't working as expected
Description
Component
API Server / GraphQL
Infrahub version
1.6.2
Current Behavior
When creating multiple nodes linked to the same peer that has a cardinality one constraint (at most one peer) in parallel, we may end up in a situation where multiple nodes are attached to this same peer.
Expected Behavior
Creating multiple nodes in parallel linked to the same cardinality one peer should allow only one successful creation.
Steps to Reproduce
load base schemas
infrahubctl schema load schema-library/base schema-library/extensions/location_minimal schema-library/extensions/compute/
infrahubctl object load objects/locations.yml
uv run reproducer.py
Should successfully create two interfaces linked to the same IP address.
Note: if you use the same interface name (for example eth0 on both interfaces), creation of one of the interfaces will fail (as expected). This is because internal locking is done on the uniqueness constaint.
#!/usr/bin/env python
# reproducer.py
import infrahub_sdk
from infrahub_sdk import InfrahubClientSync
client = InfrahubClientSync()
ip = client.create(kind="IpamIPAddress", data={"address": "10.0.0.1/24"})
ip.save(allow_upsert=True)
rack = client.create(kind="LocationRack", data={"name": "test-rack", "shortname": "test-rack"})
rack.save(allow_upsert=True)
device1 = client.create(kind="ComputePhysicalServer", data={"name": "serv1", "status": "active", "location": rack})
device1.save(allow_upsert=True)
device2 = client.create(kind="ComputePhysicalServer", data={"name": "serv2", "status": "active", "location": rack})
device2.save(allow_upsert=True)
intf1 = client.create(kind="InterfacePhysical", data={"name": "eth0", "device": device1, "ip_addresses": [ip]})
intf2 = client.create(kind="InterfacePhysical", data={"name": "eth1", "device": device2, "ip_addresses": [ip]})
batch = client.create_batch()
batch.add(task=intf1.save, allow_upsert=True)
batch.add(task=intf2.save, allow_upsert=True)
for _ in batch.execute():
print("executed batch")
# locations.yml
---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: LocationCountry
data:
- name: test-country
shortname: test-country
---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: LocationMetro
data:
- name: test-metro
shortname: test-metro
parent: test-country
---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: LocationSite
data:
- name: test-site
shortname: test-site
parent: test-metro
---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: LocationRack
data:
- name: test-rack
shortname: test-rack
parent: test-site
Additional Information
No response
coderabbitai
Metadata
Metadata
Assignees
Labels
type/bugSomething isn't working as expectedSomething isn't working as expected