summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/checkpoint.go2
-rw-r--r--cmd/podman/cleanup.go2
-rw-r--r--cmd/podman/cliconfig/config.go18
-rw-r--r--cmd/podman/common.go37
-rw-r--r--cmd/podman/init.go2
-rw-r--r--cmd/podman/kill.go2
-rw-r--r--cmd/podman/mount.go2
-rw-r--r--cmd/podman/pod_kill.go2
-rw-r--r--cmd/podman/pod_pause.go2
-rw-r--r--cmd/podman/pod_restart.go2
-rw-r--r--cmd/podman/pod_rm.go2
-rw-r--r--cmd/podman/pod_start.go2
-rw-r--r--cmd/podman/pod_stop.go2
-rw-r--r--cmd/podman/pod_unpause.go2
-rw-r--r--cmd/podman/port.go2
-rw-r--r--cmd/podman/restart.go2
-rw-r--r--cmd/podman/restore.go2
-rw-r--r--cmd/podman/rm.go8
-rw-r--r--cmd/podman/stop.go4
-rw-r--r--cmd/podman/umount.go2
-rw-r--r--completions/bash/podman2
-rw-r--r--docs/source/markdown/podman-rm.1.md10
-rw-r--r--docs/source/markdown/podman-stop.1.md8
-rw-r--r--libpod/container_internal.go5
-rw-r--r--libpod/image/image.go130
-rw-r--r--pkg/adapter/containers.go24
-rw-r--r--test/e2e/images_test.go1
-rw-r--r--test/e2e/rm_test.go76
-rw-r--r--test/e2e/stop_test.go76
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))
+ })
})