Skip to content

Commit f660c1b

Browse files
authored
Merge pull request #4238 from twz123/reset-inttests
Add integration tests around k0s reset
2 parents 17d6f6d + 9237a87 commit f660c1b

File tree

7 files changed

+185
-21
lines changed

7 files changed

+185
-21
lines changed

inttest/Makefile.variables

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ smoketests := \
5454
check-noderole-single \
5555
check-openebs\
5656
check-psp \
57+
check-reset \
5758
check-singlenode \
5859
check-statussocket \
5960
check-upgrade \

inttest/backup/backup_test.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ func (s *BackupSuite) TestK0sGetsUp() {
9696
s.Require().NoError(s.StopController(s.ControllerNode(0)))
9797
_ = s.StopController(s.ControllerNode(1)) // No error check as k0s might have actually exited since etcd is not really happy
9898

99-
s.Require().NoError(s.Reset(s.ControllerNode(0)))
100-
s.Require().NoError(s.Reset(s.ControllerNode(1)))
99+
s.reset(s.ControllerNode(0))
100+
s.reset(s.ControllerNode(1))
101101

102102
s.Require().NoError(s.restoreFunc())
103103
s.Require().NoError(s.InitController(0, "--enable-worker"))
@@ -122,6 +122,13 @@ func (s *BackupSuite) TestK0sGetsUp() {
122122
s.Require().NoError(s.VerifyFileSystemRestore())
123123
}
124124

125+
func (s *BackupSuite) reset(name string) {
126+
ssh, err := s.SSH(s.Context(), name)
127+
s.Require().NoError(err)
128+
defer ssh.Disconnect()
129+
s.Require().NoError(ssh.Exec(s.Context(), "k0s reset --debug", common.SSHStreams{}))
130+
}
131+
125132
type snapshot struct {
126133
namespaces map[types.UID]string
127134
services map[types.UID]string

inttest/byocri/byocri_test.go

+41-10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package byocri
1818

1919
import (
2020
"fmt"
21+
"strings"
2122
"testing"
2223

2324
"github.com/avast/retry-go"
@@ -31,21 +32,51 @@ type BYOCRISuite struct {
3132
common.BootlooseSuite
3233
}
3334

34-
func (s *BYOCRISuite) TestK0sGetsUp() {
35+
func (s *BYOCRISuite) TestBringYourOwnCRI() {
36+
ctx := s.Context()
37+
workerNode := s.WorkerNode(0)
3538

36-
s.NoError(s.InitController(0))
37-
s.Require().NoError(s.runDockerWorker())
39+
if ok := s.Run("k0s gets up", func() {
40+
s.NoError(s.InitController(0))
41+
s.Require().NoError(s.runDockerWorker())
3842

39-
kc, err := s.KubeClient(s.ControllerNode(0))
40-
s.Require().NoError(err)
43+
kc, err := s.KubeClient(s.ControllerNode(0))
44+
s.Require().NoError(err)
4145

42-
err = s.WaitForNodeReady(s.WorkerNode(0), kc)
43-
s.NoError(err)
46+
err = s.WaitForNodeReady(workerNode, kc)
47+
s.NoError(err)
4448

45-
s.AssertSomeKubeSystemPods(kc)
49+
s.AssertSomeKubeSystemPods(kc)
4650

47-
s.T().Log("waiting to see CNI pods ready")
48-
s.NoError(common.WaitForKubeRouterReady(s.Context(), kc), "CNI did not start")
51+
s.T().Log("waiting to see CNI pods ready")
52+
s.NoError(common.WaitForKubeRouterReady(ctx, kc), "CNI did not start")
53+
}); !ok {
54+
return
55+
}
56+
57+
s.Run("k0s reset terminates Docker containers", func() {
58+
ssh, err := s.SSH(ctx, workerNode)
59+
s.Require().NoError(err)
60+
defer ssh.Disconnect()
61+
62+
var containerIDs strings.Builder
63+
if s.NoError(ssh.Exec(ctx, "docker ps -q", common.SSHStreams{Out: &containerIDs}), "Failed to get running Docker containers") {
64+
s.NotEmpty(containerIDs.String(), "Expected some running Docker containers")
65+
}
66+
67+
s.NoError(s.StopWorker(workerNode), "Failed to stop k0s")
68+
69+
resetCmd := "k0s reset --debug --cri-socket remote:unix:///var/run/cri-dockerd.sock"
70+
streams, flushStreams := common.TestLogStreams(s.T(), "reset")
71+
err = ssh.Exec(ctx, resetCmd, streams)
72+
flushStreams()
73+
s.NoError(err, "k0s reset didn't exit cleanly")
74+
75+
containerIDs.Reset()
76+
if s.NoError(ssh.Exec(ctx, "docker ps -q", common.SSHStreams{Out: &containerIDs}), "Failed to get running Docker containers") {
77+
s.Empty(containerIDs.String(), "Expected no running Docker containers")
78+
}
79+
})
4980
}
5081

5182
func (s *BYOCRISuite) runDockerWorker() error {

inttest/common/bootloosesuite.go

-9
Original file line numberDiff line numberDiff line change
@@ -795,15 +795,6 @@ func (s *BootlooseSuite) StopWorker(name string) error {
795795
return s.launchDelegate.StopWorker(s.Context(), ssh)
796796
}
797797

798-
func (s *BootlooseSuite) Reset(name string) error {
799-
ssh, err := s.SSH(s.Context(), name)
800-
s.Require().NoError(err)
801-
defer ssh.Disconnect()
802-
resetCommand := fmt.Sprintf("%s reset --debug", s.K0sFullPath)
803-
_, err = ssh.ExecWithOutput(s.Context(), resetCommand)
804-
return err
805-
}
806-
807798
// KubeClient return kube client by loading the admin access config from given node
808799
func (s *BootlooseSuite) GetKubeConfig(node string, k0sKubeconfigArgs ...string) (*rest.Config, error) {
809800
machine, err := s.MachineForName(node)

inttest/common/ssh.go

+11
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"strconv"
2828
"strings"
2929
"sync"
30+
"testing"
3031

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

197+
// Returns SSH streams that log lines to the test log.
198+
func TestLogStreams(t *testing.T, prefix string) (_ SSHStreams, flush func()) {
199+
out := LineWriter{WriteLine: func(line []byte) { t.Logf("%s stdout: %s", prefix, string(line)) }}
200+
err := LineWriter{WriteLine: func(line []byte) { t.Logf("%s stderr: %s", prefix, string(line)) }}
201+
return SSHStreams{Out: &out, Err: &err}, func() {
202+
out.Flush()
203+
err.Flush()
204+
}
205+
}
206+
196207
func newWriterBuffer() (io.WriteCloser, func() []byte) {
197208
var mu sync.Mutex
198209
var buf bytes.Buffer

inttest/common/util.go

+41
Original file line numberDiff line numberDiff line change
@@ -345,3 +345,44 @@ func logfFrom(ctx context.Context) LogfFn {
345345
}
346346
return logrus.Infof
347347
}
348+
349+
type LineWriter struct {
350+
WriteLine func([]byte)
351+
buf []byte
352+
}
353+
354+
// Write implements [io.Writer].
355+
func (s *LineWriter) Write(in []byte) (int, error) {
356+
s.buf = append(s.buf, in...)
357+
s.logLines()
358+
return len(in), nil
359+
}
360+
361+
// Logs each complete line and discards the used data.
362+
func (s *LineWriter) logLines() {
363+
var off int
364+
for {
365+
n := bytes.IndexByte(s.buf[off:], '\n')
366+
if n < 0 {
367+
break
368+
}
369+
370+
s.WriteLine(s.buf[off : off+n])
371+
off += n + 1
372+
}
373+
374+
// Move the unprocessed data to the beginning of the buffer and reset the length.
375+
if off > 0 {
376+
len := copy(s.buf, s.buf[off:])
377+
s.buf = s.buf[:len]
378+
}
379+
}
380+
381+
// Logs any remaining data in the buffer that doesn't end with a newline.
382+
func (s *LineWriter) Flush() {
383+
if len(s.buf) > 0 {
384+
s.WriteLine(s.buf)
385+
// Reset the length and keep the underlying array.
386+
s.buf = s.buf[:0]
387+
}
388+
}

inttest/reset/reset_test.go

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
Copyright 2024 k0s authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package reset
18+
19+
import (
20+
"testing"
21+
22+
testifysuite "github.com/stretchr/testify/suite"
23+
24+
"github.com/k0sproject/k0s/inttest/common"
25+
)
26+
27+
type suite struct {
28+
common.BootlooseSuite
29+
}
30+
31+
func (s *suite) TestReset() {
32+
ctx := s.Context()
33+
workerNode := s.WorkerNode(0)
34+
35+
if ok := s.Run("k0s gets up", func() {
36+
s.Require().NoError(s.InitController(0, "--disable-components=konnectivity-server,metrics-server"))
37+
s.Require().NoError(s.RunWorkers())
38+
39+
kc, err := s.KubeClient(s.ControllerNode(0))
40+
s.Require().NoError(err)
41+
42+
err = s.WaitForNodeReady(workerNode, kc)
43+
s.NoError(err)
44+
45+
s.T().Log("waiting to see CNI pods ready")
46+
s.NoError(common.WaitForKubeRouterReady(ctx, kc), "CNI did not start")
47+
}); !ok {
48+
return
49+
}
50+
51+
s.Run("k0s reset", func() {
52+
ssh, err := s.SSH(ctx, workerNode)
53+
s.Require().NoError(err)
54+
defer ssh.Disconnect()
55+
56+
s.NoError(ssh.Exec(ctx, "test -d /var/lib/k0s", common.SSHStreams{}), "/var/lib/k0s is not a directory")
57+
s.NoError(ssh.Exec(ctx, "test -d /run/k0s", common.SSHStreams{}), "/run/k0s is not a directory")
58+
59+
s.NoError(ssh.Exec(ctx, "pidof containerd-shim-runc-v2 >&2", common.SSHStreams{}), "Expected some running containerd shims")
60+
61+
s.NoError(s.StopWorker(workerNode), "Failed to stop k0s")
62+
63+
streams, flushStreams := common.TestLogStreams(s.T(), "reset")
64+
err = ssh.Exec(ctx, "k0s reset --debug", streams)
65+
flushStreams()
66+
s.NoError(err, "k0s reset didn't exit cleanly")
67+
68+
// /var/lib/k0s is a mount point in the Docker container and can't be deleted, so it must be empty
69+
s.NoError(ssh.Exec(ctx, `x="$(ls -A /var/lib/k0s)" && echo "$x" >&2 && [ -z "$x" ]`, common.SSHStreams{}), "/var/lib/k0s is not empty")
70+
s.NoError(ssh.Exec(ctx, "! test -e /run/k0s", common.SSHStreams{}), "/run/k0s still exists")
71+
s.NoError(ssh.Exec(ctx, "! pidof containerd-shim-runc-v2 >&2", common.SSHStreams{}), "Expected no running containerd shims")
72+
})
73+
}
74+
75+
func TestResetSuite(t *testing.T) {
76+
testifysuite.Run(t, &suite{
77+
common.BootlooseSuite{
78+
ControllerCount: 1,
79+
WorkerCount: 1,
80+
},
81+
})
82+
}

0 commit comments

Comments
 (0)