diff --git a/integration/issue10467_linux_test.go b/integration/issue10467_linux_test.go new file mode 100644 index 0000000000..96a8d4ed51 --- /dev/null +++ b/integration/issue10467_linux_test.go @@ -0,0 +1,117 @@ +/* + Copyright The containerd 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 integration + +import ( + "fmt" + "path/filepath" + "syscall" + "testing" + "time" + + "github.com/containerd/continuity/fs" + "github.com/stretchr/testify/require" + "go.etcd.io/bbolt" +) + +func TestIssue10467(t *testing.T) { + latestVersion := "v1.7.20" + + releaseBinDir := t.TempDir() + + downloadReleaseBinary(t, releaseBinDir, latestVersion) + + t.Logf("Install config for release %s", latestVersion) + workDir := t.TempDir() + previousReleaseCtrdConfig(t, releaseBinDir, workDir) + + t.Log("Starting the previous release's containerd") + previousCtrdBinPath := filepath.Join(releaseBinDir, "bin", "containerd") + previousProc := newCtrdProc(t, previousCtrdBinPath, workDir, []string{"ENABLE_CRI_SANDBOXES=yes"}) + + boltdbPath := filepath.Join(workDir, "root", "io.containerd.metadata.v1.bolt", "meta.db") + + ctrdLogPath := previousProc.logPath() + t.Cleanup(func() { + if t.Failed() { + dumpFileContent(t, ctrdLogPath) + } + }) + + require.NoError(t, previousProc.isReady()) + + needToCleanup := true + t.Cleanup(func() { + if t.Failed() && needToCleanup { + t.Logf("Try to cleanup leaky pods") + cleanupPods(t, previousProc.criRuntimeService(t)) + } + }) + + t.Log("Prepare pods for current release") + upgradeCaseFunc, hookFunc := shouldManipulateContainersInPodAfterUpgrade(t, previousProc.criRuntimeService(t), previousProc.criImageService(t)) + needToCleanup = false + require.Nil(t, hookFunc) + + t.Log("Gracefully stop previous release's containerd process") + require.NoError(t, previousProc.kill(syscall.SIGTERM)) + require.NoError(t, previousProc.wait(5*time.Minute)) + + t.Logf("%s should have bucket k8s.io in root", boltdbPath) + db, err := bbolt.Open(boltdbPath, 0600, &bbolt.Options{ReadOnly: true}) + require.NoError(t, err) + require.NoError(t, db.View(func(tx *bbolt.Tx) error { + if tx.Bucket([]byte("k8s.io")) == nil { + return fmt.Errorf("expected k8s.io bucket") + } + return nil + })) + require.NoError(t, db.Close()) + + t.Log("Install default config for current release") + currentReleaseCtrdDefaultConfig(t, workDir) + + t.Log("Starting the current release's containerd") + currentProc := newCtrdProc(t, "containerd", workDir, nil) + require.NoError(t, currentProc.isReady()) + + t.Cleanup(func() { + t.Log("Cleanup all the pods") + cleanupPods(t, currentProc.criRuntimeService(t)) + + t.Log("Stopping current release's containerd process") + require.NoError(t, currentProc.kill(syscall.SIGTERM)) + require.NoError(t, currentProc.wait(5*time.Minute)) + }) + + t.Logf("%s should not have bucket k8s.io in root after restart", boltdbPath) + copiedBoltdbPath := filepath.Join(t.TempDir(), "meta.db.new") + require.NoError(t, fs.CopyFile(copiedBoltdbPath, boltdbPath)) + + db, err = bbolt.Open(copiedBoltdbPath, 0600, &bbolt.Options{ReadOnly: true}) + require.NoError(t, err) + require.NoError(t, db.View(func(tx *bbolt.Tx) error { + if tx.Bucket([]byte("k8s.io")) != nil { + return fmt.Errorf("unexpected k8s.io bucket") + } + return nil + })) + require.NoError(t, db.Close()) + + t.Log("Verifing") + upgradeCaseFunc(t, currentProc.criRuntimeService(t), currentProc.criImageService(t)) +}