mirror of
https://github.com/containers/podman.git
synced 2025-06-26 21:07:02 +08:00
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 <dwalsh@redhat.com>
This commit is contained in:
@ -111,7 +111,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
||||
return nil, errors.Wrap(err, "invalid config provided")
|
||||
}
|
||||
|
||||
finalMounts, finalVolumes, err := finalizeMounts(ctx, s, rt, rtc, newImage)
|
||||
finalMounts, finalVolumes, finalOverlays, err := finalizeMounts(ctx, s, rt, rtc, newImage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -121,7 +121,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opts, err := createContainerOptions(ctx, rt, s, pod, finalVolumes, newImage, command)
|
||||
opts, err := createContainerOptions(ctx, rt, s, pod, finalVolumes, finalOverlays, newImage, command)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -144,7 +144,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
||||
return rt.NewContainer(ctx, runtimeSpec, options...)
|
||||
}
|
||||
|
||||
func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator, pod *libpod.Pod, volumes []*specgen.NamedVolume, img *image.Image, command []string) ([]libpod.CtrCreateOption, error) {
|
||||
func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator, pod *libpod.Pod, volumes []*specgen.NamedVolume, overlays []*specgen.OverlayVolume, img *image.Image, command []string) ([]libpod.CtrCreateOption, error) {
|
||||
var options []libpod.CtrCreateOption
|
||||
var err error
|
||||
|
||||
@ -224,7 +224,7 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
|
||||
for _, volume := range volumes {
|
||||
destinations = append(destinations, volume.Dest)
|
||||
}
|
||||
for _, overlayVolume := range s.OverlayVolumes {
|
||||
for _, overlayVolume := range overlays {
|
||||
destinations = append(destinations, overlayVolume.Destination)
|
||||
}
|
||||
for _, imageVolume := range s.ImageVolumes {
|
||||
@ -244,9 +244,9 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
|
||||
options = append(options, libpod.WithNamedVolumes(vols))
|
||||
}
|
||||
|
||||
if len(s.OverlayVolumes) != 0 {
|
||||
if len(overlays) != 0 {
|
||||
var vols []*libpod.ContainerOverlayVolume
|
||||
for _, v := range s.OverlayVolumes {
|
||||
for _, v := range overlays {
|
||||
vols = append(vols, &libpod.ContainerOverlayVolume{
|
||||
Dest: v.Destination,
|
||||
Source: v.Source,
|
||||
|
@ -33,17 +33,17 @@ var (
|
||||
)
|
||||
|
||||
// Produce final mounts and named volumes for a container
|
||||
func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, img *image.Image) ([]spec.Mount, []*specgen.NamedVolume, error) {
|
||||
func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, rtc *config.Config, img *image.Image) ([]spec.Mount, []*specgen.NamedVolume, []*specgen.OverlayVolume, error) {
|
||||
// Get image volumes
|
||||
baseMounts, baseVolumes, err := getImageVolumes(ctx, img, s)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
// Get volumes-from mounts
|
||||
volFromMounts, volFromVolumes, err := getVolumesFrom(s.VolumesFrom, rt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
// Supersede from --volumes-from.
|
||||
@ -57,19 +57,53 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
|
||||
// Need to make map forms of specgen mounts/volumes.
|
||||
unifiedMounts := map[string]spec.Mount{}
|
||||
unifiedVolumes := map[string]*specgen.NamedVolume{}
|
||||
unifiedOverlays := map[string]*specgen.OverlayVolume{}
|
||||
|
||||
// Need to make map forms of specgen mounts/volumes.
|
||||
commonMounts, commonVolumes, commonOverlayVolumes, err := specgen.GenVolumeMounts(rtc.Volumes())
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
for _, m := range s.Mounts {
|
||||
if _, ok := unifiedMounts[m.Destination]; ok {
|
||||
return nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified mounts - multiple mounts at %q", m.Destination)
|
||||
return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified mounts - multiple mounts at %q", m.Destination)
|
||||
}
|
||||
unifiedMounts[m.Destination] = m
|
||||
}
|
||||
|
||||
for _, m := range commonMounts {
|
||||
if _, ok := unifiedMounts[m.Destination]; !ok {
|
||||
unifiedMounts[m.Destination] = m
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range s.Volumes {
|
||||
if _, ok := unifiedVolumes[v.Dest]; ok {
|
||||
return nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Dest)
|
||||
return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Dest)
|
||||
}
|
||||
unifiedVolumes[v.Dest] = v
|
||||
}
|
||||
|
||||
for _, v := range commonVolumes {
|
||||
if _, ok := unifiedVolumes[v.Dest]; !ok {
|
||||
unifiedVolumes[v.Dest] = v
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range s.OverlayVolumes {
|
||||
if _, ok := unifiedOverlays[v.Destination]; ok {
|
||||
return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Destination)
|
||||
}
|
||||
unifiedOverlays[v.Destination] = v
|
||||
}
|
||||
|
||||
for _, v := range commonOverlayVolumes {
|
||||
if _, ok := unifiedOverlays[v.Destination]; ok {
|
||||
unifiedOverlays[v.Destination] = v
|
||||
}
|
||||
}
|
||||
|
||||
// If requested, add container init binary
|
||||
if s.Init {
|
||||
initPath := s.InitPath
|
||||
@ -78,10 +112,10 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
|
||||
}
|
||||
initMount, err := addContainerInitBinary(s, initPath)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if _, ok := unifiedMounts[initMount.Destination]; ok {
|
||||
return nil, nil, errors.Wrapf(errDuplicateDest, "conflict with mount added by --init to %q", initMount.Destination)
|
||||
return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict with mount added by --init to %q", initMount.Destination)
|
||||
}
|
||||
unifiedMounts[initMount.Destination] = initMount
|
||||
}
|
||||
@ -115,12 +149,12 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
|
||||
// Check for conflicts between named volumes and mounts
|
||||
for dest := range baseMounts {
|
||||
if _, ok := baseVolumes[dest]; ok {
|
||||
return nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest)
|
||||
return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest)
|
||||
}
|
||||
}
|
||||
for dest := range baseVolumes {
|
||||
if _, ok := baseMounts[dest]; ok {
|
||||
return nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest)
|
||||
return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict at mount destination %v", dest)
|
||||
}
|
||||
}
|
||||
// Final step: maps to arrays
|
||||
@ -129,7 +163,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
|
||||
if mount.Type == TypeBind {
|
||||
absSrc, err := filepath.Abs(mount.Source)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source)
|
||||
return nil, nil, nil, errors.Wrapf(err, "error getting absolute path of %s", mount.Source)
|
||||
}
|
||||
mount.Source = absSrc
|
||||
}
|
||||
@ -140,7 +174,12 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
|
||||
finalVolumes = append(finalVolumes, volume)
|
||||
}
|
||||
|
||||
return finalMounts, finalVolumes, nil
|
||||
finalOverlays := make([]*specgen.OverlayVolume, 0, len(unifiedOverlays))
|
||||
for _, volume := range unifiedOverlays {
|
||||
finalOverlays = append(finalOverlays, volume)
|
||||
}
|
||||
|
||||
return finalMounts, finalVolumes, finalOverlays, nil
|
||||
}
|
||||
|
||||
// Get image volumes from the given image
|
||||
|
@ -1,13 +1,13 @@
|
||||
package specgen
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/storage"
|
||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// LogConfig describes the logging characteristics for a container
|
||||
@ -459,42 +459,6 @@ type SpecGenerator struct {
|
||||
ContainerHealthCheckConfig
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// PortMapping is one or more ports that will be mapped into the container.
|
||||
type PortMapping struct {
|
||||
// HostIP is the IP that we will bind to on the host.
|
||||
|
149
pkg/specgen/volumes.go
Normal file
149
pkg/specgen/volumes.go
Normal file
@ -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
|
||||
}
|
Reference in New Issue
Block a user