diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index 20610cfc3e..b953b7cb60 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -6,7 +6,9 @@ import ( "bytes" "errors" "fmt" + "io/fs" "net" + "os" "strconv" "strings" "sync" @@ -78,6 +80,19 @@ func NewBoltState(path string, runtime *Runtime) (State, error) { logrus.Debugf("Initializing boltdb state at %s", path) + // BoltDB is deprecated and, as of Podman 5.0, we no longer allow the + // creation of new Bolt states. + // If the DB does not already exist, error out. + // To continue testing in CI, allow creation iff an undocumented env + // var is set. + if os.Getenv("CI_DESIRED_DATABASE") != "boltdb" { + if _, err := os.Stat(path); err != nil && errors.Is(err, fs.ErrNotExist) { + return nil, fmt.Errorf("the BoltDB backend has been deprecated, no new BoltDB databases can be created: %w", define.ErrInvalidArg) + } + } else { + logrus.Debugf("Allowing deprecated database backend due to CI_DESIRED_DATABASE.") + } + db, err := bolt.Open(path, 0600, nil) if err != nil { return nil, fmt.Errorf("opening database %s: %w", path, err) diff --git a/libpod/state_test.go b/libpod/state_test.go index d6ce225264..965f01983b 100644 --- a/libpod/state_test.go +++ b/libpod/state_test.go @@ -46,6 +46,10 @@ func getEmptyBoltState() (_ State, _ string, _ lock.Manager, retErr error) { } }() + if err := os.Setenv("CI_DESIRED_DATABASE", "boltdb"); err != nil { + return nil, "", nil, err + } + dbPath := filepath.Join(tmpDir, "db.sql") lockManager, err := lock.NewInMemoryManager(16) diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index b204ebbd3e..c05ee29ee1 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -186,8 +186,11 @@ var _ = Describe("Podman Info", func() { Expect(session.OutputToString()).To(Equal(want)) }) - It("podman --db-backend info basic check", func() { + It("podman --db-backend info basic check", Serial, func() { SkipIfRemote("--db-backend only supported on the local client") + + const desiredDB = "CI_DESIRED_DATABASE" + type argWant struct { arg string want string @@ -199,14 +202,29 @@ var _ = Describe("Podman Info", func() { // now because a boltdb exists it should use boltdb when default is requested {arg: "", want: "boltdb"}, {arg: "sqlite", want: "sqlite"}, + // just because we requested sqlite doesn't mean it stays that way. + // once a boltdb exists, podman will forevermore stick with it + {arg: "", want: "boltdb"}, } for _, tt := range backends { + oldDesiredDB := os.Getenv(desiredDB) + if tt.arg == "boltdb" { + err := os.Setenv(desiredDB, "boltdb") + Expect(err).To(Not(HaveOccurred())) + defer os.Setenv(desiredDB, oldDesiredDB) + } + session := podmanTest.Podman([]string{"--db-backend", tt.arg, "--log-level=info", "info", "--format", "{{.Host.DatabaseBackend}}"}) session.WaitWithDefaultTimeout() Expect(session).To(Exit(0)) Expect(session.OutputToString()).To(Equal(tt.want)) Expect(session.ErrorToString()).To(ContainSubstring("Using %s as database backend", tt.want)) + + if tt.arg == "boltdb" { + err := os.Setenv(desiredDB, oldDesiredDB) + Expect(err).To(Not(HaveOccurred())) + } } // make sure we get an error for bogus values diff --git a/test/e2e/systemd_activate_test.go b/test/e2e/systemd_activate_test.go index 30d40c091e..129f3bd860 100644 --- a/test/e2e/systemd_activate_test.go +++ b/test/e2e/systemd_activate_test.go @@ -52,7 +52,7 @@ var _ = Describe("Systemd activate", func() { systemdArgs := []string{ "-E", "http_proxy", "-E", "https_proxy", "-E", "no_proxy", "-E", "HTTP_PROXY", "-E", "HTTPS_PROXY", "-E", "NO_PROXY", - "-E", "XDG_RUNTIME_DIR", + "-E", "XDG_RUNTIME_DIR", "-E", "CI_DESIRED_DATABASE", "--listen", addr, podmanTest.PodmanBinary} systemdArgs = append(systemdArgs, podmanOptions...) @@ -114,7 +114,7 @@ var _ = Describe("Systemd activate", func() { // start systemd activation with datagram socket activateSession := testUtils.StartSystemExec(activate, []string{ - "--datagram", "--listen", addr, + "--datagram", "--listen", addr, "-E", "CI_DESIRED_DATABASE", podmanTest.PodmanBinary, "--root=" + filepath.Join(tempdir, "server_root"), "system", "service", diff --git a/test/system/005-info.bats b/test/system/005-info.bats index 200d81f060..10b6011a38 100644 --- a/test/system/005-info.bats +++ b/test/system/005-info.bats @@ -255,4 +255,20 @@ EOF } +@test "podman - BoltDB cannot create new databases" { + skip_if_remote "DB checks only work for local Podman" + + safe_opts=$(podman_isolation_opts ${PODMAN_TMPDIR}) + + CI_DESIRED_DATABASE= run_podman 125 $safe_opts --db-backend=boltdb info + assert "$output" =~ "deprecated, no new BoltDB databases can be created" \ + "without CI_DESIRED_DATABASE" + + CI_DESIRED_DATABASE=boltdb run_podman $safe_opts --log-level=debug --db-backend=boltdb info + assert "$output" =~ "Allowing deprecated database backend" \ + "with CI_DESIRED_DATABASE" + + run_podman $safe_opts system reset --force +} + # vim: filetype=sh diff --git a/test/system/120-load.bats b/test/system/120-load.bats index 57178f55a9..e05f5196e2 100644 --- a/test/system/120-load.bats +++ b/test/system/120-load.bats @@ -83,6 +83,11 @@ verify_iid_and_name() { @test "podman image scp transfer" { skip_if_remote "only applicable under local podman" + # See https://github.com/containers/podman/pull/21300 for details + if [[ "$CI_DESIRED_DATABASE" = "boltdb" ]]; then + skip "impossible due to pitfalls in our SSH implementation" + fi + # The testing is the same whether we're root or rootless; all that # differs is the destination (not-me) username. if is_rootless; then