diff options
29 files changed, 305 insertions, 126 deletions
diff --git a/cmd/podman/checkpoint.go b/cmd/podman/checkpoint.go index 22cdb1f39..07db519f8 100644 --- a/cmd/podman/checkpoint.go +++ b/cmd/podman/checkpoint.go @@ -26,7 +26,7 @@ var ( return checkpointCmd(&checkpointCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman container checkpoint --keep ctrID podman container checkpoint --all diff --git a/cmd/podman/cleanup.go b/cmd/podman/cleanup.go index c00654162..a8bc0c116 100644 --- a/cmd/podman/cleanup.go +++ b/cmd/podman/cleanup.go @@ -27,7 +27,7 @@ var ( return cleanupCmd(&cleanupCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman container cleanup --latest podman container cleanup ctrID1 ctrID2 ctrID3 diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go index 780b68333..541b2e05d 100644 --- a/cmd/podman/cliconfig/config.go +++ b/cmd/podman/cliconfig/config.go @@ -480,11 +480,12 @@ type RestoreValues struct { type RmValues struct { PodmanCommand - All bool - Force bool - Latest bool - Storage bool - Volumes bool + All bool + Force bool + Latest bool + Storage bool + Volumes bool + CIDFiles []string } type RmiValues struct { @@ -557,9 +558,10 @@ type StatsValues struct { type StopValues struct { PodmanCommand - All bool - Latest bool - Timeout uint + All bool + Latest bool + Timeout uint + CIDFiles []string } type TopValues struct { diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 4db043f31..442823d2d 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -39,24 +39,45 @@ func shortID(id string) string { return id } -// checkAllAndLatest checks that --all and --latest are used correctly -func checkAllAndLatest(c *cobra.Command, args []string, ignoreArgLen bool) error { +// checkAllLatestAndCIDFile checks that --all and --latest are used correctly. +// If cidfile is set, also check for the --cidfile flag. +func checkAllLatestAndCIDFile(c *cobra.Command, args []string, ignoreArgLen bool, cidfile bool) error { argLen := len(args) if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil { - return errors.New("unable to lookup values for 'latest' or 'all'") + if !cidfile { + return errors.New("unable to lookup values for 'latest' or 'all'") + } else if c.Flags().Lookup("cidfile") == nil { + return errors.New("unable to lookup values for 'latest', 'all' or 'cidfile'") + } + } + + specifiedAll, _ := c.Flags().GetBool("all") + specifiedLatest, _ := c.Flags().GetBool("latest") + specifiedCIDFile := false + if cid, _ := c.Flags().GetStringArray("cidfile"); len(cid) > 0 { + specifiedCIDFile = true } - all, _ := c.Flags().GetBool("all") - latest, _ := c.Flags().GetBool("latest") - if all && latest { + + if specifiedCIDFile && (specifiedAll || specifiedLatest) { + return errors.Errorf("--all, --latest and --cidfile cannot be used together") + } else if specifiedAll && specifiedLatest { return errors.Errorf("--all and --latest cannot be used together") } + if ignoreArgLen { return nil } - if (all || latest) && argLen > 0 { + if (argLen > 0) && (specifiedAll || specifiedLatest) { return errors.Errorf("no arguments are needed with --all or --latest") + } else if cidfile && (argLen > 0) && (specifiedAll || specifiedLatest || specifiedCIDFile) { + return errors.Errorf("no arguments are needed with --all, --latest or --cidfile") } - if argLen < 1 && !all && !latest { + + if specifiedCIDFile { + return nil + } + + if argLen < 1 && !specifiedAll && !specifiedLatest && !specifiedCIDFile { return errors.Errorf("you must provide at least one name or id") } return nil diff --git a/cmd/podman/init.go b/cmd/podman/init.go index 3f97824fc..2e0b33828 100644 --- a/cmd/podman/init.go +++ b/cmd/podman/init.go @@ -23,7 +23,7 @@ var ( return initCmd(&initCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman init --latest podman init 3c45ef19d893 diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go index d5056d86d..aba2008ca 100644 --- a/cmd/podman/kill.go +++ b/cmd/podman/kill.go @@ -24,7 +24,7 @@ var ( return killCmd(&killCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman kill mywebserver podman kill 860a4b23 diff --git a/cmd/podman/mount.go b/cmd/podman/mount.go index b14827592..526a236fd 100644 --- a/cmd/podman/mount.go +++ b/cmd/podman/mount.go @@ -35,7 +35,7 @@ var ( return mountCmd(&mountCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, true) + return checkAllLatestAndCIDFile(cmd, args, true, false) }, } ) diff --git a/cmd/podman/pod_kill.go b/cmd/podman/pod_kill.go index 9bda77471..064946f72 100644 --- a/cmd/podman/pod_kill.go +++ b/cmd/podman/pod_kill.go @@ -28,7 +28,7 @@ var ( return podKillCmd(&podKillCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod kill podID podman pod kill --signal TERM mywebserver diff --git a/cmd/podman/pod_pause.go b/cmd/podman/pod_pause.go index 45e1319ff..320072919 100644 --- a/cmd/podman/pod_pause.go +++ b/cmd/podman/pod_pause.go @@ -25,7 +25,7 @@ var ( return podPauseCmd(&podPauseCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod pause podID1 podID2 podman pod pause --latest diff --git a/cmd/podman/pod_restart.go b/cmd/podman/pod_restart.go index cc090bd6e..cb9f3770f 100644 --- a/cmd/podman/pod_restart.go +++ b/cmd/podman/pod_restart.go @@ -26,7 +26,7 @@ var ( return podRestartCmd(&podRestartCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod restart podID1 podID2 podman pod restart --latest diff --git a/cmd/podman/pod_rm.go b/cmd/podman/pod_rm.go index 82d0eb977..86d6d2f27 100644 --- a/cmd/podman/pod_rm.go +++ b/cmd/podman/pod_rm.go @@ -26,7 +26,7 @@ var ( return podRmCmd(&podRmCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod rm mywebserverpod podman pod rm -f 860a4b23 diff --git a/cmd/podman/pod_start.go b/cmd/podman/pod_start.go index 64c951b43..aa2e09e98 100644 --- a/cmd/podman/pod_start.go +++ b/cmd/podman/pod_start.go @@ -26,7 +26,7 @@ var ( return podStartCmd(&podStartCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod start podID podman pod start --latest diff --git a/cmd/podman/pod_stop.go b/cmd/podman/pod_stop.go index edda99550..579e4f1d3 100644 --- a/cmd/podman/pod_stop.go +++ b/cmd/podman/pod_stop.go @@ -27,7 +27,7 @@ var ( return podStopCmd(&podStopCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod stop mywebserverpod podman pod stop --latest diff --git a/cmd/podman/pod_unpause.go b/cmd/podman/pod_unpause.go index 833434c3f..1f80a7c79 100644 --- a/cmd/podman/pod_unpause.go +++ b/cmd/podman/pod_unpause.go @@ -26,7 +26,7 @@ var ( return podUnpauseCmd(&podUnpauseCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod unpause podID1 podID2 podman pod unpause --all diff --git a/cmd/podman/port.go b/cmd/podman/port.go index 4e1f9642c..eef3d4b1d 100644 --- a/cmd/podman/port.go +++ b/cmd/podman/port.go @@ -26,7 +26,7 @@ var ( return portCmd(&portCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, true) + return checkAllLatestAndCIDFile(cmd, args, true, false) }, Example: `podman port --all podman port ctrID 80/tcp diff --git a/cmd/podman/restart.go b/cmd/podman/restart.go index c97fb0dc1..996a9f7ce 100644 --- a/cmd/podman/restart.go +++ b/cmd/podman/restart.go @@ -23,7 +23,7 @@ var ( return restartCmd(&restartCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman restart ctrID podman restart --latest diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go index caefadb6d..a8db7fa94 100644 --- a/cmd/podman/restore.go +++ b/cmd/podman/restore.go @@ -26,7 +26,7 @@ var ( return restoreCmd(&restoreCommand, cmd) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, true) + return checkAllLatestAndCIDFile(cmd, args, true, false) }, Example: `podman container restore ctrID podman container restore --latest diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go index 6329a9d8e..b3bc8e1b9 100644 --- a/cmd/podman/rm.go +++ b/cmd/podman/rm.go @@ -25,7 +25,7 @@ var ( return rmCmd(&rmCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, true) }, Example: `podman rm imageID podman rm mywebserver myflaskserver 860a4b23 @@ -44,8 +44,10 @@ func init() { flags.BoolVarP(&rmCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&rmCommand.Storage, "storage", false, "Remove container from storage library") flags.BoolVarP(&rmCommand.Volumes, "volumes", "v", false, "Remove anonymous volumes associated with the container") + flags.StringArrayVarP(&rmCommand.CIDFiles, "cidfile", "", nil, "Read the container ID from the file") markFlagHiddenForRemoteClient("storage", flags) markFlagHiddenForRemoteClient("latest", flags) + markFlagHiddenForRemoteClient("cidfile", flags) } // rmCmd removes one or more containers @@ -58,8 +60,8 @@ func rmCmd(c *cliconfig.RmValues) error { // Storage conflicts with --all/--latest/--volumes if c.Storage { - if c.All || c.Latest || c.Volumes { - return errors.Errorf("--storage conflicts with --volumes, --all, and --latest") + if c.All || c.Latest || c.Volumes || c.CIDFiles != nil { + return errors.Errorf("--storage conflicts with --volumes, --all, --latest and --cidfile") } } diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go index e04d8a12b..acecb298e 100644 --- a/cmd/podman/stop.go +++ b/cmd/podman/stop.go @@ -25,7 +25,7 @@ var ( return stopCmd(&stopCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, true) }, Example: `podman stop ctrID podman stop --latest @@ -42,7 +42,9 @@ func init() { flags.BoolVarP(&stopCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.UintVar(&stopCommand.Timeout, "time", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") flags.UintVarP(&stopCommand.Timeout, "timeout", "t", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") + flags.StringArrayVarP(&stopCommand.CIDFiles, "cidfile", "", nil, "Read the container ID from the file") markFlagHiddenForRemoteClient("latest", flags) + markFlagHiddenForRemoteClient("cidfile", flags) } // stopCmd stops a container or containers diff --git a/cmd/podman/umount.go b/cmd/podman/umount.go index c3d81d3a8..6ad485c2c 100644 --- a/cmd/podman/umount.go +++ b/cmd/podman/umount.go @@ -28,7 +28,7 @@ var ( return umountCmd(&umountCommand) }, Args: func(cmd *cobra.Command, args []string) error { - return checkAllAndLatest(cmd, args, false) + return checkAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman umount ctrID podman umount ctrID1 ctrID2 ctrID3 diff --git a/completions/bash/podman b/completions/bash/podman index d8034ad11..98950799e 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -2150,6 +2150,7 @@ _podman_rm() { local boolean_options=" --all -a + --cidfile --force -f --help @@ -2426,6 +2427,7 @@ _podman_stop() { local boolean_options=" --all -a + --cidfile -h --help --latest diff --git a/docs/source/markdown/podman-rm.1.md b/docs/source/markdown/podman-rm.1.md index c1663129c..74831fef6 100644 --- a/docs/source/markdown/podman-rm.1.md +++ b/docs/source/markdown/podman-rm.1.md @@ -18,6 +18,10 @@ Running or unusable containers will not be removed without the `-f` option. Remove all containers. Can be used in conjunction with -f as well. +**--cidfile** + +Read container ID from the specified file and remove the container. Can be specified multiple times. + **--force**, **-f** Force the removal of running and paused containers. Forcing a container removal also @@ -50,11 +54,17 @@ Remove a container by its name *mywebserver* ``` podman rm mywebserver ``` + Remove several containers by name and container id. ``` podman rm mywebserver myflaskserver 860a4b23 ``` +Remove several containers reading their IDs from files. +``` +podman rm --cidfile ./cidfile-1 --cidfile /home/user/cidfile-2 +``` + Forcibly remove a container by container ID. ``` podman rm -f 860a4b23 diff --git a/docs/source/markdown/podman-stop.1.md b/docs/source/markdown/podman-stop.1.md index b5ea670b0..5e8056e92 100644 --- a/docs/source/markdown/podman-stop.1.md +++ b/docs/source/markdown/podman-stop.1.md @@ -21,6 +21,10 @@ container and also via command line when creating the container. Stop all running containers. This does not include paused containers. +**--cidfile** + +Read container ID from the specified file and remove the container. Can be specified multiple times. + **--latest**, **-l** Instead of providing the container name or ID, use the last created container. If you use methods other than Podman @@ -40,6 +44,10 @@ podman stop 860a4b235279 podman stop mywebserver 860a4b235279 +podman stop --cidfile /home/user/cidfile-1 + +podman stop --cidfile /home/user/cidfile-1 --cidfile ./cidfile-2 + podman stop --timeout 2 860a4b235279 podman stop -a diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 028d7601d..4ff1913b5 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -652,6 +652,11 @@ func (c *Container) removeConmonFiles() error { return errors.Wrapf(err, "error removing container %s ctl file", c.ID()) } + winszFile := filepath.Join(c.bundlePath(), "winsz") + if err := os.Remove(winszFile); err != nil && !os.IsNotExist(err) { + return errors.Wrapf(err, "error removing container %s winsz file", c.ID()) + } + oomFile := filepath.Join(c.bundlePath(), "oom") if err := os.Remove(oomFile); err != nil && !os.IsNotExist(err) { return errors.Wrapf(err, "error removing container %s OOM file", c.ID()) diff --git a/libpod/image/image.go b/libpod/image/image.go index c912ac2ca..75ac85311 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -765,109 +765,65 @@ func (i *Image) History(ctx context.Context) ([]*History, error) { return nil, err } - // Use our layers list to find images that use any of them (or no - // layer, since every base layer is derived from an empty layer) as its - // topmost layer. - interestingLayers := make(map[string]bool) - var layer *storage.Layer - if i.TopLayer() != "" { - if layer, err = i.imageruntime.store.Layer(i.TopLayer()); err != nil { - return nil, err - } + // Build a mapping from top-layer to image ID. + images, err := i.imageruntime.GetImages() + if err != nil { + return nil, err } - interestingLayers[""] = true - for layer != nil { - interestingLayers[layer.ID] = true - if layer.Parent == "" { - break + topLayerMap := make(map[string]string) + for _, image := range images { + if _, exists := topLayerMap[image.TopLayer()]; !exists { + topLayerMap[image.TopLayer()] = image.ID() } - layer, err = i.imageruntime.store.Layer(layer.Parent) + } + + var allHistory []*History + var layer *storage.Layer + + // Check if we have an actual top layer to prevent lookup errors. + if i.TopLayer() != "" { + layer, err = i.imageruntime.store.Layer(i.TopLayer()) if err != nil { return nil, err } } - // Get the IDs of the images that share some of our layers. Hopefully - // this step means that we'll be able to avoid reading the - // configuration of every single image in local storage later on. - images, err := i.imageruntime.GetImages() - if err != nil { - return nil, errors.Wrapf(err, "error getting images from store") - } - interestingImages := make([]*Image, 0, len(images)) - for i := range images { - if interestingLayers[images[i].TopLayer()] { - interestingImages = append(interestingImages, images[i]) - } - } + // Iterate in reverse order over the history entries, and lookup the + // corresponding image ID, size and get the next later if needed. + numHistories := len(oci.History) - 1 + for x := numHistories; x >= 0; x-- { + var size int64 - // Build a list of image IDs that correspond to our history entries. - historyImages := make([]*Image, len(oci.History)) - if len(oci.History) > 0 { - // The starting image shares its whole history with itself. - historyImages[len(historyImages)-1] = i - for i := range interestingImages { - image, err := images[i].ociv1Image(ctx) - if err != nil { - return nil, errors.Wrapf(err, "error getting image configuration for image %q", images[i].ID()) + id := "<missing>" + if x == numHistories { + id = i.ID() + } else if layer != nil { + if !oci.History[x].EmptyLayer { + size = layer.UncompressedSize } - // If the candidate has a longer history or no history - // at all, then it doesn't share the portion of our - // history that we're interested in matching with other - // images. - if len(image.History) == 0 || len(image.History) > len(historyImages) { - continue - } - // If we don't include all of the layers that the - // candidate image does (i.e., our rootfs didn't look - // like its rootfs at any point), then it can't be part - // of our history. - if len(image.RootFS.DiffIDs) > len(oci.RootFS.DiffIDs) { - continue - } - candidateLayersAreUsed := true - for i := range image.RootFS.DiffIDs { - if image.RootFS.DiffIDs[i] != oci.RootFS.DiffIDs[i] { - candidateLayersAreUsed = false - break - } - } - if !candidateLayersAreUsed { - continue - } - // If the candidate's entire history is an initial - // portion of our history, then we're based on it, - // either directly or indirectly. - sharedHistory := historiesMatch(oci.History, image.History) - if sharedHistory == len(image.History) { - historyImages[sharedHistory-1] = images[i] + if imageID, exists := topLayerMap[layer.ID]; exists { + id = imageID + // Delete the entry to avoid reusing it for following history items. + delete(topLayerMap, layer.ID) } } - } - var ( - size int64 - sizeCount = 1 - allHistory []*History - ) - - for i := len(oci.History) - 1; i >= 0; i-- { - imageID := "<missing>" - if historyImages[i] != nil { - imageID = historyImages[i].ID() - } - if !oci.History[i].EmptyLayer { - size = img.LayerInfos()[len(img.LayerInfos())-sizeCount].Size - sizeCount++ - } allHistory = append(allHistory, &History{ - ID: imageID, - Created: oci.History[i].Created, - CreatedBy: oci.History[i].CreatedBy, + ID: id, + Created: oci.History[x].Created, + CreatedBy: oci.History[x].CreatedBy, Size: size, - Comment: oci.History[i].Comment, + Comment: oci.History[x].Comment, }) + + if layer != nil && layer.Parent != "" && !oci.History[x].EmptyLayer { + layer, err = i.imageruntime.store.Layer(layer.Parent) + if err != nil { + return nil, err + } + } } + return allHistory, nil } diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 287bd8474..02da9ec8c 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -79,7 +79,17 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa } logrus.Debugf("Setting maximum stop workers to %d", maxWorkers) - ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime) + names := cli.InputArgs + for _, cidFile := range cli.CIDFiles { + content, err := ioutil.ReadFile(cidFile) + if err != nil { + return nil, nil, errors.Wrap(err, "error reading CIDFile") + } + id := strings.Split(string(content), "\n")[0] + names = append(names, id) + } + + ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, names, r.Runtime) if err != nil { return nil, nil, err } @@ -203,7 +213,17 @@ func (r *LocalRuntime) RemoveContainers(ctx context.Context, cli *cliconfig.RmVa return ok, failures, nil } - ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, cli.InputArgs, r.Runtime) + names := cli.InputArgs + for _, cidFile := range cli.CIDFiles { + content, err := ioutil.ReadFile(cidFile) + if err != nil { + return nil, nil, errors.Wrap(err, "error reading CIDFile") + } + id := strings.Split(string(content), "\n")[0] + names = append(names, id) + } + + ctrs, err := shortcuts.GetContainersByContext(cli.All, cli.Latest, names, r.Runtime) if err != nil { // Failed to get containers. If force is specified, get the containers ID // and evict them diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go index e125c62b4..80e6d4444 100644 --- a/test/e2e/images_test.go +++ b/test/e2e/images_test.go @@ -360,7 +360,6 @@ LABEL "com.example.vendor"="Example Vendor" session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) output = session.OutputToString() - Expect(output).To(Not(MatchRegexp("<missing>"))) Expect(output).To(Not(MatchRegexp("error"))) session = podmanTest.Podman([]string{"history", "--quiet", "foo"}) diff --git a/test/e2e/rm_test.go b/test/e2e/rm_test.go index 8ee7dc750..531f14feb 100644 --- a/test/e2e/rm_test.go +++ b/test/e2e/rm_test.go @@ -1,6 +1,7 @@ package integration import ( + "io/ioutil" "os" . "github.com/containers/libpod/test/utils" @@ -138,11 +139,86 @@ var _ = Describe("Podman rm", func() { }) + It("podman rm --cidfile", func() { + SkipIfRemote() + + tmpDir, err := ioutil.TempDir("", "") + Expect(err).To(BeNil()) + tmpFile := tmpDir + "cid" + + defer os.RemoveAll(tmpDir) + + session := podmanTest.Podman([]string{"create", "--cidfile", tmpFile, ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid := session.OutputToStringArray()[0] + Expect(podmanTest.NumberOfContainers()).To(Equal(1)) + + result := podmanTest.Podman([]string{"rm", "--cidfile", tmpFile}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + output := result.OutputToString() + Expect(output).To(ContainSubstring(cid)) + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + }) + + It("podman rm multiple --cidfile", func() { + SkipIfRemote() + + tmpDir, err := ioutil.TempDir("", "") + Expect(err).To(BeNil()) + tmpFile1 := tmpDir + "cid-1" + tmpFile2 := tmpDir + "cid-2" + + defer os.RemoveAll(tmpDir) + + session := podmanTest.Podman([]string{"create", "--cidfile", tmpFile1, ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid1 := session.OutputToStringArray()[0] + Expect(podmanTest.NumberOfContainers()).To(Equal(1)) + + session = podmanTest.Podman([]string{"create", "--cidfile", tmpFile2, ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid2 := session.OutputToStringArray()[0] + Expect(podmanTest.NumberOfContainers()).To(Equal(2)) + + result := podmanTest.Podman([]string{"rm", "--cidfile", tmpFile1, "--cidfile", tmpFile2}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + output := result.OutputToString() + Expect(output).To(ContainSubstring(cid1)) + Expect(output).To(ContainSubstring(cid2)) + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + }) + + It("podman rm invalid --latest and --cidfile and --all", func() { + SkipIfRemote() + + result := podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--latest"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(125)) + + result = podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--all"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(125)) + + result = podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--all", "--latest"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(125)) + + result = podmanTest.Podman([]string{"rm", "--latest", "--all"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(125)) + }) + It("podman rm bogus container", func() { session := podmanTest.Podman([]string{"rm", "bogus"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(1)) }) + It("podman rm bogus container and a running container", func() { session := podmanTest.RunTopContainer("test1") session.WaitWithDefaultTimeout() diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go index 77ab6dbb0..c76cccfef 100644 --- a/test/e2e/stop_test.go +++ b/test/e2e/stop_test.go @@ -1,6 +1,7 @@ package integration import ( + "io/ioutil" "os" "strings" @@ -215,4 +216,79 @@ var _ = Describe("Podman stop", func() { Expect(strings.TrimSpace(finalCtrs.OutputToString())).To(Equal("")) }) + It("podman stop --cidfile", func() { + SkipIfRemote() + + tmpDir, err := ioutil.TempDir("", "") + Expect(err).To(BeNil()) + tmpFile := tmpDir + "cid" + + defer os.RemoveAll(tmpDir) + + session := podmanTest.Podman([]string{"create", "--cidfile", tmpFile, "-d", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid := session.OutputToStringArray()[0] + + session = podmanTest.Podman([]string{"start", cid}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + result := podmanTest.Podman([]string{"stop", "--cidfile", tmpFile}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + output := result.OutputToString() + Expect(output).To(ContainSubstring(cid)) + }) + + It("podman stop multiple --cidfile", func() { + SkipIfRemote() + + tmpDir, err := ioutil.TempDir("", "") + Expect(err).To(BeNil()) + tmpFile1 := tmpDir + "cid-1" + tmpFile2 := tmpDir + "cid-2" + + defer os.RemoveAll(tmpDir) + + session := podmanTest.Podman([]string{"run", "--cidfile", tmpFile1, "-d", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid1 := session.OutputToStringArray()[0] + Expect(podmanTest.NumberOfContainers()).To(Equal(1)) + + session = podmanTest.Podman([]string{"run", "--cidfile", tmpFile2, "-d", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid2 := session.OutputToStringArray()[0] + Expect(podmanTest.NumberOfContainers()).To(Equal(2)) + + result := podmanTest.Podman([]string{"stop", "--cidfile", tmpFile1, "--cidfile", tmpFile2}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + output := result.OutputToString() + Expect(output).To(ContainSubstring(cid1)) + Expect(output).To(ContainSubstring(cid2)) + Expect(podmanTest.NumberOfContainers()).To(Equal(2)) + }) + + It("podman stop invalid --latest and --cidfile and --all", func() { + SkipIfRemote() + + result := podmanTest.Podman([]string{"stop", "--cidfile", "foobar", "--latest"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(125)) + + result = podmanTest.Podman([]string{"stop", "--cidfile", "foobar", "--all"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(125)) + + result = podmanTest.Podman([]string{"stop", "--cidfile", "foobar", "--all", "--latest"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(125)) + + result = podmanTest.Podman([]string{"stop", "--latest", "--all"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(125)) + }) }) |