summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml8
-rw-r--r--.copr/prepare.sh2
-rwxr-xr-x.tool/lint1
-rw-r--r--CONTRIBUTING.md3
-rw-r--r--Dockerfile8
-rw-r--r--Dockerfile.centos8
-rw-r--r--Dockerfile.fedora8
-rw-r--r--README.md2
-rw-r--r--RELEASE_NOTES.md1
-rw-r--r--contrib/spec/podman.spec.in2
-rw-r--r--docs/podman-create.1.md1
-rw-r--r--docs/podman-run.1.md1
-rw-r--r--libpod/container.go4
-rw-r--r--libpod/container_inspect.go180
-rw-r--r--libpod/options.go2
-rw-r--r--libpod/pod.go6
-rw-r--r--libpod/volume.go1
-rw-r--r--pkg/spec/storage.go11
-rw-r--r--pkg/util/mountOpts.go15
-rw-r--r--test/e2e/run_test.go8
20 files changed, 200 insertions, 72 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 4344b6b0a..848dc2b6d 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -31,9 +31,9 @@ env:
####
#### Cache-image names to test with
###
- FEDORA_CACHE_IMAGE_NAME: "fedora-29-libpod-5157899144265728"
- PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-28-libpod-5157899144265728"
- UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-libpod-5157899144265728"
+ FEDORA_CACHE_IMAGE_NAME: "fedora-29-libpod-4844850202017792"
+ PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-28-libpod-4844850202017792"
+ UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-libpod-4844850202017792"
####
#### Variables for composing new cache-images (used in PR testing) from
@@ -43,7 +43,7 @@ env:
# Git commits to use while building dependencies into cache-images
FEDORA_CNI_COMMIT: "412b6d31280682bb4fab4446f113c22ff1886554"
CNI_COMMIT: "7480240de9749f9a0a5c8614b17f1f03e0c06ab9"
- CONMON_COMMIT: "f02c053eb37010fc76d1e2966de7f2cb9f969ef2"
+ CONMON_COMMIT: "8455ce1ef385120deb827d0f0588c04357bad4c4"
CRIU_COMMIT: "c74b83cd49c00589c0c0468ba5fe685b67fdbd0a"
# Special image w/ nested-libvirt + tools for creating new cache and base images
IMAGE_BUILDER_CACHE_IMAGE_NAME: "image-builder-image-1541772081"
diff --git a/.copr/prepare.sh b/.copr/prepare.sh
index 57c380b02..d7c5083ca 100644
--- a/.copr/prepare.sh
+++ b/.copr/prepare.sh
@@ -29,4 +29,4 @@ fi
mkdir build/
git archive --prefix "libpod-${COMMIT_SHORT}/" --format "tar.gz" HEAD -o "build/libpod-${COMMIT_SHORT}.tar.gz"
git clone https://github.com/containers/conmon
-cd conmon && git checkout 59952292a3b07ac125575024ae21956efe0ecdfb && git archive --prefix "conmon/" --format "tar.gz" HEAD -o "../build/conmon.tar.gz"
+cd conmon && git checkout 8455ce1ef385120deb827d0f0588c04357bad4c4 && git archive --prefix "conmon/" --format "tar.gz" HEAD -o "../build/conmon.tar.gz"
diff --git a/.tool/lint b/.tool/lint
index 01f44311d..67dfd4b28 100755
--- a/.tool/lint
+++ b/.tool/lint
@@ -39,7 +39,6 @@ ${LINTER} \
--exclude='.*_test\.go:.*error return value not checked.*\(errcheck\)$'\
--exclude='duplicate of.*_test.go.*\(dupl\)$'\
--exclude='cmd\/client\/.*\.go.*\(dupl\)$'\
- --exclude='libpod\/.*_easyjson.go:.*'\
--exclude='vendor\/.*'\
--exclude='podman\/.*'\
--exclude='server\/seccomp\/.*\.go.*$'\
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 87efdeb8f..8b7544ba0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -350,6 +350,9 @@ and
[PRs](https://github.com/containers/libpod/pulls)
tracking system.
+There is also a [mailing list](https://lists.podman.io/archives/) at `lists.podman.io`.
+You can subscribe by sending a message to `podman@lists.podman.io` with the subject `subscribe`.
+
[owners]: https://github.com/kubernetes/community/blob/master/contributors/guide/owners.md#owners
diff --git a/Dockerfile b/Dockerfile
index d729c00dc..214fbeb34 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -56,7 +56,7 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Install conmon
-ENV CONMON_COMMIT 59952292a3b07ac125575024ae21956efe0ecdfb
+ENV CONMON_COMMIT 8455ce1ef385120deb827d0f0588c04357bad4c4
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/containers/conmon.git "$GOPATH/src/github.com/containers/conmon.git" \
@@ -90,12 +90,6 @@ RUN set -x \
&& export GOPATH=/go \
&& go get github.com/onsi/gomega/...
-# Install easyjson
-RUN set -x \
- && export GOPATH=/go \
- && go get -u github.com/mailru/easyjson/... \
- && install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/
-
# Install latest stable criu version
RUN set -x \
&& cd /tmp \
diff --git a/Dockerfile.centos b/Dockerfile.centos
index c1d93d5d3..72b926bff 100644
--- a/Dockerfile.centos
+++ b/Dockerfile.centos
@@ -49,14 +49,8 @@ RUN set -x \
&& export GOPATH=/go \
&& go get github.com/onsi/gomega/...
-# Install easyjson
-RUN set -x \
- && export GOPATH=/go \
- && go get -u github.com/mailru/easyjson/... \
- && install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/
-
# Install conmon
-ENV CONMON_COMMIT 59952292a3b07ac125575024ae21956efe0ecdfb
+ENV CONMON_COMMIT 8455ce1ef385120deb827d0f0588c04357bad4c4
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/containers/conmon.git "$GOPATH/src/github.com/containers/conmon.git" \
diff --git a/Dockerfile.fedora b/Dockerfile.fedora
index d7c2d07e1..c34d4bb16 100644
--- a/Dockerfile.fedora
+++ b/Dockerfile.fedora
@@ -53,14 +53,8 @@ RUN set -x \
&& export GOPATH=/go \
&& go get github.com/onsi/gomega/...
-# Install easyjson
-RUN set -x \
- && export GOPATH=/go \
- && go get -u github.com/mailru/easyjson/... \
- && install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/
-
# Install conmon
-ENV CONMON_COMMIT 59952292a3b07ac125575024ae21956efe0ecdfb
+ENV CONMON_COMMIT 8455ce1ef385120deb827d0f0588c04357bad4c4
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/containers/conmon.git "$GOPATH/src/github.com/containers/conmon.git" \
diff --git a/README.md b/README.md
index 64af6a120..f25560d78 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
Libpod provides a library for applications looking to use the Container Pod concept,
popularized by Kubernetes. Libpod also contains the Pod Manager tool `(Podman)`. Podman manages pods, containers, container images, and container volumes.
-* [Latest Version: 1.3.1](https://github.com/containers/libpod/releases/latest)
+* [Latest Version: 1.4.0](https://github.com/containers/libpod/releases/latest)
* [Continuous Integration:](contrib/cirrus/README.md) [![Build Status](https://api.cirrus-ci.com/github/containers/libpod.svg)](https://cirrus-ci.com/github/containers/libpod/master)
## Overview and scope
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index e36757edc..fbb6a78b0 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -22,6 +22,7 @@
- Fixed a bug where `podman exec` would fail on older kernels ([#2968](https://github.com/containers/libpod/issues/2968))
### Misc
+- The `podman inspect` command on containers now uses the `Id` key (instead of `ID`) for the container's ID, for better compatability with the output of `docker inspect`
- The `podman commit` command is now usable with the Podman remote client
- The `--signature-policy` flag (used with several image-related commands) has been deprecated
- The `podman unshare` command now defines two environment variables in the spawned shell: `CONTAINERS_RUNROOT` and `CONTAINERS_GRAPHROOT`, pointing to temporary and permanent storage for rootless containers
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index 8c2ccd4b0..d755fd1aa 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -35,7 +35,7 @@
# People want conmon packaged with the copr rpm
%global import_path_conmon github.com/containers/conmon
%global git_conmon https://%{import_path_conmon}
-%global commit_conmon 59952292a3b07ac125575024ae21956efe0ecdfb
+%global commit_conmon 8455ce1ef385120deb827d0f0588c04357bad4c4
%global shortcommit_conmon %(c=%{commit_conmon}; echo ${c:0:7})
Name: podman
diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md
index 88f8fe8c7..a4eebef4c 100644
--- a/docs/podman-create.1.md
+++ b/docs/podman-create.1.md
@@ -458,6 +458,7 @@ Current supported mount TYPES are bind, and tmpfs.
Options specific to bind:
· bind-propagation: shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2).
+ . bind-nonrecursive: do not setup a recursive bind mount. By default it is recursive.
Options specific to tmpfs:
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index 5bf7aeee8..8d7deb99f 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -471,6 +471,7 @@ Current supported mount TYPES are bind, and tmpfs.
Options specific to bind:
· bind-propagation: Z, z, shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2).
+ . bind-nonrecursive: do not setup a recursive bind mount. By default it is recursive.
Options specific to tmpfs:
diff --git a/libpod/container.go b/libpod/container.go
index c8ab42fc3..68c4cd6b0 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -135,7 +135,6 @@ const (
// assume that their callers handled this requirement. Generally speaking, if a
// function takes the container lock and accesses any part of state, it should
// syncContainer() immediately after locking.
-// ffjson: skip
type Container struct {
config *ContainerConfig
@@ -161,7 +160,6 @@ type Container struct {
// ContainerState contains the current state of the container
// It is stored on disk in a tmpfs and recreated on reboot
-// easyjson:json
type ContainerState struct {
// The current state of the running container
State ContainerStatus `json:"state"`
@@ -222,7 +220,6 @@ type ContainerState struct {
}
// ExecSession contains information on an active exec session
-// easyjson:json
type ExecSession struct {
ID string `json:"id"`
Command []string `json:"command"`
@@ -232,7 +229,6 @@ type ExecSession struct {
// ContainerConfig contains all information that was used to create the
// container. It may not be changed once created.
// It is stored, read-only, on disk
-// easyjson:json
type ContainerConfig struct {
Spec *spec.Spec `json:"spec"`
ID string `json:"id"`
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 8e34e7088..0a62ceb7c 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -1,12 +1,11 @@
package libpod
import (
- "strings"
"time"
"github.com/containers/libpod/libpod/driver"
"github.com/cri-o/ocicni/pkg/ocicni"
- specs "github.com/opencontainers/runtime-spec/specs-go"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -29,6 +28,7 @@ type InspectContainerData struct {
HostnamePath string `json:"HostnamePath"`
HostsPath string `json:"HostsPath"`
StaticDir string `json:"StaticDir"`
+ OCIConfigPath string `json:"OCIConfigPath,omitempty"`
LogPath string `json:"LogPath"`
ConmonPidFile string `json:"ConmonPidFile"`
Name string `json:"Name"`
@@ -43,7 +43,7 @@ type InspectContainerData struct {
GraphDriver *driver.Data `json:"GraphDriver"`
SizeRw int64 `json:"SizeRw,omitempty"`
SizeRootFs int64 `json:"SizeRootFs,omitempty"`
- Mounts []specs.Mount `json:"Mounts"`
+ Mounts []*InspectMount `json:"Mounts"`
Dependencies []string `json:"Dependencies"`
NetworkSettings *InspectNetworkSettings `json:"NetworkSettings"` //TODO
ExitCommand []string `json:"ExitCommand"`
@@ -51,6 +51,35 @@ type InspectContainerData struct {
IsInfra bool `json:"IsInfra"`
}
+// InspectMount provides a record of a single mount in a container. It contains
+// fields for both named and normal volumes. Only user-specified volumes will be
+// included, and tmpfs volumes are not included even if the user specified them.
+type InspectMount struct {
+ // Whether the mount is a volume or bind mount. Allowed values are
+ // "volume" and "bind".
+ Type string `json:"Type"`
+ // The name of the volume. Empty for bind mounts.
+ Name string `json:"Name,omptempty"`
+ // The source directory for the volume.
+ Src string `json:"Source"`
+ // The destination directory for the volume. Specified as a path within
+ // the container, as it would be passed into the OCI runtime.
+ Dst string `json:"Destination"`
+ // The driver used for the named volume. Empty for bind mounts.
+ Driver string `json:"Driver"`
+ // Contains SELinux :z/:Z mount options. Unclear what, if anything, else
+ // goes in here.
+ Mode string `json:"Mode"`
+ // All remaining mount options. Additional data, not present in the
+ // original output.
+ Options []string `json:"Options"`
+ // Whether the volume is read-write
+ RW bool `json:"RW"`
+ // Mount propagation for the mount. Can be empty if not specified, but
+ // is always printed - no omitempty.
+ Propagation string `json:"Propagation"`
+}
+
// InspectContainerState provides a detailed record of a container's current
// state. It is returned as part of InspectContainerData.
// As with InspectContainerData, many portions of this struct are matched to
@@ -148,34 +177,24 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
execIDs = append(execIDs, id)
}
- if c.state.BindMounts == nil {
- c.state.BindMounts = make(map[string]string)
- }
-
resolvPath := ""
- if getPath, ok := c.state.BindMounts["/etc/resolv.conf"]; ok {
- resolvPath = getPath
- }
-
hostsPath := ""
- if getPath, ok := c.state.BindMounts["/etc/hosts"]; ok {
- hostsPath = getPath
- }
-
hostnamePath := ""
- if getPath, ok := c.state.BindMounts["/etc/hostname"]; ok {
- hostnamePath = getPath
+ if c.state.BindMounts != nil {
+ if getPath, ok := c.state.BindMounts["/etc/resolv.conf"]; ok {
+ resolvPath = getPath
+ }
+ if getPath, ok := c.state.BindMounts["/etc/hosts"]; ok {
+ hostsPath = getPath
+ }
+ if getPath, ok := c.state.BindMounts["/etc/hostname"]; ok {
+ hostnamePath = getPath
+ }
}
- var mounts []specs.Mount
- for i, mnt := range spec.Mounts {
- mounts = append(mounts, mnt)
- // We only want to show the name of the named volume in the inspect
- // output, so split the path and get the name out of it.
- if strings.Contains(mnt.Source, c.runtime.config.VolumePath) {
- split := strings.Split(mnt.Source[len(c.runtime.config.VolumePath)+1:], "/")
- mounts[i].Source = split[0]
- }
+ mounts, err := c.getInspectMounts()
+ if err != nil {
+ return nil, err
}
data := &InspectContainerData{
@@ -242,8 +261,12 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
IsInfra: c.IsInfra(),
}
+ if c.state.ConfigPath != "" {
+ data.OCIConfigPath = c.state.ConfigPath
+ }
+
if c.config.HealthCheckConfig != nil {
- // This container has a healthcheck defined in it; we need to add it's state
+ // This container has a healthcheck defined in it; we need to add it's state
healthCheckState, err := c.GetHealthCheckLog()
if err != nil {
// An error here is not considered fatal; no health state will be displayed
@@ -275,3 +298,106 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
}
return data, nil
}
+
+// Get inspect-formatted mounts list.
+// Only includes user-specified mounts. Only includes bind mounts and named
+// volumes, not tmpfs volumes.
+func (c *Container) getInspectMounts() ([]*InspectMount, error) {
+ inspectMounts := []*InspectMount{}
+
+ // No mounts, return early
+ if len(c.config.UserVolumes) == 0 {
+ return inspectMounts, nil
+ }
+
+ // We need to parse all named volumes and mounts into maps, so we don't
+ // end up with repeated lookups for each user volume.
+ // Map destination to struct, as destination is what is stored in
+ // UserVolumes.
+ namedVolumes := make(map[string]*ContainerNamedVolume)
+ mounts := make(map[string]spec.Mount)
+ for _, namedVol := range c.config.NamedVolumes {
+ namedVolumes[namedVol.Dest] = namedVol
+ }
+ for _, mount := range c.config.Spec.Mounts {
+ mounts[mount.Destination] = mount
+ }
+
+ for _, vol := range c.config.UserVolumes {
+ // We need to look up the volumes.
+ // First: is it a named volume?
+ if volume, ok := namedVolumes[vol]; ok {
+ mountStruct := new(InspectMount)
+ mountStruct.Type = "volume"
+ mountStruct.Dst = volume.Dest
+ mountStruct.Name = volume.Name
+
+ // For src and driver, we need to look up the named
+ // volume.
+ volFromDB, err := c.runtime.state.Volume(volume.Name)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error looking up volume %s in container %s config", volume.Name, c.ID())
+ }
+ mountStruct.Driver = volFromDB.Driver()
+ mountStruct.Src = volFromDB.MountPoint()
+
+ parseMountOptionsForInspect(volume.Options, mountStruct)
+
+ inspectMounts = append(inspectMounts, mountStruct)
+ } else if mount, ok := mounts[vol]; ok {
+ // It's a mount.
+ // Is it a tmpfs? If so, discard.
+ if mount.Type == "tmpfs" {
+ continue
+ }
+
+ mountStruct := new(InspectMount)
+ mountStruct.Type = "bind"
+ mountStruct.Src = mount.Source
+ mountStruct.Dst = mount.Destination
+
+ parseMountOptionsForInspect(mount.Options, mountStruct)
+
+ inspectMounts = append(inspectMounts, mountStruct)
+ }
+ // We couldn't find a mount. Log a warning.
+ logrus.Warnf("Could not find mount at destination %q when building inspect output for container %s", vol, c.ID())
+ }
+
+ return inspectMounts, nil
+}
+
+// Parse mount options so we can populate them in the mount structure.
+// The mount passed in will be modified.
+func parseMountOptionsForInspect(options []string, mount *InspectMount) {
+ isRW := true
+ mountProp := ""
+ zZ := ""
+ otherOpts := []string{}
+
+ // Some of these may be overwritten if the user passes us garbage opts
+ // (for example, [ro,rw])
+ // We catch these on the Podman side, so not a problem there, but other
+ // users of libpod who do not properly validate mount options may see
+ // this.
+ // Not really worth dealing with on our end - garbage in, garbage out.
+ for _, opt := range options {
+ switch opt {
+ case "ro":
+ isRW = false
+ case "rw":
+ // Do nothing, silently discard
+ case "shared", "slave", "private", "rshared", "rslave", "rprivate":
+ mountProp = opt
+ case "z", "Z":
+ zZ = opt
+ default:
+ otherOpts = append(otherOpts, opt)
+ }
+ }
+
+ mount.RW = isRW
+ mount.Propagation = mountProp
+ mount.Mode = zZ
+ mount.Options = otherOpts
+}
diff --git a/libpod/options.go b/libpod/options.go
index 20aa51981..cdac09654 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1127,6 +1127,8 @@ func WithGroups(groups []string) CtrCreateOption {
// These are not added to the container's spec, but will instead be used during
// commit to populate the volumes of the new image, and to trigger some OCI
// hooks that are only added if volume mounts are present.
+// Furthermore, they are used in the output of inspect, to filter volumes -
+// only volumes included in this list will be included in the output.
// Unless explicitly set, committed images will have no volumes.
// The given volumes slice must not be nil.
func WithUserVolumes(volumes []string) CtrCreateOption {
diff --git a/libpod/pod.go b/libpod/pod.go
index 4ce697402..c319c449f 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -18,7 +18,6 @@ import (
// assume their callers handled this requirement. Generally speaking, if a
// function takes the pod lock and accesses any part of state, it should
// updatePod() immediately after locking.
-// ffjson: skip
// Pod represents a group of containers that may share namespaces
type Pod struct {
config *PodConfig
@@ -30,7 +29,6 @@ type Pod struct {
}
// PodConfig represents a pod's static configuration
-// easyjson:json
type PodConfig struct {
ID string `json:"id"`
Name string `json:"name"`
@@ -66,7 +64,6 @@ type PodConfig struct {
}
// podState represents a pod's state
-// easyjson:json
type podState struct {
// CgroupPath is the path to the pod's CGroup
CgroupPath string `json:"cgroupPath"`
@@ -77,7 +74,6 @@ type podState struct {
// PodInspect represents the data we want to display for
// podman pod inspect
-// easyjson:json
type PodInspect struct {
Config *PodConfig
State *PodInspectState
@@ -85,14 +81,12 @@ type PodInspect struct {
}
// PodInspectState contains inspect data on the pod's state
-// easyjson:json
type PodInspectState struct {
CgroupPath string `json:"cgroupPath"`
InfraContainerID string `json:"infraContainerID"`
}
// PodContainerInfo keeps information on a container in a pod
-// easyjson:json
type PodContainerInfo struct {
ID string `json:"id"`
State string `json:"state"`
diff --git a/libpod/volume.go b/libpod/volume.go
index 0b37d44ef..9ed2ff087 100644
--- a/libpod/volume.go
+++ b/libpod/volume.go
@@ -10,7 +10,6 @@ type Volume struct {
}
// VolumeConfig holds the volume's config information
-//easyjson:json
type VolumeConfig struct {
// Name of the volume
Name string `json:"name"`
diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go
index e221b5cb5..283585ef8 100644
--- a/pkg/spec/storage.go
+++ b/pkg/spec/storage.go
@@ -384,7 +384,7 @@ func (config *CreateConfig) getMounts() (map[string]spec.Mount, map[string]*libp
}
finalNamedVolumes[volume.Dest] = volume
default:
- return nil, nil, errors.Errorf("invalid fylesystem type %q", kv[1])
+ return nil, nil, errors.Errorf("invalid filesystem type %q", kv[1])
}
}
@@ -403,6 +403,8 @@ func getBindMount(args []string) (spec.Mount, error) {
for _, val := range args {
kv := strings.Split(val, "=")
switch kv[0] {
+ case "bind-nonrecursive":
+ newMount.Options = append(newMount.Options, "bind")
case "ro", "nosuid", "nodev", "noexec":
// TODO: detect duplication of these options.
// (Is this necessary?)
@@ -574,7 +576,7 @@ func ValidateVolumeCtrDir(ctrDir string) error {
// ValidateVolumeOpts validates a volume's options
func ValidateVolumeOpts(options []string) error {
- var foundRootPropagation, foundRWRO, foundLabelChange int
+ var foundRootPropagation, foundRWRO, foundLabelChange, bindType int
for _, opt := range options {
switch opt {
case "rw", "ro":
@@ -592,6 +594,11 @@ func ValidateVolumeOpts(options []string) error {
if foundRootPropagation > 1 {
return errors.Errorf("invalid options %q, can only specify 1 '[r]shared', '[r]private' or '[r]slave' option", strings.Join(options, ", "))
}
+ case "bind", "rbind":
+ bindType++
+ if bindType > 1 {
+ return errors.Errorf("invalid options %q, can only specify 1 '[r]bind' option", strings.Join(options, ", "))
+ }
default:
return errors.Errorf("invalid option type %q", opt)
}
diff --git a/pkg/util/mountOpts.go b/pkg/util/mountOpts.go
index 59459807c..489e7eeef 100644
--- a/pkg/util/mountOpts.go
+++ b/pkg/util/mountOpts.go
@@ -17,10 +17,19 @@ var (
// sensible and follow convention.
func ProcessOptions(options []string) []string {
var (
- foundrw, foundro bool
- rootProp string
+ foundbind, foundrw, foundro bool
+ rootProp string
)
- options = append(options, "rbind")
+ for _, opt := range options {
+ switch opt {
+ case "bind", "rbind":
+ foundbind = true
+ break
+ }
+ }
+ if !foundbind {
+ options = append(options, "rbind")
+ }
for _, opt := range options {
switch opt {
case "rw":
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 31720ea04..3ba3c2bb3 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -659,6 +659,14 @@ USER mail`
Expect(isSharedOnly).Should(BeTrue())
})
+ It("podman run --mount type=bind,bind-nonrecursive", func() {
+ SkipIfRootless()
+ session := podmanTest.Podman([]string{"run", "--mount", "type=bind,bind-nonrecursive,slave,src=/,target=/host", fedoraMinimal, "findmnt", "-nR", "/host"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(len(session.OutputToStringArray())).To(Equal(1))
+ })
+
It("podman run --pod automatically", func() {
session := podmanTest.Podman([]string{"run", "--pod", "new:foobar", ALPINE, "ls"})
session.WaitWithDefaultTimeout()