"""
In-memory stand-in for the NB client in netbox/dc-rack-mgmt-import.py.
No real NetBox / network access exists this session -- this fake implements just
the two methods the target script calls on its client (.one() and .create()) so the
REAL main()/preflight can be driven end-to-end without a live server. It is injected
at the get_nb() seam, exactly as tests/dc-edge-wan-import/ injects its fake.
FIDELITY NOTE. The target's real .one() issues GET ...?<filter>&limit=1 and takes
results[0] -- so it is single-match by construction and CANNOT raise on a duplicate
(unlike pynetbox.get(), which the older sibling fake models raising on multi-match).
This fake matches THAT contract: .one() returns the first record whose fields equal
the filter, or None. For an idempotency SKIP that is the safe direction -- a
pre-existing object reads as "present" and is not duplicated. .create() records every
write so a test can assert a rejected/dry run wrote NOTHING. The store is keyed by
path, so ipam/prefixes, ipam/roles, dcim/sites AND ipam/ip-addresses all work.
"""
from __future__ import annotations
class FakeNB:
def __init__(self, roles=(), prefixes=(), sites=(), ip_addresses=()):
# store: endpoint path -> list of record dicts (as the API would return them)
self.store = {
"ipam/roles": [dict(r) for r in roles],
"ipam/prefixes": [dict(p) for p in prefixes],
"dcim/sites": [dict(s) for s in sites],
"ipam/ip-addresses": [dict(a) for a in ip_addresses],
}
self.creates = [] # (path, payload) for every .create() -- the write ledger
self._next_id = 1000
def one(self, path, **flt):
for rec in self.store.get(path, []):
if all(str(rec.get(k)) == str(v) for k, v in flt.items()):
return rec
return None
def create(self, path, payload):
self.creates.append((path, dict(payload)))
rec = dict(payload)
rec["id"] = self._next_id
self._next_id += 1
self.store.setdefault(path, []).append(rec)
return rec