Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion phase/gather_k0s_facts.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,9 @@ func (p *GatherK0sFacts) investigateK0s(ctx context.Context, h *cluster.Host) er
}

if status.Role != h.Role {
return fmt.Errorf("%s: is configured as k0s %s but is already running as %s - role change is not supported", h, h.Role, status.Role)
if err := p.handleRoleMismatch(h, status.Role); err != nil {
return err
}
}

h.Metadata.K0sRunningVersion = status.Version
Expand Down Expand Up @@ -405,6 +407,20 @@ func (p *GatherK0sFacts) investigateK0s(ctx context.Context, h *cluster.Host) er
return nil
}

func (p *GatherK0sFacts) handleRoleMismatch(h *cluster.Host, detectedRole string) error {
if !h.Reset {
return fmt.Errorf("%s: is configured as k0s %s but is already running as %s - role change is not supported", h, h.Role, detectedRole)
}

if !Force {
return fmt.Errorf("%s: is configured as k0s %s but is already running as %s - role change is not supported, use --force to ignore the mismatch during reset", h, h.Role, detectedRole)
}

log.Warnf("%s: was configured as %s but is already running as %s - proceeding with reset using the discovered role because --force was given", h, h.Role, detectedRole)
h.Role = detectedRole
return nil
}

func (p *GatherK0sFacts) needsUpgrade(h *cluster.Host) bool {
if h.Reset {
return false
Expand Down
30 changes: 30 additions & 0 deletions phase/gather_k0s_facts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,33 @@ func TestReportUseExistingHostsFailsWithoutBinary(t *testing.T) {
p.SetManager(mgr)
require.ErrorContains(t, p.reportUseExistingHosts(), "useExistingK0s=true but no k0s binary found on host")
}

func TestHandleRoleMismatch(t *testing.T) {
originalForce := Force
t.Cleanup(func() { Force = originalForce })

p := GatherK0sFacts{}

t.Run("host not marked for reset", func(t *testing.T) {
Force = true
h := &cluster.Host{Role: "controller"}
err := p.handleRoleMismatch(h, "worker")
require.ErrorContains(t, err, "role change is not supported")
require.Equal(t, "controller", h.Role)
})

t.Run("reset host requires force", func(t *testing.T) {
Force = false
h := &cluster.Host{Role: "controller", Reset: true}
err := p.handleRoleMismatch(h, "single")
require.ErrorContains(t, err, "use --force")
require.Equal(t, "controller", h.Role)
})

t.Run("force allows role update", func(t *testing.T) {
Force = true
h := &cluster.Host{Role: "controller", Reset: true}
require.NoError(t, p.handleRoleMismatch(h, "worker"))
require.Equal(t, "worker", h.Role)
})
}