Update podman to use containers.conf

Add more default options parsing

Switch to using --time as opposed to --timeout to better match Docker.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2020-04-16 21:54:31 -04:00
parent 5928e8fe80
commit e62d081770
39 changed files with 68 additions and 1496 deletions

View File

@ -51,12 +51,12 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
) )
createFlags.StringVar( createFlags.StringVar(
&cf.CGroupsNS, &cf.CGroupsNS,
"cgroupns", getDefaultCgroupNS(), "cgroupns", containerConfig.CgroupNS(),
"cgroup namespace to use", "cgroup namespace to use",
) )
createFlags.StringVar( createFlags.StringVar(
&cf.CGroups, &cf.CGroups,
"cgroups", "enabled", "cgroups", containerConfig.Cgroups(),
`control container cgroup configuration ("enabled"|"disabled"|"no-conmon")`, `control container cgroup configuration ("enabled"|"disabled"|"no-conmon")`,
) )
createFlags.StringVar( createFlags.StringVar(
@ -121,12 +121,12 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
) )
createFlags.StringVar( createFlags.StringVar(
&cf.DetachKeys, &cf.DetachKeys,
"detach-keys", GetDefaultDetachKeys(), "detach-keys", containerConfig.DetachKeys(),
"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-cf`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`", "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-cf`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`",
) )
createFlags.StringSliceVar( createFlags.StringSliceVar(
&cf.Device, &cf.Device,
"device", getDefaultDevices(), "device", containerConfig.Devices(),
fmt.Sprintf("Add a host device to the container"), fmt.Sprintf("Add a host device to the container"),
) )
createFlags.StringSliceVar( createFlags.StringSliceVar(
@ -161,7 +161,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
) )
createFlags.StringArrayVarP( createFlags.StringArrayVarP(
&cf.env, &cf.env,
"env", "e", getDefaultEnv(), "env", "e", containerConfig.Env(),
"Set environment variables in container", "Set environment variables in container",
) )
createFlags.BoolVar( createFlags.BoolVar(
@ -238,7 +238,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
) )
createFlags.StringVar( createFlags.StringVar(
&cf.InitPath, &cf.InitPath,
"init-path", getDefaultInitPath(), "init-path", containerConfig.InitPath(),
// Do not use the Value field for setting the default value to determine user input (i.e., non-empty string) // Do not use the Value field for setting the default value to determine user input (i.e., non-empty string)
fmt.Sprintf("Path to the container-init binary"), fmt.Sprintf("Path to the container-init binary"),
) )
@ -249,7 +249,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
) )
createFlags.StringVar( createFlags.StringVar(
&cf.IPC, &cf.IPC,
"ipc", getDefaultIPCNS(), "ipc", containerConfig.IPCNS(),
"IPC namespace to use", "IPC namespace to use",
) )
createFlags.StringVar( createFlags.StringVar(
@ -331,13 +331,13 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
// markFlagHidden(createFlags, "override-os") // markFlagHidden(createFlags, "override-os")
createFlags.StringVar( createFlags.StringVar(
&cf.PID, &cf.PID,
"pid", getDefaultPidNS(), "pid", containerConfig.PidNS(),
"PID namespace to use", "PID namespace to use",
) )
createFlags.Int64Var( createFlags.Int64Var(
&cf.PIDsLimit, &cf.PIDsLimit,
"pids-limit", getDefaultPidsLimit(), "pids-limit", containerConfig.PidsLimit(),
getDefaultPidsDescription(), "Tune container pids limit (set 0 for unlimited, -1 for server defaults)",
) )
createFlags.StringVar( createFlags.StringVar(
&cf.Pod, &cf.Pod,
@ -391,12 +391,12 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
) )
createFlags.StringArrayVar( createFlags.StringArrayVar(
&cf.SecurityOpt, &cf.SecurityOpt,
"security-opt", getDefaultSecurityOptions(), "security-opt", containerConfig.SecurityOptions(),
"Security Options", "Security Options",
) )
createFlags.StringVar( createFlags.StringVar(
&cf.ShmSize, &cf.ShmSize,
"shm-size", getDefaultShmSize(), "shm-size", containerConfig.ShmSize(),
"Size of /dev/shm "+sizeWithUnitFormat, "Size of /dev/shm "+sizeWithUnitFormat,
) )
createFlags.StringVar( createFlags.StringVar(
@ -427,7 +427,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
createFlags.StringSliceVar( createFlags.StringSliceVar(
&cf.Sysctl, &cf.Sysctl,
"sysctl", getDefaultSysctls(), "sysctl", containerConfig.Sysctls(),
"Sysctl options", "Sysctl options",
) )
createFlags.StringVar( createFlags.StringVar(
@ -452,7 +452,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
) )
createFlags.StringSliceVar( createFlags.StringSliceVar(
&cf.Ulimit, &cf.Ulimit,
"ulimit", getDefaultUlimits(), "ulimit", containerConfig.Ulimits(),
"Ulimit options", "Ulimit options",
) )
createFlags.StringVarP( createFlags.StringVarP(
@ -462,12 +462,12 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
) )
createFlags.StringVar( createFlags.StringVar(
&cf.UserNS, &cf.UserNS,
"userns", getDefaultUserNS(), "userns", containerConfig.Containers.UserNS,
"User namespace to use", "User namespace to use",
) )
createFlags.StringVar( createFlags.StringVar(
&cf.UTS, &cf.UTS,
"uts", getDefaultUTSNS(), "uts", containerConfig.Containers.UTSNS,
"UTS namespace to use", "UTS namespace to use",
) )
createFlags.StringArrayVar( createFlags.StringArrayVar(
@ -477,7 +477,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet {
) )
createFlags.StringArrayVarP( createFlags.StringArrayVarP(
&cf.Volume, &cf.Volume,
"volume", "v", getDefaultVolumes(), "volume", "v", containerConfig.Volumes(),
"Bind mount a volume into the container", "Bind mount a volume into the container",
) )
createFlags.StringSliceVar( createFlags.StringSliceVar(

View File

@ -1,18 +1,5 @@
package common package common
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/specgen"
"github.com/containers/libpod/pkg/sysinfo"
"github.com/opencontainers/selinux/go-selinux"
)
var ( var (
// DefaultHealthCheckInterval default value // DefaultHealthCheckInterval default value
DefaultHealthCheckInterval = "30s" DefaultHealthCheckInterval = "30s"
@ -25,111 +12,3 @@ var (
// DefaultImageVolume default value // DefaultImageVolume default value
DefaultImageVolume = "bind" DefaultImageVolume = "bind"
) )
// TODO these options are directly embedded into many of the CLI cobra values, as such
// this approach will not work in a remote client. so we will need to likely do something like a
// supported and unsupported approach here and backload these options into the specgen
// once we are "on" the host system.
func getDefaultSecurityOptions() []string {
securityOpts := []string{}
if containerConfig.Containers.SeccompProfile != "" && containerConfig.Containers.SeccompProfile != parse.SeccompDefaultPath {
securityOpts = append(securityOpts, fmt.Sprintf("seccomp=%s", containerConfig.Containers.SeccompProfile))
}
if apparmor.IsEnabled() && containerConfig.Containers.ApparmorProfile != "" {
securityOpts = append(securityOpts, fmt.Sprintf("apparmor=%s", containerConfig.Containers.ApparmorProfile))
}
if selinux.GetEnabled() && !containerConfig.Containers.EnableLabeling {
securityOpts = append(securityOpts, fmt.Sprintf("label=%s", selinux.DisableSecOpt()[0]))
}
return securityOpts
}
// getDefaultSysctls
func getDefaultSysctls() []string {
return containerConfig.Containers.DefaultSysctls
}
func getDefaultVolumes() []string {
return containerConfig.Containers.Volumes
}
func getDefaultDevices() []string {
return containerConfig.Containers.Devices
}
func getDefaultDNSServers() []string { //nolint
return containerConfig.Containers.DNSServers
}
func getDefaultDNSSearches() []string { //nolint
return containerConfig.Containers.DNSSearches
}
func getDefaultDNSOptions() []string { //nolint
return containerConfig.Containers.DNSOptions
}
func getDefaultEnv() []string {
return containerConfig.Containers.Env
}
func getDefaultInitPath() string {
return containerConfig.Containers.InitPath
}
func getDefaultIPCNS() string {
return containerConfig.Containers.IPCNS
}
func getDefaultPidNS() string {
return containerConfig.Containers.PidNS
}
func getDefaultNetNS() string { //nolint
if containerConfig.Containers.NetNS == string(specgen.Private) && rootless.IsRootless() {
return string(specgen.Slirp)
}
return containerConfig.Containers.NetNS
}
func getDefaultCgroupNS() string {
return containerConfig.Containers.CgroupNS
}
func getDefaultUTSNS() string {
return containerConfig.Containers.UTSNS
}
func getDefaultShmSize() string {
return containerConfig.Containers.ShmSize
}
func getDefaultUlimits() []string {
return containerConfig.Containers.DefaultUlimits
}
func getDefaultUserNS() string {
userns := os.Getenv("PODMAN_USERNS")
if userns != "" {
return userns
}
return containerConfig.Containers.UserNS
}
func getDefaultPidsLimit() int64 {
if rootless.IsRootless() {
cgroup2, _ := cgroups.IsCgroup2UnifiedMode()
if cgroup2 {
return containerConfig.Containers.PidsLimit
}
}
return sysinfo.GetDefaultPidsLimit()
}
func getDefaultPidsDescription() string {
return "Tune container pids limit (set 0 for unlimited)"
}
func GetDefaultDetachKeys() string {
return containerConfig.Engine.DetachKeys
}

View File

@ -15,15 +15,15 @@ func GetNetFlags() *pflag.FlagSet {
"Add a custom host-to-IP mapping (host:ip) (default [])", "Add a custom host-to-IP mapping (host:ip) (default [])",
) )
netFlags.StringSlice( netFlags.StringSlice(
"dns", getDefaultDNSServers(), "dns", containerConfig.DNSServers(),
"Set custom DNS servers", "Set custom DNS servers",
) )
netFlags.StringSlice( netFlags.StringSlice(
"dns-opt", getDefaultDNSOptions(), "dns-opt", containerConfig.DNSOptions(),
"Set custom DNS options", "Set custom DNS options",
) )
netFlags.StringSlice( netFlags.StringSlice(
"dns-search", getDefaultDNSSearches(), "dns-search", containerConfig.DNSSearches(),
"Set custom DNS search domains", "Set custom DNS search domains",
) )
netFlags.String( netFlags.String(
@ -35,7 +35,7 @@ func GetNetFlags() *pflag.FlagSet {
"Container MAC address (e.g. 92:d0:c6:0a:29:33)", "Container MAC address (e.g. 92:d0:c6:0a:29:33)",
) )
netFlags.String( netFlags.String(
"network", getDefaultNetNS(), "network", containerConfig.NetNS(),
"Connect a container to a network", "Connect a container to a network",
) )
netFlags.StringSliceP( netFlags.StringSliceP(

View File

@ -3,7 +3,6 @@ package containers
import ( import (
"os" "os"
"github.com/containers/libpod/cmd/podman/common"
"github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/domain/entities"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -39,7 +38,7 @@ func init() {
Command: attachCommand, Command: attachCommand,
}) })
flags := attachCommand.Flags() flags := attachCommand.Flags()
flags.StringVar(&attachOpts.DetachKeys, "detach-keys", common.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.StringVar(&attachOpts.DetachKeys, "detach-keys", containerConfig.DetachKeys(), "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(&attachOpts.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false") flags.BoolVar(&attachOpts.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false")
flags.BoolVar(&attachOpts.SigProxy, "sig-proxy", true, "Proxy received signals to the process") flags.BoolVar(&attachOpts.SigProxy, "sig-proxy", true, "Proxy received signals to the process")
flags.BoolVarP(&attachOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVarP(&attachOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of")

View File

@ -1,12 +1,9 @@
package containers package containers
import ( import (
"os"
"github.com/containers/common/pkg/config"
"github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/domain/entities"
"github.com/sirupsen/logrus" "github.com/containers/libpod/pkg/util"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -20,7 +17,7 @@ var (
RunE: registry.SubCommandExists, RunE: registry.SubCommandExists,
} }
defaultContainerConfig = getDefaultContainerConfig() containerConfig = util.DefaultContainerConfig()
) )
func init() { func init() {
@ -29,12 +26,3 @@ func init() {
Command: containerCmd, Command: containerCmd,
}) })
} }
func getDefaultContainerConfig() *config.Config {
defaultContainerConfig, err := config.Default()
if err != nil {
logrus.Error(err)
os.Exit(1)
}
return defaultContainerConfig
}

View File

@ -4,7 +4,6 @@ import (
"bufio" "bufio"
"os" "os"
"github.com/containers/libpod/cmd/podman/common"
"github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/domain/entities"
envLib "github.com/containers/libpod/pkg/env" envLib "github.com/containers/libpod/pkg/env"
@ -38,7 +37,7 @@ func init() {
}) })
flags := execCommand.Flags() flags := execCommand.Flags()
flags.SetInterspersed(false) flags.SetInterspersed(false)
flags.StringVar(&execOpts.DetachKeys, "detach-keys", common.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.StringVar(&execOpts.DetachKeys, "detach-keys", containerConfig.DetachKeys(), "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(&envInput, "env", "e", []string{}, "Set environment variables") flags.StringArrayVarP(&envInput, "env", "e", []string{}, "Set environment variables")
flags.StringSliceVar(&envFile, "env-file", []string{}, "Read in a file of environment variables") flags.StringSliceVar(&envFile, "env-file", []string{}, "Read in a file of environment variables")
flags.BoolVarP(&execOpts.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") flags.BoolVarP(&execOpts.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached")

View File

@ -16,7 +16,7 @@ import (
var ( var (
restartDescription = fmt.Sprintf(`Restarts one or more running containers. The container ID or name can be used. restartDescription = fmt.Sprintf(`Restarts one or more running containers. The container ID or name can be used.
A timeout before forcibly stopping can be set, but defaults to %d seconds.`, defaultContainerConfig.Engine.StopTimeout) A timeout before forcibly stopping can be set, but defaults to %d seconds.`, containerConfig.Engine.StopTimeout)
restartCommand = &cobra.Command{ restartCommand = &cobra.Command{
Use: "restart [flags] CONTAINER [CONTAINER...]", Use: "restart [flags] CONTAINER [CONTAINER...]",
@ -46,7 +46,7 @@ func init() {
flags.BoolVarP(&restartOptions.All, "all", "a", false, "Restart all non-running containers") 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.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.BoolVar(&restartOptions.Running, "running", false, "Restart only running containers when --all is used")
flags.UintVarP(&restartTimeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") flags.UintVarP(&restartTimeout, "time", "t", containerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
if registry.IsRemote() { if registry.IsRemote() {
_ = flags.MarkHidden("latest") _ = flags.MarkHidden("latest")
} }

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/containers/libpod/cmd/podman/common"
"github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/cmd/podman/utils" "github.com/containers/libpod/cmd/podman/utils"
"github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/define"
@ -38,7 +37,7 @@ func init() {
}) })
flags := startCommand.Flags() flags := startCommand.Flags()
flags.BoolVarP(&startOptions.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR") flags.BoolVarP(&startOptions.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR")
flags.StringVar(&startOptions.DetachKeys, "detach-keys", common.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.StringVar(&startOptions.DetachKeys, "detach-keys", containerConfig.DetachKeys(), "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(&startOptions.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") flags.BoolVarP(&startOptions.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached")
flags.BoolVarP(&startOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVarP(&startOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&startOptions.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)") flags.BoolVar(&startOptions.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)")

View File

@ -14,7 +14,7 @@ import (
var ( var (
stopDescription = fmt.Sprintf(`Stops one or more running containers. The container name or ID can be used. stopDescription = fmt.Sprintf(`Stops one or more running containers. The container name or ID can be used.
A timeout to forcibly stop the container can also be set but defaults to %d seconds otherwise.`, defaultContainerConfig.Engine.StopTimeout) A timeout to forcibly stop the container can also be set but defaults to %d seconds otherwise.`, containerConfig.Engine.StopTimeout)
stopCommand = &cobra.Command{ stopCommand = &cobra.Command{
Use: "stop [flags] CONTAINER [CONTAINER...]", Use: "stop [flags] CONTAINER [CONTAINER...]",
Short: "Stop one or more containers", Short: "Stop one or more containers",
@ -44,7 +44,7 @@ func init() {
flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing") 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.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.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.UintVarP(&stopTimeout, "time", "t", defaultContainerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") flags.UintVarP(&stopTimeout, "time", "t", containerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container")
if registry.IsRemote() { if registry.IsRemote() {
_ = flags.MarkHidden("latest") _ = flags.MarkHidden("latest")
@ -58,7 +58,7 @@ func stop(cmd *cobra.Command, args []string) error {
var ( var (
errs utils.OutputErrors errs utils.OutputErrors
) )
stopOptions.Timeout = defaultContainerConfig.Engine.StopTimeout stopOptions.Timeout = containerConfig.Engine.StopTimeout
if cmd.Flag("time").Changed { if cmd.Flag("time").Changed {
stopOptions.Timeout = stopTimeout stopOptions.Timeout = stopTimeout
} }

View File

@ -9,7 +9,6 @@ import (
"github.com/containers/libpod/cmd/podman/common" "github.com/containers/libpod/cmd/podman/common"
"github.com/containers/libpod/cmd/podman/parse" "github.com/containers/libpod/cmd/podman/parse"
"github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/errorhandling"
"github.com/containers/libpod/pkg/specgen" "github.com/containers/libpod/pkg/specgen"
@ -50,8 +49,8 @@ func init() {
flags.AddFlagSet(common.GetNetFlags()) flags.AddFlagSet(common.GetNetFlags())
flags.StringVar(&createOptions.CGroupParent, "cgroup-parent", "", "Set parent cgroup for the pod") flags.StringVar(&createOptions.CGroupParent, "cgroup-parent", "", "Set parent cgroup for the pod")
flags.BoolVar(&createOptions.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with") flags.BoolVar(&createOptions.Infra, "infra", true, "Create an infra container associated with the pod to share namespaces with")
flags.StringVar(&createOptions.InfraImage, "infra-image", define.DefaultInfraImage, "The image of the infra container to associate with the pod") flags.StringVar(&createOptions.InfraImage, "infra-image", containerConfig.Engine.InfraImage, "The image of the infra container to associate with the pod")
flags.StringVar(&createOptions.InfraCommand, "infra-command", define.DefaultInfraCommand, "The command to run on the infra container when the pod is started") flags.StringVar(&createOptions.InfraCommand, "infra-command", containerConfig.Engine.InfraCommand, "The command to run on the infra container when the pod is started")
flags.StringSliceVar(&labelFile, "label-file", []string{}, "Read in a line delimited file of labels") flags.StringSliceVar(&labelFile, "label-file", []string{}, "Read in a line delimited file of labels")
flags.StringSliceVarP(&labels, "label", "l", []string{}, "Set metadata on pod (default [])") flags.StringSliceVarP(&labels, "label", "l", []string{}, "Set metadata on pod (default [])")
flags.StringVarP(&createOptions.Name, "name", "n", "", "Assign a name to the pod") flags.StringVarP(&createOptions.Name, "name", "n", "", "Assign a name to the pod")

View File

@ -3,6 +3,7 @@ package pods
import ( import (
"github.com/containers/libpod/cmd/podman/registry" "github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/util"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -15,6 +16,7 @@ var (
TraverseChildren: true, TraverseChildren: true,
RunE: registry.SubCommandExists, RunE: registry.SubCommandExists,
} }
containerConfig = util.DefaultContainerConfig()
) )
func init() { func init() {

View File

@ -47,11 +47,10 @@ func init() {
flags.BoolVarP(&stopOptions.All, "all", "a", false, "Stop all running pods") flags.BoolVarP(&stopOptions.All, "all", "a", false, "Stop all running pods")
flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing") flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing")
flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Stop the latest pod podman is aware of") flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Stop the latest pod podman is aware of")
flags.UintVarP(&timeout, "time", "t", 0, "Seconds to wait for pod stop before killing the container") flags.UintVarP(&timeout, "time", "t", containerConfig.Engine.StopTimeout, "Seconds to wait for pod stop before killing the container")
if registry.IsRemote() { if registry.IsRemote() {
_ = flags.MarkHidden("latest") _ = flags.MarkHidden("latest")
_ = flags.MarkHidden("ignore") _ = flags.MarkHidden("ignore")
} }
flags.SetNormalizeFunc(utils.AliasFlags) flags.SetNormalizeFunc(utils.AliasFlags)
} }

View File

@ -40,7 +40,7 @@ func init() {
Parent: volumeCmd, Parent: volumeCmd,
}) })
flags := createCommand.Flags() flags := createCommand.Flags()
flags.StringVar(&createOpts.Driver, "driver", "", "Specify volume driver name (default local)") flags.StringVar(&createOpts.Driver, "driver", "local", "Specify volume driver name")
flags.StringSliceVarP(&opts.Label, "label", "l", []string{}, "Set metadata for a volume (default [])") flags.StringSliceVarP(&opts.Label, "label", "l", []string{}, "Set metadata for a volume (default [])")
flags.StringArrayVarP(&opts.Opts, "opt", "o", []string{}, "Set driver specific options (default [])") flags.StringArrayVarP(&opts.Opts, "opt", "o", []string{}, "Set driver specific options (default [])")
} }

View File

@ -20,11 +20,11 @@ import (
cnitypes "github.com/containernetworking/cni/pkg/types/current" cnitypes "github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/buildah/pkg/secrets" "github.com/containers/buildah/pkg/secrets"
"github.com/containers/common/pkg/apparmor"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
"github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events" "github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/pkg/annotations" "github.com/containers/libpod/pkg/annotations"
"github.com/containers/libpod/pkg/apparmor"
"github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/cgroups"
"github.com/containers/libpod/pkg/criu" "github.com/containers/libpod/pkg/criu"
"github.com/containers/libpod/pkg/lookup" "github.com/containers/libpod/pkg/lookup"

View File

@ -6,10 +6,6 @@ import (
) )
var ( var (
// DefaultInfraImage to use for infra container
DefaultInfraImage = "k8s.gcr.io/pause:3.2"
// DefaultInfraCommand to be run in an infra container
DefaultInfraCommand = "/pause"
// DefaultSHMLockPath is the default path for SHM locks // DefaultSHMLockPath is the default path for SHM locks
DefaultSHMLockPath = "/libpod_lock" DefaultSHMLockPath = "/libpod_lock"
// DefaultRootlessSHMLockPath is the default path for rootless SHM locks // DefaultRootlessSHMLockPath is the default path for rootless SHM locks

View File

@ -46,12 +46,12 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "NewFromLocal()")) utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "NewFromLocal()"))
return return
} }
defaultContainerConfig, err := runtime.GetConfig() containerConfig, err := runtime.GetConfig()
if err != nil { if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "GetConfig()")) utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "GetConfig()"))
return return
} }
cc, err := makeCreateConfig(defaultContainerConfig, input, newImage) cc, err := makeCreateConfig(containerConfig, input, newImage)
if err != nil { if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "makeCreatConfig()")) utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "makeCreatConfig()"))
return return
@ -60,7 +60,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
utils.CreateContainer(r.Context(), w, runtime, &cc) utils.CreateContainer(r.Context(), w, runtime, &cc)
} }
func makeCreateConfig(defaultContainerConfig *config.Config, input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) { func makeCreateConfig(containerConfig *config.Config, input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) {
var ( var (
err error err error
init bool init bool
@ -81,7 +81,7 @@ func makeCreateConfig(defaultContainerConfig *config.Config, input handlers.Crea
workDir = input.WorkingDir workDir = input.WorkingDir
} }
stopTimeout := defaultContainerConfig.Engine.StopTimeout stopTimeout := containerConfig.Engine.StopTimeout
if input.StopTimeout != nil { if input.StopTimeout != nil {
stopTimeout = uint(*input.StopTimeout) stopTimeout = uint(*input.StopTimeout)
} }

View File

@ -10,12 +10,12 @@ import (
"time" "time"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/sysinfo"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils" "github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/sysinfo"
docker "github.com/docker/docker/api/types" docker "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"github.com/google/uuid" "github.com/google/uuid"

View File

@ -1,19 +0,0 @@
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 = config.DefaultApparmorProfile
// DefaultLibpodProfile is the name of default libpod AppArmor profile.
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.
ErrApparmorRootless = errors.New("AppArmor is not supported in rootless mode")
)

View File

@ -1,289 +0,0 @@
// +build linux,apparmor
package apparmor
import (
"bufio"
"bytes"
"fmt"
"io"
"os"
"os/exec"
"path"
"strconv"
"strings"
"text/template"
"github.com/containers/libpod/pkg/rootless"
runcaa "github.com/opencontainers/runc/libcontainer/apparmor"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
// profileDirectory is the file store for apparmor profiles and macros.
var profileDirectory = "/etc/apparmor.d"
// IsEnabled returns true if AppArmor is enabled on the host.
func IsEnabled() bool {
if rootless.IsRootless() {
return false
}
return runcaa.IsEnabled()
}
// profileData holds information about the given profile for generation.
type profileData struct {
// Name is profile name.
Name string
// Imports defines the apparmor functions to import, before defining the profile.
Imports []string
// InnerImports defines the apparmor functions to import in the profile.
InnerImports []string
// Version is the {major, minor, patch} version of apparmor_parser as a single number.
Version int
}
// generateDefault creates an apparmor profile from ProfileData.
func (p *profileData) generateDefault(out io.Writer) error {
compiled, err := template.New("apparmor_profile").Parse(libpodProfileTemplate)
if err != nil {
return err
}
if macroExists("tunables/global") {
p.Imports = append(p.Imports, "#include <tunables/global>")
} else {
p.Imports = append(p.Imports, "@{PROC}=/proc/")
}
if macroExists("abstractions/base") {
p.InnerImports = append(p.InnerImports, "#include <abstractions/base>")
}
ver, err := getAAParserVersion()
if err != nil {
return err
}
p.Version = ver
return compiled.Execute(out, p)
}
// macrosExists checks if the passed macro exists.
func macroExists(m string) bool {
_, err := os.Stat(path.Join(profileDirectory, m))
return err == nil
}
// InstallDefault generates a default profile and loads it into the kernel
// using 'apparmor_parser'.
func InstallDefault(name string) error {
if rootless.IsRootless() {
return ErrApparmorRootless
}
p := profileData{
Name: name,
}
cmd := exec.Command("apparmor_parser", "-Kr")
pipe, err := cmd.StdinPipe()
if err != nil {
return err
}
if err := cmd.Start(); err != nil {
if pipeErr := pipe.Close(); pipeErr != nil {
logrus.Errorf("unable to close apparmor pipe: %q", pipeErr)
}
return err
}
if err := p.generateDefault(pipe); err != nil {
if pipeErr := pipe.Close(); pipeErr != nil {
logrus.Errorf("unable to close apparmor pipe: %q", pipeErr)
}
if cmdErr := cmd.Wait(); cmdErr != nil {
logrus.Errorf("unable to wait for apparmor command: %q", cmdErr)
}
return err
}
if pipeErr := pipe.Close(); pipeErr != nil {
logrus.Errorf("unable to close apparmor pipe: %q", pipeErr)
}
return cmd.Wait()
}
// DefaultContent returns the default profile content as byte slice. The
// profile is named as the provided `name`. The function errors if the profile
// generation fails.
func DefaultContent(name string) ([]byte, error) {
p := profileData{Name: name}
var bytes bytes.Buffer
if err := p.generateDefault(&bytes); err != nil {
return nil, err
}
return bytes.Bytes(), nil
}
// IsLoaded checks if a profile with the given name has been loaded into the
// kernel.
func IsLoaded(name string) (bool, error) {
if name != "" && rootless.IsRootless() {
return false, errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
}
file, err := os.Open("/sys/kernel/security/apparmor/profiles")
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
defer file.Close()
r := bufio.NewReader(file)
for {
p, err := r.ReadString('\n')
if err == io.EOF {
break
}
if err != nil {
return false, err
}
if strings.HasPrefix(p, name+" ") {
return true, nil
}
}
return false, nil
}
// execAAParser runs `apparmor_parser` with the passed arguments.
func execAAParser(dir string, args ...string) (string, error) {
c := exec.Command("apparmor_parser", args...)
c.Dir = dir
output, err := c.CombinedOutput()
if err != nil {
return "", fmt.Errorf("running `%s %s` failed with output: %s\nerror: %v", c.Path, strings.Join(c.Args, " "), output, err)
}
return string(output), nil
}
// getAAParserVersion returns the major and minor version of apparmor_parser.
func getAAParserVersion() (int, error) {
output, err := execAAParser("", "--version")
if err != nil {
return -1, err
}
return parseAAParserVersion(output)
}
// parseAAParserVersion parses the given `apparmor_parser --version` output and
// returns the major and minor version number as an integer.
func parseAAParserVersion(output string) (int, error) {
// output is in the form of the following:
// AppArmor parser version 2.9.1
// Copyright (C) 1999-2008 Novell Inc.
// Copyright 2009-2012 Canonical Ltd.
lines := strings.SplitN(output, "\n", 2)
words := strings.Split(lines[0], " ")
version := words[len(words)-1]
// split by major minor version
v := strings.Split(version, ".")
if len(v) == 0 || len(v) > 3 {
return -1, fmt.Errorf("parsing version failed for output: `%s`", output)
}
// Default the versions to 0.
var majorVersion, minorVersion, patchLevel int
majorVersion, err := strconv.Atoi(v[0])
if err != nil {
return -1, err
}
if len(v) > 1 {
minorVersion, err = strconv.Atoi(v[1])
if err != nil {
return -1, err
}
}
if len(v) > 2 {
patchLevel, err = strconv.Atoi(v[2])
if err != nil {
return -1, err
}
}
// major*10^5 + minor*10^3 + patch*10^0
numericVersion := majorVersion*1e5 + minorVersion*1e3 + patchLevel
return numericVersion, nil
}
// CheckProfileAndLoadDefault checks if the specified profile is loaded and
// loads the DefaultLibpodProfile if the specified on is prefixed by
// DefaultLipodProfilePrefix. This allows to always load and apply the latest
// default AppArmor profile. Note that AppArmor requires root. If it's a
// default profile, return DefaultLipodProfilePrefix, otherwise the specified
// one.
func CheckProfileAndLoadDefault(name string) (string, error) {
if name == "unconfined" {
return name, nil
}
// AppArmor is not supported in rootless mode as it requires root
// privileges. Return an error in case a specific profile is specified.
if rootless.IsRootless() {
if name != "" {
return "", errors.Wrapf(ErrApparmorRootless, "cannot load AppArmor profile %q", name)
} else {
logrus.Debug("skipping loading default AppArmor profile (rootless mode)")
return "", nil
}
}
// Check if AppArmor is disabled and error out if a profile is to be set.
if !runcaa.IsEnabled() {
if name == "" {
return "", nil
} else {
return "", fmt.Errorf("profile %q specified but AppArmor is disabled on the host", name)
}
}
// If the specified name is not empty or is not a default libpod one,
// ignore it and return the name.
if name != "" && !strings.HasPrefix(name, DefaultLipodProfilePrefix) {
isLoaded, err := IsLoaded(name)
if err != nil {
return "", err
}
if !isLoaded {
return "", fmt.Errorf("AppArmor profile %q specified but not loaded", name)
}
return name, nil
}
name = DefaultLibpodProfile
// To avoid expensive redundant loads on each invocation, check
// if it's loaded before installing it.
isLoaded, err := IsLoaded(name)
if err != nil {
return "", err
}
if !isLoaded {
err = InstallDefault(name)
if err != nil {
return "", err
}
logrus.Infof("successfully loaded AppAmor profile %q", name)
} else {
logrus.Infof("AppAmor profile %q is already loaded", name)
}
return name, nil
}

View File

@ -1,49 +0,0 @@
// +build linux,apparmor
package apparmor
const libpodProfileTemplate = `
{{range $value := .Imports}}
{{$value}}
{{end}}
profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
{{range $value := .InnerImports}}
{{$value}}
{{end}}
network,
capability,
file,
umount,
{{if ge .Version 208096}}
# Allow signals from privileged profiles and from within the same profile
signal (receive) peer=unconfined,
signal (send,receive) peer={{.Name}},
{{end}}
deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir)
# deny write to files not in /proc/<number>/** or /proc/sys/**
deny @{PROC}/{[^1-9],[^1-9][^0-9],[^1-9s][^0-9y][^0-9s],[^1-9][^0-9][^0-9][^0-9]*}/** w,
deny @{PROC}/sys/[^k]** w, # deny /proc/sys except /proc/sys/k* (effectively /proc/sys/kernel)
deny @{PROC}/sys/kernel/{?,??,[^s][^h][^m]**} w, # deny everything except shm* in /proc/sys/kernel/
deny @{PROC}/sysrq-trigger rwklx,
deny @{PROC}/kcore rwklx,
deny mount,
deny /sys/[^f]*/** wklx,
deny /sys/f[^s]*/** wklx,
deny /sys/fs/[^c]*/** wklx,
deny /sys/fs/c[^g]*/** wklx,
deny /sys/fs/cg[^r]*/** wklx,
deny /sys/firmware/** rwklx,
deny /sys/kernel/security/** rwklx,
{{if ge .Version 208095}}
# suppress ptrace denials when using using 'ps' inside a container
ptrace (trace,read) peer={{.Name}},
{{end}}
}
`

View File

@ -1,140 +0,0 @@
// +build linux,apparmor
package apparmor
import (
"os"
"testing"
)
type versionExpected struct {
output string
version int
}
func TestParseAAParserVersion(t *testing.T) {
if !IsEnabled() {
t.Skip("AppArmor disabled: skipping tests")
}
versions := []versionExpected{
{
output: `AppArmor parser version 2.10
Copyright (C) 1999-2008 Novell Inc.
Copyright 2009-2012 Canonical Ltd.
`,
version: 210000,
},
{
output: `AppArmor parser version 2.8
Copyright (C) 1999-2008 Novell Inc.
Copyright 2009-2012 Canonical Ltd.
`,
version: 208000,
},
{
output: `AppArmor parser version 2.20
Copyright (C) 1999-2008 Novell Inc.
Copyright 2009-2012 Canonical Ltd.
`,
version: 220000,
},
{
output: `AppArmor parser version 2.05
Copyright (C) 1999-2008 Novell Inc.
Copyright 2009-2012 Canonical Ltd.
`,
version: 205000,
},
{
output: `AppArmor parser version 2.9.95
Copyright (C) 1999-2008 Novell Inc.
Copyright 2009-2012 Canonical Ltd.
`,
version: 209095,
},
{
output: `AppArmor parser version 3.14.159
Copyright (C) 1999-2008 Novell Inc.
Copyright 2009-2012 Canonical Ltd.
`,
version: 314159,
},
}
for _, v := range versions {
version, err := parseAAParserVersion(v.output)
if err != nil {
t.Fatalf("expected error to be nil for %#v, got: %v", v, err)
}
if version != v.version {
t.Fatalf("expected version to be %d, was %d, for: %#v\n", v.version, version, v)
}
}
}
const (
aapath = "/sys/kernel/security/apparmor/"
profile = "libpod-default-testing"
)
func TestInstallDefault(t *testing.T) {
if _, err := os.Stat(aapath); err != nil {
t.Skip("AppArmor isn't available in this environment")
}
// removes `profile`
removeProfile := func() error {
path := aapath + ".remove"
f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(profile)
return err
}
// makes sure `profile` is loaded according to `state`
checkLoaded := func(state bool) {
loaded, err := IsLoaded(profile)
if err != nil {
t.Fatalf("Error searching AppArmor profile '%s': %v", profile, err)
}
if state != loaded {
if state {
t.Fatalf("AppArmor profile '%s' isn't loaded but should", profile)
} else {
t.Fatalf("AppArmor profile '%s' is loaded but shouldn't", profile)
}
}
}
// test installing the profile
if err := InstallDefault(profile); err != nil {
t.Fatalf("Couldn't install AppArmor profile '%s': %v", profile, err)
}
checkLoaded(true)
// remove the profile and check again
if err := removeProfile(); err != nil {
t.Fatalf("Couldn't remove AppArmor profile '%s': %v", profile, err)
}
checkLoaded(false)
}
func TestDefaultContent(t *testing.T) {
if _, err := os.Stat(aapath); err != nil {
t.Skip("AppArmor isn't available in this environment")
}
if _, err := DefaultContent(profile); err != nil {
t.Fatalf("Couldn't retrieve default AppArmor profile content '%s': %v", profile, err)
}
}

View File

@ -1,31 +0,0 @@
// +build !linux !apparmor
package apparmor
// IsEnabled dummy.
func IsEnabled() bool {
return false
}
// InstallDefault dummy.
func InstallDefault(name string) error {
return ErrApparmorUnsupported
}
// IsLoaded dummy.
func IsLoaded(name string) (bool, error) {
return false, ErrApparmorUnsupported
}
// CheckProfileAndLoadDefault dummy.
func CheckProfileAndLoadDefault(name string) (string, error) {
if name == "" {
return "", nil
}
return "", ErrApparmorUnsupported
}
// DefaultContent dummy.
func DefaultContent(name string) ([]byte, error) {
return nil, nil
}

View File

@ -5,11 +5,11 @@ import (
"github.com/containers/common/pkg/capabilities" "github.com/containers/common/pkg/capabilities"
cconfig "github.com/containers/common/pkg/config" cconfig "github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/sysinfo"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/cgroups"
"github.com/containers/libpod/pkg/env" "github.com/containers/libpod/pkg/env"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/sysinfo"
"github.com/containers/libpod/pkg/util" "github.com/containers/libpod/pkg/util"
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/opencontainers/runc/libcontainer/user" "github.com/opencontainers/runc/libcontainer/user"

View File

@ -4,9 +4,9 @@ import (
"runtime" "runtime"
"testing" "testing"
"github.com/containers/common/pkg/sysinfo"
"github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/cgroups"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/sysinfo"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/idtools"
"github.com/docker/go-units" "github.com/docker/go-units"

View File

@ -1,14 +1,16 @@
package specgen package specgen
import ( import (
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
var ( var (
// ErrInvalidPodSpecConfig describes an error given when the podspecgenerator is invalid // ErrInvalidPodSpecConfig describes an error given when the podspecgenerator is invalid
ErrInvalidPodSpecConfig error = errors.New("invalid pod spec") ErrInvalidPodSpecConfig error = errors.New("invalid pod spec")
// containerConfig has the default configurations defined in containers.conf
containerConfig = util.DefaultContainerConfig()
) )
func exclusivePodOptions(opt1, opt2 string) error { func exclusivePodOptions(opt1, opt2 string) error {
@ -96,10 +98,10 @@ func (p *PodSpecGenerator) Validate() error {
} }
} }
if len(p.InfraImage) < 1 { if len(p.InfraImage) < 1 {
p.InfraImage = define.DefaultInfraImage p.InfraImage = containerConfig.Engine.InfraImage
} }
if len(p.InfraCommand) < 1 { if len(p.InfraCommand) < 1 {
p.InfraCommand = []string{define.DefaultInfraCommand} p.InfraCommand = []string{containerConfig.Engine.InfraCommand}
} }
return nil return nil
} }

View File

@ -1 +0,0 @@
SysInfo stores information about which features a kernel supports.

View File

@ -1,12 +0,0 @@
// +build !linux,!windows
package sysinfo
import (
"runtime"
)
// NumCPU returns the number of CPUs
func NumCPU() int {
return runtime.NumCPU()
}

View File

@ -1,44 +0,0 @@
// +build linux
package sysinfo
import (
"runtime"
"unsafe"
"golang.org/x/sys/unix"
)
// numCPU queries the system for the count of threads available
// for use to this process.
//
// Issues two syscalls.
// Returns 0 on errors. Use |runtime.NumCPU| in that case.
func numCPU() int {
// Gets the affinity mask for a process: The very one invoking this function.
pid, _, _ := unix.RawSyscall(unix.SYS_GETPID, 0, 0, 0)
var mask [1024 / 64]uintptr
_, _, err := unix.RawSyscall(unix.SYS_SCHED_GETAFFINITY, pid, uintptr(len(mask)*8), uintptr(unsafe.Pointer(&mask[0])))
if err != 0 {
return 0
}
// For every available thread a bit is set in the mask.
ncpu := 0
for _, e := range mask {
if e == 0 {
continue
}
ncpu += int(popcnt(uint64(e)))
}
return ncpu
}
// NumCPU returns the number of CPUs which are currently online
func NumCPU() int {
if ncpu := numCPU(); ncpu > 0 {
return ncpu
}
return runtime.NumCPU()
}

View File

@ -1,37 +0,0 @@
// +build windows
package sysinfo
import (
"runtime"
"unsafe"
"golang.org/x/sys/windows"
)
var (
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
getCurrentProcess = kernel32.NewProc("GetCurrentProcess")
getProcessAffinityMask = kernel32.NewProc("GetProcessAffinityMask")
)
func numCPU() int {
// Gets the affinity mask for a process
var mask, sysmask uintptr
currentProcess, _, _ := getCurrentProcess.Call()
ret, _, _ := getProcessAffinityMask.Call(currentProcess, uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
if ret == 0 {
return 0
}
// For every available thread a bit is set in the mask.
ncpu := int(popcnt(uint64(mask)))
return ncpu
}
// NumCPU returns the number of CPUs which are currently online
func NumCPU() int {
if ncpu := numCPU(); ncpu > 0 {
return ncpu
}
return runtime.NumCPU()
}

View File

@ -1,153 +0,0 @@
package sysinfo
import "github.com/docker/docker/pkg/parsers"
// SysInfo stores information about which features a kernel supports.
// TODO Windows: Factor out platform specific capabilities.
type SysInfo struct {
// Whether the kernel supports AppArmor or not
AppArmor bool
// Whether the kernel supports Seccomp or not
Seccomp bool
cgroupMemInfo
cgroupCPUInfo
cgroupBlkioInfo
cgroupCpusetInfo
cgroupPids
// Whether IPv4 forwarding is supported or not, if this was disabled, networking will not work
IPv4ForwardingDisabled bool
// Whether bridge-nf-call-iptables is supported or not
BridgeNFCallIPTablesDisabled bool
// Whether bridge-nf-call-ip6tables is supported or not
BridgeNFCallIP6TablesDisabled bool
// Whether the cgroup has the mountpoint of "devices" or not
CgroupDevicesEnabled bool
}
type cgroupMemInfo struct {
// Whether memory limit is supported or not
MemoryLimit bool
// Whether swap limit is supported or not
SwapLimit bool
// Whether soft limit is supported or not
MemoryReservation bool
// Whether OOM killer disable is supported or not
OomKillDisable bool
// Whether memory swappiness is supported or not
MemorySwappiness bool
// Whether kernel memory limit is supported or not
KernelMemory bool
}
type cgroupCPUInfo struct {
// Whether CPU shares is supported or not
CPUShares bool
// Whether CPU CFS(Completely Fair Scheduler) period is supported or not
CPUCfsPeriod bool
// Whether CPU CFS(Completely Fair Scheduler) quota is supported or not
CPUCfsQuota bool
// Whether CPU real-time period is supported or not
CPURealtimePeriod bool
// Whether CPU real-time runtime is supported or not
CPURealtimeRuntime bool
}
type cgroupBlkioInfo struct {
// Whether Block IO weight is supported or not
BlkioWeight bool
// Whether Block IO weight_device is supported or not
BlkioWeightDevice bool
// Whether Block IO read limit in bytes per second is supported or not
BlkioReadBpsDevice bool
// Whether Block IO write limit in bytes per second is supported or not
BlkioWriteBpsDevice bool
// Whether Block IO read limit in IO per second is supported or not
BlkioReadIOpsDevice bool
// Whether Block IO write limit in IO per second is supported or not
BlkioWriteIOpsDevice bool
}
type cgroupCpusetInfo struct {
// Whether Cpuset is supported or not
Cpuset bool
// Available Cpuset's cpus
Cpus string
// Available Cpuset's memory nodes
Mems string
}
type cgroupPids struct {
// Whether Pids Limit is supported or not
PidsLimit bool
}
// IsCpusetCpusAvailable returns `true` if the provided string set is contained
// in cgroup's cpuset.cpus set, `false` otherwise.
// If error is not nil a parsing error occurred.
func (c cgroupCpusetInfo) IsCpusetCpusAvailable(provided string) (bool, error) {
return isCpusetListAvailable(provided, c.Cpus)
}
// IsCpusetMemsAvailable returns `true` if the provided string set is contained
// in cgroup's cpuset.mems set, `false` otherwise.
// If error is not nil a parsing error occurred.
func (c cgroupCpusetInfo) IsCpusetMemsAvailable(provided string) (bool, error) {
return isCpusetListAvailable(provided, c.Mems)
}
func isCpusetListAvailable(provided, available string) (bool, error) {
parsedProvided, err := parsers.ParseUintList(provided)
if err != nil {
return false, err
}
parsedAvailable, err := parsers.ParseUintList(available)
if err != nil {
return false, err
}
for k := range parsedProvided {
if !parsedAvailable[k] {
return false, nil
}
}
return true, nil
}
// Returns bit count of 1, used by NumCPU
func popcnt(x uint64) (n byte) {
x -= (x >> 1) & 0x5555555555555555
x = (x>>2)&0x3333333333333333 + x&0x3333333333333333
x += x >> 4
x &= 0x0f0f0f0f0f0f0f0f
x *= 0x0101010101010101
return byte(x >> 56)
}
// GetDefaultPidsLimit returns the default pids limit to run containers with
func GetDefaultPidsLimit() int64 {
sysInfo := New(true)
if !sysInfo.PidsLimit {
return 0
}
return 4096
}

View File

@ -1,261 +0,0 @@
package sysinfo
import (
"fmt"
"io/ioutil"
"os"
"path"
"strings"
cg "github.com/containers/libpod/pkg/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
func findCgroupMountpoints() (map[string]string, error) {
cgMounts, err := cgroups.GetCgroupMounts(false)
if err != nil {
return nil, fmt.Errorf("failed to parse cgroup information: %v", err)
}
mps := make(map[string]string)
for _, m := range cgMounts {
for _, ss := range m.Subsystems {
mps[ss] = m.Mountpoint
}
}
return mps, nil
}
// New returns a new SysInfo, using the filesystem to detect which features
// the kernel supports. If `quiet` is `false` warnings are printed in logs
// whenever an error occurs or misconfigurations are present.
func New(quiet bool) *SysInfo {
sysInfo := &SysInfo{}
cgMounts, err := findCgroupMountpoints()
if err != nil {
logrus.Warnf("Failed to parse cgroup information: %v", err)
} else {
sysInfo.cgroupMemInfo = checkCgroupMem(cgMounts, quiet)
sysInfo.cgroupCPUInfo = checkCgroupCPU(cgMounts, quiet)
sysInfo.cgroupBlkioInfo = checkCgroupBlkioInfo(cgMounts, quiet)
sysInfo.cgroupCpusetInfo = checkCgroupCpusetInfo(cgMounts, quiet)
sysInfo.cgroupPids = checkCgroupPids(quiet)
}
_, ok := cgMounts["devices"]
sysInfo.CgroupDevicesEnabled = ok
sysInfo.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward")
sysInfo.BridgeNFCallIPTablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables")
sysInfo.BridgeNFCallIP6TablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables")
// Check if AppArmor is supported.
if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) {
sysInfo.AppArmor = true
}
// Check if Seccomp is supported, via CONFIG_SECCOMP.
if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL {
// Make sure the kernel has CONFIG_SECCOMP_FILTER.
if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL {
sysInfo.Seccomp = true
}
}
return sysInfo
}
// checkCgroupMem reads the memory information from the memory cgroup mount point.
func checkCgroupMem(cgMounts map[string]string, quiet bool) cgroupMemInfo {
mountPoint, ok := cgMounts["memory"]
if !ok {
if !quiet {
logrus.Warn("Your kernel does not support cgroup memory limit")
}
return cgroupMemInfo{}
}
swapLimit := cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes")
if !quiet && !swapLimit {
logrus.Warn("Your kernel does not support swap memory limit")
}
memoryReservation := cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes")
if !quiet && !memoryReservation {
logrus.Warn("Your kernel does not support memory reservation")
}
oomKillDisable := cgroupEnabled(mountPoint, "memory.oom_control")
if !quiet && !oomKillDisable {
logrus.Warn("Your kernel does not support oom control")
}
memorySwappiness := cgroupEnabled(mountPoint, "memory.swappiness")
if !quiet && !memorySwappiness {
logrus.Warn("Your kernel does not support memory swappiness")
}
kernelMemory := cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes")
if !quiet && !kernelMemory {
logrus.Warn("Your kernel does not support kernel memory limit")
}
return cgroupMemInfo{
MemoryLimit: true,
SwapLimit: swapLimit,
MemoryReservation: memoryReservation,
OomKillDisable: oomKillDisable,
MemorySwappiness: memorySwappiness,
KernelMemory: kernelMemory,
}
}
// checkCgroupCPU reads the cpu information from the cpu cgroup mount point.
func checkCgroupCPU(cgMounts map[string]string, quiet bool) cgroupCPUInfo {
mountPoint, ok := cgMounts["cpu"]
if !ok {
if !quiet {
logrus.Warn("Unable to find cpu cgroup in mounts")
}
return cgroupCPUInfo{}
}
cpuShares := cgroupEnabled(mountPoint, "cpu.shares")
if !quiet && !cpuShares {
logrus.Warn("Your kernel does not support cgroup cpu shares")
}
cpuCfsPeriod := cgroupEnabled(mountPoint, "cpu.cfs_period_us")
if !quiet && !cpuCfsPeriod {
logrus.Warn("Your kernel does not support cgroup cfs period")
}
cpuCfsQuota := cgroupEnabled(mountPoint, "cpu.cfs_quota_us")
if !quiet && !cpuCfsQuota {
logrus.Warn("Your kernel does not support cgroup cfs quotas")
}
cpuRealtimePeriod := cgroupEnabled(mountPoint, "cpu.rt_period_us")
if !quiet && !cpuRealtimePeriod {
logrus.Warn("Your kernel does not support cgroup rt period")
}
cpuRealtimeRuntime := cgroupEnabled(mountPoint, "cpu.rt_runtime_us")
if !quiet && !cpuRealtimeRuntime {
logrus.Warn("Your kernel does not support cgroup rt runtime")
}
return cgroupCPUInfo{
CPUShares: cpuShares,
CPUCfsPeriod: cpuCfsPeriod,
CPUCfsQuota: cpuCfsQuota,
CPURealtimePeriod: cpuRealtimePeriod,
CPURealtimeRuntime: cpuRealtimeRuntime,
}
}
// checkCgroupBlkioInfo reads the blkio information from the blkio cgroup mount point.
func checkCgroupBlkioInfo(cgMounts map[string]string, quiet bool) cgroupBlkioInfo {
mountPoint, ok := cgMounts["blkio"]
if !ok {
if !quiet {
logrus.Warn("Unable to find blkio cgroup in mounts")
}
return cgroupBlkioInfo{}
}
weight := cgroupEnabled(mountPoint, "blkio.weight")
if !quiet && !weight {
logrus.Warn("Your kernel does not support cgroup blkio weight")
}
weightDevice := cgroupEnabled(mountPoint, "blkio.weight_device")
if !quiet && !weightDevice {
logrus.Warn("Your kernel does not support cgroup blkio weight_device")
}
readBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_bps_device")
if !quiet && !readBpsDevice {
logrus.Warn("Your kernel does not support cgroup blkio throttle.read_bps_device")
}
writeBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_bps_device")
if !quiet && !writeBpsDevice {
logrus.Warn("Your kernel does not support cgroup blkio throttle.write_bps_device")
}
readIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_iops_device")
if !quiet && !readIOpsDevice {
logrus.Warn("Your kernel does not support cgroup blkio throttle.read_iops_device")
}
writeIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_iops_device")
if !quiet && !writeIOpsDevice {
logrus.Warn("Your kernel does not support cgroup blkio throttle.write_iops_device")
}
return cgroupBlkioInfo{
BlkioWeight: weight,
BlkioWeightDevice: weightDevice,
BlkioReadBpsDevice: readBpsDevice,
BlkioWriteBpsDevice: writeBpsDevice,
BlkioReadIOpsDevice: readIOpsDevice,
BlkioWriteIOpsDevice: writeIOpsDevice,
}
}
// checkCgroupCpusetInfo reads the cpuset information from the cpuset cgroup mount point.
func checkCgroupCpusetInfo(cgMounts map[string]string, quiet bool) cgroupCpusetInfo {
mountPoint, ok := cgMounts["cpuset"]
if !ok {
if !quiet {
logrus.Warn("Unable to find cpuset cgroup in mounts")
}
return cgroupCpusetInfo{}
}
cpus, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.cpus"))
if err != nil {
return cgroupCpusetInfo{}
}
mems, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.mems"))
if err != nil {
return cgroupCpusetInfo{}
}
return cgroupCpusetInfo{
Cpuset: true,
Cpus: strings.TrimSpace(string(cpus)),
Mems: strings.TrimSpace(string(mems)),
}
}
// checkCgroupPids reads the pids information from the pids cgroup mount point.
func checkCgroupPids(quiet bool) cgroupPids {
cgroup2, err := cg.IsCgroup2UnifiedMode()
if err != nil {
logrus.Errorf("Failed to check cgroups version: %v", err)
}
if !cgroup2 {
_, err := cgroups.FindCgroupMountpoint("", "pids")
if err != nil {
if !quiet {
logrus.Warn(err)
}
return cgroupPids{}
}
}
return cgroupPids{
PidsLimit: true,
}
}
func cgroupEnabled(mountPoint, name string) bool {
_, err := os.Stat(path.Join(mountPoint, name))
return err == nil
}
func readProcBool(path string) bool {
val, err := ioutil.ReadFile(path)
if err != nil {
return false
}
return strings.TrimSpace(string(val)) == "1"
}

View File

@ -1,104 +0,0 @@
package sysinfo
import (
"io/ioutil"
"os"
"path"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"golang.org/x/sys/unix"
)
func TestReadProcBool(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "test-sysinfo-proc")
require.NoError(t, err)
defer os.RemoveAll(tmpDir)
procFile := filepath.Join(tmpDir, "read-proc-bool")
err = ioutil.WriteFile(procFile, []byte("1"), 0644)
require.NoError(t, err)
if !readProcBool(procFile) {
t.Fatal("expected proc bool to be true, got false")
}
if err := ioutil.WriteFile(procFile, []byte("0"), 0644); err != nil {
t.Fatal(err)
}
if readProcBool(procFile) {
t.Fatal("expected proc bool to be false, got true")
}
if readProcBool(path.Join(tmpDir, "no-exist")) {
t.Fatal("should be false for non-existent entry")
}
}
func TestCgroupEnabled(t *testing.T) {
cgroupDir, err := ioutil.TempDir("", "cgroup-test")
require.NoError(t, err)
defer os.RemoveAll(cgroupDir)
if cgroupEnabled(cgroupDir, "test") {
t.Fatal("cgroupEnabled should be false")
}
err = ioutil.WriteFile(path.Join(cgroupDir, "test"), []byte{}, 0644)
require.NoError(t, err)
if !cgroupEnabled(cgroupDir, "test") {
t.Fatal("cgroupEnabled should be true")
}
}
func TestNew(t *testing.T) {
sysInfo := New(false)
require.NotNil(t, sysInfo)
checkSysInfo(t, sysInfo)
sysInfo = New(true)
require.NotNil(t, sysInfo)
checkSysInfo(t, sysInfo)
}
func checkSysInfo(t *testing.T, sysInfo *SysInfo) {
// Check if Seccomp is supported, via CONFIG_SECCOMP.then sysInfo.Seccomp must be TRUE , else FALSE
if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL {
// Make sure the kernel has CONFIG_SECCOMP_FILTER.
if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL {
require.True(t, sysInfo.Seccomp)
}
} else {
require.False(t, sysInfo.Seccomp)
}
}
func TestNewAppArmorEnabled(t *testing.T) {
// Check if AppArmor is supported. then it must be TRUE , else FALSE
if _, err := os.Stat("/sys/kernel/security/apparmor"); err != nil {
t.Skip("App Armor Must be Enabled")
}
sysInfo := New(true)
require.True(t, sysInfo.AppArmor)
}
func TestNewAppArmorDisabled(t *testing.T) {
// Check if AppArmor is supported. then it must be TRUE , else FALSE
if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) {
t.Skip("App Armor Must be Disabled")
}
sysInfo := New(true)
require.False(t, sysInfo.AppArmor)
}
func TestNumCPU(t *testing.T) {
cpuNumbers := NumCPU()
if cpuNumbers <= 0 {
t.Fatal("CPU returned must be greater than zero")
}
}

View File

@ -1,122 +0,0 @@
// +build solaris,cgo
package sysinfo
import (
"bytes"
"os/exec"
"strconv"
"strings"
)
/*
#cgo LDFLAGS: -llgrp
#cgo CFLAGS: -Wall -Werror
#include <unistd.h>
#include <stdlib.h>
#include <sys/lgrp_user.h>
int getLgrpCount() {
lgrp_cookie_t lgrpcookie = LGRP_COOKIE_NONE;
uint_t nlgrps;
if ((lgrpcookie = lgrp_init(LGRP_VIEW_OS)) == LGRP_COOKIE_NONE) {
return -1;
}
nlgrps = lgrp_nlgrps(lgrpcookie);
return nlgrps;
}
*/
import "C"
// IsCPUSharesAvailable returns whether CPUShares setting is supported.
// We need FSS to be set as default scheduling class to support CPU Shares
func IsCPUSharesAvailable() bool {
cmd := exec.Command("/usr/sbin/dispadmin", "-d")
outBuf := new(bytes.Buffer)
errBuf := new(bytes.Buffer)
cmd.Stderr = errBuf
cmd.Stdout = outBuf
if err := cmd.Run(); err != nil {
return false
}
return (strings.Contains(outBuf.String(), "FSS"))
}
// New returns a new SysInfo, using the filesystem to detect which features
// the kernel supports.
//NOTE Solaris: If we change the below capabilities be sure
// to update verifyPlatformContainerSettings() in daemon_solaris.go
func New(quiet bool) *SysInfo {
sysInfo := &SysInfo{}
sysInfo.cgroupMemInfo = setCgroupMem(quiet)
sysInfo.cgroupCPUInfo = setCgroupCPU(quiet)
sysInfo.cgroupBlkioInfo = setCgroupBlkioInfo(quiet)
sysInfo.cgroupCpusetInfo = setCgroupCPUsetInfo(quiet)
sysInfo.IPv4ForwardingDisabled = false
sysInfo.AppArmor = false
return sysInfo
}
// setCgroupMem reads the memory information for Solaris.
func setCgroupMem(quiet bool) cgroupMemInfo {
return cgroupMemInfo{
MemoryLimit: true,
SwapLimit: true,
MemoryReservation: false,
OomKillDisable: false,
MemorySwappiness: false,
KernelMemory: false,
}
}
// setCgroupCPU reads the cpu information for Solaris.
func setCgroupCPU(quiet bool) cgroupCPUInfo {
return cgroupCPUInfo{
CPUShares: true,
CPUCfsPeriod: false,
CPUCfsQuota: true,
CPURealtimePeriod: false,
CPURealtimeRuntime: false,
}
}
// blkio switches are not supported in Solaris.
func setCgroupBlkioInfo(quiet bool) cgroupBlkioInfo {
return cgroupBlkioInfo{
BlkioWeight: false,
BlkioWeightDevice: false,
}
}
// setCgroupCPUsetInfo reads the cpuset information for Solaris.
func setCgroupCPUsetInfo(quiet bool) cgroupCpusetInfo {
return cgroupCpusetInfo{
Cpuset: true,
Cpus: getCPUCount(),
Mems: getLgrpCount(),
}
}
func getCPUCount() string {
ncpus := C.sysconf(C._SC_NPROCESSORS_ONLN)
if ncpus <= 0 {
return ""
}
return strconv.FormatInt(int64(ncpus), 16)
}
func getLgrpCount() string {
nlgrps := C.getLgrpCount()
if nlgrps <= 0 {
return ""
}
return strconv.FormatInt(int64(nlgrps), 16)
}

View File

@ -1,26 +0,0 @@
package sysinfo
import "testing"
func TestIsCpusetListAvailable(t *testing.T) {
cases := []struct {
provided string
available string
res bool
err bool
}{
{"1", "0-4", true, false},
{"01,3", "0-4", true, false},
{"", "0-7", true, false},
{"1--42", "0-7", false, true},
{"1-42", "00-1,8,,9", false, true},
{"1,41-42", "43,45", false, false},
{"0-3", "", false, false},
}
for _, c := range cases {
r, err := isCpusetListAvailable(c.provided, c.available)
if (c.err && err == nil) && r != c.res {
t.Fatalf("Expected pair: %v, %v for %s, %s. Got %v, %v instead", c.res, c.err, c.provided, c.available, c.err && err == nil, r)
}
}
}

View File

@ -1,9 +0,0 @@
// +build !linux,!solaris,!windows
package sysinfo
// New returns an empty SysInfo for non linux nor solaris for now.
func New(quiet bool) *SysInfo {
sysInfo := &SysInfo{}
return sysInfo
}

View File

@ -1,9 +0,0 @@
// +build windows
package sysinfo
// New returns an empty SysInfo for windows for now.
func New(quiet bool) *SysInfo {
sysInfo := &SysInfo{}
return sysInfo
}

View File

@ -13,6 +13,7 @@ import (
"time" "time"
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/types" "github.com/containers/image/v5/types"
"github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/errorhandling"
"github.com/containers/libpod/pkg/namespaces" "github.com/containers/libpod/pkg/namespaces"
@ -27,6 +28,17 @@ import (
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
) )
var containerConfig *config.Config
func init() {
var err error
containerConfig, err = config.Default()
if err != nil {
logrus.Error(err)
os.Exit(1)
}
}
// Helper function to determine the username/password passed // Helper function to determine the username/password passed
// in the creds string. It could be either or both. // in the creds string. It could be either or both.
func parseCreds(creds string) (string, string) { func parseCreds(creds string) (string, string) {
@ -669,3 +681,7 @@ func swapSELinuxLabel(cLabel, processLabel string) (string, error) {
dcon["type"] = scon["type"] dcon["type"] = scon["type"]
return dcon.Get(), nil return dcon.Get(), nil
} }
func DefaultContainerConfig() *config.Config {
return containerConfig
}

View File

@ -13,6 +13,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/containers/common/pkg/sysinfo"
"github.com/containers/image/v5/manifest" "github.com/containers/image/v5/manifest"
"github.com/containers/libpod/cmd/podman/parse" "github.com/containers/libpod/cmd/podman/parse"
"github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod"
@ -28,7 +29,6 @@ import (
"github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/seccomp" "github.com/containers/libpod/pkg/seccomp"
cc "github.com/containers/libpod/pkg/spec" cc "github.com/containers/libpod/pkg/spec"
"github.com/containers/libpod/pkg/sysinfo"
systemdGen "github.com/containers/libpod/pkg/systemd/generate" systemdGen "github.com/containers/libpod/pkg/systemd/generate"
"github.com/containers/libpod/pkg/util" "github.com/containers/libpod/pkg/util"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"

View File

@ -331,7 +331,7 @@ func intFromVarlink(v *int64, flagName string, defaultValue *int) CRInt {
// structure. // structure.
func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults { func VarlinkCreateToGeneric(opts iopodman.Create) GenericCLIResults {
// FIXME this will need to be fixed!!!!! With containers conf // FIXME this will need to be fixed!!!!! With containers conf
//defaultContainerConfig := cliconfig.GetDefaultConfig() //containerConfig := cliconfig.GetDefaultConfig()
// TODO | WARN // TODO | WARN
// We do not get a default network over varlink. Unlike the other default values for some cli // 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. // elements, it seems it gets set to the default anyway.