diff options
98 files changed, 1514 insertions, 1515 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 3f3ab2ff4..0770e0702 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -39,7 +39,7 @@ env: UBUNTU_NAME: "ubuntu-19" PRIOR_UBUNTU_NAME: "ubuntu-18" - _BUILT_IMAGE_SUFFIX: "libpod-5940307564953600" + _BUILT_IMAGE_SUFFIX: "libpod-5633729662025728" FEDORA_CACHE_IMAGE_NAME: "${FEDORA_NAME}-${_BUILT_IMAGE_SUFFIX}" PRIOR_FEDORA_CACHE_IMAGE_NAME: "${PRIOR_FEDORA_NAME}-${_BUILT_IMAGE_SUFFIX}" UBUNTU_CACHE_IMAGE_NAME: "${UBUNTU_NAME}-${_BUILT_IMAGE_SUFFIX}" @@ -195,9 +195,9 @@ vendor_task: - "gating" env: - CIRRUS_WORKING_DIR: "/usr/src/libpod" - GOPATH: "/go" - GOSRC: "/go/src/github.com/containers/libpod" + CIRRUS_WORKING_DIR: "/var/tmp/go/src/github.com/containers/libpod" + GOPATH: "/var/tmp/go" + GOSRC: "$CIRRUS_WORKING_DIR" # Runs within Cirrus's "community cluster" container: @@ -1296,6 +1296,10 @@ password [string](https://godoc.org/builtin#string) BuildInfo is used to describe user input for building images +architecture [string](https://godoc.org/builtin#string) + +addCapabilities [[]string](#[]string) + additionalTags [[]string](#[]string) annotations [[]string](#[]string) @@ -1314,8 +1318,12 @@ contextDir [string](https://godoc.org/builtin#string) defaultsMountFilePath [string](https://godoc.org/builtin#string) +devices [[]string](#[]string) + dockerfiles [[]string](#[]string) +dropCapabilities [[]string](#[]string) + err [string](https://godoc.org/builtin#string) forceRmIntermediateCtrs [bool](https://godoc.org/builtin#bool) @@ -1328,6 +1336,8 @@ layers [bool](https://godoc.org/builtin#bool) nocache [bool](https://godoc.org/builtin#bool) +os [string](https://godoc.org/builtin#string) + out [string](https://godoc.org/builtin#string) output [string](https://godoc.org/builtin#string) @@ -1344,7 +1354,13 @@ reportWriter [string](https://godoc.org/builtin#string) runtimeArgs [[]string](#[]string) +signBy [string](https://godoc.org/builtin#string) + squash [bool](https://godoc.org/builtin#bool) + +target [string](https://godoc.org/builtin#string) + +transientMounts [[]string](#[]string) ### <a name="BuildOptions"></a>type BuildOptions BuildOptions are are used to describe describe physical attributes of the build diff --git a/cmd/podman/attach.go b/cmd/podman/attach.go index 7d32c57af..6f08cc396 100644 --- a/cmd/podman/attach.go +++ b/cmd/podman/attach.go @@ -2,7 +2,6 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -32,10 +31,7 @@ func init() { attachCommand.SetHelpTemplate(HelpTemplate()) attachCommand.SetUsageTemplate(UsageTemplate()) flags := attachCommand.Flags() - flags.StringVar(&attachCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") - // Clear the default, the value specified in the config file should have the - // priority - attachCommand.DetachKeys = "" + flags.StringVar(&attachCommand.DetachKeys, "detach-keys", getDefaultDetachKeys(), "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") flags.BoolVar(&attachCommand.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false") flags.BoolVar(&attachCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process") flags.BoolVarP(&attachCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") diff --git a/cmd/podman/build.go b/cmd/podman/build.go index acd402fdd..04bc56ab0 100644 --- a/cmd/podman/build.go +++ b/cmd/podman/build.go @@ -9,9 +9,9 @@ import ( "github.com/containers/buildah" "github.com/containers/buildah/imagebuildah" buildahcli "github.com/containers/buildah/pkg/cli" - "github.com/containers/image/v5/types" + "github.com/containers/buildah/pkg/parse" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" @@ -86,6 +86,7 @@ func initBuild() { fromAndBugFlags, err := buildahcli.GetFromAndBudFlags(&fromAndBudValues, &userNSValues, &namespaceValues) if err != nil { logrus.Errorf("failed to setup podman build flags: %v", err) + os.Exit(1) } flags.AddFlagSet(&budFlags) @@ -267,14 +268,15 @@ func buildCmd(c *cliconfig.BuildValues) error { if err != nil { return err } - if conf != nil && conf.CgroupManager == define.SystemdCgroupsManager { + if conf != nil && conf.Engine.CgroupManager == config.SystemdCgroupsManager { runtimeFlags = append(runtimeFlags, "--systemd-cgroup") } // end from buildah defer runtime.DeferredShutdown(false) - var stdout, stderr, reporter *os.File + var stdin, stdout, stderr, reporter *os.File + stdin = os.Stdin stdout = os.Stdout stderr = os.Stderr reporter = os.Stderr @@ -310,6 +312,17 @@ func buildCmd(c *cliconfig.BuildValues) error { return err } + networkPolicy := buildah.NetworkDefault + for _, ns := range nsValues { + if ns.Name == "none" { + networkPolicy = buildah.NetworkDisabled + break + } else if !filepath.IsAbs(ns.Path) { + networkPolicy = buildah.NetworkEnabled + break + } + } + buildOpts := buildah.CommonBuildOptions{ AddHost: c.AddHost, CgroupParent: c.CgroupParent, @@ -341,21 +354,49 @@ func buildCmd(c *cliconfig.BuildValues) error { layers = false } + compression := imagebuildah.Gzip + if c.DisableCompression { + compression = imagebuildah.Uncompressed + } + + isolation, err := parse.IsolationOption(c.Isolation) + if err != nil { + return errors.Wrapf(err, "error parsing ID mapping options") + } + + usernsOption, idmappingOptions, err := parse.IDMappingOptions(c.PodmanCommand.Command, isolation) + if err != nil { + return errors.Wrapf(err, "error parsing ID mapping options") + } + nsValues = append(nsValues, usernsOption...) + + systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command) + if err != nil { + return errors.Wrapf(err, "error building system context") + } + options := imagebuildah.BuildOptions{ - Architecture: c.Arch, - CommonBuildOpts: &buildOpts, + AddCapabilities: c.CapAdd, AdditionalTags: tags, Annotations: c.Annotation, + Architecture: c.Arch, Args: args, + BlobDirectory: c.BlobCache, CNIConfigDir: c.CNIConfigDir, CNIPluginPath: c.CNIPlugInPath, - Compression: imagebuildah.Gzip, + CommonBuildOpts: &buildOpts, + Compression: compression, + ConfigureNetwork: networkPolicy, ContextDirectory: contextDir, DefaultMountsFilePath: c.GlobalFlags.DefaultMountsFile, + Devices: c.Devices, + DropCapabilities: c.CapDrop, Err: stderr, - In: os.Stdin, ForceRmIntermediateCtrs: c.ForceRm, + IDMappingOptions: idmappingOptions, IIDFile: c.Iidfile, + In: stdin, + Isolation: isolation, Labels: c.Label, Layers: layers, NamespaceOptions: nsValues, @@ -369,13 +410,12 @@ func buildCmd(c *cliconfig.BuildValues) error { RemoveIntermediateCtrs: c.Rm, ReportWriter: reporter, RuntimeArgs: runtimeFlags, + SignBy: c.SignBy, SignaturePolicyPath: c.SignaturePolicy, Squash: c.Squash, - SystemContext: &types.SystemContext{ - OSChoice: c.OverrideOS, - ArchitectureChoice: c.OverrideArch, - }, - Target: c.Target, + SystemContext: systemContext, + Target: c.Target, + TransientMounts: c.Volumes, } _, _, err = runtime.Build(getContext(), c, options, containerfiles) return err diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go index 3428746a9..faf292ea0 100644 --- a/cmd/podman/cliconfig/config.go +++ b/cmd/podman/cliconfig/config.go @@ -2,7 +2,10 @@ package cliconfig import ( "net" + "os" + "github.com/containers/common/pkg/config" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -700,3 +703,14 @@ type SystemDfValues struct { type UntagValues struct { PodmanCommand } + +func GetDefaultConfig() *config.Config { + var err error + conf, err := config.NewConfig("") + conf.CheckCgroupsAndAdjustConfig() + if err != nil { + logrus.Errorf("Error loading container config %v\n", err) + os.Exit(1) + } + return conf +} diff --git a/cmd/podman/cliconfig/defaults.go b/cmd/podman/cliconfig/defaults.go index ce695d153..3082207e0 100644 --- a/cmd/podman/cliconfig/defaults.go +++ b/cmd/podman/cliconfig/defaults.go @@ -11,6 +11,4 @@ var ( DefaultHealthCheckTimeout = "30s" // DefaultImageVolume default value DefaultImageVolume = "bind" - // DefaultShmSize default value - DefaultShmSize = "65536k" ) diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index dfa04315e..2ee31b643 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -3,6 +3,15 @@ package main import ( + "fmt" + "os" + + "github.com/containers/buildah/pkg/parse" + "github.com/containers/libpod/pkg/apparmor" + "github.com/containers/libpod/pkg/cgroups" + "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/sysinfo" + "github.com/opencontainers/selinux/go-selinux" "github.com/spf13/cobra" ) @@ -81,3 +90,107 @@ func getSystemSubCommands() []*cobra.Command { return systemCommands } + +func getDefaultSecurityOptions() []string { + securityOpts := []string{} + if defaultContainerConfig.Containers.SeccompProfile != "" && defaultContainerConfig.Containers.SeccompProfile != parse.SeccompDefaultPath { + securityOpts = append(securityOpts, fmt.Sprintf("seccomp=%s", defaultContainerConfig.Containers.SeccompProfile)) + } + if apparmor.IsEnabled() && defaultContainerConfig.Containers.ApparmorProfile != "" { + securityOpts = append(securityOpts, fmt.Sprintf("apparmor=%s", defaultContainerConfig.Containers.ApparmorProfile)) + } + if selinux.GetEnabled() && !defaultContainerConfig.Containers.EnableLabeling { + securityOpts = append(securityOpts, fmt.Sprintf("label=%s", selinux.DisableSecOpt()[0])) + } + return securityOpts +} + +// getDefaultSysctls +func getDefaultSysctls() []string { + return defaultContainerConfig.Containers.DefaultSysctls +} + +func getDefaultVolumes() []string { + return defaultContainerConfig.Containers.Volumes +} + +func getDefaultDevices() []string { + return defaultContainerConfig.Containers.Devices +} + +func getDefaultDNSServers() []string { + return defaultContainerConfig.Containers.DNSServers +} + +func getDefaultDNSSearches() []string { + return defaultContainerConfig.Containers.DNSSearches +} + +func getDefaultDNSOptions() []string { + return defaultContainerConfig.Containers.DNSOptions +} + +func getDefaultEnv() []string { + return defaultContainerConfig.Containers.Env +} + +func getDefaultInitPath() string { + return defaultContainerConfig.Containers.InitPath +} + +func getDefaultIPCNS() string { + return defaultContainerConfig.Containers.IPCNS +} + +func getDefaultPidNS() string { + return defaultContainerConfig.Containers.PidNS +} + +func getDefaultNetNS() string { + if defaultContainerConfig.Containers.NetNS == "private" && rootless.IsRootless() { + return "slirp4netns" + } + return defaultContainerConfig.Containers.NetNS +} + +func getDefaultCgroupNS() string { + return defaultContainerConfig.Containers.CgroupNS +} + +func getDefaultUTSNS() string { + return defaultContainerConfig.Containers.UTSNS +} + +func getDefaultShmSize() string { + return defaultContainerConfig.Containers.ShmSize +} + +func getDefaultUlimits() []string { + return defaultContainerConfig.Containers.DefaultUlimits +} + +func getDefaultUserNS() string { + userns := os.Getenv("PODMAN_USERNS") + if userns != "" { + return userns + } + return defaultContainerConfig.Containers.UserNS +} + +func getDefaultPidsLimit() int64 { + if rootless.IsRootless() { + cgroup2, _ := cgroups.IsCgroup2UnifiedMode() + if cgroup2 { + return defaultContainerConfig.Containers.PidsLimit + } + } + return sysinfo.GetDefaultPidsLimit() +} + +func getDefaultPidsDescription() string { + return "Tune container pids limit (set 0 for unlimited)" +} + +func getDefaultDetachKeys() string { + return defaultContainerConfig.Engine.DetachKeys +} diff --git a/cmd/podman/commands_remoteclient.go b/cmd/podman/commands_remoteclient.go index a278761c1..ef523ffb1 100644 --- a/cmd/podman/commands_remoteclient.go +++ b/cmd/podman/commands_remoteclient.go @@ -47,3 +47,89 @@ func getTrustSubCommands() []*cobra.Command { func getSystemSubCommands() []*cobra.Command { return []*cobra.Command{} } + +func getDefaultSecurityOptions() []string { + return []string{} +} + +// getDefaultSysctls +func getDefaultSysctls() []string { + return []string{} +} + +// getDefaultDevices +func getDefaultDevices() []string { + return []string{} +} + +func getDefaultVolumes() []string { + return []string{} +} + +func getDefaultDNSServers() []string { + return []string{} +} + +func getDefaultDNSSearches() []string { + return []string{} +} + +func getDefaultDNSOptions() []string { + return []string{} +} + +func getDefaultEnv() []string { + return []string{} +} + +func getDefaultInitPath() string { + return "" +} + +func getDefaultIPCNS() string { + return "" +} + +func getDefaultPidNS() string { + return "" +} + +func getDefaultNetNS() string { + return "" +} + +func getDefaultCgroupNS() string { + return "" +} + +func getDefaultUTSNS() string { + return "" +} + +func getDefaultShmSize() string { + return "" +} + +func getDefaultUlimits() []string { + return []string{} +} + +func getDefaultUserNS() string { + return "" +} + +func getDefaultPidsLimit() int64 { + return -1 +} + +func getDefaultPidsDescription() string { + return "Tune container pids limit (set 0 for unlimited, -1 for server defaults)" +} + +func getDefaultShareNetwork() string { + return "" +} + +func getDefaultDetachKeys() string { + return "" +} diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 4eeb09d42..9aa9a63fe 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -3,15 +3,11 @@ package main import ( "context" "fmt" - "os" "strings" "github.com/containers/buildah" buildahcli "github.com/containers/buildah/pkg/cli" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/rootless" - "github.com/containers/libpod/pkg/sysinfo" "github.com/containers/libpod/pkg/util/camelcase" jsoniter "github.com/json-iterator/go" "github.com/pkg/errors" @@ -110,29 +106,22 @@ func getContext() context.Context { return context.TODO() } -func getDefaultNetwork() string { - if rootless.IsRootless() { - return "slirp4netns" - } - return "bridge" -} - func getNetFlags() *pflag.FlagSet { netFlags := pflag.FlagSet{} netFlags.StringSlice( "add-host", []string{}, - "Add a custom host-to-IP mapping (host:ip) (default [])", + "Add a custom host-to-IP mapping (host:ip)", ) netFlags.StringSlice( - "dns", []string{}, + "dns", getDefaultDNSServers(), "Set custom DNS servers", ) netFlags.StringSlice( - "dns-opt", []string{}, + "dns-opt", getDefaultDNSOptions(), "Set custom DNS options", ) netFlags.StringSlice( - "dns-search", []string{}, + "dns-search", getDefaultDNSSearches(), "Set custom DNS search domains", ) netFlags.String( @@ -144,7 +133,7 @@ func getNetFlags() *pflag.FlagSet { "Container MAC address (e.g. 92:d0:c6:0a:29:33)", ) netFlags.String( - "network", getDefaultNetwork(), + "network", getDefaultNetNS(), "Connect a container to a network", ) netFlags.StringSliceP( @@ -162,11 +151,11 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { createFlags := c.Flags() createFlags.StringSlice( "annotation", []string{}, - "Add annotations to container (key:value) (default [])", + "Add annotations to container (key:value)", ) createFlags.StringSliceP( "attach", "a", []string{}, - "Attach to STDIN, STDOUT or STDERR (default [])", + "Attach to STDIN, STDOUT or STDERR", ) createFlags.String( "authfile", buildahcli.GetDefaultAuthFile(), @@ -189,7 +178,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "Drop capabilities from the container", ) createFlags.String( - "cgroupns", "", + "cgroupns", getDefaultCgroupNS(), "cgroup namespace to use", ) createFlags.String( @@ -244,17 +233,13 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "detach", "d", false, "Run container in background and print container ID", ) - detachKeys := createFlags.String( - "detach-keys", define.DefaultDetachKeys, + createFlags.String( + "detach-keys", getDefaultDetachKeys(), "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`", ) - // Clear the default, the value specified in the config file should have the - // priority - *detachKeys = "" - createFlags.StringSlice( - "device", []string{}, - "Add a host device to the container (default [])", + "device", getDefaultDevices(), + fmt.Sprintf("Add a host device to the container"), ) createFlags.StringSlice( "device-cgroup-rule", []string{}, @@ -281,7 +266,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "Overwrite the default ENTRYPOINT of the image", ) createFlags.StringArrayP( - "env", "e", []string{}, + "env", "e", getDefaultEnv(), "Set environment variables in container", ) createFlags.Bool( @@ -293,7 +278,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringSlice( "expose", []string{}, - "Expose a port or a range of ports (default [])", + "Expose a port or a range of ports", ) createFlags.StringSlice( "gidmap", []string{}, @@ -301,7 +286,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringSlice( "group-add", []string{}, - "Add additional groups to join (default [])", + "Add additional groups to join", ) createFlags.Bool( "help", false, "", @@ -343,16 +328,16 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "Run an init binary inside the container that forwards signals and reaps processes", ) createFlags.String( - "init-path", "", + "init-path", getDefaultInitPath(), // Do not use the Value field for setting the default value to determine user input (i.e., non-empty string) - fmt.Sprintf("Path to the container-init binary (default: %q)", define.DefaultInitPath), + fmt.Sprintf("Path to the container-init binary"), ) createFlags.BoolP( "interactive", "i", false, "Keep STDIN open even if not attached", ) createFlags.String( - "ipc", "", + "ipc", getDefaultIPCNS(), "IPC namespace to use", ) createFlags.String( @@ -361,11 +346,11 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringArrayP( "label", "l", []string{}, - "Set metadata on container (default [])", + "Set metadata on container", ) createFlags.StringSlice( "label-file", []string{}, - "Read in a line delimited file of labels (default [])", + "Read in a line delimited file of labels", ) createFlags.String( "log-driver", "", @@ -373,7 +358,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringSlice( "log-opt", []string{}, - "Logging driver options (default [])", + "Logging driver options", ) createFlags.StringP( "memory", "m", "", @@ -418,12 +403,12 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) markFlagHidden(createFlags, "override-os") createFlags.String( - "pid", "", + "pid", getDefaultPidNS(), "PID namespace to use", ) createFlags.Int64( - "pids-limit", sysinfo.GetDefaultPidsLimit(), - "Tune container pids limit (set 0 for unlimited)", + "pids-limit", getDefaultPidsLimit(), + getDefaultPidsDescription(), ) createFlags.String( "pod", "", @@ -466,11 +451,11 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "The first argument is not an image but the rootfs to the exploded container", ) createFlags.StringArray( - "security-opt", []string{}, - "Security Options (default [])", + "security-opt", getDefaultSecurityOptions(), + fmt.Sprintf("Security Options"), ) createFlags.String( - "shm-size", cliconfig.DefaultShmSize, + "shm-size", getDefaultShmSize(), "Size of /dev/shm "+sizeWithUnitFormat, ) createFlags.String( @@ -478,12 +463,12 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "Signal to stop a container. Default is SIGTERM", ) createFlags.Uint( - "stop-timeout", define.CtrRemoveTimeout, + "stop-timeout", defaultContainerConfig.Engine.StopTimeout, "Timeout (in seconds) to stop a container. Default is 10", ) createFlags.StringSlice( "storage-opt", []string{}, - "Storage driver options per container (default [])", + "Storage driver options per container", ) createFlags.String( "subgidname", "", @@ -495,8 +480,8 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringSlice( - "sysctl", []string{}, - "Sysctl options (default [])", + "sysctl", getDefaultSysctls(), + "Sysctl options", ) createFlags.String( "systemd", "true", @@ -504,7 +489,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.StringArray( "tmpfs", []string{}, - "Mount a temporary filesystem (`tmpfs`) into a container (default [])", + "Mount a temporary filesystem (`tmpfs`) into a container", ) createFlags.BoolP( "tty", "t", false, @@ -515,32 +500,32 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "UID map to use for the user namespace", ) createFlags.StringSlice( - "ulimit", []string{}, - "Ulimit options (default [])", + "ulimit", getDefaultUlimits(), + "Ulimit options", ) createFlags.StringP( "user", "u", "", "Username or UID (format: <name|uid>[:<group|gid>])", ) createFlags.String( - "userns", os.Getenv("PODMAN_USERNS"), + "userns", getDefaultUserNS(), "User namespace to use", ) createFlags.String( - "uts", "", + "uts", getDefaultUTSNS(), "UTS namespace to use", ) createFlags.StringArray( "mount", []string{}, - "Attach a filesystem mount to the container (default [])", + "Attach a filesystem mount to the container", ) createFlags.StringArrayP( - "volume", "v", []string{}, - "Bind mount a volume into the container (default [])", + "volume", "v", getDefaultVolumes(), + "Bind mount a volume into the container", ) createFlags.StringSlice( "volumes-from", []string{}, - "Mount volumes from the specified container(s) (default [])", + "Mount volumes from the specified container(s)", ) createFlags.StringP( "workdir", "w", "", diff --git a/cmd/podman/create.go b/cmd/podman/create.go index 73d62bddb..03eb1b09f 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -38,7 +38,6 @@ func init() { createCommand.PodmanCommand.Command = _createCommand createCommand.SetHelpTemplate(HelpTemplate()) createCommand.SetUsageTemplate(UsageTemplate()) - getCreateFlags(&createCommand.PodmanCommand) flags := createCommand.Flags() flags.AddFlagSet(getNetFlags()) diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go index 6e5799396..b341ab496 100644 --- a/cmd/podman/exec.go +++ b/cmd/podman/exec.go @@ -2,7 +2,6 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -35,10 +34,7 @@ func init() { execCommand.SetUsageTemplate(UsageTemplate()) flags := execCommand.Flags() flags.SetInterspersed(false) - flags.StringVar(&execCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _") - // Clear the default, the value specified in the config file should have the - // priority - execCommand.DetachKeys = "" + flags.StringVar(&execCommand.DetachKeys, "detach-keys", getDefaultDetachKeys(), "Select the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _") flags.StringArrayVarP(&execCommand.Env, "env", "e", []string{}, "Set environment variables") flags.StringSliceVar(&execCommand.EnvFile, "env-file", []string{}, "Read in a file of environment variables") flags.BoolVarP(&execCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go index e9dc87de1..8dbc4009b 100644 --- a/cmd/podman/libpodruntime/runtime.go +++ b/cmd/podman/libpodruntime/runtime.go @@ -211,8 +211,6 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, opts *runtimeOp if !opts.withFDS { options = append(options, libpod.WithEnableSDNotify()) } - if c.Flags().Changed("config") { - return libpod.NewRuntimeFromConfig(ctx, c.GlobalFlags.Config, options...) - } + return libpod.NewRuntime(ctx, options...) } diff --git a/cmd/podman/main.go b/cmd/podman/main.go index a2acbbf53..5134448da 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -6,6 +6,7 @@ import ( "os" "path" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" @@ -81,7 +82,10 @@ var rootCmd = &cobra.Command{ SilenceErrors: true, } -var MainGlobalOpts cliconfig.MainFlags +var ( + MainGlobalOpts cliconfig.MainFlags + defaultContainerConfig = getDefaultContainerConfig() +) func initCobra() { cobra.OnInitialize(initConfig) @@ -175,3 +179,12 @@ func main() { CheckForRegistries() os.Exit(exitCode) } + +func getDefaultContainerConfig() *config.Config { + defaultContainerConfig, err := config.Default() + if err != nil { + logrus.Error(err) + os.Exit(1) + } + return defaultContainerConfig +} diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go index 79b5e5af7..b03c7de44 100644 --- a/cmd/podman/main_local.go +++ b/cmd/podman/main_local.go @@ -14,9 +14,9 @@ import ( "strings" "syscall" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/libpodruntime" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/tracing" @@ -32,9 +32,11 @@ import ( const remote = false func init() { - cgroupManager := define.SystemdCgroupsManager + cgroupManager := defaultContainerConfig.Engine.CgroupManager cgroupHelp := `Cgroup manager to use ("cgroupfs"|"systemd")` cgroupv2, _ := cgroups.IsCgroup2UnifiedMode() + + defaultContainerConfig = cliconfig.GetDefaultConfig() if rootless.IsRootless() && !cgroupv2 { cgroupManager = "" cgroupHelp = "Cgroup manager is not supported in rootless mode" @@ -42,25 +44,27 @@ func init() { rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CGroupManager, "cgroup-manager", cgroupManager, cgroupHelp) // -c is deprecated due to conflict with -c on subcommands rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CpuProfile, "cpu-profile", "", "Path for the cpu profiling results") - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Config, "config", "", "Path of a libpod config file detailing container server configuration options") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.ConmonPath, "conmon", "", "Path of the conmon binary") - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.NetworkCmdPath, "network-cmd-path", "", "Path to the command for configuring the network") - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CniConfigDir, "cni-config-dir", "", "Path of the configuration directory for CNI networks") - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.DefaultMountsFile, "default-mounts-file", "", "Path to default mounts file") + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.NetworkCmdPath, "network-cmd-path", defaultContainerConfig.Engine.NetworkCmdPath, "Path to the command for configuring the network") + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.CniConfigDir, "cni-config-dir", getCNIPluginsDir(), "Path of the configuration directory for CNI networks") + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.DefaultMountsFile, "default-mounts-file", defaultContainerConfig.Containers.DefaultMountsFile, "Path to default mounts file") + if err := rootCmd.PersistentFlags().MarkHidden("cpu-profile"); err != nil { + logrus.Error("unable to mark default-mounts-file flag as hidden") + } if err := rootCmd.PersistentFlags().MarkHidden("default-mounts-file"); err != nil { logrus.Error("unable to mark default-mounts-file flag as hidden") } - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.EventsBackend, "events-backend", "", `Events backend to use ("file"|"journald"|"none")`) + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.EventsBackend, "events-backend", defaultContainerConfig.Engine.EventsLogger, `Events backend to use ("file"|"journald"|"none")`) // Override default --help information of `--help` global flag var dummyHelp bool rootCmd.PersistentFlags().BoolVar(&dummyHelp, "help", false, "Help for podman") - rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.HooksDir, "hooks-dir", []string{}, "Set the OCI hooks directory path (may be set multiple times)") + rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.HooksDir, "hooks-dir", defaultContainerConfig.Engine.HooksDir, "Set the OCI hooks directory path (may be set multiple times)") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.LogLevel, "log-level", "error", `Log messages above specified level ("debug"|"info"|"warn"|"error"|"fatal"|"panic")`) rootCmd.PersistentFlags().IntVar(&MainGlobalOpts.MaxWorks, "max-workers", 0, "The maximum number of workers for parallel operations") if err := rootCmd.PersistentFlags().MarkHidden("max-workers"); err != nil { logrus.Error("unable to mark max-workers flag as hidden") } - rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Namespace, "namespace", "", "Set the libpod namespace, used to create separate views of the containers and pods on the system") + rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Namespace, "namespace", defaultContainerConfig.Engine.Namespace, "Set the libpod namespace, used to create separate views of the containers and pods on the system") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Root, "root", "", "Path to the root directory in which data, including images, is stored") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored") rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runtime, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc") @@ -179,7 +183,7 @@ func setupRootless(cmd *cobra.Command, args []string) error { if !ownsCgroup { unitName := fmt.Sprintf("podman-%d.scope", os.Getpid()) if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil { - if conf.CgroupManager == define.SystemdCgroupsManager { + if conf.Engine.CgroupManager == config.SystemdCgroupsManager { logrus.Warnf("Failed to add podman to systemd sandbox cgroup: %v", err) } else { logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err) @@ -223,7 +227,7 @@ func setupRootless(cmd *cobra.Command, args []string) error { if err != nil { return err } - if conf.CgroupManager == define.SystemdCgroupsManager { + if conf.Engine.CgroupManager == config.SystemdCgroupsManager { logrus.Warnf("Failed to add pause process to systemd sandbox cgroup: %v", err) } else { logrus.Debugf("Failed to add pause process to systemd sandbox cgroup: %v", err) @@ -264,3 +268,10 @@ func setUMask() { func checkInput() error { return nil } +func getCNIPluginsDir() string { + if rootless.IsRootless() { + return "" + } + + return defaultContainerConfig.Network.CNIPluginDirs[0] +} diff --git a/cmd/podman/mount.go b/cmd/podman/mount.go index 526a236fd..99e185589 100644 --- a/cmd/podman/mount.go +++ b/cmd/podman/mount.go @@ -68,11 +68,7 @@ func mountCmd(c *cliconfig.MountValues) error { defer runtime.DeferredShutdown(false) if os.Geteuid() != 0 { - rtc, err := runtime.GetConfig() - if err != nil { - return err - } - if driver := rtc.StorageConfig.GraphDriverName; driver != "vfs" { + if driver := runtime.StorageConfig().GraphDriverName; driver != "vfs" { // Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part // of the mount command. return fmt.Errorf("cannot mount using driver %s in rootless mode", driver) diff --git a/cmd/podman/restart.go b/cmd/podman/restart.go index 996a9f7ce..a55f83c67 100644 --- a/cmd/podman/restart.go +++ b/cmd/podman/restart.go @@ -39,9 +39,10 @@ func init() { flags.BoolVarP(&restartCommand.All, "all", "a", false, "Restart all non-running containers") flags.BoolVarP(&restartCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&restartCommand.Running, "running", false, "Restart only running containers when --all is used") - flags.UintVarP(&restartCommand.Timeout, "timeout", "t", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") - flags.UintVar(&restartCommand.Timeout, "time", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") + flags.UintVarP(&restartCommand.Timeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") + flags.UintVar(&restartCommand.Timeout, "timeout", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") + markFlagHidden(flags, "timeout") markFlagHiddenForRemoteClient("latest", flags) } diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index cec837af6..5fa8d6c0b 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -99,7 +99,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. ArchitectureChoice: overrideArch, } - newImage, err := runtime.ImageRuntime().New(ctx, rawImageName, rtc.SignaturePolicyPath, c.String("authfile"), writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullType) + newImage, err := runtime.ImageRuntime().New(ctx, rawImageName, rtc.Engine.SignaturePolicyPath, c.String("authfile"), writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullType) if err != nil { return nil, nil, err } @@ -512,6 +512,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. } // Start with env-host + if c.Bool("env-host") { env = envLib.Join(env, osEnv) } @@ -635,7 +636,6 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. if err != nil { return nil, errors.Wrapf(err, "unable to translate --shm-size") } - // Verify the additional hosts are in correct format for _, host := range c.StringSlice("add-host") { if _, err := parse.ValidateExtraHost(host); err != nil { @@ -643,24 +643,35 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. } } - // Check for . and dns-search domains - if util.StringInSlice(".", c.StringSlice("dns-search")) && len(c.StringSlice("dns-search")) > 1 { - return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'") + var ( + dnsSearches []string + dnsServers []string + dnsOptions []string + ) + if c.Changed("dns-search") { + dnsSearches = c.StringSlice("dns-search") + // Check for explicit dns-search domain of '' + if len(dnsSearches) == 0 { + return nil, errors.Errorf("'' is not a valid domain") + } + // Validate domains are good + for _, dom := range dnsSearches { + if dom == "." { + if len(dnsSearches) > 1 { + return nil, errors.Errorf("cannot pass additional search domains when also specifying '.'") + } + continue + } + if _, err := parse.ValidateDomain(dom); err != nil { + return nil, err + } + } } - - // Check for explicit dns-search domain of '' - if c.Changed("dns-search") && len(c.StringSlice("dns-search")) == 0 { - return nil, errors.Errorf("'' is not a valid domain") + if c.IsSet("dns") { + dnsServers = append(dnsServers, c.StringSlice("dns")...) } - - // Validate domains are good - for _, dom := range c.StringSlice("dns-search") { - if dom == "." { - continue - } - if _, err := parse.ValidateDomain(dom); err != nil { - return nil, err - } + if c.IsSet("dns-opt") { + dnsOptions = c.StringSlice("dns-opt") } var ImageVolumes map[string]struct{} @@ -706,7 +717,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. pidsLimit := c.Int64("pids-limit") if c.String("cgroups") == "disabled" && !c.Changed("pids-limit") { - pidsLimit = 0 + pidsLimit = -1 } pid := &cc.PidConfig{ @@ -736,11 +747,10 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. HostAdd: c.StringSlice("add-host"), Hostname: c.String("hostname"), } - net := &cc.NetworkConfig{ - DNSOpt: c.StringSlice("dns-opt"), - DNSSearch: c.StringSlice("dns-search"), - DNSServers: c.StringSlice("dns"), + DNSOpt: dnsOptions, + DNSSearch: dnsSearches, + DNSServers: dnsServers, HTTPProxy: c.Bool("http-proxy"), MacAddress: c.String("mac-address"), Network: c.String("network"), @@ -751,9 +761,12 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. PortBindings: portBindings, } - sysctl, err := validateSysctl(c.StringSlice("sysctl")) - if err != nil { - return nil, errors.Wrapf(err, "invalid value for sysctl") + sysctl := map[string]string{} + if c.Changed("sysctl") { + sysctl, err = util.ValidateSysctls(c.StringSlice("sysctl")) + if err != nil { + return nil, errors.Wrapf(err, "invalid value for sysctl") + } } secConfig := &cc.SecurityConfig{ @@ -765,8 +778,10 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. Sysctl: sysctl, } - if err := secConfig.SetSecurityOpts(runtime, c.StringArray("security-opt")); err != nil { - return nil, err + if c.Changed("security-opt") { + if err := secConfig.SetSecurityOpts(runtime, c.StringArray("security-opt")); err != nil { + return nil, err + } } // SECCOMP @@ -780,6 +795,19 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. } else { secConfig.SeccompPolicy = policy } + rtc, err := runtime.GetConfig() + if err != nil { + return nil, err + } + volumes := rtc.Containers.Volumes + if c.Changed("volume") { + volumes = append(volumes, c.StringSlice("volume")...) + } + + devices := rtc.Containers.Devices + if c.Changed("device") { + devices = append(devices, c.StringSlice("device")...) + } config := &cc.CreateConfig{ Annotations: annotations, @@ -790,7 +818,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. Command: command, UserCommand: userCommand, Detach: c.Bool("detach"), - Devices: c.StringSlice("device"), + Devices: devices, Entrypoint: entrypoint, Env: env, // ExposedPorts: ports, @@ -845,7 +873,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. Tmpfs: c.StringArray("tmpfs"), Tty: tty, MountsFlag: c.StringArray("mount"), - Volumes: c.StringArray("volume"), + Volumes: volumes, WorkDir: workDir, Rootfs: rootfs, VolumesFrom: c.StringSlice("volumes-from"), diff --git a/cmd/podman/shared/intermediate_varlink.go b/cmd/podman/shared/intermediate_varlink.go index 691c4f92d..d2b048025 100644 --- a/cmd/podman/shared/intermediate_varlink.go +++ b/cmd/podman/shared/intermediate_varlink.go @@ -316,6 +316,7 @@ func intFromVarlink(v *int64, flagName string, defaultValue *int) CRInt { // structure. func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults { + defaultContainerConfig := cliconfig.GetDefaultConfig() // TODO | WARN // We do not get a default network over varlink. Unlike the other default values for some cli // elements, it seems it gets set to the default anyway. @@ -405,7 +406,7 @@ func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults { m["rm"] = boolFromVarlink(opts.Rm, "rm", false) m["rootfs"] = boolFromVarlink(opts.Rootfs, "rootfs", false) m["security-opt"] = stringArrayFromVarlink(opts.SecurityOpt, "security-opt", nil) - m["shm-size"] = stringFromVarlink(opts.ShmSize, "shm-size", &cliconfig.DefaultShmSize) + m["shm-size"] = stringFromVarlink(opts.ShmSize, "shm-size", &defaultContainerConfig.Containers.ShmSize) m["stop-signal"] = stringFromVarlink(opts.StopSignal, "stop-signal", nil) m["stop-timeout"] = uintFromVarlink(opts.StopTimeout, "stop-timeout", nil) m["storage-opt"] = stringSliceFromVarlink(opts.StorageOpt, "storage-opt", nil) diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go index 8ac59b33b..7da3459cf 100644 --- a/cmd/podman/sign.go +++ b/cmd/podman/sign.go @@ -126,19 +126,14 @@ func signCmd(c *cliconfig.SignValues) error { if err != nil { return err } - newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, &dockerRegistryOptions, image.SigningOptions{SignBy: signby}, nil, util.PullImageMissing) + newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.Engine.SignaturePolicyPath, "", os.Stderr, &dockerRegistryOptions, image.SigningOptions{SignBy: signby}, nil, util.PullImageMissing) if err != nil { return errors.Wrapf(err, "error pulling image %s", signimage) } if rootless.IsRootless() { if sigStoreDir == "" { - runtimeConfig, err := runtime.GetConfig() - if err != nil { - return err - } - - sigStoreDir = filepath.Join(filepath.Dir(runtimeConfig.StorageConfig.GraphRoot), "sigstore") + sigStoreDir = filepath.Join(filepath.Dir(runtime.StorageConfig().GraphRoot), "sigstore") } } else { registryInfo := trust.HaveMatchRegistry(rawSource.Reference().DockerReference().String(), registryConfigs) diff --git a/cmd/podman/start.go b/cmd/podman/start.go index a070cd18d..ee700032f 100644 --- a/cmd/podman/start.go +++ b/cmd/podman/start.go @@ -35,10 +35,7 @@ func init() { startCommand.SetUsageTemplate(UsageTemplate()) flags := startCommand.Flags() flags.BoolVarP(&startCommand.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR") - // Clear the default, the value specified in the config file should have the - // priority - startCommand.DetachKeys = "" - flags.StringVar(&startCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") + flags.StringVar(&startCommand.DetachKeys, "detach-keys", getDefaultDetachKeys(), "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") flags.BoolVarP(&startCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") flags.BoolVarP(&startCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&startCommand.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)") diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go index c62da80df..383a1f61c 100644 --- a/cmd/podman/stop.go +++ b/cmd/podman/stop.go @@ -2,7 +2,6 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/opentracing/opentracing-go" "github.com/pkg/errors" @@ -29,7 +28,7 @@ var ( }, Example: `podman stop ctrID podman stop --latest - podman stop --timeout 2 mywebserver 6e534f14da9d`, + podman stop --time 2 mywebserver 6e534f14da9d`, } ) @@ -42,8 +41,9 @@ func init() { flags.BoolVarP(&stopCommand.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing") flags.StringArrayVarP(&stopCommand.CIDFiles, "cidfile", "", nil, "Read the container ID from the file") flags.BoolVarP(&stopCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.UintVar(&stopCommand.Timeout, "time", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") - flags.UintVarP(&stopCommand.Timeout, "timeout", "t", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") + flags.UintVarP(&stopCommand.Timeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") + flags.UintVar(&stopCommand.Timeout, "timeout", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") + markFlagHidden(flags, "timeout") markFlagHiddenForRemoteClient("latest", flags) markFlagHiddenForRemoteClient("cidfile", flags) markFlagHiddenForRemoteClient("ignore", flags) diff --git a/cmd/podman/unshare.go b/cmd/podman/unshare.go index 31ce441f4..28d17a319 100644 --- a/cmd/podman/unshare.go +++ b/cmd/podman/unshare.go @@ -66,13 +66,8 @@ func unshareCmd(c *cliconfig.PodmanCommand) error { if err != nil { return err } - runtimeConfig, err := runtime.GetConfig() - if err != nil { - return err - } - cmd := exec.Command(c.InputArgs[0], c.InputArgs[1:]...) - cmd.Env = unshareEnv(runtimeConfig.StorageConfig.GraphRoot, runtimeConfig.StorageConfig.RunRoot) + cmd.Env = unshareEnv(runtime.StorageConfig().GraphRoot, runtime.StorageConfig().RunRoot) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index 0ef350fc2..0cb95ef97 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -414,6 +414,8 @@ type BuildOptions ( # BuildInfo is used to describe user input for building images type BuildInfo ( + architecture: string, + addCapabilities: []string, additionalTags: []string, annotations: []string, buildArgs: [string]string, @@ -423,13 +425,16 @@ type BuildInfo ( compression: string, contextDir: string, defaultsMountFilePath: string, + devices: []string, dockerfiles: []string, + dropCapabilities: []string, err: string, forceRmIntermediateCtrs: bool, iidfile: string, label: []string, layers: bool, nocache: bool, + os: string, out: string, output: string, outputFormat: string, @@ -438,7 +443,10 @@ type BuildInfo ( remoteIntermediateCtrs: bool, reportWriter: string, runtimeArgs: []string, - squash: bool + signBy: string, + squash: bool, + target: string, + transientMounts: []string ) # MoreResponse is a struct for when responses from varlink requires longer output diff --git a/cmd/podmanV2/containers/container.go b/cmd/podmanV2/containers/container.go index 6b44f2a3e..b922eea05 100644 --- a/cmd/podmanV2/containers/container.go +++ b/cmd/podmanV2/containers/container.go @@ -1,8 +1,12 @@ package containers import ( + "os" + + "github.com/containers/common/pkg/config" "github.com/containers/libpod/cmd/podmanV2/registry" "github.com/containers/libpod/pkg/domain/entities" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -16,6 +20,8 @@ var ( PersistentPreRunE: preRunE, RunE: registry.SubCommandExists, } + + defaultContainerConfig = getDefaultContainerConfig() ) func init() { @@ -31,3 +37,12 @@ func preRunE(cmd *cobra.Command, args []string) error { _, err := registry.NewContainerEngine(cmd, args) return err } + +func getDefaultContainerConfig() *config.Config { + defaultContainerConfig, err := config.Default() + if err != nil { + logrus.Error(err) + os.Exit(1) + } + return defaultContainerConfig +} diff --git a/cmd/podmanV2/containers/restart.go b/cmd/podmanV2/containers/restart.go index 053891f79..1f1bb11fa 100644 --- a/cmd/podmanV2/containers/restart.go +++ b/cmd/podmanV2/containers/restart.go @@ -46,8 +46,8 @@ func init() { flags.BoolVarP(&restartOptions.All, "all", "a", false, "Restart all non-running containers") flags.BoolVarP(&restartOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&restartOptions.Running, "running", false, "Restart only running containers when --all is used") - flags.UintVarP(&restartTimeout, "timeout", "t", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") - flags.UintVar(&restartTimeout, "time", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") + flags.UintVarP(&restartTimeout, "timeout", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") + flags.UintVar(&restartTimeout, "time", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") if registry.IsRemote() { _ = flags.MarkHidden("latest") } diff --git a/cmd/podmanV2/containers/stop.go b/cmd/podmanV2/containers/stop.go index 58d47fd52..9a106e8fe 100644 --- a/cmd/podmanV2/containers/stop.go +++ b/cmd/podmanV2/containers/stop.go @@ -7,7 +7,6 @@ import ( "github.com/containers/libpod/cmd/podmanV2/parse" "github.com/containers/libpod/cmd/podmanV2/registry" "github.com/containers/libpod/cmd/podmanV2/utils" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/domain/entities" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -47,8 +46,8 @@ func init() { flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing") flags.StringArrayVarP(&stopOptions.CIDFiles, "cidfile", "", nil, "Read the container ID from the file") flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - flags.UintVar(&stopTimeout, "time", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") - flags.UintVarP(&stopTimeout, "timeout", "t", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container") + flags.UintVar(&stopTimeout, "time", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") + flags.UintVarP(&stopTimeout, "timeout", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") if registry.EngineOptions.EngineMode == entities.ABIMode { _ = flags.MarkHidden("latest") _ = flags.MarkHidden("cidfile") @@ -63,7 +62,7 @@ func stop(cmd *cobra.Command, args []string) error { if cmd.Flag("timeout").Changed && cmd.Flag("time").Changed { return errors.New("the --timeout and --time flags are mutually exclusive") } - stopOptions.Timeout = define.CtrRemoveTimeout + stopOptions.Timeout = defaultContainerConfig.Engine.StopTimeout if cmd.Flag("timeout").Changed || cmd.Flag("time").Changed { stopOptions.Timeout = stopTimeout } diff --git a/completions/bash/podman b/completions/bash/podman index ca22ade0a..4a694ca44 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -3318,7 +3318,6 @@ _podman_volume() { _podman_podman() { local options_with_args=" --config -c - --cpu-profile --root --runroot --storage-driver diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh index 5895d84f4..2031432b9 100644 --- a/contrib/cirrus/lib.sh +++ b/contrib/cirrus/lib.sh @@ -34,6 +34,7 @@ PACKER_BASE=${PACKER_BASE:-./contrib/cirrus/packer} # Important filepaths SETUP_MARKER_FILEPATH="${SETUP_MARKER_FILEPATH:-/var/tmp/.setup_environment_sh_complete}" AUTHOR_NICKS_FILEPATH="${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/git_authors_to_irc_nicks.csv" +BUILDAH_PACKAGES_FILEPATH="./contrib/cirrus/packages.sh" # in buildah repo. # Log remote-client system test varlink output here export VARLINK_LOG=/var/tmp/varlink.log @@ -61,8 +62,8 @@ PACKER_VER="1.4.2" # Base-images rarely change, define them here so they're out of the way. export PACKER_BUILDS="${PACKER_BUILDS:-ubuntu-18,ubuntu-19,fedora-31,fedora-30}" # Manually produced base-image names (see $SCRIPT_BASE/README.md) -export UBUNTU_BASE_IMAGE="ubuntu-1904-disco-v20190724" -export PRIOR_UBUNTU_BASE_IMAGE="ubuntu-1804-bionic-v20190722a" +export UBUNTU_BASE_IMAGE="ubuntu-1910-eoan-v20200211" +export PRIOR_UBUNTU_BASE_IMAGE="ubuntu-1804-bionic-v20200218" # Manually produced base-image names (see $SCRIPT_BASE/README.md) export FEDORA_BASE_IMAGE="fedora-cloud-base-31-1-9-1578586410" export PRIOR_FEDORA_BASE_IMAGE="fedora-cloud-base-30-1-2-1578586410" @@ -448,6 +449,26 @@ systemd_banish() { $GOSRC/$PACKER_BASE/systemd_banish.sh } +install_buildah_packages() { + git clone https://github.com/containers/buildah.git /tmp/buildah + if [[ -r "$BUILDAH_PACKAGES_FILEPATH" ]]; then + source "$BUILDAH_PACKAGES_FILEPATH" + req_env_var UBUNTU_BUILDAH_PACKAGES FEDORA_BUILDAH_PACKAGES OS_RELEASE_ID + case "$OS_RELEASE_ID" in + fedora) + $BIGTO ooe.sh sudo dnf install -y ${FEDORA_BUILDAH_PACKAGES[@]} + ;; + ubuntu) + $LILTO $SUDOAPTGET update + $BIGTO $SUDOAPTGET install ${UBUNTU_BUILDAH_PACKAGES[@]} + ;; + *) bad_os_id_ver ;; + esac + else + warn "Could not find $BUILDAH_PACKAGES_FILEPATH in buildah repository root." + fi +} + _finalize() { set +e # Don't fail at the very end if [[ -d "$CUSTOM_CLOUD_CONFIG_DEFAULTS" ]] diff --git a/contrib/cirrus/logcollector.sh b/contrib/cirrus/logcollector.sh index e0190971e..0b179591a 100755 --- a/contrib/cirrus/logcollector.sh +++ b/contrib/cirrus/logcollector.sh @@ -61,6 +61,7 @@ case $1 in PKG_NAMES+=(\ container-selinux \ crun \ + libseccomp \ runc \ ) ;; @@ -69,6 +70,7 @@ case $1 in PKG_LST_CMD='dpkg-query --show --showformat=${Package}-${Version}-${Architecture}\n' PKG_NAMES+=(\ cri-o-runc \ + libseccomp2 \ ) ;; *) bad_os_id_ver ;; diff --git a/contrib/cirrus/packer/fedora_setup.sh b/contrib/cirrus/packer/fedora_setup.sh index 20014e5f3..81a46b13f 100644 --- a/contrib/cirrus/packer/fedora_setup.sh +++ b/contrib/cirrus/packer/fedora_setup.sh @@ -26,7 +26,6 @@ else warn "NOT enabling updates-testing repository for image based on $PRIOR_FEDORA_BASE_IMAGE" fi -echo "Installing general build/test dependencies for Fedora '$OS_RELEASE_VER'" REMOVE_PACKAGES=() INSTALL_PACKAGES=(\ autoconf @@ -74,6 +73,7 @@ INSTALL_PACKAGES=(\ make msitools nmap-ncat + ostree-devel pandoc podman procps-ng @@ -86,11 +86,15 @@ INSTALL_PACKAGES=(\ python3-dateutil python3-psutil python3-pytoml + rsync + runc selinux-policy-devel skopeo + skopeo-containers slirp4netns unzip vim + wget which xz zip @@ -112,16 +116,23 @@ case "$OS_RELEASE_VER" in *) bad_os_id_ver ;; esac + +echo "Installing general build/test dependencies for Fedora '$OS_RELEASE_VER'" $BIGTO ooe.sh sudo dnf install -y ${INSTALL_PACKAGES[@]} +install_buildah_packages + [[ "${#REMOVE_PACKAGES[@]}" -eq "0" ]] || \ $LILTO ooe.sh sudo dnf erase -y ${REMOVE_PACKAGES[@]} -# Ensure there are no disruptive periodic services enabled by default in image -systemd_banish +echo "Enabling cgroup management from containers" +ooe.sh sudo setsebool container_manage_cgroup true ooe.sh sudo /tmp/libpod/hack/install_catatonit.sh +# Ensure there are no disruptive periodic services enabled by default in image +systemd_banish + rh_finalize echo "SUCCESS!" diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh index 7c39a76f8..46e7a620f 100644 --- a/contrib/cirrus/packer/ubuntu_setup.sh +++ b/contrib/cirrus/packer/ubuntu_setup.sh @@ -15,9 +15,6 @@ install_ooe export GOPATH="$(mktemp -d)" trap "sudo rm -rf $GOPATH" EXIT -# Ensure there are no disruptive periodic services enabled by default in image -systemd_banish - # Stop disruption upon boot ASAP after booting echo "Disabling all packaging activity on boot" # Don't let sed process sed's temporary files @@ -32,98 +29,123 @@ $BIGTO $SUDOAPTGET update echo "Upgrading all packages" $BIGTO $SUDOAPTGET upgrade -echo "Adding PPAs" +echo "Adding third-party repositories and PPAs" $LILTO $SUDOAPTGET install software-properties-common -$LILTO $SUDOAPTADD ppa:projectatomic/ppa $LILTO $SUDOAPTADD ppa:criu/ppa if [[ "$OS_RELEASE_VER" -eq "18" ]] then $LILTO $SUDOAPTADD ppa:longsleep/golang-backports fi -$LILTO $SUDOAPTGET update - -echo "Installing general testing and system dependencies" -$BIGTO $SUDOAPTGET install \ - apparmor \ - aufs-tools \ - autoconf \ - automake \ - bash-completion \ - bats \ - bison \ - btrfs-tools \ - build-essential \ - containernetworking-plugins \ - containers-common \ - cri-o-runc \ - criu \ - curl \ - conmon \ - dnsmasq \ - e2fslibs-dev \ - emacs-nox \ - file \ - gawk \ - gcc \ - gettext \ - go-md2man \ - golang \ - iproute2 \ - iptables \ - jq \ - libaio-dev \ - libapparmor-dev \ - libcap-dev \ - libdevmapper-dev \ - libdevmapper1.02.1 \ - libfuse-dev \ - libfuse2 \ - libglib2.0-dev \ - libgpgme11-dev \ - liblzma-dev \ - libnet1 \ - libnet1-dev \ - libnl-3-dev \ - libvarlink \ - libprotobuf-c-dev \ - libprotobuf-dev \ - libseccomp-dev \ - libseccomp2 \ - libsystemd-dev \ - libtool \ - libudev-dev \ - lsof \ - make \ - netcat \ - pkg-config \ - podman \ - protobuf-c-compiler \ - protobuf-compiler \ - python-future \ - python-minimal \ - python-protobuf \ - python3-dateutil \ - python3-pip \ - python3-psutil \ - python3-pytoml \ - python3-setuptools \ - skopeo \ - slirp4netns \ - socat \ - unzip \ - vim \ - xz-utils \ +echo "Configuring/Instaling deps from Open build server" +VERSION_ID=$(source /etc/os-release; echo $VERSION_ID) +echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_$VERSION_ID/ /" \ + | ooe.sh sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list +ooe.sh curl -L -o /tmp/Release.key "https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_${VERSION_ID}/Release.key" +ooe.sh sudo apt-key add - < /tmp/Release.key + +INSTALL_PACKAGES=(\ + apparmor + aufs-tools + autoconf + automake + bash-completion + bison + build-essential + bzip2 + conmon + containernetworking-plugins + containers-common + coreutils + cri-o-runc + criu + curl + dnsmasq + e2fslibs-dev + emacs-nox + file + gawk + gcc + gettext + git + go-md2man + golang + iproute2 + iptables + jq + libaio-dev + libapparmor-dev + libcap-dev + libdevmapper-dev + libdevmapper1.02.1 + libfuse-dev + libfuse2 + libglib2.0-dev + libgpgme11-dev + liblzma-dev + libnet1 + libnet1-dev + libnl-3-dev + libprotobuf-c-dev + libprotobuf-dev + libseccomp-dev + libseccomp2 + libselinux-dev + libsystemd-dev + libtool + libudev-dev + libvarlink + lsof + make + netcat + openssl + pkg-config + podman + protobuf-c-compiler + protobuf-compiler + python-future + python-minimal + python-protobuf + python3-dateutil + python3-pip + python3-psutil + python3-pytoml + python3-setuptools + rsync + runc + scons + skopeo + slirp4netns + socat + unzip + vim + wget + xz-utils + yum-utils zip + zlib1g-dev +) if [[ "$OS_RELEASE_VER" -ge "19" ]] then - echo "Installing Ubuntu > 18 packages" - $LILTO $SUDOAPTGET install fuse3 libfuse3-dev libbtrfs-dev -fi + INSTALL_PACKAGES+=(\ + bats + btrfs-progs + fuse3 + libbtrfs-dev + libfuse3-dev + ) +else + echo "Downloading version of bats with fix for a \$IFS related bug in 'run' command" + cd /tmp + BATS_URL='http://launchpadlibrarian.net/438140887/bats_1.1.0+git104-g1c83a1b-1_all.deb' + curl -L -O "$BATS_URL" + cd - + INSTALL_PACKAGES+=(\ + /tmp/$(basename $BATS_URL) + btrfs-tools + ) -if [[ "$OS_RELEASE_VER" -eq "18" ]] -then echo "Forced Ubuntu 18 kernel to enable cgroup swap accounting." SEDCMD='s/^GRUB_CMDLINE_LINUX="(.*)"/GRUB_CMDLINE_LINUX="\1 cgroup_enable=memory swapaccount=1"/g' ooe.sh sudo sed -re "$SEDCMD" -i /etc/default/grub.d/* @@ -131,9 +153,27 @@ then ooe.sh sudo update-grub fi +echo "Installing general testing and system dependencies" +# Necessary to update cache of newly added repos +$LILTO $SUDOAPTGET update +$BIGTO $SUDOAPTGET install ${INSTALL_PACKAGES[@]} + +install_buildah_packages + +echo "Installing cataonit and libseccomp.sudo" ooe.sh sudo /tmp/libpod/hack/install_catatonit.sh ooe.sh sudo make -C /tmp/libpod install.libseccomp.sudo +# Ensure there are no disruptive periodic services enabled by default in image +systemd_banish + +CRIO_RUNC_PATH="/usr/lib/cri-o-runc/sbin/runc" +if sudo dpkg -L cri-o-runc | grep -m 1 -q "$CRIO_RUNC_PATH" +then + echo "Linking $CRIO_RUNC_PATH to /usr/bin/runc for ease of testing." + sudo ln -f "$CRIO_RUNC_PATH" "/usr/bin/runc" +fi + ubuntu_finalize echo "SUCCESS!" diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh index 9b4a56acd..eceb80b00 100755 --- a/contrib/cirrus/setup_environment.sh +++ b/contrib/cirrus/setup_environment.sh @@ -39,23 +39,8 @@ done cd "${GOSRC}/" case "${OS_RELEASE_ID}" in ubuntu) - CRIO_RUNC_PATH="/usr/lib/cri-o-runc/sbin/runc" - if dpkg -L cri-o-runc | grep -m 1 -q "$CRIO_RUNC_PATH" - then - echo "Linking $CRIO_RUNC_PATH to /usr/bin/runc for ease of testing." - ln -f "$CRIO_RUNC_PATH" "/usr/bin/runc" - fi ;; fedora) - # This is temporary and should be removed once conmon is in stable - # and the images can be rebuilt properly. - if [[ "$OS_RELEASE_VER" -eq "30" ]]; then - dnf -y install https://kojipkgs.fedoraproject.org//packages/conmon/2.0.13/1.fc30/x86_64/conmon-2.0.13-1.fc30.x86_64.rpm - else - dnf -y install https://kojipkgs.fedoraproject.org//packages/conmon/2.0.13/1.fc31/x86_64/conmon-2.0.13-1.fc31.x86_64.rpm - fi - # End of temporary patch - # All SELinux distros need this for systemd-in-a-container setsebool container_manage_cgroup true if [[ "$ADD_SECOND_PARTITION" == "true" ]]; then @@ -67,6 +52,10 @@ case "${OS_RELEASE_ID}" in echo "mq-deadline" > /sys/block/sda/queue/scheduler cat /sys/block/sda/queue/scheduler + if [[ "$ADD_SECOND_PARTITION" == "true" ]]; then + bash "$SCRIPT_BASE/add_second_partition.sh" + fi + warn "Forcing systemd cgroup manager" X=$(echo "export CGROUP_MANAGER=systemd" | \ tee -a /etc/environment) && eval "$X" && echo "$X" diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 63c63dcd2..38b95edc3 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -70,8 +70,8 @@ Drop Linux capabilities Set the cgroup namespace mode for the container. **host**: use the host's cgroup namespace inside the container. **container:<NAME|ID>**: join the namespace of the specified container. - **private**: create a new cgroup namespace. **ns:<PATH>**: join the namespace at the specified path. + **private**: create a new cgroup namespace. If the host uses cgroups v1, the default is set to **host**. On cgroups v2 the default is **private**. @@ -550,6 +550,7 @@ Valid values are: - `host`: use the Podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. - `<network-name>|<network-id>`: connect to a user-defined network, multiple networks should be comma separated - `ns:<path>`: path to a network namespace to join +- `private`: create a new namespace for the container (default) - `slirp4netns`: use slirp4netns to create a user network stack. This is the default for rootless containers **--network-alias**=*alias* @@ -579,9 +580,10 @@ Tune the host's OOM preferences for containers (accepts -1000 to 1000) Set the PID mode for the container Default is to create a private PID namespace for the container - 'container:<name|id>': join another container's PID namespace - 'host': use the host's PID namespace for the container. Note: the host mode gives the container full access to local PID and is therefore considered insecure. - 'ns': join the specified PID namespace +- `container:<name|id>`: join another container's PID namespace +- `host`: use the host's PID namespace for the container. Note: the host mode gives the container full access to local PID and is therefore considered insecure. +- `ns`: join the specified PID namespace +- `private`: create a new namespace for the container (default) **--pids-limit**=*limit* @@ -824,14 +826,16 @@ Without this argument the command will be run as root in the container. **--userns**=*host* **--userns**=*keep-id* **--userns**=container:container +**--userns**=private **--userns**=*ns:my_namespace* Set the user namespace mode for the container. It defaults to the **PODMAN_USERNS** environment variable. An empty value means user namespaces are disabled. +- `container`: join the user namespace of the specified container. - `host`: run in the user namespace of the caller. This is the default if no user namespace options are set. The processes running in the container will have the same privileges on the host as any other process launched by the calling user. - `keep-id`: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is ignored for containers created by the root user. - `ns`: run the container in the given existing user namespace. -- `container`: join the user namespace of the specified container. +- `private`: create a new namespace for the container (default) This option is incompatible with --gidmap, --uidmap, --subuid and --subgid diff --git a/docs/source/markdown/podman-restart.1.md b/docs/source/markdown/podman-restart.1.md index 6507530e1..247d50685 100644 --- a/docs/source/markdown/podman-restart.1.md +++ b/docs/source/markdown/podman-restart.1.md @@ -26,7 +26,7 @@ The latest option is not supported on the remote client. **--running** Restart all containers that are already in the *running* state. -**-t**, **--time**, **--timeout**=*time* +**-t**, **--time**=*time* Timeout to wait before forcibly stopping the container. diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 3225654b6..e8b7d56b7 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -561,6 +561,7 @@ Valid _mode_ values are: - **host**: use the Podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure; - _network-id_: connect to a user-defined network, multiple networks should be comma separated; - **ns:**_path_: path to a network namespace to join; +- `private`: create a new namespace for the container (default) - **slirp4netns**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. **--network-alias**=*alias* @@ -594,6 +595,7 @@ The efault is to create a private PID namespace for the container. - **container:**_id_: join another container's PID namespace; - **host**: use the host's PID namespace for the container. Note the host mode gives the container full access to local PID and is therefore considered insecure; +- **private**: create a new namespace for the container (default) - **ns:**_path_: join the specified PID namespace. **--pids-limit**=*limit* @@ -867,6 +869,7 @@ Set the user namespace mode for the container. It defaults to the **PODMAN_USER - **host**: run in the user namespace of the caller. This is the default if no user namespace options are set. The processes running in the container will have the same privileges on the host as any other process launched by the calling user. - **keep-id**: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is ignored for containers created by the root user. - **ns**: run the container in the given existing user namespace. +- **private**: create a new namespace for the container (default) - **container**: join the user namespace of the specified container. This option is incompatible with **--gidmap**, **--uidmap**, **--subuid** and **--subgid**. @@ -876,6 +879,7 @@ This option is incompatible with **--gidmap**, **--uidmap**, **--subuid** and ** Set the UTS namespace mode for the container. The following values are supported: - **host**: use the host's UTS namespace inside the container. +- **private**: create a new namespace for the container (default) - **ns**: use own UTS namespace. **NOTE**: the host mode gives the container access to changing the host's hostname and is therefore considered insecure. diff --git a/docs/source/markdown/podman-stop.1.md b/docs/source/markdown/podman-stop.1.md index 7dbf18887..23b3415e9 100644 --- a/docs/source/markdown/podman-stop.1.md +++ b/docs/source/markdown/podman-stop.1.md @@ -38,9 +38,9 @@ to run containers such as CRI-O, the last started container could be from either The latest option is not supported on the remote client. -**--timeout**, **--time**, **-t**=*time* +**--time**, **-t**=*time* -Timeout to wait before forcibly stopping the container +Time to wait before forcibly stopping the container ## EXAMPLES diff --git a/docs/source/markdown/podman-version.1.md b/docs/source/markdown/podman-version.1.md index de22c4800..86c270e02 100644 --- a/docs/source/markdown/podman-version.1.md +++ b/docs/source/markdown/podman-version.1.md @@ -7,7 +7,7 @@ podman\-version - Display the Podman version information **podman version** [*options*] ## DESCRIPTION -Shows the following information: Version, Go Version, Git Commit, Build Time, +Shows the following information: Remote API Version, Version, Go Version, Git Commit, Build Time, OS, and Architecture. ## OPTIONS diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md index 5797535f7..cd4148c95 100644 --- a/docs/source/markdown/podman.1.md +++ b/docs/source/markdown/podman.1.md @@ -31,18 +31,9 @@ Note: CGroup manager is not supported in rootless mode when using CGroups Versio **--cni-config-dir** Path of the configuration directory for CNI networks. (Default: `/etc/cni/net.d`) -**--config** -Path of a libpod config file detailing container server configuration options - -Default libpod config file is /usr/share/containers/libpod.conf. Override file is in /etc/containers/libpod.conf. In rootless mode the config file will be read from $HOME/.config/containers/libpod.conf. - **--conmon** Path of the conmon binary (Default path is configured in `libpod.conf`) -**--cpu-profile**=*path* - -Path to where the cpu performance results should be written - **--events-backend**=*type* Backend to use for storing events. Allowed values are **file**, **journald**, and **none**. diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index 2ce8e0de4..34ca7f740 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -6,7 +6,6 @@ import ( "strings" "sync" - "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" bolt "github.com/etcd-io/bbolt" jsoniter "github.com/json-iterator/go" @@ -347,12 +346,12 @@ func (s *BoltState) Refresh() error { // GetDBConfig retrieves runtime configuration fields that were created when // the database was first initialized -func (s *BoltState) GetDBConfig() (*config.DBConfig, error) { +func (s *BoltState) GetDBConfig() (*DBConfig, error) { if !s.valid { return nil, define.ErrDBClosed } - cfg := new(config.DBConfig) + cfg := new(DBConfig) db, err := s.getDBCon() if err != nil { diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index 1c4c9e12d..6e1f2a5f2 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -104,37 +104,37 @@ func checkRuntimeConfig(db *bolt.DB, rt *Runtime) error { }, { "libpod root directory (staticdir)", - rt.config.StaticDir, + rt.config.Engine.StaticDir, staticDirKey, "", }, { "libpod temporary files directory (tmpdir)", - rt.config.TmpDir, + rt.config.Engine.TmpDir, tmpDirKey, "", }, { "storage temporary directory (runroot)", - rt.config.StorageConfig.RunRoot, + rt.StorageConfig().RunRoot, runRootKey, storeOpts.RunRoot, }, { "storage graph root directory (graphroot)", - rt.config.StorageConfig.GraphRoot, + rt.StorageConfig().GraphRoot, graphRootKey, storeOpts.GraphRoot, }, { "storage graph driver", - rt.config.StorageConfig.GraphDriverName, + rt.StorageConfig().GraphDriverName, graphDriverKey, storeOpts.GraphDriverName, }, { "volume path", - rt.config.VolumePath, + rt.config.Engine.VolumePath, volPathKey, "", }, diff --git a/libpod/common_test.go b/libpod/common_test.go index 747252cf4..abf336f97 100644 --- a/libpod/common_test.go +++ b/libpod/common_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/containers/libpod/libpod/config" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/lock" "github.com/cri-o/ocicni/pkg/ocicni" @@ -73,7 +73,9 @@ func getTestContainer(id, name string, manager lock.Manager) (*Container, error) }, runtime: &Runtime{ config: &config.Config{ - VolumePath: "/does/not/exist/tmp/volumes", + Engine: config.EngineConfig{ + VolumePath: "/does/not/exist/tmp/volumes", + }, }, }, valid: true, diff --git a/libpod/config/config.go b/libpod/config/config.go deleted file mode 100644 index b94c1b20b..000000000 --- a/libpod/config/config.go +++ /dev/null @@ -1,618 +0,0 @@ -package config - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "path/filepath" - "regexp" - "strconv" - "strings" - - "github.com/BurntSushi/toml" - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/cgroups" - "github.com/containers/libpod/pkg/rootless" - "github.com/containers/libpod/pkg/util" - "github.com/containers/storage" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -const ( - // _defaultTransport is a prefix that we apply to an image name to check - // docker hub first for the image. - _defaultTransport = "docker://" - - // _rootlessConfigPath is the path to the rootless libpod.conf in $HOME. - _rootlessConfigPath = ".config/containers/libpod.conf" - - // _conmonMinMajorVersion is the major version required for conmon. - _conmonMinMajorVersion = 2 - - // _conmonMinMinorVersion is the minor version required for conmon. - _conmonMinMinorVersion = 0 - - // _conmonMinPatchVersion is the sub-minor version required for conmon. - _conmonMinPatchVersion = 1 - - // _conmonVersionFormatErr is used when the expected versio-format of conmon - // has changed. - _conmonVersionFormatErr = "conmon version changed format" - - // InstallPrefix is the prefix where podman will be installed. - // It can be overridden at build time. - _installPrefix = "/usr" - - // EtcDir is the sysconfdir where podman should look for system config files. - // It can be overridden at build time. - _etcDir = "/etc" - - // SeccompDefaultPath defines the default seccomp path. - SeccompDefaultPath = _installPrefix + "/share/containers/seccomp.json" - - // SeccompOverridePath if this exists it overrides the default seccomp path. - SeccompOverridePath = _etcDir + "/crio/seccomp.json" - - // _rootConfigPath is the path to the libpod configuration file - // This file is loaded to replace the builtin default config before - // runtime options (e.g. WithStorageConfig) are applied. - // If it is not present, the builtin default config is used instead - // This path can be overridden when the runtime is created by using - // NewRuntimeFromConfig() instead of NewRuntime(). - _rootConfigPath = _installPrefix + "/share/containers/libpod.conf" - - // _rootOverrideConfigPath is the path to an override for the default libpod - // configuration file. If OverrideConfigPath exists, it will be used in - // place of the configuration file pointed to by ConfigPath. - _rootOverrideConfigPath = _etcDir + "/containers/libpod.conf" -) - -// SetOptions contains a subset of options in a Config. It's used to indicate if -// a given option has either been set by the user or by a parsed libpod -// configuration file. If not, the corresponding option might be overwritten by -// values from the database. This behavior guarantees backwards compat with -// older version of libpod and Podman. -type SetOptions struct { - // StorageConfigRunRootSet indicates if the RunRoot has been explicitly set - // by the config or by the user. It's required to guarantee backwards - // compatibility with older versions of libpod for which we must query the - // database configuration. Not included in the on-disk config. - StorageConfigRunRootSet bool `toml:"-"` - - // StorageConfigGraphRootSet indicates if the RunRoot has been explicitly - // set by the config or by the user. It's required to guarantee backwards - // compatibility with older versions of libpod for which we must query the - // database configuration. Not included in the on-disk config. - StorageConfigGraphRootSet bool `toml:"-"` - - // StorageConfigGraphDriverNameSet indicates if the GraphDriverName has been - // explicitly set by the config or by the user. It's required to guarantee - // backwards compatibility with older versions of libpod for which we must - // query the database configuration. Not included in the on-disk config. - StorageConfigGraphDriverNameSet bool `toml:"-"` - - // VolumePathSet indicates if the VolumePath has been explicitly set by the - // config or by the user. It's required to guarantee backwards compatibility - // with older versions of libpod for which we must query the database - // configuration. Not included in the on-disk config. - VolumePathSet bool `toml:"-"` - - // StaticDirSet indicates if the StaticDir has been explicitly set by the - // config or by the user. It's required to guarantee backwards compatibility - // with older versions of libpod for which we must query the database - // configuration. Not included in the on-disk config. - StaticDirSet bool `toml:"-"` - - // TmpDirSet indicates if the TmpDir has been explicitly set by the config - // or by the user. It's required to guarantee backwards compatibility with - // older versions of libpod for which we must query the database - // configuration. Not included in the on-disk config. - TmpDirSet bool `toml:"-"` -} - -// Config contains configuration options used to set up a libpod runtime -type Config struct { - // NOTE: when changing this struct, make sure to update (*Config).Merge(). - - // SetOptions contains a subset of config options. It's used to indicate if - // a given option has either been set by the user or by a parsed libpod - // configuration file. If not, the corresponding option might be - // overwritten by values from the database. This behavior guarantees - // backwards compat with older version of libpod and Podman. - SetOptions - - // StateType is the type of the backing state store. Avoid using multiple - // values for this with the same containers/storage configuration on the - // same system. Different state types do not interact, and each will see a - // separate set of containers, which may cause conflicts in - // containers/storage. As such this is not exposed via the config file. - StateType define.RuntimeStateStore `toml:"-"` - - // StorageConfig is the configuration used by containers/storage Not - // included in the on-disk config, use the dedicated containers/storage - // configuration file instead. - StorageConfig storage.StoreOptions `toml:"-"` - - // VolumePath is the default location that named volumes will be created - // under. This convention is followed by the default volume driver, but - // may not be by other drivers. - VolumePath string `toml:"volume_path,omitempty"` - - // ImageDefaultTransport is the default transport method used to fetch - // images. - ImageDefaultTransport string `toml:"image_default_transport,omitempty"` - - // SignaturePolicyPath is the path to a signature policy to use for - // validating images. If left empty, the containers/image default signature - // policy will be used. - SignaturePolicyPath string `toml:"signature_policy_path,omitempty"` - - // OCIRuntime is the OCI runtime to use. - OCIRuntime string `toml:"runtime,omitempty"` - - // OCIRuntimes are the set of configured OCI runtimes (default is runc). - OCIRuntimes map[string][]string `toml:"runtimes,omitempty"` - - // RuntimeSupportsJSON is the list of the OCI runtimes that support - // --format=json. - RuntimeSupportsJSON []string `toml:"runtime_supports_json,omitempty"` - - // RuntimeSupportsNoCgroups is a list of OCI runtimes that support - // running containers without CGroups. - RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroups,omitempty"` - - // RuntimePath is the path to OCI runtime binary for launching containers. - // The first path pointing to a valid file will be used This is used only - // when there are no OCIRuntime/OCIRuntimes defined. It is used only to be - // backward compatible with older versions of Podman. - RuntimePath []string `toml:"runtime_path,omitempty"` - - // ConmonPath is the path to the Conmon binary used for managing containers. - // The first path pointing to a valid file will be used. - ConmonPath []string `toml:"conmon_path,omitempty"` - - // ConmonEnvVars are environment variables to pass to the Conmon binary - // when it is launched. - ConmonEnvVars []string `toml:"conmon_env_vars,omitempty"` - - // CGroupManager is the CGroup Manager to use Valid values are "cgroupfs" - // and "systemd". - CgroupManager string `toml:"cgroup_manager,omitempty"` - - // InitPath is the path to the container-init binary. - InitPath string `toml:"init_path,omitempty"` - - // StaticDir is the path to a persistent directory to store container - // files. - StaticDir string `toml:"static_dir,omitempty"` - - // TmpDir is the path to a temporary directory to store per-boot container - // files. Must be stored in a tmpfs. - TmpDir string `toml:"tmp_dir,omitempty"` - - // MaxLogSize is the maximum size of container logfiles. - MaxLogSize int64 `toml:"max_log_size,omitempty"` - - // NoPivotRoot sets whether to set no-pivot-root in the OCI runtime. - NoPivotRoot bool `toml:"no_pivot_root,omitempty"` - - // CNIConfigDir sets the directory where CNI configuration files are - // stored. - CNIConfigDir string `toml:"cni_config_dir,omitempty"` - - // CNIPluginDir sets a number of directories where the CNI network - // plugins can be located. - CNIPluginDir []string `toml:"cni_plugin_dir,omitempty"` - - // CNIDefaultNetwork is the network name of the default CNI network - // to attach pods to. - CNIDefaultNetwork string `toml:"cni_default_network,omitempty"` - - // HooksDir holds paths to the directories containing hooks - // configuration files. When the same filename is present in in - // multiple directories, the file in the directory listed last in - // this slice takes precedence. - HooksDir []string `toml:"hooks_dir,omitempty"` - - // DefaultMountsFile is the path to the default mounts file for testing - // purposes only. - DefaultMountsFile string `toml:"-"` - - // Namespace is the libpod namespace to use. 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. The default namespace is "". - Namespace string `toml:"namespace,omitempty"` - - // InfraImage is the image a pod infra container will use to manage - // namespaces. - InfraImage string `toml:"infra_image,omitempty"` - - // InfraCommand is the command run to start up a pod infra container. - InfraCommand string `toml:"infra_command,omitempty"` - - // EnablePortReservation determines whether libpod will reserve ports on the - // host when they are forwarded to containers. When enabled, when ports are - // forwarded to containers, they are held open by conmon as long as the - // container is running, ensuring that they cannot be reused by other - // programs on the host. However, this can cause significant memory usage if - // a container has many ports forwarded to it. Disabling this can save - // memory. - EnablePortReservation bool `toml:"enable_port_reservation,omitempty"` - - // EnableLabeling indicates whether libpod will support container labeling. - EnableLabeling bool `toml:"label,omitempty"` - - // NetworkCmdPath is the path to the slirp4netns binary. - NetworkCmdPath string `toml:"network_cmd_path,omitempty"` - - // NumLocks is the number of locks to make available for containers and - // pods. - NumLocks uint32 `toml:"num_locks,omitempty"` - - // LockType is the type of locking to use. - LockType string `toml:"lock_type,omitempty"` - - // EventsLogger determines where events should be logged. - EventsLogger string `toml:"events_logger,omitempty"` - - // EventsLogFilePath is where the events log is stored. - EventsLogFilePath string `toml:"events_logfile_path,omitempty"` - - //DetachKeys is the sequence of keys used to detach a container. - DetachKeys string `toml:"detach_keys,omitempty"` - - // SDNotify tells Libpod to allow containers to notify the host systemd of - // readiness using the SD_NOTIFY mechanism. - SDNotify bool `toml:",omitempty"` - - // CgroupCheck indicates the configuration has been rewritten after an - // upgrade to Fedora 31 to change the default OCI runtime for cgroupsv2. - CgroupCheck bool `toml:"cgroup_check,omitempty"` -} - -// DBConfig is a set of Libpod runtime configuration settings that are saved in -// a State when it is first created, and can subsequently be retrieved. -type DBConfig struct { - LibpodRoot string - LibpodTmp string - StorageRoot string - StorageTmp string - GraphDriver string - VolumePath string -} - -// readConfigFromFile reads the specified config file at `path` and attempts to -// unmarshal its content into a Config. The config param specifies the previous -// default config. If the path, only specifies a few fields in the Toml file -// the defaults from the config parameter will be used for all other fields. -func readConfigFromFile(path string, config *Config) (*Config, error) { - logrus.Debugf("Reading configuration file %q", path) - _, err := toml.DecodeFile(path, config) - if err != nil { - return nil, fmt.Errorf("unable to decode configuration %v: %v", path, err) - } - - // For the sake of backwards compat we need to check if the config fields - // with *Set suffix are set in the config. Note that the storage-related - // fields are NOT set in the config here but in the storage.conf OR directly - // by the user. - if config.VolumePath != "" { - config.VolumePathSet = true - } - if config.StaticDir != "" { - config.StaticDirSet = true - } - if config.TmpDir != "" { - config.TmpDirSet = true - } - - return config, err -} - -// Write decodes the config as TOML and writes it to the specified path. -func (c *Config) Write(path string) error { - f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0666) - if err != nil { - return errors.Wrapf(err, "error opening config file %q", path) - } - - buffer := new(bytes.Buffer) - if err := toml.NewEncoder(buffer).Encode(c); err != nil { - return errors.Wrapf(err, "error encoding config") - } - - if _, err := f.WriteString(buffer.String()); err != nil { - return errors.Wrapf(err, "error writing config %q", path) - } - return err -} - -// FindConmon iterates over (*Config).ConmonPath and returns the path to first -// (version) matching conmon binary. If non is found, we try to do a path lookup -// of "conmon". -func (c *Config) FindConmon() (string, error) { - foundOutdatedConmon := false - for _, path := range c.ConmonPath { - stat, err := os.Stat(path) - if err != nil { - continue - } - if stat.IsDir() { - continue - } - if err := probeConmon(path); err != nil { - logrus.Warnf("Conmon at %s invalid: %v", path, err) - foundOutdatedConmon = true - continue - } - logrus.Debugf("Using conmon: %q", path) - return path, nil - } - - // Search the $PATH as last fallback - if path, err := exec.LookPath("conmon"); err == nil { - if err := probeConmon(path); err != nil { - logrus.Warnf("Conmon at %s is invalid: %v", path, err) - foundOutdatedConmon = true - } else { - logrus.Debugf("Using conmon from $PATH: %q", path) - return path, nil - } - } - - if foundOutdatedConmon { - return "", errors.Wrapf(define.ErrConmonOutdated, - "please update to v%d.%d.%d or later", - _conmonMinMajorVersion, _conmonMinMinorVersion, _conmonMinPatchVersion) - } - - return "", errors.Wrapf(define.ErrInvalidArg, - "could not find a working conmon binary (configured options: %v)", - c.ConmonPath) -} - -// probeConmon calls conmon --version and verifies it is a new enough version for -// the runtime expectations podman currently has. -func probeConmon(conmonBinary string) error { - cmd := exec.Command(conmonBinary, "--version") - var out bytes.Buffer - cmd.Stdout = &out - err := cmd.Run() - if err != nil { - return err - } - r := regexp.MustCompile(`^conmon version (?P<Major>\d+).(?P<Minor>\d+).(?P<Patch>\d+)`) - - matches := r.FindStringSubmatch(out.String()) - if len(matches) != 4 { - return errors.Wrap(err, _conmonVersionFormatErr) - } - major, err := strconv.Atoi(matches[1]) - if err != nil { - return errors.Wrap(err, _conmonVersionFormatErr) - } - if major < _conmonMinMajorVersion { - return define.ErrConmonOutdated - } - if major > _conmonMinMajorVersion { - return nil - } - - minor, err := strconv.Atoi(matches[2]) - if err != nil { - return errors.Wrap(err, _conmonVersionFormatErr) - } - if minor < _conmonMinMinorVersion { - return define.ErrConmonOutdated - } - if minor > _conmonMinMinorVersion { - return nil - } - - patch, err := strconv.Atoi(matches[3]) - if err != nil { - return errors.Wrap(err, _conmonVersionFormatErr) - } - if patch < _conmonMinPatchVersion { - return define.ErrConmonOutdated - } - if patch > _conmonMinPatchVersion { - return nil - } - - return nil -} - -// NewConfig creates a new Config. It starts with an empty config and, if -// specified, merges the config at `userConfigPath` path. Depending if we're -// running as root or rootless, we then merge the system configuration followed -// by merging the default config (hard-coded default in memory). -// -// Note that the OCI runtime is hard-set to `crun` if we're running on a system -// with cgroupsv2. Other OCI runtimes are not yet supporting cgroupsv2. This -// might change in the future. -func NewConfig(userConfigPath string) (*Config, error) { - // Start with the default config and iteratively merge fields in the system - // configs. - config, err := defaultConfigFromMemory() - if err != nil { - return nil, err - } - - // Now, check if the user can access system configs and merge them if needed. - configs, err := systemConfigs() - if err != nil { - return nil, errors.Wrapf(err, "error finding config on system") - } - - for _, path := range configs { - config, err = readConfigFromFile(path, config) - if err != nil { - return nil, errors.Wrapf(err, "error reading system config %q", path) - } - } - - // First, try to read the user-specified config - if userConfigPath != "" { - var err error - config, err = readConfigFromFile(userConfigPath, config) - if err != nil { - return nil, errors.Wrapf(err, "error reading user config %q", userConfigPath) - } - } - - // Since runc does not currently support cgroupV2 - // Change to default crun on first running of libpod.conf - // TODO Once runc has support for cgroups, this function should be removed. - if !config.CgroupCheck && rootless.IsRootless() { - cgroupsV2, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return nil, err - } - if cgroupsV2 { - path, err := exec.LookPath("crun") - if err != nil { - // Can't find crun path so do nothing - logrus.Warnf("Can not find crun package on the host, containers might fail to run on cgroup V2 systems without crun: %q", err) - } else { - config.CgroupCheck = true - config.OCIRuntime = path - } - } - } - - // If we need to, switch to cgroupfs and logger=file on rootless. - config.checkCgroupsAndLogger() - - // Relative paths can cause nasty bugs, because core paths we use could - // shift between runs (or even parts of the program - the OCI runtime - // uses a different working directory than we do, for example. - if !filepath.IsAbs(config.StaticDir) { - return nil, errors.Wrapf(define.ErrInvalidArg, "static directory must be an absolute path - instead got %q", config.StaticDir) - } - if !filepath.IsAbs(config.TmpDir) { - return nil, errors.Wrapf(define.ErrInvalidArg, "temporary directory must be an absolute path - instead got %q", config.TmpDir) - } - if !filepath.IsAbs(config.VolumePath) { - return nil, errors.Wrapf(define.ErrInvalidArg, "volume path must be an absolute path - instead got %q", config.VolumePath) - } - - return config, nil -} - -func rootlessConfigPath() (string, error) { - home, err := util.HomeDir() - if err != nil { - return "", err - } - - return filepath.Join(home, _rootlessConfigPath), nil -} - -func systemConfigs() ([]string, error) { - if rootless.IsRootless() { - path, err := rootlessConfigPath() - if err != nil { - return nil, err - } - if _, err := os.Stat(path); err == nil { - return []string{path}, nil - } - return nil, err - } - - configs := []string{} - if _, err := os.Stat(_rootConfigPath); err == nil { - configs = append(configs, _rootConfigPath) - } - if _, err := os.Stat(_rootOverrideConfigPath); err == nil { - configs = append(configs, _rootOverrideConfigPath) - } - return configs, nil -} - -// checkCgroupsAndLogger checks if we're running rootless with the systemd -// cgroup manager. In case the user session isn't available, we're switching the -// cgroup manager to cgroupfs and the events logger backend to 'file'. -// Note, this only applies to rootless. -func (c *Config) checkCgroupsAndLogger() { - if !rootless.IsRootless() || (c.CgroupManager != - define.SystemdCgroupsManager && c.EventsLogger == "file") { - return - } - - session := os.Getenv("DBUS_SESSION_BUS_ADDRESS") - hasSession := session != "" - if hasSession && strings.HasPrefix(session, "unix:path=") { - _, err := os.Stat(strings.TrimPrefix(session, "unix:path=")) - hasSession = err == nil - } - - if !hasSession { - logrus.Warningf("The cgroup manager or the events logger is set to use systemd but there is no systemd user session available") - logrus.Warningf("For using systemd, you may need to login using an user session") - logrus.Warningf("Alternatively, you can enable lingering with: `loginctl enable-linger %d` (possibly as root)", rootless.GetRootlessUID()) - logrus.Warningf("Falling back to --cgroup-manager=cgroupfs and --events-backend=file") - c.CgroupManager = define.CgroupfsCgroupsManager - c.EventsLogger = "file" - } -} - -// MergeDBConfig merges the configuration from the database. -func (c *Config) MergeDBConfig(dbConfig *DBConfig) error { - - if !c.StorageConfigRunRootSet && dbConfig.StorageTmp != "" { - if c.StorageConfig.RunRoot != dbConfig.StorageTmp && - c.StorageConfig.RunRoot != "" { - logrus.Debugf("Overriding run root %q with %q from database", - c.StorageConfig.RunRoot, dbConfig.StorageTmp) - } - c.StorageConfig.RunRoot = dbConfig.StorageTmp - } - - if !c.StorageConfigGraphRootSet && dbConfig.StorageRoot != "" { - if c.StorageConfig.GraphRoot != dbConfig.StorageRoot && - c.StorageConfig.GraphRoot != "" { - logrus.Debugf("Overriding graph root %q with %q from database", - c.StorageConfig.GraphRoot, dbConfig.StorageRoot) - } - c.StorageConfig.GraphRoot = dbConfig.StorageRoot - } - - if !c.StorageConfigGraphDriverNameSet && dbConfig.GraphDriver != "" { - if c.StorageConfig.GraphDriverName != dbConfig.GraphDriver && - c.StorageConfig.GraphDriverName != "" { - logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve", - c.StorageConfig.GraphDriverName, dbConfig.GraphDriver) - } - c.StorageConfig.GraphDriverName = dbConfig.GraphDriver - } - - if !c.StaticDirSet && dbConfig.LibpodRoot != "" { - if c.StaticDir != dbConfig.LibpodRoot && c.StaticDir != "" { - logrus.Debugf("Overriding static dir %q with %q from database", c.StaticDir, dbConfig.LibpodRoot) - } - c.StaticDir = dbConfig.LibpodRoot - } - - if !c.TmpDirSet && dbConfig.LibpodTmp != "" { - if c.TmpDir != dbConfig.LibpodTmp && c.TmpDir != "" { - logrus.Debugf("Overriding tmp dir %q with %q from database", c.TmpDir, dbConfig.LibpodTmp) - } - c.TmpDir = dbConfig.LibpodTmp - c.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log") - } - - if !c.VolumePathSet && dbConfig.VolumePath != "" { - if c.VolumePath != dbConfig.VolumePath && c.VolumePath != "" { - logrus.Debugf("Overriding volume path %q with %q from database", c.VolumePath, dbConfig.VolumePath) - } - c.VolumePath = dbConfig.VolumePath - } - return nil -} diff --git a/libpod/config/config_test.go b/libpod/config/config_test.go deleted file mode 100644 index 24620ce0e..000000000 --- a/libpod/config/config_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package config - -import ( - "reflect" - "testing" - - "github.com/containers/libpod/libpod/define" - "github.com/containers/storage" - "github.com/stretchr/testify/assert" -) - -func TestEmptyConfig(t *testing.T) { - // Make sure that we can read empty configs - config, err := readConfigFromFile("testdata/empty.conf", &Config{}) - assert.NotNil(t, config) - assert.Nil(t, err) -} - -func TestDefaultLibpodConf(t *testing.T) { - // Make sure that we can read the default libpod.conf - config, err := readConfigFromFile("testdata/libpod.conf", &Config{}) - assert.NotNil(t, config) - assert.Nil(t, err) -} - -func TestMergeEmptyAndDefaultMemoryConfig(t *testing.T) { - // Make sure that when we merge the default config into an empty one that we - // effectively get the default config. - defaultConfig, err := defaultConfigFromMemory() - assert.NotNil(t, defaultConfig) - assert.Nil(t, err) - defaultConfig.StateType = define.InvalidStateStore - defaultConfig.StorageConfig = storage.StoreOptions{} - - emptyConfig, err := readConfigFromFile("testdata/empty.conf", defaultConfig) - assert.NotNil(t, emptyConfig) - assert.Nil(t, err) - - equal := reflect.DeepEqual(emptyConfig, defaultConfig) - assert.True(t, equal) -} - -func TestMergeEmptyAndLibpodConfig(t *testing.T) { - // Make sure that when we merge the default config into an empty one that we - // effectively get the default config. - libpodConfig, err := readConfigFromFile("testdata/libpod.conf", &Config{}) - assert.NotNil(t, libpodConfig) - assert.Nil(t, err) - libpodConfig.StateType = define.InvalidStateStore - libpodConfig.StorageConfig = storage.StoreOptions{} - - emptyConfig, err := readConfigFromFile("testdata/empty.conf", libpodConfig) - assert.NotNil(t, emptyConfig) - assert.Nil(t, err) - - equal := reflect.DeepEqual(emptyConfig, libpodConfig) - assert.True(t, equal) -} diff --git a/libpod/config/default.go b/libpod/config/default.go deleted file mode 100644 index c4a4efdaf..000000000 --- a/libpod/config/default.go +++ /dev/null @@ -1,153 +0,0 @@ -package config - -import ( - "os" - "path/filepath" - - "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/libpod/events" - "github.com/containers/libpod/pkg/cgroups" - "github.com/containers/libpod/pkg/rootless" - "github.com/containers/libpod/pkg/util" - "github.com/containers/storage" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -const ( - // _defaultGraphRoot points to the default path of the graph root. - _defaultGraphRoot = "/var/lib/containers/storage" - // _defaultRootlessSignaturePolicyPath points to the default path of the - // rootless policy.json file. - _defaultRootlessSignaturePolicyPath = ".config/containers/policy.json" -) - -// defaultConfigFromMemory returns a default libpod configuration. Note that the -// config is different for root and rootless. It also parses the storage.conf. -func defaultConfigFromMemory() (*Config, error) { - c := new(Config) - tmp, err := defaultTmpDir() - if err != nil { - return nil, err - } - c.TmpDir = tmp - - c.EventsLogFilePath = filepath.Join(c.TmpDir, "events", "events.log") - - storeOpts, err := storage.DefaultStoreOptions(rootless.IsRootless(), rootless.GetRootlessUID()) - if err != nil { - return nil, err - } - if storeOpts.GraphRoot == "" { - logrus.Warnf("Storage configuration is unset - using hardcoded default graph root %q", _defaultGraphRoot) - storeOpts.GraphRoot = _defaultGraphRoot - } - c.StaticDir = filepath.Join(storeOpts.GraphRoot, "libpod") - c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes") - c.StorageConfig = storeOpts - - c.ImageDefaultTransport = _defaultTransport - c.StateType = define.BoltDBStateStore - c.OCIRuntime = "runc" - - // If we're running on cgroups v2, default to using crun. - if onCgroupsv2, _ := cgroups.IsCgroup2UnifiedMode(); onCgroupsv2 { - c.OCIRuntime = "crun" - } - - c.OCIRuntimes = map[string][]string{ - "runc": { - "/usr/bin/runc", - "/usr/sbin/runc", - "/usr/local/bin/runc", - "/usr/local/sbin/runc", - "/sbin/runc", - "/bin/runc", - "/usr/lib/cri-o-runc/sbin/runc", - "/run/current-system/sw/bin/runc", - }, - "crun": { - "/usr/bin/crun", - "/usr/sbin/crun", - "/usr/local/bin/crun", - "/usr/local/sbin/crun", - "/sbin/crun", - "/bin/crun", - "/run/current-system/sw/bin/crun", - }, - } - c.ConmonPath = []string{ - "/usr/libexec/podman/conmon", - "/usr/local/libexec/podman/conmon", - "/usr/local/lib/podman/conmon", - "/usr/bin/conmon", - "/usr/sbin/conmon", - "/usr/local/bin/conmon", - "/usr/local/sbin/conmon", - "/run/current-system/sw/bin/conmon", - } - c.ConmonEnvVars = []string{ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - } - c.RuntimeSupportsJSON = []string{ - "crun", - "runc", - } - c.RuntimeSupportsNoCgroups = []string{"crun"} - c.InitPath = define.DefaultInitPath - c.CgroupManager = define.SystemdCgroupsManager - c.MaxLogSize = -1 - c.NoPivotRoot = false - c.CNIConfigDir = _etcDir + "/cni/net.d/" - c.CNIPluginDir = []string{ - "/usr/libexec/cni", - "/usr/lib/cni", - "/usr/local/lib/cni", - "/opt/cni/bin", - } - c.CNIDefaultNetwork = "podman" - c.InfraCommand = define.DefaultInfraCommand - c.InfraImage = define.DefaultInfraImage - c.EnablePortReservation = true - c.EnableLabeling = true - c.NumLocks = 2048 - c.EventsLogger = events.DefaultEventerType.String() - c.DetachKeys = define.DefaultDetachKeys - // TODO - ideally we should expose a `type LockType string` along with - // constants. - c.LockType = "shm" - - if rootless.IsRootless() { - home, err := util.HomeDir() - if err != nil { - return nil, err - } - sigPath := filepath.Join(home, _defaultRootlessSignaturePolicyPath) - if _, err := os.Stat(sigPath); err == nil { - c.SignaturePolicyPath = sigPath - } - } - return c, nil -} - -func defaultTmpDir() (string, error) { - if !rootless.IsRootless() { - return "/var/run/libpod", nil - } - - runtimeDir, err := util.GetRuntimeDir() - if err != nil { - return "", err - } - libpodRuntimeDir := filepath.Join(runtimeDir, "libpod") - - if err := os.Mkdir(libpodRuntimeDir, 0700|os.ModeSticky); err != nil { - if !os.IsExist(err) { - return "", errors.Wrapf(err, "cannot mkdir %s", libpodRuntimeDir) - } else if err := os.Chmod(libpodRuntimeDir, 0700|os.ModeSticky); err != nil { - // The directory already exist, just set the sticky bit - return "", errors.Wrapf(err, "could not set sticky bit on %s", libpodRuntimeDir) - } - } - return filepath.Join(libpodRuntimeDir, "tmp"), nil -} diff --git a/libpod/config/testdata/empty.conf b/libpod/config/testdata/empty.conf deleted file mode 100644 index e69de29bb..000000000 --- a/libpod/config/testdata/empty.conf +++ /dev/null diff --git a/libpod/config/testdata/libpod.conf b/libpod/config/testdata/libpod.conf deleted file mode 120000 index 17d09fe4a..000000000 --- a/libpod/config/testdata/libpod.conf +++ /dev/null @@ -1 +0,0 @@ -../../../libpod.conf
\ No newline at end of file diff --git a/libpod/container.go b/libpod/container.go index e59fb9fe8..c1deb95f9 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -11,6 +11,7 @@ import ( "github.com/containernetworking/cni/pkg/types" cnitypes "github.com/containernetworking/cni/pkg/types/current" + "github.com/containers/common/pkg/config" "github.com/containers/image/v5/manifest" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/lock" @@ -1083,10 +1084,10 @@ func (c *Container) NamespacePath(linuxNS LinuxNS) (string, error) { //nolint:in // CGroupPath returns a cgroups "path" for a given container. func (c *Container) CGroupPath() (string, error) { - switch c.runtime.config.CgroupManager { - case define.CgroupfsCgroupsManager: + switch c.runtime.config.Engine.CgroupManager { + case config.CgroupfsCgroupsManager: return filepath.Join(c.config.CgroupParent, fmt.Sprintf("libpod-%s", c.ID())), nil - case define.SystemdCgroupsManager: + case config.SystemdCgroupsManager: if rootless.IsRootless() { uid := rootless.GetRootlessUID() parts := strings.SplitN(c.config.CgroupParent, "/", 2) @@ -1100,7 +1101,7 @@ func (c *Container) CGroupPath() (string, error) { } return filepath.Join(c.config.CgroupParent, createUnitName("libpod", c.ID())), nil default: - return "", errors.Wrapf(define.ErrInvalidArg, "unsupported CGroup manager %s in use", c.runtime.config.CgroupManager) + return "", errors.Wrapf(define.ErrInvalidArg, "unsupported CGroup manager %s in use", c.runtime.config.Engine.CgroupManager) } } diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 7552eb483..f81be8b22 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/driver" "github.com/containers/libpod/pkg/util" @@ -769,10 +770,10 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named // CGroup parent // Need to check if it's the default, and not print if so. defaultCgroupParent := "" - switch c.runtime.config.CgroupManager { - case define.CgroupfsCgroupsManager: + switch c.runtime.config.Engine.CgroupManager { + case config.CgroupfsCgroupsManager: defaultCgroupParent = CgroupfsDefaultCgroupParent - case define.SystemdCgroupsManager: + case config.SystemdCgroupsManager: defaultCgroupParent = SystemdDefaultCgroupParent } if c.config.CgroupParent != defaultCgroupParent { diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 7a85c1f04..4e18819b8 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -515,14 +515,14 @@ func (c *Container) refresh() error { c.state.RunDir = dir if len(c.config.IDMappings.UIDMap) != 0 || len(c.config.IDMappings.GIDMap) != 0 { - info, err := os.Stat(c.runtime.config.TmpDir) + info, err := os.Stat(c.runtime.config.Engine.TmpDir) if err != nil { - return errors.Wrapf(err, "cannot stat `%s`", c.runtime.config.TmpDir) + return errors.Wrapf(err, "cannot stat `%s`", c.runtime.config.Engine.TmpDir) } - if err := os.Chmod(c.runtime.config.TmpDir, info.Mode()|0111); err != nil { - return errors.Wrapf(err, "cannot chmod `%s`", c.runtime.config.TmpDir) + if err := os.Chmod(c.runtime.config.Engine.TmpDir, info.Mode()|0111); err != nil { + return errors.Wrapf(err, "cannot chmod `%s`", c.runtime.config.Engine.TmpDir) } - root := filepath.Join(c.runtime.config.TmpDir, "containers-root", c.ID()) + root := filepath.Join(c.runtime.config.Engine.TmpDir, "containers-root", c.ID()) if err := os.MkdirAll(root, 0755); err != nil { return errors.Wrapf(err, "error creating userNS tmpdir for container %s", c.ID()) } @@ -898,7 +898,7 @@ func (c *Container) completeNetworkSetup() error { if err := c.syncContainer(); err != nil { return err } - if c.config.NetMode == "slirp4netns" { + if c.config.NetMode.IsSlirp4netns() { return c.runtime.setupRootlessNetNS(c) } if err := c.runtime.setupNetNS(c); err != nil { @@ -1689,7 +1689,7 @@ func (c *Container) saveSpec(spec *spec.Spec) error { // Warning: precreate hooks may alter 'config' in place. func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (extensionStageHooks map[string][]spec.Hook, err error) { allHooks := make(map[string][]spec.Hook) - if c.runtime.config.HooksDir == nil { + if c.runtime.config.Engine.HooksDir == nil { if rootless.IsRootless() { return nil, nil } @@ -1713,7 +1713,7 @@ func (c *Container) setupOCIHooks(ctx context.Context, config *spec.Spec) (exten } } } else { - manager, err := hooks.New(ctx, c.runtime.config.HooksDir, []string{"precreate", "poststop"}) + manager, err := hooks.New(ctx, c.runtime.config.Engine.HooksDir, []string{"precreate", "poststop"}) if err != nil { return nil, err } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 2f0f59c24..a3f97f2a6 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -20,6 +20,7 @@ import ( cnitypes "github.com/containernetworking/cni/pkg/types/current" "github.com/containernetworking/plugins/pkg/ns" "github.com/containers/buildah/pkg/secrets" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/pkg/annotations" @@ -29,6 +30,7 @@ import ( "github.com/containers/libpod/pkg/lookup" "github.com/containers/libpod/pkg/resolvconf" "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/util" "github.com/containers/storage/pkg/archive" securejoin "github.com/cyphar/filepath-securejoin" "github.com/opencontainers/runc/libcontainer/user" @@ -92,7 +94,7 @@ func (c *Container) prepare() error { } // handle rootless network namespace setup - if c.state.NetNS != nil && c.config.NetMode == "slirp4netns" && !c.config.PostConfigureNetNS { + if c.state.NetNS != nil && c.config.NetMode.IsSlirp4netns() && !c.config.PostConfigureNetNS { createNetNSErr = c.runtime.setupRootlessNetNS(c) } }() @@ -1213,7 +1215,7 @@ func (c *Container) makeBindMounts() error { } // Add Secret Mounts - secretMounts := secrets.SecretMountsWithUIDGID(c.config.MountLabel, c.state.RunDir, c.runtime.config.DefaultMountsFile, c.state.RunDir, c.RootUID(), c.RootGID(), rootless.IsRootless(), false) + secretMounts := secrets.SecretMountsWithUIDGID(c.config.MountLabel, c.state.RunDir, c.runtime.config.Containers.DefaultMountsFile, c.state.RunDir, c.RootUID(), c.RootGID(), rootless.IsRootless(), false) for _, mount := range secretMounts { if _, ok := c.state.BindMounts[mount.Destination]; !ok { c.state.BindMounts[mount.Destination] = mount.Source @@ -1274,11 +1276,21 @@ func (c *Container) generateResolvConf() (string, error) { } } + var dns []net.IP + for _, i := range c.runtime.config.Containers.DNSServers { + result := net.ParseIP(i) + if result == nil { + return "", errors.Wrapf(define.ErrInvalidArg, "invalid IP address %s", i) + } + dns = append(dns, result) + } + dnsServers := append(dns, c.config.DNSServer...) // If the user provided dns, it trumps all; then dns masq; then resolv.conf switch { - case len(c.config.DNSServer) > 0: + case len(dnsServers) > 0: + // We store DNS servers as net.IP, so need to convert to string - for _, server := range c.config.DNSServer { + for _, server := range dnsServers { nameservers = append(nameservers, server.String()) } case len(cniNameServers) > 0: @@ -1292,14 +1304,22 @@ func (c *Container) generateResolvConf() (string, error) { } } - search := resolvconf.GetSearchDomains(resolv.Content) - if len(c.config.DNSSearch) > 0 { - search = c.config.DNSSearch + var search []string + if len(c.config.DNSSearch) > 0 || len(c.runtime.config.Containers.DNSSearches) > 0 { + if !util.StringInSlice(".", c.config.DNSSearch) { + search = c.runtime.config.Containers.DNSSearches + search = append(search, c.config.DNSSearch...) + } + } else { + search = resolvconf.GetSearchDomains(resolv.Content) } - options := resolvconf.GetOptions(resolv.Content) - if len(c.config.DNSOption) > 0 { - options = c.config.DNSOption + var options []string + if len(c.config.DNSOption) > 0 || len(c.runtime.config.Containers.DNSOptions) > 0 { + options = c.runtime.config.Containers.DNSOptions + options = append(options, c.config.DNSOption...) + } else { + options = resolvconf.GetOptions(resolv.Content) } destPath := filepath.Join(c.state.RunDir, "resolv.conf") @@ -1445,14 +1465,14 @@ func (c *Container) getOCICgroupPath() (string, error) { switch { case (rootless.IsRootless() && !unified) || c.config.NoCgroups: return "", nil - case c.runtime.config.CgroupManager == define.SystemdCgroupsManager: + case c.runtime.config.Engine.CgroupManager == config.SystemdCgroupsManager: // When runc is set to use Systemd as a cgroup manager, it // expects cgroups to be passed as follows: // slice:prefix:name systemdCgroups := fmt.Sprintf("%s:libpod:%s", path.Base(c.config.CgroupParent), c.ID()) logrus.Debugf("Setting CGroups for container %s to %s", c.ID(), systemdCgroups) return systemdCgroups, nil - case c.runtime.config.CgroupManager == define.CgroupfsCgroupsManager: + case c.runtime.config.Engine.CgroupManager == config.CgroupfsCgroupsManager: cgroupPath, err := c.CGroupPath() if err != nil { return "", err @@ -1460,6 +1480,6 @@ func (c *Container) getOCICgroupPath() (string, error) { logrus.Debugf("Setting CGroup path for container %s to %s", c.ID(), cgroupPath) return cgroupPath, nil default: - return "", errors.Wrapf(define.ErrInvalidArg, "invalid cgroup manager %s requested", c.runtime.config.CgroupManager) + return "", errors.Wrapf(define.ErrInvalidArg, "invalid cgroup manager %s requested", c.runtime.config.Engine.CgroupManager) } } diff --git a/libpod/define/config.go b/libpod/define/config.go index c06c32471..5598f97a3 100644 --- a/libpod/define/config.go +++ b/libpod/define/config.go @@ -1,8 +1,6 @@ package define var ( - // DefaultInitPath is the default path to the container-init binary - DefaultInitPath = "/usr/libexec/podman/catatonit" // DefaultInfraImage to use for infra container DefaultInfraImage = "k8s.gcr.io/pause:3.2" // DefaultInfraCommand to be run in an infra container @@ -11,15 +9,9 @@ var ( DefaultSHMLockPath = "/libpod_lock" // DefaultRootlessSHMLockPath is the default path for rootless SHM locks DefaultRootlessSHMLockPath = "/libpod_rootless_lock" - // DefaultDetachKeys is the default keys sequence for detaching a - // container - DefaultDetachKeys = "ctrl-p,ctrl-q" ) const ( - // CtrRemoveTimeout is the default number of seconds to wait after stopping a container - // before sending the kill signal - CtrRemoveTimeout = 10 // DefaultTransport is a prefix that we apply to an image name // to check docker hub first for the image DefaultTransport = "docker://" diff --git a/libpod/define/runtime.go b/libpod/define/runtime.go index 4d8c6cb4d..1539e19ee 100644 --- a/libpod/define/runtime.go +++ b/libpod/define/runtime.go @@ -18,10 +18,6 @@ const ( SQLiteStateStore RuntimeStateStore = iota // BoltDBStateStore is a state backed by a BoltDB database BoltDBStateStore RuntimeStateStore = iota - // CgroupfsCgroupsManager represents cgroupfs native cgroup manager - CgroupfsCgroupsManager = "cgroupfs" - // SystemdCgroupsManager represents systemd native cgroup manager - SystemdCgroupsManager = "systemd" // ContainerCreateTimeout is the timeout before we decide we've failed // to create a container. // TODO: Make this generic - all OCI runtime operations should use the @@ -29,9 +25,4 @@ const ( // TODO: Consider dropping from 240 to 60 seconds. I don't think waiting // 4 minutes versus 1 minute makes a real difference. ContainerCreateTimeout = 240 * time.Second - // DefaultShmSize is the default shm size - DefaultShmSize = 64 * 1024 * 1024 - // NsRunDir is the default directory in which running network namespaces - // are stored - NsRunDir = "/var/run/netns" ) diff --git a/libpod/events.go b/libpod/events.go index be21e510a..20ebecc66 100644 --- a/libpod/events.go +++ b/libpod/events.go @@ -11,8 +11,8 @@ import ( // newEventer returns an eventer that can be used to read/write events func (r *Runtime) newEventer() (events.Eventer, error) { options := events.EventerOptions{ - EventerType: r.config.EventsLogger, - LogFilePath: r.config.EventsLogFilePath, + EventerType: r.config.Engine.EventsLogger, + LogFilePath: r.config.Engine.EventsLogFilePath, } return events.NewEventer(options) } diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go index ca562ab7e..2f802f333 100644 --- a/libpod/in_memory_state.go +++ b/libpod/in_memory_state.go @@ -3,7 +3,6 @@ package libpod import ( "strings" - "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/registrar" "github.com/containers/storage/pkg/truncindex" @@ -90,8 +89,8 @@ func (s *InMemoryState) Refresh() error { // GetDBConfig is not implemented for in-memory state. // As we do not store a config, return an empty one. -func (s *InMemoryState) GetDBConfig() (*config.DBConfig, error) { - return &config.DBConfig{}, nil +func (s *InMemoryState) GetDBConfig() (*DBConfig, error) { + return &DBConfig{}, nil } // ValidateDBConfig is not implemented for the in-memory state. diff --git a/libpod/info.go b/libpod/info.go index e5c075d97..8d411f0d4 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -165,7 +165,7 @@ func (r *Runtime) storeInfo() (map[string]interface{}, error) { } } info["GraphOptions"] = graphOptions - info["VolumePath"] = r.config.VolumePath + info["VolumePath"] = r.config.Engine.VolumePath configFile, err := storage.DefaultConfigFile(rootless.IsRootless()) if err != nil { diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index ab6ec4439..c3a90f481 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -148,7 +148,7 @@ func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q []*cnitypes.Result, logrus.Debugf("Made network namespace at %s for container %s", ctrNS.Path(), ctr.ID()) networkStatus := []*cnitypes.Result{} - if !rootless.IsRootless() && ctr.config.NetMode != "slirp4netns" { + if !rootless.IsRootless() && !ctr.config.NetMode.IsSlirp4netns() { networkStatus, err = r.configureNetNS(ctr, ctrNS) } return ctrNS, networkStatus, err @@ -177,7 +177,7 @@ func checkSlirpFlags(path string) (*slirpFeatures, error) { // Configure the network namespace for a rootless container func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { - path := r.config.NetworkCmdPath + path := r.config.Engine.NetworkCmdPath if path == "" { var err error @@ -196,7 +196,7 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { defer errorhandling.CloseQuiet(syncW) havePortMapping := len(ctr.Config().PortMappings) > 0 - logPath := filepath.Join(ctr.runtime.config.TmpDir, fmt.Sprintf("slirp4netns-%s.log", ctr.config.ID)) + logPath := filepath.Join(ctr.runtime.config.Engine.TmpDir, fmt.Sprintf("slirp4netns-%s.log", ctr.config.ID)) cmdArgs := []string{} slirpFeatures, err := checkSlirpFlags(path) @@ -338,7 +338,7 @@ func (r *Runtime) setupRootlessPortMapping(ctr *Container, netnsPath string) (er defer errorhandling.CloseQuiet(syncR) defer errorhandling.CloseQuiet(syncW) - logPath := filepath.Join(ctr.runtime.config.TmpDir, fmt.Sprintf("rootlessport-%s.log", ctr.config.ID)) + logPath := filepath.Join(ctr.runtime.config.Engine.TmpDir, fmt.Sprintf("rootlessport-%s.log", ctr.config.ID)) logFile, err := os.Create(logPath) if err != nil { return errors.Wrapf(err, "failed to open rootlessport log file %s", logPath) @@ -362,7 +362,7 @@ func (r *Runtime) setupRootlessPortMapping(ctr *Container, netnsPath string) (er NetNSPath: netnsPath, ExitFD: 3, ReadyFD: 4, - TmpDir: ctr.runtime.config.TmpDir, + TmpDir: ctr.runtime.config.Engine.TmpDir, } cfgJSON, err := json.Marshal(cfg) if err != nil { @@ -485,7 +485,7 @@ func (r *Runtime) teardownNetNS(ctr *Container) error { logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS.Path(), ctr.ID()) // rootless containers do not use the CNI plugin - if !rootless.IsRootless() && ctr.config.NetMode != "slirp4netns" { + if !rootless.IsRootless() && !ctr.config.NetMode.IsSlirp4netns() { var requestedIP net.IP if ctr.requestedIP != nil { requestedIP = ctr.requestedIP diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index 5fc46c31c..433993edb 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -9,6 +9,7 @@ import ( "os" "path/filepath" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/kubeutils" @@ -104,7 +105,7 @@ func (c *Container) attachToExec(streams *AttachStreams, keys *string, sessionID defer errorhandling.CloseQuiet(startFd) defer errorhandling.CloseQuiet(attachFd) - detachString := define.DefaultDetachKeys + detachString := config.DefaultDetachKeys if keys != nil { detachString = *keys } diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 6d9a976cb..ce888c690 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -20,8 +20,8 @@ import ( "text/template" "time" + "github.com/containers/common/pkg/config" conmonConfig "github.com/containers/conmon/runner/config" - "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/errorhandling" @@ -80,13 +80,13 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime runtime.name = name runtime.conmonPath = conmonPath - runtime.conmonEnv = runtimeCfg.ConmonEnvVars - runtime.cgroupManager = runtimeCfg.CgroupManager - runtime.tmpDir = runtimeCfg.TmpDir - runtime.logSizeMax = runtimeCfg.MaxLogSize - runtime.noPivot = runtimeCfg.NoPivotRoot - runtime.reservePorts = runtimeCfg.EnablePortReservation - runtime.sdNotify = runtimeCfg.SDNotify + runtime.conmonEnv = runtimeCfg.Engine.ConmonEnvVars + runtime.cgroupManager = runtimeCfg.Engine.CgroupManager + runtime.tmpDir = runtimeCfg.Engine.TmpDir + runtime.logSizeMax = runtimeCfg.Containers.LogSizeMax + runtime.noPivot = runtimeCfg.Engine.NoPivotRoot + runtime.reservePorts = runtimeCfg.Engine.EnablePortReservation + runtime.sdNotify = runtimeCfg.Engine.SDNotify // TODO: probe OCI runtime for feature and enable automatically if // available. @@ -127,7 +127,7 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime runtime.exitsDir = filepath.Join(runtime.tmpDir, "exits") runtime.socketsDir = filepath.Join(runtime.tmpDir, "socket") - if runtime.cgroupManager != define.CgroupfsCgroupsManager && runtime.cgroupManager != define.SystemdCgroupsManager { + if runtime.cgroupManager != config.CgroupfsCgroupsManager && runtime.cgroupManager != config.SystemdCgroupsManager { return nil, errors.Wrapf(define.ErrInvalidArg, "invalid cgroup manager specified: %s", runtime.cgroupManager) } @@ -177,7 +177,7 @@ func hasCurrentUserMapped(ctr *Container) bool { // CreateContainer creates a container. func (r *ConmonOCIRuntime) CreateContainer(ctr *Container, restoreOptions *ContainerCheckpointOptions) (err error) { if !hasCurrentUserMapped(ctr) { - for _, i := range []string{ctr.state.RunDir, ctr.runtime.config.TmpDir, ctr.config.StaticDir, ctr.state.Mountpoint, ctr.runtime.config.VolumePath} { + for _, i := range []string{ctr.state.RunDir, ctr.runtime.config.Engine.TmpDir, ctr.config.StaticDir, ctr.state.Mountpoint, ctr.runtime.config.Engine.VolumePath} { if err := makeAccessible(i, ctr.RootUID(), ctr.RootGID()); err != nil { return err } @@ -519,7 +519,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, httpConn net.Conn, httpBuf logrus.Debugf("Successfully connected to container %s attach socket %s", ctr.ID(), socketPath) - detachString := define.DefaultDetachKeys + detachString := ctr.runtime.config.Engine.DetachKeys if detachKeys != nil { detachString = *detachKeys } @@ -1365,7 +1365,7 @@ func (r *ConmonOCIRuntime) configureConmonEnv(runtimeDir string) ([]string, []*o func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, pidPath, logPath, exitDir, ociLogPath, logTag string) []string { // set the conmon API version to be able to use the correct sync struct keys args := []string{"--api-version", "1"} - if r.cgroupManager == define.SystemdCgroupsManager && !ctr.config.NoCgroups { + if r.cgroupManager == config.SystemdCgroupsManager && !ctr.config.NoCgroups { args = append(args, "-s") } args = append(args, "-c", ctr.ID()) @@ -1483,7 +1483,7 @@ func (r *ConmonOCIRuntime) moveConmonToCgroupAndSignal(ctr *Container, cmd *exec if mustCreateCgroup { cgroupParent := ctr.CgroupParent() - if r.cgroupManager == define.SystemdCgroupsManager { + if r.cgroupManager == config.SystemdCgroupsManager { unitName := createUnitName("libpod-conmon", ctr.ID()) realCgroupParent := cgroupParent diff --git a/libpod/oci_conmon_unsupported.go b/libpod/oci_conmon_unsupported.go index a2f52f527..395b6f6d9 100644 --- a/libpod/oci_conmon_unsupported.go +++ b/libpod/oci_conmon_unsupported.go @@ -3,7 +3,8 @@ package libpod import ( - "github.com/containers/libpod/libpod/config" + "github.com/containers/common/pkg/config" + "github.com/containers/libpod/libpod/define" ) diff --git a/libpod/oci_missing.go b/libpod/oci_missing.go index 326591d89..a5d589255 100644 --- a/libpod/oci_missing.go +++ b/libpod/oci_missing.go @@ -50,7 +50,7 @@ func getMissingRuntime(name string, r *Runtime) (OCIRuntime, error) { newRuntime := new(MissingRuntime) newRuntime.name = name - newRuntime.exitsDir = filepath.Join(r.config.TmpDir, "exits") + newRuntime.exitsDir = filepath.Join(r.config.Engine.TmpDir, "exits") missingRuntimes[name] = newRuntime diff --git a/libpod/options.go b/libpod/options.go index 74f9c485e..dfbec364a 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -7,6 +7,7 @@ import ( "regexp" "syscall" + "github.com/containers/common/pkg/config" "github.com/containers/image/v5/manifest" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" @@ -42,48 +43,48 @@ func WithStorageConfig(config storage.StoreOptions) RuntimeOption { setField := false if config.RunRoot != "" { - rt.config.StorageConfig.RunRoot = config.RunRoot - rt.config.StorageConfigRunRootSet = true + rt.storageConfig.RunRoot = config.RunRoot + rt.storageSet.RunRootSet = true setField = true } if config.GraphRoot != "" { - rt.config.StorageConfig.GraphRoot = config.GraphRoot - rt.config.StorageConfigGraphRootSet = true + rt.storageConfig.GraphRoot = config.GraphRoot + rt.storageSet.GraphRootSet = true // Also set libpod static dir, so we are a subdirectory // of the c/storage store by default - rt.config.StaticDir = filepath.Join(config.GraphRoot, "libpod") - rt.config.StaticDirSet = true + rt.config.Engine.StaticDir = filepath.Join(config.GraphRoot, "libpod") + rt.storageSet.StaticDirSet = true // Also set libpod volume path, so we are a subdirectory // of the c/storage store by default - rt.config.VolumePath = filepath.Join(config.GraphRoot, "volumes") - rt.config.VolumePathSet = true + rt.config.Engine.VolumePath = filepath.Join(config.GraphRoot, "volumes") + rt.storageSet.VolumePathSet = true setField = true } if config.GraphDriverName != "" { - rt.config.StorageConfig.GraphDriverName = config.GraphDriverName - rt.config.StorageConfigGraphDriverNameSet = true + rt.storageConfig.GraphDriverName = config.GraphDriverName + rt.storageSet.GraphDriverNameSet = true setField = true } if config.GraphDriverOptions != nil { - rt.config.StorageConfig.GraphDriverOptions = make([]string, len(config.GraphDriverOptions)) - copy(rt.config.StorageConfig.GraphDriverOptions, config.GraphDriverOptions) + rt.storageConfig.GraphDriverOptions = make([]string, len(config.GraphDriverOptions)) + copy(rt.storageConfig.GraphDriverOptions, config.GraphDriverOptions) setField = true } if config.UIDMap != nil { - rt.config.StorageConfig.UIDMap = make([]idtools.IDMap, len(config.UIDMap)) - copy(rt.config.StorageConfig.UIDMap, config.UIDMap) + rt.storageConfig.UIDMap = make([]idtools.IDMap, len(config.UIDMap)) + copy(rt.storageConfig.UIDMap, config.UIDMap) } if config.GIDMap != nil { - rt.config.StorageConfig.GIDMap = make([]idtools.IDMap, len(config.GIDMap)) - copy(rt.config.StorageConfig.GIDMap, config.GIDMap) + rt.storageConfig.GIDMap = make([]idtools.IDMap, len(config.GIDMap)) + copy(rt.storageConfig.GIDMap, config.GIDMap) } // If any one of runroot, graphroot, graphdrivername, @@ -94,11 +95,11 @@ func WithStorageConfig(config storage.StoreOptions) RuntimeOption { if err != nil { return err } - if rt.config.StorageConfig.GraphRoot == "" { - rt.config.StorageConfig.GraphRoot = storeOpts.GraphRoot + if rt.storageConfig.GraphRoot == "" { + rt.storageConfig.GraphRoot = storeOpts.GraphRoot } - if rt.config.StorageConfig.RunRoot == "" { - rt.config.StorageConfig.RunRoot = storeOpts.RunRoot + if rt.storageConfig.RunRoot == "" { + rt.storageConfig.RunRoot = storeOpts.RunRoot } } @@ -113,7 +114,7 @@ func WithDefaultTransport(defaultTransport string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.ImageDefaultTransport = defaultTransport + rt.config.Engine.ImageDefaultTransport = defaultTransport return nil } @@ -129,7 +130,7 @@ func WithSignaturePolicy(path string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.SignaturePolicyPath = path + rt.config.Engine.SignaturePolicyPath = path return nil } @@ -139,17 +140,17 @@ func WithSignaturePolicy(path string) RuntimeOption { // Please note that information is not portable between backing states. // As such, if this differs between two libpods running on the same system, // they will not share containers, and unspecified behavior may occur. -func WithStateType(storeType define.RuntimeStateStore) RuntimeOption { +func WithStateType(storeType config.RuntimeStateStore) RuntimeOption { return func(rt *Runtime) error { if rt.valid { return define.ErrRuntimeFinalized } - if storeType == define.InvalidStateStore { + if storeType == config.InvalidStateStore { return errors.Wrapf(define.ErrInvalidArg, "must provide a valid state store type") } - rt.config.StateType = storeType + rt.config.Engine.StateType = storeType return nil } @@ -166,8 +167,7 @@ func WithOCIRuntime(runtime string) RuntimeOption { return errors.Wrapf(define.ErrInvalidArg, "must provide a valid path") } - rt.config.OCIRuntime = runtime - rt.config.RuntimePath = nil + rt.config.Engine.OCIRuntime = runtime return nil } @@ -185,7 +185,7 @@ func WithConmonPath(path string) RuntimeOption { return errors.Wrapf(define.ErrInvalidArg, "must provide a valid path") } - rt.config.ConmonPath = []string{path} + rt.config.Engine.ConmonPath = []string{path} return nil } @@ -198,8 +198,8 @@ func WithConmonEnv(environment []string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.ConmonEnvVars = make([]string, len(environment)) - copy(rt.config.ConmonEnvVars, environment) + rt.config.Engine.ConmonEnvVars = make([]string, len(environment)) + copy(rt.config.Engine.ConmonEnvVars, environment) return nil } @@ -213,7 +213,7 @@ func WithNetworkCmdPath(path string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.NetworkCmdPath = path + rt.config.Engine.NetworkCmdPath = path return nil } @@ -228,12 +228,12 @@ func WithCgroupManager(manager string) RuntimeOption { return define.ErrRuntimeFinalized } - if manager != define.CgroupfsCgroupsManager && manager != define.SystemdCgroupsManager { + if manager != config.CgroupfsCgroupsManager && manager != config.SystemdCgroupsManager { return errors.Wrapf(define.ErrInvalidArg, "CGroup manager must be one of %s and %s", - define.CgroupfsCgroupsManager, define.SystemdCgroupsManager) + config.CgroupfsCgroupsManager, config.SystemdCgroupsManager) } - rt.config.CgroupManager = manager + rt.config.Engine.CgroupManager = manager return nil } @@ -247,8 +247,8 @@ func WithStaticDir(dir string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.StaticDir = dir - rt.config.StaticDirSet = true + rt.config.Engine.StaticDir = dir + rt.config.Engine.StaticDirSet = true return nil } @@ -267,7 +267,7 @@ func WithHooksDir(hooksDirs ...string) RuntimeOption { } } - rt.config.HooksDir = hooksDirs + rt.config.Engine.HooksDir = hooksDirs return nil } } @@ -285,7 +285,7 @@ func WithDefaultMountsFile(mountsFile string) RuntimeOption { if mountsFile == "" { return define.ErrInvalidArg } - rt.config.DefaultMountsFile = mountsFile + rt.config.Containers.DefaultMountsFile = mountsFile return nil } } @@ -298,8 +298,8 @@ func WithTmpDir(dir string) RuntimeOption { if rt.valid { return define.ErrRuntimeFinalized } - rt.config.TmpDir = dir - rt.config.TmpDirSet = true + rt.config.Engine.TmpDir = dir + rt.config.Engine.TmpDirSet = true return nil } @@ -322,7 +322,7 @@ func WithMaxLogSize(limit int64) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.MaxLogSize = limit + rt.config.Containers.LogSizeMax = limit return nil } @@ -336,7 +336,7 @@ func WithNoPivotRoot() RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.NoPivotRoot = true + rt.config.Engine.NoPivotRoot = true return nil } @@ -349,7 +349,7 @@ func WithCNIConfigDir(dir string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.CNIConfigDir = dir + rt.config.Network.NetworkConfigDir = dir return nil } @@ -362,7 +362,7 @@ func WithCNIPluginDir(dir string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.CNIPluginDir = []string{dir} + rt.config.Network.CNIPluginDirs = []string{dir} return nil } @@ -382,7 +382,7 @@ func WithNamespace(ns string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.Namespace = ns + rt.config.Engine.Namespace = ns return nil } @@ -397,8 +397,8 @@ func WithVolumePath(volPath string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.VolumePath = volPath - rt.config.VolumePathSet = true + rt.config.Engine.VolumePath = volPath + rt.config.Engine.VolumePathSet = true return nil } @@ -415,7 +415,7 @@ func WithDefaultInfraImage(img string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.InfraImage = img + rt.config.Engine.InfraImage = img return nil } @@ -429,7 +429,7 @@ func WithDefaultInfraCommand(cmd string) RuntimeOption { return define.ErrRuntimeFinalized } - rt.config.InfraCommand = cmd + rt.config.Engine.InfraCommand = cmd return nil } @@ -452,7 +452,7 @@ func WithRenumber() RuntimeOption { } // WithMigrate instructs libpod to migrate container configurations to account -// for changes between Libpod versions. All running containers will be stopped +// for changes between Engine versions. All running containers will be stopped // during a migration, then restarted after the migration is complete. func WithMigrate() RuntimeOption { return func(rt *Runtime) error { @@ -466,10 +466,10 @@ func WithMigrate() RuntimeOption { } } -// WithMigrateRuntime instructs Libpod to change the default OCI runtime on all +// WithMigrateRuntime instructs Engine to change the default OCI runtime on all // containers during a migration. This is not used if `MigrateRuntime()` is not // also passed. -// Libpod makes no promises that your containers continue to work with the new +// Engine makes no promises that your containers continue to work with the new // runtime - migrations between dissimilar runtimes may well break things. // Use with caution. func WithMigrateRuntime(requestedRuntime string) RuntimeOption { @@ -501,7 +501,7 @@ func WithEventsLogger(logger string) RuntimeOption { return errors.Wrapf(define.ErrInvalidArg, "%q is not a valid events backend", logger) } - rt.config.EventsLogger = logger + rt.config.Engine.EventsLogger = logger return nil } @@ -511,7 +511,7 @@ func WithEventsLogger(logger string) RuntimeOption { // listening func WithEnableSDNotify() RuntimeOption { return func(rt *Runtime) error { - rt.config.SDNotify = true + rt.config.Engine.SDNotify = true return nil } } @@ -1094,7 +1094,8 @@ func WithDNS(dnsServers []string) CtrCreateOption { } dns = append(dns, result) } - ctr.config.DNSServer = dns + ctr.config.DNSServer = append(ctr.config.DNSServer, dns...) + return nil } } @@ -1105,7 +1106,10 @@ func WithDNSOption(dnsOptions []string) CtrCreateOption { if ctr.valid { return define.ErrCtrFinalized } - ctr.config.DNSOption = dnsOptions + 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...) return nil } } diff --git a/libpod/pod_internal.go b/libpod/pod_internal.go index b5895d133..851f52a4e 100644 --- a/libpod/pod_internal.go +++ b/libpod/pod_internal.go @@ -5,6 +5,7 @@ import ( "path/filepath" "time" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/storage/pkg/stringid" "github.com/pkg/errors" @@ -65,19 +66,19 @@ func (p *Pod) refresh() error { // We need to recreate the pod's cgroup if p.config.UsePodCgroup { - switch p.runtime.config.CgroupManager { - case define.SystemdCgroupsManager: + switch p.runtime.config.Engine.CgroupManager { + case config.SystemdCgroupsManager: cgroupPath, err := systemdSliceFromPath(p.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", p.ID())) if err != nil { logrus.Errorf("Error creating CGroup for pod %s: %v", p.ID(), err) } p.state.CgroupPath = cgroupPath - case define.CgroupfsCgroupsManager: + case config.CgroupfsCgroupsManager: p.state.CgroupPath = filepath.Join(p.config.CgroupParent, p.ID()) logrus.Debugf("setting pod cgroup to %s", p.state.CgroupPath) default: - return errors.Wrapf(define.ErrInvalidArg, "unknown cgroups manager %s specified", p.runtime.config.CgroupManager) + return errors.Wrapf(define.ErrInvalidArg, "unknown cgroups manager %s specified", p.runtime.config.Engine.CgroupManager) } } diff --git a/libpod/reset.go b/libpod/reset.go index ae0a0cde9..c6754b7f6 100644 --- a/libpod/reset.go +++ b/libpod/reset.go @@ -88,14 +88,13 @@ func (r *Runtime) Reset(ctx context.Context) error { } prevError = err } - runtimeDir, err := util.GetRuntimeDir() if err != nil { return err } - tempDir := r.config.TmpDir - if r.config.TmpDir == runtimeDir { - tempDir = filepath.Join(r.config.TmpDir, "containers") + tempDir := r.config.Engine.TmpDir + if tempDir == runtimeDir { + tempDir = filepath.Join(tempDir, "containers") } if err := os.RemoveAll(tempDir); err != nil { if prevError != nil { diff --git a/libpod/runtime.go b/libpod/runtime.go index 8dcec82db..422b79359 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -11,11 +11,13 @@ import ( is "github.com/containers/image/v5/storage" "github.com/containers/image/v5/types" - "github.com/containers/libpod/libpod/config" + + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/lock" + "github.com/containers/libpod/pkg/cgroups" sysreg "github.com/containers/libpod/pkg/registries" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/util" @@ -30,9 +32,20 @@ import ( // NewRuntime type RuntimeOption func(*Runtime) error +type storageSet struct { + RunRootSet bool + GraphRootSet bool + StaticDirSet bool + VolumePathSet bool + GraphDriverNameSet bool + TmpDirSet bool +} + // Runtime is the core libpod runtime type Runtime struct { - config *config.Config + config *config.Config + storageConfig storage.StoreOptions + storageSet storageSet state State store storage.Store @@ -116,7 +129,12 @@ func SetXdgDirs() error { // NewRuntime creates a new container runtime // Options can be passed to override the default configuration for the runtime func NewRuntime(ctx context.Context, options ...RuntimeOption) (runtime *Runtime, err error) { - return newRuntimeFromConfig(ctx, "", options...) + conf, err := config.NewConfig("") + if err != nil { + return nil, err + } + conf.CheckCgroupsAndAdjustConfig() + return newRuntimeFromConfig(ctx, conf, options...) } // NewRuntimeFromConfig creates a new container runtime using the given @@ -124,21 +142,29 @@ func NewRuntime(ctx context.Context, options ...RuntimeOption) (runtime *Runtime // functions can be used to mutate this configuration further. // An error will be returned if the configuration file at the given path does // not exist or cannot be loaded -func NewRuntimeFromConfig(ctx context.Context, userConfigPath string, options ...RuntimeOption) (runtime *Runtime, err error) { - if userConfigPath == "" { - return nil, errors.New("invalid configuration file specified") - } - return newRuntimeFromConfig(ctx, userConfigPath, options...) +func NewRuntimeFromConfig(ctx context.Context, userConfig *config.Config, options ...RuntimeOption) (runtime *Runtime, err error) { + + return newRuntimeFromConfig(ctx, userConfig, options...) } -func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ...RuntimeOption) (runtime *Runtime, err error) { +func newRuntimeFromConfig(ctx context.Context, conf *config.Config, options ...RuntimeOption) (runtime *Runtime, err error) { runtime = new(Runtime) - conf, err := config.NewConfig(userConfigPath) + if conf.Engine.OCIRuntime == "" { + conf.Engine.OCIRuntime = "runc" + // If we're running on cgroups v2, default to using crun. + if onCgroupsv2, _ := cgroups.IsCgroup2UnifiedMode(); onCgroupsv2 { + conf.Engine.OCIRuntime = "crun" + } + } + + runtime.config = conf + + storeOpts, err := storage.DefaultStoreOptions(rootless.IsRootless(), rootless.GetRootlessUID()) if err != nil { return nil, err } - runtime.config = conf + runtime.storageConfig = storeOpts // Overwrite config with user-given configuration options for _, opt := range options { @@ -157,9 +183,9 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) { var err error var manager lock.Manager - switch runtime.config.LockType { + switch runtime.config.Engine.LockType { case "file": - lockPath := filepath.Join(runtime.config.TmpDir, "locks") + lockPath := filepath.Join(runtime.config.Engine.TmpDir, "locks") manager, err = lock.OpenFileLockManager(lockPath) if err != nil { if os.IsNotExist(errors.Cause(err)) { @@ -178,11 +204,11 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) { lockPath = fmt.Sprintf("%s_%d", define.DefaultRootlessSHMLockPath, rootless.GetRootlessUID()) } // Set up the lock manager - manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks) + manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.Engine.NumLocks) if err != nil { switch { case os.IsNotExist(errors.Cause(err)): - manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks) + manager, err = lock.NewSHMLockManager(lockPath, runtime.config.Engine.NumLocks) if err != nil { return nil, errors.Wrapf(err, "failed to get new shm lock manager") } @@ -196,7 +222,7 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) { return nil, errors.Wrapf(err, "error removing libpod locks file %s", lockPath) } - manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks) + manager, err = lock.NewSHMLockManager(lockPath, runtime.config.Engine.NumLocks) if err != nil { return nil, err } @@ -205,7 +231,7 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) { } } default: - return nil, errors.Wrapf(define.ErrInvalidArg, "unknown lock type %s", runtime.config.LockType) + return nil, errors.Wrapf(define.ErrInvalidArg, "unknown lock type %s", runtime.config.Engine.LockType) } return manager, nil } @@ -221,11 +247,11 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { runtime.conmonPath = cPath // Make the static files directory if it does not exist - if err := os.MkdirAll(runtime.config.StaticDir, 0700); err != nil { + if err := os.MkdirAll(runtime.config.Engine.StaticDir, 0700); err != nil { // The directory is allowed to exist if !os.IsExist(err) { return errors.Wrapf(err, "error creating runtime static files directory %s", - runtime.config.StaticDir) + runtime.config.Engine.StaticDir) } } @@ -235,17 +261,17 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { // libpod/state, the config could take care of the code below. It // would further allow to move the types and consts into a coherent // package. - switch runtime.config.StateType { - case define.InMemoryStateStore: + switch runtime.config.Engine.StateType { + case config.InMemoryStateStore: state, err := NewInMemoryState() if err != nil { return err } runtime.state = state - case define.SQLiteStateStore: + case config.SQLiteStateStore: return errors.Wrapf(define.ErrInvalidArg, "SQLite state is currently disabled") - case define.BoltDBStateStore: - dbPath := filepath.Join(runtime.config.StaticDir, "bolt_state.db") + case config.BoltDBStateStore: + dbPath := filepath.Join(runtime.config.Engine.StaticDir, "bolt_state.db") state, err := NewBoltState(dbPath, runtime) if err != nil { @@ -253,7 +279,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { } runtime.state = state default: - return errors.Wrapf(define.ErrInvalidArg, "unrecognized state type passed (%v)", runtime.config.StateType) + return errors.Wrapf(define.ErrInvalidArg, "unrecognized state type passed (%v)", runtime.config.Engine.StateType) } // Grab config from the database so we can reset some defaults @@ -262,16 +288,16 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { return errors.Wrapf(err, "error retrieving runtime configuration from database") } - if err := runtime.config.MergeDBConfig(dbConfig); err != nil { + if err := runtime.mergeDBConfig(dbConfig); err != nil { return errors.Wrapf(err, "error merging database config into runtime config") } - logrus.Debugf("Using graph driver %s", runtime.config.StorageConfig.GraphDriverName) - logrus.Debugf("Using graph root %s", runtime.config.StorageConfig.GraphRoot) - logrus.Debugf("Using run root %s", runtime.config.StorageConfig.RunRoot) - logrus.Debugf("Using static dir %s", runtime.config.StaticDir) - logrus.Debugf("Using tmp dir %s", runtime.config.TmpDir) - logrus.Debugf("Using volume path %s", runtime.config.VolumePath) + logrus.Debugf("Using graph driver %s", runtime.storageConfig.GraphDriverName) + logrus.Debugf("Using graph root %s", runtime.storageConfig.GraphRoot) + logrus.Debugf("Using run root %s", runtime.storageConfig.RunRoot) + logrus.Debugf("Using static dir %s", runtime.config.Engine.StaticDir) + logrus.Debugf("Using tmp dir %s", runtime.config.Engine.TmpDir) + logrus.Debugf("Using volume path %s", runtime.config.Engine.VolumePath) // Validate our config against the database, now that we've set our // final storage configuration @@ -279,10 +305,10 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { return err } - if err := runtime.state.SetNamespace(runtime.config.Namespace); err != nil { + if err := runtime.state.SetNamespace(runtime.config.Engine.Namespace); err != nil { return errors.Wrapf(err, "error setting libpod namespace in state") } - logrus.Debugf("Set libpod namespace to %q", runtime.config.Namespace) + logrus.Debugf("Set libpod namespace to %q", runtime.config.Engine.Namespace) // Set up containers/storage var store storage.Store @@ -316,66 +342,40 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { // Set up containers/image runtime.imageContext = &types.SystemContext{ - SignaturePolicyPath: runtime.config.SignaturePolicyPath, + SignaturePolicyPath: runtime.config.Engine.SignaturePolicyPath, } // Create the tmpDir - if err := os.MkdirAll(runtime.config.TmpDir, 0751); err != nil { + if err := os.MkdirAll(runtime.config.Engine.TmpDir, 0751); err != nil { // The directory is allowed to exist if !os.IsExist(err) { - return errors.Wrapf(err, "error creating tmpdir %s", runtime.config.TmpDir) + return errors.Wrapf(err, "error creating tmpdir %s", runtime.config.Engine.TmpDir) } } // Create events log dir - if err := os.MkdirAll(filepath.Dir(runtime.config.EventsLogFilePath), 0700); err != nil { + if err := os.MkdirAll(filepath.Dir(runtime.config.Engine.EventsLogFilePath), 0700); err != nil { // The directory is allowed to exist if !os.IsExist(err) { - return errors.Wrapf(err, "error creating events dirs %s", filepath.Dir(runtime.config.EventsLogFilePath)) + return errors.Wrapf(err, "error creating events dirs %s", filepath.Dir(runtime.config.Engine.EventsLogFilePath)) } } // Make lookup tables for runtime support supportsJSON := make(map[string]bool) supportsNoCgroups := make(map[string]bool) - for _, r := range runtime.config.RuntimeSupportsJSON { + for _, r := range runtime.config.Engine.RuntimeSupportsJSON { supportsJSON[r] = true } - for _, r := range runtime.config.RuntimeSupportsNoCgroups { + for _, r := range runtime.config.Engine.RuntimeSupportsNoCgroups { supportsNoCgroups[r] = true } // Get us at least one working OCI runtime. runtime.ociRuntimes = make(map[string]OCIRuntime) - // Is the old runtime_path defined? - if runtime.config.RuntimePath != nil { - // Don't print twice in rootless mode. - if os.Geteuid() == 0 { - logrus.Warningf("The configuration is using `runtime_path`, which is deprecated and will be removed in future. Please use `runtimes` and `runtime`") - logrus.Warningf("If you are using both `runtime_path` and `runtime`, the configuration from `runtime_path` is used") - } - - if len(runtime.config.RuntimePath) == 0 { - return errors.Wrapf(define.ErrInvalidArg, "empty runtime path array passed") - } - - name := filepath.Base(runtime.config.RuntimePath[0]) - - json := supportsJSON[name] - nocgroups := supportsNoCgroups[name] - - ociRuntime, err := newConmonOCIRuntime(name, runtime.config.RuntimePath, runtime.conmonPath, runtime.config, json, nocgroups) - if err != nil { - return err - } - - runtime.ociRuntimes[name] = ociRuntime - runtime.defaultOCIRuntime = ociRuntime - } - // Initialize remaining OCI runtimes - for name, paths := range runtime.config.OCIRuntimes { + for name, paths := range runtime.config.Engine.OCIRuntimes { json := supportsJSON[name] nocgroups := supportsNoCgroups[name] @@ -393,16 +393,16 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { } // Do we have a default OCI runtime? - if runtime.config.OCIRuntime != "" { + if runtime.config.Engine.OCIRuntime != "" { // If the string starts with / it's a path to a runtime // executable. - if strings.HasPrefix(runtime.config.OCIRuntime, "/") { - name := filepath.Base(runtime.config.OCIRuntime) + if strings.HasPrefix(runtime.config.Engine.OCIRuntime, "/") { + name := filepath.Base(runtime.config.Engine.OCIRuntime) json := supportsJSON[name] nocgroups := supportsNoCgroups[name] - ociRuntime, err := newConmonOCIRuntime(name, []string{runtime.config.OCIRuntime}, runtime.conmonPath, runtime.config, json, nocgroups) + ociRuntime, err := newConmonOCIRuntime(name, []string{runtime.config.Engine.OCIRuntime}, runtime.conmonPath, runtime.config, json, nocgroups) if err != nil { return err } @@ -410,9 +410,9 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { runtime.ociRuntimes[name] = ociRuntime runtime.defaultOCIRuntime = ociRuntime } else { - ociRuntime, ok := runtime.ociRuntimes[runtime.config.OCIRuntime] + ociRuntime, ok := runtime.ociRuntimes[runtime.config.Engine.OCIRuntime] if !ok { - return errors.Wrapf(define.ErrInvalidArg, "default OCI runtime %q not found", runtime.config.OCIRuntime) + return errors.Wrapf(define.ErrInvalidArg, "default OCI runtime %q not found", runtime.config.Engine.OCIRuntime) } runtime.defaultOCIRuntime = ociRuntime } @@ -429,17 +429,18 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { } // Make the per-boot files directory if it does not exist - if err := os.MkdirAll(runtime.config.TmpDir, 0755); err != nil { + if err := os.MkdirAll(runtime.config.Engine.TmpDir, 0755); err != nil { // The directory is allowed to exist if !os.IsExist(err) { return errors.Wrapf(err, "error creating runtime temporary files directory %s", - runtime.config.TmpDir) + runtime.config.Engine.TmpDir) } } // Set up the CNI net plugin if !rootless.IsRootless() { - netPlugin, err := ocicni.InitCNI(runtime.config.CNIDefaultNetwork, runtime.config.CNIConfigDir, runtime.config.CNIPluginDir...) + + netPlugin, err := ocicni.InitCNI(runtime.config.Network.DefaultNetwork, runtime.config.Network.NetworkConfigDir, runtime.config.Network.CNIPluginDirs...) if err != nil { return errors.Wrapf(err, "error configuring CNI network plugin") } @@ -449,8 +450,8 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { // We now need to see if the system has restarted // We check for the presence of a file in our tmp directory to verify this // This check must be locked to prevent races - runtimeAliveLock := filepath.Join(runtime.config.TmpDir, "alive.lck") - runtimeAliveFile := filepath.Join(runtime.config.TmpDir, "alive") + runtimeAliveLock := filepath.Join(runtime.config.Engine.TmpDir, "alive.lck") + runtimeAliveFile := filepath.Join(runtime.config.Engine.TmpDir, "alive") aliveLock, err := storage.GetLockfile(runtimeAliveLock) if err != nil { return errors.Wrapf(err, "error acquiring runtime init lock") @@ -587,7 +588,7 @@ func (r *Runtime) Shutdown(force bool) error { logrus.Errorf("Error retrieving containers from database: %v", err) } else { for _, ctr := range ctrs { - if err := ctr.StopWithTimeout(define.CtrRemoveTimeout); err != nil { + if err := ctr.StopWithTimeout(r.config.Engine.StopTimeout); err != nil { logrus.Errorf("Error stopping container %s: %v", ctr.ID(), err) } } @@ -733,7 +734,7 @@ func (r *Runtime) generateName() (string, error) { // Configure store and image runtime func (r *Runtime) configureStore() error { - store, err := storage.GetStore(r.config.StorageConfig) + store, err := storage.GetStore(r.storageConfig) if err != nil { return err } @@ -750,9 +751,9 @@ func (r *Runtime) configureStore() error { r.storageService = storageService ir := image.NewImageRuntimeFromStore(r.store) - ir.SignaturePolicyPath = r.config.SignaturePolicyPath - ir.EventsLogFilePath = r.config.EventsLogFilePath - ir.EventsLogger = r.config.EventsLogger + ir.SignaturePolicyPath = r.config.Engine.SignaturePolicyPath + ir.EventsLogFilePath = r.config.Engine.EventsLogFilePath + ir.EventsLogger = r.config.Engine.EventsLogger r.imageRuntime = ir @@ -775,3 +776,74 @@ func (r *Runtime) SystemContext() *types.SystemContext { func (r *Runtime) GetOCIRuntimePath() string { return r.defaultOCIRuntime.Path() } + +// StorageConfig retrieves the storage options for the container runtime +func (r *Runtime) StorageConfig() storage.StoreOptions { + return r.storageConfig +} + +// DBConfig is a set of Libpod runtime configuration settings that are saved in +// a State when it is first created, and can subsequently be retrieved. +type DBConfig struct { + LibpodRoot string + LibpodTmp string + StorageRoot string + StorageTmp string + GraphDriver string + VolumePath string +} + +// mergeDBConfig merges the configuration from the database. +func (r *Runtime) mergeDBConfig(dbConfig *DBConfig) error { + + c := r.config.Engine + if !r.storageSet.RunRootSet && dbConfig.StorageTmp != "" { + if r.storageConfig.RunRoot != dbConfig.StorageTmp && + r.storageConfig.RunRoot != "" { + logrus.Debugf("Overriding run root %q with %q from database", + r.storageConfig.RunRoot, dbConfig.StorageTmp) + } + r.storageConfig.RunRoot = dbConfig.StorageTmp + } + + if !r.storageSet.GraphRootSet && dbConfig.StorageRoot != "" { + if r.storageConfig.GraphRoot != dbConfig.StorageRoot && + r.storageConfig.GraphRoot != "" { + logrus.Debugf("Overriding graph root %q with %q from database", + r.storageConfig.GraphRoot, dbConfig.StorageRoot) + } + r.storageConfig.GraphRoot = dbConfig.StorageRoot + } + + if !r.storageSet.GraphDriverNameSet && dbConfig.GraphDriver != "" { + if r.storageConfig.GraphDriverName != dbConfig.GraphDriver && + r.storageConfig.GraphDriverName != "" { + logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve", + r.storageConfig.GraphDriverName, dbConfig.GraphDriver) + } + r.storageConfig.GraphDriverName = dbConfig.GraphDriver + } + + if !r.storageSet.StaticDirSet && dbConfig.LibpodRoot != "" { + if c.StaticDir != dbConfig.LibpodRoot && c.StaticDir != "" { + logrus.Debugf("Overriding static dir %q with %q from database", c.StaticDir, dbConfig.LibpodRoot) + } + c.StaticDir = dbConfig.LibpodRoot + } + + if !r.storageSet.TmpDirSet && dbConfig.LibpodTmp != "" { + if c.TmpDir != dbConfig.LibpodTmp && c.TmpDir != "" { + logrus.Debugf("Overriding tmp dir %q with %q from database", c.TmpDir, dbConfig.LibpodTmp) + } + c.TmpDir = dbConfig.LibpodTmp + c.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log") + } + + if !r.storageSet.VolumePathSet && dbConfig.VolumePath != "" { + if c.VolumePath != dbConfig.VolumePath && c.VolumePath != "" { + logrus.Debugf("Overriding volume path %q with %q from database", c.VolumePath, dbConfig.VolumePath) + } + c.VolumePath = dbConfig.VolumePath + } + return nil +} diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index b99e6df84..207ac6477 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -8,11 +8,13 @@ import ( "strings" "time" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/rootless" "github.com/containers/storage/pkg/stringid" + "github.com/docker/go-units" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/opentracing/opentracing-go" @@ -59,7 +61,7 @@ func (r *Runtime) RestoreContainer(ctx context.Context, rSpec *spec.Spec, config // If the path to ConmonPidFile starts with the default value (RunRoot), then // the user has not specified '--conmon-pidfile' during run or create (probably). // In that case reset ConmonPidFile to be set to the default value later. - if strings.HasPrefix(ctr.config.ConmonPidFile, r.config.StorageConfig.RunRoot) { + if strings.HasPrefix(ctr.config.ConmonPidFile, r.storageConfig.RunRoot) { ctr.config.ConmonPidFile = "" } @@ -76,7 +78,11 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf if config == nil { ctr.config.ID = stringid.GenerateNonCryptoID() - ctr.config.ShmSize = define.DefaultShmSize + size, err := units.FromHumanSize(r.config.Containers.ShmSize) + if err != nil { + return nil, errors.Wrapf(err, "converting containers.conf ShmSize %s to an int", r.config.Containers.ShmSize) + } + ctr.config.ShmSize = size } else { // This is a restore from an imported checkpoint ctr.restoreFromCheckpoint = true @@ -101,14 +107,14 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf ctr.state.BindMounts = make(map[string]string) - ctr.config.StopTimeout = define.CtrRemoveTimeout + ctr.config.StopTimeout = r.config.Engine.StopTimeout ctr.config.OCIRuntime = r.defaultOCIRuntime.Name() // Set namespace based on current runtime namespace // Do so before options run so they can override it - if r.config.Namespace != "" { - ctr.config.Namespace = r.config.Namespace + if r.config.Engine.Namespace != "" { + ctr.config.Namespace = r.config.Engine.Namespace } ctr.runtime = r @@ -200,8 +206,8 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai // Check CGroup parent sanity, and set it if it was not set. // Only if we're actually configuring CGroups. if !ctr.config.NoCgroups { - switch r.config.CgroupManager { - case define.CgroupfsCgroupsManager: + switch r.config.Engine.CgroupManager { + case config.CgroupfsCgroupsManager: if ctr.config.CgroupParent == "" { if pod != nil && pod.config.UsePodCgroup { podCgroup, err := pod.CgroupPath() @@ -218,7 +224,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai } else if strings.HasSuffix(path.Base(ctr.config.CgroupParent), ".slice") { return nil, errors.Wrapf(define.ErrInvalidArg, "systemd slice received as cgroup parent when using cgroupfs") } - case define.SystemdCgroupsManager: + case config.SystemdCgroupsManager: if ctr.config.CgroupParent == "" { switch { case pod != nil && pod.config.UsePodCgroup: @@ -236,7 +242,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai return nil, errors.Wrapf(define.ErrInvalidArg, "did not receive systemd slice as cgroup parent when using systemd to manage cgroups") } default: - return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported CGroup manager: %s - cannot validate cgroup parent", r.config.CgroupManager) + return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported CGroup manager: %s - cannot validate cgroup parent", r.config.Engine.CgroupManager) } } diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go index 155ac83d9..06a7b3936 100644 --- a/libpod/runtime_pod_infra_linux.go +++ b/libpod/runtime_pod_infra_linux.go @@ -36,7 +36,7 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm isRootless := rootless.IsRootless() - entryCmd := []string{r.config.InfraCommand} + entryCmd := []string{r.config.Engine.InfraCommand} var options []CtrCreateOption // I've seen circumstances where config is being passed as nil. // Let's err on the side of safety and make sure it's safe to use. @@ -142,7 +142,7 @@ func (r *Runtime) createInfraContainer(ctx context.Context, p *Pod) (*Container, return nil, define.ErrRuntimeStopped } - newImage, err := r.ImageRuntime().New(ctx, r.config.InfraImage, "", "", nil, nil, image.SigningOptions{}, nil, util.PullImageMissing) + newImage, err := r.ImageRuntime().New(ctx, r.config.Engine.InfraImage, "", "", nil, nil, image.SigningOptions{}, nil, util.PullImageMissing) if err != nil { return nil, err } @@ -154,5 +154,5 @@ func (r *Runtime) createInfraContainer(ctx context.Context, p *Pod) (*Container, imageName := newImage.Names()[0] imageID := data.ID - return r.makeInfraContainer(ctx, p, imageName, r.config.InfraImage, imageID, data.Config) + return r.makeInfraContainer(ctx, p, imageName, r.config.Engine.InfraImage, imageID, data.Config) } diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 4afd5760a..872e8ea8a 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/pkg/cgroups" @@ -34,8 +35,8 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po // Set default namespace to runtime's namespace // Do so before options run so they can override it - if r.config.Namespace != "" { - pod.config.Namespace = r.config.Namespace + if r.config.Engine.Namespace != "" { + pod.config.Namespace = r.config.Engine.Namespace } for _, option := range options { @@ -75,8 +76,8 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po pod.valid = true // Check CGroup parent sanity, and set it if it was not set - switch r.config.CgroupManager { - case define.CgroupfsCgroupsManager: + switch r.config.Engine.CgroupManager { + case config.CgroupfsCgroupsManager: if pod.config.CgroupParent == "" { pod.config.CgroupParent = CgroupfsDefaultCgroupParent } else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") { @@ -89,7 +90,7 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po if pod.config.UsePodCgroup { pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID()) } - case define.SystemdCgroupsManager: + case config.SystemdCgroupsManager: if pod.config.CgroupParent == "" { if rootless.IsRootless() { pod.config.CgroupParent = SystemdDefaultRootlessCgroupParent @@ -109,7 +110,7 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po pod.state.CgroupPath = cgroupPath } default: - return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported CGroup manager: %s - cannot validate cgroup parent", r.config.CgroupManager) + return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported CGroup manager: %s - cannot validate cgroup parent", r.config.Engine.CgroupManager) } if pod.config.UsePodCgroup { @@ -198,7 +199,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) // the pod and conmon CGroups with a PID limit to prevent them from // spawning any further processes (particularly cleanup processes) which // would prevent removing the CGroups. - if p.runtime.config.CgroupManager == define.CgroupfsCgroupsManager { + if p.runtime.config.Engine.CgroupManager == config.CgroupfsCgroupsManager { // Get the conmon CGroup conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon") conmonCgroup, err := cgroups.Load(conmonCgroupPath) @@ -272,8 +273,8 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) if p.state.CgroupPath != "" { logrus.Debugf("Removing pod cgroup %s", p.state.CgroupPath) - switch p.runtime.config.CgroupManager { - case define.SystemdCgroupsManager: + switch p.runtime.config.Engine.CgroupManager { + case config.SystemdCgroupsManager: if err := deleteSystemdCgroup(p.state.CgroupPath); err != nil { if removalErr == nil { removalErr = errors.Wrapf(err, "error removing pod %s cgroup", p.ID()) @@ -281,7 +282,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) } } - case define.CgroupfsCgroupsManager: + case config.CgroupfsCgroupsManager: // Delete the cgroupfs cgroup // Make sure the conmon cgroup is deleted first // Since the pod is almost gone, don't bother failing @@ -326,9 +327,9 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) // keep going so we make sure to evict the pod before // ending up with an inconsistent state. if removalErr == nil { - removalErr = errors.Wrapf(define.ErrInternal, "unrecognized cgroup manager %s when removing pod %s cgroups", p.runtime.config.CgroupManager, p.ID()) + removalErr = errors.Wrapf(define.ErrInternal, "unrecognized cgroup manager %s when removing pod %s cgroups", p.runtime.config.Engine.CgroupManager, p.ID()) } else { - logrus.Errorf("Unknown cgroups manager %s specified - cannot remove pod %s cgroup", p.runtime.config.CgroupManager, p.ID()) + logrus.Errorf("Unknown cgroups manager %s specified - cannot remove pod %s cgroup", p.runtime.config.Engine.CgroupManager, p.ID()) } } } diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index e9cfda9d4..d4b46cc94 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -71,7 +71,7 @@ func (r *Runtime) newVolume(ctx context.Context, options ...VolumeCreateOption) } // Create the mountpoint of this volume - volPathRoot := filepath.Join(r.config.VolumePath, volume.config.Name) + volPathRoot := filepath.Join(r.config.Engine.VolumePath, volume.config.Name) if err := os.MkdirAll(volPathRoot, 0700); err != nil { return nil, errors.Wrapf(err, "error creating volume directory %q", volPathRoot) } diff --git a/libpod/state.go b/libpod/state.go index 9690e5819..6206a2994 100644 --- a/libpod/state.go +++ b/libpod/state.go @@ -1,7 +1,5 @@ package libpod -import "github.com/containers/libpod/libpod/config" - // State is a storage backend for libpod's current state. // A State is only initialized once per instance of libpod. // As such, initialization methods for State implementations may safely assume @@ -28,7 +26,7 @@ type State interface { // root and tmp dirs, and c/storage graph driver. // This is not implemented by the in-memory state, as it has no need to // validate runtime configuration. - GetDBConfig() (*config.DBConfig, error) + GetDBConfig() (*DBConfig, error) // ValidateDBConfig validates the config in the given Runtime struct // against paths stored in the configured database. diff --git a/libpod/state_test.go b/libpod/state_test.go index 39937d8e4..db1c8dd99 100644 --- a/libpod/state_test.go +++ b/libpod/state_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/containers/libpod/libpod/config" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/lock" "github.com/containers/storage" @@ -54,7 +54,7 @@ func getEmptyBoltState() (s State, p string, m lock.Manager, err error) { runtime := new(Runtime) runtime.config = new(config.Config) - runtime.config.StorageConfig = storage.StoreOptions{} + runtime.storageConfig = storage.StoreOptions{} runtime.lockManager = lockManager state, err := NewBoltState(dbPath, runtime) diff --git a/libpod/util.go b/libpod/util.go index f79d6c09b..e9d234bbe 100644 --- a/libpod/util.go +++ b/libpod/util.go @@ -12,7 +12,8 @@ import ( "strings" "time" - "github.com/containers/libpod/libpod/config" + "github.com/containers/common/pkg/config" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/utils" "github.com/fsnotify/fsnotify" diff --git a/libpod/volume_internal.go b/libpod/volume_internal.go index e89b3484d..781ff77ca 100644 --- a/libpod/volume_internal.go +++ b/libpod/volume_internal.go @@ -23,7 +23,7 @@ func newVolume(runtime *Runtime) (*Volume, error) { // teardownStorage deletes the volume from volumePath func (v *Volume) teardownStorage() error { - return os.RemoveAll(filepath.Join(v.runtime.config.VolumePath, v.Name())) + return os.RemoveAll(filepath.Join(v.runtime.config.Engine.VolumePath, v.Name())) } // Volumes with options set, or a filesystem type, or a device to mount need to diff --git a/pkg/adapter/checkpoint_restore.go b/pkg/adapter/checkpoint_restore.go index 7f80b782a..a5b74013b 100644 --- a/pkg/adapter/checkpoint_restore.go +++ b/pkg/adapter/checkpoint_restore.go @@ -114,7 +114,7 @@ func crImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input stri return nil, err } - _, err = runtime.ImageRuntime().New(ctx, config.RootfsImageName, rtc.SignaturePolicyPath, "", writer, nil, image.SigningOptions{}, nil, util.PullImageMissing) + _, err = runtime.ImageRuntime().New(ctx, config.RootfsImageName, rtc.Engine.SignaturePolicyPath, "", writer, nil, image.SigningOptions{}, nil, util.PullImageMissing) if err != nil { return nil, err } diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 0d2ca1a64..a2f73307b 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -16,6 +16,7 @@ import ( "time" "github.com/containers/buildah" + cfg "github.com/containers/common/pkg/config" "github.com/containers/image/v5/manifest" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/shared" @@ -380,11 +381,11 @@ func (r *LocalRuntime) selectDetachKeys(flagValue string) (string, error) { if err != nil { return "", errors.Wrapf(err, "unable to retrieve runtime config") } - if config.DetachKeys != "" { - return config.DetachKeys, nil + if config.Engine.DetachKeys != "" { + return config.Engine.DetachKeys, nil } - return define.DefaultDetachKeys, nil + return cfg.DefaultDetachKeys, nil } // Run a libpod container @@ -1369,9 +1370,9 @@ func (r *LocalRuntime) Commit(ctx context.Context, c *cliconfig.CommitValues, co return "", err } - sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false) + sc := image.GetSystemContext(rtc.Engine.SignaturePolicyPath, "", false) coptions := buildah.CommitOptions{ - SignaturePolicyPath: rtc.SignaturePolicyPath, + SignaturePolicyPath: rtc.Engine.SignaturePolicyPath, ReportWriter: writer, SystemContext: sc, PreferredManifestType: mimeType, diff --git a/pkg/adapter/network.go b/pkg/adapter/network.go index b25f54a13..577ffe19f 100644 --- a/pkg/adapter/network.go +++ b/pkg/adapter/network.go @@ -23,9 +23,9 @@ func getCNIConfDir(r *LocalRuntime) (string, error) { if err != nil { return "", err } - configPath := config.CNIConfigDir + configPath := config.Network.NetworkConfigDir - if len(config.CNIConfigDir) < 1 { + if len(config.Network.NetworkConfigDir) < 1 { configPath = network.CNIConfigDir } return configPath, nil @@ -211,7 +211,7 @@ func (r *LocalRuntime) NetworkCreateBridge(cli *cliconfig.NetworkCreateValues) ( plugins = append(plugins, network.NewPortMapPlugin()) plugins = append(plugins, network.NewFirewallPlugin()) // if we find the dnsname plugin, we add configuration for it - if network.HasDNSNamePlugin(runtimeConfig.CNIPluginDir) && !cli.DisableDNS { + if network.HasDNSNamePlugin(runtimeConfig.Network.CNIPluginDirs) && !cli.DisableDNS { // Note: in the future we might like to allow for dynamic domain names plugins = append(plugins, network.NewDNSNamePlugin(network.DefaultPodmanDomainName)) } diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go index 76e221fae..7a181e7e5 100644 --- a/pkg/adapter/runtime.go +++ b/pkg/adapter/runtime.go @@ -13,7 +13,6 @@ import ( "github.com/containers/buildah" "github.com/containers/buildah/imagebuildah" "github.com/containers/buildah/pkg/formats" - "github.com/containers/buildah/pkg/parse" "github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/types" "github.com/containers/libpod/cmd/podman/cliconfig" @@ -296,37 +295,13 @@ func libpodVolumeToVolume(volumes []*libpod.Volume) []*Volume { // Build is the wrapper to build images func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, options imagebuildah.BuildOptions, dockerfiles []string) (string, reference.Canonical, error) { - namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c.PodmanCommand.Command) - if err != nil { - return "", nil, errors.Wrapf(err, "error parsing namespace-related options") - } - usernsOption, idmappingOptions, err := parse.IDMappingOptions(c.PodmanCommand.Command, options.Isolation) - if err != nil { - return "", nil, errors.Wrapf(err, "error parsing ID mapping options") - } - namespaceOptions.AddOrReplace(usernsOption...) - - systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command) - if err != nil { - return "", nil, errors.Wrapf(err, "error building system context") - } authfile := c.Authfile if len(c.Authfile) == 0 { authfile = os.Getenv("REGISTRY_AUTH_FILE") } - systemContext.AuthFilePath = authfile - commonOpts, err := parse.CommonBuildOptions(c.PodmanCommand.Command) - if err != nil { - return "", nil, err - } - - options.NamespaceOptions = namespaceOptions - options.ConfigureNetwork = networkPolicy - options.IDMappingOptions = idmappingOptions - options.CommonBuildOpts = commonOpts - options.SystemContext = systemContext + options.SystemContext.AuthFilePath = authfile if c.GlobalFlags.Runtime != "" { options.Runtime = c.GlobalFlags.Runtime diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go index fc396eddb..a616e6c7a 100644 --- a/pkg/adapter/runtime_remote.go +++ b/pkg/adapter/runtime_remote.go @@ -17,6 +17,7 @@ import ( "github.com/containers/buildah/imagebuildah" "github.com/containers/buildah/pkg/formats" + "github.com/containers/common/pkg/config" "github.com/containers/image/v5/docker/reference" "github.com/containers/image/v5/types" "github.com/containers/libpod/cmd/podman/cliconfig" @@ -113,15 +114,20 @@ func (r RemoteRuntime) DeferredShutdown(force bool) { } } -// RuntimeConfig is a bogus wrapper for compat with the libpod runtime -type RuntimeConfig struct { +// Containers is a bogus wrapper for compat with the libpod runtime +type ContainersConfig struct { // CGroupManager is the CGroup Manager to use // Valid values are "cgroupfs" and "systemd" CgroupManager string } +// RuntimeConfig is a bogus wrapper for compat with the libpod runtime +type RuntimeConfig struct { + Containers ContainersConfig +} + // Shutdown is a bogus wrapper for compat with the libpod runtime -func (r *RemoteRuntime) GetConfig() (*RuntimeConfig, error) { +func (r *RemoteRuntime) GetConfig() (*config.Config, error) { return nil, nil } @@ -535,32 +541,40 @@ func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, opti Ulimit: options.CommonBuildOpts.Ulimit, Volume: options.CommonBuildOpts.Volumes, } - buildinfo := iopodman.BuildInfo{ - AdditionalTags: options.AdditionalTags, - Annotations: options.Annotations, - BuildArgs: options.Args, - BuildOptions: buildOptions, - CniConfigDir: options.CNIConfigDir, - CniPluginDir: options.CNIPluginPath, - Compression: string(options.Compression), - DefaultsMountFilePath: options.DefaultMountsFilePath, - Dockerfiles: dockerfiles, // Err: string(options.Err), + // Out: + // ReportWriter: + Architecture: options.Architecture, + AddCapabilities: options.AddCapabilities, + AdditionalTags: options.AdditionalTags, + Annotations: options.Annotations, + BuildArgs: options.Args, + BuildOptions: buildOptions, + CniConfigDir: options.CNIConfigDir, + CniPluginDir: options.CNIPluginPath, + Compression: string(options.Compression), + Devices: options.Devices, + DefaultsMountFilePath: options.DefaultMountsFilePath, + Dockerfiles: dockerfiles, + DropCapabilities: options.DropCapabilities, ForceRmIntermediateCtrs: options.ForceRmIntermediateCtrs, Iidfile: options.IIDFile, Label: options.Labels, Layers: options.Layers, - Nocache: options.NoCache, - // Out: + // NamespaceOptions: options.NamespaceOptions, + Nocache: options.NoCache, + Os: options.OS, Output: options.Output, OutputFormat: options.OutputFormat, PullPolicy: options.PullPolicy.String(), Quiet: options.Quiet, RemoteIntermediateCtrs: options.RemoveIntermediateCtrs, - // ReportWriter: - RuntimeArgs: options.RuntimeArgs, - Squash: options.Squash, + RuntimeArgs: options.RuntimeArgs, + SignBy: options.SignBy, + Squash: options.Squash, + Target: options.Target, + TransientMounts: options.TransientMounts, } // tar the file outputFile, err := ioutil.TempFile("", "varlink_tar_send") diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go index 6b8440fc2..12af40876 100644 --- a/pkg/api/handlers/compat/containers_create.go +++ b/pkg/api/handlers/compat/containers_create.go @@ -6,8 +6,8 @@ import ( "net/http" "strings" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod" - "github.com/containers/libpod/libpod/define" image2 "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" @@ -46,7 +46,12 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "NewFromLocal()")) return } - cc, err := makeCreateConfig(input, newImage) + defaultContainerConfig, err := runtime.GetConfig() + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "GetConfig()")) + return + } + cc, err := makeCreateConfig(defaultContainerConfig, input, newImage) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "makeCreatConfig()")) return @@ -55,7 +60,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { utils.CreateContainer(r.Context(), w, runtime, &cc) } -func makeCreateConfig(input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) { +func makeCreateConfig(defaultContainerConfig *config.Config, input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) { var ( err error init bool @@ -76,7 +81,7 @@ func makeCreateConfig(input handlers.CreateContainerConfig, newImage *image2.Ima workDir = input.WorkingDir } - stopTimeout := uint(define.CtrRemoveTimeout) + stopTimeout := defaultContainerConfig.Engine.StopTimeout if input.StopTimeout != nil { stopTimeout = uint(*input.StopTimeout) } diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go index 354a13bf5..ea9cbd691 100644 --- a/pkg/api/handlers/compat/images.go +++ b/pkg/api/handlers/compat/images.go @@ -129,13 +129,13 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()")) return } - sc := image2.GetSystemContext(rtc.SignaturePolicyPath, "", false) + sc := image2.GetSystemContext(rtc.Engine.SignaturePolicyPath, "", false) tag := "latest" options := libpod.ContainerCommitOptions{ Pause: true, } options.CommitOptions = buildah.CommitOptions{ - SignaturePolicyPath: rtc.SignaturePolicyPath, + SignaturePolicyPath: rtc.Engine.SignaturePolicyPath, ReportWriter: os.Stderr, SystemContext: sc, PreferredManifestType: manifest.DockerV2Schema2MediaType, diff --git a/pkg/api/handlers/compat/info.go b/pkg/api/handlers/compat/info.go index 30b49948d..104d0793b 100644 --- a/pkg/api/handlers/compat/info.go +++ b/pkg/api/handlers/compat/info.go @@ -9,8 +9,8 @@ import ( "strings" "time" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod" - "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" @@ -60,7 +60,7 @@ func GetInfo(w http.ResponseWriter, r *http.Request) { CPUCfsQuota: sysInfo.CPUCfsQuota, CPUSet: sysInfo.Cpuset, CPUShares: sysInfo.CPUShares, - CgroupDriver: configInfo.CgroupManager, + CgroupDriver: configInfo.Engine.CgroupManager, ClusterAdvertise: "", ClusterStore: "", ContainerdCommit: docker.Commit{}, @@ -69,7 +69,7 @@ func GetInfo(w http.ResponseWriter, r *http.Request) { ContainersRunning: stateInfo[define.ContainerStateRunning], ContainersStopped: stateInfo[define.ContainerStateStopped] + stateInfo[define.ContainerStateExited], Debug: log.IsLevelEnabled(log.DebugLevel), - DefaultRuntime: configInfo.OCIRuntime, + DefaultRuntime: configInfo.Engine.OCIRuntime, DockerRootDir: storeInfo["GraphRoot"].(string), Driver: storeInfo["GraphDriverName"].(string), DriverStatus: getGraphStatus(storeInfo), @@ -152,7 +152,7 @@ func getSecOpts(sysInfo *sysinfo.SysInfo) []string { func getRuntimes(configInfo *config.Config) map[string]docker.Runtime { var runtimes = map[string]docker.Runtime{} - for name, paths := range configInfo.OCIRuntimes { + for name, paths := range configInfo.Engine.OCIRuntimes { runtimes[name] = docker.Runtime{ Path: paths[0], Args: nil, diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index ee85c1a41..4b24d7d9f 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -452,7 +452,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { utils.Error(w, "failed to get runtime config", http.StatusInternalServerError, errors.Wrap(err, "failed to get runtime config")) return } - sc := image2.GetSystemContext(rtc.SignaturePolicyPath, "", false) + sc := image2.GetSystemContext(rtc.Engine.SignaturePolicyPath, "", false) tag := "latest" options := libpod.ContainerCommitOptions{ Pause: true, @@ -471,7 +471,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) { return } options.CommitOptions = buildah.CommitOptions{ - SignaturePolicyPath: rtc.SignaturePolicyPath, + SignaturePolicyPath: rtc.Engine.SignaturePolicyPath, ReportWriter: os.Stderr, SystemContext: sc, PreferredManifestType: mimeType, diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go index a3d2caba6..d87ed7eba 100644 --- a/pkg/api/handlers/libpod/manifests.go +++ b/pkg/api/handlers/libpod/manifests.go @@ -36,7 +36,7 @@ func ManifestCreate(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) return } - sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false) + sc := image.GetSystemContext(rtc.Engine.SignaturePolicyPath, "", false) manID, err := image.CreateManifestList(runtime.ImageRuntime(), *sc, query.Name, query.Image, query.All) if err != nil { utils.InternalServerError(w, err) @@ -79,7 +79,7 @@ func ManifestAdd(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) return } - sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false) + sc := image.GetSystemContext(rtc.Engine.SignaturePolicyPath, "", false) newID, err := newImage.AddManifest(*sc, manifestInput) if err != nil { utils.InternalServerError(w, err) @@ -149,7 +149,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) return } - sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false) + sc := image.GetSystemContext(rtc.Engine.SignaturePolicyPath, "", false) opts := manifests.PushOptions{ ImageListSelection: copy2.CopySpecificImages, SystemContext: sc, diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go index e3dbe3b35..e8a92e93e 100644 --- a/pkg/api/handlers/libpod/networks.go +++ b/pkg/api/handlers/libpod/networks.go @@ -18,7 +18,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) return } - configDir := config.CNIConfigDir + configDir := config.Network.NetworkConfigDir if len(configDir) < 1 { configDir = network.CNIConfigDir } diff --git a/pkg/apparmor/apparmor.go b/pkg/apparmor/apparmor.go index 1e824550d..8e17361cb 100644 --- a/pkg/apparmor/apparmor.go +++ b/pkg/apparmor/apparmor.go @@ -3,14 +3,15 @@ package apparmor import ( "errors" + "github.com/containers/common/pkg/config" libpodVersion "github.com/containers/libpod/version" ) var ( // DefaultLipodProfilePrefix is used for version-independent presence checks. - DefaultLipodProfilePrefix = "libpod-default" + "-" + DefaultLipodProfilePrefix = config.DefaultApparmorProfile // DefaultLibpodProfile is the name of default libpod AppArmor profile. - DefaultLibpodProfile = DefaultLipodProfilePrefix + libpodVersion.Version + DefaultLibpodProfile = DefaultLipodProfilePrefix + "-" + libpodVersion.Version // ErrApparmorUnsupported indicates that AppArmor support is not supported. ErrApparmorUnsupported = errors.New("AppArmor is not supported") // ErrApparmorRootless indicates that AppArmor support is not supported in rootless mode. diff --git a/pkg/domain/entities/engine.go b/pkg/domain/entities/engine.go index 8553f5326..c14348529 100644 --- a/pkg/domain/entities/engine.go +++ b/pkg/domain/entities/engine.go @@ -4,7 +4,7 @@ import ( "os/user" "path/filepath" - "github.com/containers/libpod/libpod/define" + "github.com/containers/common/pkg/config" "github.com/spf13/pflag" ) @@ -60,7 +60,7 @@ type EngineOptions struct { func NewEngineOptions() (EngineOptions, error) { u, _ := user.Current() return EngineOptions{ - CGroupManager: define.SystemdCgroupsManager, + CGroupManager: config.SystemdCgroupsManager, CniConfigDir: "", Config: "", ConmonPath: filepath.Join("usr", "bin", "conmon"), diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go index 730ded2e0..d59759707 100644 --- a/pkg/domain/infra/runtime_libpod.go +++ b/pkg/domain/infra/runtime_libpod.go @@ -220,9 +220,6 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo if !opts.withFDS { options = append(options, libpod.WithEnableSDNotify()) } - if fs.Changed("config") { - return libpod.NewRuntimeFromConfig(ctx, opts.flags.Config, options...) - } return libpod.NewRuntime(ctx, options...) } diff --git a/pkg/namespaces/namespaces.go b/pkg/namespaces/namespaces.go index 78b55bb2a..14453e7f4 100644 --- a/pkg/namespaces/namespaces.go +++ b/pkg/namespaces/namespaces.go @@ -101,7 +101,7 @@ func (n UsernsMode) IsPrivate() bool { func (n UsernsMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { - case "", hostType, "keep-id", nsType: + case "", privateType, hostType, "keep-id", nsType: case containerType: if len(parts) != 2 || parts[1] == "" { return false @@ -173,7 +173,7 @@ func (n UTSMode) Container() string { func (n UTSMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { - case "", hostType: + case "", privateType, hostType: case containerType: if len(parts) != 2 || parts[1] == "" { return false @@ -255,7 +255,7 @@ func (n PidMode) IsContainer() bool { func (n PidMode) Valid() bool { parts := strings.Split(string(n), ":") switch mode := parts[0]; mode { - case "", hostType: + case "", privateType, hostType: case containerType: if len(parts) != 2 || parts[1] == "" { return false diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 12dfed8c3..daa997104 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -196,6 +196,7 @@ func (c *CreateConfig) createExitCommand(runtime *libpod.Runtime) ([]string, err if err != nil { return nil, err } + storageConfig := runtime.StorageConfig() // We need a cleanup process for containers in the current model. // But we can't assume that the caller is Podman - it could be another @@ -208,23 +209,23 @@ func (c *CreateConfig) createExitCommand(runtime *libpod.Runtime) ([]string, err } command := []string{cmd, - "--root", config.StorageConfig.GraphRoot, - "--runroot", config.StorageConfig.RunRoot, + "--root", storageConfig.GraphRoot, + "--runroot", storageConfig.RunRoot, "--log-level", logrus.GetLevel().String(), - "--cgroup-manager", config.CgroupManager, - "--tmpdir", config.TmpDir, + "--cgroup-manager", config.Engine.CgroupManager, + "--tmpdir", config.Engine.TmpDir, } - if config.OCIRuntime != "" { - command = append(command, []string{"--runtime", config.OCIRuntime}...) + if config.Engine.OCIRuntime != "" { + command = append(command, []string{"--runtime", config.Engine.OCIRuntime}...) } - if config.StorageConfig.GraphDriverName != "" { - command = append(command, []string{"--storage-driver", config.StorageConfig.GraphDriverName}...) + if storageConfig.GraphDriverName != "" { + command = append(command, []string{"--storage-driver", storageConfig.GraphDriverName}...) } - for _, opt := range config.StorageConfig.GraphDriverOptions { + for _, opt := range storageConfig.GraphDriverOptions { command = append(command, []string{"--storage-opt", opt}...) } - if config.EventsLogger != "" { - command = append(command, []string{"--events-backend", config.EventsLogger}...) + if config.Engine.EventsLogger != "" { + command = append(command, []string{"--events-backend", config.Engine.EventsLogger}...) } if c.Syslog { diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 8f0630b85..d4fd5976f 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -4,9 +4,8 @@ import ( "strings" "github.com/containers/common/pkg/capabilities" + cconfig "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod" - libpodconfig "github.com/containers/libpod/libpod/config" - "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/env" "github.com/containers/libpod/pkg/rootless" @@ -81,6 +80,37 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM g.AddLinuxMaskedPaths("/sys/kernel") } } + var runtimeConfig *cconfig.Config + + if runtime != nil { + runtimeConfig, err = runtime.GetConfig() + if err != nil { + return nil, err + } + g.Config.Process.Capabilities.Bounding = runtimeConfig.Containers.DefaultCapabilities + sysctls, err := util.ValidateSysctls(runtimeConfig.Containers.DefaultSysctls) + if err != nil { + return nil, err + } + + for name, val := range config.Security.Sysctl { + sysctls[name] = val + } + config.Security.Sysctl = sysctls + if !util.StringInSlice("host", config.Resources.Ulimit) { + config.Resources.Ulimit = append(runtimeConfig.Containers.DefaultUlimits, config.Resources.Ulimit...) + } + if config.Resources.PidsLimit < 0 && !config.cgroupDisabled() { + config.Resources.PidsLimit = runtimeConfig.Containers.PidsLimit + } + + } else { + g.Config.Process.Capabilities.Bounding = cconfig.DefaultCapabilities + if config.Resources.PidsLimit < 0 && !config.cgroupDisabled() { + config.Resources.PidsLimit = cconfig.DefaultPidsLimit + } + } + gid5Available := true if isRootless { nGids, err := GetAvailableGids() @@ -242,16 +272,6 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM } } - // SECURITY OPTS - var runtimeConfig *libpodconfig.Config - - if runtime != nil { - runtimeConfig, err = runtime.GetConfig() - if err != nil { - return nil, err - } - } - g.SetProcessNoNewPrivileges(config.Security.NoNewPrivs) if !config.Security.Privileged { @@ -261,7 +281,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM // Unless already set via the CLI, check if we need to disable process // labels or set the defaults. if len(config.Security.LabelOpts) == 0 && runtimeConfig != nil { - if !runtimeConfig.EnableLabeling { + if !runtimeConfig.Containers.EnableLabeling { // Disabled in the config. config.Security.LabelOpts = append(config.Security.LabelOpts, "disable") } else if err := config.Security.SetLabelOpts(runtime, &config.Pid, &config.Ipc); err != nil { @@ -284,7 +304,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM if err != nil { return nil, err } - if (!cgroup2 || (runtimeConfig != nil && runtimeConfig.CgroupManager != define.SystemdCgroupsManager)) && config.Resources.PidsLimit == sysinfo.GetDefaultPidsLimit() { + if (!cgroup2 || (runtimeConfig != nil && runtimeConfig.Engine.CgroupManager != cconfig.SystemdCgroupsManager)) && config.Resources.PidsLimit == sysinfo.GetDefaultPidsLimit() { setPidLimit = false } } @@ -376,7 +396,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM configSpec.Linux.Resources = &spec.LinuxResources{} } - canUseResources := cgroup2 && runtimeConfig != nil && (runtimeConfig.CgroupManager == define.SystemdCgroupsManager) + canUseResources := cgroup2 && runtimeConfig != nil && (runtimeConfig.Engine.CgroupManager == cconfig.SystemdCgroupsManager) if addedResources && !canUseResources { return nil, errors.New("invalid configuration, cannot specify resource limits without cgroups v2 and --cgroup-manager=systemd") @@ -433,6 +453,10 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM return configSpec, nil } +func (config *CreateConfig) cgroupDisabled() bool { + return config.Cgroup.Cgroups == "disabled" +} + func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, g *generate.Generator) { if !privileged { for _, mp := range []string{ diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go index c365701de..b0687b4c2 100644 --- a/pkg/spec/storage.go +++ b/pkg/spec/storage.go @@ -124,7 +124,7 @@ func (config *CreateConfig) parseVolumes(runtime *libpod.Runtime) ([]spec.Mount, if err != nil { return nil, nil, err } - initPath = rtc.InitPath + initPath = rtc.Engine.InitPath } initMount, err := config.addContainerInitBinary(initPath) if err != nil { diff --git a/pkg/specgen/container_create.go b/pkg/specgen/container_create.go index cf082441d..b4039bb91 100644 --- a/pkg/specgen/container_create.go +++ b/pkg/specgen/container_create.go @@ -4,9 +4,10 @@ import ( "context" "os" + "github.com/containers/common/pkg/config" "github.com/containers/libpod/libpod" - "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" + "github.com/containers/storage" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -30,7 +31,7 @@ func (s *SpecGenerator) MakeContainer(rt *libpod.Runtime) (*libpod.Container, er if err != nil { return nil, err } - options = append(options, s.createExitCommandOption(rtc, podmanPath)) + options = append(options, s.createExitCommandOption(rt.StorageConfig(), rtc, podmanPath)) newImage, err := rt.ImageRuntime().NewFromLocal(s.Image) if err != nil { return nil, err @@ -148,7 +149,7 @@ func (s *SpecGenerator) createContainerOptions(rt *libpod.Runtime) ([]libpod.Ctr return options, nil } -func (s *SpecGenerator) createExitCommandOption(config *config.Config, podmanPath string) libpod.CtrCreateOption { +func (s *SpecGenerator) createExitCommandOption(storageConfig storage.StoreOptions, config *config.Config, podmanPath string) libpod.CtrCreateOption { // We need a cleanup process for containers in the current model. // But we can't assume that the caller is Podman - it could be another // user of the API. @@ -156,23 +157,23 @@ func (s *SpecGenerator) createExitCommandOption(config *config.Config, podmanPat // still invoke a cleanup process. command := []string{podmanPath, - "--root", config.StorageConfig.GraphRoot, - "--runroot", config.StorageConfig.RunRoot, + "--root", storageConfig.GraphRoot, + "--runroot", storageConfig.RunRoot, "--log-level", logrus.GetLevel().String(), - "--cgroup-manager", config.CgroupManager, - "--tmpdir", config.TmpDir, + "--cgroup-manager", config.Engine.CgroupManager, + "--tmpdir", config.Engine.TmpDir, } - if config.OCIRuntime != "" { - command = append(command, []string{"--runtime", config.OCIRuntime}...) + if config.Engine.OCIRuntime != "" { + command = append(command, []string{"--runtime", config.Engine.OCIRuntime}...) } - if config.StorageConfig.GraphDriverName != "" { - command = append(command, []string{"--storage-driver", config.StorageConfig.GraphDriverName}...) + if storageConfig.GraphDriverName != "" { + command = append(command, []string{"--storage-driver", storageConfig.GraphDriverName}...) } - for _, opt := range config.StorageConfig.GraphDriverOptions { + for _, opt := range storageConfig.GraphDriverOptions { command = append(command, []string{"--storage-opt", opt}...) } - if config.EventsLogger != "" { - command = append(command, []string{"--events-backend", config.EventsLogger}...) + if config.Engine.EventsLogger != "" { + command = append(command, []string{"--events-backend", config.Engine.EventsLogger}...) } // TODO Mheon wants to leave this for now diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 3e11c010a..0c055745d 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -609,3 +609,46 @@ func Tmpdir() string { return tmpdir } + +// ValidateSysctls validates a list of sysctl and returns it. +func ValidateSysctls(strSlice []string) (map[string]string, error) { + sysctl := make(map[string]string) + validSysctlMap := map[string]bool{ + "kernel.msgmax": true, + "kernel.msgmnb": true, + "kernel.msgmni": true, + "kernel.sem": true, + "kernel.shmall": true, + "kernel.shmmax": true, + "kernel.shmmni": true, + "kernel.shm_rmid_forced": true, + } + validSysctlPrefixes := []string{ + "net.", + "fs.mqueue.", + } + + for _, val := range strSlice { + foundMatch := false + arr := strings.Split(val, "=") + if len(arr) < 2 { + return nil, errors.Errorf("%s is invalid, sysctl values must be in the form of KEY=VALUE", val) + } + if validSysctlMap[arr[0]] { + sysctl[arr[0]] = arr[1] + continue + } + + for _, prefix := range validSysctlPrefixes { + if strings.HasPrefix(arr[0], prefix) { + sysctl[arr[0]] = arr[1] + foundMatch = true + break + } + } + if !foundMatch { + return nil, errors.Errorf("sysctl '%s' is not whitelisted", arr[0]) + } + } + return sysctl, nil +} diff --git a/pkg/util/utils_test.go b/pkg/util/utils_test.go index 0995d1e20..a9b37844e 100644 --- a/pkg/util/utils_test.go +++ b/pkg/util/utils_test.go @@ -245,3 +245,15 @@ func TestGetImageConfigMisc(t *testing.T) { _, err = GetImageConfig([]string{"BADINST testvalue"}) assert.NotNil(t, err) } + +func TestValidateSysctls(t *testing.T) { + strSlice := []string{"net.core.test1=4", "kernel.msgmax=2"} + result, _ := ValidateSysctls(strSlice) + assert.Equal(t, result["net.core.test1"], "4") +} + +func TestValidateSysctlBadSysctl(t *testing.T) { + strSlice := []string{"BLAU=BLUE", "GELB^YELLOW"} + _, err := ValidateSysctls(strSlice) + assert.Error(t, err) +} diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index 2dfb84e58..82587f5c4 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -30,7 +30,6 @@ import ( "github.com/containers/libpod/utils" "github.com/containers/storage/pkg/archive" v1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -147,7 +146,6 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI err error ) - systemContext := types.SystemContext{} contextDir := config.ContextDir newContextDir, err := ioutil.TempDir("", "buildTarball") @@ -175,6 +173,8 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI logrus.Errorf("unable to delete directory '%s': %q", newContextDir, err) } }() + + systemContext := types.SystemContext{} // All output (stdout, stderr) is captured in output as well var output bytes.Buffer @@ -192,40 +192,40 @@ func (i *LibpodAPI) BuildImage(call iopodman.VarlinkCall, config iopodman.BuildI Volumes: config.BuildOptions.Volume, } - hostNetwork := buildah.NamespaceOption{ - Name: string(specs.NetworkNamespace), - Host: true, - } - - namespace = append(namespace, hostNetwork) - options := imagebuildah.BuildOptions{ - CommonBuildOpts: commonOpts, + AddCapabilities: config.AddCapabilities, AdditionalTags: config.AdditionalTags, Annotations: config.Annotations, + Architecture: config.Architecture, Args: config.BuildArgs, CNIConfigDir: config.CniConfigDir, CNIPluginPath: config.CniPluginDir, + CommonBuildOpts: commonOpts, Compression: stringCompressionToArchiveType(config.Compression), ContextDirectory: newContextDir, DefaultMountsFilePath: config.DefaultsMountFilePath, + Devices: config.Devices, Err: &output, ForceRmIntermediateCtrs: config.ForceRmIntermediateCtrs, IIDFile: config.Iidfile, Labels: config.Label, Layers: config.Layers, + NamespaceOptions: namespace, NoCache: config.Nocache, + OS: config.Os, Out: &output, Output: config.Output, - NamespaceOptions: namespace, OutputFormat: config.OutputFormat, PullPolicy: stringPullPolicyToType(config.PullPolicy), Quiet: config.Quiet, RemoveIntermediateCtrs: config.RemoteIntermediateCtrs, ReportWriter: &output, RuntimeArgs: config.RuntimeArgs, + SignBy: config.SignBy, Squash: config.Squash, SystemContext: &systemContext, + Target: config.Target, + TransientMounts: config.TransientMounts, } if call.WantsMore() { @@ -587,7 +587,7 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch if err != nil { return call.ReplyErrorOccurred(err.Error()) } - sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false) + sc := image.GetSystemContext(rtc.Engine.SignaturePolicyPath, "", false) switch manifestType { case "oci", "": // nolint mimeType = buildah.OCIv1ImageManifest @@ -597,7 +597,7 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch return call.ReplyErrorOccurred(fmt.Sprintf("unrecognized image format %q", manifestType)) } coptions := buildah.CommitOptions{ - SignaturePolicyPath: rtc.SignaturePolicyPath, + SignaturePolicyPath: rtc.Engine.SignaturePolicyPath, ReportWriter: output, SystemContext: sc, PreferredManifestType: mimeType, diff --git a/test/e2e/config/containers-caps.conf b/test/e2e/config/containers-caps.conf new file mode 100644 index 000000000..7b964e4a7 --- /dev/null +++ b/test/e2e/config/containers-caps.conf @@ -0,0 +1,17 @@ +[containers] + +# List of default capabilities for containers. If it is empty or commented out, +# the default capabilities defined in the container engine will be added. +# +default_capabilities = [ + "CHOWN", + "DAC_OVERRIDE", + "FOWNER", + "FSETID", + "KILL", + "MKNOD", + "NET_BIND_SERVICE", + "SETGID", + "SETPCAP", + "SETUID", +] diff --git a/test/e2e/config/containers-ns.conf b/test/e2e/config/containers-ns.conf new file mode 100644 index 000000000..d2cf5b03f --- /dev/null +++ b/test/e2e/config/containers-ns.conf @@ -0,0 +1,24 @@ +[containers] + +pidns = "host" +netns = "host" +ipcns = "host" +utsns = "host" +userns = "host" +cgroupns = "host" + +# List of default capabilities for containers. If it is empty or commented out, +# the default capabilities defined in the container engine will be added. +# +default_capabilities = [ + "CHOWN", + "DAC_OVERRIDE", + "FOWNER", + "FSETID", + "KILL", + "MKNOD", + "NET_BIND_SERVICE", + "SETGID", + "SETPCAP", + "SETUID", +] diff --git a/test/e2e/config/containers.conf b/test/e2e/config/containers.conf new file mode 100644 index 000000000..55d18f5e8 --- /dev/null +++ b/test/e2e/config/containers.conf @@ -0,0 +1,50 @@ +[containers] + +# A list of ulimits to be set in containers by default, specified as +# "<ulimit name>=<soft limit>:<hard limit>", for example: +# "nofile=1024:2048" +# See setrlimit(2) for a list of resource names. +# Any limit not specified here will be inherited from the process launching the +# container engine. +# Ulimits has limits for non privileged container engines. +# +default_ulimits = [ + "nofile=500:500", +] + +# Environment variable list for the conmon process; used for passing necessary +# environment variables to conmon or the runtime. +# +env = [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "foo=bar", +] + +# container engines use container separation using MAC(SELinux) labeling. +# Flag is ignored on label disabled systems. +# +label = true + +# Size of /dev/shm. Specified as <number><unit>. +# Unit is optional, values: +# b (bytes), k (kilobytes), m (megabytes), or g (gigabytes). +# If the unit is omitted, the system uses bytes. +# +shm_size = "201k" + +# List of devices. Specified as +# "<device-on-host>:<device-on-container>:<permissions>", for example: +# "/dev/sdc:/dev/xvdc:rwm". +# If it is empty or commented out, only the default devices will be used +# +devices = [ + "/dev/zero:/dev/notone,rwm", +] + +default_sysctls = [ + "net.ipv4.ping_group_range=0 1000", +] + +dns_searches=[ "foobar.com", ] +dns_servers=[ "1.2.3.4", ] +dns_options=[ "debug", ] diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go new file mode 100644 index 000000000..a2ef7eb4a --- /dev/null +++ b/test/e2e/containers_conf_test.go @@ -0,0 +1,214 @@ +// +build !remoteclient + +package integration + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + + . "github.com/containers/libpod/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman run", func() { + var ( + tempdir string + err error + podmanTest *PodmanTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() + podmanTest.SeedImages() + os.Setenv("CONTAINERS_CONF", "config/containers.conf") + }) + + AfterEach(func() { + podmanTest.Cleanup() + f := CurrentGinkgoTestDescription() + processTestResult(f) + os.Unsetenv("CONTAINERS_CONF") + }) + + It("podman run limits test", func() { + SkipIfRootless() + //containers.conf is set to "nofile=500:500" + session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("500")) + + session = podmanTest.Podman([]string{"run", "--rm", "--ulimit", "nofile=2048:2048", fedoraMinimal, "ulimit", "-n"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("2048")) + }) + + It("podman run with containers.conf having additional env", func() { + //containers.conf default env includes foo + session := podmanTest.Podman([]string{"run", ALPINE, "printenv"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("foo=bar")) + }) + + It("podman run with additional devices", func() { + //containers.conf devices includes notone + session := podmanTest.Podman([]string{"run", "--device", "/dev/null:/dev/bar", ALPINE, "ls", "/dev"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("bar")) + Expect(session.OutputToString()).To(ContainSubstring("notone")) + }) + + It("podman run shm-size", func() { + //containers.conf default sets shm-size=201k, which ends up as 200k + session := podmanTest.Podman([]string{"run", ALPINE, "grep", "shm", "/proc/self/mounts"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("size=200k")) + }) + + It("podman Capabilities in containers.conf", func() { + SkipIfRootless() + os.Setenv("CONTAINERS_CONF", "config/containers.conf") + cap := podmanTest.Podman([]string{"run", ALPINE, "grep", "CapEff", "/proc/self/status"}) + cap.WaitWithDefaultTimeout() + Expect(cap.ExitCode()).To(Equal(0)) + + os.Setenv("CONTAINERS_CONF", "config/containers-ns.conf") + session := podmanTest.Podman([]string{"run", "busybox", "grep", "CapEff", "/proc/self/status"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).ToNot(Equal(cap.OutputToString())) + }) + + It("podman Regular capabilties", func() { + SkipIfRootless() + os.Setenv("CONTAINERS_CONF", "config/containers.conf") + setup := podmanTest.RunTopContainer("test1") + setup.WaitWithDefaultTimeout() + result := podmanTest.Podman([]string{"top", "test1", "capeff"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(result.OutputToString()).To(ContainSubstring("SYS_CHROOT")) + Expect(result.OutputToString()).To(ContainSubstring("NET_RAW")) + }) + + It("podman drop capabilties", func() { + os.Setenv("CONTAINERS_CONF", "config/containers-caps.conf") + setup := podmanTest.RunTopContainer("test1") + setup.WaitWithDefaultTimeout() + result := podmanTest.Podman([]string{"container", "top", "test1", "capeff"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(result.OutputToString()).ToNot(ContainSubstring("SYS_CHROOT")) + Expect(result.OutputToString()).ToNot(ContainSubstring("NET_RAW")) + }) + + verifyNSHandling := func(nspath, option string) { + os.Setenv("CONTAINERS_CONF", "config/containers-ns.conf") + //containers.conf default ipcns to default to host + session := podmanTest.Podman([]string{"run", ALPINE, "ls", "-l", nspath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + fields := strings.Split(session.OutputToString(), " ") + ctrNS := strings.TrimSuffix(fields[len(fields)-1], "\n") + + cmd := exec.Command("ls", "-l", nspath) + res, err := cmd.Output() + Expect(err).To(BeNil()) + fields = strings.Split(string(res), " ") + hostNS := strings.TrimSuffix(fields[len(fields)-1], "\n") + Expect(hostNS).To(Equal(ctrNS)) + + session = podmanTest.Podman([]string{"run", option, "private", ALPINE, "ls", "-l", nspath}) + fields = strings.Split(session.OutputToString(), " ") + ctrNS = fields[len(fields)-1] + Expect(hostNS).ToNot(Equal(ctrNS)) + } + + It("podman compare netns", func() { + verifyNSHandling("/proc/self/ns/net", "--network") + }) + + It("podman compare ipcns", func() { + verifyNSHandling("/proc/self/ns/ipc", "--ipc") + }) + + It("podman compare utsns", func() { + verifyNSHandling("/proc/self/ns/uts", "--uts") + }) + + It("podman compare pidns", func() { + verifyNSHandling("/proc/self/ns/pid", "--pid") + }) + + It("podman compare cgroupns", func() { + verifyNSHandling("/proc/self/ns/cgroup", "--cgroupns") + }) + + It("podman containers.conf additionalvolumes", func() { + conffile := filepath.Join(podmanTest.TempDir, "container.conf") + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + err := ioutil.WriteFile(conffile, []byte(fmt.Sprintf("[containers]\nvolumes=[\"%s:%s:Z\",]\n", tempdir, tempdir)), 0755) + if err != nil { + os.Exit(1) + } + + os.Setenv("CONTAINERS_CONF", conffile) + result := podmanTest.Podman([]string{"run", ALPINE, "ls", tempdir}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + }) + + It("podman run containers.conf sysctl test", func() { + SkipIfRootless() + //containers.conf is set to "net.ipv4.ping_group_range=0 1000" + session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "cat", "/proc/sys/net/ipv4/ping_group_range"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("1000")) + }) + + It("podman run containers.conf search domain", func() { + session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session.LineInOuputStartsWith("search foobar.com") + }) + + It("podman run add dns server", func() { + session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session.LineInOuputStartsWith("server 1.2.3.4") + }) + + It("podman run add dns option", func() { + session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session.LineInOuputStartsWith("options debug") + }) + + It("podman run containers.conf remove all search domain", func() { + session := podmanTest.Podman([]string{"run", "--dns-search=.", ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.LineInOuputStartsWith("search")).To(BeFalse()) + }) +}) |