diff options
author | baude <bbaude@redhat.com> | 2017-11-28 16:25:01 -0600 |
---|---|---|
committer | baude <bbaude@redhat.com> | 2017-12-11 08:24:30 -0600 |
commit | e8a32e3722e0b814c654cdb8809565a21fc120d3 (patch) | |
tree | 8b88407b645e9403f4fc7ebf2e4d62bc34785a20 /libpod | |
parent | 8d31ec2ad775c97c4b860eb24a3481092b6e88e3 (diff) | |
download | podman-e8a32e3722e0b814c654cdb8809565a21fc120d3.tar.gz podman-e8a32e3722e0b814c654cdb8809565a21fc120d3.tar.bz2 podman-e8a32e3722e0b814c654cdb8809565a21fc120d3.zip |
kpod exec
Initial wiring of kpod exec. We wont support the following options
for exec:
* detach -- unsure of use case
* detach-keys -- not supported by runc
* interactive -- all terminals will be interactive
Not adding exec tests as we need to think about how to support a
test that requires console access but our CI tests have no console.
Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container.go | 34 | ||||
-rw-r--r-- | libpod/oci.go | 6 | ||||
-rw-r--r-- | libpod/runc.go | 117 |
3 files changed, 154 insertions, 3 deletions
diff --git a/libpod/container.go b/libpod/container.go index 40aa689ff..474d4be95 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -14,6 +14,7 @@ import ( "github.com/containers/storage" "github.com/containers/storage/pkg/archive" + "github.com/docker/docker/daemon/caps" "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/namesgenerator" "github.com/docker/docker/pkg/stringid" @@ -552,9 +553,36 @@ func (c *Container) Kill(signal uint) error { } // Exec starts a new process inside the container -// Returns fully qualified URL of streaming server for executed process -func (c *Container) Exec(cmd []string, tty bool, stdin bool) (string, error) { - return "", ErrNotImplemented +func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) error { + var capList []string + c.lock.Lock() + defer c.lock.Unlock() + + if err := c.syncContainer(); err != nil { + return err + } + + conState := c.state.State + + if conState != ContainerStateRunning { + return errors.Errorf("cannot attach to container that is not running") + } + if privileged { + capList = caps.GetAllCapabilities() + } + globalOpts := runcGlobalOptions{ + log: c.LogPath(), + } + execOpts := runcExecOptions{ + capAdd: capList, + pidFile: filepath.Join(c.state.RunDir, fmt.Sprintf("%s-execpid", stringid.GenerateNonCryptoID()[:12])), + env: env, + user: user, + cwd: c.config.Spec.Process.Cwd, + tty: tty, + } + + return c.runtime.ociRuntime.execContainer(c, cmd, globalOpts, execOpts) } // Attach attaches to a container diff --git a/libpod/oci.go b/libpod/oci.go index 6ea6bb64f..323e97273 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -454,3 +454,9 @@ func (r *OCIRuntime) pauseContainer(ctr *Container) error { func (r *OCIRuntime) unpauseContainer(ctr *Container) error { return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "resume", ctr.ID()) } + +//execContiner executes a command in a running container +func (r *OCIRuntime) execContainer(c *Container, cmd []string, globalOpts runcGlobalOptions, commandOpts runcExecOptions) error { + r.RuncExec(c, cmd, globalOpts, commandOpts) + return nil +} diff --git a/libpod/runc.go b/libpod/runc.go new file mode 100644 index 000000000..efbb51b24 --- /dev/null +++ b/libpod/runc.go @@ -0,0 +1,117 @@ +package libpod + +import ( + "os" + "os/exec" + "strings" + + "github.com/sirupsen/logrus" +) + +type runcGlobalOptions struct { + log string + logFormat string + root string + criu string + systemdCgroup bool +} +type runcExecOptions struct { + consoleSocket string + cwd string + env []string + tty bool + user string + processPath string + detach bool + pidFile string + processLabel string + apparmor string + noNewPrivs bool + capAdd []string +} + +func parseGlobalOptionsToArgs(opts runcGlobalOptions) []string { + args := []string{} + if opts.log != "" { + args = append(args, "--log", opts.log) + } + if opts.logFormat != "" { + args = append(args, "--log-format", opts.logFormat) + } + if opts.root != "" { + args = append(args, "--root", opts.root) + } + if opts.criu != "" { + args = append(args, "--criu", opts.criu) + } + if opts.systemdCgroup { + args = append(args, "--systemd-cgroup") + } + return args +} + +// RuncExec executes 'runc --options exec --options cmd' +func (r *OCIRuntime) RuncExec(container *Container, command []string, globalOpts runcGlobalOptions, execOpts runcExecOptions) error { + args := []string{} + args = append(args, parseGlobalOptionsToArgs(globalOpts)...) + // Add subcommand + args = append(args, "exec") + // Now add subcommand args + + if execOpts.consoleSocket != "" { + args = append(args, "--console-socket", execOpts.consoleSocket) + } + if execOpts.cwd != "" { + args = append(args, "--cwd", execOpts.cwd) + } + + if len(execOpts.env) > 0 { + for _, envInput := range execOpts.env { + args = append(args, "--env", envInput) + } + } + if execOpts.tty { + args = append(args, "--tty") + } + if execOpts.user != "" { + args = append(args, "--user", execOpts.user) + + } + if execOpts.processPath != "" { + args = append(args, "--process", execOpts.processPath) + } + if execOpts.detach { + args = append(args, "--detach") + } + if execOpts.pidFile != "" { + args = append(args, "--pid-file", execOpts.pidFile) + } + if execOpts.processLabel != "" { + args = append(args, "--process-label", execOpts.processLabel) + } + if execOpts.apparmor != "" { + args = append(args, "--apparmor", execOpts.apparmor) + } + if execOpts.noNewPrivs { + args = append(args, "--no-new-privs") + } + if len(execOpts.capAdd) > 0 { + for _, capAddValue := range execOpts.capAdd { + args = append(args, "--cap", capAddValue) + } + } + + // Append Cid + args = append(args, container.ID()) + // Append Cmd + args = append(args, command...) + + logrus.Debug("Executing runc command: %s %s", r.path, strings.Join(args, " ")) + cmd := exec.Command(r.path, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin + cmd.Start() + err := cmd.Wait() + return err +} |