Merge c921dfc2f9
into 3991a0531c
This commit is contained in:
commit
2c88c79f43
10 changed files with 275 additions and 2 deletions
|
@ -44,6 +44,7 @@ It is currently in active development in the Kubernetes community through the [d
|
|||
| [kpod-attach(1)](/docs/kpod-attach.1.md) | Instead of providing a `kpod attach` command, the man page `kpod-attach` describes how to use the `kpod logs` and `kpod exec` commands to achieve the same goals as `kpod attach`.||
|
||||
| [kpod-cp(1)](/docs/kpod-cp.1.md) | Instead of providing a `kpod cp` command, the man page `kpod-cp` describes how to use the `kpod mount` command to have even more flexibility and functionality.||
|
||||
| [kpod-diff(1)](/docs/kpod-diff.1.md) | Inspect changes on a container or image's filesystem ||
|
||||
| [kpod-exec(1)](/docs/kpod-exec.1.md) | Execute a command in a running container
|
||||
| [kpod-export(1)](/docs/kpod-export.1.md) | Export container's filesystem contents as a tar archive ||
|
||||
| [kpod-history(1)](/docs/kpod-history.1.md) | Shows the history of an image |[](https://asciinema.org/a/bCvUQJ6DkxInMELZdc5DinNSx)|
|
||||
| [kpod-images(1)](/docs/kpod-images.1.md) | List images in local storage |[](https://asciinema.org/a/133649)|
|
||||
|
|
82
cmd/kpod/exec.go
Normal file
82
cmd/kpod/exec.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/kubernetes-incubator/cri-o/libkpod"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
execFlags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "detach, d",
|
||||
Usage: "detached mode: command will run in the background",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
Name: "env, e",
|
||||
Usage: "set environment variables",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "tty, t",
|
||||
Usage: "Allocate a pseudo TTY",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "user, u",
|
||||
Usage: "Sets the username (UID) and groupname (GID) for the specified command",
|
||||
},
|
||||
}
|
||||
execDescription = `
|
||||
kpod exec
|
||||
|
||||
Run a command in a running container. The command will only run while the primary
|
||||
PID in the container is running.
|
||||
`
|
||||
|
||||
execCommand = cli.Command{
|
||||
Name: "exec",
|
||||
Usage: "Run a command in a running container",
|
||||
Description: execDescription,
|
||||
Flags: execFlags,
|
||||
Action: execCmd,
|
||||
ArgsUsage: "[OPTIONS} CONTAINER-NAME COMMAND",
|
||||
}
|
||||
)
|
||||
|
||||
func execCmd(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
detachFlag := c.Bool("detach")
|
||||
envFlags := c.StringSlice("env")
|
||||
ttyFlag := c.Bool("tty")
|
||||
userFlag := c.String("user")
|
||||
|
||||
if len(args) < 2 {
|
||||
return errors.Errorf("you must provide a container name or ID and a command to run")
|
||||
}
|
||||
if err := validateFlags(c, execFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
container := args[0]
|
||||
var command []string
|
||||
for _, cmd := range args[1:] {
|
||||
command = append(command, cmd)
|
||||
}
|
||||
|
||||
config, err := getConfig(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get config")
|
||||
}
|
||||
server, err := libkpod.New(config)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get container server")
|
||||
}
|
||||
defer server.Shutdown()
|
||||
err = server.Update()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not update list of containers")
|
||||
}
|
||||
if err := server.ContainerExec(container, command, detachFlag, envFlags, ttyFlag, userFlag); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
|
@ -32,6 +32,7 @@ func main() {
|
|||
|
||||
app.Commands = []cli.Command{
|
||||
diffCommand,
|
||||
execCommand,
|
||||
exportCommand,
|
||||
historyCommand,
|
||||
imagesCommand,
|
||||
|
|
|
@ -404,6 +404,12 @@ _kpod_wait() {
|
|||
_complete_ "$options_with_args" "$boolean_options"
|
||||
}
|
||||
|
||||
_kpod_exec() {
|
||||
local options_with_args="--env -e --user -u"
|
||||
local boolean_options="--help -h --tty -t --detach -d"
|
||||
_complete_ "$options_with_args" "$boolean_options"
|
||||
}
|
||||
|
||||
_complete_() {
|
||||
local options_with_args=$1
|
||||
local boolean_options="$2 -h --help"
|
||||
|
@ -474,6 +480,7 @@ _kpod_kpod() {
|
|||
"
|
||||
commands="
|
||||
diff
|
||||
exec
|
||||
export
|
||||
history
|
||||
images
|
||||
|
|
48
docs/kpod-exec.1.md
Normal file
48
docs/kpod-exec.1.md
Normal file
|
@ -0,0 +1,48 @@
|
|||
% kpod(1) kpod-exec - Run a command in a running container
|
||||
% Brent Baude
|
||||
# kpod-exec "1" "October 2017" "kpod"
|
||||
|
||||
## NAME
|
||||
kpod exec - Run a command in a running container
|
||||
|
||||
## SYNOPSIS
|
||||
**kpod exec [OPTIONS] CONTAINER COMMAND
|
||||
|
||||
## DESCRIPTION
|
||||
Run a command in a running container. The command will only run while the container's primary process (PID 1) is running.
|
||||
restarted if the container is restarted.
|
||||
|
||||
## OPTIONS
|
||||
|
||||
**--detach, -d**
|
||||
|
||||
Detached mode: run the command in the background.
|
||||
|
||||
**--env, -e**
|
||||
|
||||
Set one or environment variables for the container environment.
|
||||
|
||||
**--tty, -t**
|
||||
|
||||
Allocate a pseudo-TTY.
|
||||
|
||||
**--user, -u**
|
||||
|
||||
Sets the username or UID used and optionally the groupname or GID for the specified command. The format is *uid:gid*.
|
||||
|
||||
|
||||
## EXAMPLE
|
||||
|
||||
kpod exec mywebserver ls
|
||||
|
||||
kpod exec 860a4b23 ls
|
||||
|
||||
kpod exec -e FOO=bar -e BAR=foo 860a4b23 ls
|
||||
|
||||
kpod exec -u foo:users mywebserver ls
|
||||
|
||||
## SEE ALSO
|
||||
kpod(1)
|
||||
|
||||
## HISTORY
|
||||
October 2017, Originally compiled by Brent Baude <bbaude@redhat.com>
|
|
@ -32,4 +32,4 @@ kpod stop --timeout 2 860a4b23
|
|||
kpod(1), kpod-rm(1)
|
||||
|
||||
## HISTORY
|
||||
September 2018, Originally compiled by Brent Baude <bbaude@redhat.com>
|
||||
September 2017, Originally compiled by Brent Baude <bbaude@redhat.com>
|
||||
|
|
29
libkpod/exec.go
Normal file
29
libkpod/exec.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package libkpod
|
||||
|
||||
import (
|
||||
"github.com/kubernetes-incubator/cri-o/oci"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ContainerExec runs a command in a running container
|
||||
func (c *ContainerServer) ContainerExec(container string, command []string, detach bool, environmentVars []string, tty bool, user string) error {
|
||||
ctr, err := c.LookupContainer(container)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to find container %s", container)
|
||||
}
|
||||
ctrID := ctr.ID()
|
||||
|
||||
cStatus := c.runtime.ContainerStatus(ctr)
|
||||
switch cStatus.Status {
|
||||
case oci.ContainerStatePaused:
|
||||
return errors.Errorf("cannot run a command in a paused container %s", ctrID)
|
||||
case oci.ContainerStateRunning:
|
||||
if err := c.runtime.ExecContainerCommand(ctr, command, detach, environmentVars, tty, user); err != nil {
|
||||
return errors.Wrapf(err, "failed to exec command in container %s", ctrID)
|
||||
}
|
||||
default:
|
||||
return errors.Errorf("container %s is not running", ctrID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
27
oci/oci.go
27
oci/oci.go
|
@ -724,3 +724,30 @@ func (r *Runtime) UnpauseContainer(c *Container) error {
|
|||
_, err := utils.ExecCmd(r.Path(c), "resume", c.id)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecContainerCommand runs a command inside a running container
|
||||
func (r *Runtime) ExecContainerCommand(c *Container, command []string, detach bool, environmentVars []string, tty bool, user string) error {
|
||||
//var args []string
|
||||
commandArgs := []string{"exec"}
|
||||
if tty {
|
||||
commandArgs = append(commandArgs, "-t")
|
||||
}
|
||||
if detach {
|
||||
commandArgs = append(commandArgs, "-d")
|
||||
}
|
||||
for _, envVar := range environmentVars {
|
||||
commandArgs = append(commandArgs, "-e", envVar)
|
||||
}
|
||||
if user != "" {
|
||||
commandArgs = append(commandArgs, "-u", user)
|
||||
}
|
||||
commandArgs = append(commandArgs, c.id)
|
||||
commandArgs = append(commandArgs, command...)
|
||||
logrus.Debug("Running command: %s", strings.Join(commandArgs, " "))
|
||||
c.opLock.Lock()
|
||||
defer c.opLock.Unlock()
|
||||
err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.Path(c), commandArgs...)
|
||||
return err
|
||||
return nil
|
||||
|
||||
}
|
||||
|
|
78
test/kpod_exec.bats
Normal file
78
test/kpod_exec.bats
Normal file
|
@ -0,0 +1,78 @@
|
|||
#!/usr/bin/env bats
|
||||
|
||||
load helpers
|
||||
|
||||
IMAGE="redis:alpine"
|
||||
|
||||
function teardown() {
|
||||
cleanup_test
|
||||
}
|
||||
|
||||
@test "exec on a bogus container" {
|
||||
run ${KPOD_BINARY} ${KPOD_OPTIONS} exec foobar ls
|
||||
echo "$output"
|
||||
[ "$status" -eq 1 ]
|
||||
}
|
||||
|
||||
@test "Run a simple command" {
|
||||
start_crio
|
||||
run crioctl pod run --config "$TESTDATA"/sandbox_config.json
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
pod_id="$output"
|
||||
run crioctl image pull "$IMAGE"
|
||||
[ "$status" -eq 0 ]
|
||||
run crioctl ctr create --config "$TESTDATA"/container_redis.json --pod "$pod_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
ctr_id="$output"
|
||||
run crioctl ctr start --id "$ctr_id"
|
||||
echo "$output"
|
||||
run ${KPOD_BINARY} ${KPOD_OPTIONS} exec "$ctr_id" ls
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
cleanup_pods
|
||||
stop_crio
|
||||
}
|
||||
|
||||
# Disabled until runc is fixed upstream to handle
|
||||
# longer and more complicated command sequences.
|
||||
#@test "Check for environment variable" {
|
||||
# start_crio
|
||||
# run crioctl pod run --config "$TESTDATA"/sandbox_config.json
|
||||
# echo "$output"
|
||||
# [ "$status" -eq 0 ]
|
||||
# pod_id="$output"
|
||||
# run crioctl image pull "$IMAGE"
|
||||
# [ "$status" -eq 0 ]
|
||||
# run crioctl ctr create --config "$TESTDATA"/container_redis.json --pod "$pod_id"
|
||||
# echo "$output"
|
||||
# [ "$status" -eq 0 ]
|
||||
# ctr_id="$output"
|
||||
# run crioctl ctr start --id "$ctr_id"
|
||||
# echo "$output"
|
||||
# run ${KPOD_BINARY} ${KPOD_OPTIONS} exec -e FOO=bar "$ctr_id" env | grep FOO
|
||||
# echo "$output"
|
||||
# [ "$status" -eq 0 ]
|
||||
# cleanup_pods
|
||||
# stop_crio
|
||||
#}
|
||||
|
||||
@test "Execute command in a non-running container" {
|
||||
start_crio
|
||||
run crioctl pod run --config "$TESTDATA"/sandbox_config.json
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
pod_id="$output"
|
||||
run crioctl image pull "$IMAGE"
|
||||
[ "$status" -eq 0 ]
|
||||
run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id"
|
||||
echo "$output"
|
||||
[ "$status" -eq 0 ]
|
||||
ctr_id="$output"
|
||||
run ${KPOD_BINARY} ${KPOD_OPTIONS} exec ls
|
||||
echo "$output"
|
||||
[ "$status" -eq 1 ]
|
||||
cleanup_pods
|
||||
stop_crio
|
||||
}
|
|
@ -24,7 +24,6 @@ Following provides equivalent with cri-o tools for gathering information or jump
|
|||
|
||||
| Existing Step | CRI-O (and friends) |
|
||||
| :---: | :---: |
|
||||
| `docker exec` | [`crioctl ctr exec`](./docs/crio.8.md) |
|
||||
| `docker info` | [`kpod info`](./docs/kpod-info.1.md) |
|
||||
| `docker inspect` | [`kpod inspect`](./docs/kpod-inspect.1.md) |
|
||||
| `docker logs` | [`kpod logs`](./docs/kpod-logs.1.md) |
|
||||
|
@ -43,6 +42,7 @@ There are other equivalents for these tools
|
|||
| `docker build` | [`buildah bud`](https://github.com/projectatomic/buildah/blob/master/docs/buildah-bud.md) |
|
||||
| `docker cp` | [`kpod mount`](./docs/kpod-cp.1.md) **** |
|
||||
| `docker diff` | [`kpod diff`](./docs/kpod-diff.1.md) |
|
||||
| `docker exec` | [`kpod exec`](./docs/kpod-exec.1.md) |
|
||||
| `docker export` | [`kpod export`](./docs/kpod-export.1.md) |
|
||||
| `docker history`| [`kpod history`](./docs/kpod-history.1.md)|
|
||||
| `docker images` | [`kpod images`](./docs/kpod-images.1.md) |
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue