summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/utils/error.go7
-rw-r--r--docs/source/markdown/podman-volume-create.1.md44
-rw-r--r--go.mod2
-rw-r--r--go.sum3
-rw-r--r--libpod/container_internal_linux.go38
-rw-r--r--libpod/options.go26
-rw-r--r--libpod/runtime_volume_linux.go23
-rw-r--r--libpod/volume.go4
-rw-r--r--libpod/volume_internal.go3
-rw-r--r--libpod/volume_internal_linux.go2
-rw-r--r--pkg/domain/infra/abi/containers.go15
-rw-r--r--pkg/domain/infra/abi/parse/parse.go21
-rw-r--r--pkg/domain/infra/tunnel/containers.go17
-rw-r--r--pkg/machine/qemu/machine.go6
-rw-r--r--test/e2e/run_networking_test.go11
-rw-r--r--test/system/080-pause.bats19
-rw-r--r--vendor/github.com/docker/docker/api/swagger.yaml4
-rw-r--r--vendor/modules.txt2
18 files changed, 194 insertions, 53 deletions
diff --git a/cmd/podman/utils/error.go b/cmd/podman/utils/error.go
index 3464f0779..2d58bc70d 100644
--- a/cmd/podman/utils/error.go
+++ b/cmd/podman/utils/error.go
@@ -1,6 +1,9 @@
package utils
-import "fmt"
+import (
+ "fmt"
+ "os"
+)
type OutputErrors []error
@@ -10,7 +13,7 @@ func (o OutputErrors) PrintErrors() (lastError error) {
}
lastError = o[len(o)-1]
for e := 0; e < len(o)-1; e++ {
- fmt.Println(o[e])
+ fmt.Fprintf(os.Stderr, "Error: %s\n", o[e])
}
return
}
diff --git a/docs/source/markdown/podman-volume-create.1.md b/docs/source/markdown/podman-volume-create.1.md
index a06411000..9bf5a3d81 100644
--- a/docs/source/markdown/podman-volume-create.1.md
+++ b/docs/source/markdown/podman-volume-create.1.md
@@ -17,7 +17,7 @@ driver options can be set using the **--opt** flag.
#### **--driver**=*driver*
-Specify the volume driver name (default **local**). Setting this to a value other than **local** Podman will attempt to create the volume using a volume plugin with the given name. Such plugins must be defined in the **volume_plugins** section of the **containers.conf**(5) configuration file.
+Specify the volume driver name (default **local**). Setting this to a value other than **local** Podman attempts to create the volume using a volume plugin with the given name. Such plugins must be defined in the **volume_plugins** section of the **containers.conf**(5) configuration file.
#### **--help**
@@ -34,10 +34,14 @@ For the default driver, **local**, this allows a volume to be configured to moun
For the `local` driver the following options are supported: `type`, `device`, and `o`.
The `type` option sets the type of the filesystem to be mounted, and is equivalent to the `-t` flag to **mount(8)**.
The `device` option sets the device to be mounted, and is equivalent to the `device` argument to **mount(8)**.
-The `o` option sets options for the mount, and is equivalent to the `-o` flag to **mount(8)** with two exceptions.
-The `o` option supports `uid` and `gid` options to set the UID and GID of the created volume that are not normally supported by **mount(8)**.
-Using volume options with the **local** driver requires root privileges.
-When not using the **local** driver, the given options will be passed directly to the volume plugin. In this case, supported options will be dictated by the plugin in question, not Podman.
+
+The `o` option sets options for the mount, and is equivalent to the `-o` flag to **mount(8)** with these exceptions:
+
+ - The `o` option supports `uid` and `gid` options to set the UID and GID of the created volume that are not normally supported by **mount(8)**.
+ - The `o` option supports the `size` option to set the maximum size of the created volume and the `inodes` option to set the maximum number of inodes for the volume. Currently these flags are only supported on "xfs" file system mounted with the `prjquota` flag described in the **xfs_quota(8)** man page.
+ - Using volume options other then the UID/GID options with the **local** driver requires root privileges.
+
+When not using the **local** driver, the given options are passed directly to the volume plugin. In this case, supported options are dictated by the plugin in question, not Podman.
## EXAMPLES
@@ -53,8 +57,36 @@ $ podman volume create --label foo=bar myvol
# podman volume create --opt device=tmpfs --opt type=tmpfs --opt o=uid=1000,gid=1000 testvol
```
+## QUOTAS
+
+podman volume create uses `XFS project quota controls` for controlling the size and the number of inodes of builtin volumes. The directory used to store the volumes must be an`XFS` file system and be mounted with the `pquota` option.
+
+Example /etc/fstab entry:
+```
+/dev/podman/podman-var /var xfs defaults,x-systemd.device-timeout=0,pquota 1 2
+```
+
+Podman generates project ids for each builtin volume, but these project ids need to be unique for the XFS file system. These project ids by default are generated randomly, with a potential for overlap with other quotas on the same file
+system.
+
+The xfs_quota tool can be used to assign a project id to the storage driver directory, e.g.:
+
+```
+echo 100000:/var/lib/containers/storage/overlay >> /etc/projects
+echo 200000:/var/lib/containers/storage/volumes >> /etc/projects
+echo storage:100000 >> /etc/projid
+echo volumes:200000 >> /etc/projid
+xfs_quota -x -c 'project -s storage volumes' /<xfs mount point>
+```
+
+In the example above we are configuring the overlay storage driver for newly
+created containers as well as volumes to use project ids with a **start offset**.
+All containers will be assigned larger project ids (e.g. >= 100000).
+All volume assigned project ids larger project ids starting with 200000.
+This prevents xfs_quota management conflicts with containers/storage.
+
## SEE ALSO
-**podman-volume**(1), **mount**(8), **containers.conf**(5)
+**podman-volume**(1), **mount**(8), **containers.conf**(5), **xfs_quota**(8), `xfs_quota(8)`, `projects(5)`, `projid(5)`
## HISTORY
January 2020, updated with information on volume plugins by Matthew Heon <mheon@redhat.com>
diff --git a/go.mod b/go.mod
index b69ba2917..153e32711 100644
--- a/go.mod
+++ b/go.mod
@@ -25,7 +25,7 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/digitalocean/go-qemu v0.0.0-20210209191958-152a1535e49f
github.com/docker/distribution v2.7.1+incompatible
- github.com/docker/docker v20.10.7+incompatible
+ github.com/docker/docker v20.10.8+incompatible
github.com/docker/go-connections v0.4.0
github.com/docker/go-plugins-helpers v0.0.0-20200102110956-c9a8a2d92ccc
github.com/docker/go-units v0.4.0
diff --git a/go.sum b/go.sum
index 2ef22bdbc..8be637dec 100644
--- a/go.sum
+++ b/go.sum
@@ -322,8 +322,9 @@ github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v1.4.2-0.20191219165747-a9416c67da9f/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v20.10.8+incompatible h1:RVqD337BgQicVCzYrrlhLDWhq6OAD2PJDUg2LsEUvKM=
+github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index bff64aa95..f30f622ac 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1912,6 +1912,7 @@ func (c *Container) appendHosts(path string, netCtr *Container) (string, error)
// and returns a string in a format that can be written to the host file
func (c *Container) getHosts() string {
var hosts string
+
if len(c.config.HostAdd) > 0 {
for _, host := range c.config.HostAdd {
// the host format has already been verified at this point
@@ -1922,36 +1923,33 @@ func (c *Container) getHosts() string {
hosts += c.cniHosts()
- // If not making a network namespace, add our own hostname.
+ // Add hostname for slirp4netns
if c.Hostname() != "" {
if c.config.NetMode.IsSlirp4netns() {
// When using slirp4netns, the interface gets a static IP
slirp4netnsIP, err := GetSlirp4netnsIP(c.slirp4netnsSubnet)
if err != nil {
- logrus.Warn("failed to determine slirp4netnsIP: ", err.Error())
+ logrus.Warnf("failed to determine slirp4netnsIP: %v", err.Error())
} else {
hosts += fmt.Sprintf("# used by slirp4netns\n%s\t%s %s\n", slirp4netnsIP.String(), c.Hostname(), c.config.Name)
}
- } else {
- hasNetNS := false
- netNone := false
- for _, ns := range c.config.Spec.Linux.Namespaces {
- if ns.Type == spec.NetworkNamespace {
- hasNetNS = true
- if ns.Path == "" && !c.config.CreateNetNS {
- netNone = true
- }
- break
+ }
+
+ // Do we have a network namespace?
+ netNone := false
+ for _, ns := range c.config.Spec.Linux.Namespaces {
+ if ns.Type == spec.NetworkNamespace {
+ if ns.Path == "" && !c.config.CreateNetNS {
+ netNone = true
}
+ break
}
- if !hasNetNS {
- // 127.0.1.1 and host's hostname to match Docker
- osHostname, _ := os.Hostname()
- hosts += fmt.Sprintf("127.0.1.1 %s %s %s\n", osHostname, c.Hostname(), c.config.Name)
- }
- if netNone {
- hosts += fmt.Sprintf("127.0.1.1 %s %s\n", c.Hostname(), c.config.Name)
- }
+ }
+
+ // If we are net=none (have a network namespace, but not connected to
+ // anything) add the container's name and hostname to localhost.
+ if netNone {
+ hosts += fmt.Sprintf("127.0.0.1 %s %s\n", c.Hostname(), c.config.Name)
}
}
diff --git a/libpod/options.go b/libpod/options.go
index 17a36008d..b021b9f50 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1645,6 +1645,32 @@ func WithVolumeUID(uid int) VolumeCreateOption {
}
}
+// WithVolumeSize sets the maximum size of the volume
+func WithVolumeSize(size uint64) VolumeCreateOption {
+ return func(volume *Volume) error {
+ if volume.valid {
+ return define.ErrVolumeFinalized
+ }
+
+ volume.config.Size = size
+
+ return nil
+ }
+}
+
+// WithVolumeInodes sets the maximum inodes of the volume
+func WithVolumeInodes(inodes uint64) VolumeCreateOption {
+ return func(volume *Volume) error {
+ if volume.valid {
+ return define.ErrVolumeFinalized
+ }
+
+ volume.config.Inodes = inodes
+
+ return nil
+ }
+}
+
// WithVolumeGID sets the GID that the volume will be created as.
func WithVolumeGID(gid int) VolumeCreateOption {
return func(volume *Volume) error {
diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go
index 3d5bc8bb2..40df98d7c 100644
--- a/libpod/runtime_volume_linux.go
+++ b/libpod/runtime_volume_linux.go
@@ -12,6 +12,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/events"
volplugin "github.com/containers/podman/v3/libpod/plugin"
+ "github.com/containers/storage/drivers/quota"
"github.com/containers/storage/pkg/stringid"
pluginapi "github.com/docker/go-plugins-helpers/volume"
"github.com/pkg/errors"
@@ -68,7 +69,7 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption)
// Validate options
for key := range volume.config.Options {
switch key {
- case "device", "o", "type", "UID", "GID":
+ case "device", "o", "type", "UID", "GID", "SIZE", "INODES":
// Do nothing, valid keys
default:
return nil, errors.Wrapf(define.ErrInvalidArg, "invalid mount option %s for driver 'local'", key)
@@ -106,6 +107,26 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption)
if err := LabelVolumePath(fullVolPath); err != nil {
return nil, err
}
+ projectQuotaSupported := false
+
+ q, err := quota.NewControl(r.config.Engine.VolumePath)
+ if err == nil {
+ projectQuotaSupported = true
+ }
+ quota := quota.Quota{}
+ if volume.config.Size > 0 || volume.config.Inodes > 0 {
+ if !projectQuotaSupported {
+ return nil, errors.New("Volume options size and inodes not supported. Filesystem does not support Project Quota")
+ }
+ quota.Size = volume.config.Size
+ quota.Inodes = volume.config.Inodes
+ }
+ if projectQuotaSupported {
+ if err := q.SetQuota(fullVolPath, quota); err != nil {
+ return nil, errors.Wrapf(err, "failed to set size quota size=%d inodes=%d for volume directory %q", volume.config.Size, volume.config.Inodes, fullVolPath)
+ }
+ }
+
volume.config.MountPoint = fullVolPath
}
diff --git a/libpod/volume.go b/libpod/volume.go
index 506c45b5a..8f3dc4fcc 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -49,6 +49,10 @@ type VolumeConfig struct {
UID int `json:"uid"`
// GID the volume will be created as.
GID int `json:"gid"`
+ // Size maximum of the volume.
+ Size uint64 `json:"size"`
+ // Inodes maximum of the volume.
+ Inodes uint64 `json:"inodes"`
}
// VolumeState holds the volume's mutable state.
diff --git a/libpod/volume_internal.go b/libpod/volume_internal.go
index 19008a253..f69f1c044 100644
--- a/libpod/volume_internal.go
+++ b/libpod/volume_internal.go
@@ -49,6 +49,9 @@ func (v *Volume) needsMount() bool {
if _, ok := v.config.Options["GID"]; ok {
index++
}
+ if _, ok := v.config.Options["SIZE"]; ok {
+ index++
+ }
// when uid or gid is set there is also the "o" option
// set so we have to ignore this one as well
if index > 0 {
diff --git a/libpod/volume_internal_linux.go b/libpod/volume_internal_linux.go
index 92391de1d..45cd22385 100644
--- a/libpod/volume_internal_linux.go
+++ b/libpod/volume_internal_linux.go
@@ -104,7 +104,7 @@ func (v *Volume) mount() error {
logrus.Debugf("Running mount command: %s %s", mountPath, strings.Join(mountArgs, " "))
if output, err := mountCmd.CombinedOutput(); err != nil {
- logrus.Debugf("Mount failed with %v", err)
+ logrus.Debugf("Mount %v failed with %v", mountCmd, err)
return errors.Wrapf(errors.Errorf(string(output)), "error mounting volume %s", v.Name())
}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index ddd768328..a74b65ab9 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -119,6 +119,10 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
report := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := c.Pause()
+ if err != nil && options.All && errors.Cause(err) == define.ErrCtrStateInvalid {
+ logrus.Debugf("Container %s is not running", c.ID())
+ continue
+ }
report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err})
}
return report, nil
@@ -132,6 +136,10 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
report := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := c.Unpause()
+ if err != nil && options.All && errors.Cause(err) == define.ErrCtrStateInvalid {
+ logrus.Debugf("Container %s is not paused", c.ID())
+ continue
+ }
report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err})
}
return report, nil
@@ -220,9 +228,14 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
}
reports := make([]*entities.KillReport, 0, len(ctrs))
for _, con := range ctrs {
+ err := con.Kill(uint(sig))
+ if options.All && errors.Cause(err) == define.ErrCtrStateInvalid {
+ logrus.Debugf("Container %s is not running", con.ID())
+ continue
+ }
reports = append(reports, &entities.KillReport{
Id: con.ID(),
- Err: con.Kill(uint(sig)),
+ Err: err,
RawInput: ctrMap[con.ID()],
})
}
diff --git a/pkg/domain/infra/abi/parse/parse.go b/pkg/domain/infra/abi/parse/parse.go
index 56c747711..5a75e1216 100644
--- a/pkg/domain/infra/abi/parse/parse.go
+++ b/pkg/domain/infra/abi/parse/parse.go
@@ -6,12 +6,13 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
+ units "github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
// Handle volume options from CLI.
-// Parse "o" option to find UID, GID.
+// Parse "o" option to find UID, GID, Size.
func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) {
libpodOptions := []libpod.VolumeCreateOption{}
volumeOptions := make(map[string]string)
@@ -28,6 +29,24 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error)
// "opt=value"
splitO := strings.SplitN(o, "=", 2)
switch strings.ToLower(splitO[0]) {
+ case "size":
+ size, err := units.FromHumanSize(splitO[1])
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot convert size %s to integer", splitO[1])
+ }
+ libpodOptions = append(libpodOptions, libpod.WithVolumeSize(uint64(size)))
+ finalVal = append(finalVal, o)
+ // set option "SIZE": "$size"
+ volumeOptions["SIZE"] = splitO[1]
+ case "inodes":
+ inodes, err := strconv.ParseUint(splitO[1], 10, 64)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot convert inodes %s to integer", splitO[1])
+ }
+ libpodOptions = append(libpodOptions, libpod.WithVolumeInodes(uint64(inodes)))
+ finalVal = append(finalVal, o)
+ // set option "INODES": "$size"
+ volumeOptions["INODES"] = splitO[1]
case "uid":
if len(splitO) != 2 {
return nil, errors.Wrapf(define.ErrInvalidArg, "uid option must provide a UID")
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 3c2802165..b638bfe24 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -63,19 +63,27 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := containers.Pause(ic.ClientCtx, c.ID, nil)
+ if err != nil && options.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() {
+ logrus.Debugf("Container %s is not running", c.ID)
+ continue
+ }
reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err})
}
return reports, nil
}
func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
+ reports := []*entities.PauseUnpauseReport{}
ctrs, err := getContainersByContext(ic.ClientCtx, options.All, false, namesOrIds)
if err != nil {
return nil, err
}
- reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := containers.Unpause(ic.ClientCtx, c.ID, nil)
+ if err != nil && options.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() {
+ logrus.Debugf("Container %s is not paused", c.ID)
+ continue
+ }
reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err})
}
return reports, nil
@@ -136,9 +144,14 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
options := new(containers.KillOptions).WithSignal(opts.Signal)
reports := make([]*entities.KillReport, 0, len(ctrs))
for _, c := range ctrs {
+ err := containers.Kill(ic.ClientCtx, c.ID, options)
+ if err != nil && opts.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() {
+ logrus.Debugf("Container %s is not running", c.ID)
+ continue
+ }
reports = append(reports, &entities.KillReport{
Id: c.ID,
- Err: containers.Kill(ic.ClientCtx, c.ID, options),
+ Err: err,
RawInput: ctrMap[c.ID],
})
}
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 42ae23c43..0740a2b2c 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -603,9 +603,9 @@ func CheckActiveVM() (bool, string, error) {
// startHostNetworking runs a binary on the host system that allows users
// to setup port forwarding to the podman virtual machine
func (v *MachineVM) startHostNetworking() error {
- binary, err := exec.LookPath(machine.ForwarderBinaryName)
- if err != nil {
- return err
+ binary := filepath.Join("/usr/lib/podman/", machine.ForwarderBinaryName)
+ if _, err := os.Stat(binary); os.IsNotExist(err) {
+ return errors.Errorf("unable to find %s", binary)
}
// Listen on all at port 7777 for setting up and tearing
// down forwarding
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index 80a82ea05..92388b099 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -685,13 +685,6 @@ var _ = Describe("Podman run networking", func() {
Expect(podrm).Should(Exit(0))
})
- It("podman run net=host adds entry to /etc/hosts", func() {
- run := podmanTest.Podman([]string{"run", "--net=host", ALPINE, "cat", "/etc/hosts"})
- run.WaitWithDefaultTimeout()
- Expect(run).Should(Exit(0))
- Expect(strings.Contains(run.OutputToString(), "127.0.1.1")).To(BeTrue())
- })
-
It("podman run with --net=host and --hostname sets correct hostname", func() {
hostname := "testctr"
run := podmanTest.Podman([]string{"run", "--net=host", "--hostname", hostname, ALPINE, "hostname"})
@@ -731,10 +724,6 @@ var _ = Describe("Podman run networking", func() {
ping_test("--net=none")
})
- It("podman attempt to ping container name and hostname --net=host", func() {
- ping_test("--net=host")
- })
-
It("podman attempt to ping container name and hostname --net=private", func() {
ping_test("--net=private")
})
diff --git a/test/system/080-pause.bats b/test/system/080-pause.bats
index ea4c85f8f..1eb47dcfb 100644
--- a/test/system/080-pause.bats
+++ b/test/system/080-pause.bats
@@ -57,4 +57,23 @@ load helpers
run_podman 125 unpause $cname
}
+@test "podman unpause --all" {
+ if is_rootless && ! is_cgroupsv2; then
+ skip "'podman pause' (rootless) only works with cgroups v2"
+ fi
+
+ cname=$(random_string 10)
+ run_podman create --name notrunning $IMAGE
+ run_podman run -d --name $cname $IMAGE sleep 100
+ cid="$output"
+ run_podman pause $cid
+ run_podman inspect --format '{{.State.Status}}' $cid
+ is "$output" "paused" "podman inspect .State.Status"
+ run_podman unpause --all
+ is "$output" "$cid" "podman unpause output"
+ run_podman ps --format '{{.ID}} {{.Names}} {{.Status}}'
+ is "$output" "${cid:0:12} $cname Up.*" "podman ps on resumed container"
+ run_podman rm -f $cname
+ run_podman rm -f notrunning
+}
# vim: filetype=sh
diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml
index 1294e5a22..bada4a8e3 100644
--- a/vendor/github.com/docker/docker/api/swagger.yaml
+++ b/vendor/github.com/docker/docker/api/swagger.yaml
@@ -5583,12 +5583,12 @@ paths:
schema:
$ref: "#/definitions/ErrorResponse"
404:
- description: "no such container"
+ description: "no such image"
schema:
$ref: "#/definitions/ErrorResponse"
examples:
application/json:
- message: "No such container: c2ada9df5af8"
+ message: "No such image: c2ada9df5af8"
409:
description: "conflict"
schema:
diff --git a/vendor/modules.txt b/vendor/modules.txt
index c26f302fc..ddf731e22 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -285,7 +285,7 @@ github.com/docker/distribution/registry/client/auth/challenge
github.com/docker/distribution/registry/client/transport
github.com/docker/distribution/registry/storage/cache
github.com/docker/distribution/registry/storage/cache/memory
-# github.com/docker/docker v20.10.7+incompatible
+# github.com/docker/docker v20.10.8+incompatible
github.com/docker/docker/api
github.com/docker/docker/api/types
github.com/docker/docker/api/types/blkiodev