Release 0.81#
2026-10-11 · Full Changelog
Breaking changes: node extras removed
The extras node field is removed. Every key it carried either moved to a kind-specific config key — set directly on the node definition — or was dead code and is dropped. A topology that still sets extras fails to parse with a pointer to the kind-specific config documentation.
Removed node extras#
The extras node field predates the kind-specific config mechanism introduced in 0.80, and everything it carried was either kind-specific or dead. With kind-specific config the proper home for kind-owned keys, extras is gone and its keys are set directly on the node definition:
| old key | new key | where |
|---|---|---|
extras.frr.daemons |
daemons |
frr/frrouting kinds |
extras.ceos-copy-to-flash |
copy-to-flash |
arista_ceos kind |
extras.k8s_kind.deploy.kubeconfig |
kubeconfig |
k8s-kind kind |
extras.k8s_kind.deploy.wait |
wait |
k8s-kind kind |
For example, a lab that selected the FRR daemons with extras:
now sets the daemons key on the node definition:
The migrated keys participate in the regular node > group > kinds > defaults inheritance, are validated per kind, and are modeled in the JSON schema. Magic variables are resolved in kind-specific config values, as they were in extras.
Two keys are dropped without replacement:
extras.srl-agents— the SR Linux agent spec copy into the node'sappmgrdirectory was removed in 0.74, leaving the key as a silent no-op in the Docker runtime.extras.mysocket-proxy— no consumer; the mysocketctl/border0 integration is long gone.
C9s dry-run plan shows pod replacements#
The c9s runtime's deploy --dry-run reported resource-level
changes only, while applying such a plan replaced the Pods of every node whose links changed —
seconds for container kinds, but a multi-minute reboot for VM-backed kinds. The plan now adds one
recreate Pod entry per affected node, so the preview shows the real lifecycle impact:
A link that is added, rewired, or deleted affects both of its endpoints, and only nodes whose Pod
exists and that are still desired get an entry. The lifecycle decision follows the node's
link-apply-mode override or the kind
default: live keeps the Pod and gets no entry, while restart and recreate both replace it and
are reported as recreate. When no kind resolver is available the plan degrades to the
conservative recreate default for every affected node, so pod replacements are over-reported
rather than hidden. See the dry-run documentation.
Done in #3473
Miscellaneous#
-
c9s runtime decoupling: the topology compiler moved from clabernetes to containerlab, and both compile with the same engine. #3458
-
destroy --cleanupno longer reports success when destroy failed: the cleanup error is joined with the destroy error instead of replacing it, the lab directories of failed labs are kept — preserving the state file a retry needs — and one unreadable topology no longer prevents the remaining labs indestroy --allfrom being destroyed. #3470 - Destroy no longer creates management networks as a side effect: networks missing from the host
are skipped while preparing the destroy copy, and networks recorded in the lab state but no
longer defined by the topology (for example after an overridden
--network) now get theirDOCKER-USERforwarding rules removed. #3471 - A failed fresh
c9sdeploy no longer deletes aTopologythat a concurrent deploy updated in the meantime: the rollback only deletes the topology this deploy created, so a running lab is not lost without warning. #3472