Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport release-1.29] Add integration tests around k0s reset #5338

Merged
merged 1 commit into from
Dec 11, 2024
Merged
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
1 change: 1 addition & 0 deletions inttest/Makefile.variables
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ smoketests := \
check-noderole-single \
check-openebs\
check-psp \
check-reset \
check-singlenode \
check-statussocket \
check-upgrade \
11 changes: 9 additions & 2 deletions inttest/backup/backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ func (s *BackupSuite) TestK0sGetsUp() {
s.Require().NoError(s.StopController(s.ControllerNode(0)))
_ = s.StopController(s.ControllerNode(1)) // No error check as k0s might have actually exited since etcd is not really happy

s.Require().NoError(s.Reset(s.ControllerNode(0)))
s.Require().NoError(s.Reset(s.ControllerNode(1)))
s.reset(s.ControllerNode(0))
s.reset(s.ControllerNode(1))

s.Require().NoError(s.restoreFunc())
s.Require().NoError(s.InitController(0, "--enable-worker"))
Expand All @@ -122,6 +122,13 @@ func (s *BackupSuite) TestK0sGetsUp() {
s.Require().NoError(s.VerifyFileSystemRestore())
}

func (s *BackupSuite) reset(name string) {
ssh, err := s.SSH(s.Context(), name)
s.Require().NoError(err)
defer ssh.Disconnect()
s.Require().NoError(ssh.Exec(s.Context(), "k0s reset --debug", common.SSHStreams{}))
}

type snapshot struct {
namespaces map[types.UID]string
services map[types.UID]string
Expand Down
51 changes: 41 additions & 10 deletions inttest/byocri/byocri_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package byocri

import (
"fmt"
"strings"
"testing"

"github.com/avast/retry-go"
Expand All @@ -31,21 +32,51 @@ type BYOCRISuite struct {
common.BootlooseSuite
}

func (s *BYOCRISuite) TestK0sGetsUp() {
func (s *BYOCRISuite) TestBringYourOwnCRI() {
ctx := s.Context()
workerNode := s.WorkerNode(0)

s.NoError(s.InitController(0))
s.Require().NoError(s.runDockerWorker())
if ok := s.Run("k0s gets up", func() {
s.NoError(s.InitController(0))
s.Require().NoError(s.runDockerWorker())

kc, err := s.KubeClient(s.ControllerNode(0))
s.Require().NoError(err)
kc, err := s.KubeClient(s.ControllerNode(0))
s.Require().NoError(err)

err = s.WaitForNodeReady(s.WorkerNode(0), kc)
s.NoError(err)
err = s.WaitForNodeReady(workerNode, kc)
s.NoError(err)

s.AssertSomeKubeSystemPods(kc)
s.AssertSomeKubeSystemPods(kc)

s.T().Log("waiting to see CNI pods ready")
s.NoError(common.WaitForKubeRouterReady(s.Context(), kc), "CNI did not start")
s.T().Log("waiting to see CNI pods ready")
s.NoError(common.WaitForKubeRouterReady(ctx, kc), "CNI did not start")
}); !ok {
return
}

s.Run("k0s reset terminates Docker containers", func() {
ssh, err := s.SSH(ctx, workerNode)
s.Require().NoError(err)
defer ssh.Disconnect()

var containerIDs strings.Builder
if s.NoError(ssh.Exec(ctx, "docker ps -q", common.SSHStreams{Out: &containerIDs}), "Failed to get running Docker containers") {
s.NotEmpty(containerIDs.String(), "Expected some running Docker containers")
}

s.NoError(s.StopWorker(workerNode), "Failed to stop k0s")

resetCmd := "k0s reset --debug --cri-socket remote:unix:///var/run/cri-dockerd.sock"
streams, flushStreams := common.TestLogStreams(s.T(), "reset")
err = ssh.Exec(ctx, resetCmd, streams)
flushStreams()
s.NoError(err, "k0s reset didn't exit cleanly")

containerIDs.Reset()
if s.NoError(ssh.Exec(ctx, "docker ps -q", common.SSHStreams{Out: &containerIDs}), "Failed to get running Docker containers") {
s.Empty(containerIDs.String(), "Expected no running Docker containers")
}
})
}

func (s *BYOCRISuite) runDockerWorker() error {
Expand Down
9 changes: 0 additions & 9 deletions inttest/common/bootloosesuite.go
Original file line number Diff line number Diff line change
Expand Up @@ -795,15 +795,6 @@ func (s *BootlooseSuite) StopWorker(name string) error {
return s.launchDelegate.StopWorker(s.Context(), ssh)
}

func (s *BootlooseSuite) Reset(name string) error {
ssh, err := s.SSH(s.Context(), name)
s.Require().NoError(err)
defer ssh.Disconnect()
resetCommand := fmt.Sprintf("%s reset --debug", s.K0sFullPath)
_, err = ssh.ExecWithOutput(s.Context(), resetCommand)
return err
}

// KubeClient return kube client by loading the admin access config from given node
func (s *BootlooseSuite) GetKubeConfig(node string, k0sKubeconfigArgs ...string) (*rest.Config, error) {
machine, err := s.MachineForName(node)
Expand Down
11 changes: 11 additions & 0 deletions inttest/common/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"strconv"
"strings"
"sync"
"testing"

"github.com/mitchellh/go-homedir"
"golang.org/x/crypto/ssh"
Expand Down Expand Up @@ -193,6 +194,16 @@ func (c *SSHConnection) Exec(ctx context.Context, cmd string, streams SSHStreams
}
}

// Returns SSH streams that log lines to the test log.
func TestLogStreams(t *testing.T, prefix string) (_ SSHStreams, flush func()) {
out := LineWriter{WriteLine: func(line []byte) { t.Logf("%s stdout: %s", prefix, string(line)) }}
err := LineWriter{WriteLine: func(line []byte) { t.Logf("%s stderr: %s", prefix, string(line)) }}
return SSHStreams{Out: &out, Err: &err}, func() {
out.Flush()
err.Flush()
}
}

func newWriterBuffer() (io.WriteCloser, func() []byte) {
var mu sync.Mutex
var buf bytes.Buffer
Expand Down
41 changes: 41 additions & 0 deletions inttest/common/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,3 +345,44 @@ func logfFrom(ctx context.Context) LogfFn {
}
return logrus.Infof
}

type LineWriter struct {
WriteLine func([]byte)
buf []byte
}

// Write implements [io.Writer].
func (s *LineWriter) Write(in []byte) (int, error) {
s.buf = append(s.buf, in...)
s.logLines()
return len(in), nil
}

// Logs each complete line and discards the used data.
func (s *LineWriter) logLines() {
var off int
for {
n := bytes.IndexByte(s.buf[off:], '\n')
if n < 0 {
break
}

s.WriteLine(s.buf[off : off+n])
off += n + 1
}

// Move the unprocessed data to the beginning of the buffer and reset the length.
if off > 0 {
len := copy(s.buf, s.buf[off:])
s.buf = s.buf[:len]
}
}

// Logs any remaining data in the buffer that doesn't end with a newline.
func (s *LineWriter) Flush() {
if len(s.buf) > 0 {
s.WriteLine(s.buf)
// Reset the length and keep the underlying array.
s.buf = s.buf[:0]
}
}
82 changes: 82 additions & 0 deletions inttest/reset/reset_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
Copyright 2024 k0s authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package reset

import (
"testing"

testifysuite "github.com/stretchr/testify/suite"

"github.com/k0sproject/k0s/inttest/common"
)

type suite struct {
common.BootlooseSuite
}

func (s *suite) TestReset() {
ctx := s.Context()
workerNode := s.WorkerNode(0)

if ok := s.Run("k0s gets up", func() {
s.Require().NoError(s.InitController(0, "--disable-components=konnectivity-server,metrics-server"))
s.Require().NoError(s.RunWorkers())

kc, err := s.KubeClient(s.ControllerNode(0))
s.Require().NoError(err)

err = s.WaitForNodeReady(workerNode, kc)
s.NoError(err)

s.T().Log("waiting to see CNI pods ready")
s.NoError(common.WaitForKubeRouterReady(ctx, kc), "CNI did not start")
}); !ok {
return
}

s.Run("k0s reset", func() {
ssh, err := s.SSH(ctx, workerNode)
s.Require().NoError(err)
defer ssh.Disconnect()

s.NoError(ssh.Exec(ctx, "test -d /var/lib/k0s", common.SSHStreams{}), "/var/lib/k0s is not a directory")
s.NoError(ssh.Exec(ctx, "test -d /run/k0s", common.SSHStreams{}), "/run/k0s is not a directory")

s.NoError(ssh.Exec(ctx, "pidof containerd-shim-runc-v2 >&2", common.SSHStreams{}), "Expected some running containerd shims")

s.NoError(s.StopWorker(workerNode), "Failed to stop k0s")

streams, flushStreams := common.TestLogStreams(s.T(), "reset")
err = ssh.Exec(ctx, "k0s reset --debug", streams)
flushStreams()
s.NoError(err, "k0s reset didn't exit cleanly")

// /var/lib/k0s is a mount point in the Docker container and can't be deleted, so it must be empty
s.NoError(ssh.Exec(ctx, `x="$(ls -A /var/lib/k0s)" && echo "$x" >&2 && [ -z "$x" ]`, common.SSHStreams{}), "/var/lib/k0s is not empty")
s.NoError(ssh.Exec(ctx, "! test -e /run/k0s", common.SSHStreams{}), "/run/k0s still exists")
s.NoError(ssh.Exec(ctx, "! pidof containerd-shim-runc-v2 >&2", common.SSHStreams{}), "Expected no running containerd shims")
})
}

func TestResetSuite(t *testing.T) {
testifysuite.Run(t, &suite{
common.BootlooseSuite{
ControllerCount: 1,
WorkerCount: 1,
},
})
}
Loading