Add unique constraint to IntegerKeyValueSetting.key

IntegerKeyValueSetting is used as a singleton-style key/value store:
callers do get(key=...) and get_or_create(key=..., ...) and assume at
most one row per key. The model, however, did not enforce uniqueness on
the key field, so nothing prevented duplicate rows at the database
level.

This was a real race for _create_soa_rdataset in catalog_zone_manager,
which calls get_or_create without select_for_update (unlike
increment_soa_serial, which does take a lock). Two concurrent AXFR
queries for a catalog zone could both pass the get_or_create existence
check and both insert a row for key='catalog-zone-soa-serial'. Every
subsequent IntegerKeyValueSetting.objects.get(key=...) call would then
raise MultipleObjectsReturned, breaking catalog-zone SOA rendering and
serial increments.

Add unique=True to the key CharField and ship migration 0003 to enforce
the invariant at the database level. Existing deployments are assumed to
have clean state (no duplicate keys); if duplicates exist, the migration
should be preceded by manual deduplication.
This commit is contained in:
sven authored and Sven Luthi committed 2026-08-11 12:10:07 +02:00
1 parent 55c562d5a7
commit ad0397bf61
2 files changed
+17 -1

No files matched your search

+1 -1
View File
@@ -7,7 +7,7 @@ import netbox_dns.models
class IntegerKeyValueSetting(models.Model):
_netbox_private = True
key = models.CharField(max_length=64)
key = models.CharField(max_length=64, unique=True)
value = models.IntegerField()
def __str__(self):