Skip to content

Add support for L2VPN - #607

Open
flynn-nrg wants to merge 13 commits into
netbox-community:mainfrom
flynn-nrg:feat/l2pvn-crd
Open

Add support for L2VPN#607
flynn-nrg wants to merge 13 commits into
netbox-community:mainfrom
flynn-nrg:feat/l2pvn-crd

Conversation

@flynn-nrg

@flynn-nrg flynn-nrg commented Jul 31, 2026

Copy link
Copy Markdown

Add L2VPN and L2VPNClaim support

Adds L2VPN (Layer 2 VPN) management to the NetBox Operator, following the same claim/resource pattern already used for IP addresses, prefixes, IP ranges and ASNs.

New CRDs

  • L2VPN — represents a single L2VPN in NetBox (name, type, identifier/VNI, tenant, comments, description, custom fields, preserveInNetbox).
  • L2VPNClaim — claims an L2VPN identifier (VXLAN VNI) either as an exact identifier or from an identifierRangeStart/identifierRangeEnd range, and creates an owned L2VPN CR. identifier and the range fields are mutually exclusive (CEL validation) and immutable once set.

Controllers

  • L2VPNReconciler — reserves/updates the L2VPN in NetBox (ReserveOrUpdateL2VPN), finalizer-based cleanup (l2vpn.netbox.dev/finalizer), lease-locks the parent identifier range while the L2VPN is not yet Ready, reports conditions and events.
  • L2VPNClaimReconciler — restores a previously assigned identifier by hash before falling back to the explicit identifier or a new range-based allocation, syncs mutable fields down to the owned L2VPN, lease-locks per range to avoid races between concurrent claims (l2vpnclaim.netbox.dev/finalizer).

NetBox client

New methods on NetboxCompositeClient: ReserveOrUpdateL2VPN, DeleteL2VPN, RestoreExistingL2VPNByHash, GetAvailableL2VPNIdentifierByClaim (scans existing L2VPNs, since NetBox has no dedicated "available identifiers" endpoint for L2VPN). New L2VPN/L2VPNClaim models and regenerated mocks for the VpnL2vpns* API surface. The netboxOperatorRestorationHash custom field is extended to cover vpn.l2vpn in the kind data-load job.

Tests & docs

  • Unit tests for the NetBox client (pkg/netbox/api/l2vpn_test.go, l2vpn_claim_test.go) and for the controllers (internal/controller/l2vpn_controller_test.go, l2vpnclaim_controller_test.go), covering reservation, update, restoration-hash mismatch, reserve failure, range allocation, restore-by-hash, and lease-lock contention.
  • Chainsaw e2e tests under tests/e2e/l2vpn: explicit/range apply-update, range restore, range-exhausted, invalid tenant/custom-field, and owner-reference cases.
  • Sample manifests under config/samples/.
  • README section "L2VPN Management" documenting the L2VPN/L2VPNClaim model and usage.

Behaviour notes

  • Restoration hash makes identifier assignment sticky across CR re-creation; preserveInNetbox: true keeps the L2VPN in NetBox after CR deletion, enabling later reclaim.
  • name, type, identifier and tenant immutability enforced via CEL validation rules on both L2VPN and L2VPNClaim.

This was done with the help of Claude. I haven't seen anything in the docs about it so I assume it's fine.

@flynn-nrg
flynn-nrg marked this pull request as ready for review July 31, 2026 14:52
@bruelea

bruelea commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Hi @flynn-nrg, thanks for opening a PR.

If a l2vpnclaim CR is created with the "identifier" field, is it equivalent to creating a l2vpn CR?
We'll follow up with a more detailed review.

@flynn-nrg

Copy link
Copy Markdown
Author

Hi @flynn-nrg, thanks for opening a PR.

If a l2vpnclaim CR is created with the "identifier" field, is it equivalent to creating a l2vpn CR? We'll follow up with a more detailed review.

It follows the same pattern by the other claims like IpAddressClaim, so it will compute a restoration hash first and check if the matching object already exists. If not and there is a identifier it will be used directly to create a child L2VPN CR.

Mirrors the existing IpAddress/IpAddressClaim envtest + gomock pattern:
wires L2VPNReconciler/L2VPNClaimReconciler into the test manager with
dedicated MockVpnAPI instances per reconciler, and covers reservation,
update, restoration-hash mismatch, reserve failure, range allocation,
restore-by-hash, explicit identifier, and lease-lock contention.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants