diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/apiv2/27-containersEvents.at | 4 | ||||
-rw-r--r-- | test/e2e/config.go | 2 | ||||
-rw-r--r-- | test/e2e/events_test.go | 21 | ||||
-rw-r--r-- | test/e2e/volume_ls_test.go | 31 | ||||
-rw-r--r-- | test/e2e/volume_plugin_test.go | 68 | ||||
-rw-r--r-- | test/system/160-volumes.bats | 23 | ||||
-rw-r--r-- | test/testvol/Containerfile | 9 | ||||
-rw-r--r-- | test/testvol/create.go | 26 | ||||
-rw-r--r-- | test/testvol/list.go | 32 | ||||
-rw-r--r-- | test/testvol/main.go | 23 | ||||
-rw-r--r-- | test/testvol/remove.go | 26 | ||||
-rw-r--r-- | test/testvol/util.go | 29 |
12 files changed, 285 insertions, 9 deletions
diff --git a/test/apiv2/27-containersEvents.at b/test/apiv2/27-containersEvents.at index a86f2e353..e0a66e0ac 100644 --- a/test/apiv2/27-containersEvents.at +++ b/test/apiv2/27-containersEvents.at @@ -18,6 +18,10 @@ t GET "libpod/events?stream=false&since=$START" 200 \ 'select(.status | contains("died")).Action=died' \ 'select(.status | contains("died")).Actor.Attributes.containerExitCode=1' +t GET "libpod/events?stream=false&since=$START" 200 \ + 'select(.status | contains("start")).Action=start' \ + 'select(.status | contains("start")).HealthStatus='\ + # compat api, uses status=die (#12643) t GET "events?stream=false&since=$START" 200 \ 'select(.status | contains("start")).Action=start' \ diff --git a/test/e2e/config.go b/test/e2e/config.go index 2ca8e2a15..fbcc9dfff 100644 --- a/test/e2e/config.go +++ b/test/e2e/config.go @@ -15,7 +15,7 @@ var ( healthcheck = "quay.io/libpod/alpine_healthcheck:latest" ImageCacheDir = "/tmp/podman/imagecachedir" fedoraToolbox = "registry.fedoraproject.org/fedora-toolbox:36" - volumeTest = "quay.io/libpod/volume-plugin-test-img:latest" + volumeTest = "quay.io/libpod/volume-plugin-test-img:20220623" // This image has seccomp profiles that blocks all syscalls. // The intention behind blocking all syscalls is to prevent diff --git a/test/e2e/events_test.go b/test/e2e/events_test.go index 725118ab0..528fa143d 100644 --- a/test/e2e/events_test.go +++ b/test/e2e/events_test.go @@ -216,4 +216,25 @@ var _ = Describe("Podman events", func() { Expect(result.OutputToString()).To(ContainSubstring("create")) }) + It("podman events health_status generated", func() { + session := podmanTest.Podman([]string{"run", "--name", "test-hc", "-dt", "--health-cmd", "echo working", "busybox"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + for i := 0; i < 5; i++ { + hc := podmanTest.Podman([]string{"healthcheck", "run", "test-hc"}) + hc.WaitWithDefaultTimeout() + exitCode := hc.ExitCode() + if exitCode == 0 || i == 4 { + break + } + time.Sleep(1 * time.Second) + } + + result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=health_status"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(len(result.OutputToStringArray())).To(BeNumerically(">=", 1), "Number of health_status events") + }) + }) diff --git a/test/e2e/volume_ls_test.go b/test/e2e/volume_ls_test.go index 19f87fb8a..dcfb13f4e 100644 --- a/test/e2e/volume_ls_test.go +++ b/test/e2e/volume_ls_test.go @@ -152,6 +152,37 @@ var _ = Describe("Podman volume ls", func() { Expect(lsDangling).Should(Exit(0)) Expect(lsDangling.OutputToString()).To(ContainSubstring(volName1)) }) + + It("podman ls volume with --filter name", func() { + volName1 := "volume1" + session := podmanTest.Podman([]string{"volume", "create", volName1}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + volName2 := "volume2" + session2 := podmanTest.Podman([]string{"volume", "create", volName2}) + session2.WaitWithDefaultTimeout() + Expect(session2).Should(Exit(0)) + + session = podmanTest.Podman([]string{"volume", "ls", "--filter", "name=volume1*"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToStringArray()).To(HaveLen(3)) + Expect(session.OutputToStringArray()[1]).To(ContainSubstring(volName1)) + Expect(session.OutputToStringArray()[2]).To(ContainSubstring(volName2)) + + session = podmanTest.Podman([]string{"volume", "ls", "--filter", "name=volumex"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToStringArray()).To(BeEmpty()) + + session = podmanTest.Podman([]string{"volume", "ls", "--filter", "name=volume1"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToStringArray()).To(HaveLen(2)) + Expect(session.OutputToStringArray()[1]).To(ContainSubstring(volName1)) + }) + It("podman ls volume with multiple --filter flag", func() { session := podmanTest.Podman([]string{"volume", "create", "--label", "foo=bar", "myvol"}) volName := session.OutputToString() diff --git a/test/e2e/volume_plugin_test.go b/test/e2e/volume_plugin_test.go index 4700afdb5..b585f8dd8 100644 --- a/test/e2e/volume_plugin_test.go +++ b/test/e2e/volume_plugin_test.go @@ -6,6 +6,7 @@ import ( "path/filepath" . "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" @@ -188,4 +189,71 @@ var _ = Describe("Podman volume plugins", func() { 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)) + + localvol := "local-" + stringid.GenerateNonCryptoID() + // create local volume + session := podmanTest.Podman([]string{"volume", "create", localvol}) + session.WaitWithDefaultTimeout() + Expect(session).To(Exit(0)) + + vol1 := "vol1-" + stringid.GenerateNonCryptoID() + 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.GenerateNonCryptoID() + 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 + }) }) diff --git a/test/system/160-volumes.bats b/test/system/160-volumes.bats index 797883ec6..da60112a0 100644 --- a/test/system/160-volumes.bats +++ b/test/system/160-volumes.bats @@ -64,6 +64,29 @@ function teardown() { } +# Filter volumes by name +@test "podman volume filter --name" { + suffix=$(random_string) + prefix="volume" + + for i in 1 2; do + myvolume=${prefix}_${i}_${suffix} + run_podman volume create $myvolume + is "$output" "$myvolume" "output from volume create $i" + done + + run_podman volume ls --filter name=${prefix}_1.+ --format "{{.Name}}" + is "$output" "${prefix}_1_${suffix}" "--filter name=${prefix}_1.+ shows only one volume" + + # The _1* is intentional as asterisk has different meaning in glob and regexp. Make sure this is regexp + run_podman volume ls --filter name=${prefix}_1* --format "{{.Name}}" + is "$output" "${prefix}_1_${suffix}.*${prefix}_2_${suffix}.*" "--filter name=${prefix}_1* shows ${prefix}_1_${suffix} and ${prefix}_2_${suffix}" + + for i in 1 2; do + run_podman volume rm ${prefix}_${i}_${suffix} + done +} + # Named volumes @test "podman volume create / run" { myvolume=myvol$(random_string) diff --git a/test/testvol/Containerfile b/test/testvol/Containerfile new file mode 100644 index 000000000..32448f5a9 --- /dev/null +++ b/test/testvol/Containerfile @@ -0,0 +1,9 @@ +FROM docker.io/library/golang:1.18-alpine AS build-img +COPY ./ /go/src/github.com/containers/podman/ +WORKDIR /go/src/github.com/containers/podman +RUN GO111MODULE=off go build -o /testvol ./test/testvol + +FROM alpine +COPY --from=build-img /testvol /usr/local/bin +WORKDIR / +ENTRYPOINT ["/usr/local/bin/testvol", "serve"] diff --git a/test/testvol/create.go b/test/testvol/create.go new file mode 100644 index 000000000..d29300f0b --- /dev/null +++ b/test/testvol/create.go @@ -0,0 +1,26 @@ +package main + +import ( + pluginapi "github.com/docker/go-plugins-helpers/volume" + "github.com/spf13/cobra" +) + +var createCmd = &cobra.Command{ + Use: "create NAME", + Short: "create a volume", + Long: `Create a volume in the volume plugin listening on --sock-name`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + return createVol(config.sockName, args[0]) + }, +} + +func createVol(sockName, volName string) error { + plugin, err := getPlugin(sockName) + if err != nil { + return err + } + createReq := new(pluginapi.CreateRequest) + createReq.Name = volName + return plugin.CreateVolume(createReq) +} diff --git a/test/testvol/list.go b/test/testvol/list.go new file mode 100644 index 000000000..fea615a70 --- /dev/null +++ b/test/testvol/list.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +var listCmd = &cobra.Command{ + Use: "list", + Short: "list all volumes", + Long: `List all volumes from the volume plugin listening on --sock-name`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, args []string) error { + return listVol(config.sockName) + }, +} + +func listVol(sockName string) error { + plugin, err := getPlugin(sockName) + if err != nil { + return err + } + vols, err := plugin.ListVolumes() + if err != nil { + return err + } + for _, vol := range vols { + fmt.Println(vol.Name) + } + return nil +} diff --git a/test/testvol/main.go b/test/testvol/main.go index 30ab365b3..99c6fb694 100644 --- a/test/testvol/main.go +++ b/test/testvol/main.go @@ -14,13 +14,20 @@ import ( ) var rootCmd = &cobra.Command{ - Use: "testvol", - Short: "testvol - volume plugin for Podman", + Use: "testvol", + Short: "testvol - volume plugin for Podman testing", + PersistentPreRunE: before, + SilenceUsage: true, +} + +var serveCmd = &cobra.Command{ + Use: "serve", + Short: "serve the volume plugin on the unix socket", Long: `Creates simple directory volumes using the Volume Plugin API for testing volume plugin functionality`, + Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return startServer(config.sockName) }, - PersistentPreRunE: before, } // Configuration for the volume plugin @@ -37,9 +44,12 @@ var config = cliConfig{ } func init() { - rootCmd.Flags().StringVar(&config.sockName, "sock-name", config.sockName, "Name of unix socket for plugin") - rootCmd.Flags().StringVar(&config.path, "path", "", "Path to initialize state and mount points") + rootCmd.PersistentFlags().StringVar(&config.sockName, "sock-name", config.sockName, "Name of unix socket for plugin") rootCmd.PersistentFlags().StringVar(&config.logLevel, "log-level", config.logLevel, "Log messages including and over the specified level: debug, info, warn, error, fatal, panic") + + serveCmd.Flags().StringVar(&config.path, "path", "", "Path to initialize state and mount points") + + rootCmd.AddCommand(serveCmd, createCmd, removeCmd, listCmd) } func before(cmd *cobra.Command, args []string) error { @@ -59,11 +69,8 @@ func before(cmd *cobra.Command, args []string) error { func main() { if err := rootCmd.Execute(); err != nil { - logrus.Errorf("Running volume plugin: %v", err) os.Exit(1) } - - os.Exit(0) } // startServer runs the HTTP server and responds to requests diff --git a/test/testvol/remove.go b/test/testvol/remove.go new file mode 100644 index 000000000..2839b0b50 --- /dev/null +++ b/test/testvol/remove.go @@ -0,0 +1,26 @@ +package main + +import ( + pluginapi "github.com/docker/go-plugins-helpers/volume" + "github.com/spf13/cobra" +) + +var removeCmd = &cobra.Command{ + Use: "remove NAME", + Short: "remove a volume", + Long: `Remove a volume in the volume plugin listening on --sock-name`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + return removeVol(config.sockName, args[0]) + }, +} + +func removeVol(sockName, volName string) error { + plugin, err := getPlugin(sockName) + if err != nil { + return err + } + removeReq := new(pluginapi.RemoveRequest) + removeReq.Name = volName + return plugin.RemoveVolume(removeReq) +} diff --git a/test/testvol/util.go b/test/testvol/util.go new file mode 100644 index 000000000..7a0aeba86 --- /dev/null +++ b/test/testvol/util.go @@ -0,0 +1,29 @@ +package main + +import ( + "path/filepath" + "strings" + + "github.com/containers/podman/v4/libpod/plugin" +) + +const pluginSockDir = "/run/docker/plugins" + +func getSocketPath(pathOrName string) string { + if filepath.IsAbs(pathOrName) { + return pathOrName + } + + // only a name join it with the default path + return filepath.Join(pluginSockDir, pathOrName+".sock") +} + +func getPluginName(pathOrName string) string { + return strings.TrimSuffix(filepath.Base(pathOrName), ".sock") +} + +func getPlugin(sockNameOrPath string) (*plugin.VolumePlugin, error) { + path := getSocketPath(sockNameOrPath) + name := getPluginName(sockNameOrPath) + return plugin.GetVolumePlugin(name, path) +} |