mirror of
https://github.com/containers/podman.git
synced 2025-06-28 14:29:04 +08:00
Add container runlabel command
Execute the command as described by a container image. The value of the label is processed into a command by: 1. Ensuring the first argument of the command is podman. 2. Substituting any variables with those defined by the environment or otherwise. If no label exists in the container image, nothing is done. podman container runlabel LABEL IMAGE extra_args Signed-off-by: baude <bbaude@redhat.com>
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
|
||||
|
@ -2084,6 +2084,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