mirror of
https://github.com/containers/podman.git
synced 2025-06-23 02:18:13 +08:00
Merge pull request #1528 from baude/runlabel
Add container runlabel command
This commit is contained in:
@ -25,6 +25,7 @@ var (
|
||||
restartCommand,
|
||||
rmCommand,
|
||||
runCommand,
|
||||
runlabelCommand,
|
||||
startCommand,
|
||||
statsCommand,
|
||||
stopCommand,
|
||||
|
188
cmd/podman/runlabel.go
Normal file
188
cmd/podman/runlabel.go
Normal file
@ -0,0 +1,188 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||
"github.com/containers/libpod/cmd/podman/shared"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
"github.com/containers/libpod/utils"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
runlabelFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "authfile",
|
||||
Usage: "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "display",
|
||||
Usage: "preview the command that `podman install` would execute",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "cert-dir",
|
||||
Usage: "`pathname` of a directory containing TLS certificates and keys",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "creds",
|
||||
Usage: "`credentials` (USERNAME:PASSWORD) to use for authenticating to a registry",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "Assign a name to the container",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "opt1",
|
||||
Usage: "Optional parameter to pass for install",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "opt2",
|
||||
Usage: "Optional parameter to pass for install",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "opt3",
|
||||
Usage: "Optional parameter to pass for install",
|
||||
Hidden: true,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Suppress output information when installing images",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "pull, p",
|
||||
Usage: "pull the image if it does not exist locally prior to executing the label contents",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "signature-policy",
|
||||
Usage: "`pathname` of signature policy file (not usually used)",
|
||||
},
|
||||
cli.BoolTFlag{
|
||||
Name: "tls-verify",
|
||||
Usage: "require HTTPS and verify certificates when contacting registries (default: true)",
|
||||
},
|
||||
}
|
||||
|
||||
runlabelDescription = `
|
||||
Executes a command as described by a container image label.
|
||||
`
|
||||
runlabelCommand = cli.Command{
|
||||
Name: "runlabel",
|
||||
Usage: "Execute the command described by an image label",
|
||||
Description: runlabelDescription,
|
||||
Flags: runlabelFlags,
|
||||
Action: runlabelCmd,
|
||||
ArgsUsage: "",
|
||||
OnUsageError: usageErrorHandler,
|
||||
}
|
||||
)
|
||||
|
||||
// installCmd gets the data from the command line and calls installImage
|
||||
// to copy an image from a registry to a local machine
|
||||
func runlabelCmd(c *cli.Context) error {
|
||||
var (
|
||||
imageName string
|
||||
stdErr, stdOut io.Writer
|
||||
stdIn io.Reader
|
||||
newImage *image.Image
|
||||
)
|
||||
|
||||
opts := make(map[string]string)
|
||||
runtime, err := libpodruntime.GetRuntime(c)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could not get runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
args := c.Args()
|
||||
if len(args) == 0 {
|
||||
logrus.Errorf("an image name must be specified")
|
||||
return nil
|
||||
}
|
||||
if len(args) < 2 {
|
||||
logrus.Errorf("the runlabel command requires at least 2 arguments")
|
||||
return nil
|
||||
}
|
||||
if err := validateFlags(c, runlabelFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
if c.Bool("display") && c.Bool("quiet") {
|
||||
return errors.Errorf("the display and quiet flags cannot be used together.")
|
||||
}
|
||||
|
||||
pull := c.Bool("pull")
|
||||
label := args[0]
|
||||
|
||||
runlabelImage := args[1]
|
||||
|
||||
if c.IsSet("opts1") {
|
||||
opts["opts1"] = c.String("opts1")
|
||||
}
|
||||
if c.IsSet("opts2") {
|
||||
opts["opts2"] = c.String("opts2")
|
||||
}
|
||||
if c.IsSet("opts3") {
|
||||
opts["opts3"] = c.String("opts3")
|
||||
}
|
||||
|
||||
ctx := getContext()
|
||||
rtc := runtime.GetConfig()
|
||||
|
||||
stdErr = os.Stderr
|
||||
stdOut = os.Stdout
|
||||
stdIn = os.Stdin
|
||||
|
||||
if c.Bool("quiet") {
|
||||
stdErr = nil
|
||||
stdOut = nil
|
||||
stdIn = nil
|
||||
}
|
||||
|
||||
if pull {
|
||||
newImage, err = runtime.ImageRuntime().New(ctx, runlabelImage, rtc.SignaturePolicyPath, "", stdOut, nil, image.SigningOptions{}, false, false)
|
||||
} else {
|
||||
newImage, err = runtime.ImageRuntime().NewFromLocal(runlabelImage)
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "unable to find image")
|
||||
}
|
||||
|
||||
if len(newImage.Names()) < 1 {
|
||||
imageName = newImage.ID()
|
||||
} else {
|
||||
imageName = newImage.Names()[0]
|
||||
}
|
||||
|
||||
runLabel, err := newImage.GetLabel(ctx, label)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If no label to execute, we return
|
||||
if runLabel == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// The user provided extra arguments that need to be tacked onto the label's command
|
||||
if len(args) > 2 {
|
||||
runLabel = fmt.Sprintf("%s %s", runLabel, strings.Join(args[2:], " "))
|
||||
}
|
||||
|
||||
cmd := shared.GenerateCommand(runLabel, imageName, c.String("name"))
|
||||
env := shared.GenerateRunEnvironment(c.String("name"), imageName, opts)
|
||||
|
||||
if !c.Bool("quiet") {
|
||||
fmt.Printf("Command: %s\n", strings.Join(cmd, " "))
|
||||
if c.Bool("display") {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return utils.ExecCmdWithStdStreams(stdIn, stdOut, stdErr, env, cmd[0], cmd[1:]...)
|
||||
}
|
57
cmd/podman/shared/funcs.go
Normal file
57
cmd/podman/shared/funcs.go
Normal file
@ -0,0 +1,57 @@
|
||||
package shared
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GenerateCommand takes a label (string) and converts it to an executable command
|
||||
func GenerateCommand(command, imageName, name string) []string {
|
||||
var (
|
||||
newCommand []string
|
||||
)
|
||||
if name == "" {
|
||||
name = imageName
|
||||
}
|
||||
cmd := strings.Split(command, " ")
|
||||
// Replace the first position of cmd with podman whether
|
||||
// it is docker, /usr/bin/docker, or podman
|
||||
newCommand = append(newCommand, "podman")
|
||||
for _, arg := range cmd[1:] {
|
||||
var newArg string
|
||||
switch arg {
|
||||
case "IMAGE":
|
||||
newArg = imageName
|
||||
case "IMAGE=IMAGE":
|
||||
newArg = fmt.Sprintf("IMAGE=%s", imageName)
|
||||
case "NAME":
|
||||
newArg = name
|
||||
case "NAME=NAME":
|
||||
newArg = fmt.Sprintf("NAME=%s", name)
|
||||
default:
|
||||
newArg = arg
|
||||
}
|
||||
newCommand = append(newCommand, newArg)
|
||||
}
|
||||
return newCommand
|
||||
}
|
||||
|
||||
// GenerateRunEnvironment merges the current environment variables with optional
|
||||
// environment variables provided by the user
|
||||
func GenerateRunEnvironment(name, imageName string, opts map[string]string) []string {
|
||||
newEnv := os.Environ()
|
||||
newEnv = append(newEnv, fmt.Sprintf("NAME=%s", name))
|
||||
newEnv = append(newEnv, fmt.Sprintf("IMAGE=%s", imageName))
|
||||
|
||||
if opts["opt1"] != "" {
|
||||
newEnv = append(newEnv, fmt.Sprintf("OPT1=%s", opts["opt1"]))
|
||||
}
|
||||
if opts["opt2"] != "" {
|
||||
newEnv = append(newEnv, fmt.Sprintf("OPT2=%s", opts["opt2"]))
|
||||
}
|
||||
if opts["opt3"] != "" {
|
||||
newEnv = append(newEnv, fmt.Sprintf("OPT3=%s", opts["opt3"]))
|
||||
}
|
||||
return newEnv
|
||||
}
|
89
cmd/podman/shared/funcs_test.go
Normal file
89
cmd/podman/shared/funcs_test.go
Normal file
@ -0,0 +1,89 @@
|
||||
package shared
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/containers/libpod/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
name = "foo"
|
||||
imageName = "bar"
|
||||
)
|
||||
|
||||
func TestGenerateCommand(t *testing.T) {
|
||||
inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
|
||||
correctCommand := "podman run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
|
||||
newCommand := GenerateCommand(inputCommand, "foo", "bar")
|
||||
assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
|
||||
}
|
||||
|
||||
func TestGenerateCommandPath(t *testing.T) {
|
||||
inputCommand := "/usr/bin/docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
|
||||
correctCommand := "podman run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
|
||||
newCommand := GenerateCommand(inputCommand, "foo", "bar")
|
||||
assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
|
||||
}
|
||||
|
||||
func TestGenerateCommandNoSetName(t *testing.T) {
|
||||
inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
|
||||
correctCommand := "podman run -it --name foo -e NAME=foo -e IMAGE=foo foo echo install"
|
||||
newCommand := GenerateCommand(inputCommand, "foo", "")
|
||||
assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
|
||||
}
|
||||
|
||||
func TestGenerateCommandNoName(t *testing.T) {
|
||||
inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install"
|
||||
correctCommand := "podman run -it -e IMAGE=foo foo echo install"
|
||||
newCommand := GenerateCommand(inputCommand, "foo", "")
|
||||
assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
|
||||
}
|
||||
|
||||
func TestGenerateCommandAlreadyPodman(t *testing.T) {
|
||||
inputCommand := "podman run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
|
||||
correctCommand := "podman run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
|
||||
newCommand := GenerateCommand(inputCommand, "foo", "bar")
|
||||
assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
|
||||
}
|
||||
|
||||
func TestGenerateRunEnvironment(t *testing.T) {
|
||||
opts := make(map[string]string)
|
||||
opts["opt1"] = "one"
|
||||
opts["opt2"] = "two"
|
||||
opts["opt3"] = "three"
|
||||
envs := GenerateRunEnvironment(name, imageName, opts)
|
||||
assert.True(t, util.StringInSlice("OPT1=one", envs))
|
||||
assert.True(t, util.StringInSlice("OPT2=two", envs))
|
||||
assert.True(t, util.StringInSlice("OPT3=three", envs))
|
||||
}
|
||||
|
||||
func TestGenerateRunEnvironmentNoOpts(t *testing.T) {
|
||||
opts := make(map[string]string)
|
||||
envs := GenerateRunEnvironment(name, imageName, opts)
|
||||
assert.False(t, util.StringInSlice("OPT1=", envs))
|
||||
assert.False(t, util.StringInSlice("OPT2=", envs))
|
||||
assert.False(t, util.StringInSlice("OPT3=", envs))
|
||||
}
|
||||
|
||||
func TestGenerateRunEnvironmentSingleOpt(t *testing.T) {
|
||||
opts := make(map[string]string)
|
||||
opts["opt1"] = "one"
|
||||
envs := GenerateRunEnvironment(name, imageName, opts)
|
||||
assert.True(t, util.StringInSlice("OPT1=one", envs))
|
||||
assert.False(t, util.StringInSlice("OPT2=", envs))
|
||||
assert.False(t, util.StringInSlice("OPT3=", envs))
|
||||
}
|
||||
|
||||
func TestGenerateRunEnvironmentName(t *testing.T) {
|
||||
opts := make(map[string]string)
|
||||
envs := GenerateRunEnvironment(name, imageName, opts)
|
||||
assert.True(t, util.StringInSlice("NAME=foo", envs))
|
||||
}
|
||||
|
||||
func TestGenerateRunEnvironmentImage(t *testing.T) {
|
||||
opts := make(map[string]string)
|
||||
envs := GenerateRunEnvironment(name, imageName, opts)
|
||||
assert.True(t, util.StringInSlice("IMAGE=bar", envs))
|
||||
}
|
@ -50,6 +50,7 @@
|
||||
| [podman-rm(1)](/docs/podman-rm.1.md) | Removes one or more containers |[](https://asciinema.org/a/7EMk22WrfGtKWmgHJX9Nze1Qp)|
|
||||
| [podman-rmi(1)](/docs/podman-rmi.1.md) | Removes one or more images |[](https://asciinema.org/a/133799)|
|
||||
| [podman-run(1)](/docs/podman-run.1.md) | Run a command in a container ||
|
||||
| [podman-runlabel(1)](/docs/podman-container-runlabel.1.md) | Executes the command of a container image's label ||
|
||||
| [podman-save(1)](/docs/podman-save.1.md) | Saves an image to an archive |[](https://asciinema.org/a/kp8kOaexEhEa20P1KLZ3L5X4g)|
|
||||
| [podman-search(1)](/docs/podman-search.1.md) | Search a registry for an image ||
|
||||
| [podman-start(1)](/docs/podman-start.1.md) | Starts one or more containers
|
||||
|
@ -2086,6 +2086,36 @@ _podman_logout() {
|
||||
_complete_ "$options_with_args" "$boolean_options"
|
||||
}
|
||||
|
||||
_podman_container_runlabel() {
|
||||
local options_with_args="
|
||||
--authfile
|
||||
--cert-dir
|
||||
--creds
|
||||
--name
|
||||
--signature-policy
|
||||
"
|
||||
|
||||
local boolean_options="
|
||||
--display
|
||||
--help
|
||||
-h
|
||||
-p
|
||||
--pull
|
||||
-q
|
||||
--quiet
|
||||
--tls-verify
|
||||
"
|
||||
|
||||
case "$cur" in
|
||||
-*)
|
||||
COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
|
||||
;;
|
||||
*)
|
||||
__podman_complete_images --id
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_podman_pod_create() {
|
||||
local options_with_args="
|
||||
--cgroup-parent
|
||||
|
102
docs/podman-container-runlabel.1.md
Normal file
102
docs/podman-container-runlabel.1.md
Normal file
@ -0,0 +1,102 @@
|
||||
% PODMAN(1) Podman Man Pages
|
||||
% Brent Baude
|
||||
% September 2018
|
||||
# NAME
|
||||
podman-container-runlabel - Execute Image Label Method
|
||||
|
||||
# SYNOPSIS
|
||||
**podman container runlabel**
|
||||
[**-h**|**--help**]
|
||||
[**--display**]
|
||||
[**-n**][**--name**[=*NAME*]]
|
||||
[**-p**][[**--pull**]]
|
||||
[**--rootfs**=*ROOTFS*]
|
||||
[**--set**=*NAME*=*VALUE*]
|
||||
[**--storage**]
|
||||
LABEL IMAGE [ARG...]
|
||||
|
||||
# DESCRIPTION
|
||||
**podman container runlabel** reads the provided `LABEL` field in the container
|
||||
IMAGE and executes the provided value for the label as a command. If this field does not
|
||||
exist, `podman container runlabel` will just exit.
|
||||
|
||||
If the container image has a LABEL INSTALL instruction like the following:
|
||||
|
||||
`LABEL INSTALL /usr/bin/podman run -t -i --rm \${OPT1} --privileged -v /:/host --net=host --ipc=host --pid=host -e HOST=/host -e NAME=\${NAME} -e IMAGE=\${IMAGE} -e CONFDIR=\/etc/${NAME} -e LOGDIR=/var/log/\${NAME} -e DATADIR=/var/lib/\${NAME} \${IMAGE} \${OPT2} /bin/install.sh \${OPT3}`
|
||||
|
||||
`podman container runlabel` will set the following environment variables for use in the command:
|
||||
|
||||
Note: Podman will always ensure that `podman` is the first argument of the command being executed.
|
||||
|
||||
**NAME**
|
||||
The name specified via the command. NAME will be replaced with IMAGE if it is not specified.
|
||||
|
||||
**IMAGE**
|
||||
Image name specified via the command.
|
||||
|
||||
**SUDO_UID**
|
||||
The `SUDO_UID` environment variable. This is useful with the podman
|
||||
`-u` option for user space tools. If the environment variable is
|
||||
not available, the value of `/proc/self/loginuid` is used.
|
||||
|
||||
**SUDO_GID**
|
||||
The `SUDO_GID` environment variable. This is useful with the podman
|
||||
`-u` option for user space tools. If the environment variable is
|
||||
not available, the default GID of the value for `SUDO_UID` is used.
|
||||
If this value is not available, the value of `/proc/self/loginuid`
|
||||
is used.
|
||||
|
||||
Any additional arguments will be appended to the command.
|
||||
|
||||
# OPTIONS:
|
||||
**--authfile**
|
||||
|
||||
Path of the authentication file. Default is ${XDG_RUNTIME\_DIR}/containers/auth.json, which is set using `podman login`.
|
||||
If the authorization state is not found there, $HOME/.docker/config.json is checked, which is set using `docker login`.
|
||||
|
||||
**--display**
|
||||
|
||||
Display the label's value of the image having populated its environment variables.
|
||||
The runlabel command will not execute if --display is specified.
|
||||
|
||||
**--cert-dir** *path*
|
||||
|
||||
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry.
|
||||
Default certificates directory is _/etc/containers/certs.d_.
|
||||
|
||||
**--creds**
|
||||
|
||||
The [username[:password]] to use to authenticate with the registry if required.
|
||||
If one or both values are not supplied, a command line prompt will appear and the
|
||||
value can be entered. The password is entered without echo.
|
||||
|
||||
**-h** **--help**
|
||||
Print usage statement
|
||||
|
||||
**-n** **--name**=""
|
||||
Use this name for creating content for the container. NAME will default to the IMAGENAME if it is not specified.
|
||||
|
||||
**p** **--pull**
|
||||
Pull the image if it cannot be found in local storage.
|
||||
|
||||
**--quiet, -q**
|
||||
|
||||
Suppress output information when pulling images
|
||||
|
||||
**--signature-policy="PATHNAME"**
|
||||
|
||||
Pathname of a signature policy file to use. It is not recommended that this
|
||||
option be used, as the default behavior of using the system-wide default policy
|
||||
(frequently */etc/containers/policy.json*) is most often preferred
|
||||
|
||||
**--tls-verify**
|
||||
|
||||
Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
|
||||
then tls verification will be used, If set to false then tls verification will not be used. If not specified
|
||||
tls verification will be used unless the target registry is listed as an insecure registry in registries.conf
|
||||
|
||||
## SEE ALSO
|
||||
podman(1)
|
||||
|
||||
# HISTORY
|
||||
September 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)
|
@ -744,6 +744,20 @@ func (i *Image) Labels(ctx context.Context) (map[string]string, error) {
|
||||
return imgInspect.Labels, nil
|
||||
}
|
||||
|
||||
// GetLabel Returns a case-insensitive match of a given label
|
||||
func (i *Image) GetLabel(ctx context.Context, label string) (string, error) {
|
||||
imageLabels, err := i.Labels(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for k, v := range imageLabels {
|
||||
if strings.ToLower(k) == strings.ToLower(label) {
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// Annotations returns the annotations of an image
|
||||
func (i *Image) Annotations(ctx context.Context) (map[string]string, error) {
|
||||
manifest, manifestType, err := i.Manifest(ctx)
|
||||
|
@ -535,7 +535,7 @@ func (r *OCIRuntime) updateContainerStatus(ctr *Container) error {
|
||||
// Sets time the container was started, but does not save it.
|
||||
func (r *OCIRuntime) startContainer(ctr *Container) error {
|
||||
// TODO: streams should probably *not* be our STDIN/OUT/ERR - redirect to buffers?
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "start", ctr.ID()); err != nil {
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, "start", ctr.ID()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -547,7 +547,7 @@ func (r *OCIRuntime) startContainer(ctr *Container) error {
|
||||
// killContainer sends the given signal to the given container
|
||||
func (r *OCIRuntime) killContainer(ctr *Container, signal uint) error {
|
||||
logrus.Debugf("Sending signal %d to container %s", signal, ctr.ID())
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "kill", ctr.ID(), fmt.Sprintf("%d", signal)); err != nil {
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, "kill", ctr.ID(), fmt.Sprintf("%d", signal)); err != nil {
|
||||
return errors.Wrapf(err, "error sending signal to container %s", ctr.ID())
|
||||
}
|
||||
|
||||
@ -605,7 +605,7 @@ func (r *OCIRuntime) stopContainer(ctr *Container, timeout uint) error {
|
||||
args = []string{"kill", "--all", ctr.ID(), "KILL"}
|
||||
}
|
||||
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, args...); err != nil {
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, args...); err != nil {
|
||||
// Again, check if the container is gone. If it is, exit cleanly.
|
||||
err := unix.Kill(ctr.state.PID, 0)
|
||||
if err == unix.ESRCH {
|
||||
@ -631,12 +631,12 @@ func (r *OCIRuntime) deleteContainer(ctr *Container) error {
|
||||
|
||||
// pauseContainer pauses the given container
|
||||
func (r *OCIRuntime) pauseContainer(ctr *Container) error {
|
||||
return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "pause", ctr.ID())
|
||||
return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, "pause", ctr.ID())
|
||||
}
|
||||
|
||||
// unpauseContainer unpauses the given container
|
||||
func (r *OCIRuntime) unpauseContainer(ctr *Container) error {
|
||||
return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "resume", ctr.ID())
|
||||
return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, "resume", ctr.ID())
|
||||
}
|
||||
|
||||
// execContainer executes a command in a running container
|
||||
@ -740,7 +740,7 @@ func (r *OCIRuntime) execStopContainer(ctr *Container, timeout uint) error {
|
||||
// Stop using SIGTERM by default
|
||||
// Use SIGSTOP after a timeout
|
||||
logrus.Debugf("Killing all processes in container %s with SIGTERM", ctr.ID())
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "kill", "--all", ctr.ID(), "TERM"); err != nil {
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, "kill", "--all", ctr.ID(), "TERM"); err != nil {
|
||||
return errors.Wrapf(err, "error sending SIGTERM to container %s processes", ctr.ID())
|
||||
}
|
||||
|
||||
@ -755,7 +755,7 @@ func (r *OCIRuntime) execStopContainer(ctr *Container, timeout uint) error {
|
||||
|
||||
// Send SIGKILL
|
||||
logrus.Debugf("Killing all processes in container %s with SIGKILL", ctr.ID())
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, r.path, "kill", "--all", ctr.ID(), "KILL"); err != nil {
|
||||
if err := utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, "kill", "--all", ctr.ID(), "KILL"); err != nil {
|
||||
return errors.Wrapf(err, "error sending SIGKILL to container %s processes", ctr.ID())
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ var (
|
||||
CGROUP_MANAGER = "systemd"
|
||||
STORAGE_OPTIONS = "--storage-driver vfs"
|
||||
ARTIFACT_DIR = "/tmp/.artifacts"
|
||||
CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, nginx, redis, registry, infra}
|
||||
CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, nginx, redis, registry, infra, labels}
|
||||
RESTORE_IMAGES = []string{ALPINE, BB}
|
||||
ALPINE = "docker.io/library/alpine:latest"
|
||||
BB = "docker.io/library/busybox:latest"
|
||||
@ -41,6 +41,7 @@ var (
|
||||
redis = "docker.io/library/redis:alpine"
|
||||
registry = "docker.io/library/registry:2"
|
||||
infra = "k8s.gcr.io/pause:3.1"
|
||||
labels = "quay.io/baude/alpine_labels:latest"
|
||||
defaultWaitTimeout = 90
|
||||
)
|
||||
|
||||
|
@ -29,11 +29,14 @@ func ExecCmd(name string, args ...string) (string, error) {
|
||||
}
|
||||
|
||||
// ExecCmdWithStdStreams execute a command with the specified standard streams.
|
||||
func ExecCmdWithStdStreams(stdin io.Reader, stdout, stderr io.Writer, name string, args ...string) error {
|
||||
func ExecCmdWithStdStreams(stdin io.Reader, stdout, stderr io.Writer, env []string, name string, args ...string) error {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Stdin = stdin
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = stderr
|
||||
if env != nil {
|
||||
cmd.Env = env
|
||||
}
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user