Skip to content

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:

topology:
  nodes:
    r1:
      kind: frr
      extras:
        frr:
          daemons: [ospfd, bgpd]

now sets the daemons key on the node definition:

topology:
  nodes:
    r1:
      kind: frr
      daemons: [ospfd, bgpd]

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's appmgr directory 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:

│ recreate │ Pod       │ c9s-mv/sros                     │
│ update   │ Topology  │ c9s-mv/mv                       │

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 --cleanup no 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 in destroy --all from 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 their DOCKER-USER forwarding rules removed. #3471
  • A failed fresh c9s deploy no longer deletes a Topology that 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