mirror of
https://github.com/containers/podman.git
synced 2025-06-27 05:26:50 +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:
@ -84,7 +84,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
|
|||||||
cgroupsFlagName := "cgroups"
|
cgroupsFlagName := "cgroups"
|
||||||
createFlags.StringVar(
|
createFlags.StringVar(
|
||||||
&cf.CGroupsMode,
|
&cf.CGroupsMode,
|
||||||
cgroupsFlagName, containerConfig.Cgroups(),
|
cgroupsFlagName, cgroupConfig(),
|
||||||
`control container cgroup configuration ("enabled"|"disabled"|"no-conmon"|"split")`,
|
`control container cgroup configuration ("enabled"|"disabled"|"no-conmon"|"split")`,
|
||||||
)
|
)
|
||||||
_ = cmd.RegisterFlagCompletionFunc(cgroupsFlagName, AutocompleteCgroupMode)
|
_ = cmd.RegisterFlagCompletionFunc(cgroupsFlagName, AutocompleteCgroupMode)
|
||||||
@ -180,7 +180,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
|
|||||||
deviceFlagName := "device"
|
deviceFlagName := "device"
|
||||||
createFlags.StringSliceVar(
|
createFlags.StringSliceVar(
|
||||||
&cf.Devices,
|
&cf.Devices,
|
||||||
deviceFlagName, containerConfig.Devices(),
|
deviceFlagName, devices(),
|
||||||
fmt.Sprintf("Add a host device to the container"),
|
fmt.Sprintf("Add a host device to the container"),
|
||||||
)
|
)
|
||||||
_ = cmd.RegisterFlagCompletionFunc(deviceFlagName, completion.AutocompleteDefault)
|
_ = cmd.RegisterFlagCompletionFunc(deviceFlagName, completion.AutocompleteDefault)
|
||||||
@ -238,7 +238,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
|
|||||||
|
|
||||||
envFlagName := "env"
|
envFlagName := "env"
|
||||||
createFlags.StringArrayP(
|
createFlags.StringArrayP(
|
||||||
envFlagName, "e", containerConfig.Env(),
|
envFlagName, "e", env(),
|
||||||
"Set environment variables in container",
|
"Set environment variables in container",
|
||||||
)
|
)
|
||||||
_ = cmd.RegisterFlagCompletionFunc(envFlagName, completion.AutocompleteNone)
|
_ = cmd.RegisterFlagCompletionFunc(envFlagName, completion.AutocompleteNone)
|
||||||
@ -357,7 +357,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
|
|||||||
initPathFlagName := "init-path"
|
initPathFlagName := "init-path"
|
||||||
createFlags.StringVar(
|
createFlags.StringVar(
|
||||||
&cf.InitPath,
|
&cf.InitPath,
|
||||||
initPathFlagName, containerConfig.InitPath(),
|
initPathFlagName, initPath(),
|
||||||
// Do not use the Value field for setting the default value to determine user input (i.e., non-empty string)
|
// Do not use the Value field for setting the default value to determine user input (i.e., non-empty string)
|
||||||
fmt.Sprintf("Path to the container-init binary"),
|
fmt.Sprintf("Path to the container-init binary"),
|
||||||
)
|
)
|
||||||
@ -508,7 +508,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
|
|||||||
|
|
||||||
pidsLimitFlagName := "pids-limit"
|
pidsLimitFlagName := "pids-limit"
|
||||||
createFlags.Int64(
|
createFlags.Int64(
|
||||||
pidsLimitFlagName, containerConfig.PidsLimit(),
|
pidsLimitFlagName, pidsLimit(),
|
||||||
"Tune container pids limit (set 0 for unlimited, -1 for server defaults)",
|
"Tune container pids limit (set 0 for unlimited, -1 for server defaults)",
|
||||||
)
|
)
|
||||||
_ = cmd.RegisterFlagCompletionFunc(pidsLimitFlagName, completion.AutocompleteNone)
|
_ = cmd.RegisterFlagCompletionFunc(pidsLimitFlagName, completion.AutocompleteNone)
|
||||||
@ -543,7 +543,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
|
|||||||
pullFlagName := "pull"
|
pullFlagName := "pull"
|
||||||
createFlags.StringVar(
|
createFlags.StringVar(
|
||||||
&cf.Pull,
|
&cf.Pull,
|
||||||
pullFlagName, containerConfig.Engine.PullPolicy,
|
pullFlagName, policy(),
|
||||||
`Pull image before creating ("always"|"missing"|"never")`,
|
`Pull image before creating ("always"|"missing"|"never")`,
|
||||||
)
|
)
|
||||||
_ = cmd.RegisterFlagCompletionFunc(pullFlagName, AutocompletePullOption)
|
_ = cmd.RegisterFlagCompletionFunc(pullFlagName, AutocompletePullOption)
|
||||||
@ -606,7 +606,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
|
|||||||
|
|
||||||
shmSizeFlagName := "shm-size"
|
shmSizeFlagName := "shm-size"
|
||||||
createFlags.String(
|
createFlags.String(
|
||||||
shmSizeFlagName, containerConfig.ShmSize(),
|
shmSizeFlagName, shmSize(),
|
||||||
"Size of /dev/shm "+sizeWithUnitFormat,
|
"Size of /dev/shm "+sizeWithUnitFormat,
|
||||||
)
|
)
|
||||||
_ = cmd.RegisterFlagCompletionFunc(shmSizeFlagName, completion.AutocompleteNone)
|
_ = cmd.RegisterFlagCompletionFunc(shmSizeFlagName, completion.AutocompleteNone)
|
||||||
@ -715,7 +715,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
|
|||||||
ulimitFlagName := "ulimit"
|
ulimitFlagName := "ulimit"
|
||||||
createFlags.StringSliceVar(
|
createFlags.StringSliceVar(
|
||||||
&cf.Ulimit,
|
&cf.Ulimit,
|
||||||
ulimitFlagName, containerConfig.Ulimits(),
|
ulimitFlagName, ulimits(),
|
||||||
"Ulimit options",
|
"Ulimit options",
|
||||||
)
|
)
|
||||||
_ = cmd.RegisterFlagCompletionFunc(ulimitFlagName, completion.AutocompleteNone)
|
_ = cmd.RegisterFlagCompletionFunc(ulimitFlagName, completion.AutocompleteNone)
|
||||||
@ -753,7 +753,7 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
|
|||||||
volumeFlagName := "volume"
|
volumeFlagName := "volume"
|
||||||
createFlags.StringArrayVarP(
|
createFlags.StringArrayVarP(
|
||||||
&cf.Volume,
|
&cf.Volume,
|
||||||
volumeFlagName, "v", containerConfig.Volumes(),
|
volumeFlagName, "v", volumes(),
|
||||||
"Bind mount a volume into the container",
|
"Bind mount a volume into the container",
|
||||||
)
|
)
|
||||||
_ = cmd.RegisterFlagCompletionFunc(volumeFlagName, AutocompleteVolumeFlag)
|
_ = cmd.RegisterFlagCompletionFunc(volumeFlagName, AutocompleteVolumeFlag)
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containers/podman/v2/cmd/podman/registry"
|
||||||
"github.com/containers/podman/v2/pkg/api/handlers"
|
"github.com/containers/podman/v2/pkg/api/handlers"
|
||||||
"github.com/containers/podman/v2/pkg/cgroups"
|
"github.com/containers/podman/v2/pkg/cgroups"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
@ -440,3 +441,66 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup
|
|||||||
cmd = append(cmd, cc.Config.Cmd...)
|
cmd = append(cmd, cc.Config.Cmd...)
|
||||||
return &cliOpts, cmd, nil
|
return &cliOpts, cmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ulimits() []string {
|
||||||
|
if !registry.IsRemote() {
|
||||||
|
return containerConfig.Ulimits()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cgroupConfig() string {
|
||||||
|
if !registry.IsRemote() {
|
||||||
|
return containerConfig.Cgroups()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func devices() []string {
|
||||||
|
if !registry.IsRemote() {
|
||||||
|
return containerConfig.Devices()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func env() []string {
|
||||||
|
if !registry.IsRemote() {
|
||||||
|
return containerConfig.Env()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func initPath() string {
|
||||||
|
if !registry.IsRemote() {
|
||||||
|
return containerConfig.InitPath()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func pidsLimit() int64 {
|
||||||
|
if !registry.IsRemote() {
|
||||||
|
return containerConfig.PidsLimit()
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func policy() string {
|
||||||
|
if !registry.IsRemote() {
|
||||||
|
return containerConfig.Engine.PullPolicy
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func shmSize() string {
|
||||||
|
if !registry.IsRemote() {
|
||||||
|
return containerConfig.ShmSize()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func volumes() []string {
|
||||||
|
if !registry.IsRemote() {
|
||||||
|
return containerConfig.Volumes()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/containers/podman/v2/pkg/util"
|
"github.com/containers/podman/v2/pkg/util"
|
||||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -45,7 +44,7 @@ func parseVolumes(volumeFlag, mountFlag, tmpfsFlag []string, addReadOnlyTmpfs bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Next --volumes flag.
|
// Next --volumes flag.
|
||||||
volumeMounts, volumeVolumes, overlayVolumes, err := getVolumeMounts(volumeFlag)
|
volumeMounts, volumeVolumes, overlayVolumes, err := specgen.GenVolumeMounts(volumeFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
@ -594,105 +593,6 @@ func getImageVolume(args []string) (*specgen.ImageVolume, error) {
|
|||||||
return newVolume, nil
|
return newVolume, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*specgen.NamedVolume, map[string]*specgen.OverlayVolume, error) {
|
|
||||||
mounts := make(map[string]spec.Mount)
|
|
||||||
volumes := make(map[string]*specgen.NamedVolume)
|
|
||||||
overlayVolumes := make(map[string]*specgen.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(specgen.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: string(TypeBind),
|
|
||||||
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(specgen.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
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTmpfsMounts creates spec.Mount structs for user-requested tmpfs mounts
|
// GetTmpfsMounts creates spec.Mount structs for user-requested tmpfs mounts
|
||||||
func getTmpfsMounts(tmpfsFlag []string) (map[string]spec.Mount, error) {
|
func getTmpfsMounts(tmpfsFlag []string) (map[string]spec.Mount, error) {
|
||||||
m := make(map[string]spec.Mount)
|
m := make(map[string]spec.Mount)
|
||||||
|
@ -18,6 +18,10 @@ any point.
|
|||||||
|
|
||||||
The initial status of the container created with **podman create** is 'created'.
|
The initial status of the container created with **podman create** is 'created'.
|
||||||
|
|
||||||
|
Default settings for flags are defined in `containers.conf`. Most settings for
|
||||||
|
remote connections use the server's containers.conf, except when documented in
|
||||||
|
man pages.
|
||||||
|
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
#### **--add-host**=*host*
|
#### **--add-host**=*host*
|
||||||
|
|
||||||
@ -817,6 +821,7 @@ Signal to stop a container. Default is SIGTERM.
|
|||||||
#### **--stop-timeout**=*seconds*
|
#### **--stop-timeout**=*seconds*
|
||||||
|
|
||||||
Timeout (in seconds) to stop a container. Default is 10.
|
Timeout (in seconds) to stop a container. Default is 10.
|
||||||
|
Remote connections use local containers.conf for defaults
|
||||||
|
|
||||||
#### **--subgidname**=*name*
|
#### **--subgidname**=*name*
|
||||||
|
|
||||||
@ -893,10 +898,12 @@ standard input.
|
|||||||
#### **--tz**=*timezone*
|
#### **--tz**=*timezone*
|
||||||
|
|
||||||
Set timezone in container. This flag takes area-based timezones, GMT time, as well as `local`, which sets the timezone in the container to match the host machine. See `/usr/share/zoneinfo/` for valid timezones.
|
Set timezone in container. This flag takes area-based timezones, GMT time, as well as `local`, which sets the timezone in the container to match the host machine. See `/usr/share/zoneinfo/` for valid timezones.
|
||||||
|
Remote connections use local containers.conf for defaults
|
||||||
|
|
||||||
#### **--umask**=*umask*
|
#### **--umask**=*umask*
|
||||||
|
|
||||||
Set the umask inside the container. Defaults to `0022`.
|
Set the umask inside the container. Defaults to `0022`.
|
||||||
|
Remote connections use local containers.conf for defaults
|
||||||
|
|
||||||
#### **--uidmap**=*container_uid:host_uid:amount*
|
#### **--uidmap**=*container_uid:host_uid:amount*
|
||||||
|
|
||||||
|
@ -33,6 +33,10 @@ is located at _/run/.containerenv_.
|
|||||||
When running from a user defined network namespace, the _/etc/netns/NSNAME/resolv.conf_
|
When running from a user defined network namespace, the _/etc/netns/NSNAME/resolv.conf_
|
||||||
will be used if it exists, otherwise _/etc/resolv.conf_ will be used.
|
will be used if it exists, otherwise _/etc/resolv.conf_ will be used.
|
||||||
|
|
||||||
|
Default settings are defined in `containers.conf`. Most settings for remote
|
||||||
|
connections use the servers containers.conf, except when documented in man
|
||||||
|
pages.
|
||||||
|
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
#### **--add-host**=_host_:_ip_
|
#### **--add-host**=_host_:_ip_
|
||||||
|
|
||||||
@ -857,6 +861,7 @@ Signal to stop a container. Default is **SIGTERM**.
|
|||||||
#### **--stop-timeout**=*seconds*
|
#### **--stop-timeout**=*seconds*
|
||||||
|
|
||||||
Timeout to stop a container. Default is **10**.
|
Timeout to stop a container. Default is **10**.
|
||||||
|
Remote connections use local containers.conf for defaults
|
||||||
|
|
||||||
#### **--subgidname**=*name*
|
#### **--subgidname**=*name*
|
||||||
|
|
||||||
@ -952,10 +957,12 @@ standard input.
|
|||||||
#### **--tz**=*timezone*
|
#### **--tz**=*timezone*
|
||||||
|
|
||||||
Set timezone in container. This flag takes area-based timezones, GMT time, as well as `local`, which sets the timezone in the container to match the host machine. See `/usr/share/zoneinfo/` for valid timezones.
|
Set timezone in container. This flag takes area-based timezones, GMT time, as well as `local`, which sets the timezone in the container to match the host machine. See `/usr/share/zoneinfo/` for valid timezones.
|
||||||
|
Remote connections use local containers.conf for defaults
|
||||||
|
|
||||||
#### **--umask**=*umask*
|
#### **--umask**=*umask*
|
||||||
|
|
||||||
Set the umask inside the container. Defaults to `0022`.
|
Set the umask inside the container. Defaults to `0022`.
|
||||||
|
Remote connections use local containers.conf for defaults
|
||||||
|
|
||||||
#### **--uidmap**=*container_uid*:*host_uid*:*amount*
|
#### **--uidmap**=*container_uid*:*host_uid*:*amount*
|
||||||
|
|
||||||
|
@ -17,6 +17,10 @@ Podman uses Buildah(1) internally to create container images. Both tools share i
|
|||||||
(not container) storage, hence each can use or manipulate images (but not containers)
|
(not container) storage, hence each can use or manipulate images (but not containers)
|
||||||
created by the other.
|
created by the other.
|
||||||
|
|
||||||
|
Default settings for flags are defined in `containers.conf`. Most settings for
|
||||||
|
Remote connections use the server's containers.conf, except when documented in
|
||||||
|
man pages.
|
||||||
|
|
||||||
**podman [GLOBAL OPTIONS]**
|
**podman [GLOBAL OPTIONS]**
|
||||||
|
|
||||||
## GLOBAL OPTIONS
|
## GLOBAL OPTIONS
|
||||||
@ -33,6 +37,7 @@ Path of the configuration directory for CNI networks. (Default: `/etc/cni/net.d
|
|||||||
|
|
||||||
#### **--connection**, **-c**
|
#### **--connection**, **-c**
|
||||||
Connection to use for remote podman (Default connection is configured in `containers.conf`)
|
Connection to use for remote podman (Default connection is configured in `containers.conf`)
|
||||||
|
Remote connections use local containers.conf for default.
|
||||||
|
|
||||||
#### **--conmon**
|
#### **--conmon**
|
||||||
Path of the conmon binary (Default path is configured in `containers.conf`)
|
Path of the conmon binary (Default path is configured in `containers.conf`)
|
||||||
@ -71,6 +76,7 @@ Identity value resolution precedence:
|
|||||||
- command line value
|
- command line value
|
||||||
- environment variable `CONTAINER_SSHKEY`, if `CONTAINER_HOST` is found
|
- environment variable `CONTAINER_SSHKEY`, if `CONTAINER_HOST` is found
|
||||||
- `containers.conf`
|
- `containers.conf`
|
||||||
|
Remote connections use local containers.conf for default.
|
||||||
|
|
||||||
#### **--log-level**=*level*
|
#### **--log-level**=*level*
|
||||||
|
|
||||||
@ -86,6 +92,7 @@ Path to the command binary to use for setting up a network. It is currently onl
|
|||||||
|
|
||||||
#### **--remote**, **-r**
|
#### **--remote**, **-r**
|
||||||
Access Podman service will be remote
|
Access Podman service will be remote
|
||||||
|
Remote connections use local containers.conf for default.
|
||||||
|
|
||||||
#### **--url**=*value*
|
#### **--url**=*value*
|
||||||
URL to access Podman service (default from `containers.conf`, rootless `unix://run/user/$UID/podman/podman.sock` or as root `unix://run/podman/podman.sock`).
|
URL to access Podman service (default from `containers.conf`, rootless `unix://run/user/$UID/podman/podman.sock` or as root `unix://run/podman/podman.sock`).
|
||||||
@ -104,6 +111,7 @@ URL value resolution precedence:
|
|||||||
- environment variable `CONTAINER_HOST`
|
- environment variable `CONTAINER_HOST`
|
||||||
- `containers.conf`
|
- `containers.conf`
|
||||||
- `unix://run/podman/podman.sock`
|
- `unix://run/podman/podman.sock`
|
||||||
|
Remote connections use local containers.conf for default.
|
||||||
|
|
||||||
#### **--root**=*value*
|
#### **--root**=*value*
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
|||||||
return nil, errors.Wrap(err, "invalid config provided")
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
|||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
|
|||||||
return rt.NewContainer(ctx, runtimeSpec, options...)
|
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 options []libpod.CtrCreateOption
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
|
|||||||
for _, volume := range volumes {
|
for _, volume := range volumes {
|
||||||
destinations = append(destinations, volume.Dest)
|
destinations = append(destinations, volume.Dest)
|
||||||
}
|
}
|
||||||
for _, overlayVolume := range s.OverlayVolumes {
|
for _, overlayVolume := range overlays {
|
||||||
destinations = append(destinations, overlayVolume.Destination)
|
destinations = append(destinations, overlayVolume.Destination)
|
||||||
}
|
}
|
||||||
for _, imageVolume := range s.ImageVolumes {
|
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))
|
options = append(options, libpod.WithNamedVolumes(vols))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.OverlayVolumes) != 0 {
|
if len(overlays) != 0 {
|
||||||
var vols []*libpod.ContainerOverlayVolume
|
var vols []*libpod.ContainerOverlayVolume
|
||||||
for _, v := range s.OverlayVolumes {
|
for _, v := range overlays {
|
||||||
vols = append(vols, &libpod.ContainerOverlayVolume{
|
vols = append(vols, &libpod.ContainerOverlayVolume{
|
||||||
Dest: v.Destination,
|
Dest: v.Destination,
|
||||||
Source: v.Source,
|
Source: v.Source,
|
||||||
|
@ -33,17 +33,17 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Produce final mounts and named volumes for a container
|
// 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
|
// Get image volumes
|
||||||
baseMounts, baseVolumes, err := getImageVolumes(ctx, img, s)
|
baseMounts, baseVolumes, err := getImageVolumes(ctx, img, s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get volumes-from mounts
|
// Get volumes-from mounts
|
||||||
volFromMounts, volFromVolumes, err := getVolumesFrom(s.VolumesFrom, rt)
|
volFromMounts, volFromVolumes, err := getVolumesFrom(s.VolumesFrom, rt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Supersede from --volumes-from.
|
// 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.
|
// Need to make map forms of specgen mounts/volumes.
|
||||||
unifiedMounts := map[string]spec.Mount{}
|
unifiedMounts := map[string]spec.Mount{}
|
||||||
unifiedVolumes := map[string]*specgen.NamedVolume{}
|
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 {
|
for _, m := range s.Mounts {
|
||||||
if _, ok := unifiedMounts[m.Destination]; ok {
|
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
|
unifiedMounts[m.Destination] = m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, m := range commonMounts {
|
||||||
|
if _, ok := unifiedMounts[m.Destination]; !ok {
|
||||||
|
unifiedMounts[m.Destination] = m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, v := range s.Volumes {
|
for _, v := range s.Volumes {
|
||||||
if _, ok := unifiedVolumes[v.Dest]; ok {
|
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
|
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 requested, add container init binary
|
||||||
if s.Init {
|
if s.Init {
|
||||||
initPath := s.InitPath
|
initPath := s.InitPath
|
||||||
@ -78,10 +112,10 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
|
|||||||
}
|
}
|
||||||
initMount, err := addContainerInitBinary(s, initPath)
|
initMount, err := addContainerInitBinary(s, initPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
if _, ok := unifiedMounts[initMount.Destination]; ok {
|
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
|
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
|
// Check for conflicts between named volumes and mounts
|
||||||
for dest := range baseMounts {
|
for dest := range baseMounts {
|
||||||
if _, ok := baseVolumes[dest]; ok {
|
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 {
|
for dest := range baseVolumes {
|
||||||
if _, ok := baseMounts[dest]; ok {
|
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
|
// Final step: maps to arrays
|
||||||
@ -129,7 +163,7 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
|
|||||||
if mount.Type == TypeBind {
|
if mount.Type == TypeBind {
|
||||||
absSrc, err := filepath.Abs(mount.Source)
|
absSrc, err := filepath.Abs(mount.Source)
|
||||||
if err != nil {
|
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
|
mount.Source = absSrc
|
||||||
}
|
}
|
||||||
@ -140,7 +174,12 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
|
|||||||
finalVolumes = append(finalVolumes, volume)
|
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
|
// Get image volumes from the given image
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package specgen
|
package specgen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net"
|
"net"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/containers/image/v5/manifest"
|
"github.com/containers/image/v5/manifest"
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LogConfig describes the logging characteristics for a container
|
// LogConfig describes the logging characteristics for a container
|
||||||
@ -459,42 +459,6 @@ type SpecGenerator struct {
|
|||||||
ContainerHealthCheckConfig
|
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.
|
// PortMapping is one or more ports that will be mapped into the container.
|
||||||
type PortMapping struct {
|
type PortMapping struct {
|
||||||
// HostIP is the IP that we will bind to on the host.
|
// 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
|
||||||
|
}
|
51
test/e2e/config/containers-remote.conf
Normal file
51
test/e2e/config/containers-remote.conf
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
[containers]
|
||||||
|
|
||||||
|
# A list of ulimits to be set in containers by default, specified as
|
||||||
|
# "<ulimit name>=<soft limit>:<hard limit>", for example:
|
||||||
|
# "nofile=1024:2048"
|
||||||
|
# See setrlimit(2) for a list of resource names.
|
||||||
|
# Any limit not specified here will be inherited from the process launching the
|
||||||
|
# container engine.
|
||||||
|
# Ulimits has limits for non privileged container engines.
|
||||||
|
#
|
||||||
|
default_ulimits = [
|
||||||
|
"nofile=100:100",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Environment variable list for the conmon process; used for passing necessary
|
||||||
|
# environment variables to conmon or the runtime.
|
||||||
|
#
|
||||||
|
env = [
|
||||||
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||||
|
"foo=bar1",
|
||||||
|
]
|
||||||
|
|
||||||
|
# container engines use container separation using MAC(SELinux) labeling.
|
||||||
|
# Flag is ignored on label disabled systems.
|
||||||
|
#
|
||||||
|
label = false
|
||||||
|
|
||||||
|
# Size of /dev/shm. Specified as <number><unit>.
|
||||||
|
# Unit is optional, values:
|
||||||
|
# b (bytes), k (kilobytes), m (megabytes), or g (gigabytes).
|
||||||
|
# If the unit is omitted, the system uses bytes.
|
||||||
|
#
|
||||||
|
shm_size = "202k"
|
||||||
|
|
||||||
|
# List of devices. Specified as
|
||||||
|
# "<device-on-host>:<device-on-container>:<permissions>", for example:
|
||||||
|
# "/dev/sdc:/dev/xvdc:rwm".
|
||||||
|
# If it is empty or commented out, only the default devices will be used
|
||||||
|
#
|
||||||
|
devices = []
|
||||||
|
|
||||||
|
default_sysctls = [
|
||||||
|
"net.ipv4.ping_group_range=0 0",
|
||||||
|
]
|
||||||
|
|
||||||
|
dns_searches=[ "barfoo.com", ]
|
||||||
|
dns_servers=[ "4.3.2.1", ]
|
||||||
|
|
||||||
|
tz = "America/New_York"
|
||||||
|
|
||||||
|
umask = "0022"
|
@ -177,6 +177,9 @@ var _ = Describe("Podman run", func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
os.Setenv("CONTAINERS_CONF", conffile)
|
os.Setenv("CONTAINERS_CONF", conffile)
|
||||||
|
if IsRemote() {
|
||||||
|
podmanTest.RestartRemoteService()
|
||||||
|
}
|
||||||
result := podmanTest.Podman([]string{"run", ALPINE, "ls", tempdir})
|
result := podmanTest.Podman([]string{"run", ALPINE, "ls", tempdir})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result.ExitCode()).To(Equal(0))
|
Expect(result.ExitCode()).To(Equal(0))
|
||||||
@ -224,6 +227,17 @@ var _ = Describe("Podman run", func() {
|
|||||||
Expect(session.LineInOuputStartsWith("search")).To(BeFalse())
|
Expect(session.LineInOuputStartsWith("search")).To(BeFalse())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman run use containers.conf search domain", func() {
|
||||||
|
session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.LineInOuputStartsWith("search")).To(BeTrue())
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("foobar.com"))
|
||||||
|
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("1.2.3.4"))
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("debug"))
|
||||||
|
})
|
||||||
|
|
||||||
It("podman run containers.conf timezone", func() {
|
It("podman run containers.conf timezone", func() {
|
||||||
//containers.conf timezone set to Pacific/Honolulu
|
//containers.conf timezone set to Pacific/Honolulu
|
||||||
session := podmanTest.Podman([]string{"run", ALPINE, "date", "+'%H %Z'"})
|
session := podmanTest.Podman([]string{"run", ALPINE, "date", "+'%H %Z'"})
|
||||||
@ -231,6 +245,7 @@ var _ = Describe("Podman run", func() {
|
|||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
Expect(session.OutputToString()).To(ContainSubstring("HST"))
|
Expect(session.OutputToString()).To(ContainSubstring("HST"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman run containers.conf umask", func() {
|
It("podman run containers.conf umask", func() {
|
||||||
//containers.conf umask set to 0002
|
//containers.conf umask set to 0002
|
||||||
if !strings.Contains(podmanTest.OCIRuntime, "crun") {
|
if !strings.Contains(podmanTest.OCIRuntime, "crun") {
|
||||||
@ -243,4 +258,57 @@ var _ = Describe("Podman run", func() {
|
|||||||
Expect(session.OutputToString()).To(Equal("0002"))
|
Expect(session.OutputToString()).To(Equal("0002"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman-remote test localcontainers.conf versus remote containers.conf", func() {
|
||||||
|
if !IsRemote() {
|
||||||
|
Skip("this test is only for remote")
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Setenv("CONTAINERS_CONF", "config/containers-remote.conf")
|
||||||
|
// Configuration that comes from remote server
|
||||||
|
// env
|
||||||
|
session := podmanTest.Podman([]string{"run", ALPINE, "printenv", "foo"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.OutputToString()).To(Equal("bar"))
|
||||||
|
|
||||||
|
// dns-search, server, options
|
||||||
|
session = podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.LineInOuputStartsWith("search")).To(BeTrue())
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("foobar.com"))
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("1.2.3.4"))
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("debug"))
|
||||||
|
|
||||||
|
// sysctls
|
||||||
|
session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/proc/sys/net/ipv4/ping_group_range"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("1000"))
|
||||||
|
|
||||||
|
// shm-size
|
||||||
|
session = podmanTest.Podman([]string{"run", ALPINE, "grep", "shm", "/proc/self/mounts"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("size=200k"))
|
||||||
|
|
||||||
|
// ulimits
|
||||||
|
session = podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("500"))
|
||||||
|
|
||||||
|
// Configuration that comes from remote client
|
||||||
|
// Timezone
|
||||||
|
session = podmanTest.Podman([]string{"run", ALPINE, "date", "+'%H %Z'"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("EST"))
|
||||||
|
|
||||||
|
// Umask
|
||||||
|
session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "sh", "-c", "umask"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(session.OutputToString()).To(Equal("0022"))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user