From 977094781841f57c82b71e3ccc32dad952a8c0e5 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Wed, 18 Nov 2020 16:51:33 -0500 Subject: Document containers.conf settings for remote connections Currently we don't document which end of the podman-remote client server operations uses the containers.conf. This PR begins documenting this and then testing to make sure the defaults follow the rules. Fixes: https://github.com/containers/podman/issues/7657 Signed-off-by: Daniel J Walsh --- pkg/specgen/volumes.go | 149 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 pkg/specgen/volumes.go (limited to 'pkg/specgen/volumes.go') diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go new file mode 100644 index 000000000..1178f9960 --- /dev/null +++ b/pkg/specgen/volumes.go @@ -0,0 +1,149 @@ +package specgen + +import ( + "path/filepath" + "strings" + + "github.com/containers/buildah/pkg/parse" + spec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +// NamedVolume holds information about a named volume that will be mounted into +// the container. +type NamedVolume struct { + // Name is the name of the named volume to be mounted. May be empty. + // If empty, a new named volume with a pseudorandomly generated name + // will be mounted at the given destination. + Name string + // Destination to mount the named volume within the container. Must be + // an absolute path. Path will be created if it does not exist. + Dest string + // Options are options that the named volume will be mounted with. + Options []string +} + +// OverlayVolume holds information about a overlay volume that will be mounted into +// the container. +type OverlayVolume struct { + // Destination is the absolute path where the mount will be placed in the container. + Destination string `json:"destination"` + // Source specifies the source path of the mount. + Source string `json:"source,omitempty"` +} + +// ImageVolume is a volume based on a container image. The container image is +// first mounted on the host and is then bind-mounted into the container. An +// ImageVolume is always mounted read only. +type ImageVolume struct { + // Source is the source of the image volume. The image can be referred + // to by name and by ID. + Source string + // Destination is the absolute path of the mount in the container. + Destination string + // ReadWrite sets the volume writable. + ReadWrite bool +} + +// GenVolumeMounts parses user input into mounts, volumes and overlay volumes +func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*NamedVolume, map[string]*OverlayVolume, error) { + errDuplicateDest := errors.Errorf("duplicate mount destination") + + mounts := make(map[string]spec.Mount) + volumes := make(map[string]*NamedVolume) + overlayVolumes := make(map[string]*OverlayVolume) + + volumeFormatErr := errors.Errorf("incorrect volume format, should be [host-dir:]ctr-dir[:option]") + + for _, vol := range volumeFlag { + var ( + options []string + src string + dest string + err error + ) + + splitVol := strings.Split(vol, ":") + if len(splitVol) > 3 { + return nil, nil, nil, errors.Wrapf(volumeFormatErr, vol) + } + + src = splitVol[0] + if len(splitVol) == 1 { + // This is an anonymous named volume. Only thing given + // is destination. + // Name/source will be blank, and populated by libpod. + src = "" + dest = splitVol[0] + } else if len(splitVol) > 1 { + dest = splitVol[1] + } + if len(splitVol) > 2 { + if options, err = parse.ValidateVolumeOpts(strings.Split(splitVol[2], ",")); err != nil { + return nil, nil, nil, err + } + } + + // Do not check source dir for anonymous volumes + if len(splitVol) > 1 { + if err := parse.ValidateVolumeHostDir(src); err != nil { + return nil, nil, nil, err + } + } + if err := parse.ValidateVolumeCtrDir(dest); err != nil { + return nil, nil, nil, err + } + + cleanDest := filepath.Clean(dest) + + if strings.HasPrefix(src, "/") || strings.HasPrefix(src, ".") { + // This is not a named volume + overlayFlag := false + for _, o := range options { + if o == "O" { + overlayFlag = true + if len(options) > 1 { + return nil, nil, nil, errors.New("can't use 'O' with other options") + } + } + } + if overlayFlag { + // This is a overlay volume + newOverlayVol := new(OverlayVolume) + newOverlayVol.Destination = cleanDest + newOverlayVol.Source = src + if _, ok := overlayVolumes[newOverlayVol.Destination]; ok { + return nil, nil, nil, errors.Wrapf(errDuplicateDest, newOverlayVol.Destination) + } + overlayVolumes[newOverlayVol.Destination] = newOverlayVol + } else { + newMount := spec.Mount{ + Destination: cleanDest, + Type: "bind", + Source: src, + Options: options, + } + if _, ok := mounts[newMount.Destination]; ok { + return nil, nil, nil, errors.Wrapf(errDuplicateDest, newMount.Destination) + } + mounts[newMount.Destination] = newMount + } + } else { + // This is a named volume + newNamedVol := new(NamedVolume) + newNamedVol.Name = src + newNamedVol.Dest = cleanDest + newNamedVol.Options = options + + if _, ok := volumes[newNamedVol.Dest]; ok { + return nil, nil, nil, errors.Wrapf(errDuplicateDest, newNamedVol.Dest) + } + volumes[newNamedVol.Dest] = newNamedVol + } + + logrus.Debugf("User mount %s:%s options %v", src, dest, options) + } + + return mounts, volumes, overlayVolumes, nil +} -- cgit v1.2.3-54-g00ecf From f7f85fef7c7086a39e57eb36e875209bb9553f4e Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Wed, 25 Nov 2020 16:43:53 +0100 Subject: Do not validate the volume source path in specgen The volume src path should not be validated in specgen since the remote client also uses that part and the path must only exists on the server. This now fails later and only on the server and not the client. I don't think I can add a test for this because the CI runs server and client always on the same vm. Fixes #8473 Signed-off-by: Paul Holzinger --- cmd/podman/common/volumes.go | 4 ++-- pkg/specgen/volumes.go | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'pkg/specgen/volumes.go') diff --git a/cmd/podman/common/volumes.go b/cmd/podman/common/volumes.go index 0468f15e0..dfbb7b1b2 100644 --- a/cmd/podman/common/volumes.go +++ b/cmd/podman/common/volumes.go @@ -323,8 +323,8 @@ func getBindMount(args []string) (spec.Mount, error) { if len(kv) == 1 { return newMount, errors.Wrapf(optionArgError, kv[0]) } - if err := parse.ValidateVolumeHostDir(kv[1]); err != nil { - return newMount, err + if len(kv[1]) == 0 { + return newMount, errors.Wrapf(optionArgError, "host directory cannot be empty") } newMount.Source = kv[1] setSource = true diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go index 1178f9960..41efee3b3 100644 --- a/pkg/specgen/volumes.go +++ b/pkg/specgen/volumes.go @@ -84,11 +84,10 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na return nil, nil, nil, err } } - // Do not check source dir for anonymous volumes if len(splitVol) > 1 { - if err := parse.ValidateVolumeHostDir(src); err != nil { - return nil, nil, nil, err + if len(src) == 0 { + return nil, nil, nil, errors.New("host directory cannot be empty") } } if err := parse.ValidateVolumeCtrDir(dest); err != nil { -- cgit v1.2.3-54-g00ecf