diff options
-rw-r--r-- | .travis.yml | 4 | ||||
-rw-r--r-- | cmd/podman/common.go | 64 | ||||
-rw-r--r-- | cmd/podman/utils.go | 55 | ||||
-rw-r--r-- | libkpod/config.go | 304 | ||||
-rw-r--r-- | libkpod/config_test.go | 54 | ||||
-rw-r--r-- | libkpod/hooks.go | 101 | ||||
-rw-r--r-- | libkpod/testdata/config.toml | 28 |
7 files changed, 57 insertions, 553 deletions
diff --git a/.travis.yml b/.travis.yml index d71867667..58de2614d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,6 +45,4 @@ jobs: - make integration go: 1.8.x -# Turn off notifications until we have our own channel (After rename) -# notifications: - irc: "chat.freenode.net#podman" +irc: "chat.freenode.net#podman" diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 921f30b84..e0aaf52c0 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -1,7 +1,6 @@ package main import ( - "os" "reflect" "regexp" "strings" @@ -9,7 +8,6 @@ import ( "github.com/containers/storage" "github.com/fatih/camelcase" "github.com/pkg/errors" - "github.com/projectatomic/libpod/libkpod" "github.com/projectatomic/libpod/libpod" "github.com/urfave/cli" ) @@ -23,69 +21,9 @@ var ( ) const ( - crioConfigPath = "/etc/crio/crio.conf" - idTruncLength = 12 + idTruncLength = 12 ) -func getRuntime(c *cli.Context) (*libpod.Runtime, error) { - - config, err := getConfig(c) - if err != nil { - return nil, errors.Wrapf(err, "could not get config") - } - - options := storage.DefaultStoreOptions - options.GraphRoot = config.Root - options.RunRoot = config.RunRoot - options.GraphDriverName = config.Storage - options.GraphDriverOptions = config.StorageOptions - - return libpod.NewRuntime(libpod.WithStorageConfig(options), libpod.WithConmonPath(config.Conmon), libpod.WithOCIRuntime(config.Runtime), libpod.WithCNIConfigDir(config.NetworkDir)) -} - -func getConfig(c *cli.Context) (*libkpod.Config, error) { - config := libkpod.DefaultConfig() - var configFile string - if c.GlobalIsSet("config") { - configFile = c.GlobalString("config") - } else if _, err := os.Stat(crioConfigPath); err == nil { - configFile = crioConfigPath - } - // load and merge the configfile from the commandline or use - // the default crio config file - if configFile != "" { - err := config.UpdateFromFile(configFile) - if err != nil { - return config, err - } - } - if c.GlobalIsSet("root") { - config.Root = c.GlobalString("root") - } - if c.GlobalIsSet("runroot") { - config.RunRoot = c.GlobalString("runroot") - } - if c.GlobalIsSet("conmon") { - config.Conmon = c.GlobalString("conmon") - } - if c.GlobalIsSet("storage-driver") { - config.Storage = c.GlobalString("storage-driver") - } - if c.GlobalIsSet("storage-opt") { - opts := c.GlobalStringSlice("storage-opt") - if len(opts) > 0 { - config.StorageOptions = opts - } - } - if c.GlobalIsSet("runtime") { - config.Runtime = c.GlobalString("runtime") - } - if c.GlobalIsSet("cni-config-dir") { - config.NetworkDir = c.GlobalString("cni-config-dir") - } - return config, nil -} - func splitCamelCase(src string) string { entries := camelcase.Split(src) return strings.Join(entries, " ") diff --git a/cmd/podman/utils.go b/cmd/podman/utils.go new file mode 100644 index 000000000..4c42c8ff5 --- /dev/null +++ b/cmd/podman/utils.go @@ -0,0 +1,55 @@ +package main + +import ( + "github.com/containers/storage" + "github.com/projectatomic/libpod/libpod" + "github.com/urfave/cli" +) + +// Generate a new libpod runtime configured by command line options +func getRuntime(c *cli.Context) (*libpod.Runtime, error) { + options := []libpod.RuntimeOption{} + + if c.GlobalIsSet("root") || c.GlobalIsSet("runroot") || + c.GlobalIsSet("storage-opt") || c.GlobalIsSet("storage-driver") { + storageOpts := storage.DefaultStoreOptions + + if c.GlobalIsSet("root") { + storageOpts.GraphRoot = c.GlobalString("root") + } + if c.GlobalIsSet("runroot") { + storageOpts.RunRoot = c.GlobalString("runroot") + } + if c.GlobalIsSet("storage-driver") { + storageOpts.GraphDriverName = c.GlobalString("storage-driver") + } + if c.GlobalIsSet("storage-opt") { + storageOpts.GraphDriverOptions = c.GlobalStringSlice("storage-opt") + } + + options = append(options, libpod.WithStorageConfig(storageOpts)) + } + + // TODO CLI flags for image config? + // TODO CLI flag for signature policy? + + if c.GlobalIsSet("runtime") { + options = append(options, libpod.WithOCIRuntime(c.GlobalString("runtime"))) + } + + if c.GlobalIsSet("conmon") { + options = append(options, libpod.WithConmonPath(c.GlobalString("conmon"))) + } + + // TODO flag to set CGroup manager? + // TODO flag to set libpod static dir? + // TODO flag to set libpod tmp dir? + + if c.GlobalIsSet("cni-config-dir") { + options = append(options, libpod.WithCNIConfigDir(c.GlobalString("cni-config-dir"))) + } + + // TODO flag to set CNI plugins dir? + + return libpod.NewRuntime(options...) +} diff --git a/libkpod/config.go b/libkpod/config.go deleted file mode 100644 index 9713e4bd7..000000000 --- a/libkpod/config.go +++ /dev/null @@ -1,304 +0,0 @@ -package libkpod - -import ( - "bytes" - "io/ioutil" - - "github.com/BurntSushi/toml" - "github.com/opencontainers/selinux/go-selinux" -) - -// Default paths if none are specified -const ( - crioRoot = "/var/lib/containers/storage" - crioRunRoot = "/var/run/containers/storage" - pauseImage = "kubernetes/pause" - pauseCommand = "/pause" - defaultTransport = "docker://" - seccompProfilePath = "/etc/crio/seccomp.json" - apparmorProfileName = "crio-default" - cniConfigDir = "/etc/cni/net.d/" - cniBinDir = "/usr/libexec/cni/" - cgroupManager = "" //oci.CgroupfsCgroupsManager - containerExitsDir = "" //oci.ContainerExitsDir -) - -// Config represents the entire set of configuration values that can be set for -// the server. This is intended to be loaded from a toml-encoded config file. -type Config struct { - RootConfig - RuntimeConfig - ImageConfig - NetworkConfig -} - -// ImageVolumesType describes image volume handling strategies -type ImageVolumesType string - -const ( - // ImageVolumesMkdir option is for using mkdir to handle image volumes - ImageVolumesMkdir ImageVolumesType = "mkdir" - // ImageVolumesIgnore option is for ignoring image volumes altogether - ImageVolumesIgnore ImageVolumesType = "ignore" - // ImageVolumesBind option is for using bind mounted volumes - ImageVolumesBind ImageVolumesType = "bind" -) - -const ( - // DefaultPidsLimit is the default value for maximum number of processes - // allowed inside a container - DefaultPidsLimit = 1024 - - // DefaultLogSizeMax is the default value for the maximum log size - // allowed for a container. Negative values mean that no limit is imposed. - DefaultLogSizeMax = -1 -) - -// This structure is necessary to fake the TOML tables when parsing, -// while also not requiring a bunch of layered structs for no good -// reason. - -// RootConfig represents the root of the "crio" TOML config table. -type RootConfig struct { - // Root is a path to the "root directory" where data not - // explicitly handled by other options will be stored. - Root string `toml:"root"` - - // RunRoot is a path to the "run directory" where state information not - // explicitly handled by other options will be stored. - RunRoot string `toml:"runroot"` - - // Storage is the name of the storage driver which handles actually - // storing the contents of containers. - Storage string `toml:"storage_driver"` - - // StorageOption is a list of storage driver specific options. - StorageOptions []string `toml:"storage_option"` - - // LogDir is the default log directory were all logs will go unless kubelet - // tells us to put them somewhere else. - LogDir string `toml:"log_dir"` - - // FileLocking specifies whether to use file-based or in-memory locking - // File-based locking is required when multiple users of libkpod are - // present on the same system - FileLocking bool `toml:"file_locking"` -} - -// RuntimeConfig represents the "crio.runtime" TOML config table. -type RuntimeConfig struct { - // Runtime is the OCI compatible runtime used for trusted container workloads. - // This is a mandatory setting as this runtime will be the default one and - // will also be used for untrusted container workloads if - // RuntimeUntrustedWorkload is not set. - Runtime string `toml:"runtime"` - - // RuntimeUntrustedWorkload is the OCI compatible runtime used for untrusted - // container workloads. This is an optional setting, except if - // DefaultWorkloadTrust is set to "untrusted". - RuntimeUntrustedWorkload string `toml:"runtime_untrusted_workload"` - - // DefaultWorkloadTrust is the default level of trust crio puts in container - // workloads. This can either be "trusted" or "untrusted" and the default - // is "trusted" - // Containers can be run through different container runtimes, depending on - // the trust hints we receive from kubelet: - // - If kubelet tags a container workload as untrusted, crio will try first - // to run it through the untrusted container workload runtime. If it is not - // set, crio will use the trusted runtime. - // - If kubelet does not provide any information about the container workload trust - // level, the selected runtime will depend on the DefaultWorkloadTrust setting. - // If it is set to "untrusted", then all containers except for the host privileged - // ones, will be run by the RuntimeUntrustedWorkload runtime. Host privileged - // containers are by definition trusted and will always use the trusted container - // runtime. If DefaultWorkloadTrust is set to "trusted", crio will use the trusted - // container runtime for all containers. - DefaultWorkloadTrust string `toml:"default_workload_trust"` - - // NoPivot instructs the runtime to not use `pivot_root`, but instead use `MS_MOVE` - NoPivot bool `toml:"no_pivot"` - - // Conmon is the path to conmon binary, used for managing the runtime. - Conmon string `toml:"conmon"` - - // ConmonEnv is the environment variable list for conmon process. - ConmonEnv []string `toml:"conmon_env"` - - // SELinux determines whether or not SELinux is used for pod separation. - SELinux bool `toml:"selinux"` - - // SeccompProfile is the seccomp json profile path which is used as the - // default for the runtime. - SeccompProfile string `toml:"seccomp_profile"` - - // ApparmorProfile is the apparmor profile name which is used as the - // default for the runtime. - ApparmorProfile string `toml:"apparmor_profile"` - - // CgroupManager is the manager implementation name which is used to - // handle cgroups for containers. - CgroupManager string `toml:"cgroup_manager"` - - // HooksDirPath location of oci hooks config files - HooksDirPath string `toml:"hooks_dir_path"` - - // DefaultMounts is the list of mounts to be mounted for each container - // The format of each mount is "host-path:container-path" - DefaultMounts []string `toml:"default_mounts"` - - // Hooks List of hooks to run with container - Hooks map[string]HookParams - - // PidsLimit is the number of processes each container is restricted to - // by the cgroup process number controller. - PidsLimit int64 `toml:"pids_limit"` - - // LogSizeMax is the maximum number of bytes after which the log file - // will be truncated. It can be expressed as a human-friendly string - // that is parsed to bytes. - // Negative values indicate that the log file won't be truncated. - LogSizeMax int64 `toml:"log_size_max"` - - // ContainerExitsDir is the directory in which container exit files are - // written to by conmon. - ContainerExitsDir string `toml:"container_exits_dir"` -} - -// ImageConfig represents the "crio.image" TOML config table. -type ImageConfig struct { - // DefaultTransport is a value we prefix to image names that fail to - // validate source references. - DefaultTransport string `toml:"default_transport"` - // PauseImage is the name of an image which we use to instantiate infra - // containers. - PauseImage string `toml:"pause_image"` - // PauseCommand is the path of the binary we run in an infra - // container that's been instantiated using PauseImage. - PauseCommand string `toml:"pause_command"` - // SignaturePolicyPath is the name of the file which decides what sort - // of policy we use when deciding whether or not to trust an image that - // we've pulled. Outside of testing situations, it is strongly advised - // that this be left unspecified so that the default system-wide policy - // will be used. - SignaturePolicyPath string `toml:"signature_policy"` - // InsecureRegistries is a list of registries that must be contacted w/o - // TLS verification. - InsecureRegistries []string `toml:"insecure_registries"` - // ImageVolumes controls how volumes specified in image config are handled - ImageVolumes ImageVolumesType `toml:"image_volumes"` - // Registries holds a list of registries used to pull unqualified images - Registries []string `toml:"registries"` -} - -// NetworkConfig represents the "crio.network" TOML config table -type NetworkConfig struct { - // NetworkDir is where CNI network configuration files are stored. - NetworkDir string `toml:"network_dir"` - - // PluginDir is where CNI plugin binaries are stored. - PluginDir string `toml:"plugin_dir"` -} - -// tomlConfig is another way of looking at a Config, which is -// TOML-friendly (it has all of the explicit tables). It's just used for -// conversions. -type tomlConfig struct { - Crio struct { - RootConfig - Runtime struct{ RuntimeConfig } `toml:"runtime"` - Image struct{ ImageConfig } `toml:"image"` - Network struct{ NetworkConfig } `toml:"network"` - } `toml:"crio"` -} - -func (t *tomlConfig) toConfig(c *Config) { - c.RootConfig = t.Crio.RootConfig - c.RuntimeConfig = t.Crio.Runtime.RuntimeConfig - c.ImageConfig = t.Crio.Image.ImageConfig - c.NetworkConfig = t.Crio.Network.NetworkConfig -} - -func (t *tomlConfig) fromConfig(c *Config) { - t.Crio.RootConfig = c.RootConfig - t.Crio.Runtime.RuntimeConfig = c.RuntimeConfig - t.Crio.Image.ImageConfig = c.ImageConfig - t.Crio.Network.NetworkConfig = c.NetworkConfig -} - -// UpdateFromFile populates the Config from the TOML-encoded file at the given path. -// Returns errors encountered when reading or parsing the files, or nil -// otherwise. -func (c *Config) UpdateFromFile(path string) error { - data, err := ioutil.ReadFile(path) - if err != nil { - return err - } - - t := new(tomlConfig) - t.fromConfig(c) - - _, err = toml.Decode(string(data), t) - if err != nil { - return err - } - - t.toConfig(c) - return nil -} - -// ToFile outputs the given Config as a TOML-encoded file at the given path. -// Returns errors encountered when generating or writing the file, or nil -// otherwise. -func (c *Config) ToFile(path string) error { - var w bytes.Buffer - e := toml.NewEncoder(&w) - - t := new(tomlConfig) - t.fromConfig(c) - - if err := e.Encode(*t); err != nil { - return err - } - - return ioutil.WriteFile(path, w.Bytes(), 0644) -} - -// DefaultConfig returns the default configuration for crio. -func DefaultConfig() *Config { - return &Config{ - RootConfig: RootConfig{ - Root: crioRoot, - RunRoot: crioRunRoot, - LogDir: "/var/log/crio/pods", - FileLocking: true, - }, - RuntimeConfig: RuntimeConfig{ - Runtime: "/usr/bin/runc", - RuntimeUntrustedWorkload: "", - DefaultWorkloadTrust: "trusted", - - ConmonEnv: []string{ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - }, - SELinux: selinux.GetEnabled(), - SeccompProfile: seccompProfilePath, - ApparmorProfile: apparmorProfileName, - CgroupManager: cgroupManager, - PidsLimit: DefaultPidsLimit, - ContainerExitsDir: containerExitsDir, - HooksDirPath: DefaultHooksDirPath, - LogSizeMax: DefaultLogSizeMax, - }, - ImageConfig: ImageConfig{ - DefaultTransport: defaultTransport, - PauseImage: pauseImage, - PauseCommand: pauseCommand, - SignaturePolicyPath: "", - ImageVolumes: ImageVolumesMkdir, - }, - NetworkConfig: NetworkConfig{ - NetworkDir: cniConfigDir, - PluginDir: cniBinDir, - }, - } -} diff --git a/libkpod/config_test.go b/libkpod/config_test.go deleted file mode 100644 index e6820d3c0..000000000 --- a/libkpod/config_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package libkpod - -import ( - "io/ioutil" - "os" - "testing" -) - -// TestConfigToFile ensures Config.ToFile(..) encodes and writes out -// a Config instance toa a file on disk. -func TestConfigToFile(t *testing.T) { - // Test with a default configuration - c := DefaultConfig() - tmpfile, err := ioutil.TempFile("", "config") - if err != nil { - t.Fatalf("Unable to create temporary file: %+v", err) - } - // Clean up temporary file - defer os.Remove(tmpfile.Name()) - - // Make the ToFile calls - err = c.ToFile(tmpfile.Name()) - // Make sure no errors occurred while populating the file - if err != nil { - t.Fatalf("Unable to write to temporary file: %+v", err) - } - - // Make sure the file is on disk - if _, err := os.Stat(tmpfile.Name()); os.IsNotExist(err) { - t.Fatalf("The config file was not written to disk: %+v", err) - } -} - -// TestConfigUpdateFromFile ensures Config.UpdateFromFile(..) properly -// updates an already create Config instancec with new data. -func TestConfigUpdateFromFile(t *testing.T) { - // Test with a default configuration - c := DefaultConfig() - // Make the ToFile calls - err := c.UpdateFromFile("testdata/config.toml") - // Make sure no errors occurred while populating from the file - if err != nil { - t.Fatalf("Unable update config from file: %+v", err) - } - - // Check fields that should have changed after UpdateFromFile - if c.Storage != "overlay2" { - t.Fatalf("Update failed. Storage did not change to overlay2") - } - - if c.RuntimeConfig.PidsLimit != 2048 { - t.Fatalf("Update failed. RuntimeConfig.PidsLimit did not change to 2048") - } -} diff --git a/libkpod/hooks.go b/libkpod/hooks.go deleted file mode 100644 index 26a9ee431..000000000 --- a/libkpod/hooks.go +++ /dev/null @@ -1,101 +0,0 @@ -package libkpod - -/* -import ( - "encoding/json" - "io/ioutil" - "os" - "path/filepath" - "regexp" - "strings" - "syscall" - - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) -*/ -const ( - // DefaultHooksDirPath Default directory containing hooks config files - DefaultHooksDirPath = "/usr/share/containers/oci/hooks.d" - // OverrideHooksDirPath Directory where admin can override the default configuration - OverrideHooksDirPath = "/etc/containers/oci/hooks.d" -) - -// HookParams is the structure returned from read the hooks configuration -type HookParams struct { - Hook string `json:"hook"` - Stage []string `json:"stage"` - Cmds []string `json:"cmd"` - Annotations []string `json:"annotation"` - HasBindMounts bool `json:"hasbindmounts"` -} - -/* -// readHook reads hooks json files, verifies it and returns the json config -func readHook(hookPath string) (HookParams, error) { - var hook HookParams - raw, err := ioutil.ReadFile(hookPath) - if err != nil { - return hook, errors.Wrapf(err, "error Reading hook %q", hookPath) - } - if err := json.Unmarshal(raw, &hook); err != nil { - return hook, errors.Wrapf(err, "error Unmarshalling JSON for %q", hookPath) - } - if _, err := os.Stat(hook.Hook); err != nil { - return hook, errors.Wrapf(err, "unable to stat hook %q in hook config %q", hook.Hook, hookPath) - } - validStage := map[string]bool{"prestart": true, "poststart": true, "poststop": true} - for _, cmd := range hook.Cmds { - if _, err = regexp.Compile(cmd); err != nil { - return hook, errors.Wrapf(err, "invalid cmd regular expression %q defined in hook config %q", cmd, hookPath) - } - } - for _, cmd := range hook.Annotations { - if _, err = regexp.Compile(cmd); err != nil { - return hook, errors.Wrapf(err, "invalid cmd regular expression %q defined in hook config %q", cmd, hookPath) - } - } - for _, stage := range hook.Stage { - if !validStage[stage] { - return hook, errors.Wrapf(err, "unknown stage %q defined in hook config %q", stage, hookPath) - } - } - return hook, nil -} - -// readHooks reads hooks json files in directory to setup OCI Hooks -// adding hooks to the passedin hooks map. -func readHooks(hooksPath string, hooks map[string]HookParams) error { - if _, err := os.Stat(hooksPath); err != nil { - if os.IsNotExist(err) { - logrus.Warnf("hooks path: %q does not exist", hooksPath) - return nil - } - return errors.Wrapf(err, "unable to stat hooks path %q", hooksPath) - } - - files, err := ioutil.ReadDir(hooksPath) - if err != nil { - return err - } - - for _, file := range files { - if !strings.HasSuffix(file.Name(), ".json") { - continue - } - hook, err := readHook(filepath.Join(hooksPath, file.Name())) - if err != nil { - return err - } - for key, h := range hooks { - // hook.Hook can only be defined in one hook file, unless it has the - // same name in the override path. - if hook.Hook == h.Hook && key != file.Name() { - return errors.Wrapf(syscall.EINVAL, "duplicate path, hook %q from %q already defined in %q", hook.Hook, hooksPath, key) - } - } - hooks[file.Name()] = hook - } - return nil -} -*/ diff --git a/libkpod/testdata/config.toml b/libkpod/testdata/config.toml deleted file mode 100644 index e19d36017..000000000 --- a/libkpod/testdata/config.toml +++ /dev/null @@ -1,28 +0,0 @@ -[crio] - root = "/var/lib/containers/storage" - runroot = "/var/run/containers/storage" - storage_driver = "overlay2" - log_dir = "/var/log/crio/pods" - file_locking = true - [crio.runtime] - runtime = "/usr/bin/runc" - runtime_untrusted_workload = "" - default_workload_trust = "trusted" - conmon = "/usr/local/libexec/crio/conmon" - conmon_env = ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"] - selinux = true - seccomp_profile = "/etc/crio/seccomp.json" - apparmor_profile = "crio-default" - cgroup_manager = "cgroupfs" - hooks_dir_path = "/usr/share/containers/oci/hooks.d" - pids_limit = 2048 - container_exits_dir = "/var/run/podman/exits" - [crio.image] - default_transport = "docker://" - pause_image = "kubernetes/pause" - pause_command = "/pause" - signature_policy = "" - image_volumes = "mkdir" - [crio.network] - network_dir = "/etc/cni/net.d/" - plugin_dir = "/opt/cni/bin/" |