Skip to content

fix(k3s): count-up/respec join legacy (pre-K3sNode) clusters (bug 2)#116

Merged
astrojerms merged 1 commit into
mainfrom
fix/legacy-cluster-countup
Jul 8, 2026
Merged

fix(k3s): count-up/respec join legacy (pre-K3sNode) clusters (bug 2)#116
astrojerms merged 1 commit into
mainfrom
fix/legacy-cluster-countup

Conversation

@astrojerms

Copy link
Copy Markdown
Owner

Fixes Bug 2 from the 2026-07-07 recovery: converging an existing cluster created via the old inline path failed with resolve refs: K3sNode "dev-cp-0" not found — the Plan-based count-up pointed each new worker join at $ref(K3sNode/<cp>), but a legacy cluster has no K3sNode resource for its CPs, so the worker VM was created but never joined.

Fix

setJoin now branches on whether the surviving CP has a K3sNode resource:

  • Has one (Plan/K3sNode-built clusters) → keep the $ref, so the resolver still serializes install ordering.
  • Doesn't (legacy inline cluster) → resolve the join directly: CP IP from the cluster-state agent endpoints, node-token via SSH (cat /var/lib/rancher/k3s/server/node-token) behind a testable readCPNodeToken seam — and set concrete joinFrom/joinURLFrom values, which applyK3sNode already accepts as bare strings.

Both the count-up (addNodesViaPlan) and respec (respecNodesViaPlan) paths use it.

Tests

TestSetJoin_UsesRefWhenK3sNodeExists (CP has K3sNode state → $ref), TestSetJoin_ConcreteForLegacyCP (no K3sNode state → concrete values via the faked reader). Existing count-up/respec tests updated to seed the CP K3sNode state they implicitly assume (they exercise the Plan/K3sNode path). Full suite + -race, lint/staticcheck/modernize clean, make build green.

With #115 (bug 1), both recovery bugs are now fixed — and this one means openctl could have finished the dev-worker-0 rejoin itself.

Bug 2 from the 2026-07-07 recovery: converging an existing cluster
created via the old inline path failed with "resolve refs: K3sNode
dev-cp-0 not found" -- the Plan-based count-up pointed each new worker
join at $ref(K3sNode/<cp>), but a legacy cluster has no K3sNode resource
for its control planes, so the worker VM was created but never joined.

setJoin now branches: if the surviving CP has a K3sNode resource (Plan/
K3sNode-built clusters) it keeps the $ref so the resolver serializes
ordering; if not (legacy inline cluster), it resolves the join token +
IP directly -- CP IP from the cluster-state agent endpoints, node-token
via SSH (cat /var/lib/rancher/k3s/server/node-token) behind a testable
readCPNodeToken seam -- and sets concrete joinFrom/joinURLFrom values,
which applyK3sNode already accepts as bare strings. Both the count-up
(addNodesViaPlan) and respec (respecNodesViaPlan) paths use it.

Tests: setJoin uses a $ref when the CP has K3sNode state, and concrete
values (via the faked token reader) when it does not; existing count-up/
respec tests updated to seed the CP K3sNode state they implicitly assume
(they exercise the Plan/K3sNode path).
@astrojerms astrojerms merged commit 1bea00c into main Jul 8, 2026
6 checks passed
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.

1 participant