mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-09-02 05:37:51 +00:00
WaitForFile only checks if the socket file exists on the filesystem, but the plugin may not be listening yet. Add a small delay after WaitForFile to ensure the plugin is actually ready to accept connections. This fixes flaky volume plugin tests that fail with 'connection refused' even though the socket file exists. Signed-off-by: Lokesh Mandvekar <lsm5@redhat.com> Signed-off-by: Chris Evich <cevich@redhat.com>
330 lines
13 KiB
Go
330 lines
13 KiB
Go
package integration
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
. "github.com/containers/podman/v4/test/utils"
|
|
"github.com/containers/storage/pkg/stringid"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
. "github.com/onsi/gomega/gexec"
|
|
)
|
|
|
|
var _ = Describe("Podman volume plugins", func() {
|
|
var (
|
|
tempdir string
|
|
err error
|
|
podmanTest *PodmanTestIntegration
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
tempdir, err = CreateTempDirInTempDir()
|
|
if err != nil {
|
|
os.Exit(1)
|
|
}
|
|
podmanTest = PodmanTestCreate(tempdir)
|
|
podmanTest.Setup()
|
|
os.Setenv("CONTAINERS_CONF", "config/containers.conf")
|
|
SkipIfRemote("Volume plugins only supported as local")
|
|
SkipIfRootless("Root is required for volume plugin testing")
|
|
err = os.MkdirAll("/run/docker/plugins", 0755)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
AfterEach(func() {
|
|
podmanTest.CleanupVolume()
|
|
f := CurrentGinkgoTestDescription()
|
|
processTestResult(f)
|
|
os.Unsetenv("CONTAINERS_CONF")
|
|
})
|
|
|
|
It("volume create with nonexistent plugin errors", func() {
|
|
session := podmanTest.Podman([]string{"volume", "create", "--driver", "notexist", "test_volume_name"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).To(ExitWithError())
|
|
})
|
|
|
|
It("volume create with not-running plugin does not error", func() {
|
|
session := podmanTest.Podman([]string{"volume", "create", "--driver", "testvol0", "test_volume_name"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).To(ExitWithError())
|
|
})
|
|
|
|
It("volume create and remove with running plugin succeeds", func() {
|
|
podmanTest.AddImageToRWStore(volumeTest)
|
|
|
|
pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes")
|
|
err := os.Mkdir(pluginStatePath, 0755)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
// Keep this distinct within tests to avoid multiple tests using the same plugin.
|
|
pluginName := "testvol1"
|
|
plugin := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins", "-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath})
|
|
plugin.WaitWithDefaultTimeout()
|
|
Expect(plugin).Should(Exit(0))
|
|
|
|
// Make sure the socket is available (see #17956)
|
|
err = WaitForFile(fmt.Sprintf("/run/docker/plugins/%s.sock", pluginName))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
// Give the plugin a moment to start listening on the socket
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
volName := "testVolume1"
|
|
create := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, volName})
|
|
create.WaitWithDefaultTimeout()
|
|
Expect(create).Should(Exit(0))
|
|
|
|
ls1 := podmanTest.Podman([]string{"volume", "ls", "-q"})
|
|
ls1.WaitWithDefaultTimeout()
|
|
Expect(ls1).Should(Exit(0))
|
|
arrOutput := ls1.OutputToStringArray()
|
|
Expect(arrOutput).To(HaveLen(1))
|
|
Expect(arrOutput[0]).To(ContainSubstring(volName))
|
|
|
|
remove := podmanTest.Podman([]string{"volume", "rm", volName})
|
|
remove.WaitWithDefaultTimeout()
|
|
Expect(remove).Should(Exit(0))
|
|
|
|
ls2 := podmanTest.Podman([]string{"volume", "ls", "-q"})
|
|
ls2.WaitWithDefaultTimeout()
|
|
Expect(ls2).Should(Exit(0))
|
|
Expect(ls2.OutputToStringArray()).To(BeEmpty())
|
|
})
|
|
|
|
It("volume inspect with running plugin succeeds", func() {
|
|
podmanTest.AddImageToRWStore(volumeTest)
|
|
|
|
pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes")
|
|
err := os.Mkdir(pluginStatePath, 0755)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
// Keep this distinct within tests to avoid multiple tests using the same plugin.
|
|
pluginName := "testvol2"
|
|
plugin := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins", "-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath})
|
|
plugin.WaitWithDefaultTimeout()
|
|
Expect(plugin).Should(Exit(0))
|
|
|
|
// Make sure the socket is available (see #17956)
|
|
err = WaitForFile(fmt.Sprintf("/run/docker/plugins/%s.sock", pluginName))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
// Give the plugin a moment to start listening on the socket
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
volName := "testVolume1"
|
|
create := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, volName})
|
|
create.WaitWithDefaultTimeout()
|
|
Expect(create).Should(Exit(0))
|
|
|
|
volInspect := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .Driver }}", volName})
|
|
volInspect.WaitWithDefaultTimeout()
|
|
Expect(volInspect).Should(Exit(0))
|
|
Expect(volInspect.OutputToString()).To(ContainSubstring(pluginName))
|
|
})
|
|
|
|
It("remove plugin with stopped plugin succeeds", func() {
|
|
podmanTest.AddImageToRWStore(volumeTest)
|
|
|
|
pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes")
|
|
err := os.Mkdir(pluginStatePath, 0755)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
// Keep this distinct within tests to avoid multiple tests using the same plugin.
|
|
pluginName := "testvol3"
|
|
ctrName := "pluginCtr"
|
|
plugin := podmanTest.Podman([]string{"run", "--name", ctrName, "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins", "-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath})
|
|
plugin.WaitWithDefaultTimeout()
|
|
Expect(plugin).Should(Exit(0))
|
|
|
|
// Make sure the socket is available (see #17956)
|
|
err = WaitForFile(fmt.Sprintf("/run/docker/plugins/%s.sock", pluginName))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
// Give the plugin a moment to start listening on the socket
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
volName := "testVolume1"
|
|
create := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, volName})
|
|
create.WaitWithDefaultTimeout()
|
|
Expect(create).Should(Exit(0))
|
|
|
|
ls1 := podmanTest.Podman([]string{"volume", "ls", "-q"})
|
|
ls1.WaitWithDefaultTimeout()
|
|
Expect(ls1).Should(Exit(0))
|
|
arrOutput := ls1.OutputToStringArray()
|
|
Expect(arrOutput).To(HaveLen(1))
|
|
Expect(arrOutput[0]).To(ContainSubstring(volName))
|
|
|
|
stop := podmanTest.Podman([]string{"stop", "--timeout", "0", ctrName})
|
|
stop.WaitWithDefaultTimeout()
|
|
Expect(stop).Should(Exit(0))
|
|
|
|
// Remove should exit non-zero because missing plugin
|
|
remove := podmanTest.Podman([]string{"volume", "rm", volName})
|
|
remove.WaitWithDefaultTimeout()
|
|
Expect(remove).To(ExitWithError())
|
|
|
|
// But the volume should still be gone
|
|
ls2 := podmanTest.Podman([]string{"volume", "ls", "-q"})
|
|
ls2.WaitWithDefaultTimeout()
|
|
Expect(ls2).Should(Exit(0))
|
|
Expect(ls2.OutputToStringArray()).To(BeEmpty())
|
|
})
|
|
|
|
It("use plugin in containers", func() {
|
|
podmanTest.AddImageToRWStore(volumeTest)
|
|
|
|
pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes")
|
|
err := os.Mkdir(pluginStatePath, 0755)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
// Keep this distinct within tests to avoid multiple tests using the same plugin.
|
|
pluginName := "testvol4"
|
|
plugin := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins", "-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath})
|
|
plugin.WaitWithDefaultTimeout()
|
|
Expect(plugin).Should(Exit(0))
|
|
|
|
// Make sure the socket is available (see #17956)
|
|
err = WaitForFile(fmt.Sprintf("/run/docker/plugins/%s.sock", pluginName))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
// Give the plugin a moment to start listening on the socket
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
volName := "testVolume1"
|
|
create := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, volName})
|
|
create.WaitWithDefaultTimeout()
|
|
Expect(create).Should(Exit(0))
|
|
|
|
ctr1Name := "ctr1"
|
|
ctr1 := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "--name", ctr1Name, "-v", fmt.Sprintf("%v:/test", volName), ALPINE, "sh", "-c", "touch /test/testfile && echo helloworld > /test/testfile"})
|
|
ctr1.WaitWithDefaultTimeout()
|
|
Expect(ctr1).Should(Exit(0))
|
|
|
|
ctr2Name := "ctr2"
|
|
ctr2 := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "--name", ctr2Name, "-v", fmt.Sprintf("%v:/test", volName), ALPINE, "cat", "/test/testfile"})
|
|
ctr2.WaitWithDefaultTimeout()
|
|
Expect(ctr2).Should(Exit(0))
|
|
Expect(ctr2.OutputToString()).To(ContainSubstring("helloworld"))
|
|
|
|
// HACK: `volume rm -f` is timing out trying to remove containers using the volume.
|
|
// Solution: remove them manually...
|
|
// TODO: fix this when I get back
|
|
rmAll := podmanTest.Podman([]string{"rm", "-f", ctr2Name, ctr1Name})
|
|
rmAll.WaitWithDefaultTimeout()
|
|
Expect(rmAll).Should(Exit(0))
|
|
})
|
|
|
|
It("podman volume reload", func() {
|
|
podmanTest.AddImageToRWStore(volumeTest)
|
|
|
|
confFile := filepath.Join(podmanTest.TempDir, "containers.conf")
|
|
err := os.WriteFile(confFile, []byte(`[engine]
|
|
[engine.volume_plugins]
|
|
testvol5 = "/run/docker/plugins/testvol5.sock"`), 0o644)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
os.Setenv("CONTAINERS_CONF", confFile)
|
|
|
|
pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes")
|
|
err = os.Mkdir(pluginStatePath, 0755)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
// Keep this distinct within tests to avoid multiple tests using the same plugin.
|
|
pluginName := "testvol5"
|
|
ctrName := "pluginCtr"
|
|
plugin := podmanTest.Podman([]string{"run", "--name", ctrName, "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins",
|
|
"-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath})
|
|
plugin.WaitWithDefaultTimeout()
|
|
Expect(plugin).Should(Exit(0))
|
|
|
|
// Make sure the socket is available (see #17956)
|
|
err = WaitForFile(fmt.Sprintf("/run/docker/plugins/%s.sock", pluginName))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
// Give the plugin a moment to start listening on the socket
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
localvol := "local-" + stringid.GenerateRandomID()
|
|
// create local volume
|
|
session := podmanTest.Podman([]string{"volume", "create", localvol})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).To(Exit(0))
|
|
|
|
vol1 := "vol1-" + stringid.GenerateRandomID()
|
|
session = podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, vol1})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).To(Exit(0))
|
|
|
|
// now create volume in plugin without podman
|
|
vol2 := "vol2-" + stringid.GenerateRandomID()
|
|
plugin = podmanTest.Podman([]string{"exec", ctrName, "/usr/local/bin/testvol", "--sock-name", pluginName, "create", vol2})
|
|
plugin.WaitWithDefaultTimeout()
|
|
Expect(plugin).Should(Exit(0))
|
|
|
|
session = podmanTest.Podman([]string{"volume", "ls", "-q"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).To(Exit(0))
|
|
Expect(session.OutputToStringArray()).To(ContainElements(localvol, vol1))
|
|
Expect(session.ErrorToString()).To(Equal("")) // make sure no errors are shown
|
|
|
|
plugin = podmanTest.Podman([]string{"exec", ctrName, "/usr/local/bin/testvol", "--sock-name", pluginName, "remove", vol1})
|
|
plugin.WaitWithDefaultTimeout()
|
|
Expect(plugin).Should(Exit(0))
|
|
|
|
// now reload volumes from plugins
|
|
session = podmanTest.Podman([]string{"volume", "reload"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).To(Exit(0))
|
|
Expect(string(session.Out.Contents())).To(Equal(fmt.Sprintf(`Added:
|
|
%s
|
|
Removed:
|
|
%s
|
|
`, vol2, vol1)))
|
|
Expect(session.ErrorToString()).To(Equal("")) // make sure no errors are shown
|
|
|
|
session = podmanTest.Podman([]string{"volume", "ls", "-q"})
|
|
session.WaitWithDefaultTimeout()
|
|
Expect(session).To(Exit(0))
|
|
Expect(session.OutputToStringArray()).To(ContainElements(localvol, vol2))
|
|
Expect(session.ErrorToString()).To(Equal("")) // make no errors are shown
|
|
})
|
|
|
|
It("volume driver timeouts test", func() {
|
|
podmanTest.AddImageToRWStore(volumeTest)
|
|
|
|
pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes")
|
|
err := os.Mkdir(pluginStatePath, 0755)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
// Keep this distinct within tests to avoid multiple tests using the same plugin.
|
|
pluginName := "testvol6"
|
|
plugin := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins", "-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath})
|
|
plugin.WaitWithDefaultTimeout()
|
|
Expect(plugin).Should(Exit(0))
|
|
|
|
// Make sure the socket is available (see #17956)
|
|
err = WaitForFile(fmt.Sprintf("/run/docker/plugins/%s.sock", pluginName))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
// Give the plugin a moment to start listening on the socket
|
|
time.Sleep(500 * time.Millisecond)
|
|
|
|
volName := "testVolume1"
|
|
create := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, volName})
|
|
create.WaitWithDefaultTimeout()
|
|
Expect(create).Should(Exit(0))
|
|
|
|
volInspect := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .Timeout }}", volName})
|
|
volInspect.WaitWithDefaultTimeout()
|
|
Expect(volInspect).Should(Exit(0))
|
|
Expect(volInspect.OutputToString()).To(ContainSubstring("15"))
|
|
|
|
volName2 := "testVolume2"
|
|
create2 := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, "--opt", "o=timeout=3", volName2})
|
|
create2.WaitWithDefaultTimeout()
|
|
Expect(create2).Should(Exit(0))
|
|
|
|
volInspect2 := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .Timeout }}", volName2})
|
|
volInspect2.WaitWithDefaultTimeout()
|
|
Expect(volInspect2).Should(Exit(0))
|
|
Expect(volInspect2.OutputToString()).To(ContainSubstring("3"))
|
|
})
|
|
})
|