Add kpod run
and kpod create
CLI front ends
Add kpod-run/kpod-create man page and command completions Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> This patch implements the ability to create and run containers using kpod Signed-off-by: Matthew Heon <mheon@redhat.com> Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
parent
c5e73ba65f
commit
409a228a73
10 changed files with 2901 additions and 2 deletions
|
@ -133,3 +133,320 @@ func validateFlags(c *cli.Context, flags []cli.Flag) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Common flags shared between commands
|
||||
var createFlags = []cli.Flag{
|
||||
cli.StringSliceFlag{
|
||||
Name: "add-host",
|
||||
Usage: "Add a custom host-to-IP mapping (host:ip) (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "attach, a",
|
||||
Usage: "Attach to STDIN, STDOUT or STDERR (default [])",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "blkio-weight",
|
||||
Usage: "Block IO weight (relative weight) accepts a weight value between 10 and 1000.",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "blkio-weight-device",
|
||||
Usage: "Block IO weight (relative device weight, format: `DEVICE_NAME:WEIGHT`)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "cap-add",
|
||||
Usage: "Add capabilities to the container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "cap-drop",
|
||||
Usage: "Drop capabilities from the container",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cgroup-parent",
|
||||
Usage: "Optional parent cgroup for the container",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "cpu-count",
|
||||
Usage: "Limit the number of CPUs available for execution by the container.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cid-file",
|
||||
Usage: "Write the container ID to the file",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "cpu-period",
|
||||
Usage: "Limit the CPU CFS (Completely Fair Scheduler) period",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "cpu-quota",
|
||||
Usage: "Limit the CPU CFS (Completely Fair Scheduler) quota",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "cpu-rt-period",
|
||||
Usage: "Limit the CPU real-time period in microseconds",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "cpu-rt-runtime",
|
||||
Usage: "Limit the CPU real-time runtime in microseconds",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "cpu-shares",
|
||||
Usage: "CPU shares (relative weight)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cpus",
|
||||
Usage: "Number of CPUs. The default is 0.000 which means no limit",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cpuset-cpus",
|
||||
Usage: "CPUs in which to allow execution (0-3, 0,1)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cpuset-mems",
|
||||
Usage: "Memory nodes (MEMs) in which to allow execution (0-3, 0,1). Only effective on NUMA systems.",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "detach, d",
|
||||
Usage: "Run container in background and print container ID",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "detach-keys",
|
||||
Usage: "Override 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 `_`",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "device",
|
||||
Usage: "Add a host device to the container (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "device-read-bps",
|
||||
Usage: "Limit read rate (bytes per second) from a device (e.g. --device-read-bps=/dev/sda:1mb)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "device-read-iops",
|
||||
Usage: "Limit read rate (IO per second) from a device (e.g. --device-read-iops=/dev/sda:1000)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "device-write-bps",
|
||||
Usage: "Limit write rate (bytes per second) to a device (e.g. --device-write-bps=/dev/sda:1mb)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "device-write-iops",
|
||||
Usage: "Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "dns",
|
||||
Usage: "Set custom DNS servers",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "dns-opt",
|
||||
Usage: "Set custom DNS options",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "dns-search",
|
||||
Usage: "Set custom DNS search domains",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "entrypoint",
|
||||
Usage: "Overwrite the default ENTRYPOINT of the image",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "env, e",
|
||||
Usage: "Set environment variables in container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "env-file",
|
||||
Usage: "Read in a file of environment variables",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "expose",
|
||||
Usage: "Expose a port or a range of ports (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "group-add",
|
||||
Usage: "Add additional groups to join (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "hostname",
|
||||
Usage: "Set container hostname",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "interactive, i",
|
||||
Usage: "Keep STDIN open even if not attached",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "ip",
|
||||
Usage: "Container IPv4 address (e.g. 172.23.0.9)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "ip6",
|
||||
Usage: "Container IPv6 address (e.g. 2001:db8::1b99)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "ipc",
|
||||
Usage: "IPC Namespace to use",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "kernel-memory",
|
||||
Usage: "Kernel memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "label",
|
||||
Usage: "Set metadata on container (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "label-file",
|
||||
Usage: "Read in a line delimited file of labels (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "link-local-ip",
|
||||
Usage: "Container IPv4/IPv6 link-local addresses (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "log-driver",
|
||||
Usage: "Logging driver for the container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "log-opt",
|
||||
Usage: "Logging driver options (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "mac-address",
|
||||
Usage: "Container MAC address (e.g. 92:d0:c6:0a:29:33)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "memory, m",
|
||||
Usage: "Memory limit (format: <number>[<unit>], where unit = b, k, m or g)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "memory-reservation",
|
||||
Usage: "Memory soft limit (format: <number>[<unit>], where unit = b, k, m or g)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "memory-swap",
|
||||
Usage: "Swap limit equal to memory plus swap: '-1' to enable unlimited swap",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "memory-swappiness",
|
||||
Usage: "Tune container memory swappiness (0 to 100) (default -1)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Assign a name to the container",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "net",
|
||||
Usage: "Setup the network namespace",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "network",
|
||||
Usage: "Connect a container to a network (default 'default')",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "network-alias",
|
||||
Usage: "Add network-scoped alias for the container (default [])",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "oom-kill-disable",
|
||||
Usage: "Disable OOM Killer",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "oom-score-adj",
|
||||
Usage: "Tune the host's OOM preferences (-1000 to 1000)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "pid",
|
||||
Usage: "PID Namespace to use",
|
||||
},
|
||||
cli.Int64Flag{
|
||||
Name: "pids-limit",
|
||||
Usage: "Tune container pids limit (set -1 for unlimited)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "pod",
|
||||
Usage: "Run container in an existing pod",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "privileged",
|
||||
Usage: "Give extended privileges to container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "publish, p",
|
||||
Usage: "Publish a container's port, or a range of ports, to the host (default [])",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "publish-all, P",
|
||||
Usage: "Publish all exposed ports to random ports on the host interface",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "read-only",
|
||||
Usage: "Make containers root filesystem read-only",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "rm",
|
||||
Usage: "Remove container (and pod if created) after exit",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "security-opt",
|
||||
Usage: "Security Options (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "shm-size",
|
||||
Usage: "Size of `/dev/shm`. The format is `<number><unit>`. default is 64 MB",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "sig-proxy",
|
||||
Usage: "Proxy received signals to the process (default true)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "stop-signal",
|
||||
Usage: "Signal to stop a container. Default is SIGTERM",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "stop-timeout",
|
||||
Usage: "Timeout (in seconds) to stop a container. Default is 10",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "storage-opt",
|
||||
Usage: "Storage driver options per container (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "sysctl",
|
||||
Usage: "Sysctl options (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "tmpfs",
|
||||
Usage: "Mount a temporary filesystem (`tmpfs`) into a container (default [])",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "tty, t",
|
||||
Usage: "Allocate a pseudo-TTY for container",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "ulimit",
|
||||
Usage: "Ulimit options (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "user, u",
|
||||
Usage: "Username or UID (format: <name|uid>[:<group|gid>])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "userns",
|
||||
Usage: "User namespace to use",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "uts",
|
||||
Usage: "UTS namespace to use",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "volume, v",
|
||||
Usage: "Bind mount a volume into the container (default [])",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "volumes-from",
|
||||
Usage: "Mount volumes from the specified container(s) (default [])",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "workdir, w",
|
||||
Usage: "Working `directory inside the container",
|
||||
Value: "/",
|
||||
},
|
||||
}
|
||||
|
|
160
cmd/kpod/create.go
Normal file
160
cmd/kpod/create.go
Normal file
|
@ -0,0 +1,160 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||
)
|
||||
|
||||
type createResourceConfig struct {
|
||||
blkioWeight int64
|
||||
blkioDevice []string
|
||||
cpuShares int64
|
||||
cpuCount int64
|
||||
cpuPeriod int64
|
||||
cpusetCpus string
|
||||
cpusetNames string
|
||||
cpuFile string
|
||||
cpuMems string
|
||||
cpuQuota int64
|
||||
cpuRtPeriod int64
|
||||
cpuRtRuntime int64
|
||||
cpus int64
|
||||
deviceReadBps []string
|
||||
deviceReadIops []string
|
||||
deviceWriteBps []string
|
||||
deviceWriteIops []string
|
||||
memory string
|
||||
memoryReservation string
|
||||
memorySwap string
|
||||
memorySwapiness string
|
||||
kernelMemory string
|
||||
oomScoreAdj string
|
||||
pidsLimit string
|
||||
shmSize string
|
||||
ulimit []string
|
||||
}
|
||||
|
||||
type createConfig struct {
|
||||
additionalGroups []int64
|
||||
args []string
|
||||
capAdd []string
|
||||
capDrop []string
|
||||
cgroupParent string
|
||||
command string
|
||||
detach bool
|
||||
devices []*pb.Device
|
||||
dnsOpt []string
|
||||
dnsSearch []string
|
||||
dnsServers []string
|
||||
entrypoint string
|
||||
env map[string]string
|
||||
expose []string
|
||||
groupAdd []string
|
||||
hostname string
|
||||
image string
|
||||
interactive bool
|
||||
ip6Address string
|
||||
ipAddress string
|
||||
labels map[string]string
|
||||
linkLocalIP []string
|
||||
logDriver string
|
||||
logDriverOpt []string
|
||||
macAddress string
|
||||
mounts []*pb.Mount
|
||||
name string
|
||||
network string
|
||||
networkAlias []string
|
||||
nsIPC string
|
||||
nsNet string
|
||||
nsPID string
|
||||
nsUser string
|
||||
pod string
|
||||
ports []*pb.PortMapping
|
||||
privileged bool
|
||||
publish []string
|
||||
publishAll bool
|
||||
readOnlyRootfs bool
|
||||
resources createResourceConfig
|
||||
rm bool
|
||||
securityOpts []string
|
||||
shmSize string
|
||||
sigProxy bool
|
||||
stdin bool
|
||||
stopSignal string
|
||||
stopTimeout int64
|
||||
storageOpts []string
|
||||
sysctl string
|
||||
tmpfs []string
|
||||
tty bool
|
||||
user int64
|
||||
userns string
|
||||
volumes []string
|
||||
volumesFrom []string
|
||||
workDir 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...]]",
|
||||
}
|
||||
|
||||
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
|
||||
if len(c.Args()) != 1 {
|
||||
return errors.Errorf("must specify name of image to create from")
|
||||
}
|
||||
if err := validateFlags(c, createFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
runtime, err := getRuntime(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
|
||||
createConfig, err := parseCreateOpts(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtimeSpec, err := createConfigToOCISpec(createConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctr, err := runtime.NewContainer(runtimeSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Should we also call ctr.Create() to make the container in runc?
|
||||
|
||||
fmt.Printf("%s\n", ctr.ID())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parses CLI options related to container creation into a config which can be
|
||||
// parsed into an OCI runtime spec
|
||||
func parseCreateOpts(c *cli.Context) (*createConfig, error) {
|
||||
return nil, errors.Errorf("NOT IMPLEMENTED")
|
||||
}
|
||||
|
||||
// Parses information needed to create a container into an OCI runtime spec
|
||||
func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
|
||||
return nil, errors.Errorf("NOT IMPLEMENTED")
|
||||
}
|
|
@ -31,6 +31,7 @@ func main() {
|
|||
app.Version = v
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
createCommand,
|
||||
diffCommand,
|
||||
exportCommand,
|
||||
historyCommand,
|
||||
|
@ -50,6 +51,7 @@ func main() {
|
|||
renameCommand,
|
||||
rmCommand,
|
||||
rmiCommand,
|
||||
runCommand,
|
||||
saveCommand,
|
||||
statsCommand,
|
||||
stopCommand,
|
||||
|
|
53
cmd/kpod/run.go
Normal file
53
cmd/kpod/run.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var runDescription = "Runs a command in a new container from the given image"
|
||||
|
||||
var runCommand = cli.Command{
|
||||
Name: "run",
|
||||
Usage: "run a command in a new container",
|
||||
Description: runDescription,
|
||||
Flags: createFlags,
|
||||
Action: runCmd,
|
||||
ArgsUsage: "IMAGE [COMMAND [ARG...]]",
|
||||
}
|
||||
|
||||
func runCmd(c *cli.Context) error {
|
||||
if len(c.Args()) != 1 {
|
||||
return errors.Errorf("must specify name of image to create from")
|
||||
}
|
||||
if err := validateFlags(c, createFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
runtime, err := getRuntime(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
|
||||
createConfig, err := parseCreateOpts(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
runtimeSpec, err := createConfigToOCISpec(createConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctr, err := runtime.NewContainer(runtimeSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Should we also call ctr.Create() to make the container in runc?
|
||||
|
||||
fmt.Printf("%s\n", ctr.ID())
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue