2017-11-01 15:24:59 +00:00
package libpod
import (
2018-01-19 14:51:59 +00:00
"net"
2018-04-26 15:21:48 +00:00
"os"
2017-11-29 17:58:42 +00:00
"path/filepath"
2020-06-19 13:29:34 +00:00
"strings"
2017-12-19 19:41:23 +00:00
"syscall"
2017-11-01 15:24:59 +00:00
2021-06-18 21:27:39 +00:00
"github.com/containers/buildah/pkg/parse"
2020-03-27 14:13:51 +00:00
"github.com/containers/common/pkg/config"
2021-01-15 06:27:23 +00:00
"github.com/containers/common/pkg/secrets"
2019-10-24 14:37:22 +00:00
"github.com/containers/image/v5/manifest"
2020-05-13 11:44:29 +00:00
"github.com/containers/image/v5/types"
2021-02-20 13:28:38 +00:00
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/pkg/namespaces"
"github.com/containers/podman/v3/pkg/rootless"
2021-07-07 21:00:30 +00:00
"github.com/containers/podman/v3/pkg/specgen"
2021-02-20 13:28:38 +00:00
"github.com/containers/podman/v3/pkg/util"
2017-11-01 15:24:59 +00:00
"github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
2017-12-05 22:50:29 +00:00
"github.com/cri-o/ocicni/pkg/ocicni"
2021-06-17 21:36:35 +00:00
"github.com/opencontainers/runtime-spec/specs-go"
2020-09-09 22:19:39 +00:00
"github.com/opencontainers/runtime-tools/generate"
2017-11-01 15:24:59 +00:00
"github.com/pkg/errors"
2020-05-13 11:44:29 +00:00
"github.com/sirupsen/logrus"
2017-11-01 15:24:59 +00:00
)
// Runtime Creation Options
2020-06-19 13:29:34 +00:00
var (
// SdNotifyModeValues describes the only values that SdNotifyMode can be
SdNotifyModeValues = [ ] string { define . SdNotifyModeContainer , define . SdNotifyModeConmon , define . SdNotifyModeIgnore }
)
2017-11-01 15:24:59 +00:00
2018-04-30 16:12:09 +00:00
// WithStorageConfig uses the given configuration to set up container storage.
2017-11-01 15:24:59 +00:00
// If this is not specified, the system default configuration will be used
2018-04-30 15:56:31 +00:00
// instead.
2017-11-01 15:24:59 +00:00
func WithStorageConfig ( config storage . StoreOptions ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-01 15:24:59 +00:00
}
2018-12-10 19:12:10 +00:00
setField := false
2018-12-02 19:06:33 +00:00
if config . RunRoot != "" {
2020-03-27 14:13:51 +00:00
rt . storageConfig . RunRoot = config . RunRoot
rt . storageSet . RunRootSet = true
2018-12-10 19:12:10 +00:00
setField = true
2018-12-02 19:06:33 +00:00
}
2017-11-01 15:24:59 +00:00
2018-12-02 19:06:33 +00:00
if config . GraphRoot != "" {
2020-03-27 14:13:51 +00:00
rt . storageConfig . GraphRoot = config . GraphRoot
rt . storageSet . GraphRootSet = true
2017-11-01 15:24:59 +00:00
2018-12-03 20:13:07 +00:00
// Also set libpod static dir, so we are a subdirectory
// of the c/storage store by default
2020-03-27 14:13:51 +00:00
rt . config . Engine . StaticDir = filepath . Join ( config . GraphRoot , "libpod" )
rt . storageSet . StaticDirSet = true
2018-12-10 19:12:10 +00:00
2019-02-21 14:24:34 +00:00
// Also set libpod volume path, so we are a subdirectory
// of the c/storage store by default
2020-03-27 14:13:51 +00:00
rt . config . Engine . VolumePath = filepath . Join ( config . GraphRoot , "volumes" )
rt . storageSet . VolumePathSet = true
2019-02-21 14:24:34 +00:00
2018-12-10 19:12:10 +00:00
setField = true
2018-12-02 19:06:33 +00:00
}
2017-11-01 15:24:59 +00:00
2021-03-09 10:06:21 +00:00
graphDriverChanged := false
2018-12-02 19:06:33 +00:00
if config . GraphDriverName != "" {
2020-03-27 14:13:51 +00:00
rt . storageConfig . GraphDriverName = config . GraphDriverName
rt . storageSet . GraphDriverNameSet = true
2018-12-10 19:12:10 +00:00
setField = true
2021-03-09 10:06:21 +00:00
graphDriverChanged = true
2018-12-02 19:06:33 +00:00
}
2018-12-02 20:21:35 +00:00
if config . GraphDriverOptions != nil {
2021-03-09 10:06:21 +00:00
if graphDriverChanged {
rt . storageConfig . GraphDriverOptions = make ( [ ] string , len ( config . GraphDriverOptions ) )
copy ( rt . storageConfig . GraphDriverOptions , config . GraphDriverOptions )
} else {
2021-03-31 20:45:35 +00:00
rt . storageConfig . GraphDriverOptions = config . GraphDriverOptions
2021-03-09 10:06:21 +00:00
}
2018-12-10 19:12:10 +00:00
setField = true
2018-12-02 20:21:35 +00:00
}
2017-11-01 15:24:59 +00:00
2018-12-02 20:21:35 +00:00
if config . UIDMap != nil {
2020-03-27 14:13:51 +00:00
rt . storageConfig . UIDMap = make ( [ ] idtools . IDMap , len ( config . UIDMap ) )
copy ( rt . storageConfig . UIDMap , config . UIDMap )
2018-12-02 20:21:35 +00:00
}
2017-11-01 15:24:59 +00:00
2018-12-02 20:21:35 +00:00
if config . GIDMap != nil {
2020-03-27 14:13:51 +00:00
rt . storageConfig . GIDMap = make ( [ ] idtools . IDMap , len ( config . GIDMap ) )
copy ( rt . storageConfig . GIDMap , config . GIDMap )
2018-12-02 20:21:35 +00:00
}
2017-11-01 15:24:59 +00:00
2018-12-10 19:12:10 +00:00
// If any one of runroot, graphroot, graphdrivername,
// or graphdriveroptions are set, then GraphRoot and RunRoot
// must be set
if setField {
2019-03-28 09:30:09 +00:00
storeOpts , err := storage . DefaultStoreOptions ( rootless . IsRootless ( ) , rootless . GetRootlessUID ( ) )
if err != nil {
return err
}
2020-03-27 14:13:51 +00:00
if rt . storageConfig . GraphRoot == "" {
rt . storageConfig . GraphRoot = storeOpts . GraphRoot
2018-12-10 19:12:10 +00:00
}
2020-03-27 14:13:51 +00:00
if rt . storageConfig . RunRoot == "" {
rt . storageConfig . RunRoot = storeOpts . RunRoot
2018-12-10 19:12:10 +00:00
}
}
2017-11-01 15:24:59 +00:00
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithDefaultTransport sets the default transport for retrieving images.
2018-02-16 20:18:31 +00:00
func WithDefaultTransport ( defaultTransport string ) RuntimeOption {
2017-11-01 15:24:59 +00:00
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-01 15:24:59 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . ImageDefaultTransport = defaultTransport
2017-11-01 15:24:59 +00:00
return nil
}
}
// WithSignaturePolicy specifies the path of a file which decides how trust is
// managed for images we've pulled.
// If this is not specified, the system default configuration will be used
2018-04-30 15:56:31 +00:00
// instead.
2017-11-01 15:24:59 +00:00
func WithSignaturePolicy ( path string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-01 15:24:59 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . SignaturePolicyPath = path
2017-11-01 15:24:59 +00:00
return nil
}
}
2018-04-30 16:12:09 +00:00
// WithStateType sets the backing state implementation for libpod.
// Please note that information is not portable between backing states.
2018-01-03 21:27:33 +00:00
// As such, if this differs between two libpods running on the same system,
2018-04-30 15:56:31 +00:00
// they will not share containers, and unspecified behavior may occur.
2020-03-27 14:13:51 +00:00
func WithStateType ( storeType config . RuntimeStateStore ) RuntimeOption {
2017-11-09 18:51:20 +00:00
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-09 18:51:20 +00:00
}
2020-03-27 14:13:51 +00:00
if storeType == config . InvalidStateStore {
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "must provide a valid state store type" )
2018-01-03 21:27:33 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . StateType = storeType
2017-11-09 18:51:20 +00:00
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithOCIRuntime specifies an OCI runtime to use for running containers.
2019-01-04 10:16:40 +00:00
func WithOCIRuntime ( runtime string ) RuntimeOption {
2017-11-01 15:24:59 +00:00
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-01 15:24:59 +00:00
}
2019-01-04 10:16:40 +00:00
if runtime == "" {
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "must provide a valid path" )
2018-02-28 03:31:18 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . OCIRuntime = runtime
2017-11-01 15:24:59 +00:00
return nil
}
}
// WithConmonPath specifies the path to the conmon binary which manages the
2018-04-30 15:56:31 +00:00
// runtime.
2017-11-01 15:24:59 +00:00
func WithConmonPath ( path string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-01 15:24:59 +00:00
}
2018-02-28 03:31:18 +00:00
if path == "" {
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "must provide a valid path" )
2018-01-03 18:39:35 +00:00
}
2018-02-28 03:31:18 +00:00
2020-03-27 14:13:51 +00:00
rt . config . Engine . ConmonPath = [ ] string { path }
2018-02-28 03:31:18 +00:00
2017-11-01 15:24:59 +00:00
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithConmonEnv specifies the environment variable list for the conmon process.
2017-11-01 15:24:59 +00:00
func WithConmonEnv ( environment [ ] string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-01 15:24:59 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . ConmonEnvVars = make ( [ ] string , len ( environment ) )
copy ( rt . config . Engine . ConmonEnvVars , environment )
2017-11-01 15:24:59 +00:00
return nil
}
}
2019-03-05 10:46:47 +00:00
// WithNetworkCmdPath specifies the path to the slirp4netns binary which manages the
// runtime.
func WithNetworkCmdPath ( path string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2019-03-05 10:46:47 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . NetworkCmdPath = path
2019-03-05 10:46:47 +00:00
return nil
}
}
2017-11-01 15:24:59 +00:00
// WithCgroupManager specifies the manager implementation name which is used to
2018-04-30 15:56:31 +00:00
// handle cgroups for containers.
// Current valid values are "cgroupfs" and "systemd".
2017-11-01 15:24:59 +00:00
func WithCgroupManager ( manager string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-01 15:24:59 +00:00
}
2020-03-27 14:13:51 +00:00
if manager != config . CgroupfsCgroupsManager && manager != config . SystemdCgroupsManager {
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "CGroup manager must be one of %s and %s" ,
2020-03-27 14:13:51 +00:00
config . CgroupfsCgroupsManager , config . SystemdCgroupsManager )
2018-03-21 16:19:26 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . CgroupManager = manager
2017-11-01 15:24:59 +00:00
return nil
}
}
// WithStaticDir sets the directory that static runtime files which persist
2018-04-30 15:56:31 +00:00
// across reboots will be stored.
2017-11-01 15:24:59 +00:00
func WithStaticDir ( dir string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-01 15:24:59 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . StaticDir = dir
rt . config . Engine . StaticDirSet = true
2017-11-01 15:24:59 +00:00
return nil
}
}
2020-05-13 11:44:29 +00:00
// WithRegistriesConf configures the runtime to always use specified
// registries.conf for image processing.
func WithRegistriesConf ( path string ) RuntimeOption {
logrus . Debugf ( "Setting custom registries.conf: %q" , path )
return func ( rt * Runtime ) error {
if _ , err := os . Stat ( path ) ; err != nil {
return errors . Wrap ( err , "error locating specified registries.conf" )
}
if rt . imageContext == nil {
2021-06-18 21:27:39 +00:00
rt . imageContext = & types . SystemContext {
BigFilesTemporaryDir : parse . GetTempDir ( ) ,
}
2020-05-13 11:44:29 +00:00
}
2021-06-18 21:27:39 +00:00
2020-05-13 11:44:29 +00:00
rt . imageContext . SystemRegistriesConfPath = path
return nil
}
}
libpod/container_internal: Deprecate implicit hook directories
Part of the motivation for 800eb863 (Hooks supports two directories,
process default and override, 2018-09-17, #1487) was [1]:
> We only use this for override. The reason this was caught is people
> are trying to get hooks to work with CoreOS. You are not allowed to
> write to /usr/share... on CoreOS, so they wanted podman to also look
> at /etc, where users and third parties can write.
But we'd also been disabling hooks completely for rootless users. And
even for root users, the override logic was tricky when folks actually
had content in both directories. For example, if you wanted to
disable a hook from the default directory, you'd have to add a no-op
hook to the override directory.
Also, the previous implementation failed to handle the case where
there hooks defined in the override directory but the default
directory did not exist:
$ podman version
Version: 0.11.2-dev
Go Version: go1.10.3
Git Commit: "6df7409cb5a41c710164c42ed35e33b28f3f7214"
Built: Sun Dec 2 21:30:06 2018
OS/Arch: linux/amd64
$ ls -l /etc/containers/oci/hooks.d/test.json
-rw-r--r--. 1 root root 184 Dec 2 16:27 /etc/containers/oci/hooks.d/test.json
$ podman --log-level=debug run --rm docker.io/library/alpine echo 'successful container' 2>&1 | grep -i hook
time="2018-12-02T21:31:19-08:00" level=debug msg="reading hooks from /usr/share/containers/oci/hooks.d"
time="2018-12-02T21:31:19-08:00" level=warning msg="failed to load hooks: {}%!(EXTRA *os.PathError=open /usr/share/containers/oci/hooks.d: no such file or directory)"
With this commit:
$ podman --log-level=debug run --rm docker.io/library/alpine echo 'successful container' 2>&1 | grep -i hook
time="2018-12-02T21:33:07-08:00" level=debug msg="reading hooks from /usr/share/containers/oci/hooks.d"
time="2018-12-02T21:33:07-08:00" level=debug msg="reading hooks from /etc/containers/oci/hooks.d"
time="2018-12-02T21:33:07-08:00" level=debug msg="added hook /etc/containers/oci/hooks.d/test.json"
time="2018-12-02T21:33:07-08:00" level=debug msg="hook test.json matched; adding to stages [prestart]"
time="2018-12-02T21:33:07-08:00" level=warning msg="implicit hook directories are deprecated; set --hooks-dir="/etc/containers/oci/hooks.d" explicitly to continue to load hooks from this directory"
time="2018-12-02T21:33:07-08:00" level=error msg="container create failed: container_linux.go:336: starting container process caused "process_linux.go:399: container init caused \"process_linux.go:382: running prestart hook 0 caused \\\"error running hook: exit status 1, stdout: , stderr: oh, noes!\\\\n\\\"\""
(I'd setup the hook to error out). You can see that it's silenly
ignoring the ENOENT for /usr/share/containers/oci/hooks.d and
continuing on to load hooks from /etc/containers/oci/hooks.d.
When it loads the hook, it also logs a warning-level message
suggesting that callers explicitly configure their hook directories.
That will help consumers migrate, so we can drop the implicit hook
directories in some future release. When folks *do* explicitly
configure hook directories (via the newly-public --hooks-dir and
hooks_dir options), we error out if they're missing:
$ podman --hooks-dir /does/not/exist run --rm docker.io/library/alpine echo 'successful container'
error setting up OCI Hooks: open /does/not/exist: no such file or directory
I've dropped the trailing "path" from the old, hidden --hooks-dir-path
and hooks_dir_path because I think "dir(ectory)" is already enough
context for "we expect a path argument". I consider this name change
non-breaking because the old forms were undocumented.
Coming back to rootless users, I've enabled hooks now. I expect they
were previously disabled because users had no way to avoid
/usr/share/containers/oci/hooks.d which might contain hooks that
required root permissions. But now rootless users will have to
explicitly configure hook directories, and since their default config
is from ~/.config/containers/libpod.conf, it's a misconfiguration if
it contains hooks_dir entries which point at directories with hooks
that require root access. We error out so they can fix their
libpod.conf.
[1]: https://github.com/containers/libpod/pull/1487#discussion_r218149355
Signed-off-by: W. Trevor King <wking@tremily.us>
2018-12-03 05:22:08 +00:00
// WithHooksDir sets the directories to look for OCI runtime hook configuration.
func WithHooksDir ( hooksDirs ... string ) RuntimeOption {
2018-03-29 15:01:47 +00:00
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2018-03-29 15:01:47 +00:00
}
libpod/container_internal: Deprecate implicit hook directories
Part of the motivation for 800eb863 (Hooks supports two directories,
process default and override, 2018-09-17, #1487) was [1]:
> We only use this for override. The reason this was caught is people
> are trying to get hooks to work with CoreOS. You are not allowed to
> write to /usr/share... on CoreOS, so they wanted podman to also look
> at /etc, where users and third parties can write.
But we'd also been disabling hooks completely for rootless users. And
even for root users, the override logic was tricky when folks actually
had content in both directories. For example, if you wanted to
disable a hook from the default directory, you'd have to add a no-op
hook to the override directory.
Also, the previous implementation failed to handle the case where
there hooks defined in the override directory but the default
directory did not exist:
$ podman version
Version: 0.11.2-dev
Go Version: go1.10.3
Git Commit: "6df7409cb5a41c710164c42ed35e33b28f3f7214"
Built: Sun Dec 2 21:30:06 2018
OS/Arch: linux/amd64
$ ls -l /etc/containers/oci/hooks.d/test.json
-rw-r--r--. 1 root root 184 Dec 2 16:27 /etc/containers/oci/hooks.d/test.json
$ podman --log-level=debug run --rm docker.io/library/alpine echo 'successful container' 2>&1 | grep -i hook
time="2018-12-02T21:31:19-08:00" level=debug msg="reading hooks from /usr/share/containers/oci/hooks.d"
time="2018-12-02T21:31:19-08:00" level=warning msg="failed to load hooks: {}%!(EXTRA *os.PathError=open /usr/share/containers/oci/hooks.d: no such file or directory)"
With this commit:
$ podman --log-level=debug run --rm docker.io/library/alpine echo 'successful container' 2>&1 | grep -i hook
time="2018-12-02T21:33:07-08:00" level=debug msg="reading hooks from /usr/share/containers/oci/hooks.d"
time="2018-12-02T21:33:07-08:00" level=debug msg="reading hooks from /etc/containers/oci/hooks.d"
time="2018-12-02T21:33:07-08:00" level=debug msg="added hook /etc/containers/oci/hooks.d/test.json"
time="2018-12-02T21:33:07-08:00" level=debug msg="hook test.json matched; adding to stages [prestart]"
time="2018-12-02T21:33:07-08:00" level=warning msg="implicit hook directories are deprecated; set --hooks-dir="/etc/containers/oci/hooks.d" explicitly to continue to load hooks from this directory"
time="2018-12-02T21:33:07-08:00" level=error msg="container create failed: container_linux.go:336: starting container process caused "process_linux.go:399: container init caused \"process_linux.go:382: running prestart hook 0 caused \\\"error running hook: exit status 1, stdout: , stderr: oh, noes!\\\\n\\\"\""
(I'd setup the hook to error out). You can see that it's silenly
ignoring the ENOENT for /usr/share/containers/oci/hooks.d and
continuing on to load hooks from /etc/containers/oci/hooks.d.
When it loads the hook, it also logs a warning-level message
suggesting that callers explicitly configure their hook directories.
That will help consumers migrate, so we can drop the implicit hook
directories in some future release. When folks *do* explicitly
configure hook directories (via the newly-public --hooks-dir and
hooks_dir options), we error out if they're missing:
$ podman --hooks-dir /does/not/exist run --rm docker.io/library/alpine echo 'successful container'
error setting up OCI Hooks: open /does/not/exist: no such file or directory
I've dropped the trailing "path" from the old, hidden --hooks-dir-path
and hooks_dir_path because I think "dir(ectory)" is already enough
context for "we expect a path argument". I consider this name change
non-breaking because the old forms were undocumented.
Coming back to rootless users, I've enabled hooks now. I expect they
were previously disabled because users had no way to avoid
/usr/share/containers/oci/hooks.d which might contain hooks that
required root permissions. But now rootless users will have to
explicitly configure hook directories, and since their default config
is from ~/.config/containers/libpod.conf, it's a misconfiguration if
it contains hooks_dir entries which point at directories with hooks
that require root access. We error out so they can fix their
libpod.conf.
[1]: https://github.com/containers/libpod/pull/1487#discussion_r218149355
Signed-off-by: W. Trevor King <wking@tremily.us>
2018-12-03 05:22:08 +00:00
for _ , hooksDir := range hooksDirs {
if hooksDir == "" {
2019-07-16 19:56:24 +00:00
return errors . Wrap ( define . ErrInvalidArg , "empty-string hook directories are not supported" )
libpod/container_internal: Deprecate implicit hook directories
Part of the motivation for 800eb863 (Hooks supports two directories,
process default and override, 2018-09-17, #1487) was [1]:
> We only use this for override. The reason this was caught is people
> are trying to get hooks to work with CoreOS. You are not allowed to
> write to /usr/share... on CoreOS, so they wanted podman to also look
> at /etc, where users and third parties can write.
But we'd also been disabling hooks completely for rootless users. And
even for root users, the override logic was tricky when folks actually
had content in both directories. For example, if you wanted to
disable a hook from the default directory, you'd have to add a no-op
hook to the override directory.
Also, the previous implementation failed to handle the case where
there hooks defined in the override directory but the default
directory did not exist:
$ podman version
Version: 0.11.2-dev
Go Version: go1.10.3
Git Commit: "6df7409cb5a41c710164c42ed35e33b28f3f7214"
Built: Sun Dec 2 21:30:06 2018
OS/Arch: linux/amd64
$ ls -l /etc/containers/oci/hooks.d/test.json
-rw-r--r--. 1 root root 184 Dec 2 16:27 /etc/containers/oci/hooks.d/test.json
$ podman --log-level=debug run --rm docker.io/library/alpine echo 'successful container' 2>&1 | grep -i hook
time="2018-12-02T21:31:19-08:00" level=debug msg="reading hooks from /usr/share/containers/oci/hooks.d"
time="2018-12-02T21:31:19-08:00" level=warning msg="failed to load hooks: {}%!(EXTRA *os.PathError=open /usr/share/containers/oci/hooks.d: no such file or directory)"
With this commit:
$ podman --log-level=debug run --rm docker.io/library/alpine echo 'successful container' 2>&1 | grep -i hook
time="2018-12-02T21:33:07-08:00" level=debug msg="reading hooks from /usr/share/containers/oci/hooks.d"
time="2018-12-02T21:33:07-08:00" level=debug msg="reading hooks from /etc/containers/oci/hooks.d"
time="2018-12-02T21:33:07-08:00" level=debug msg="added hook /etc/containers/oci/hooks.d/test.json"
time="2018-12-02T21:33:07-08:00" level=debug msg="hook test.json matched; adding to stages [prestart]"
time="2018-12-02T21:33:07-08:00" level=warning msg="implicit hook directories are deprecated; set --hooks-dir="/etc/containers/oci/hooks.d" explicitly to continue to load hooks from this directory"
time="2018-12-02T21:33:07-08:00" level=error msg="container create failed: container_linux.go:336: starting container process caused "process_linux.go:399: container init caused \"process_linux.go:382: running prestart hook 0 caused \\\"error running hook: exit status 1, stdout: , stderr: oh, noes!\\\\n\\\"\""
(I'd setup the hook to error out). You can see that it's silenly
ignoring the ENOENT for /usr/share/containers/oci/hooks.d and
continuing on to load hooks from /etc/containers/oci/hooks.d.
When it loads the hook, it also logs a warning-level message
suggesting that callers explicitly configure their hook directories.
That will help consumers migrate, so we can drop the implicit hook
directories in some future release. When folks *do* explicitly
configure hook directories (via the newly-public --hooks-dir and
hooks_dir options), we error out if they're missing:
$ podman --hooks-dir /does/not/exist run --rm docker.io/library/alpine echo 'successful container'
error setting up OCI Hooks: open /does/not/exist: no such file or directory
I've dropped the trailing "path" from the old, hidden --hooks-dir-path
and hooks_dir_path because I think "dir(ectory)" is already enough
context for "we expect a path argument". I consider this name change
non-breaking because the old forms were undocumented.
Coming back to rootless users, I've enabled hooks now. I expect they
were previously disabled because users had no way to avoid
/usr/share/containers/oci/hooks.d which might contain hooks that
required root permissions. But now rootless users will have to
explicitly configure hook directories, and since their default config
is from ~/.config/containers/libpod.conf, it's a misconfiguration if
it contains hooks_dir entries which point at directories with hooks
that require root access. We error out so they can fix their
libpod.conf.
[1]: https://github.com/containers/libpod/pull/1487#discussion_r218149355
Signed-off-by: W. Trevor King <wking@tremily.us>
2018-12-03 05:22:08 +00:00
}
libpod: Add HooksDirNotExistFatal
And add an argument to WithHooksDir to set it.
If the hook dir doesn't exist, the new hooks package considers that a
fatal error. When a podman caller sets
--hooks-dir-path=/some/typoed/directory, a fatal error is more helpful
than silently not loading any hooks. However, callers who call podman
without setting --hooks-dir-path may not need hooks at all. We don't
want to pester those callers with not-exist errors. With this commit,
we:
* Assume the caller knows what they're doing if they set
--hooks-dir-path and set HooksDirNotExistFatal.
* If the caller does not explicitly set --hooks-dir-path, assume they
won't mind if the hook directory is missing and set
HooksDirNotExistFatal false.
We also considered checking for the directory's existence in the code
calling WithHooksDir or from within WithHooksDir, but checks there
would race with the underlying ioutil.ReadDir in the hooks package.
By pushing the warn/error decision down into libpod's implementation,
we avoid a racy "do we expect this to work once libpod gets to it?"
pre-check.
I've also added a check to error if WithHooksDir is called with an
empty-string argument, because we haven't defined the semantics of
that (is it clearing a previous value? Is it effectively the same as
the current directory?). I agree with Matthew that a separate
WithNoHooks, or a *string argument to WithHooks, or some such would be
a better API for clearing previous values [1]. But for now, I'm just
erroring out to fail early for callers who might otherwise be
surprised that libpod ignores empty-string HooksDir.
[1]: https://github.com/projectatomic/libpod/pull/686#issuecomment-385119370
Signed-off-by: W. Trevor King <wking@tremily.us>
Closes: #686
Approved by: mheon
2018-04-27 21:41:42 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . HooksDir = hooksDirs
2018-03-29 15:01:47 +00:00
return nil
}
}
2021-03-30 00:21:00 +00:00
// WithCDI sets the devices to check for for CDI configuration.
func WithCDI ( devices [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . CDIDevices = devices
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithDefaultMountsFile sets the file to look at for default mounts (mainly
// secrets).
// Note we are not saving this in the database as it is for testing purposes
// only.
2018-04-26 15:29:02 +00:00
func WithDefaultMountsFile ( mountsFile string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2018-04-26 15:29:02 +00:00
}
2018-04-26 20:41:06 +00:00
if mountsFile == "" {
2019-07-16 19:56:24 +00:00
return define . ErrInvalidArg
2018-04-26 20:41:06 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Containers . DefaultMountsFile = mountsFile
2018-04-26 15:29:02 +00:00
return nil
}
}
2017-11-01 15:24:59 +00:00
// WithTmpDir sets the directory that temporary runtime files which are not
2018-04-30 15:56:31 +00:00
// expected to survive across reboots will be stored.
2021-01-07 10:37:24 +00:00
// This should be located on a tmpfs mount (/tmp or /run for example).
2017-11-01 15:24:59 +00:00
func WithTmpDir ( dir string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-01 15:24:59 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . TmpDir = dir
rt . config . Engine . TmpDirSet = true
2017-11-01 15:24:59 +00:00
return nil
}
}
2019-07-01 18:35:16 +00:00
// WithNoStore sets a bool on the runtime that we do not need
// any containers storage.
func WithNoStore ( ) RuntimeOption {
return func ( rt * Runtime ) error {
rt . noStore = true
return nil
}
}
2017-11-01 15:24:59 +00:00
// WithNoPivotRoot sets the runtime to use MS_MOVE instead of PIVOT_ROOT when
2018-04-30 15:56:31 +00:00
// starting containers.
2019-07-03 20:37:17 +00:00
func WithNoPivotRoot ( ) RuntimeOption {
2017-11-01 15:24:59 +00:00
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-01 15:24:59 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . NoPivotRoot = true
2017-11-01 15:24:59 +00:00
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithCNIConfigDir sets the CNI configuration directory.
2017-12-14 19:36:27 +00:00
func WithCNIConfigDir ( dir string ) RuntimeOption {
2017-11-30 19:25:00 +00:00
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-11-30 19:25:00 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Network . NetworkConfigDir = dir
2017-12-14 19:36:27 +00:00
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithCNIPluginDir sets the CNI plugins directory.
2017-12-14 19:36:27 +00:00
func WithCNIPluginDir ( dir string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2017-12-14 19:36:27 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Network . CNIPluginDirs = [ ] string { dir }
2017-11-30 19:25:00 +00:00
return nil
}
}
2018-06-26 03:39:11 +00:00
// WithNamespace sets the namespace for libpod.
// Namespaces are used to create scopes to separate containers and pods
// in the state.
// When namespace is set, libpod will only view containers and pods in
// the same namespace. All containers and pods created will default to
// the namespace set here.
// A namespace of "", the empty string, is equivalent to no namespace,
// and all containers and pods will be visible.
func WithNamespace ( ns string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2018-06-26 03:39:11 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . Namespace = ns
2018-06-26 03:39:11 +00:00
return nil
}
}
2018-08-08 13:50:15 +00:00
// WithVolumePath sets the path under which all named volumes
// should be created.
2019-11-12 04:39:36 +00:00
// The path changes based on whether the user is running as root or not.
2018-08-08 13:50:15 +00:00
func WithVolumePath ( volPath string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2018-08-08 13:50:15 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . VolumePath = volPath
rt . config . Engine . VolumePathSet = true
2018-08-08 13:50:15 +00:00
return nil
}
}
2018-08-17 14:36:51 +00:00
// WithDefaultInfraImage sets the infra image for libpod.
// An infra image is used for inter-container kernel
// namespace sharing within a pod. Typically, an infra
2018-07-27 17:58:50 +00:00
// container is lightweight and is there to reap
// zombie processes within its pid namespace.
2018-08-17 14:36:51 +00:00
func WithDefaultInfraImage ( img string ) RuntimeOption {
2018-07-27 17:58:50 +00:00
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2018-07-27 17:58:50 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . InfraImage = img
2018-07-27 17:58:50 +00:00
return nil
}
}
2018-08-17 14:36:51 +00:00
// WithDefaultInfraCommand sets the command to
2018-07-27 17:58:50 +00:00
// run on pause container start up.
2018-08-17 14:36:51 +00:00
func WithDefaultInfraCommand ( cmd string ) RuntimeOption {
2018-07-27 17:58:50 +00:00
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2018-07-27 17:58:50 +00:00
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . InfraCommand = cmd
2018-07-27 17:58:50 +00:00
return nil
}
}
2021-06-29 19:39:11 +00:00
// WithDefaultInfraName sets the infra container name for a single pod.
func WithDefaultInfraName ( name string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
return define . ErrRuntimeFinalized
}
rt . config . Engine . InfraImage = name
return nil
}
}
2019-02-18 21:20:02 +00:00
// WithRenumber instructs libpod to perform a lock renumbering while
// initializing. This will handle migrations from early versions of libpod with
// file locks to newer versions with SHM locking, as well as changes in the
// number of configured locks.
2019-02-15 14:59:11 +00:00
func WithRenumber ( ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2019-02-15 14:59:11 +00:00
}
rt . doRenumber = true
return nil
}
}
2019-05-01 19:07:30 +00:00
// WithMigrate instructs libpod to migrate container configurations to account
2020-03-27 14:13:51 +00:00
// for changes between Engine versions. All running containers will be stopped
2019-05-01 19:07:30 +00:00
// during a migration, then restarted after the migration is complete.
2019-04-15 20:03:47 +00:00
func WithMigrate ( ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
2019-07-16 19:56:24 +00:00
return define . ErrRuntimeFinalized
2019-04-15 20:03:47 +00:00
}
rt . doMigrate = true
return nil
}
}
2020-03-27 14:13:51 +00:00
// WithMigrateRuntime instructs Engine to change the default OCI runtime on all
2019-10-08 18:12:58 +00:00
// containers during a migration. This is not used if `MigrateRuntime()` is not
// also passed.
2020-03-27 14:13:51 +00:00
// Engine makes no promises that your containers continue to work with the new
2019-10-08 18:12:58 +00:00
// runtime - migrations between dissimilar runtimes may well break things.
// Use with caution.
func WithMigrateRuntime ( requestedRuntime string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
return define . ErrRuntimeFinalized
}
if requestedRuntime == "" {
return errors . Wrapf ( define . ErrInvalidArg , "must provide a non-empty name for new runtime" )
}
rt . migrateRuntime = requestedRuntime
return nil
}
}
2019-07-16 19:56:24 +00:00
// WithEventsLogger sets the events backend to use.
// Currently supported values are "file" for file backend and "journald" for
// journald backend.
func WithEventsLogger ( logger string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
return define . ErrRuntimeFinalized
}
if ! events . IsValidEventer ( logger ) {
return errors . Wrapf ( define . ErrInvalidArg , "%q is not a valid events backend" , logger )
}
2020-03-27 14:13:51 +00:00
rt . config . Engine . EventsLogger = logger
2020-12-11 16:02:21 +00:00
rt . config . Engine . EventsLogFilePath = filepath . Join ( rt . config . Engine . TmpDir , "events" , "events.log" )
2019-07-16 19:56:24 +00:00
return nil
}
}
2019-08-14 14:29:47 +00:00
// WithEnableSDNotify sets a runtime option so we know whether to disable socket/FD
// listening
func WithEnableSDNotify ( ) RuntimeOption {
return func ( rt * Runtime ) error {
2020-03-27 14:13:51 +00:00
rt . config . Engine . SDNotify = true
2019-08-14 14:29:47 +00:00
return nil
}
}
2020-08-21 17:56:50 +00:00
// WithRuntimeFlags adds the global runtime flags to the container config
func WithRuntimeFlags ( runtimeFlags [ ] string ) RuntimeOption {
return func ( rt * Runtime ) error {
if rt . valid {
return define . ErrRuntimeFinalized
}
rt . runtimeFlags = runtimeFlags
return nil
}
}
2017-11-01 15:24:59 +00:00
// Container Creation Options
2020-10-05 20:33:09 +00:00
// WithMaxLogSize sets the maximum size of container logs.
// Positive sizes are limits in bytes, -1 is unlimited.
func WithMaxLogSize ( limit int64 ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrRuntimeFinalized
}
ctr . config . LogSize = limit
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithShmDir sets the directory that should be mounted on /dev/shm.
2017-11-30 14:37:57 +00:00
func WithShmDir ( dir string ) CtrCreateOption {
2017-11-03 14:46:51 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-11-03 14:46:51 +00:00
}
2017-11-30 14:37:57 +00:00
ctr . config . ShmDir = dir
return nil
}
}
2018-10-15 19:42:12 +00:00
// WithSystemd turns on systemd mode in the container
func WithSystemd ( ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-10-15 19:42:12 +00:00
}
ctr . config . Systemd = true
return nil
}
}
2020-06-19 13:29:34 +00:00
// WithSdNotifyMode sets the sd-notify method
func WithSdNotifyMode ( mode string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
// verify values
if len ( mode ) > 0 && ! util . StringInSlice ( strings . ToLower ( mode ) , SdNotifyModeValues ) {
return errors . Wrapf ( define . ErrInvalidArg , "--sdnotify values must be one of %q" , strings . Join ( SdNotifyModeValues , ", " ) )
}
ctr . config . SdNotifyMode = mode
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithShmSize sets the size of /dev/shm tmpfs mount.
2018-01-10 20:58:18 +00:00
func WithShmSize ( size int64 ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-10 20:58:18 +00:00
}
ctr . config . ShmSize = size
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithPrivileged sets the privileged flag in the container runtime.
2018-01-23 16:12:13 +00:00
func WithPrivileged ( privileged bool ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-23 16:12:13 +00:00
}
ctr . config . Privileged = privileged
return nil
}
}
2018-09-18 13:06:40 +00:00
// WithSecLabels sets the labels for SELinux.
func WithSecLabels ( labelOpts [ ] string ) CtrCreateOption {
2017-11-30 14:37:57 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-11-30 14:37:57 +00:00
}
2018-10-18 19:50:11 +00:00
ctr . config . LabelOpts = labelOpts
2017-11-03 14:46:51 +00:00
return nil
}
}
2020-09-11 10:12:58 +00:00
// WithUser sets the user identity field in configuration.
2018-04-30 15:56:31 +00:00
// Valid uses [user | user:group | uid | uid:gid | user:gid | uid:group ].
2017-12-18 17:05:06 +00:00
func WithUser ( user string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-12-18 17:05:06 +00:00
}
ctr . config . User = user
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithRootFSFromImage sets up a fresh root filesystem using the given image.
2017-11-01 15:24:59 +00:00
// If useImageConfig is specified, image volumes, environment variables, and
2018-04-30 15:56:31 +00:00
// other configuration from the image will be added to the config.
// TODO: Replace image name and ID with a libpod.Image struct when that is
// finished.
2020-03-10 07:32:19 +00:00
func WithRootFSFromImage ( imageID , imageName , rawImageName string ) CtrCreateOption {
2017-11-01 15:24:59 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-11-01 15:24:59 +00:00
}
ctr . config . RootfsImageID = imageID
ctr . config . RootfsImageName = imageName
2020-03-10 07:32:19 +00:00
ctr . config . RawImageName = rawImageName
2017-11-01 15:24:59 +00:00
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithStdin keeps stdin on the container open to allow interaction.
2017-11-01 15:24:59 +00:00
func WithStdin ( ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-11-01 15:24:59 +00:00
}
ctr . config . Stdin = true
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithPod adds the container to a pod.
2018-06-25 14:35:15 +00:00
// Containers which join a pod can only join the Linux namespaces of other
// containers in the same pod.
// Containers can only join pods in the same libpod namespace.
2017-11-01 15:24:59 +00:00
func ( r * Runtime ) WithPod ( pod * Pod ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-11-01 15:24:59 +00:00
}
if pod == nil {
2019-07-16 19:56:24 +00:00
return define . ErrInvalidArg
2017-11-01 15:24:59 +00:00
}
ctr . config . Pod = pod . ID ( )
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithLabels adds labels to the container.
2017-11-01 15:24:59 +00:00
func WithLabels ( labels map [ string ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-11-01 15:24:59 +00:00
}
ctr . config . Labels = make ( map [ string ] string )
for key , value := range labels {
ctr . config . Labels [ key ] = value
}
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithName sets the container's name.
2017-11-01 15:24:59 +00:00
func WithName ( name string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-11-01 15:24:59 +00:00
}
2018-01-02 19:02:52 +00:00
// Check the name against a regex
2020-05-21 16:07:46 +00:00
if ! define . NameRegex . MatchString ( name ) {
return define . RegexError
2018-01-02 19:02:52 +00:00
}
2017-11-01 15:24:59 +00:00
ctr . config . Name = name
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithStopSignal sets the signal that will be sent to stop the container.
2017-12-19 19:41:23 +00:00
func WithStopSignal ( signal syscall . Signal ) CtrCreateOption {
2017-11-01 15:24:59 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-11-01 15:24:59 +00:00
}
if signal == 0 {
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "stop signal cannot be 0" )
2017-11-01 15:24:59 +00:00
} else if signal > 64 {
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "stop signal cannot be greater than 64 (SIGRTMAX)" )
2017-11-01 15:24:59 +00:00
}
2017-12-19 19:41:23 +00:00
ctr . config . StopSignal = uint ( signal )
2017-11-01 15:24:59 +00:00
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithStopTimeout sets the time to after initial stop signal is sent to the
// container, before sending the kill signal.
2017-12-19 20:42:30 +00:00
func WithStopTimeout ( timeout uint ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-12-19 20:42:30 +00:00
}
ctr . config . StopTimeout = timeout
return nil
}
}
2021-04-22 19:38:36 +00:00
// WithTimeout sets the maximum time a container is allowed to run"
func WithTimeout ( timeout uint ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . Timeout = timeout
return nil
}
}
2020-12-21 22:48:43 +00:00
// WithIDMappings sets the idmappings for the container
2018-04-24 00:42:53 +00:00
func WithIDMappings ( idmappings storage . IDMappingOptions ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-04-24 00:42:53 +00:00
}
ctr . config . IDMappings = idmappings
return nil
}
}
2018-06-22 20:44:59 +00:00
// WithExitCommand sets the ExitCommand for the container, appending on the ctr.ID() to the end
func WithExitCommand ( exitCommand [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-06-22 20:44:59 +00:00
}
2020-01-13 12:01:45 +00:00
ctr . config . ExitCommand = exitCommand
ctr . config . ExitCommand = append ( ctr . config . ExitCommand , ctr . ID ( ) )
2018-06-22 20:44:59 +00:00
return nil
}
}
2018-07-27 17:58:50 +00:00
// WithUTSNSFromPod indicates the the container should join the UTS namespace of
// its pod
2018-08-20 21:56:35 +00:00
func WithUTSNSFromPod ( p * Pod ) CtrCreateOption {
2018-07-27 17:58:50 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-07-27 17:58:50 +00:00
}
2018-08-23 17:33:10 +00:00
if err := validPodNSOption ( p , ctr . config . Pod ) ; err != nil {
return err
2018-08-20 21:56:35 +00:00
}
infraContainer , err := p . InfraContainerID ( )
if err != nil {
return err
}
ctr . config . UTSNsCtr = infraContainer
2018-07-27 17:58:50 +00:00
return nil
}
}
2018-01-11 22:41:59 +00:00
// WithIPCNSFrom indicates the the container should join the IPC namespace of
2018-04-30 15:56:31 +00:00
// the given container.
2018-02-10 20:11:32 +00:00
// If the container has joined a pod, it can only join the namespaces of
2018-04-30 15:56:31 +00:00
// containers in the same pod.
2018-01-11 22:41:59 +00:00
func WithIPCNSFrom ( nsCtr * Container ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-11 22:41:59 +00:00
}
Add ContainerStateRemoving
When Libpod removes a container, there is the possibility that
removal will not fully succeed. The most notable problems are
storage issues, where the container cannot be removed from
c/storage.
When this occurs, we were faced with a choice. We can keep the
container in the state, appearing in `podman ps` and available for
other API operations, but likely unable to do any of them as it's
been partially removed. Or we can remove it very early and clean
up after it's already gone. We have, until now, used the second
approach.
The problem that arises is intermittent problems removing
storage. We end up removing a container, failing to remove its
storage, and ending up with a container permanently stuck in
c/storage that we can't remove with the normal Podman CLI, can't
use the name of, and generally can't interact with. A notable
cause is when Podman is hit by a SIGKILL midway through removal,
which can consistently cause `podman rm` to fail to remove
storage.
We now add a new state for containers that are in the process of
being removed, ContainerStateRemoving. We set this at the
beginning of the removal process. It notifies Podman that the
container cannot be used anymore, but preserves it in the DB
until it is fully removed. This will allow Remove to be run on
these containers again, which should successfully remove storage
if it fails.
Fixes #3906
Signed-off-by: Matthew Heon <mheon@redhat.com>
2019-11-11 14:52:13 +00:00
if err := checkDependencyContainer ( nsCtr , ctr ) ; err != nil {
return err
2018-02-10 20:11:32 +00:00
}
2018-01-11 22:41:59 +00:00
ctr . config . IPCNsCtr = nsCtr . ID ( )
return nil
}
}
// WithMountNSFrom indicates the the container should join the mount namespace
2018-04-30 15:56:31 +00:00
// of the given container.
2018-02-10 20:11:32 +00:00
// If the container has joined a pod, it can only join the namespaces of
2018-04-30 15:56:31 +00:00
// containers in the same pod.
2018-01-11 22:41:59 +00:00
func WithMountNSFrom ( nsCtr * Container ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-11 22:41:59 +00:00
}
Add ContainerStateRemoving
When Libpod removes a container, there is the possibility that
removal will not fully succeed. The most notable problems are
storage issues, where the container cannot be removed from
c/storage.
When this occurs, we were faced with a choice. We can keep the
container in the state, appearing in `podman ps` and available for
other API operations, but likely unable to do any of them as it's
been partially removed. Or we can remove it very early and clean
up after it's already gone. We have, until now, used the second
approach.
The problem that arises is intermittent problems removing
storage. We end up removing a container, failing to remove its
storage, and ending up with a container permanently stuck in
c/storage that we can't remove with the normal Podman CLI, can't
use the name of, and generally can't interact with. A notable
cause is when Podman is hit by a SIGKILL midway through removal,
which can consistently cause `podman rm` to fail to remove
storage.
We now add a new state for containers that are in the process of
being removed, ContainerStateRemoving. We set this at the
beginning of the removal process. It notifies Podman that the
container cannot be used anymore, but preserves it in the DB
until it is fully removed. This will allow Remove to be run on
these containers again, which should successfully remove storage
if it fails.
Fixes #3906
Signed-off-by: Matthew Heon <mheon@redhat.com>
2019-11-11 14:52:13 +00:00
if err := checkDependencyContainer ( nsCtr , ctr ) ; err != nil {
return err
2018-02-10 20:11:32 +00:00
}
2018-01-11 22:41:59 +00:00
ctr . config . MountNsCtr = nsCtr . ID ( )
return nil
}
}
// WithNetNSFrom indicates the the container should join the network namespace
2018-04-30 15:56:31 +00:00
// of the given container.
2018-02-10 20:11:32 +00:00
// If the container has joined a pod, it can only join the namespaces of
2018-04-30 15:56:31 +00:00
// containers in the same pod.
2018-01-11 22:41:59 +00:00
func WithNetNSFrom ( nsCtr * Container ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-11 22:41:59 +00:00
}
Add ContainerStateRemoving
When Libpod removes a container, there is the possibility that
removal will not fully succeed. The most notable problems are
storage issues, where the container cannot be removed from
c/storage.
When this occurs, we were faced with a choice. We can keep the
container in the state, appearing in `podman ps` and available for
other API operations, but likely unable to do any of them as it's
been partially removed. Or we can remove it very early and clean
up after it's already gone. We have, until now, used the second
approach.
The problem that arises is intermittent problems removing
storage. We end up removing a container, failing to remove its
storage, and ending up with a container permanently stuck in
c/storage that we can't remove with the normal Podman CLI, can't
use the name of, and generally can't interact with. A notable
cause is when Podman is hit by a SIGKILL midway through removal,
which can consistently cause `podman rm` to fail to remove
storage.
We now add a new state for containers that are in the process of
being removed, ContainerStateRemoving. We set this at the
beginning of the removal process. It notifies Podman that the
container cannot be used anymore, but preserves it in the DB
until it is fully removed. This will allow Remove to be run on
these containers again, which should successfully remove storage
if it fails.
Fixes #3906
Signed-off-by: Matthew Heon <mheon@redhat.com>
2019-11-11 14:52:13 +00:00
if err := checkDependencyContainer ( nsCtr , ctr ) ; err != nil {
return err
2018-01-11 22:41:59 +00:00
}
ctr . config . NetNsCtr = nsCtr . ID ( )
return nil
}
}
// WithPIDNSFrom indicates the the container should join the PID namespace of
2018-04-30 15:56:31 +00:00
// the given container.
2018-02-10 20:11:32 +00:00
// If the container has joined a pod, it can only join the namespaces of
2018-04-30 15:56:31 +00:00
// containers in the same pod.
2018-01-11 22:41:59 +00:00
func WithPIDNSFrom ( nsCtr * Container ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-11 22:41:59 +00:00
}
Add ContainerStateRemoving
When Libpod removes a container, there is the possibility that
removal will not fully succeed. The most notable problems are
storage issues, where the container cannot be removed from
c/storage.
When this occurs, we were faced with a choice. We can keep the
container in the state, appearing in `podman ps` and available for
other API operations, but likely unable to do any of them as it's
been partially removed. Or we can remove it very early and clean
up after it's already gone. We have, until now, used the second
approach.
The problem that arises is intermittent problems removing
storage. We end up removing a container, failing to remove its
storage, and ending up with a container permanently stuck in
c/storage that we can't remove with the normal Podman CLI, can't
use the name of, and generally can't interact with. A notable
cause is when Podman is hit by a SIGKILL midway through removal,
which can consistently cause `podman rm` to fail to remove
storage.
We now add a new state for containers that are in the process of
being removed, ContainerStateRemoving. We set this at the
beginning of the removal process. It notifies Podman that the
container cannot be used anymore, but preserves it in the DB
until it is fully removed. This will allow Remove to be run on
these containers again, which should successfully remove storage
if it fails.
Fixes #3906
Signed-off-by: Matthew Heon <mheon@redhat.com>
2019-11-11 14:52:13 +00:00
if err := checkDependencyContainer ( nsCtr , ctr ) ; err != nil {
return err
2018-02-10 20:11:32 +00:00
}
2018-01-11 22:41:59 +00:00
ctr . config . PIDNsCtr = nsCtr . ID ( )
return nil
}
}
2020-06-30 19:44:14 +00:00
// WithAddCurrentUserPasswdEntry indicates that container should add current
// user entry to /etc/passwd, since the UID will be mapped into the container,
// via user namespace
func WithAddCurrentUserPasswdEntry ( ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . AddCurrentUserPasswdEntry = true
return nil
}
}
2018-01-11 22:41:59 +00:00
// WithUserNSFrom indicates the the container should join the user namespace of
2018-04-30 15:56:31 +00:00
// the given container.
2018-02-10 20:11:32 +00:00
// If the container has joined a pod, it can only join the namespaces of
2018-04-30 15:56:31 +00:00
// containers in the same pod.
2018-01-11 22:41:59 +00:00
func WithUserNSFrom ( nsCtr * Container ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-11 22:41:59 +00:00
}
Add ContainerStateRemoving
When Libpod removes a container, there is the possibility that
removal will not fully succeed. The most notable problems are
storage issues, where the container cannot be removed from
c/storage.
When this occurs, we were faced with a choice. We can keep the
container in the state, appearing in `podman ps` and available for
other API operations, but likely unable to do any of them as it's
been partially removed. Or we can remove it very early and clean
up after it's already gone. We have, until now, used the second
approach.
The problem that arises is intermittent problems removing
storage. We end up removing a container, failing to remove its
storage, and ending up with a container permanently stuck in
c/storage that we can't remove with the normal Podman CLI, can't
use the name of, and generally can't interact with. A notable
cause is when Podman is hit by a SIGKILL midway through removal,
which can consistently cause `podman rm` to fail to remove
storage.
We now add a new state for containers that are in the process of
being removed, ContainerStateRemoving. We set this at the
beginning of the removal process. It notifies Podman that the
container cannot be used anymore, but preserves it in the DB
until it is fully removed. This will allow Remove to be run on
these containers again, which should successfully remove storage
if it fails.
Fixes #3906
Signed-off-by: Matthew Heon <mheon@redhat.com>
2019-11-11 14:52:13 +00:00
if err := checkDependencyContainer ( nsCtr , ctr ) ; err != nil {
return err
2018-02-10 20:11:32 +00:00
}
2018-01-11 22:41:59 +00:00
ctr . config . UserNsCtr = nsCtr . ID ( )
2019-07-24 09:20:31 +00:00
ctr . config . IDMappings = nsCtr . config . IDMappings
2018-01-11 22:41:59 +00:00
2021-01-12 14:16:12 +00:00
g := generate . Generator { Config : ctr . config . Spec }
2020-09-09 22:19:39 +00:00
g . ClearLinuxUIDMappings ( )
for _ , uidmap := range nsCtr . config . IDMappings . UIDMap {
g . AddLinuxUIDMapping ( uint32 ( uidmap . HostID ) , uint32 ( uidmap . ContainerID ) , uint32 ( uidmap . Size ) )
}
g . ClearLinuxGIDMappings ( )
for _ , gidmap := range nsCtr . config . IDMappings . GIDMap {
g . AddLinuxGIDMapping ( uint32 ( gidmap . HostID ) , uint32 ( gidmap . ContainerID ) , uint32 ( gidmap . Size ) )
}
ctr . config . IDMappings = nsCtr . config . IDMappings
2018-01-11 22:41:59 +00:00
return nil
}
}
// WithUTSNSFrom indicates the the container should join the UTS namespace of
2018-04-30 15:56:31 +00:00
// the given container.
2018-02-10 20:11:32 +00:00
// If the container has joined a pod, it can only join the namespaces of
2018-04-30 15:56:31 +00:00
// containers in the same pod.
2018-01-11 22:41:59 +00:00
func WithUTSNSFrom ( nsCtr * Container ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-11 22:41:59 +00:00
}
Add ContainerStateRemoving
When Libpod removes a container, there is the possibility that
removal will not fully succeed. The most notable problems are
storage issues, where the container cannot be removed from
c/storage.
When this occurs, we were faced with a choice. We can keep the
container in the state, appearing in `podman ps` and available for
other API operations, but likely unable to do any of them as it's
been partially removed. Or we can remove it very early and clean
up after it's already gone. We have, until now, used the second
approach.
The problem that arises is intermittent problems removing
storage. We end up removing a container, failing to remove its
storage, and ending up with a container permanently stuck in
c/storage that we can't remove with the normal Podman CLI, can't
use the name of, and generally can't interact with. A notable
cause is when Podman is hit by a SIGKILL midway through removal,
which can consistently cause `podman rm` to fail to remove
storage.
We now add a new state for containers that are in the process of
being removed, ContainerStateRemoving. We set this at the
beginning of the removal process. It notifies Podman that the
container cannot be used anymore, but preserves it in the DB
until it is fully removed. This will allow Remove to be run on
these containers again, which should successfully remove storage
if it fails.
Fixes #3906
Signed-off-by: Matthew Heon <mheon@redhat.com>
2019-11-11 14:52:13 +00:00
if err := checkDependencyContainer ( nsCtr , ctr ) ; err != nil {
return err
2018-02-10 20:11:32 +00:00
}
2018-01-11 22:41:59 +00:00
ctr . config . UTSNsCtr = nsCtr . ID ( )
return nil
}
}
// WithCgroupNSFrom indicates the the container should join the CGroup namespace
2018-04-30 15:56:31 +00:00
// of the given container.
2018-02-10 20:11:32 +00:00
// If the container has joined a pod, it can only join the namespaces of
2018-04-30 15:56:31 +00:00
// containers in the same pod.
2018-01-11 22:41:59 +00:00
func WithCgroupNSFrom ( nsCtr * Container ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-11 22:41:59 +00:00
}
Add ContainerStateRemoving
When Libpod removes a container, there is the possibility that
removal will not fully succeed. The most notable problems are
storage issues, where the container cannot be removed from
c/storage.
When this occurs, we were faced with a choice. We can keep the
container in the state, appearing in `podman ps` and available for
other API operations, but likely unable to do any of them as it's
been partially removed. Or we can remove it very early and clean
up after it's already gone. We have, until now, used the second
approach.
The problem that arises is intermittent problems removing
storage. We end up removing a container, failing to remove its
storage, and ending up with a container permanently stuck in
c/storage that we can't remove with the normal Podman CLI, can't
use the name of, and generally can't interact with. A notable
cause is when Podman is hit by a SIGKILL midway through removal,
which can consistently cause `podman rm` to fail to remove
storage.
We now add a new state for containers that are in the process of
being removed, ContainerStateRemoving. We set this at the
beginning of the removal process. It notifies Podman that the
container cannot be used anymore, but preserves it in the DB
until it is fully removed. This will allow Remove to be run on
these containers again, which should successfully remove storage
if it fails.
Fixes #3906
Signed-off-by: Matthew Heon <mheon@redhat.com>
2019-11-11 14:52:13 +00:00
if err := checkDependencyContainer ( nsCtr , ctr ) ; err != nil {
return err
2018-02-10 20:11:32 +00:00
}
2018-01-11 22:41:59 +00:00
ctr . config . CgroupNsCtr = nsCtr . ID ( )
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithDependencyCtrs sets dependency containers of the given container.
// Dependency containers must be running before this container is started.
2018-03-31 23:58:31 +00:00
func WithDependencyCtrs ( ctrs [ ] * Container ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-03-31 23:58:31 +00:00
}
deps := make ( [ ] string , 0 , len ( ctrs ) )
for _ , dep := range ctrs {
2020-03-01 22:54:11 +00:00
if err := checkDependencyContainer ( dep , ctr ) ; err != nil {
return err
2018-03-31 23:58:31 +00:00
}
deps = append ( deps , dep . ID ( ) )
}
ctr . config . Dependencies = deps
return nil
}
}
2017-12-05 22:50:29 +00:00
// WithNetNS indicates that the container should be given a new network
2018-04-30 15:56:31 +00:00
// namespace with a minimal configuration.
// An optional array of port mappings can be provided.
// Conflicts with WithNetNSFrom().
2018-11-26 20:31:06 +00:00
func WithNetNS ( portMappings [ ] ocicni . PortMapping , postConfigureNetNS bool , netmode string , networks [ ] string ) CtrCreateOption {
2017-12-05 22:50:29 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2017-12-05 22:50:29 +00:00
}
2018-04-20 16:59:19 +00:00
ctr . config . PostConfigureNetNS = postConfigureNetNS
2019-02-18 02:55:30 +00:00
ctr . config . NetMode = namespaces . NetworkMode ( netmode )
2019-03-28 21:39:56 +00:00
ctr . config . CreateNetNS = true
2018-01-04 18:59:33 +00:00
ctr . config . PortMappings = portMappings
2019-10-24 08:42:49 +00:00
2018-07-12 14:51:31 +00:00
ctr . config . Networks = networks
2017-12-05 22:50:29 +00:00
return nil
}
}
2018-10-02 17:34:58 +00:00
// WithStaticIP indicates that the container should request a static IP from
// the CNI plugins.
// It cannot be set unless WithNetNS has already been passed.
// Further, it cannot be set if additional CNI networks to join have been
// specified.
func WithStaticIP ( ip net . IP ) CtrCreateOption {
return func ( ctr * Container ) error {
2018-10-10 19:06:08 +00:00
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-10-02 17:34:58 +00:00
}
ctr . config . StaticIP = ip
return nil
}
}
2020-07-16 10:19:51 +00:00
// WithNetworkOptions sets additional options for the networks.
func WithNetworkOptions ( options map [ string ] [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . NetworkOptions = options
return nil
}
}
2019-09-17 22:26:48 +00:00
// WithStaticMAC indicates that the container should request a static MAC from
// the CNI plugins.
// It cannot be set unless WithNetNS has already been passed.
// Further, it cannot be set if additional CNI networks to join have been
// specified.
func WithStaticMAC ( mac net . HardwareAddr ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . StaticMAC = mac
return nil
}
}
2019-05-18 23:39:11 +00:00
// WithLogDriver sets the log driver for the container
func WithLogDriver ( driver string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2019-05-18 23:39:11 +00:00
}
2019-05-20 17:58:31 +00:00
switch driver {
case "" :
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "log driver must be set" )
2020-06-10 18:35:00 +00:00
case define . JournaldLogging , define . KubernetesLogging , define . JSONLogging , define . NoLogging :
2019-05-20 17:58:31 +00:00
break
default :
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "invalid log driver" )
2019-05-18 23:39:11 +00:00
}
ctr . config . LogDriver = driver
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithLogPath sets the path to the log file.
2018-01-30 05:23:58 +00:00
func WithLogPath ( path string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-30 05:23:58 +00:00
}
if path == "" {
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "log path must be set" )
2018-01-30 05:23:58 +00:00
}
ctr . config . LogPath = path
return nil
}
}
2020-01-07 12:41:56 +00:00
// WithLogTag sets the tag to the log file.
func WithLogTag ( tag string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
if tag == "" {
return errors . Wrapf ( define . ErrInvalidArg , "log tag must be set" )
}
ctr . config . LogTag = tag
return nil
}
}
2020-01-14 14:05:12 +00:00
// WithCgroupsMode disables the creation of CGroups for the conmon process.
func WithCgroupsMode ( mode string ) CtrCreateOption {
2019-07-15 20:44:56 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
2020-01-14 14:05:12 +00:00
switch mode {
case "disabled" :
ctr . config . NoCgroups = true
ctr . config . CgroupsMode = mode
2020-06-18 11:56:30 +00:00
case "enabled" , "no-conmon" , cgroupSplit :
2020-01-14 14:05:12 +00:00
ctr . config . CgroupsMode = mode
default :
return errors . Wrapf ( define . ErrInvalidArg , "Invalid cgroup mode %q" , mode )
2019-07-15 20:44:56 +00:00
}
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithCgroupParent sets the Cgroup Parent of the new container.
2018-01-10 21:21:54 +00:00
func WithCgroupParent ( parent string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-10 21:21:54 +00:00
}
if parent == "" {
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "cgroup parent cannot be empty" )
2018-01-10 21:21:54 +00:00
}
ctr . config . CgroupParent = parent
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithDNSSearch sets the additional search domains of a container.
2018-01-19 14:51:59 +00:00
func WithDNSSearch ( searchDomains [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-19 14:51:59 +00:00
}
ctr . config . DNSSearch = searchDomains
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithDNS sets additional name servers for the container.
2018-01-19 14:51:59 +00:00
func WithDNS ( dnsServers [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-19 14:51:59 +00:00
}
var dns [ ] net . IP
for _ , i := range dnsServers {
result := net . ParseIP ( i )
if result == nil {
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "invalid IP address %s" , i )
2018-01-19 14:51:59 +00:00
}
dns = append ( dns , result )
}
2020-03-27 14:13:51 +00:00
ctr . config . DNSServer = append ( ctr . config . DNSServer , dns ... )
2018-01-19 14:51:59 +00:00
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithDNSOption sets addition dns options for the container.
2018-01-19 14:51:59 +00:00
func WithDNSOption ( dnsOptions [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-19 14:51:59 +00:00
}
2020-03-27 14:13:51 +00:00
if ctr . config . UseImageResolvConf {
return errors . Wrapf ( define . ErrInvalidArg , "cannot add DNS options if container will not create /etc/resolv.conf" )
}
ctr . config . DNSOption = append ( ctr . config . DNSOption , dnsOptions ... )
2018-01-19 14:51:59 +00:00
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithHosts sets additional host:IP for the hosts file.
2018-01-19 14:51:59 +00:00
func WithHosts ( hosts [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-01-19 14:51:59 +00:00
}
2019-03-22 18:39:09 +00:00
2018-01-19 14:51:59 +00:00
ctr . config . HostAdd = hosts
return nil
}
}
2018-03-26 18:09:10 +00:00
2018-04-30 15:56:31 +00:00
// WithConmonPidFile specifies the path to the file that receives the pid of
// conmon.
2018-03-26 18:09:10 +00:00
func WithConmonPidFile ( path string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-03-26 18:09:10 +00:00
}
ctr . config . ConmonPidFile = path
return nil
}
}
2018-04-03 17:37:25 +00:00
2018-04-30 15:56:31 +00:00
// WithGroups sets additional groups for the container, which are defined by
// the user.
2018-04-03 17:37:25 +00:00
func WithGroups ( groups [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-04-03 17:37:25 +00:00
}
ctr . config . Groups = groups
return nil
}
}
2018-04-30 15:09:48 +00:00
2018-05-01 16:08:52 +00:00
// WithUserVolumes sets the user-added volumes of the container.
// These are not added to the container's spec, but will instead be used during
// commit to populate the volumes of the new image, and to trigger some OCI
// hooks that are only added if volume mounts are present.
2019-06-12 21:14:21 +00:00
// Furthermore, they are used in the output of inspect, to filter volumes -
// only volumes included in this list will be included in the output.
2018-05-01 16:08:52 +00:00
// Unless explicitly set, committed images will have no volumes.
// The given volumes slice must not be nil.
func WithUserVolumes ( volumes [ ] string ) CtrCreateOption {
2018-04-30 15:09:48 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-04-30 15:09:48 +00:00
}
2018-05-01 16:08:52 +00:00
if volumes == nil {
2019-07-16 19:56:24 +00:00
return define . ErrInvalidArg
2018-05-01 16:08:52 +00:00
}
ctr . config . UserVolumes = make ( [ ] string , 0 , len ( volumes ) )
2019-07-10 18:14:17 +00:00
ctr . config . UserVolumes = append ( ctr . config . UserVolumes , volumes ... )
2018-05-01 16:08:52 +00:00
return nil
}
}
// WithEntrypoint sets the entrypoint of the container.
// This is not used to change the container's spec, but will instead be used
// during commit to populate the entrypoint of the new image.
// If not explicitly set it will default to the image's entrypoint.
// A nil entrypoint is allowed, and will clear entrypoint on the created image.
func WithEntrypoint ( entrypoint [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-05-01 16:08:52 +00:00
}
ctr . config . Entrypoint = make ( [ ] string , 0 , len ( entrypoint ) )
2019-07-10 18:14:17 +00:00
ctr . config . Entrypoint = append ( ctr . config . Entrypoint , entrypoint ... )
2018-05-01 16:08:52 +00:00
return nil
}
}
// WithCommand sets the command of the container.
// This is not used to change the container's spec, but will instead be used
// during commit to populate the command of the new image.
// If not explicitly set it will default to the image's command.
// A nil command is allowed, and will clear command on the created image.
func WithCommand ( command [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-05-01 16:08:52 +00:00
}
ctr . config . Command = make ( [ ] string , 0 , len ( command ) )
2019-07-10 18:14:17 +00:00
ctr . config . Command = append ( ctr . config . Command , command ... )
2018-04-30 15:09:48 +00:00
return nil
}
}
2018-06-25 14:35:15 +00:00
// WithRootFS sets the rootfs for the container.
// This creates a container from a directory on disk and not an image.
2018-04-26 15:21:48 +00:00
func WithRootFS ( rootfs string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-04-26 15:21:48 +00:00
}
if _ , err := os . Stat ( rootfs ) ; err != nil {
2020-10-28 17:16:42 +00:00
return err
2018-04-26 15:21:48 +00:00
}
ctr . config . Rootfs = rootfs
return nil
}
}
2018-06-26 03:39:11 +00:00
// WithCtrNamespace sets the namespace the container will be created in.
2018-06-25 14:35:15 +00:00
// Namespaces are used to create separate views of Podman's state - runtimes can
// join a specific namespace and see only containers and pods in that namespace.
// Empty string namespaces are allowed, and correspond to a lack of namespace.
2018-06-26 03:39:11 +00:00
func WithCtrNamespace ( ns string ) CtrCreateOption {
2018-06-25 14:35:15 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-06-25 14:35:15 +00:00
}
ctr . config . Namespace = ns
return nil
}
}
2019-03-26 17:55:19 +00:00
// WithUseImageResolvConf tells the container not to bind-mount resolv.conf in.
2019-03-22 18:39:09 +00:00
// This conflicts with other DNS-related options.
2019-03-26 17:55:19 +00:00
func WithUseImageResolvConf ( ) CtrCreateOption {
2019-03-22 18:39:09 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2019-03-22 18:39:09 +00:00
}
2019-03-26 17:55:19 +00:00
ctr . config . UseImageResolvConf = true
2019-03-22 18:39:09 +00:00
return nil
}
}
2019-03-26 17:55:19 +00:00
// WithUseImageHosts tells the container not to bind-mount /etc/hosts in.
2019-03-22 18:39:09 +00:00
// This conflicts with WithHosts().
2019-03-26 17:55:19 +00:00
func WithUseImageHosts ( ) CtrCreateOption {
2019-03-22 18:39:09 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2019-03-22 18:39:09 +00:00
}
2019-03-26 17:55:19 +00:00
ctr . config . UseImageHosts = true
2019-03-22 18:39:09 +00:00
return nil
}
}
2019-04-01 19:22:32 +00:00
// WithRestartPolicy sets the container's restart policy. Valid values are
// "no", "on-failure", and "always". The empty string is allowed, and will be
// equivalent to "no".
func WithRestartPolicy ( policy string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2019-04-01 19:22:32 +00:00
}
switch policy {
2021-03-15 11:55:06 +00:00
case define . RestartPolicyNone , define . RestartPolicyNo , define . RestartPolicyOnFailure , define . RestartPolicyAlways , define . RestartPolicyUnlessStopped :
2019-04-01 19:22:32 +00:00
ctr . config . RestartPolicy = policy
default :
2019-07-16 19:56:24 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "%q is not a valid restart policy" , policy )
2019-04-01 19:22:32 +00:00
}
return nil
}
}
// WithRestartRetries sets the number of retries to use when restarting a
// container with the "on-failure" restart policy.
// 0 is an allowed value, and indicates infinite retries.
func WithRestartRetries ( tries uint ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2019-04-01 19:22:32 +00:00
}
ctr . config . RestartRetries = tries
return nil
}
}
2018-08-17 14:36:51 +00:00
// withIsInfra sets the container to be an infra container. This means the container will be sometimes hidden
2018-07-27 17:58:50 +00:00
// and expected to be the first container in the pod.
2018-08-17 14:36:51 +00:00
func withIsInfra ( ) CtrCreateOption {
2018-07-27 17:58:50 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2018-07-27 17:58:50 +00:00
}
2018-08-17 14:36:51 +00:00
ctr . config . IsInfra = true
2018-07-27 17:58:50 +00:00
return nil
}
}
2019-03-12 19:53:08 +00:00
// WithNamedVolumes adds the given named volumes to the container.
func WithNamedVolumes ( volumes [ ] * ContainerNamedVolume ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
2019-07-16 19:56:24 +00:00
return define . ErrCtrFinalized
2019-03-12 19:53:08 +00:00
}
for _ , vol := range volumes {
2020-03-31 08:59:44 +00:00
mountOpts , err := util . ProcessOptions ( vol . Options , false , "" )
2019-08-22 15:21:20 +00:00
if err != nil {
return errors . Wrapf ( err , "error processing options for named volume %q mounted at %q" , vol . Name , vol . Dest )
}
2019-03-12 19:53:08 +00:00
ctr . config . NamedVolumes = append ( ctr . config . NamedVolumes , & ContainerNamedVolume {
Name : vol . Name ,
Dest : vol . Dest ,
2019-08-22 15:21:20 +00:00
Options : mountOpts ,
2019-03-12 19:53:08 +00:00
} )
}
return nil
}
}
2020-07-09 19:46:14 +00:00
// WithOverlayVolumes adds the given overlay volumes to the container.
func WithOverlayVolumes ( volumes [ ] * ContainerOverlayVolume ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
for _ , vol := range volumes {
ctr . config . OverlayVolumes = append ( ctr . config . OverlayVolumes , & ContainerOverlayVolume {
2021-01-06 01:50:58 +00:00
Dest : vol . Dest ,
Source : vol . Source ,
Options : vol . Options ,
2020-07-09 19:46:14 +00:00
} )
}
return nil
}
}
2020-10-26 10:35:02 +00:00
// WithImageVolumes adds the given image volumes to the container.
func WithImageVolumes ( volumes [ ] * ContainerImageVolume ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
for _ , vol := range volumes {
ctr . config . ImageVolumes = append ( ctr . config . ImageVolumes , & ContainerImageVolume {
Dest : vol . Dest ,
Source : vol . Source ,
ReadWrite : vol . ReadWrite ,
} )
}
return nil
}
}
2019-07-15 18:55:20 +00:00
// WithHealthCheck adds the healthcheck to the container config
func WithHealthCheck ( healthCheck * manifest . Schema2HealthConfig ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . HealthCheckConfig = healthCheck
return nil
}
}
2020-06-16 18:22:05 +00:00
// WithPreserveFDs forwards from the process running Libpod into the container
// the given number of extra FDs (starting after the standard streams) to the created container
func WithPreserveFDs ( fd uint ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . PreserveFDs = fd
return nil
}
}
2019-12-12 11:11:12 +00:00
// WithCreateCommand adds the full command plus arguments of the current
// process to the container config.
2020-07-07 21:19:59 +00:00
func WithCreateCommand ( cmd [ ] string ) CtrCreateOption {
2019-12-12 11:11:12 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
2020-07-07 21:19:59 +00:00
ctr . config . CreateCommand = cmd
2019-12-12 11:11:12 +00:00
return nil
}
}
2020-07-31 21:08:06 +00:00
// WithCreateWorkingDir tells Podman to create the container's working directory
// if it does not exist.
func WithCreateWorkingDir ( ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . CreateWorkingDir = true
return nil
}
}
2020-10-26 21:17:45 +00:00
// WithNetworkAliases sets network aliases for the container.
// Accepts a map of network name to aliases.
func WithNetworkAliases ( aliases map [ string ] [ ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . NetworkAliases = aliases
return nil
}
}
2018-08-08 13:50:15 +00:00
// Volume Creation Options
// WithVolumeName sets the name of the volume.
func WithVolumeName ( name string ) VolumeCreateOption {
return func ( volume * Volume ) error {
if volume . valid {
2019-07-16 19:56:24 +00:00
return define . ErrVolumeFinalized
2018-08-08 13:50:15 +00:00
}
// Check the name against a regex
2020-05-21 16:07:46 +00:00
if ! define . NameRegex . MatchString ( name ) {
return define . RegexError
2018-08-08 13:50:15 +00:00
}
volume . config . Name = name
return nil
}
}
2019-07-15 18:55:20 +00:00
// WithVolumeDriver sets the volume's driver.
// It is presently not implemented, but will be supported in a future Podman
// release.
func WithVolumeDriver ( driver string ) VolumeCreateOption {
2019-03-22 11:15:26 +00:00
return func ( volume * Volume ) error {
if volume . valid {
2019-07-16 19:56:24 +00:00
return define . ErrVolumeFinalized
2019-03-22 11:15:26 +00:00
}
2020-11-16 19:32:12 +00:00
volume . config . Driver = driver
2020-04-27 20:28:01 +00:00
return nil
2019-03-22 11:15:26 +00:00
}
}
2019-07-15 18:55:20 +00:00
// WithVolumeLabels sets the labels of the volume.
func WithVolumeLabels ( labels map [ string ] string ) VolumeCreateOption {
2019-03-22 11:15:26 +00:00
return func ( volume * Volume ) error {
if volume . valid {
2019-07-16 19:56:24 +00:00
return define . ErrVolumeFinalized
2019-03-22 11:15:26 +00:00
}
2019-03-22 18:23:18 +00:00
2019-07-15 18:55:20 +00:00
volume . config . Labels = make ( map [ string ] string )
for key , value := range labels {
volume . config . Labels [ key ] = value
}
2019-03-22 18:23:18 +00:00
2019-03-22 11:15:26 +00:00
return nil
}
}
2019-03-22 18:23:18 +00:00
// WithVolumeOptions sets the options of the volume.
func WithVolumeOptions ( options map [ string ] string ) VolumeCreateOption {
2018-08-08 13:50:15 +00:00
return func ( volume * Volume ) error {
if volume . valid {
2019-07-16 19:56:24 +00:00
return define . ErrVolumeFinalized
2018-08-08 13:50:15 +00:00
}
2019-03-22 18:23:18 +00:00
volume . config . Options = make ( map [ string ] string )
for key , value := range options {
volume . config . Options [ key ] = value
2018-08-08 13:50:15 +00:00
}
return nil
}
}
2019-03-22 18:23:18 +00:00
// WithVolumeUID sets the UID that the volume will be created as.
func WithVolumeUID ( uid int ) VolumeCreateOption {
2018-08-08 13:50:15 +00:00
return func ( volume * Volume ) error {
if volume . valid {
2019-07-16 19:56:24 +00:00
return define . ErrVolumeFinalized
2018-08-08 13:50:15 +00:00
}
2019-03-22 18:23:18 +00:00
volume . config . UID = uid
2018-08-08 13:50:15 +00:00
return nil
}
}
2019-03-22 18:23:18 +00:00
// WithVolumeGID sets the GID that the volume will be created as.
func WithVolumeGID ( gid int ) VolumeCreateOption {
2018-08-08 13:50:15 +00:00
return func ( volume * Volume ) error {
if volume . valid {
2019-07-16 19:56:24 +00:00
return define . ErrVolumeFinalized
2018-08-08 13:50:15 +00:00
}
2019-03-22 18:23:18 +00:00
volume . config . GID = gid
2018-08-08 13:50:15 +00:00
return nil
}
}
2021-06-10 11:52:30 +00:00
// WithVolumeNoChown prevents the volume from being chowned to the process uid at first use.
func WithVolumeNoChown ( ) VolumeCreateOption {
return func ( volume * Volume ) error {
if volume . valid {
return define . ErrVolumeFinalized
}
volume . state . NeedsChown = false
return nil
}
}
Deprecate & remove IsCtrSpecific in favor of IsAnon
In Podman 1.6.3, we added support for anonymous volumes - fixing
our old, broken support for named volumes that were created with
containers. Unfortunately, this reused the database field we used
for the old implementation, and toggled volume removal on for
`podman run --rm` - so now, we were removing *named* volumes
created with older versions of Podman.
We can't modify these old volumes in the DB, so the next-safest
thing to do is swap to a new field to indicate volumes should be
removed. Problem: Volumes created with 1.6.3 and up until this
lands, even anonymous volumes, will not be removed. However, this
is safer than removing too many volumes, as we were doing before.
Fixes #5009
Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2020-01-29 19:04:51 +00:00
// withSetAnon sets a bool notifying libpod that this volume is anonymous and
// should be removed when containers using it are removed and volumes are
// specified for removal.
func withSetAnon ( ) VolumeCreateOption {
2019-02-26 17:16:58 +00:00
return func ( volume * Volume ) error {
if volume . valid {
2019-07-16 19:56:24 +00:00
return define . ErrVolumeFinalized
2019-02-26 17:16:58 +00:00
}
Deprecate & remove IsCtrSpecific in favor of IsAnon
In Podman 1.6.3, we added support for anonymous volumes - fixing
our old, broken support for named volumes that were created with
containers. Unfortunately, this reused the database field we used
for the old implementation, and toggled volume removal on for
`podman run --rm` - so now, we were removing *named* volumes
created with older versions of Podman.
We can't modify these old volumes in the DB, so the next-safest
thing to do is swap to a new field to indicate volumes should be
removed. Problem: Volumes created with 1.6.3 and up until this
lands, even anonymous volumes, will not be removed. However, this
is safer than removing too many volumes, as we were doing before.
Fixes #5009
Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2020-01-29 19:04:51 +00:00
volume . config . IsAnon = true
2019-02-26 17:16:58 +00:00
return nil
}
}
2020-06-30 21:21:52 +00:00
// WithTimezone sets the timezone in the container
func WithTimezone ( path string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
if path != "local" {
zone := filepath . Join ( "/usr/share/zoneinfo" , path )
file , err := os . Stat ( zone )
if err != nil {
return err
}
//We don't want to mount a timezone directory
if file . IsDir ( ) {
return errors . New ( "Invalid timezone: is a directory" )
}
}
ctr . config . Timezone = path
return nil
}
}
2020-07-17 01:49:47 +00:00
// WithUmask sets the umask in the container
func WithUmask ( umask string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
if ! define . UmaskRegex . MatchString ( umask ) {
return errors . Wrapf ( define . ErrInvalidArg , "Invalid umask string %s" , umask )
}
ctr . config . Umask = umask
return nil
}
}
2021-01-15 06:27:23 +00:00
// WithSecrets adds secrets to the container
2021-05-14 20:29:44 +00:00
func WithSecrets ( containerSecrets [ ] * ContainerSecret ) CtrCreateOption {
2021-01-15 06:27:23 +00:00
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
2021-05-14 20:29:44 +00:00
ctr . config . Secrets = containerSecrets
2021-01-15 06:27:23 +00:00
return nil
}
}
2021-05-05 14:34:13 +00:00
// WithSecrets adds environment variable secrets to the container
func WithEnvSecrets ( envSecrets map [ string ] string ) CtrCreateOption {
return func ( ctr * Container ) error {
ctr . config . EnvSecrets = make ( map [ string ] * secrets . Secret )
if ctr . valid {
return define . ErrCtrFinalized
}
2021-05-14 20:29:44 +00:00
manager , err := ctr . runtime . SecretsManager ( )
2021-05-05 14:34:13 +00:00
if err != nil {
return err
}
for target , src := range envSecrets {
secr , err := manager . Lookup ( src )
if err != nil {
return err
}
ctr . config . EnvSecrets [ target ] = secr
}
return nil
}
}
2021-04-15 14:36:50 +00:00
// WithPidFile adds pidFile to the container
func WithPidFile ( pidFile string ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . PidFile = pidFile
return nil
}
}
2018-04-30 15:09:48 +00:00
// Pod Creation Options
2020-09-13 15:54:08 +00:00
// WithInfraImage sets the infra image for libpod.
// An infra image is used for inter-container kernel
// namespace sharing within a pod. Typically, an infra
// container is lightweight and is there to reap
// zombie processes within its pid namespace.
func WithInfraImage ( img string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
pod . config . InfraContainer . InfraImage = img
return nil
}
}
// WithInfraCommand sets the command to
// run on pause container start up.
func WithInfraCommand ( cmd [ ] string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
pod . config . InfraContainer . InfraCommand = cmd
return nil
}
}
2021-06-29 19:39:11 +00:00
// WithInfraName sets the infra container name for a single pod.
func WithInfraName ( name string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
pod . config . InfraContainer . InfraName = name
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithPodName sets the name of the pod.
2018-04-30 15:09:48 +00:00
func WithPodName ( name string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-04-30 15:09:48 +00:00
}
// Check the name against a regex
2020-05-21 16:07:46 +00:00
if ! define . NameRegex . MatchString ( name ) {
return define . RegexError
2018-04-30 15:09:48 +00:00
}
pod . config . Name = name
return nil
}
}
2019-08-17 02:42:36 +00:00
// WithPodHostname sets the hostname of the pod.
func WithPodHostname ( hostname string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
// Check the hostname against a regex
2020-05-21 16:07:46 +00:00
if ! define . NameRegex . MatchString ( hostname ) {
return define . RegexError
2019-08-17 02:42:36 +00:00
}
pod . config . Hostname = hostname
return nil
}
}
2020-05-28 08:54:17 +00:00
// WithPodCreateCommand adds the full command plus arguments of the current
// process to the pod config.
2020-07-07 21:19:59 +00:00
func WithPodCreateCommand ( createCmd [ ] string ) PodCreateOption {
2020-05-28 08:54:17 +00:00
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-07-07 21:19:59 +00:00
pod . config . CreateCommand = createCmd
2020-05-28 08:54:17 +00:00
return nil
}
}
2020-05-29 11:20:22 +00:00
// WithInfraConmonPidFile sets the path to a custom conmon PID file for the
// infra container.
func WithInfraConmonPidFile ( path string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
pod . config . InfraContainer . ConmonPidFile = path
return nil
}
}
2018-04-30 15:56:31 +00:00
// WithPodLabels sets the labels of a pod.
2018-04-30 15:09:48 +00:00
func WithPodLabels ( labels map [ string ] string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-04-30 15:09:48 +00:00
}
pod . config . Labels = make ( map [ string ] string )
for key , value := range labels {
pod . config . Labels [ key ] = value
}
return nil
}
}
2018-05-16 16:45:09 +00:00
// WithPodCgroupParent sets the Cgroup Parent of the pod.
func WithPodCgroupParent ( path string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-05-16 16:45:09 +00:00
}
pod . config . CgroupParent = path
return nil
}
}
// WithPodCgroups tells containers in this pod to use the cgroup created for
// this pod.
// This can still be overridden at the container level by explicitly specifying
// a CGroup parent.
func WithPodCgroups ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-05-16 16:45:09 +00:00
}
pod . config . UsePodCgroup = true
return nil
}
}
2018-06-25 14:35:15 +00:00
// WithPodNamespace sets the namespace for the created pod.
// Namespaces are used to create separate views of Podman's state - runtimes can
// join a specific namespace and see only containers and pods in that namespace.
// Empty string namespaces are allowed, and correspond to a lack of namespace.
// Containers must belong to the same namespace as the pod they join.
func WithPodNamespace ( ns string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-06-25 14:35:15 +00:00
}
pod . config . Namespace = ns
return nil
}
}
2018-07-27 17:58:50 +00:00
// WithPodIPC tells containers in this pod to use the ipc namespace
// created for this pod.
// Containers in a pod will inherit the kernel namespaces from the
// first container added.
func WithPodIPC ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-07-27 17:58:50 +00:00
}
pod . config . UsePodIPC = true
return nil
}
}
// WithPodNet tells containers in this pod to use the network namespace
// created for this pod.
// Containers in a pod will inherit the kernel namespaces from the
// first container added.
func WithPodNet ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-07-27 17:58:50 +00:00
}
pod . config . UsePodNet = true
return nil
}
}
2018-08-20 21:56:35 +00:00
// WithPodMount tells containers in this pod to use the mount namespace
2018-07-27 17:58:50 +00:00
// created for this pod.
// Containers in a pod will inherit the kernel namespaces from the
// first container added.
2018-08-20 21:56:35 +00:00
// TODO implement WithMountNSFrom, so WithMountNsFromPod functions properly
// Then this option can be added on the pod level
func WithPodMount ( ) PodCreateOption {
2018-07-27 17:58:50 +00:00
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-07-27 17:58:50 +00:00
}
2018-08-20 21:56:35 +00:00
pod . config . UsePodMount = true
2018-07-27 17:58:50 +00:00
return nil
}
}
// WithPodUser tells containers in this pod to use the user namespace
// created for this pod.
// Containers in a pod will inherit the kernel namespaces from the
// first container added.
2018-08-20 21:56:35 +00:00
// TODO implement WithUserNSFrom, so WithUserNsFromPod functions properly
// Then this option can be added on the pod level
2018-07-27 17:58:50 +00:00
func WithPodUser ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-07-27 17:58:50 +00:00
}
pod . config . UsePodUser = true
return nil
}
}
// WithPodPID tells containers in this pod to use the pid namespace
// created for this pod.
// Containers in a pod will inherit the kernel namespaces from the
// first container added.
func WithPodPID ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-07-27 17:58:50 +00:00
}
pod . config . UsePodPID = true
return nil
}
}
// WithPodUTS tells containers in this pod to use the uts namespace
// created for this pod.
// Containers in a pod will inherit the kernel namespaces from the
// first container added.
func WithPodUTS ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-07-27 17:58:50 +00:00
}
pod . config . UsePodUTS = true
return nil
}
}
Fix bug where pods would unintentionally share cgroupns
This one was a massive pain to track down.
The original symptom was an error message from rootless Podman
trying to make a container in a pod. I unfortunately did not look
at the error message closely enough to realize that the namespace
in question was the cgroup namespace (the reproducer pod was
explicitly set to only share the network namespace), else this
would have been quite a bit shorter.
I spent considerable effort trying to track down differences
between the inspect output of the two containers, and when that
failed I was forced to resort to diffing the OCI specs. That
finally proved fruitful, and I was able to determine what should
have been obvious all along: the container was joining the cgroup
namespace of the infra container when it really ought not to
have.
From there, I discovered a variable collision in pod config. The
UsePodCgroup variable means "create a parent cgroup for the pod
and join containers in the pod to it". Unfortunately, it is very
similar to UsePodUTS, UsePodNet, etc, which mean "the pod shares
this namespace", so an accessor was accidentally added for it
that indicated the pod shared the cgroup namespace when it really
did not. Once I realized that, it was a quick fix - add a bool to
the pod's configuration to indicate whether the cgroup ns was
shared (distinct from UsePodCgroup) and use that for the
accessor.
Also included are fixes for `podman inspect` and
`podman pod inspect` that fix them to actually display the state
of the cgroup namespace (for container inspect) and what
namespaces are shared (for pod inspect). Either of those would
have made tracking this down considerably quicker.
Fixes #6149
Signed-off-by: Matthew Heon <mheon@redhat.com>
2020-05-08 21:41:50 +00:00
// WithPodCgroup tells containers in this pod to use the cgroup namespace
// created for this pod.
// Containers in a pod will inherit the kernel namespaces from the first
// container added.
func WithPodCgroup ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
pod . config . UsePodCgroupNS = true
return nil
}
}
2018-08-17 14:36:51 +00:00
// WithInfraContainer tells the pod to create a pause container
func WithInfraContainer ( ) PodCreateOption {
2018-07-27 17:58:50 +00:00
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-07-27 17:58:50 +00:00
}
2018-08-17 14:36:51 +00:00
pod . config . InfraContainer . HasInfraContainer = true
2018-07-27 17:58:50 +00:00
return nil
}
}
2018-11-19 19:20:56 +00:00
// WithInfraContainerPorts tells the pod to add port bindings to the pause container
func WithInfraContainerPorts ( bindings [ ] ocicni . PortMapping ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
2019-07-16 19:56:24 +00:00
return define . ErrPodFinalized
2018-11-19 19:20:56 +00:00
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot set pod ports as no infra container is being created" )
}
2018-11-19 19:20:56 +00:00
pod . config . InfraContainer . PortBindings = bindings
return nil
}
}
2020-02-03 16:17:32 +00:00
// WithPodStaticIP sets a static IP for the pod.
func WithPodStaticIP ( ip net . IP ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot set pod static IP as no infra container is being created" )
}
2020-02-17 21:21:07 +00:00
if pod . config . InfraContainer . HostNetwork {
return errors . Wrapf ( define . ErrInvalidArg , "cannot set static IP if host network is specified" )
}
2020-02-03 16:17:32 +00:00
if len ( pod . config . InfraContainer . Networks ) > 1 {
return errors . Wrapf ( define . ErrInvalidArg , "cannot set a static IP if joining more than 1 CNI network" )
}
pod . config . InfraContainer . StaticIP = ip
return nil
}
}
// WithPodStaticMAC sets a static MAC address for the pod.
func WithPodStaticMAC ( mac net . HardwareAddr ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot set pod static MAC as no infra container is being created" )
}
2020-02-17 21:21:07 +00:00
if pod . config . InfraContainer . HostNetwork {
return errors . Wrapf ( define . ErrInvalidArg , "cannot set static MAC if host network is specified" )
}
2020-02-03 16:17:32 +00:00
if len ( pod . config . InfraContainer . Networks ) > 1 {
return errors . Wrapf ( define . ErrInvalidArg , "cannot set a static MAC if joining more than 1 CNI network" )
}
pod . config . InfraContainer . StaticMAC = mac
return nil
}
}
// WithPodUseImageResolvConf sets a pod to use an image's resolv.conf and not
// create its own.
func WithPodUseImageResolvConf ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot configure pod DNS as no infra container is being created" )
}
2020-02-03 16:17:32 +00:00
if len ( pod . config . InfraContainer . DNSServer ) != 0 ||
len ( pod . config . InfraContainer . DNSSearch ) != 0 ||
len ( pod . config . InfraContainer . DNSOption ) != 0 {
return errors . Wrapf ( define . ErrInvalidArg , "requested use of image resolv.conf conflicts with already-configured DNS settings" )
}
pod . config . InfraContainer . UseImageResolvConf = true
return nil
}
}
// WithPodDNS sets the DNS Servers for a pod.
func WithPodDNS ( dnsServer [ ] string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot configure pod DNS as no infra container is being created" )
}
2020-02-03 16:17:32 +00:00
if pod . config . InfraContainer . UseImageResolvConf {
return errors . Wrapf ( define . ErrInvalidArg , "cannot add DNS servers if pod will not create /etc/resolv.conf" )
}
pod . config . InfraContainer . DNSServer = dnsServer
return nil
}
}
// WithPodDNSSearch sets the DNS Search domains for a pod.
func WithPodDNSSearch ( dnsSearch [ ] string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot configure pod DNS as no infra container is being created" )
}
2020-02-03 16:17:32 +00:00
if pod . config . InfraContainer . UseImageResolvConf {
return errors . Wrapf ( define . ErrInvalidArg , "cannot add DNS search domains if pod will not create /etc/resolv.conf" )
}
pod . config . InfraContainer . DNSSearch = dnsSearch
return nil
}
}
// WithPodDNSOption sets DNS Options for a pod.
func WithPodDNSOption ( dnsOption [ ] string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot configure pod DNS as no infra container is being created" )
}
2020-02-03 16:17:32 +00:00
if pod . config . InfraContainer . UseImageResolvConf {
return errors . Wrapf ( define . ErrInvalidArg , "cannot add DNS options if pod will not create /etc/resolv.conf" )
}
pod . config . InfraContainer . DNSOption = dnsOption
return nil
}
}
// WithPodUseImageHosts tells the pod not to create /etc/hosts and instead to
// use the one provided by the image.
func WithPodUseImageHosts ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot configure pod hosts as no infra container is being created" )
}
2020-02-03 16:17:32 +00:00
if len ( pod . config . InfraContainer . HostAdd ) != 0 {
return errors . Wrapf ( define . ErrInvalidArg , "not creating /etc/hosts conflicts with adding to the hosts file" )
}
pod . config . InfraContainer . UseImageHosts = true
return nil
}
}
// WithPodHosts adds additional entries to the pod's /etc/hosts
func WithPodHosts ( hosts [ ] string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot configure pod hosts as no infra container is being created" )
}
2020-02-03 16:17:32 +00:00
if pod . config . InfraContainer . UseImageHosts {
return errors . Wrapf ( define . ErrInvalidArg , "cannot add to /etc/hosts if container is using image hosts" )
}
pod . config . InfraContainer . HostAdd = hosts
return nil
}
}
// WithPodNetworks sets additional CNI networks for the pod to join.
func WithPodNetworks ( networks [ ] string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot configure pod CNI networks as no infra container is being created" )
}
2020-02-17 21:21:07 +00:00
if ( pod . config . InfraContainer . StaticIP != nil || pod . config . InfraContainer . StaticMAC != nil ) &&
len ( networks ) > 1 {
return errors . Wrapf ( define . ErrInvalidArg , "cannot join more than one CNI network if setting a static IP or MAC address" )
}
if pod . config . InfraContainer . HostNetwork {
return errors . Wrapf ( define . ErrInvalidArg , "cannot join pod to CNI networks if host network is specified" )
}
2020-02-03 16:17:32 +00:00
pod . config . InfraContainer . Networks = networks
return nil
}
}
2020-02-17 21:21:07 +00:00
2021-02-01 18:53:14 +00:00
// WithPodNoNetwork tells the pod to disable external networking.
func WithPodNoNetwork ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot disable pod networking as no infra container is being created" )
}
if len ( pod . config . InfraContainer . PortBindings ) > 0 ||
pod . config . InfraContainer . StaticIP != nil ||
pod . config . InfraContainer . StaticMAC != nil ||
len ( pod . config . InfraContainer . Networks ) > 0 ||
pod . config . InfraContainer . HostNetwork {
return errors . Wrapf ( define . ErrInvalidArg , "cannot disable pod network if network-related configuration is specified" )
}
pod . config . InfraContainer . NoNetwork = true
return nil
}
}
2020-02-17 21:21:07 +00:00
// WithPodHostNetwork tells the pod to use the host's network namespace.
func WithPodHostNetwork ( ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
2020-02-17 21:49:59 +00:00
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot configure pod host networking as no infra container is being created" )
}
2020-02-17 21:21:07 +00:00
if len ( pod . config . InfraContainer . PortBindings ) > 0 ||
pod . config . InfraContainer . StaticIP != nil ||
pod . config . InfraContainer . StaticMAC != nil ||
2021-02-01 18:53:14 +00:00
len ( pod . config . InfraContainer . Networks ) > 0 ||
pod . config . InfraContainer . NoNetwork {
2020-02-17 21:21:07 +00:00
return errors . Wrapf ( define . ErrInvalidArg , "cannot set host network if network-related configuration is specified" )
}
pod . config . InfraContainer . HostNetwork = true
return nil
}
}
Ensure pod infra containers have an exit command
Most Libpod containers are made via `pkg/specgen/generate` which
includes code to generate an appropriate exit command which will
handle unmounting the container's storage, cleaning up the
container's network, etc. There is one notable exception: pod
infra containers, which are made entirely within Libpod and do
not touch pkg/specgen. As such, no cleanup process, network never
cleaned up, bad things can happen.
There is good news, though - it's not that difficult to add this,
and it's done in this PR. Generally speaking, we don't allow
passing options directly to the infra container at create time,
but we do (optionally) proxy a pre-approved set of options into
it when we create it. Add ExitCommand to these options, and set
it at time of pod creation using the same code we use to generate
exit commands for normal containers.
Fixes #7103
Signed-off-by: Matthew Heon <mheon@redhat.com>
2020-08-10 19:00:42 +00:00
// WithPodInfraExitCommand sets an exit command for the pod's infra container.
// Semantics are identical to WithExitCommand() above - the ID of the container
// will be appended to the end of the provided command (note that this will
// specifically be the ID of the infra container *and not the pod's id*.
func WithPodInfraExitCommand ( exitCmd [ ] string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot configure pod infra container exit command as no infra container is being created" )
}
pod . config . InfraContainer . ExitCommand = exitCmd
return nil
}
}
2020-09-25 14:00:43 +00:00
// WithPodSlirp4netns tells the pod to use slirp4netns.
func WithPodSlirp4netns ( networkOptions map [ string ] [ ] string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
if ! pod . config . InfraContainer . HasInfraContainer {
return errors . Wrapf ( define . ErrInvalidArg , "cannot configure pod networking as no infra container is being created" )
}
if pod . config . InfraContainer . HostNetwork {
return errors . Wrapf ( define . ErrInvalidArg , "cannot set both HostNetwork and Slirp4netns" )
}
pod . config . InfraContainer . Slirp4netns = true
pod . config . InfraContainer . NetworkOptions = networkOptions
return nil
}
}
2021-05-05 13:44:29 +00:00
// WithVolatile sets the volatile flag for the container storage.
// The option can potentially cause data loss when used on a container that must survive a machine reboot.
func WithVolatile ( ) CtrCreateOption {
return func ( ctr * Container ) error {
if ctr . valid {
return define . ErrCtrFinalized
}
ctr . config . Volatile = true
return nil
}
}
2021-06-17 21:36:35 +00:00
// WithPodCPUPAQ takes the given cpu period and quota and inserts them in the proper place.
func WithPodCPUPAQ ( period uint64 , quota int64 ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
if pod . CPUPeriod ( ) != 0 && pod . CPUQuota ( ) != 0 {
pod . config . InfraContainer . ResourceLimits . CPU = & specs . LinuxCPU {
Period : & period ,
Quota : & quota ,
}
} else {
pod . config . InfraContainer . ResourceLimits = & specs . LinuxResources { }
pod . config . InfraContainer . ResourceLimits . CPU = & specs . LinuxCPU {
Period : & period ,
Quota : & quota ,
}
}
return nil
}
}
// WithPodCPUSetCPUS computes and sets the Cpus linux resource string which determines the amount of cores, from those available, we are allowed to execute on
func WithPodCPUSetCPUs ( inp string ) PodCreateOption {
return func ( pod * Pod ) error {
if pod . valid {
return define . ErrPodFinalized
}
if pod . ResourceLim ( ) . CPU . Period != nil {
pod . config . InfraContainer . ResourceLimits . CPU . Cpus = inp
} else {
pod . config . InfraContainer . ResourceLimits = & specs . LinuxResources { }
pod . config . InfraContainer . ResourceLimits . CPU = & specs . LinuxCPU { }
pod . config . InfraContainer . ResourceLimits . CPU . Cpus = inp
}
return nil
}
}
2021-07-07 21:00:30 +00:00
func WithPodPidNS ( inp specgen . Namespace ) PodCreateOption {
return func ( p * Pod ) error {
if p . valid {
return define . ErrPodFinalized
}
if p . config . UsePodPID {
switch inp . NSMode {
case "container" :
return errors . Wrap ( define . ErrInvalidArg , "Cannot take container in a different NS as an argument" )
case "host" :
p . config . UsePodPID = false
}
p . config . InfraContainer . PidNS = inp
}
return nil
}
}