From 24f219efb75bbe6c155552c4a33fc79bc55ba2eb Mon Sep 17 00:00:00 2001 From: Toshiki Sonoda Date: Tue, 26 Jul 2022 10:00:52 +0900 Subject: Fix: Restore a container which name is equal to a image name If there is a match for both container and image, we restore the container. Fixes: https://github.com/containers/podman/issues/15055 Signed-off-by: Toshiki Sonoda --- test/e2e/checkpoint_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'test/e2e') diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go index d288c278e..03c9fc97e 100644 --- a/test/e2e/checkpoint_test.go +++ b/test/e2e/checkpoint_test.go @@ -222,6 +222,26 @@ var _ = Describe("Podman checkpoint", func() { Expect(result).Should(Exit(0)) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) + + // Restore a container which name is equal to a image name (#15055) + localRunString = getRunString([]string{"--name", "alpine", "quay.io/libpod/alpine:latest", "top"}) + session = podmanTest.Podman(localRunString) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + result = podmanTest.Podman([]string{"container", "checkpoint", "alpine"}) + result.WaitWithDefaultTimeout() + + Expect(result).Should(Exit(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1)) + Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited")) + + result = podmanTest.Podman([]string{"container", "restore", "alpine"}) + result.WaitWithDefaultTimeout() + + Expect(result).Should(Exit(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2)) + Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up")) }) It("podman pause a checkpointed container by id", func() { -- cgit v1.2.3-54-g00ecf From b7feafcb063bd152e4637b80684c82a4afbf9a98 Mon Sep 17 00:00:00 2001 From: Toshiki Sonoda Date: Tue, 26 Jul 2022 09:56:24 +0900 Subject: Fix: manifest push --rm removes a correct manifest list This bug is reproduced when we execute the following command: 1. podman manifest add 2. podman manifest push --rm dir: If pushing succeeds, it is expected to remove only a manifest list. However, manifest list remains on local storage and images are removed. This commit fixes `podman manifest push --rm` to remove only a manifest list. And, supports `manifest push --rm option` in remote environment, like host environment. Fixes: https://github.com/containers/podman/issues/15033 Signed-off-by: Toshiki Sonoda --- pkg/domain/infra/abi/manifest.go | 3 ++- pkg/domain/infra/tunnel/manifest.go | 10 +++++++++ test/e2e/manifest_test.go | 44 ++++++++++++++++++++++++++++++++----- 3 files changed, 50 insertions(+), 7 deletions(-) (limited to 'test/e2e') diff --git a/pkg/domain/infra/abi/manifest.go b/pkg/domain/infra/abi/manifest.go index 60f727234..6606b2cd0 100644 --- a/pkg/domain/infra/abi/manifest.go +++ b/pkg/domain/infra/abi/manifest.go @@ -334,7 +334,8 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin } if opts.Rm { - if _, rmErrors := ir.Libpod.LibimageRuntime().RemoveImages(ctx, []string{manifestList.ID()}, nil); len(rmErrors) > 0 { + rmOpts := &libimage.RemoveImagesOptions{LookupManifest: true} + if _, rmErrors := ir.Libpod.LibimageRuntime().RemoveImages(ctx, []string{manifestList.ID()}, rmOpts); len(rmErrors) > 0 { return "", fmt.Errorf("error removing manifest after push: %w", rmErrors[0]) } } diff --git a/pkg/domain/infra/tunnel/manifest.go b/pkg/domain/infra/tunnel/manifest.go index d2554f198..4a3148fac 100644 --- a/pkg/domain/infra/tunnel/manifest.go +++ b/pkg/domain/infra/tunnel/manifest.go @@ -110,5 +110,15 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin } } digest, err := manifests.Push(ir.ClientCtx, name, destination, options) + if err != nil { + return "", fmt.Errorf("error adding to manifest list %s: %w", name, err) + } + + if opts.Rm { + if _, rmErrors := ir.Remove(ctx, []string{name}, entities.ImageRemoveOptions{LookupManifest: true}); len(rmErrors) > 0 { + return "", fmt.Errorf("error removing manifest after push: %w", rmErrors[0]) + } + } + return digest, err } diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go index 1f58419a1..a7fcd1559 100644 --- a/test/e2e/manifest_test.go +++ b/test/e2e/manifest_test.go @@ -339,6 +339,16 @@ var _ = Describe("Podman manifest", func() { push = podmanTest.Podman([]string{"manifest", "push", "--tls-verify=false", "--creds=podmantest:wrongpasswd", "foo", "localhost:" + registry.Port + "/credstest"}) push.WaitWithDefaultTimeout() Expect(push).To(ExitWithError()) + + // push --rm after pull image (#15033) + push = podmanTest.Podman([]string{"manifest", "push", "--rm", "--tls-verify=false", "--creds=" + registry.User + ":" + registry.Password, "foo", "localhost:" + registry.Port + "/rmtest"}) + push.WaitWithDefaultTimeout() + Expect(push).Should(Exit(0)) + + session = podmanTest.Podman([]string{"images", "-q", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) }) It("push with error", func() { @@ -348,8 +358,8 @@ var _ = Describe("Podman manifest", func() { Expect(session.ErrorToString()).NotTo(BeEmpty()) }) - It("push --rm", func() { - SkipIfRemote("remote does not support --rm") + It("push --rm to local directory", func() { + SkipIfRemote("manifest push to dir not supported in remote mode") session := podmanTest.Podman([]string{"manifest", "create", "foo"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -365,13 +375,35 @@ var _ = Describe("Podman manifest", func() { session = podmanTest.Podman([]string{"manifest", "push", "--purge", "foo", "dir:" + dest}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"manifest", "inspect", "foo"}) + session = podmanTest.Podman([]string{"images", "-q", "foo"}) session.WaitWithDefaultTimeout() - Expect(session).To(ExitWithError()) + Expect(session).Should(Exit(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) - session = podmanTest.Podman([]string{"manifest", "rm", "foo1", "foo2"}) + // push --rm after pull image (#15033) + session = podmanTest.Podman([]string{"pull", "quay.io/libpod/testdigest_v2s2"}) session.WaitWithDefaultTimeout() - Expect(session).To(ExitWithError()) + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"manifest", "create", "bar"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"manifest", "add", "bar", "quay.io/libpod/testdigest_v2s2"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"manifest", "push", "--rm", "bar", "dir:" + dest}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + session = podmanTest.Podman([]string{"images", "-q", "bar"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0)) + + session = podmanTest.Podman([]string{"manifest", "rm", "foo", "bar"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(ExitWithError()) + Expect(session.ErrorToString()).To(ContainSubstring("foo: image not known")) + Expect(session.ErrorToString()).To(ContainSubstring("bar: image not known")) }) It("exists", func() { -- cgit v1.2.3-54-g00ecf From 5c17d1b14ba00acfc8a8a96dd08898c612a6eac4 Mon Sep 17 00:00:00 2001 From: Aditya R Date: Fri, 29 Jul 2022 23:04:45 +0530 Subject: test: verify manifest inspect must contain OCI annotations Signed-off-by: Aditya R --- test/e2e/manifest_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'test/e2e') diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go index a7fcd1559..caac23a44 100644 --- a/test/e2e/manifest_test.go +++ b/test/e2e/manifest_test.go @@ -171,13 +171,15 @@ var _ = Describe("Podman manifest", func() { session = podmanTest.Podman([]string{"manifest", "add", "foo", imageListInstance}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"manifest", "annotate", "--arch", "bar", "foo", imageListARM64InstanceDigest}) + session = podmanTest.Podman([]string{"manifest", "annotate", "--annotation", "hello=world", "--arch", "bar", "foo", imageListARM64InstanceDigest}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) session = podmanTest.Podman([]string{"manifest", "inspect", "foo"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToString()).To(ContainSubstring(`"architecture": "bar"`)) + // Check added annotation + Expect(session.OutputToString()).To(ContainSubstring(`"hello": "world"`)) }) It("remove digest", func() { -- cgit v1.2.3-54-g00ecf From 8c36b8c5210be96688eb8601c03ca21f562bced0 Mon Sep 17 00:00:00 2001 From: Toshiki Sonoda Date: Wed, 3 Aug 2022 14:39:38 +0900 Subject: Cirrus: Fix e2e tests for "mount_rootless_test" e2e `mount_rootless_test` did not load `podman binary path` successfully. This PR fix this problem. [It] podman unshare podman mount: ``` [+1596s] Running: ... unshare mount [+1596s] Error: exec: no command [+1596s] output: ``` [It] podman unshare image podman mount: ``` [+1599s] Running: ... unshare image mount quay.io/libpod/alpine:latest [+1599s] Error: exec: no command [+1599s] output: ``` Signed-off-by: Toshiki Sonoda --- test/e2e/mount_rootless_test.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'test/e2e') diff --git a/test/e2e/mount_rootless_test.go b/test/e2e/mount_rootless_test.go index 994a5899b..b0452deda 100644 --- a/test/e2e/mount_rootless_test.go +++ b/test/e2e/mount_rootless_test.go @@ -52,9 +52,16 @@ var _ = Describe("Podman mount", func() { Expect(setup).Should(Exit(0)) cid := setup.OutputToString() - session := podmanTest.Podman([]string{"unshare", PODMAN_BINARY, "mount", cid}) + // command: podman unshare podman mount cid + args := []string{"unshare", podmanTest.PodmanBinary} + opts := podmanTest.PodmanMakeOptions([]string{"mount", cid}, false, false) + args = append(args, opts...) + + // container root file system location is /tmp/... because "--root /tmp/..." + session := podmanTest.Podman(args) session.WaitWithDefaultTimeout() - Expect(setup).Should(Exit(0)) + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("/tmp")) }) It("podman image mount", func() { @@ -71,8 +78,15 @@ var _ = Describe("Podman mount", func() { setup.WaitWithDefaultTimeout() Expect(setup).Should(Exit(0)) - session := podmanTest.Podman([]string{"unshare", PODMAN_BINARY, "image", "mount", ALPINE}) + // command: podman unshare podman image mount ALPINE + args := []string{"unshare", podmanTest.PodmanBinary} + opts := podmanTest.PodmanMakeOptions([]string{"image", "mount", ALPINE}, false, false) + args = append(args, opts...) + + // image location is /tmp/... because "--root /tmp/..." + session := podmanTest.Podman(args) session.WaitWithDefaultTimeout() - Expect(setup).Should(Exit(0)) + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("/tmp")) }) }) -- cgit v1.2.3-54-g00ecf From a6ea3325a08378c1b39a446647aa697b3bd31619 Mon Sep 17 00:00:00 2001 From: Karthik Elango Date: Wed, 27 Jul 2022 10:43:06 -0400 Subject: start filter flag changes Tying filtering logic for podman stop and start to same place in getContainersAndInputByContext() to reduce code redundancy Signed-off-by: Karthik Elango --- cmd/podman/containers/start.go | 20 +++++++-------- pkg/domain/infra/abi/containers.go | 46 ++++++++++------------------------- pkg/domain/infra/tunnel/containers.go | 31 +---------------------- pkg/domain/infra/tunnel/helpers.go | 11 ++++++++- test/e2e/start_test.go | 39 +++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 74 deletions(-) (limited to 'test/e2e') diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go index cd4fa17b8..fc3488e0c 100644 --- a/cmd/podman/containers/start.go +++ b/cmd/podman/containers/start.go @@ -59,8 +59,10 @@ func startFlags(cmd *cobra.Command) { flags.BoolVarP(&startOptions.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") flags.BoolVar(&startOptions.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)") - flags.StringSliceVarP(&filters, "filter", "f", []string{}, "Filter output based on conditions given") - _ = cmd.RegisterFlagCompletionFunc("filter", common.AutocompletePsFilters) + + filterFlagName := "filter" + flags.StringSliceVarP(&filters, filterFlagName, "f", []string{}, "Filter output based on conditions given") + _ = cmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePsFilters) flags.BoolVar(&startOptions.All, "all", false, "Start all containers regardless of their state or configuration") @@ -84,7 +86,7 @@ func init() { } func validateStart(cmd *cobra.Command, args []string) error { - if len(args) == 0 && !startOptions.Latest && !startOptions.All { + if len(args) == 0 && !startOptions.Latest && !startOptions.All && len(filters) < 1 { return errors.New("start requires at least one argument") } if startOptions.All && startOptions.Latest { @@ -123,14 +125,12 @@ func start(cmd *cobra.Command, args []string) error { } containers := args - if len(filters) > 0 { - for _, f := range filters { - split := strings.SplitN(f, "=", 2) - if len(split) == 1 { - return fmt.Errorf("invalid filter %q", f) - } - startOptions.Filters[split[0]] = append(startOptions.Filters[split[0]], split[1]) + for _, f := range filters { + split := strings.SplitN(f, "=", 2) + if len(split) < 2 { + return fmt.Errorf("invalid filter %q", f) } + startOptions.Filters[split[0]] = append(startOptions.Filters[split[0]], split[1]) } responses, err := registry.ContainerEngine().ContainerStart(registry.GetContext(), containers, startOptions) diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 1b6c1617c..f12e17c09 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -40,6 +40,7 @@ import ( // is specified. It also returns a list of the corresponding input name used to lookup each container. func getContainersAndInputByContext(all, latest bool, names []string, filters map[string][]string, runtime *libpod.Runtime) (ctrs []*libpod.Container, rawInput []string, err error) { var ctr *libpod.Container + var filteredCtrs []*libpod.Container ctrs = []*libpod.Container{} filterFuncs := make([]libpod.ContainerFilter, 0, len(filters)) @@ -58,7 +59,17 @@ func getContainersAndInputByContext(all, latest bool, names []string, filters ma } rawInput = []string{} for _, candidate := range ctrs { - rawInput = append(rawInput, candidate.ID()) + if len(names) > 0 { + for _, name := range names { + if candidate.ID() == name || candidate.Name() == name { + rawInput = append(rawInput, candidate.ID()) + filteredCtrs = append(filteredCtrs, candidate) + } + } + ctrs = filteredCtrs + } else { + rawInput = append(rawInput, candidate.ID()) + } } case all: ctrs, err = runtime.GetAllContainers() @@ -860,38 +871,7 @@ func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID s func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) { reports := []*entities.ContainerStartReport{} var exitCode = define.ExecErrorCodeGeneric - containersNamesOrIds := namesOrIds - all := options.All - if len(options.Filters) > 0 { - all = false - filterFuncs := make([]libpod.ContainerFilter, 0, len(options.Filters)) - if len(options.Filters) > 0 { - for k, v := range options.Filters { - generatedFunc, err := dfilters.GenerateContainerFilterFuncs(k, v, ic.Libpod) - if err != nil { - return nil, err - } - filterFuncs = append(filterFuncs, generatedFunc) - } - } - candidates, err := ic.Libpod.GetContainers(filterFuncs...) - if err != nil { - return nil, err - } - containersNamesOrIds = []string{} - for _, candidate := range candidates { - if options.All { - containersNamesOrIds = append(containersNamesOrIds, candidate.ID()) - continue - } - for _, nameOrID := range namesOrIds { - if nameOrID == candidate.ID() || nameOrID == candidate.Name() { - containersNamesOrIds = append(containersNamesOrIds, nameOrID) - } - } - } - } - ctrs, rawInputs, err := getContainersAndInputByContext(all, options.Latest, containersNamesOrIds, options.Filters, ic.Libpod) + ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, namesOrIds, options.Filters, ic.Libpod) if err != nil { return nil, err } diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index c8371baf9..0bf792879 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -623,36 +623,7 @@ func logIfRmError(id string, err error, reports []*reports.RmReport) { func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) { reports := []*entities.ContainerStartReport{} var exitCode = define.ExecErrorCodeGeneric - containersNamesOrIds := namesOrIds - all := options.All - if len(options.Filters) > 0 { - all = false - containersNamesOrIds = []string{} - opts := new(containers.ListOptions).WithFilters(options.Filters).WithAll(true) - candidates, listErr := containers.List(ic.ClientCtx, opts) - if listErr != nil { - return nil, listErr - } - for _, candidate := range candidates { - if options.All { - containersNamesOrIds = append(containersNamesOrIds, candidate.ID) - continue - } - for _, nameOrID := range namesOrIds { - if nameOrID == candidate.ID { - containersNamesOrIds = append(containersNamesOrIds, nameOrID) - continue - } - for _, containerName := range candidate.Names { - if containerName == nameOrID { - containersNamesOrIds = append(containersNamesOrIds, nameOrID) - continue - } - } - } - } - } - ctrs, err := getContainersByContext(ic.ClientCtx, all, false, containersNamesOrIds) + ctrs, namesOrIds, err := getContainersAndInputByContext(ic.ClientCtx, options.All, false, namesOrIds, options.Filters) if err != nil { return nil, err } diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go index 9ff1641f0..20ea07948 100644 --- a/pkg/domain/infra/tunnel/helpers.go +++ b/pkg/domain/infra/tunnel/helpers.go @@ -31,8 +31,17 @@ func getContainersAndInputByContext(contextWithConnection context.Context, all, rawInputs := []string{} switch { case len(filters) > 0: + namesOrIDs = nil for i := range allContainers { - namesOrIDs = append(namesOrIDs, allContainers[i].ID) + if len(namesOrIDs) > 0 { + for _, name := range namesOrIDs { + if name == allContainers[i].ID { + namesOrIDs = append(namesOrIDs, allContainers[i].ID) + } + } + } else { + namesOrIDs = append(namesOrIDs, allContainers[i].ID) + } } case all: for i := range allContainers { diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go index 73af9d12c..736008ed3 100644 --- a/test/e2e/start_test.go +++ b/test/e2e/start_test.go @@ -1,6 +1,7 @@ package integration import ( + "fmt" "io/ioutil" "os" "strconv" @@ -231,4 +232,42 @@ var _ = Describe("Podman start", func() { _, err = strconv.Atoi(containerPID) // Make sure it's a proper integer Expect(err).To(BeNil()) }) + + It("podman start container --filter", func() { + session1 := podmanTest.Podman([]string{"container", "create", ALPINE}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + cid1 := session1.OutputToString() + + session1 = podmanTest.Podman([]string{"container", "create", ALPINE}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + cid2 := session1.OutputToString() + + session1 = podmanTest.Podman([]string{"container", "create", ALPINE}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + cid3 := session1.OutputToString() + shortCid3 := cid3[0:5] + + session1 = podmanTest.Podman([]string{"start", cid1, "-f", "status=running"}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + Expect(session1.OutputToString()).To(HaveLen(0)) + + session1 = podmanTest.Podman([]string{"start", "--all", "--filter", fmt.Sprintf("id=%swrongid", shortCid3)}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + Expect(session1.OutputToString()).To(HaveLen(0)) + + session1 = podmanTest.Podman([]string{"start", "--all", "--filter", fmt.Sprintf("id=%s", shortCid3)}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + Expect(session1.OutputToString()).To(BeEquivalentTo(cid3)) + + session1 = podmanTest.Podman([]string{"start", "-f", fmt.Sprintf("id=%s", cid2)}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + Expect(session1.OutputToString()).To(BeEquivalentTo(cid2)) + }) }) -- cgit v1.2.3-54-g00ecf From 91a1f3022b7bcc84e8587d104c86f3e61979467b Mon Sep 17 00:00:00 2001 From: Toshiki Sonoda Date: Fri, 5 Aug 2022 12:01:51 +0900 Subject: e2e: Add rootless mount cleanup test `podman run -d mount cleanup test` adapt to rootless environment. Signed-off-by: Toshiki Sonoda --- test/e2e/run_cleanup_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'test/e2e') diff --git a/test/e2e/run_cleanup_test.go b/test/e2e/run_cleanup_test.go index ea2caf907..5aa81140d 100644 --- a/test/e2e/run_cleanup_test.go +++ b/test/e2e/run_cleanup_test.go @@ -36,7 +36,7 @@ var _ = Describe("Podman run exit", func() { It("podman run -d mount cleanup test", func() { SkipIfRemote("podman-remote does not support mount") - SkipIfRootless("TODO rootless podman mount requires podman unshare first") + SkipIfRootless("rootless podman mount requires podman unshare first") result := podmanTest.Podman([]string{"run", "-dt", ALPINE, "top"}) result.WaitWithDefaultTimeout() @@ -69,6 +69,49 @@ var _ = Describe("Podman run exit", func() { pmount.WaitWithDefaultTimeout() Expect(pmount).Should(Exit(0)) Expect(pmount.OutputToString()).NotTo(ContainSubstring(cid)) + }) + + It("podman run -d mount cleanup rootless test", func() { + SkipIfRemote("podman-remote does not support mount") + SkipIfNotRootless("Use unshare in rootless only") + + result := podmanTest.Podman([]string{"run", "-dt", ALPINE, "top"}) + result.WaitWithDefaultTimeout() + cid := result.OutputToString() + Expect(result).Should(Exit(0)) + + mount := podmanTest.Podman([]string{"unshare", "mount"}) + mount.WaitWithDefaultTimeout() + Expect(mount).Should(Exit(0)) + Expect(mount.OutputToString()).To(ContainSubstring(cid)) + + // command: podman unshare podman image mount ALPINE + args := []string{"unshare", podmanTest.PodmanBinary} + opts := podmanTest.PodmanMakeOptions([]string{"mount", "--no-trunc"}, false, false) + args = append(args, opts...) + + pmount := podmanTest.Podman(args) + pmount.WaitWithDefaultTimeout() + Expect(pmount).Should(Exit(0)) + Expect(pmount.OutputToString()).To(ContainSubstring(cid)) + stop := podmanTest.Podman([]string{"stop", cid}) + stop.WaitWithDefaultTimeout() + Expect(stop).Should(Exit(0)) + + // We have to force cleanup so the unmount happens + podmanCleanupSession := podmanTest.Podman([]string{"container", "cleanup", cid}) + podmanCleanupSession.WaitWithDefaultTimeout() + Expect(podmanCleanupSession).Should(Exit(0)) + + mount = podmanTest.Podman([]string{"unshare", "mount"}) + mount.WaitWithDefaultTimeout() + Expect(mount).Should(Exit(0)) + Expect(mount.OutputToString()).NotTo(ContainSubstring(cid)) + + pmount = podmanTest.Podman(args) + pmount.WaitWithDefaultTimeout() + Expect(pmount).Should(Exit(0)) + Expect(pmount.OutputToString()).NotTo(ContainSubstring(cid)) }) }) -- cgit v1.2.3-54-g00ecf From fa1085ed01e2b901bfd3963ea4e1952a9d27a694 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 8 Aug 2022 11:09:53 +0200 Subject: cmd: refuse --userns if a mapping is specified if an explicit mapping is specified, do not accept `--userns` since it overriden to "private". Closes: https://github.com/containers/podman/issues/15233 Signed-off-by: Giuseppe Scrivano --- cmd/podman/containers/create.go | 16 +++++++--------- test/e2e/run_userns_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 9 deletions(-) (limited to 'test/e2e') diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 7d0f4d9ae..455127fd7 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -192,16 +192,14 @@ func replaceContainer(name string) error { } func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra bool) (entities.ContainerCreateOptions, error) { - vals.UserNS = c.Flag("userns").Value.String() - // if user did not modify --userns flag and did turn on - // uid/gid mappings, set userns flag to "private" - if !c.Flag("userns").Changed && vals.UserNS == "host" { - if len(vals.UIDMap) > 0 || - len(vals.GIDMap) > 0 || - vals.SubUIDName != "" || - vals.SubGIDName != "" { - vals.UserNS = "private" + if len(vals.UIDMap) > 0 || len(vals.GIDMap) > 0 || vals.SubUIDName != "" || vals.SubGIDName != "" { + if c.Flag("userns").Changed { + return vals, errors.New("--userns and --uidmap/--gidmap/--subuidname/--subgidname are mutually exclusive") } + // force userns flag to "private" + vals.UserNS = "private" + } else { + vals.UserNS = c.Flag("userns").Value.String() } if c.Flag("kernel-memory") != nil && c.Flag("kernel-memory").Changed { logrus.Warnf("The --kernel-memory flag is no longer supported. This flag is a noop.") diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go index 613727118..f247b2dac 100644 --- a/test/e2e/run_userns_test.go +++ b/test/e2e/run_userns_test.go @@ -307,6 +307,30 @@ var _ = Describe("Podman UserNS support", func() { } }) + + It("podman --userns= conflicts with ui[dg]map and sub[ug]idname", func() { + session := podmanTest.Podman([]string{"run", "--userns=host", "--uidmap=0:1:500", "alpine", "true"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(125)) + Expect(session.ErrorToString()).To(ContainSubstring("--userns and --uidmap/--gidmap/--subuidname/--subgidname are mutually exclusive")) + + session = podmanTest.Podman([]string{"run", "--userns=host", "--gidmap=0:200:5000", "alpine", "true"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(125)) + Expect(session.ErrorToString()).To(ContainSubstring("--userns and --uidmap/--gidmap/--subuidname/--subgidname are mutually exclusive")) + + // with sub[ug]idname we don't check for the error output since the error message could be different, depending on the + // system configuration since the specified user could not be defined and cause a different earlier error. + // In any case, make sure the command doesn't succeed. + session = podmanTest.Podman([]string{"run", "--userns=private", "--subuidname=containers", "alpine", "true"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Not(Exit(0))) + + session = podmanTest.Podman([]string{"run", "--userns=private", "--subgidname=containers", "alpine", "true"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Not(Exit(0))) + }) + It("podman PODMAN_USERNS", func() { SkipIfNotRootless("keep-id only works in rootless mode") -- cgit v1.2.3-54-g00ecf