summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml6
-rw-r--r--Dockerfile2
-rw-r--r--cmd/podman/create.go65
-rw-r--r--cmd/podman/exists.go37
-rw-r--r--cmd/podman/logs.go17
-rw-r--r--cmd/podman/pod.go1
-rw-r--r--cmd/podman/ps.go2
-rw-r--r--completions/bash/podman10
-rw-r--r--contrib/cirrus/lib.sh22
-rw-r--r--contrib/cirrus/packer/ubuntu_setup.sh8
-rwxr-xr-xcontrib/cirrus/setup_environment.sh2
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/create_action.py2
-rw-r--r--contrib/python/pypodman/pypodman/lib/actions/run_action.py2
-rw-r--r--contrib/python/pypodman/pypodman/lib/podman_parser.py2
-rw-r--r--docs/podman-create.1.md10
-rw-r--r--docs/podman-pod-exists.1.md40
-rw-r--r--docs/podman-ps.1.md2
-rw-r--r--docs/podman-run.1.md8
-rw-r--r--libpod/container_internal.go47
-rw-r--r--libpod/oci.go8
-rw-r--r--pkg/rootless/rootless_linux.go26
-rw-r--r--pkg/spec/createconfig.go7
-rw-r--r--test/e2e/create_test.go90
-rw-r--r--test/e2e/exists_test.go32
-rw-r--r--test/e2e/run_test.go11
-rw-r--r--vendor.conf2
-rw-r--r--vendor/github.com/containers/storage/containers.go10
-rw-r--r--vendor/github.com/containers/storage/containers_ffjson.go1
-rw-r--r--vendor/github.com/containers/storage/drivers/aufs/aufs.go22
-rw-r--r--vendor/github.com/containers/storage/drivers/btrfs/btrfs.go3
-rw-r--r--vendor/github.com/containers/storage/drivers/devmapper/deviceset.go15
-rw-r--r--vendor/github.com/containers/storage/drivers/devmapper/driver.go5
-rw-r--r--vendor/github.com/containers/storage/drivers/driver.go1
-rw-r--r--vendor/github.com/containers/storage/drivers/overlay/overlay.go4
-rw-r--r--vendor/github.com/containers/storage/drivers/vfs/driver.go3
-rw-r--r--vendor/github.com/containers/storage/drivers/windows/windows.go3
-rw-r--r--vendor/github.com/containers/storage/drivers/zfs/zfs.go7
-rw-r--r--vendor/github.com/containers/storage/layers_ffjson.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/archive/example_changes.go97
-rw-r--r--vendor/github.com/containers/storage/pkg/idtools/parser.go4
-rw-r--r--vendor/github.com/containers/storage/store.go60
41 files changed, 584 insertions, 114 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 983ee1237..304efb2f4 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -20,7 +20,7 @@ env:
CNI_COMMIT: "7480240de9749f9a0a5c8614b17f1f03e0c06ab9"
CRIO_COMMIT: "7a283c391abb7bd25086a8ff91dbb36ebdd24466"
CRIU_COMMIT: "c74b83cd49c00589c0c0468ba5fe685b67fdbd0a"
- RUNC_COMMIT: "78ef28e63bec2ee4c139b5e3e0d691eb9bdc748d"
+ RUNC_COMMIT: "869add33186caff4a22e3e11a7472a2d48d77889"
# File to update in home-dir with task-specific env. var values
ENVLIB: ".bash_profile"
# Overrides default location (/tmp/cirrus) for repo clone
@@ -42,7 +42,7 @@ full_vm_testing_task:
# 'matrix' combinations. All run in parallel.
matrix:
# Images are generated separetly, from build_images_task (below)
- image_name: "ubuntu-1804-bionic-v20180911-libpod-63a86a18"
+ image_name: "ubuntu-18-libpod-0c954a67"
# TODO: Make these work (also build_images_task below)
#image_name: "rhel-server-ec2-7-5-165-1-libpod-fce09afe"
#image_name: "centos-7-v20180911-libpod-fce09afe"
@@ -80,7 +80,7 @@ optional_system_testing_task:
gce_instance:
matrix:
- image_name: "ubuntu-1804-bionic-v20180911-libpod-63a86a18"
+ image_name: "ubuntu-1804-bionic-v20180911-libpod-e8d18305"
# TODO: Make these work (also build_images_task below)
#image_name: "rhel-server-ec2-7-5-165-1-libpod-fce09afe"
#image_name: "centos-7-v20180911-libpod-fce09afe"
diff --git a/Dockerfile b/Dockerfile
index 3eb7b0a07..e1d7b4649 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -52,7 +52,7 @@ ADD . /go/src/github.com/containers/libpod
RUN set -x && cd /go/src/github.com/containers/libpod && make install.libseccomp.sudo
# Install runc
-ENV RUNC_COMMIT 78ef28e63bec2ee4c139b5e3e0d691eb9bdc748d
+ENV RUNC_COMMIT 869add33186caff4a22e3e11a7472a2d48d77889
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
&& git clone https://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index bcf830c7c..c40650f83 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -11,6 +11,7 @@ import (
"syscall"
"github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
ann "github.com/containers/libpod/pkg/annotations"
@@ -375,8 +376,8 @@ func configureEntrypoint(c *cli.Context, data *inspect.ImageData) []string {
return entrypoint
}
-func configurePod(c *cli.Context, runtime *libpod.Runtime, namespaces map[string]string) (map[string]string, error) {
- pod, err := runtime.LookupPod(c.String("pod"))
+func configurePod(c *cli.Context, runtime *libpod.Runtime, namespaces map[string]string, podName string) (map[string]string, error) {
+ pod, err := runtime.LookupPod(podName)
if err != nil {
return namespaces, err
}
@@ -409,6 +410,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
inputCommand, command []string
memoryLimit, memoryReservation, memorySwap, memoryKernel int64
blkioWeight uint16
+ namespaces map[string]string
)
idmappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidname"), c.String("subgidname"))
if err != nil {
@@ -492,12 +494,21 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
return nil, errors.Errorf("--cpu-quota and --cpus cannot be set together")
}
+ // EXPOSED PORTS
+ var portBindings map[nat.Port][]nat.PortBinding
+ if data != nil {
+ portBindings, err = cc.ExposedPorts(c.StringSlice("expose"), c.StringSlice("publish"), c.Bool("publish-all"), data.ContainerConfig.ExposedPorts)
+ if err != nil {
+ return nil, err
+ }
+ }
+
// Kernel Namespaces
// TODO Fix handling of namespace from pod
// Instead of integrating here, should be done in libpod
// However, that also involves setting up security opts
// when the pod's namespace is integrated
- namespaces := map[string]string{
+ namespaces = map[string]string{
"pid": c.String("pid"),
"net": c.String("net"),
"ipc": c.String("ipc"),
@@ -505,8 +516,41 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
"uts": c.String("uts"),
}
+ originalPodName := c.String("pod")
+ podName := strings.Replace(originalPodName, "new:", "", 1)
+ // after we strip out :new, make sure there is something left for a pod name
+ if len(podName) < 1 && c.IsSet("pod") {
+ return nil, errors.Errorf("new pod name must be at least one character")
+ }
if c.IsSet("pod") {
- namespaces, err = configurePod(c, runtime, namespaces)
+ if strings.HasPrefix(originalPodName, "new:") {
+ // pod does not exist; lets make it
+ var podOptions []libpod.PodCreateOption
+ podOptions = append(podOptions, libpod.WithPodName(podName), libpod.WithInfraContainer(), libpod.WithPodCgroups())
+ if len(portBindings) > 0 {
+ ociPortBindings, err := cc.NatToOCIPortBindings(portBindings)
+ if err != nil {
+ return nil, err
+ }
+ podOptions = append(podOptions, libpod.WithInfraContainerPorts(ociPortBindings))
+ }
+
+ podNsOptions, err := shared.GetNamespaceOptions(strings.Split(DefaultKernelNamespaces, ","))
+ if err != nil {
+ return nil, err
+ }
+ podOptions = append(podOptions, podNsOptions...)
+ // make pod
+ pod, err := runtime.NewPod(ctx, podOptions...)
+ if err != nil {
+ return nil, err
+ }
+ logrus.Debugf("pod %s created by new container request", pod.ID())
+
+ // The container now cannot have port bindings; so we reset the map
+ portBindings = make(map[nat.Port][]nat.PortBinding)
+ }
+ namespaces, err = configurePod(c, runtime, namespaces, podName)
if err != nil {
return nil, err
}
@@ -535,7 +579,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
// Make sure if network is set to container namespace, port binding is not also being asked for
netMode := ns.NetworkMode(namespaces["net"])
if netMode.IsContainer() {
- if len(c.StringSlice("publish")) > 0 || c.Bool("publish-all") {
+ if len(portBindings) > 0 {
return nil, errors.Errorf("cannot set port bindings on an existing container network namespace")
}
}
@@ -644,15 +688,6 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
return nil, errors.Errorf("No command specified on command line or as CMD or ENTRYPOINT in this image")
}
- // EXPOSED PORTS
- var portBindings map[nat.Port][]nat.PortBinding
- if data != nil {
- portBindings, err = cc.ExposedPorts(c.StringSlice("expose"), c.StringSlice("publish"), c.Bool("publish-all"), data.ContainerConfig.ExposedPorts)
- if err != nil {
- return nil, err
- }
- }
-
// SHM Size
shmSize, err := units.FromHumanSize(c.String("shm-size"))
if err != nil {
@@ -746,7 +781,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
NetMode: netMode,
UtsMode: utsMode,
PidMode: pidMode,
- Pod: c.String("pod"),
+ Pod: podName,
Privileged: c.Bool("privileged"),
Publish: c.StringSlice("publish"),
PublishAll: c.Bool("publish-all"),
diff --git a/cmd/podman/exists.go b/cmd/podman/exists.go
index 2f7b7c185..2e2559ec7 100644
--- a/cmd/podman/exists.go
+++ b/cmd/podman/exists.go
@@ -44,6 +44,23 @@ var (
}
)
+var (
+ podExistsDescription = `
+ podman pod exists
+
+ Check if a pod exists in local storage
+`
+
+ podExistsCommand = cli.Command{
+ Name: "exists",
+ Usage: "Check if a pod exists in local storage",
+ Description: podExistsDescription,
+ Action: podExistsCmd,
+ ArgsUsage: "POD-NAME",
+ OnUsageError: usageErrorHandler,
+ }
+)
+
func imageExistsCmd(c *cli.Context) error {
args := c.Args()
if len(args) > 1 || len(args) < 1 {
@@ -81,3 +98,23 @@ func containerExistsCmd(c *cli.Context) error {
}
return nil
}
+
+func podExistsCmd(c *cli.Context) error {
+ args := c.Args()
+ if len(args) > 1 || len(args) < 1 {
+ return errors.New("you may only check for the existence of one pod at a time")
+ }
+ runtime, err := libpodruntime.GetRuntime(c)
+ if err != nil {
+ return errors.Wrapf(err, "could not get runtime")
+ }
+ defer runtime.Shutdown(false)
+
+ if _, err := runtime.LookupPod(args[0]); err != nil {
+ if errors.Cause(err) == libpod.ErrNoSuchPod {
+ os.Exit(1)
+ }
+ return err
+ }
+ return nil
+}
diff --git a/cmd/podman/logs.go b/cmd/podman/logs.go
index 84aca5e61..75947c34e 100644
--- a/cmd/podman/logs.go
+++ b/cmd/podman/logs.go
@@ -40,14 +40,15 @@ var (
logsDescription = "The podman logs command batch-retrieves whatever logs are present for a container at the time of execution. This does not guarantee execution" +
"order when combined with podman run (i.e. your run may not have generated any logs at the time you execute podman logs"
logsCommand = cli.Command{
- Name: "logs",
- Usage: "Fetch the logs of a container",
- Description: logsDescription,
- Flags: sortFlags(logsFlags),
- Action: logsCmd,
- ArgsUsage: "CONTAINER",
- SkipArgReorder: true,
- OnUsageError: usageErrorHandler,
+ Name: "logs",
+ Usage: "Fetch the logs of a container",
+ Description: logsDescription,
+ Flags: sortFlags(logsFlags),
+ Action: logsCmd,
+ ArgsUsage: "CONTAINER",
+ SkipArgReorder: true,
+ OnUsageError: usageErrorHandler,
+ UseShortOptionHandling: true,
}
)
diff --git a/cmd/podman/pod.go b/cmd/podman/pod.go
index 0c6ec5e8c..a30361134 100644
--- a/cmd/podman/pod.go
+++ b/cmd/podman/pod.go
@@ -11,6 +11,7 @@ Pods are a group of one or more containers sharing the same network, pid and ipc
`
podSubCommands = []cli.Command{
podCreateCommand,
+ podExistsCommand,
podInspectCommand,
podKillCommand,
podPauseCommand,
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go
index 83274c9a8..0b03388a2 100644
--- a/cmd/podman/ps.go
+++ b/cmd/podman/ps.go
@@ -184,7 +184,7 @@ var (
Usage: "Display the extended information",
},
cli.BoolFlag{
- Name: "pod",
+ Name: "pod, p",
Usage: "Print the ID and name of the pod the containers are associated with",
},
cli.BoolFlag{
diff --git a/completions/bash/podman b/completions/bash/podman
index 076ec7ab4..9518cfa22 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -2033,7 +2033,7 @@ _podman_ps() {
--help -h
--latest -l
--no-trunc
- --pod
+ --pod -p
--quiet -q
--size -s
--namespace --ns
@@ -2235,6 +2235,14 @@ _podman_container_exists() {
"
}
+_podman_pod_exists() {
+ local options_with_args="
+ "
+
+ local boolean_options="
+ "
+}
+
_podman_image_exists() {
local options_with_args="
"
diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh
index 6d43c6ea5..04314e5fe 100644
--- a/contrib/cirrus/lib.sh
+++ b/contrib/cirrus/lib.sh
@@ -157,6 +157,19 @@ install_cni_plugins() {
sudo cp bin/* /usr/libexec/cni
}
+install_runc_from_git(){
+ wd=$(pwd)
+ DEST="$GOPATH/src/github.com/opencontainers/runc"
+ rm -rf "$DEST"
+ ooe.sh git clone https://github.com/opencontainers/runc.git "$DEST"
+ cd "$DEST"
+ ooe.sh git fetch origin --tags
+ ooe.sh git checkout -q "$RUNC_COMMIT"
+ ooe.sh make static BUILDTAGS="seccomp selinux"
+ sudo install -m 755 runc /usr/bin/runc
+ cd $wd
+}
+
install_runc(){
OS_RELEASE_ID=$(os_release_id)
echo "Installing RunC from commit $RUNC_COMMIT"
@@ -179,14 +192,7 @@ install_runc(){
cd "$GOPATH/src/github.com/containers/libpod"
ooe.sh sudo make install.libseccomp.sudo
fi
- DEST="$GOPATH/src/github.com/opencontainers/runc"
- rm -rf "$DEST"
- ooe.sh git clone https://github.com/opencontainers/runc.git "$DEST"
- cd "$DEST"
- ooe.sh git fetch origin --tags
- ooe.sh git checkout -q "$RUNC_COMMIT"
- ooe.sh make static BUILDTAGS="seccomp selinux"
- sudo install -m 755 runc /usr/bin/runc
+ install_runc_from_git
}
install_buildah() {
diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh
index 4cf1f335b..ef209a4a4 100644
--- a/contrib/cirrus/packer/ubuntu_setup.sh
+++ b/contrib/cirrus/packer/ubuntu_setup.sh
@@ -21,11 +21,13 @@ install_ooe
export GOPATH="$(mktemp -d)"
trap "sudo rm -rf $GOPATH" EXIT
+export DEBIAN_FRONTEND=noninteractive
+
# Try twice as workaround for minor networking problems
echo "Updating system and installing package dependencies"
-ooe.sh sudo apt-get -qq update || sudo apt-get -qq update
-ooe.sh sudo apt-get -qq upgrade || sudo apt-get -qq upgrade
-ooe.sh sudo apt-get -qq install --no-install-recommends \
+ooe.sh sudo -E apt-get -qq update || sudo -E apt-get -qq update
+ooe.sh sudo -E apt-get -qq upgrade || sudo -E apt-get -qq upgrade
+ooe.sh sudo -E apt-get -qq install --no-install-recommends \
apparmor \
autoconf \
automake \
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 167db127f..2563b5f43 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -53,6 +53,8 @@ then
# Some setup needs to vary between distros
case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in
ubuntu-18)
+ # Always install runc on Ubuntu
+ install_runc_from_git
envstr='export BUILDTAGS="seccomp $($GOSRC/hack/btrfs_tag.sh) $($GOSRC/hack/btrfs_installed_tag.sh) $($GOSRC/hack/ostree_tag.sh) varlink exclude_graphdriver_devicemapper"'
;;
fedora-28) ;& # Continue to the next item
diff --git a/contrib/python/pypodman/pypodman/lib/actions/create_action.py b/contrib/python/pypodman/pypodman/lib/actions/create_action.py
index d9631763a..26a312bb1 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/create_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/create_action.py
@@ -21,7 +21,7 @@ class Create(AbstractActionBase):
parser.add_argument('image', nargs=1, help='source image id')
parser.add_argument(
'command',
- nargs='*',
+ nargs=parent.REMAINDER,
help='command and args to run.',
)
parser.set_defaults(class_=cls, method='create')
diff --git a/contrib/python/pypodman/pypodman/lib/actions/run_action.py b/contrib/python/pypodman/pypodman/lib/actions/run_action.py
index a63eb7917..6a6b3cb2c 100644
--- a/contrib/python/pypodman/pypodman/lib/actions/run_action.py
+++ b/contrib/python/pypodman/pypodman/lib/actions/run_action.py
@@ -21,7 +21,7 @@ class Run(AbstractActionBase):
parser.add_argument('image', nargs=1, help='source image id.')
parser.add_argument(
'command',
- nargs='*',
+ nargs=parent.REMAINDER,
help='command and args to run.',
)
parser.set_defaults(class_=cls, method='run')
diff --git a/contrib/python/pypodman/pypodman/lib/podman_parser.py b/contrib/python/pypodman/pypodman/lib/podman_parser.py
index 28fb44cf0..412c8c8fd 100644
--- a/contrib/python/pypodman/pypodman/lib/podman_parser.py
+++ b/contrib/python/pypodman/pypodman/lib/podman_parser.py
@@ -97,6 +97,8 @@ class PodmanArgumentParser(argparse.ArgumentParser):
actions_parser = self.add_subparsers(
dest='subparser_name', help='commands')
+ # For create/exec/run: don't process options intended for subcommand
+ actions_parser.REMAINDER = argparse.REMAINDER
# import buried here to prevent import loops
import pypodman.lib.actions # pylint: disable=cyclic-import
diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md
index 474796a35..f1409a554 100644
--- a/docs/podman-create.1.md
+++ b/docs/podman-create.1.md
@@ -455,7 +455,8 @@ Tune the container's pids limit. Set `-1` to have unlimited pids for the contain
**--pod**=""
-Run container in an existing pod
+Run container in an existing pod. If you want podman to make the pod for you, preference the pod name with `new:`.
+To make a pod with more granular options, use the `podman pod create` command before creating a container.
**--privileged**=*true*|*false*
@@ -466,9 +467,10 @@ By default, podman containers are
This is because by default a container is not allowed to access any devices.
A “privileged” container is given access to all devices.
-When the operator executes **podman run --privileged**, podman enables access
-to all devices on the host as well as set turn off most of the security measures
-protecting the host from the container.
+When the operator executes a privileged container, podman enables access
+to all devices on the host, turns off graphdriver mount options, as well as
+turning off most of the security measures protecting the host from the
+container.
**-p**, **--publish**=[]
diff --git a/docs/podman-pod-exists.1.md b/docs/podman-pod-exists.1.md
new file mode 100644
index 000000000..8fb2fc90e
--- /dev/null
+++ b/docs/podman-pod-exists.1.md
@@ -0,0 +1,40 @@
+% podman-pod-exits(1) Podman Man Pages
+% Brent Baude
+% December 2018
+# NAME
+podman-pod-exists- Check if a pod exists in local storage
+
+# SYNOPSIS
+**podman pod exists**
+[**-h**|**--help**]
+POD
+
+# DESCRIPTION
+**podman pod exists** checks if a pod exists in local storage. The **ID** or **Name**
+of the pod may be used as input. Podman will return an exit code
+of `0` when the pod is found. A `1` will be returned otherwise. An exit code of `125` indicates there
+was an issue accessing the local storage.
+
+## Examples ##
+
+Check if a pod called `web` exists in local storage (the pod does actually exist).
+```
+$ sudo podman pod exists web
+$ echo $?
+0
+$
+```
+
+Check if a pod called `backend` exists in local storage (the pod does not actually exist).
+```
+$ sudo podman pod exists backend
+$ echo $?
+1
+$
+```
+
+## SEE ALSO
+podman-pod(1), podman(1)
+
+# HISTORY
+December 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
diff --git a/docs/podman-ps.1.md b/docs/podman-ps.1.md
index 2cb77ffed..7333a1095 100644
--- a/docs/podman-ps.1.md
+++ b/docs/podman-ps.1.md
@@ -24,7 +24,7 @@ all the containers information. By default it lists:
Show all the containers, default is only running containers
-**--pod**
+**--pod, -p**
Display the pods the containers are associated with
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index 202091b07..5917f6f7a 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -439,7 +439,8 @@ Tune the container's pids limit. Set `-1` to have unlimited pids for the contain
**--pod**=""
-Run container in an existing pod
+Run container in an existing pod. If you want podman to make the pod for you, preference the pod name with `new:`.
+To make a pod with more granular options, use the `podman pod create` command before creating a container.
**--privileged**=*true*|*false*
@@ -451,8 +452,9 @@ container is not allowed to access any devices. A “privileged” container
is given access to all devices.
When the operator executes **podman run --privileged**, podman enables access
-to all devices on the host as well as set turn off most of the security measures
-protecting the host from the container.
+to all devices on the host, turns off graphdriver mount options, as well as
+turning off most of the security measures protecting the host from the
+container.
**-p**, **--publish**=[]
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index b616e0a07..e31a8099c 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -273,6 +273,27 @@ func (c *Container) setupStorage(ctx context.Context) error {
},
LabelOpts: c.config.LabelOpts,
}
+ if c.config.Privileged {
+ privOpt := func(opt string) bool {
+ for _, privopt := range []string{"nodev", "nosuid", "noexec"} {
+ if opt == privopt {
+ return true
+ }
+ }
+ return false
+ }
+ defOptions, err := storage.GetDefaultMountOptions()
+ if err != nil {
+ return errors.Wrapf(err, "error getting default mount options")
+ }
+ var newOptions []string
+ for _, opt := range defOptions {
+ if !privOpt(opt) {
+ newOptions = append(newOptions, opt)
+ }
+ }
+ options.MountOpts = newOptions
+ }
if c.config.Rootfs == "" {
options.IDMappingOptions = c.config.IDMappings
@@ -821,28 +842,22 @@ func (c *Container) mountStorage() (string, error) {
return c.state.Mountpoint, nil
}
- if !rootless.IsRootless() {
- // TODO: generalize this mount code so it will mount every mount in ctr.config.Mounts
- mounted, err := mount.Mounted(c.config.ShmDir)
- if err != nil {
- return "", errors.Wrapf(err, "unable to determine if %q is mounted", c.config.ShmDir)
- }
+ mounted, err := mount.Mounted(c.config.ShmDir)
+ if err != nil {
+ return "", errors.Wrapf(err, "unable to determine if %q is mounted", c.config.ShmDir)
+ }
+ if !mounted {
+ shmOptions := fmt.Sprintf("mode=1777,size=%d", c.config.ShmSize)
+ if err := c.mountSHM(shmOptions); err != nil {
+ return "", err
+ }
if err := os.Chown(c.config.ShmDir, c.RootUID(), c.RootGID()); err != nil {
return "", errors.Wrapf(err, "failed to chown %s", c.config.ShmDir)
}
-
- if !mounted {
- shmOptions := fmt.Sprintf("mode=1777,size=%d", c.config.ShmSize)
- if err := c.mountSHM(shmOptions); err != nil {
- return "", err
- }
- if err := os.Chown(c.config.ShmDir, c.RootUID(), c.RootGID()); err != nil {
- return "", errors.Wrapf(err, "failed to chown %s", c.config.ShmDir)
- }
- }
}
+ // TODO: generalize this mount code so it will mount every mount in ctr.config.Mounts
mountPoint := c.config.Rootfs
if mountPoint == "" {
mountPoint, err = c.mount()
diff --git a/libpod/oci.go b/libpod/oci.go
index 6ca3ef2e6..3222f9403 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -696,8 +696,12 @@ func (r *OCIRuntime) stopContainer(ctr *Container, timeout uint) error {
// deleteContainer deletes a container from the OCI runtime
func (r *OCIRuntime) deleteContainer(ctr *Container) error {
- _, err := utils.ExecCmd(r.path, "delete", "--force", ctr.ID())
- return err
+ runtimeDir, err := util.GetRootlessRuntimeDir()
+ if err != nil {
+ return err
+ }
+ env := []string{fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)}
+ return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, "delete", "--force", ctr.ID())
}
// pauseContainer pauses the given container
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 85b0ef392..07002da3f 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -74,7 +74,7 @@ func GetRootlessUID() int {
func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap) error {
path, err := exec.LookPath(tool)
if err != nil {
- return err
+ return errors.Wrapf(err, "cannot find %s", tool)
}
appendTriplet := func(l []string, a, b, c int) []string {
@@ -92,7 +92,11 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap)
Path: path,
Args: args,
}
- return cmd.Run()
+
+ if err := cmd.Run(); err != nil {
+ return errors.Wrapf(err, "cannot setup namespace using %s", tool)
+ }
+ return nil
}
// JoinNS re-exec podman in a new userNS and join the user namespace of the specified
@@ -191,11 +195,13 @@ func BecomeRootInUserNS() (bool, int, error) {
return false, -1, errors.Errorf("cannot re-exec process")
}
+ allowSingleIDMapping := os.Getenv("PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS") != ""
+
var uids, gids []idtools.IDMap
username := os.Getenv("USER")
if username == "" {
user, err := user.LookupId(fmt.Sprintf("%d", os.Getuid()))
- if err != nil && os.Getenv("PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS") == "" {
+ if err != nil && !allowSingleIDMapping {
if os.IsNotExist(err) {
return false, 0, errors.Wrapf(err, "/etc/subuid or /etc/subgid does not exist, see subuid/subgid man pages for information on these files")
}
@@ -206,7 +212,7 @@ func BecomeRootInUserNS() (bool, int, error) {
}
}
mappings, err := idtools.NewIDMappings(username, username)
- if os.Getenv("PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS") == "" {
+ if !allowSingleIDMapping {
if err != nil {
return false, -1, err
}
@@ -236,7 +242,11 @@ func BecomeRootInUserNS() (bool, int, error) {
uidsMapped := false
if mappings != nil && uids != nil {
- uidsMapped = tryMappingTool("newuidmap", pid, os.Getuid(), uids) == nil
+ err := tryMappingTool("newuidmap", pid, os.Getuid(), uids)
+ if !allowSingleIDMapping && err != nil {
+ return false, 0, err
+ }
+ uidsMapped = err == nil
}
if !uidsMapped {
setgroups := fmt.Sprintf("/proc/%d/setgroups", pid)
@@ -254,7 +264,11 @@ func BecomeRootInUserNS() (bool, int, error) {
gidsMapped := false
if mappings != nil && gids != nil {
- gidsMapped = tryMappingTool("newgidmap", pid, os.Getgid(), gids) == nil
+ err := tryMappingTool("newgidmap", pid, os.Getgid(), gids)
+ if !allowSingleIDMapping && err != nil {
+ return false, 0, err
+ }
+ gidsMapped = err == nil
}
if !gidsMapped {
gidMap := fmt.Sprintf("/proc/%d/gid_map", pid)
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index a0fd40318..25f8cd7a1 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -496,8 +496,13 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib
// CreatePortBindings iterates ports mappings and exposed ports into a format CNI understands
func (c *CreateConfig) CreatePortBindings() ([]ocicni.PortMapping, error) {
+ return NatToOCIPortBindings(c.PortBindings)
+}
+
+// NatToOCIPortBindings iterates a nat.portmap slice and creates []ocicni portmapping slice
+func NatToOCIPortBindings(ports nat.PortMap) ([]ocicni.PortMapping, error) {
var portBindings []ocicni.PortMapping
- for containerPb, hostPb := range c.PortBindings {
+ for containerPb, hostPb := range ports {
var pm ocicni.PortMapping
pm.ContainerPort = int32(containerPb.Int())
for _, i := range hostPb {
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index befe7b06d..684a7cd88 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -3,6 +3,7 @@ package integration
import (
"fmt"
"os"
+ "path/filepath"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
@@ -110,4 +111,93 @@ var _ = Describe("Podman create", func() {
Expect(result.ExitCode()).To(Equal(0))
Expect(result.OutputToString()).To(Equal("/bin/foo -c"))
})
+
+ It("podman create --mount flag with multiple mounts", func() {
+ vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
+ err := os.MkdirAll(vol1, 0755)
+ Expect(err).To(BeNil())
+ vol2 := filepath.Join(podmanTest.TempDir, "vol-test2")
+ err = os.MkdirAll(vol2, 0755)
+ Expect(err).To(BeNil())
+
+ session := podmanTest.Podman([]string{"create", "--name", "test", "--mount", "type=bind,src=" + vol1 + ",target=/myvol1,z", "--mount", "type=bind,src=" + vol2 + ",target=/myvol2,z", ALPINE, "touch", "/myvol2/foo.txt"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"start", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"logs", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).ToNot(ContainSubstring("cannot touch"))
+ })
+
+ It("podman create with --mount flag", func() {
+ if podmanTest.Host.Arch == "ppc64le" {
+ Skip("skip failing test on ppc64le")
+ }
+ mountPath := filepath.Join(podmanTest.TempDir, "secrets")
+ os.Mkdir(mountPath, 0755)
+ session := podmanTest.Podman([]string{"create", "--name", "test", "--rm", "--mount", fmt.Sprintf("type=bind,src=%s,target=/create/test", mountPath), ALPINE, "grep", "/create/test", "/proc/self/mountinfo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"start", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"logs", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("/create/test rw"))
+
+ session = podmanTest.Podman([]string{"create", "--name", "test_ro", "--rm", "--mount", fmt.Sprintf("type=bind,src=%s,target=/create/test,ro", mountPath), ALPINE, "grep", "/create/test", "/proc/self/mountinfo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"start", "test_ro"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"logs", "test_ro"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("/create/test ro"))
+
+ session = podmanTest.Podman([]string{"create", "--name", "test_shared", "--rm", "--mount", fmt.Sprintf("type=bind,src=%s,target=/create/test,shared", mountPath), ALPINE, "grep", "/create/test", "/proc/self/mountinfo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"start", "test_shared"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"logs", "test_shared"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ found, matches := session.GrepString("/create/test")
+ Expect(found).Should(BeTrue())
+ Expect(matches[0]).To(ContainSubstring("rw"))
+ Expect(matches[0]).To(ContainSubstring("shared"))
+
+ mountPath = filepath.Join(podmanTest.TempDir, "scratchpad")
+ os.Mkdir(mountPath, 0755)
+ session = podmanTest.Podman([]string{"create", "--name", "test_tmpfs", "--rm", "--mount", "type=tmpfs,target=/create/test", ALPINE, "grep", "/create/test", "/proc/self/mountinfo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"start", "test_tmpfs"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"logs", "test_tmpfs"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("/create/test rw,nosuid,nodev,noexec,relatime - tmpfs"))
+ })
+
+ It("podman create --pod automatically", func() {
+ session := podmanTest.Podman([]string{"create", "--pod", "new:foobar", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ check := podmanTest.Podman([]string{"pod", "ps", "--no-trunc"})
+ check.WaitWithDefaultTimeout()
+ match, _ := check.GrepString("foobar")
+ Expect(match).To(BeTrue())
+ })
})
diff --git a/test/e2e/exists_test.go b/test/e2e/exists_test.go
index 9165e8902..d9652de4b 100644
--- a/test/e2e/exists_test.go
+++ b/test/e2e/exists_test.go
@@ -82,4 +82,36 @@ var _ = Describe("Podman image|container exists", func() {
Expect(session.ExitCode()).To(Equal(1))
})
+ It("podman pod exists in local storage by name", func() {
+ setup, rc, _ := podmanTest.CreatePod("foobar")
+ setup.WaitWithDefaultTimeout()
+ Expect(rc).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"pod", "exists", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+ It("podman pod exists in local storage by container ID", func() {
+ setup, rc, podID := podmanTest.CreatePod("")
+ setup.WaitWithDefaultTimeout()
+ Expect(rc).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"pod", "exists", podID})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+ It("podman pod exists in local storage by short container ID", func() {
+ setup, rc, podID := podmanTest.CreatePod("")
+ setup.WaitWithDefaultTimeout()
+ Expect(rc).To(Equal(0))
+
+ session := podmanTest.Podman([]string{"pod", "exists", podID[0:12]})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+ It("podman pod does not exist in local storage", func() {
+ session := podmanTest.Podman([]string{"pod", "exists", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(1))
+ })
})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 38504828b..aaee7fa53 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -628,4 +628,15 @@ USER mail`
isSharedOnly := !strings.Contains(shared[0], "shared,")
Expect(isSharedOnly).Should(BeTrue())
})
+
+ It("podman run --pod automatically", func() {
+ session := podmanTest.Podman([]string{"run", "--pod", "new:foobar", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ check := podmanTest.Podman([]string{"pod", "ps", "--no-trunc"})
+ check.WaitWithDefaultTimeout()
+ match, _ := check.GrepString("foobar")
+ Expect(match).To(BeTrue())
+ })
})
diff --git a/vendor.conf b/vendor.conf
index f9fccfdfb..be306a181 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -12,7 +12,7 @@ github.com/containerd/continuity master
github.com/containernetworking/cni v0.7.0-alpha1
github.com/containernetworking/plugins 1562a1e60ed101aacc5e08ed9dbeba8e9f3d4ec1
github.com/containers/image bd10b1b53b2976f215b3f2f848fb8e7cad779aeb
-github.com/containers/storage 3161726d1db0d0d4e86a9667dd476f09b997f497
+github.com/containers/storage 9d3838cd434d32042f9bdf1f9f4a2bf2d6ea8dc5
github.com/containers/psgo 5dde6da0bc8831b35243a847625bcf18183bd1ee
github.com/coreos/go-systemd v14
github.com/cri-o/ocicni 2d2983e40c242322a56c22a903785e7f83eb378c
diff --git a/vendor/github.com/containers/storage/containers.go b/vendor/github.com/containers/storage/containers.go
index 0a125331d..beaf41f39 100644
--- a/vendor/github.com/containers/storage/containers.go
+++ b/vendor/github.com/containers/storage/containers.go
@@ -147,6 +147,13 @@ func (c *Container) ProcessLabel() string {
return ""
}
+func (c *Container) MountOpts() []string {
+ if mountOpts, ok := c.Flags["MountOpts"].([]string); ok {
+ return mountOpts
+ }
+ return nil
+}
+
func (r *containerStore) Containers() ([]Container, error) {
containers := make([]Container, len(r.containers))
for i := range r.containers {
@@ -293,6 +300,9 @@ func (r *containerStore) Create(id string, names []string, image, layer, metadat
if _, idInUse := r.byid[id]; idInUse {
return nil, ErrDuplicateID
}
+ if options.MountOpts != nil {
+ options.Flags["MountOpts"] = append([]string{}, options.MountOpts...)
+ }
names = dedupeNames(names)
for _, name := range names {
if _, nameInUse := r.byname[name]; nameInUse {
diff --git a/vendor/github.com/containers/storage/containers_ffjson.go b/vendor/github.com/containers/storage/containers_ffjson.go
index 6e83808d4..aef6becfe 100644
--- a/vendor/github.com/containers/storage/containers_ffjson.go
+++ b/vendor/github.com/containers/storage/containers_ffjson.go
@@ -1,6 +1,5 @@
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
// source: containers.go
-//
package storage
diff --git a/vendor/github.com/containers/storage/drivers/aufs/aufs.go b/vendor/github.com/containers/storage/drivers/aufs/aufs.go
index 474c7574d..ca69816be 100644
--- a/vendor/github.com/containers/storage/drivers/aufs/aufs.go
+++ b/vendor/github.com/containers/storage/drivers/aufs/aufs.go
@@ -441,7 +441,7 @@ func (a *Driver) Get(id string, options graphdriver.MountOpts) (string, error) {
// If a dir does not have a parent ( no layers )do not try to mount
// just return the diff path to the data
if len(parents) > 0 {
- if err := a.mount(id, m, options.MountLabel, parents); err != nil {
+ if err := a.mount(id, m, parents, options); err != nil {
return "", err
}
}
@@ -585,7 +585,7 @@ func (a *Driver) getParentLayerPaths(id string) ([]string, error) {
return layers, nil
}
-func (a *Driver) mount(id string, target string, mountLabel string, layers []string) error {
+func (a *Driver) mount(id string, target string, layers []string, options graphdriver.MountOpts) error {
a.Lock()
defer a.Unlock()
@@ -596,7 +596,7 @@ func (a *Driver) mount(id string, target string, mountLabel string, layers []str
rw := a.getDiffPath(id)
- if err := a.aufsMount(layers, rw, target, mountLabel); err != nil {
+ if err := a.aufsMount(layers, rw, target, options); err != nil {
return fmt.Errorf("error creating aufs mount to %s: %v", target, err)
}
return nil
@@ -643,7 +643,7 @@ func (a *Driver) Cleanup() error {
return mountpk.Unmount(a.root)
}
-func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err error) {
+func (a *Driver) aufsMount(ro []string, rw, target string, options graphdriver.MountOpts) (err error) {
defer func() {
if err != nil {
Unmount(target)
@@ -657,7 +657,7 @@ func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err erro
if useDirperm() {
offset += len(",dirperm1")
}
- b := make([]byte, unix.Getpagesize()-len(mountLabel)-offset) // room for xino & mountLabel
+ b := make([]byte, unix.Getpagesize()-len(options.MountLabel)-offset) // room for xino & mountLabel
bp := copy(b, fmt.Sprintf("br:%s=rw", rw))
index := 0
@@ -670,21 +670,25 @@ func (a *Driver) aufsMount(ro []string, rw, target, mountLabel string) (err erro
}
opts := "dio,xino=/dev/shm/aufs.xino"
- if a.mountOptions != "" {
- opts += fmt.Sprintf(",%s", a.mountOptions)
+ mountOptions := a.mountOptions
+ if len(options.Options) > 0 {
+ mountOptions = strings.Join(options.Options, ",")
+ }
+ if mountOptions != "" {
+ opts += fmt.Sprintf(",%s", mountOptions)
}
if useDirperm() {
opts += ",dirperm1"
}
- data := label.FormatMountLabel(fmt.Sprintf("%s,%s", string(b[:bp]), opts), mountLabel)
+ data := label.FormatMountLabel(fmt.Sprintf("%s,%s", string(b[:bp]), opts), options.MountLabel)
if err = mount("none", target, "aufs", 0, data); err != nil {
return
}
for ; index < len(ro); index++ {
layer := fmt.Sprintf(":%s=ro+wh", ro[index])
- data := label.FormatMountLabel(fmt.Sprintf("append%s", layer), mountLabel)
+ data := label.FormatMountLabel(fmt.Sprintf("append%s", layer), options.MountLabel)
if err = mount("none", target, "aufs", unix.MS_REMOUNT, data); err != nil {
return
}
diff --git a/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go b/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go
index adc34d209..567cda9d3 100644
--- a/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go
+++ b/vendor/github.com/containers/storage/drivers/btrfs/btrfs.go
@@ -640,6 +640,9 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (string, error) {
if err != nil {
return "", err
}
+ if len(options.Options) > 0 {
+ return "", fmt.Errorf("btrfs driver does not support mount options")
+ }
if !st.IsDir() {
return "", fmt.Errorf("%s: not a directory", dir)
diff --git a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go
index cbf67b3eb..2801dfdc5 100644
--- a/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go
+++ b/vendor/github.com/containers/storage/drivers/devmapper/deviceset.go
@@ -2364,7 +2364,7 @@ func (devices *DeviceSet) xfsSetNospaceRetries(info *devInfo) error {
}
// MountDevice mounts the device if not already mounted.
-func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error {
+func (devices *DeviceSet) MountDevice(hash, path string, moptions graphdriver.MountOpts) error {
info, err := devices.lookupDeviceWithLock(hash)
if err != nil {
return err
@@ -2396,8 +2396,17 @@ func (devices *DeviceSet) MountDevice(hash, path, mountLabel string) error {
options = joinMountOptions(options, "nouuid")
}
- options = joinMountOptions(options, devices.mountOptions)
- options = joinMountOptions(options, label.FormatMountLabel("", mountLabel))
+ mountOptions := devices.mountOptions
+ if len(moptions.Options) > 0 {
+ addNouuid := strings.Contains("nouuid", mountOptions)
+ mountOptions = strings.Join(moptions.Options, ",")
+ if addNouuid {
+ mountOptions = fmt.Sprintf("nouuid,", mountOptions)
+ }
+ }
+
+ options = joinMountOptions(options, mountOptions)
+ options = joinMountOptions(options, label.FormatMountLabel("", moptions.MountLabel))
if err := mount.Mount(info.DevName(), path, fstype, options); err != nil {
return fmt.Errorf("devmapper: Error mounting '%s' on '%s': %s\n%v", info.DevName(), path, err, string(dmesg.Dmesg(256)))
diff --git a/vendor/github.com/containers/storage/drivers/devmapper/driver.go b/vendor/github.com/containers/storage/drivers/devmapper/driver.go
index 9fc082d7d..39a4fbe2c 100644
--- a/vendor/github.com/containers/storage/drivers/devmapper/driver.go
+++ b/vendor/github.com/containers/storage/drivers/devmapper/driver.go
@@ -9,8 +9,6 @@ import (
"path"
"strconv"
- "github.com/sirupsen/logrus"
-
"github.com/containers/storage/drivers"
"github.com/containers/storage/pkg/devicemapper"
"github.com/containers/storage/pkg/idtools"
@@ -18,6 +16,7 @@ import (
"github.com/containers/storage/pkg/mount"
"github.com/containers/storage/pkg/system"
units "github.com/docker/go-units"
+ "github.com/sirupsen/logrus"
)
func init() {
@@ -189,7 +188,7 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (string, error) {
}
// Mount the device
- if err := d.DeviceSet.MountDevice(id, mp, options.MountLabel); err != nil {
+ if err := d.DeviceSet.MountDevice(id, mp, options); err != nil {
d.ctr.Decrement(mp)
return "", err
}
diff --git a/vendor/github.com/containers/storage/drivers/driver.go b/vendor/github.com/containers/storage/drivers/driver.go
index 4569c7b59..476b55160 100644
--- a/vendor/github.com/containers/storage/drivers/driver.go
+++ b/vendor/github.com/containers/storage/drivers/driver.go
@@ -49,6 +49,7 @@ type MountOpts struct {
// UidMaps & GidMaps are the User Namespace mappings to be assigned to content in the mount point
UidMaps []idtools.IDMap
GidMaps []idtools.IDMap
+ Options []string
}
// InitFunc initializes the storage driver.
diff --git a/vendor/github.com/containers/storage/drivers/overlay/overlay.go b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
index b7e15a7f6..a165a13a3 100644
--- a/vendor/github.com/containers/storage/drivers/overlay/overlay.go
+++ b/vendor/github.com/containers/storage/drivers/overlay/overlay.go
@@ -743,7 +743,9 @@ func (d *Driver) get(id string, disableShifting bool, options graphdriver.MountO
workDir := path.Join(dir, "work")
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), diffDir, workDir)
- if d.options.mountOptions != "" {
+ if len(options.Options) > 0 {
+ opts = fmt.Sprintf("%s,%s", strings.Join(options.Options, ","), opts)
+ } else if d.options.mountOptions != "" {
opts = fmt.Sprintf("%s,%s", d.options.mountOptions, opts)
}
mountData := label.FormatMountLabel(opts, options.MountLabel)
diff --git a/vendor/github.com/containers/storage/drivers/vfs/driver.go b/vendor/github.com/containers/storage/drivers/vfs/driver.go
index d10fb2607..e3a67a69b 100644
--- a/vendor/github.com/containers/storage/drivers/vfs/driver.go
+++ b/vendor/github.com/containers/storage/drivers/vfs/driver.go
@@ -181,6 +181,9 @@ func (d *Driver) Remove(id string) error {
// Get returns the directory for the given id.
func (d *Driver) Get(id string, options graphdriver.MountOpts) (_ string, retErr error) {
dir := d.dir(id)
+ if len(options.Options) > 0 {
+ return "", fmt.Errorf("vfs driver does not support mount options")
+ }
if st, err := os.Stat(dir); err != nil {
return "", err
} else if !st.IsDir() {
diff --git a/vendor/github.com/containers/storage/drivers/windows/windows.go b/vendor/github.com/containers/storage/drivers/windows/windows.go
index 4ccf657dc..c6d86a4ab 100644
--- a/vendor/github.com/containers/storage/drivers/windows/windows.go
+++ b/vendor/github.com/containers/storage/drivers/windows/windows.go
@@ -367,6 +367,9 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (string, error) {
logrus.Debugf("WindowsGraphDriver Get() id %s mountLabel %s", id, options.MountLabel)
var dir string
+ if len(options.Options) > 0 {
+ return "", fmt.Errorf("windows driver does not support mount options")
+ }
rID, err := d.resolveID(id)
if err != nil {
return "", err
diff --git a/vendor/github.com/containers/storage/drivers/zfs/zfs.go b/vendor/github.com/containers/storage/drivers/zfs/zfs.go
index 4e27a0a6f..c3ce6e869 100644
--- a/vendor/github.com/containers/storage/drivers/zfs/zfs.go
+++ b/vendor/github.com/containers/storage/drivers/zfs/zfs.go
@@ -366,8 +366,13 @@ func (d *Driver) Get(id string, options graphdriver.MountOpts) (string, error) {
return mountpoint, nil
}
+ mountOptions := d.options.mountOptions
+ if len(options.Options) > 0 {
+ mountOptions = strings.Join(options.Options, ",")
+ }
+
filesystem := d.zfsPath(id)
- opts := label.FormatMountLabel(d.options.mountOptions, options.MountLabel)
+ opts := label.FormatMountLabel(mountOptions, options.MountLabel)
logrus.Debugf(`[zfs] mount("%s", "%s", "%s")`, filesystem, mountpoint, opts)
rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps)
diff --git a/vendor/github.com/containers/storage/layers_ffjson.go b/vendor/github.com/containers/storage/layers_ffjson.go
index 09b5d0f33..125b5d8c9 100644
--- a/vendor/github.com/containers/storage/layers_ffjson.go
+++ b/vendor/github.com/containers/storage/layers_ffjson.go
@@ -1,5 +1,5 @@
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
-// source: ./layers.go
+// source: layers.go
package storage
diff --git a/vendor/github.com/containers/storage/pkg/archive/example_changes.go b/vendor/github.com/containers/storage/pkg/archive/example_changes.go
new file mode 100644
index 000000000..70f9c5564
--- /dev/null
+++ b/vendor/github.com/containers/storage/pkg/archive/example_changes.go
@@ -0,0 +1,97 @@
+// +build ignore
+
+// Simple tool to create an archive stream from an old and new directory
+//
+// By default it will stream the comparison of two temporary directories with junk files
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "path"
+
+ "github.com/containers/storage/pkg/archive"
+ "github.com/sirupsen/logrus"
+)
+
+var (
+ flDebug = flag.Bool("D", false, "debugging output")
+ flNewDir = flag.String("newdir", "", "")
+ flOldDir = flag.String("olddir", "", "")
+ log = logrus.New()
+)
+
+func main() {
+ flag.Usage = func() {
+ fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)")
+ fmt.Printf("%s [OPTIONS]\n", os.Args[0])
+ flag.PrintDefaults()
+ }
+ flag.Parse()
+ log.Out = os.Stderr
+ if (len(os.Getenv("DEBUG")) > 0) || *flDebug {
+ logrus.SetLevel(logrus.DebugLevel)
+ }
+ var newDir, oldDir string
+
+ if len(*flNewDir) == 0 {
+ var err error
+ newDir, err = ioutil.TempDir("", "storage-test-newDir")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.RemoveAll(newDir)
+ if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil {
+ log.Fatal(err)
+ }
+ } else {
+ newDir = *flNewDir
+ }
+
+ if len(*flOldDir) == 0 {
+ oldDir, err := ioutil.TempDir("", "storage-test-oldDir")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer os.RemoveAll(oldDir)
+ } else {
+ oldDir = *flOldDir
+ }
+
+ changes, err := archive.ChangesDirs(newDir, oldDir)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ a, err := archive.ExportChanges(newDir, changes)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer a.Close()
+
+ i, err := io.Copy(os.Stdout, a)
+ if err != nil && err != io.EOF {
+ log.Fatal(err)
+ }
+ fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i)
+}
+
+func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) {
+ fileData := []byte("fooo")
+ for n := 0; n < numberOfFiles; n++ {
+ fileName := fmt.Sprintf("file-%d", n)
+ if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
+ return 0, err
+ }
+ if makeLinks {
+ if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil {
+ return 0, err
+ }
+ }
+ }
+ totalSize := numberOfFiles * len(fileData)
+ return totalSize, nil
+}
diff --git a/vendor/github.com/containers/storage/pkg/idtools/parser.go b/vendor/github.com/containers/storage/pkg/idtools/parser.go
index 9b76395c2..c56aa86a2 100644
--- a/vendor/github.com/containers/storage/pkg/idtools/parser.go
+++ b/vendor/github.com/containers/storage/pkg/idtools/parser.go
@@ -30,8 +30,8 @@ func parseTriple(spec []string) (container, host, size uint32, err error) {
}
// ParseIDMap parses idmap triples from string.
-func ParseIDMap(idMapSpec, mapSetting string) (idmap []IDMap, err error) {
- if len(idMapSpec) > 0 {
+func ParseIDMap(mapSpec []string, mapSetting string) (idmap []IDMap, err error) {
+ for _, idMapSpec := range mapSpec {
idSpec := strings.Fields(strings.Map(nonDigitsToWhitespace, idMapSpec))
if len(idSpec)%3 != 0 {
return nil, fmt.Errorf("error initializing ID mappings: %s setting is malformed", mapSetting)
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index dfc30c43f..e0dd1b92f 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -21,6 +21,7 @@ import (
"github.com/containers/storage/pkg/directory"
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/ioutils"
+ "github.com/containers/storage/pkg/parsers"
"github.com/containers/storage/pkg/stringid"
"github.com/containers/storage/pkg/stringutils"
digest "github.com/opencontainers/go-digest"
@@ -501,6 +502,7 @@ type ContainerOptions struct {
IDMappingOptions
LabelOpts []string
Flags map[string]interface{}
+ MountOpts []string
}
type store struct {
@@ -2144,21 +2146,20 @@ func (s *store) DeleteContainer(id string) error {
if err = rlstore.Delete(container.LayerID); err != nil {
return err
}
- if err = rcstore.Delete(id); err != nil {
- return err
- }
- middleDir := s.graphDriverName + "-containers"
- gcpath := filepath.Join(s.GraphRoot(), middleDir, container.ID)
- if err = os.RemoveAll(gcpath); err != nil {
- return err
- }
- rcpath := filepath.Join(s.RunRoot(), middleDir, container.ID)
- if err = os.RemoveAll(rcpath); err != nil {
- return err
- }
- return nil
}
- return ErrNotALayer
+ if err = rcstore.Delete(id); err != nil {
+ return err
+ }
+ middleDir := s.graphDriverName + "-containers"
+ gcpath := filepath.Join(s.GraphRoot(), middleDir, container.ID)
+ if err = os.RemoveAll(gcpath); err != nil {
+ return err
+ }
+ rcpath := filepath.Join(s.RunRoot(), middleDir, container.ID)
+ if err = os.RemoveAll(rcpath); err != nil {
+ return err
+ }
+ return nil
}
}
return ErrNotAContainer
@@ -2279,10 +2280,14 @@ func (s *store) Version() ([][2]string, error) {
func (s *store) Mount(id, mountLabel string) (string, error) {
container, err := s.Container(id)
- var uidMap, gidMap []idtools.IDMap
+ var (
+ uidMap, gidMap []idtools.IDMap
+ mountOpts []string
+ )
if err == nil {
uidMap, gidMap = container.UIDMap, container.GIDMap
id = container.LayerID
+ mountOpts = container.MountOpts()
}
rlstore, err := s.LayerStore()
if err != nil {
@@ -2298,6 +2303,7 @@ func (s *store) Mount(id, mountLabel string) (string, error) {
MountLabel: mountLabel,
UidMaps: uidMap,
GidMaps: gidMap,
+ Options: mountOpts,
}
return rlstore.Mount(id, options)
}
@@ -3203,13 +3209,13 @@ func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) {
storeOptions.GIDMap = mappings.GIDs()
}
- uidmap, err := idtools.ParseIDMap(config.Storage.Options.RemapUIDs, "remap-uids")
+ uidmap, err := idtools.ParseIDMap([]string{config.Storage.Options.RemapUIDs}, "remap-uids")
if err != nil {
fmt.Print(err)
} else {
storeOptions.UIDMap = append(storeOptions.UIDMap, uidmap...)
}
- gidmap, err := idtools.ParseIDMap(config.Storage.Options.RemapGIDs, "remap-gids")
+ gidmap, err := idtools.ParseIDMap([]string{config.Storage.Options.RemapGIDs}, "remap-gids")
if err != nil {
fmt.Print(err)
} else {
@@ -3233,3 +3239,23 @@ func init() {
ReloadConfigurationFile(defaultConfigFile, &DefaultStoreOptions)
}
+
+func GetDefaultMountOptions() ([]string, error) {
+ mountOpts := []string{
+ ".mountopt",
+ fmt.Sprintf("%s.mountopt", DefaultStoreOptions.GraphDriverName),
+ }
+ for _, option := range DefaultStoreOptions.GraphDriverOptions {
+ key, val, err := parsers.ParseKeyValueOpt(option)
+ if err != nil {
+ return nil, err
+ }
+ key = strings.ToLower(key)
+ for _, m := range mountOpts {
+ if m == key {
+ return strings.Split(val, ","), nil
+ }
+ }
+ }
+ return nil, nil
+}