Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package k0sctl for openSUSE:Factory checked in at 2026-07-01 17:09:26 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/k0sctl (Old) and /work/SRC/openSUSE:Factory/.k0sctl.new.11887 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "k0sctl" Wed Jul 1 17:09:26 2026 rev:23 rq:1362970 version:0.31.1 Changes: -------- --- /work/SRC/openSUSE:Factory/k0sctl/k0sctl.changes 2026-06-18 18:45:32.433352640 +0200 +++ /work/SRC/openSUSE:Factory/.k0sctl.new.11887/k0sctl.changes 2026-07-01 17:09:58.726214598 +0200 @@ -1,0 +2,8 @@ +Wed Jul 01 11:44:58 UTC 2026 - Johannes Kastl <[email protected]> + +- Update to version 0.31.1: + * Bump github.com/k0sproject/rig from 0.21.10 to 0.21.11 (#1107) + * fix: normalize k0s node names before maintenance (#1095) + * Bump actions/checkout from 6 to 7 (#1105) + +------------------------------------------------------------------- Old: ---- k0sctl-0.31.0.obscpio New: ---- k0sctl-0.31.1.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ k0sctl.spec ++++++ --- /var/tmp/diff_new_pack.CLMZZl/_old 2026-07-01 17:10:03.122366238 +0200 +++ /var/tmp/diff_new_pack.CLMZZl/_new 2026-07-01 17:10:03.126366376 +0200 @@ -18,7 +18,7 @@ Name: k0sctl -Version: 0.31.0 +Version: 0.31.1 Release: 0 Summary: A bootstrapping and management tool for k0s clusters License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.CLMZZl/_old 2026-07-01 17:10:03.194368722 +0200 +++ /var/tmp/diff_new_pack.CLMZZl/_new 2026-07-01 17:10:03.214369411 +0200 @@ -2,7 +2,7 @@ <service name="obs_scm" mode="manual"> <param name="url">https://github.com/k0sproject/k0sctl.git</param> <param name="scm">git</param> - <param name="revision">v0.31.0</param> + <param name="revision">refs/tags/v0.31.1</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.CLMZZl/_old 2026-07-01 17:10:03.254370792 +0200 +++ /var/tmp/diff_new_pack.CLMZZl/_new 2026-07-01 17:10:03.262371068 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/k0sproject/k0sctl.git</param> - <param name="changesrevision">def1a095778cd5ca0ef703d9b6fe13789b17f67a</param></service></servicedata> + <param name="changesrevision">6bff2efc5590b3e569344cfcd68d9db164cc2881</param></service></servicedata> (No newline at EOF) ++++++ k0sctl-0.31.0.obscpio -> k0sctl-0.31.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/.github/workflows/actionlint.yml new/k0sctl-0.31.1/.github/workflows/actionlint.yml --- old/k0sctl-0.31.0/.github/workflows/actionlint.yml 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/.github/workflows/actionlint.yml 2026-06-29 12:30:26.000000000 +0200 @@ -8,7 +8,7 @@ actionlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: reviewdog/action-actionlint@v1 with: fail_on_error: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/.github/workflows/codeql-analysis.yml new/k0sctl-0.31.1/.github/workflows/codeql-analysis.yml --- old/k0sctl-0.31.0/.github/workflows/codeql-analysis.yml 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/.github/workflows/codeql-analysis.yml 2026-06-29 12:30:26.000000000 +0200 @@ -38,7 +38,7 @@ steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 # Added as suggested in https://github.com/github/codeql-action/issues/1842 to bring in a newer go than exists # preinstalled on the runners diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/.github/workflows/dco.yaml new/k0sctl-0.31.1/.github/workflows/dco.yaml --- old/k0sctl-0.31.0/.github/workflows/dco.yaml 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/.github/workflows/dco.yaml 2026-06-29 12:30:26.000000000 +0200 @@ -18,7 +18,7 @@ runs-on: ubuntu-24.04 steps: - name: Checkout k0s - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Set up Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@v6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/.github/workflows/go.yml new/k0sctl-0.31.1/.github/workflows/go.yml --- old/k0sctl-0.31.0/.github/workflows/go.yml 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/.github/workflows/go.yml 2026-06-29 12:30:26.000000000 +0200 @@ -16,7 +16,7 @@ runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up Go uses: actions/setup-go@v6 @@ -30,7 +30,7 @@ build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up Go uses: actions/setup-go@v6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/.github/workflows/golangci-lint.yml new/k0sctl-0.31.1/.github/workflows/golangci-lint.yml --- old/k0sctl-0.31.0/.github/workflows/golangci-lint.yml 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/.github/workflows/golangci-lint.yml 2026-06-29 12:30:26.000000000 +0200 @@ -10,7 +10,7 @@ runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Set up Go uses: actions/setup-go@v6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/.github/workflows/gomod-lint.yml new/k0sctl-0.31.1/.github/workflows/gomod-lint.yml --- old/k0sctl-0.31.0/.github/workflows/gomod-lint.yml 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/.github/workflows/gomod-lint.yml 2026-06-29 12:30:26.000000000 +0200 @@ -11,7 +11,7 @@ runs-on: ubuntu-latest steps: - name: Check out code into the Go module directory - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Set up Go uses: actions/setup-go@v6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/.github/workflows/release.yml new/k0sctl-0.31.1/.github/workflows/release.yml --- old/k0sctl-0.31.0/.github/workflows/release.yml 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/.github/workflows/release.yml 2026-06-29 12:30:26.000000000 +0200 @@ -14,7 +14,7 @@ packages: write # needed for ghcr access steps: - name: Check out code into the Go module directory - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Tag name id: tag-name diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/.github/workflows/smoke.yml new/k0sctl-0.31.1/.github/workflows/smoke.yml --- old/k0sctl-0.31.0/.github/workflows/smoke.yml 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/.github/workflows/smoke.yml 2026-06-29 12:30:26.000000000 +0200 @@ -16,7 +16,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Set up Go uses: actions/setup-go@v6 @@ -49,7 +49,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -68,7 +68,7 @@ steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -81,7 +81,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Build image @@ -102,7 +102,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -119,7 +119,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -137,7 +137,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests run: make smoke-files @@ -152,7 +152,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests run: make smoke-dynamic @@ -163,7 +163,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run OS override smoke test run: make smoke-os-override @@ -174,7 +174,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run k0sDownloadURL smoke test run: make smoke-downloadurl @@ -194,7 +194,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -215,7 +215,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -235,7 +235,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -255,7 +255,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -268,7 +268,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -286,7 +286,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -305,7 +305,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run smoke tests env: @@ -318,7 +318,7 @@ runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: ./.github/actions/smoke-test-cache - name: Run init smoke test run: make smoke-init diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/.github/workflows/update-latest-release.yml new/k0sctl-0.31.1/.github/workflows/update-latest-release.yml --- old/k0sctl-0.31.0/.github/workflows/update-latest-release.yml 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/.github/workflows/update-latest-release.yml 2026-06-29 12:30:26.000000000 +0200 @@ -20,7 +20,7 @@ runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: ref: ${{ github.sha }} fetch-depth: 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/go.mod new/k0sctl-0.31.1/go.mod --- old/k0sctl-0.31.0/go.mod 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/go.mod 2026-06-29 12:30:26.000000000 +0200 @@ -14,7 +14,7 @@ github.com/creasty/defaults v1.8.0 github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/k0sproject/dig v0.4.0 - github.com/k0sproject/rig v0.21.10 + github.com/k0sproject/rig v0.21.11 github.com/logrusorgru/aurora v2.0.3+incompatible github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect github.com/masterzen/winrm v0.0.0-20250927112105-5f8e6c707321 // indirect diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/go.sum new/k0sctl-0.31.1/go.sum --- old/k0sctl-0.31.0/go.sum 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/go.sum 2026-06-29 12:30:26.000000000 +0200 @@ -104,8 +104,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/k0sproject/dig v0.4.0 h1:yBxFUUxNXAMGBg6b7c6ypxdx/o3RmhoI5v5ABOw5tn0= github.com/k0sproject/dig v0.4.0/go.mod h1:rlZ7N7ZEcB4Fi96TPXkZ4dqyAiDWOGLapyL9YpZ7Qz4= -github.com/k0sproject/rig v0.21.10 h1:VcozC0Ctwl2Ceoo69LZ4twAPVpzhIjp9qfufmMnyO9s= -github.com/k0sproject/rig v0.21.10/go.mod h1:EgLRaRBorLg7aeYGjj2qISKdpU9oxSJxW0Ccjz3gieE= +github.com/k0sproject/rig v0.21.11 h1:hXElTYqYJeKj0FhSkPALXZIlZxyhDsnhKYqhk13MTzw= +github.com/k0sproject/rig v0.21.11/go.mod h1:EgLRaRBorLg7aeYGjj2qISKdpU9oxSJxW0Ccjz3gieE= github.com/k0sproject/version v0.8.0 h1:Yh1SFDeBqQ7etrGwffY8bWKdbAUjeBOhiZ6oQuuz4sM= github.com/k0sproject/version v0.8.0/go.mod h1:iNV3O8blndsQhxZ8zACfpQhrLDlrTvDlCzx+vgCFtSI= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/phase/gather_facts.go new/k0sctl-0.31.1/phase/gather_facts.go --- old/k0sctl-0.31.0/phase/gather_facts.go 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/phase/gather_facts.go 2026-06-29 12:30:26.000000000 +0200 @@ -77,8 +77,8 @@ } if h.HostnameOverride != "" { - log.Infof("%s: using %s from configuration as hostname", h, h.HostnameOverride) - h.Metadata.Hostname = h.HostnameOverride + h.Metadata.Hostname = strings.ToLower(h.HostnameOverride) + log.Infof("%s: using %s from configuration as hostname", h, h.Metadata.Hostname) } else { n := h.Configurer.Hostname(h) if n == "" { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/phase/gather_k0s_facts.go new/k0sctl-0.31.1/phase/gather_k0s_facts.go --- old/k0sctl-0.31.0/phase/gather_k0s_facts.go 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/phase/gather_k0s_facts.go 2026-06-29 12:30:26.000000000 +0200 @@ -414,7 +414,7 @@ } if !h.IsController() { - log.Infof("%s: checking if worker %s has joined", p.leader, h.Metadata.Hostname) + log.Infof("%s: checking if worker %s has joined", p.leader, h.KubernetesNodeName()) if err := node.KubeNodeReadyFunc(h)(ctx); err != nil { log.Debugf("%s: failed to get ready status: %s", h, err.Error()) } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/phase/reset_controllers.go new/k0sctl-0.31.1/phase/reset_controllers.go --- old/k0sctl-0.31.0/phase/reset_controllers.go 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/phase/reset_controllers.go 2026-06-29 12:30:26.000000000 +0200 @@ -82,7 +82,7 @@ if err := p.leader.DrainNode( &cluster.Host{ Metadata: cluster.HostMetadata{ - Hostname: h.Metadata.Hostname, + Hostname: h.KubernetesNodeName(), }, }, p.Config.Spec.Options.Drain, @@ -96,7 +96,7 @@ log.Debugf("%s: deleting node...", h) if err := p.leader.DeleteNode(&cluster.Host{ Metadata: cluster.HostMetadata{ - Hostname: h.Metadata.Hostname, + Hostname: h.KubernetesNodeName(), }, }); err != nil { log.Warnf("%s: failed to delete node: %s", h, err.Error()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/phase/reset_workers.go new/k0sctl-0.31.1/phase/reset_workers.go --- old/k0sctl-0.31.0/phase/reset_workers.go 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/phase/reset_workers.go 2026-06-29 12:30:26.000000000 +0200 @@ -81,7 +81,7 @@ if err := p.leader.DrainNode( &cluster.Host{ Metadata: cluster.HostMetadata{ - Hostname: h.Metadata.Hostname, + Hostname: h.KubernetesNodeName(), }, }, p.Config.Spec.Options.Drain, @@ -95,7 +95,7 @@ if !p.NoDelete { if err := p.leader.DeleteNode(&cluster.Host{ Metadata: cluster.HostMetadata{ - Hostname: h.Metadata.Hostname, + Hostname: h.KubernetesNodeName(), }, }); err != nil { log.Warnf("%s: failed to delete node: %s", h, err.Error()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/phase/validate_hosts.go new/k0sctl-0.31.1/phase/validate_hosts.go --- old/k0sctl-0.31.0/phase/validate_hosts.go 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/phase/validate_hosts.go 2026-06-29 12:30:26.000000000 +0200 @@ -39,7 +39,7 @@ controllerCount := len(p.Config.Spec.Hosts.Controllers()) var resetControllerCount int for _, h := range p.Config.Spec.Hosts { - p.hncount[h.Metadata.Hostname]++ + p.hncount[h.KubernetesNodeName()]++ if p.machineidcount != nil { p.machineidcount[h.Metadata.MachineID]++ } @@ -82,8 +82,8 @@ } func (p *ValidateHosts) validateUniqueHostname(_ context.Context, h *cluster.Host) error { - if p.hncount[h.Metadata.Hostname] > 1 { - return fmt.Errorf("hostname is not unique: %s", h.Metadata.Hostname) + if p.hncount[h.KubernetesNodeName()] > 1 { + return fmt.Errorf("hostname is not unique: %s", h.KubernetesNodeName()) } return nil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/phase/validate_hosts_test.go new/k0sctl-0.31.1/phase/validate_hosts_test.go --- old/k0sctl-0.31.0/phase/validate_hosts_test.go 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/phase/validate_hosts_test.go 2026-06-29 12:30:26.000000000 +0200 @@ -66,6 +66,43 @@ }) } +func TestValidateUniqueHostname(t *testing.T) { + makeHost := func(hostname string) *cluster.Host { + h := &cluster.Host{Configurer: &mockconfigurer{}} + h.Metadata.Hostname = hostname + return h + } + + t.Run("duplicate hostname same case", func(t *testing.T) { + hosts := cluster.Hosts{makeHost("worker-1"), makeHost("worker-1")} + p := &ValidateHosts{hncount: make(map[string]int, len(hosts))} + for _, h := range hosts { + p.hncount[h.KubernetesNodeName()]++ + } + require.Error(t, p.validateUniqueHostname(context.Background(), hosts[0])) + }) + + t.Run("duplicate hostname different case", func(t *testing.T) { + hosts := cluster.Hosts{makeHost("Worker-1"), makeHost("worker-1")} + p := &ValidateHosts{hncount: make(map[string]int, len(hosts))} + for _, h := range hosts { + p.hncount[h.KubernetesNodeName()]++ + } + require.Error(t, p.validateUniqueHostname(context.Background(), hosts[0])) + require.Error(t, p.validateUniqueHostname(context.Background(), hosts[1])) + }) + + t.Run("unique hostnames", func(t *testing.T) { + hosts := cluster.Hosts{makeHost("worker-1"), makeHost("worker-2")} + p := &ValidateHosts{hncount: make(map[string]int, len(hosts))} + for _, h := range hosts { + p.hncount[h.KubernetesNodeName()]++ + } + require.NoError(t, p.validateUniqueHostname(context.Background(), hosts[0])) + require.NoError(t, p.validateUniqueHostname(context.Background(), hosts[1])) + }) +} + func TestValidateConfigurer(t *testing.T) { p := &ValidateHosts{} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go new/k0sctl-0.31.1/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go --- old/k0sctl-0.31.0/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host.go 2026-06-29 12:30:26.000000000 +0200 @@ -55,9 +55,9 @@ Metadata HostMetadata `yaml:"-"` Configurer configurer.Configurer `yaml:"-"` - binaryProvider k0s.BinaryProvider // user-set override via SetK0sBinaryProvider - cachedDefaultProvider k0s.BinaryProvider // auto-built default; rebuilt when target changes - cachedDefaultProviderTarget *version.Version // target used to build cachedDefaultProvider + binaryProvider k0s.BinaryProvider // user-set override via SetK0sBinaryProvider + cachedDefaultProvider k0s.BinaryProvider // auto-built default; rebuilt when target changes + cachedDefaultProviderTarget *version.Version // target used to build cachedDefaultProvider } // SetK0sBinaryProvider overrides the binary acquisition strategy for this host. @@ -285,7 +285,6 @@ DryRunFakeLeader bool } - // Resolve prepares host-scoped data after unmarshalling by resolving upload files // and normalizing relative paths (like K0sBinaryPath) against baseDir. func (h *Host) Resolve(baseDir string) error { @@ -631,29 +630,35 @@ return h.DataDir } +// KubernetesNodeName returns the Kubernetes node name for this host. +// Hostnames are normalized to match the lowercase node names created by k0s. +func (h *Host) KubernetesNodeName() string { + return strings.ToLower(h.Metadata.Hostname) +} + // DrainNode drains the given node func (h *Host) DrainNode(node *Host, options DrainOption) error { - return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "drain %s %s", options.ToKubectlArgs(h.Configurer), quote(h.Configurer, node.Metadata.Hostname)), exec.Sudo(h)) + return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "drain %s %s", options.ToKubectlArgs(h.Configurer), quote(h.Configurer, node.KubernetesNodeName())), exec.Sudo(h)) } // CordonNode marks the node unschedulable func (h *Host) CordonNode(node *Host) error { - return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "cordon %s", quote(h.Configurer, node.Metadata.Hostname)), exec.Sudo(h)) + return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "cordon %s", quote(h.Configurer, node.KubernetesNodeName())), exec.Sudo(h)) } // UncordonNode marks the node schedulable func (h *Host) UncordonNode(node *Host) error { - return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "uncordon %s", quote(h.Configurer, node.Metadata.Hostname)), exec.Sudo(h)) + return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "uncordon %s", quote(h.Configurer, node.KubernetesNodeName())), exec.Sudo(h)) } // DeleteNode deletes the given node from kubernetes func (h *Host) DeleteNode(node *Host) error { - return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "delete node %s", quote(h.Configurer, node.Metadata.Hostname)), exec.Sudo(h)) + return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "delete node %s", quote(h.Configurer, node.KubernetesNodeName())), exec.Sudo(h)) } // Taints returns all taints added to the node. func (h *Host) Taints(node *Host) ([]string, error) { - output, err := h.ExecOutput(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), `get node %s -o jsonpath='{range .spec.taints[*]}{.key}={.value}:{.effect}{"\n"}{end}'`, quote(h.Configurer, node.Metadata.Hostname)), exec.Sudo(h)) + output, err := h.ExecOutput(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), `get node %s -o jsonpath='{range .spec.taints[*]}{.key}={.value}:{.effect}{"\n"}{end}'`, quote(h.Configurer, node.KubernetesNodeName())), exec.Sudo(h)) if err != nil { return nil, fmt.Errorf("failed to get node taints: %w", err) } @@ -662,7 +667,7 @@ // AddTaint adds a taint to the node. func (h *Host) AddTaint(node *Host, taint string) error { - return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "taint nodes --overwrite %s %s", quote(h.Configurer, node.Metadata.Hostname), quote(h.Configurer, taint)), exec.Sudo(h)) + return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "taint nodes --overwrite %s %s", quote(h.Configurer, node.KubernetesNodeName()), quote(h.Configurer, taint)), exec.Sudo(h)) } // RemoveTaint removes a taint from the node. @@ -675,7 +680,7 @@ // Removing a taint not on the node results in an error, so no action is taken return nil } - return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "taint nodes %s %s-", quote(h.Configurer, node.Metadata.Hostname), quote(h.Configurer, taint)), exec.Sudo(h)) + return h.Exec(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "taint nodes %s %s-", quote(h.Configurer, node.KubernetesNodeName()), quote(h.Configurer, taint)), exec.Sudo(h)) } // CheckHTTPStatus will perform a web request to the url and return an error if the http status is not the expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host_test.go new/k0sctl-0.31.1/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host_test.go --- old/k0sctl-0.31.0/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host_test.go 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/pkg/apis/k0sctl.k0sproject.io/v1beta1/cluster/host_test.go 2026-06-29 12:30:26.000000000 +0200 @@ -23,6 +23,11 @@ require.Equal(t, "k0scontroller", h.K0sServiceName()) } +func TestKubernetesNodeName(t *testing.T) { + h := Host{Metadata: HostMetadata{Hostname: "IN291O-worker-0"}} + require.Equal(t, "in291o-worker-0", h.KubernetesNodeName()) +} + type mockconfigurer struct { cfg.Linux linux.Ubuntu diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/k0sctl-0.31.0/pkg/node/statusfunc.go new/k0sctl-0.31.1/pkg/node/statusfunc.go --- old/k0sctl-0.31.0/pkg/node/statusfunc.go 2026-06-18 13:20:25.000000000 +0200 +++ new/k0sctl-0.31.1/pkg/node/statusfunc.go 2026-06-29 12:30:26.000000000 +0200 @@ -46,7 +46,8 @@ // On connection loss (e.g. SSH session dropped) it disconnects and reconnects so the next retry uses a fresh connection. func KubeNodeReadyFunc(h *cluster.Host) retryFunc { return func(_ context.Context) error { - output, err := h.ExecOutput(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "get node %s -o json", h.Configurer.Quote(h.Metadata.Hostname)), exec.HideOutput(), exec.Sudo(h)) + nodeName := h.KubernetesNodeName() + output, err := h.ExecOutput(h.Configurer.KubectlCmdf(h, h.K0sDataDir(), "get node %s -o json", h.Configurer.Quote(nodeName)), exec.HideOutput(), exec.Sudo(h)) if err != nil { err = fmt.Errorf("failed to get node status: %w", err) if IsConnectionError(err) { @@ -70,10 +71,10 @@ if c.Status == "True" { return nil } - return fmt.Errorf("node %s is not ready", h.Metadata.Hostname) + return fmt.Errorf("node %s is not ready", nodeName) } } - return fmt.Errorf("node %s 'Ready' condition not found", h.Metadata.Hostname) + return fmt.Errorf("node %s 'Ready' condition not found", nodeName) } } ++++++ k0sctl.obsinfo ++++++ --- /var/tmp/diff_new_pack.CLMZZl/_old 2026-07-01 17:10:03.682385555 +0200 +++ /var/tmp/diff_new_pack.CLMZZl/_new 2026-07-01 17:10:03.714386659 +0200 @@ -1,5 +1,5 @@ name: k0sctl -version: 0.31.0 -mtime: 1781781625 -commit: def1a095778cd5ca0ef703d9b6fe13789b17f67a +version: 0.31.1 +mtime: 1782729026 +commit: 6bff2efc5590b3e569344cfcd68d9db164cc2881 ++++++ vendor.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/github.com/k0sproject/rig/connection.go new/vendor/github.com/k0sproject/rig/connection.go --- old/vendor/github.com/k0sproject/rig/connection.go 2026-06-18 13:20:25.000000000 +0200 +++ new/vendor/github.com/k0sproject/rig/connection.go 2026-06-29 12:30:26.000000000 +0200 @@ -18,7 +18,6 @@ rigos "github.com/k0sproject/rig/os" ps "github.com/k0sproject/rig/pkg/powershell" "github.com/k0sproject/rig/pkg/rigfs" - "github.com/mattn/go-shellwords" ) const osWindows = "windows" @@ -266,34 +265,17 @@ return cmd } +// sudoSudo wraps the command in a shell invocation under sudo. Passing the command to +// "${SHELL:-sh}" -c as a single quoted argument ensures compound expressions (pipes, +// boolean lists, subshells, redirections) and inline KEY=VALUE assignments are interpreted +// by a shell rather than handed to sudo verbatim. This mirrors the doas decorator and the +// rig v2 sudo behavior. func sudoSudo(cmd string) string { - parts, err := shellwords.Parse(cmd) - if err != nil { - return "sudo -- " + cmd - } - - var idx int - for i, p := range parts { - if strings.Contains(p, "=") { - idx = i + 1 - continue - } - break - } - - if idx == 0 { - return "sudo -- " + cmd - } - - for i, p := range parts { - parts[i] = shellescape.Quote(p) - } - - return fmt.Sprintf("sudo %s -- %s", strings.Join(parts[0:idx], " "), strings.Join(parts[idx:], " ")) + return `sudo -n -- "${SHELL:-sh}" -c ` + shellescape.Quote(cmd) } func sudoDoas(cmd string) string { - return `doas -n -- "${SHELL-sh}" -c ` + shellescape.Quote(cmd) + return `doas -n -- "${SHELL:-sh}" -c ` + shellescape.Quote(cmd) } // sudoWindows is a no-op: the session already has effective administrator privileges. @@ -313,7 +295,7 @@ c.SetSudofn(sudoSudo) return } - if c.Exec(`doas -n -- "${SHELL-sh}" -c true`) == nil { + if c.Exec(`doas -n -- "${SHELL:-sh}" -c true`) == nil { // user has passwordless doas c.SetSudofn(sudoDoas) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt --- old/vendor/modules.txt 2026-06-18 13:20:25.000000000 +0200 +++ new/vendor/modules.txt 2026-06-29 12:30:26.000000000 +0200 @@ -168,7 +168,7 @@ # github.com/k0sproject/dig v0.4.0 ## explicit; go 1.21 github.com/k0sproject/dig -# github.com/k0sproject/rig v0.21.10 +# github.com/k0sproject/rig v0.21.11 ## explicit; go 1.26 github.com/k0sproject/rig github.com/k0sproject/rig/exec
