summaryrefslogtreecommitdiff
path: root/cmd/kpod/create.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/kpod/create.go')
-rw-r--r--cmd/kpod/create.go507
1 files changed, 0 insertions, 507 deletions
diff --git a/cmd/kpod/create.go b/cmd/kpod/create.go
deleted file mode 100644
index afed70eaa..000000000
--- a/cmd/kpod/create.go
+++ /dev/null
@@ -1,507 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "fmt"
- "os"
- "strconv"
- "strings"
-
- "github.com/docker/docker/api/types/container"
- "github.com/docker/go-units"
- "github.com/opencontainers/selinux/go-selinux/label"
- "github.com/pkg/errors"
- "github.com/projectatomic/libpod/libpod"
- "github.com/sirupsen/logrus"
- "github.com/urfave/cli"
- pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
-)
-
-type mountType string
-
-// Type constants
-const (
- // TypeBind is the type for mounting host dir
- TypeBind mountType = "bind"
- // TypeVolume is the type for remote storage volumes
- // TypeVolume mountType = "volume" // re-enable upon use
- // TypeTmpfs is the type for mounting tmpfs
- TypeTmpfs mountType = "tmpfs"
-)
-
-var (
- defaultEnvVariables = map[string]string{
- "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
- "TERM": "xterm",
- }
-)
-
-type createResourceConfig struct {
- BlkioWeight uint16 // blkio-weight
- BlkioWeightDevice []string // blkio-weight-device
- CPUPeriod uint64 // cpu-period
- CPUQuota int64 // cpu-quota
- CPURtPeriod uint64 // cpu-rt-period
- CPURtRuntime int64 // cpu-rt-runtime
- CPUShares uint64 // cpu-shares
- CPUs string // cpus
- CPUsetCPUs string
- CPUsetMems string // cpuset-mems
- DeviceReadBps []string // device-read-bps
- DeviceReadIOps []string // device-read-iops
- DeviceWriteBps []string // device-write-bps
- DeviceWriteIOps []string // device-write-iops
- DisableOomKiller bool // oom-kill-disable
- KernelMemory int64 // kernel-memory
- Memory int64 //memory
- MemoryReservation int64 // memory-reservation
- MemorySwap int64 //memory-swap
- MemorySwappiness int // memory-swappiness
- OomScoreAdj int //oom-score-adj
- PidsLimit int64 // pids-limit
- ShmSize string
- Ulimit []string //ulimit
-}
-
-type createConfig struct {
- Runtime *libpod.Runtime
- Args []string
- CapAdd []string // cap-add
- CapDrop []string // cap-drop
- CidFile string
- CgroupParent string // cgroup-parent
- Command []string
- Detach bool // detach
- Devices []*pb.Device // device
- DNSOpt []string //dns-opt
- DNSSearch []string //dns-search
- DNSServers []string //dns
- Entrypoint string //entrypoint
- Env map[string]string //env
- Expose []string //expose
- GroupAdd []uint32 // group-add
- Hostname string //hostname
- Image string
- Interactive bool //interactive
- IpcMode container.IpcMode //ipc
- IP6Address string //ipv6
- IPAddress string //ip
- Labels map[string]string //label
- LinkLocalIP []string // link-local-ip
- LogDriver string // log-driver
- LogDriverOpt []string // log-opt
- MacAddress string //mac-address
- Name string //name
- NetMode container.NetworkMode //net
- Network string //network
- NetworkAlias []string //network-alias
- PidMode container.PidMode //pid
- NsUser string
- Pod string //pod
- Privileged bool //privileged
- Publish []string //publish
- PublishAll bool //publish-all
- ReadOnlyRootfs bool //read-only
- Resources createResourceConfig
- Rm bool //rm
- ShmDir string
- SigProxy bool //sig-proxy
- StopSignal string // stop-signal
- StopTimeout int64 // stop-timeout
- StorageOpts []string //storage-opt
- Sysctl map[string]string //sysctl
- Tmpfs []string // tmpfs
- Tty bool //tty
- User uint32 //user
- Group uint32 // group
- UtsMode container.UTSMode //uts
- Volumes []string //volume
- WorkDir string //workdir
- MountLabel string //SecurityOpts
- ProcessLabel string //SecurityOpts
- NoNewPrivileges bool //SecurityOpts
- ApparmorProfile string //SecurityOpts
- SeccompProfilePath string //SecurityOpts
- SecurityOpts []string
-}
-
-var createDescription = "Creates a new container from the given image or" +
- " storage and prepares it for running the specified command. The" +
- " container ID is then printed to stdout. You can then start it at" +
- " any time with the kpod start <container_id> command. The container" +
- " will be created with the initial state 'created'."
-
-var createCommand = cli.Command{
- Name: "create",
- Usage: "create but do not start a container",
- Description: createDescription,
- Flags: createFlags,
- Action: createCmd,
- ArgsUsage: "IMAGE [COMMAND [ARG...]]",
- SkipArgReorder: true,
- UseShortOptionHandling: true,
-}
-
-func createCmd(c *cli.Context) error {
- // TODO should allow user to create based off a directory on the host not just image
- // Need CLI support for this
- var imageName string
- if err := validateFlags(c, createFlags); err != nil {
- return err
- }
-
- runtime, err := getRuntime(c)
- if err != nil {
- return errors.Wrapf(err, "error creating libpod runtime")
- }
- defer runtime.Shutdown(false)
-
- createConfig, err := parseCreateOpts(c, runtime)
- if err != nil {
- return err
- }
-
- // Deal with the image after all the args have been checked
- createImage := runtime.NewImage(createConfig.Image)
- createImage.LocalName, _ = createImage.GetLocalImageName()
- if createImage.LocalName == "" {
- // The image wasnt found by the user input'd name or its fqname
- // Pull the image
- fmt.Printf("Trying to pull %s...", createImage.PullName)
- createImage.Pull()
- }
-
- runtimeSpec, err := createConfigToOCISpec(createConfig)
- if err != nil {
- return err
- }
- if createImage.LocalName != "" {
- nameIsID, err := runtime.IsImageID(createImage.LocalName)
- if err != nil {
- return err
- }
- if nameIsID {
- // If the input from the user is an ID, then we need to get the image
- // name for cstorage
- createImage.LocalName, err = createImage.GetNameByID()
- if err != nil {
- return err
- }
- }
- imageName = createImage.LocalName
- } else {
- imageName, err = createImage.GetFQName()
- }
- if err != nil {
- return err
- }
- imageID, err := createImage.GetImageID()
- if err != nil {
- return err
- }
- options, err := createConfig.GetContainerCreateOptions()
- if err != nil {
- return errors.Wrapf(err, "unable to parse new container options")
- }
- // Gather up the options for NewContainer which consist of With... funcs
- options = append(options, libpod.WithRootFSFromImage(imageID, imageName, false))
- options = append(options, libpod.WithSELinuxLabels(createConfig.ProcessLabel, createConfig.MountLabel))
- options = append(options, libpod.WithShmDir(createConfig.ShmDir))
- ctr, err := runtime.NewContainer(runtimeSpec, options...)
- if err != nil {
- return err
- }
-
- createConfigJSON, err := json.Marshal(createConfig)
- if err != nil {
- return err
- }
- if err := ctr.AddArtifact("create-config", createConfigJSON); err != nil {
- return err
- }
-
- logrus.Debug("new container created ", ctr.ID())
-
- if c.String("cidfile") != "" {
- libpod.WriteFile(ctr.ID(), c.String("cidfile"))
- } else {
- fmt.Printf("%s\n", ctr.ID())
- }
-
- return nil
-}
-
-const seccompDefaultPath = "/etc/crio/seccomp.json"
-
-func parseSecurityOpt(config *createConfig, securityOpts []string) error {
- var (
- labelOpts []string
- err error
- )
-
- if config.PidMode.IsHost() {
- labelOpts = append(labelOpts, label.DisableSecOpt()...)
- } else if config.PidMode.IsContainer() {
- ctr, err := config.Runtime.LookupContainer(config.PidMode.Container())
- if err != nil {
- return errors.Wrapf(err, "container %q not found", config.PidMode.Container())
- }
- labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...)
- }
-
- if config.IpcMode.IsHost() {
- labelOpts = append(labelOpts, label.DisableSecOpt()...)
- } else if config.IpcMode.IsContainer() {
- ctr, err := config.Runtime.LookupContainer(config.IpcMode.Container())
- if err != nil {
- return errors.Wrapf(err, "container %q not found", config.IpcMode.Container())
- }
- labelOpts = append(labelOpts, label.DupSecOpt(ctr.ProcessLabel())...)
- }
-
- for _, opt := range securityOpts {
- if opt == "no-new-privileges" {
- config.NoNewPrivileges = true
- } else {
- con := strings.SplitN(opt, "=", 2)
- if len(con) != 2 {
- return fmt.Errorf("Invalid --security-opt 1: %q", opt)
- }
-
- switch con[0] {
- case "label":
- labelOpts = append(labelOpts, con[1])
- case "apparmor":
- config.ApparmorProfile = con[1]
- case "seccomp":
- config.SeccompProfilePath = con[1]
- default:
- return fmt.Errorf("Invalid --security-opt 2: %q", opt)
- }
- }
- }
-
- if config.SeccompProfilePath == "" {
- if _, err := os.Stat(seccompDefaultPath); err != nil {
- if !os.IsNotExist(err) {
- return errors.Wrapf(err, "can't check if %q exists", seccompDefaultPath)
- }
- } else {
- config.SeccompProfilePath = seccompDefaultPath
- }
- }
- config.ProcessLabel, config.MountLabel, err = label.InitLabels(labelOpts)
- return err
-}
-
-// Parses CLI options related to container creation into a config which can be
-// parsed into an OCI runtime spec
-func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime) (*createConfig, error) {
- var command []string
- var memoryLimit, memoryReservation, memorySwap, memoryKernel int64
- var blkioWeight uint16
- var uid, gid uint32
-
- if len(c.Args()) < 1 {
- return nil, errors.Errorf("image name or ID is required")
- }
- image := c.Args()[0]
-
- if len(c.Args()) > 1 {
- command = c.Args()[1:]
- }
-
- // LABEL VARIABLES
- labels, err := getAllLabels(c.StringSlice("label-file"), c.StringSlice("labels"))
- if err != nil {
- return &createConfig{}, errors.Wrapf(err, "unable to process labels")
- }
- // ENVIRONMENT VARIABLES
- env := defaultEnvVariables
- if err := readKVStrings(env, c.StringSlice("env-file"), c.StringSlice("env")); err != nil {
- return &createConfig{}, errors.Wrapf(err, "unable to process environment variables")
- }
-
- sysctl, err := convertStringSliceToMap(c.StringSlice("sysctl"), "=")
- if err != nil {
- return &createConfig{}, errors.Wrapf(err, "sysctl values must be in the form of KEY=VALUE")
- }
-
- groupAdd, err := stringSlicetoUint32Slice(c.StringSlice("group-add"))
- if err != nil {
- return &createConfig{}, errors.Wrapf(err, "invalid value for groups provided")
- }
-
- if c.String("user") != "" {
- // TODO
- // We need to mount the imagefs and get the uid/gid
- // For now, user zeros
- uid = 0
- gid = 0
- }
-
- if c.String("memory") != "" {
- memoryLimit, err = units.RAMInBytes(c.String("memory"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for memory")
- }
- }
- if c.String("memory-reservation") != "" {
- memoryReservation, err = units.RAMInBytes(c.String("memory-reservation"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for memory-reservation")
- }
- }
- if c.String("memory-swap") != "" {
- memorySwap, err = units.RAMInBytes(c.String("memory-swap"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for memory-swap")
- }
- }
- if c.String("kernel-memory") != "" {
- memoryKernel, err = units.RAMInBytes(c.String("kernel-memory"))
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for kernel-memory")
- }
- }
- if c.String("blkio-weight") != "" {
- u, err := strconv.ParseUint(c.String("blkio-weight"), 10, 16)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid value for blkio-weight")
- }
- blkioWeight = uint16(u)
- }
-
- if err = parseVolumes(c.StringSlice("volume")); err != nil {
- return nil, err
- }
-
- // Because we cannot do a non-terminal attach, we need to set tty to true
- // if detach is not false
- // TODO Allow non-terminal attach
- tty := c.Bool("tty")
- if !c.Bool("detach") && !tty {
- tty = true
- }
-
- pidMode := container.PidMode(c.String("pid"))
- if !pidMode.Valid() {
- return nil, errors.Errorf("--pid %q is not valid", c.String("pid"))
- }
-
- if c.Bool("detach") && c.Bool("rm") {
- return nil, errors.Errorf("--rm and --detach can not be specified together")
- }
-
- utsMode := container.UTSMode(c.String("uts"))
- if !utsMode.Valid() {
- return nil, errors.Errorf("--uts %q is not valid", c.String("uts"))
- }
- ipcMode := container.IpcMode(c.String("ipc"))
- if !ipcMode.Valid() {
- return nil, errors.Errorf("--ipc %q is not valid", ipcMode)
- }
- shmDir := ""
- if ipcMode.IsHost() {
- shmDir = "/dev/shm"
- } else if ipcMode.IsContainer() {
- ctr, err := runtime.LookupContainer(ipcMode.Container())
- if err != nil {
- return nil, errors.Wrapf(err, "container %q not found", ipcMode.Container())
- }
- shmDir = ctr.ShmDir()
- }
-
- config := &createConfig{
- Runtime: runtime,
- CapAdd: c.StringSlice("cap-add"),
- CapDrop: c.StringSlice("cap-drop"),
- CgroupParent: c.String("cgroup-parent"),
- Command: command,
- Detach: c.Bool("detach"),
- DNSOpt: c.StringSlice("dns-opt"),
- DNSSearch: c.StringSlice("dns-search"),
- DNSServers: c.StringSlice("dns"),
- Entrypoint: c.String("entrypoint"),
- Env: env,
- Expose: c.StringSlice("expose"),
- GroupAdd: groupAdd,
- Hostname: c.String("hostname"),
- Image: image,
- Interactive: c.Bool("interactive"),
- IP6Address: c.String("ipv6"),
- IPAddress: c.String("ip"),
- Labels: labels,
- LinkLocalIP: c.StringSlice("link-local-ip"),
- LogDriver: c.String("log-driver"),
- LogDriverOpt: c.StringSlice("log-opt"),
- MacAddress: c.String("mac-address"),
- Name: c.String("name"),
- Network: c.String("network"),
- NetworkAlias: c.StringSlice("network-alias"),
- IpcMode: ipcMode,
- NetMode: container.NetworkMode(c.String("network")),
- UtsMode: utsMode,
- PidMode: pidMode,
- Pod: c.String("pod"),
- Privileged: c.Bool("privileged"),
- Publish: c.StringSlice("publish"),
- PublishAll: c.Bool("publish-all"),
- ReadOnlyRootfs: c.Bool("read-only"),
- Resources: createResourceConfig{
- BlkioWeight: blkioWeight,
- BlkioWeightDevice: c.StringSlice("blkio-weight-device"),
- CPUShares: c.Uint64("cpu-shares"),
- CPUPeriod: c.Uint64("cpu-period"),
- CPUsetCPUs: c.String("cpu-period"),
- CPUsetMems: c.String("cpuset-mems"),
- CPUQuota: c.Int64("cpu-quota"),
- CPURtPeriod: c.Uint64("cpu-rt-period"),
- CPURtRuntime: c.Int64("cpu-rt-runtime"),
- CPUs: c.String("cpus"),
- DeviceReadBps: c.StringSlice("device-read-bps"),
- DeviceReadIOps: c.StringSlice("device-read-iops"),
- DeviceWriteBps: c.StringSlice("device-write-bps"),
- DeviceWriteIOps: c.StringSlice("device-write-iops"),
- DisableOomKiller: c.Bool("oom-kill-disable"),
- ShmSize: c.String("shm-size"),
- Memory: memoryLimit,
- MemoryReservation: memoryReservation,
- MemorySwap: memorySwap,
- MemorySwappiness: c.Int("memory-swappiness"),
- KernelMemory: memoryKernel,
- OomScoreAdj: c.Int("oom-score-adj"),
-
- PidsLimit: c.Int64("pids-limit"),
- Ulimit: c.StringSlice("ulimit"),
- },
- Rm: c.Bool("rm"),
- ShmDir: shmDir,
- SigProxy: c.Bool("sig-proxy"),
- StopSignal: c.String("stop-signal"),
- StopTimeout: c.Int64("stop-timeout"),
- StorageOpts: c.StringSlice("storage-opt"),
- Sysctl: sysctl,
- Tmpfs: c.StringSlice("tmpfs"),
- Tty: tty,
- User: uid,
- Group: gid,
- Volumes: c.StringSlice("volume"),
- WorkDir: c.String("workdir"),
- }
-
- if !config.Privileged {
- if err := parseSecurityOpt(config, c.StringSlice("security-opt")); err != nil {
- return nil, err
- }
- }
- config.SecurityOpts = c.StringSlice("security-opt")
- warnings, err := verifyContainerResources(config, false)
- if err != nil {
- return nil, err
- }
- for _, warning := range warnings {
- fmt.Fprintln(os.Stderr, warning)
- }
- return config, nil
-}