summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/machine/machine_unix.go4
-rw-r--r--docs/source/Tutorials.rst3
-rw-r--r--docs/tutorials/mac_win_client.md4
-rw-r--r--go.mod2
-rw-r--r--go.sum3
-rwxr-xr-xhack/parse-localbenchmarks104
-rw-r--r--libpod/info.go11
-rw-r--r--libpod/info_test.go8
-rw-r--r--libpod/runtime.go2
-rw-r--r--libpod/runtime_ctr.go6
-rw-r--r--pkg/api/handlers/compat/images_build.go49
-rw-r--r--pkg/machine/wsl/machine.go40
-rw-r--r--pkg/specgen/generate/pause_image.go6
-rw-r--r--test/apiv2/10-images.at4
-rw-r--r--test/system/170-run-userns.bats13
-rw-r--r--vendor/modules.txt2
16 files changed, 234 insertions, 27 deletions
diff --git a/cmd/podman/machine/machine_unix.go b/cmd/podman/machine/machine_unix.go
index 213c24f8c..b56d081ec 100644
--- a/cmd/podman/machine/machine_unix.go
+++ b/cmd/podman/machine/machine_unix.go
@@ -1,5 +1,5 @@
-//go:build linux || ignore || aix || ignore || android || ignore || darwin || ignore || freebsd || ignore || hurd || ignore || illumos || ignore || ios || ignore || netbsd || ignore || openbsd || ignore || solaris
-// +build linux ignore aix ignore android ignore darwin ignore freebsd ignore hurd ignore illumos ignore ios ignore netbsd ignore openbsd ignore solaris
+//go:build linux || aix || android || darwin || dragonfly || freebsd || hurd || illumos || ios || netbsd || openbsd || solaris
+// +build linux aix android darwin dragonfly freebsd hurd illumos ios netbsd openbsd solaris
package machine
diff --git a/docs/source/Tutorials.rst b/docs/source/Tutorials.rst
index 34a029484..c2cbcb8a9 100644
--- a/docs/source/Tutorials.rst
+++ b/docs/source/Tutorials.rst
@@ -6,7 +6,8 @@ Here are a number of useful tutorials to get you up and running with Podman. If
* `Basic Setup and Use of Podman <https://github.com/containers/podman/blob/main/docs/tutorials/podman_tutorial.md>`_: Learn how to setup Podman and perform some basic commands with the utility.
* `Basic Setup and Use of Podman in a Rootless environment <https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md>`_: The steps required to setup rootless Podman are enumerated.
-* `Podman Mac/Windows tutorial <https://github.com/containers/podman/blob/main/docs/tutorials/mac_win_client.md>`_: Special setup for running the Podman remote client on a Mac or Windows PC and connecting to Podman running on a Linux VM are documented.
+* `Podman for Windows <https://github.com/containers/podman/blob/main/docs/tutorials/podman-for-windows.md>`_: A guide to installing and using Podman on Windows.
+* `Podman Remote Clients on Mac/Windows <https://github.com/containers/podman/blob/main/docs/tutorials/mac_win_client.md>`_: Advanced setup for connecting to a remote Linux system using the Podman remote client on Mac and Windows.
* `How to sign and distribute container images using Podman <https://github.com/containers/podman/blob/main/docs/tutorials/image_signing.md>`_: Learn how to setup and use image signing with Podman.
* `Podman remote-client tutorial <https://github.com/containers/podman/blob/main/docs/tutorials/remote_client.md>`_: A brief how-to on using the Podman remote-client.
* `How to use libpod for custom/derivative projects <https://github.com/containers/podman/blob/main/docs/tutorials/podman-derivative-api.md>`_: How the libpod API can be used within your own project.
diff --git a/docs/tutorials/mac_win_client.md b/docs/tutorials/mac_win_client.md
index 159296d5e..553a38394 100644
--- a/docs/tutorials/mac_win_client.md
+++ b/docs/tutorials/mac_win_client.md
@@ -1,5 +1,9 @@
# Podman Remote clients for macOS and Windows
+***
+**_NOTE:_** For running Podman on Windows, refer to the [Podman for Windows](podman-for-windows.md) guide, which uses the recommended approach of a Podman-managed Linux backend. For Mac, see the [Podman installation instructions](https://podman.io/getting-started/installation). This guide covers the advanced usage of Podman with a custom Linux VM or a remote external Linux system.
+***
+
## Introduction
The core Podman runtime environment can only run on Linux operating systems. But other operating systems can use the “remote client” to manage their containers to a Linux backend. This remote client is nearly identical to the standard Podman program. Certain functions that do not make sense for remote clients have been removed. For example, the “--latest” switch for container commands has been removed.
diff --git a/go.mod b/go.mod
index 388a20df1..c96cf7473 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/digitalocean/go-qemu v0.0.0-20210326154740-ac9e0b687001
github.com/docker/distribution v2.8.1+incompatible
- github.com/docker/docker v20.10.15+incompatible
+ github.com/docker/docker v20.10.16+incompatible
github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11
github.com/docker/go-plugins-helpers v0.0.0-20211224144127-6eecb7beb651
github.com/docker/go-units v0.4.0
diff --git a/go.sum b/go.sum
index 03ebb4202..722ed26f0 100644
--- a/go.sum
+++ b/go.sum
@@ -431,8 +431,9 @@ github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r
github.com/docker/docker v20.10.3-0.20220208084023-a5c757555091+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.14+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v20.10.15+incompatible h1:dk9FewY/9Xwm4ay/HViEEHSQuM/kL4F+JaG6GQdgmGo=
github.com/docker/docker v20.10.15+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v20.10.16+incompatible h1:2Db6ZR/+FUR3hqPMwnogOPHFn405crbpxvWzKovETOQ=
+github.com/docker/docker v20.10.16+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
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=
diff --git a/hack/parse-localbenchmarks b/hack/parse-localbenchmarks
new file mode 100755
index 000000000..6e22cabbb
--- /dev/null
+++ b/hack/parse-localbenchmarks
@@ -0,0 +1,104 @@
+#!/usr/bin/perl
+#
+# parse-localbenchmarks - convert localbenchmarks output to CSV
+#
+# This is a filter. It transforms data from one format to another. Usage:
+#
+# $ make localbenchmarks &> mylogfile
+# $ hack/parse-localbenchmarks <mylogfile > benchmarks.csv
+#
+# To be more precise, this is a very stupid simpleminded filter. It is
+# not a complete solution to the benchmarks problem. In particular,
+# other tools are still needed to:
+#
+# * Actually _run_ the benchmarks in some standard production environment
+# * Run this script on the results
+# * Save results, with identifying tags (datetime, git hash, PR id, ...)
+# * Compare two or more sets of CSVs
+#
+(our $ME = $0) =~ s|^.*/||; # script name
+
+use v5.14;
+use utf8;
+
+# FIXME: add --help. Some day. Not urgent.
+die "$ME: This is a filter, not an interactive tool\n" if -t *STDIN;
+
+my $n_samples; # Number of timing runs (FIXME: unused)
+my %results; # Timing results
+my @benchmarks; # Names of benchmarks
+my ($type, $testname); # Current context
+
+#
+# Pass 1: read in timings
+#
+while (my $line = <STDIN>) {
+ # Log will have lots of ginkgo output. The only thing we care about is
+ # the summary at the end, which will look something like:
+ #
+ # * [MEASUREMENT]
+ # Podman Benchmark Suite
+ # ....
+ # Ran 3 samples:
+ # [CPU] podman images:
+ # Fastest Time: 0.265s
+ # Slowest Time: 0.322s
+ # Average Time: 0.302s ± 0.018s
+ # [MEM] podman images:
+ # Smallest: 44076.0KB
+ # Largest: 44616.0KB
+ # Average: 44338.7KB ± 171.2KB
+ # [CPU] podman push:
+ # ....repeat [CPU] and [MEM] for each test
+ # --------------------------
+ # SSSSSSSSSSSSSSSSSSSSS (and more ginkgo output we don't care about)
+ #
+ chomp $line;
+ next unless $line =~ /^.{1,3}\s+\[MEASUREMENT\]/ .. $line =~ /^-{20,}$/;
+
+ # Trim leading & trailing whitespace
+ $line =~ s/(^\s+|\s+$)//g;
+
+ # FIXME: we don't actually emit this. What would be a good way to do so?
+ if ($line =~ /^Ran\s+(\d+)\s+samples/) {
+ $n_samples = $1;
+ }
+
+ # e.g., [CPU] podman foo:
+ elsif ($line =~ /^\[([A-Z]+)\]\s+(\S.*\S):$/) {
+ ($type, $testname) = ($1, $2);
+ }
+
+ # e.g., 'Fastest Time: 0.265s'
+ elsif ($line =~ /^(\S.*?\S):\s+(.*)/) {
+ my $benchmark = "$type $1";
+ $results{$testname}{$benchmark} = $2;
+
+ # Keep an ordered list of benchmark names (as in, the order we
+ # encounter them)
+ push @benchmarks, $benchmark
+ unless grep { $_ eq $benchmark } @benchmarks;
+ }
+
+ else {
+ warn "Cannot grok '$line'\n" if $ENV{DEBUG_PARSELOCALBENCHMARKS};
+ }
+}
+
+#
+# Pass 2: write out CSV
+#
+
+# Headings...
+print "\"Test Name\"";
+printf ", \"%s\"", $_ for @benchmarks;
+print "\n";
+
+# ...then data
+for my $t (sort keys %results) {
+ printf "\"%s\"", $t;
+ for my $benchmark (@benchmarks) {
+ printf ", \"%s\"", $results{$t}{$benchmark} || '';
+ }
+ print "\n";
+}
diff --git a/libpod/info.go b/libpod/info.go
index 321680a81..bc49a6cc9 100644
--- a/libpod/info.go
+++ b/libpod/info.go
@@ -406,26 +406,25 @@ func getCPUUtilization() (*define.CPUUsage, error) {
}
defer f.Close()
scanner := bufio.NewScanner(f)
- // Read firt line of /proc/stat
+ // Read first line of /proc/stat that has entries for system ("cpu" line)
for scanner.Scan() {
break
}
// column 1 is user, column 3 is system, column 4 is idle
- stats := strings.Split(scanner.Text(), " ")
+ stats := strings.Fields(scanner.Text())
return statToPercent(stats)
}
func statToPercent(stats []string) (*define.CPUUsage, error) {
- // There is always an extra space between cpu and the first metric
- userTotal, err := strconv.ParseFloat(stats[2], 64)
+ userTotal, err := strconv.ParseFloat(stats[1], 64)
if err != nil {
return nil, errors.Wrapf(err, "unable to parse user value %q", stats[1])
}
- systemTotal, err := strconv.ParseFloat(stats[4], 64)
+ systemTotal, err := strconv.ParseFloat(stats[3], 64)
if err != nil {
return nil, errors.Wrapf(err, "unable to parse system value %q", stats[3])
}
- idleTotal, err := strconv.ParseFloat(stats[5], 64)
+ idleTotal, err := strconv.ParseFloat(stats[4], 64)
if err != nil {
return nil, errors.Wrapf(err, "unable to parse idle value %q", stats[4])
}
diff --git a/libpod/info_test.go b/libpod/info_test.go
index 909b573c0..b0e4bf8c0 100644
--- a/libpod/info_test.go
+++ b/libpod/info_test.go
@@ -20,7 +20,7 @@ func Test_statToPercent(t *testing.T) {
}{
{
name: "GoodParse",
- args: args{in0: []string{"cpu", " ", "33628064", "27537", "9696996", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
+ args: args{in0: []string{"cpu", "33628064", "27537", "9696996", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
want: &define.CPUUsage{
UserPercent: 2.48,
SystemPercent: 0.71,
@@ -30,19 +30,19 @@ func Test_statToPercent(t *testing.T) {
},
{
name: "BadUserValue",
- args: args{in0: []string{"cpu", " ", "k", "27537", "9696996", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
+ args: args{in0: []string{"cpu", "k", "27537", "9696996", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
want: nil,
wantErr: assert.Error,
},
{
name: "BadSystemValue",
- args: args{in0: []string{"cpu", " ", "33628064", "27537", "k", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
+ args: args{in0: []string{"cpu", "33628064", "27537", "k", "1314806705", "588142", "4775073", "2789228", "0", "598711", "0"}},
want: nil,
wantErr: assert.Error,
},
{
name: "BadIdleValue",
- args: args{in0: []string{"cpu", " ", "33628064", "27537", "9696996", "k", "588142", "4775073", "2789228", "0", "598711", "0"}},
+ args: args{in0: []string{"cpu", "33628064", "27537", "9696996", "k", "588142", "4775073", "2789228", "0", "598711", "0"}},
want: nil,
wantErr: assert.Error,
},
diff --git a/libpod/runtime.go b/libpod/runtime.go
index f4cd9cf00..58f20ef5b 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -349,7 +349,7 @@ func makeRuntime(runtime *Runtime) (retErr error) {
// it will try to use existing XDG_RUNTIME_DIR
// if current user has no write access to XDG_RUNTIME_DIR we will fail later
if err := unix.Access(runtime.storageConfig.RunRoot, unix.W_OK); err != nil {
- msg := "XDG_RUNTIME_DIR is pointing to a path which is not writable. Most likely podman will fail."
+ msg := fmt.Sprintf("RunRoot is pointing to a path (%s) which is not writable. Most likely podman will fail.", runtime.storageConfig.RunRoot)
if errors.Is(err, os.ErrNotExist) {
// if dir does not exists try to create it
if err := os.MkdirAll(runtime.storageConfig.RunRoot, 0700); err != nil {
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index df7174ac6..7e8a21a8c 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -732,7 +732,11 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
// after setting the state to ContainerStateRemoving will prevent that the container is
// restarted
if err := c.removeAllExecSessions(); err != nil {
- return err
+ if cleanupErr == nil {
+ cleanupErr = err
+ } else {
+ logrus.Errorf("Remove exec sessions: %v", err)
+ }
}
// Stop the container's storage
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index f0d07f492..318688222 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -119,6 +119,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
Registry string `schema:"registry"`
Rm bool `schema:"rm"`
RusageLogFile string `schema:"rusagelogfile"`
+ Remote string `schema:"remote"`
Seccomp string `schema:"seccomp"`
Secrets string `schema:"secrets"`
SecurityOpt string `schema:"securityopt"`
@@ -169,14 +170,50 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
// convert addcaps formats
containerFiles := []string{}
- if _, found := r.URL.Query()["dockerfile"]; found {
- var m = []string{}
- if err := json.Unmarshal([]byte(query.Dockerfile), &m); err != nil {
- // it's not json, assume just a string
- m = []string{filepath.Join(contextDirectory, query.Dockerfile)}
+ // Tells if query paramemter `dockerfile` is set or not.
+ dockerFileSet := false
+ if utils.IsLibpodRequest(r) && query.Remote != "" {
+ // The context directory could be a URL. Try to handle that.
+ anchorDir, err := ioutil.TempDir(parse.GetTempDir(), "libpod_builder")
+ if err != nil {
+ utils.InternalServerError(w, err)
+ }
+ tempDir, subDir, err := buildahDefine.TempDirForURL(anchorDir, "buildah", query.Remote)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ }
+ if tempDir != "" {
+ // We had to download it to a temporary directory.
+ // Delete it later.
+ defer func() {
+ if err = os.RemoveAll(tempDir); err != nil {
+ // We are deleting this on server so log on server end
+ // client does not have to worry about server cleanup.
+ logrus.Errorf("Cannot delete downloaded temp dir %q: %s", tempDir, err)
+ }
+ }()
+ contextDirectory = filepath.Join(tempDir, subDir)
+ } else {
+ // Nope, it was local. Use it as is.
+ absDir, err := filepath.Abs(query.Remote)
+ if err != nil {
+ utils.BadRequest(w, "remote", query.Remote, err)
+ }
+ contextDirectory = absDir
}
- containerFiles = m
} else {
+ if _, found := r.URL.Query()["dockerfile"]; found {
+ var m = []string{}
+ if err := json.Unmarshal([]byte(query.Dockerfile), &m); err != nil {
+ // it's not json, assume just a string
+ m = []string{filepath.Join(contextDirectory, query.Dockerfile)}
+ }
+ containerFiles = m
+ dockerFileSet = true
+ }
+ }
+
+ if !dockerFileSet {
containerFiles = []string{filepath.Join(contextDirectory, "Dockerfile")}
if utils.IsLibpodRequest(r) {
containerFiles = []string{filepath.Join(contextDirectory, "Containerfile")}
diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go
index 57fb36fc9..0b2874baf 100644
--- a/pkg/machine/wsl/machine.go
+++ b/pkg/machine/wsl/machine.go
@@ -36,6 +36,7 @@ var (
const (
ErrorSuccessRebootInitiated = 1641
ErrorSuccessRebootRequired = 3010
+ currentMachineVersion = 2
)
const containersConf = `[containers]
@@ -168,6 +169,8 @@ type MachineVM struct {
Rootful bool
// SSH identity, username, etc
machine.SSHConfig
+ // machine version
+ Version int
}
type ExitCodeError struct {
@@ -241,12 +244,29 @@ func readAndMigrate(configPath string, name string) (*MachineVM, error) {
return vm, err
}
err = json.Unmarshal(b, vm)
- if err == nil && vm.Created.IsZero() {
- err = vm.migrate40(configPath)
+ if err == nil && vm.Version < currentMachineVersion {
+ err = vm.migrateMachine(configPath)
}
+
return vm, err
}
+func (v *MachineVM) migrateMachine(configPath string) error {
+ if v.Created.IsZero() {
+ if err := v.migrate40(configPath); err != nil {
+ return err
+ }
+ }
+
+ // Update older machines to use lingering
+ if err := enableUserLinger(v, toDist(v.Name)); err != nil {
+ return err
+ }
+
+ v.Version = currentMachineVersion
+ return v.writeConfig()
+}
+
func (v *MachineVM) migrate40(configPath string) error {
v.ConfigPath = configPath
fi, err := os.Stat(configPath)
@@ -255,7 +275,7 @@ func (v *MachineVM) migrate40(configPath string) error {
}
v.Created = fi.ModTime()
v.LastUp = getLegacyLastStart(v)
- return v.writeConfig()
+ return nil
}
func getLegacyLastStart(vm *MachineVM) time.Time {
@@ -284,6 +304,7 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
sshDir := filepath.Join(homeDir, ".ssh")
v.IdentityPath = filepath.Join(sshDir, v.Name)
v.Rootful = opts.Rootful
+ v.Version = currentMachineVersion
if err := downloadDistro(v, opts); err != nil {
return false, err
@@ -486,6 +507,10 @@ func configureSystem(v *MachineVM, dist string) error {
return errors.Wrap(err, "could not generate linger service for guest OS")
}
+ if err := enableUserLinger(v, dist); err != nil {
+ return err
+ }
+
if err := pipeCmdPassThrough("wsl", withUser(lingerSetup, user), "-d", dist, "sh"); err != nil {
return errors.Wrap(err, "could not configure systemd settomgs for guest OS")
}
@@ -501,6 +526,15 @@ func configureSystem(v *MachineVM, dist string) error {
return nil
}
+func enableUserLinger(v *MachineVM, dist string) error {
+ lingerCmd := "mkdir -p /var/lib/systemd/linger; touch /var/lib/systemd/linger/" + v.RemoteUsername
+ if err := runCmdPassThrough("wsl", "-d", dist, "sh", "-c", lingerCmd); err != nil {
+ return errors.Wrap(err, "could not enable linger for remote user on guest OS")
+ }
+
+ return nil
+}
+
func installScripts(dist string) error {
if err := pipeCmdPassThrough("wsl", enterns, "-d", dist, "sh", "-c",
"cat > /usr/local/bin/enterns; chmod 755 /usr/local/bin/enterns"); err != nil {
diff --git a/pkg/specgen/generate/pause_image.go b/pkg/specgen/generate/pause_image.go
index 4aba230a3..ddf35f230 100644
--- a/pkg/specgen/generate/pause_image.go
+++ b/pkg/specgen/generate/pause_image.go
@@ -80,6 +80,12 @@ ENTRYPOINT ["/catatonit", "-P"]`, catatonitPath)
Quiet: true,
IgnoreFile: "/dev/null", // makes sure to not read a local .ignorefile (see #13529)
IIDFile: "/dev/null", // prevents Buildah from writing the ID on stdout
+ IDMappingOptions: &buildahDefine.IDMappingOptions{
+ // Use the host UID/GID mappings for the build to avoid issues when
+ // running with a custom mapping (BZ #2083997).
+ HostUIDMapping: true,
+ HostGIDMapping: true,
+ },
}
if _, _, err := rt.Build(context.Background(), buildOptions, tmpF.Name()); err != nil {
return "", err
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index 9526183e3..a994f8e11 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -190,6 +190,10 @@ t POST "libpod/build?dockerfile=containerfile" $CONTAINERFILE_TAR application/js
t POST "build?dockerfile=containerfile" $CONTAINERFILE_TAR application/json 200 \
.stream~"STEP 1/1: FROM $IMAGE"
+# Libpod: allow building from url: https://github.com/alpinelinux/docker-alpine.git and must ignore any provided tar
+t POST "libpod/build?remote=https%3A%2F%2Fgithub.com%2Falpinelinux%2Fdocker-alpine.git" $CONTAINERFILE_TAR 200 \
+ .stream~"STEP 1/5: FROM alpine:3.14"
+
# Build api response header must contain Content-type: application/json
t POST "build?dockerfile=containerfile" $CONTAINERFILE_TAR application/json 200
response_headers=$(cat "$WORKDIR/curl.headers.out")
diff --git a/test/system/170-run-userns.bats b/test/system/170-run-userns.bats
index d754306b2..b80351902 100644
--- a/test/system/170-run-userns.bats
+++ b/test/system/170-run-userns.bats
@@ -36,6 +36,19 @@ function _require_crun() {
is "$output" ".*457" "Check group leaked into container"
}
+@test "rootful pod with custom ID mapping" {
+ skip_if_rootless "does not work rootless - rootful feature"
+ skip_if_remote "remote --uidmap is broken (see #14233)"
+ random_pod_name=$(random_string 30)
+ run_podman pod create --uidmap 0:200000:5000 --name=$random_pod_name
+ run_podman pod start $random_pod_name
+
+ # Remove the pod and the pause image
+ run_podman pod rm $random_pod_name
+ run_podman version --format "{{.Server.Version}}-{{.Server.Built}}"
+ run_podman rmi -f localhost/podman-pause:$output
+}
+
@test "podman --remote --group-add keep-groups " {
if is_remote; then
run_podman 125 run --rm --group-add keep-groups $IMAGE id
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 0576d8f20..c73f11330 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -328,7 +328,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.15+incompatible
+# github.com/docker/docker v20.10.16+incompatible
## explicit
github.com/docker/docker/api
github.com/docker/docker/api/types