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,
|
restartCommand,
|
||||||
rmCommand,
|
rmCommand,
|
||||||
runCommand,
|
runCommand,
|
||||||
|
runlabelCommand,
|
||||||
startCommand,
|
startCommand,
|
||||||
statsCommand,
|
statsCommand,
|
||||||
stopCommand,
|
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-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-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-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-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-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
|
| [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"
|
_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() {
|
_podman_pod_create() {
|
||||||
local options_with_args="
|
local options_with_args="
|
||||||
--cgroup-parent
|
--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
|
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
|
// Annotations returns the annotations of an image
|
||||||
func (i *Image) Annotations(ctx context.Context) (map[string]string, error) {
|
func (i *Image) Annotations(ctx context.Context) (map[string]string, error) {
|
||||||
manifest, manifestType, err := i.Manifest(ctx)
|
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.
|
// Sets time the container was started, but does not save it.
|
||||||
func (r *OCIRuntime) startContainer(ctr *Container) error {
|
func (r *OCIRuntime) startContainer(ctr *Container) error {
|
||||||
// TODO: streams should probably *not* be our STDIN/OUT/ERR - redirect to buffers?
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +547,7 @@ func (r *OCIRuntime) startContainer(ctr *Container) error {
|
|||||||
// killContainer sends the given signal to the given container
|
// killContainer sends the given signal to the given container
|
||||||
func (r *OCIRuntime) killContainer(ctr *Container, signal uint) error {
|
func (r *OCIRuntime) killContainer(ctr *Container, signal uint) error {
|
||||||
logrus.Debugf("Sending signal %d to container %s", signal, ctr.ID())
|
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())
|
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"}
|
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.
|
// Again, check if the container is gone. If it is, exit cleanly.
|
||||||
err := unix.Kill(ctr.state.PID, 0)
|
err := unix.Kill(ctr.state.PID, 0)
|
||||||
if err == unix.ESRCH {
|
if err == unix.ESRCH {
|
||||||
@ -631,12 +631,12 @@ func (r *OCIRuntime) deleteContainer(ctr *Container) error {
|
|||||||
|
|
||||||
// pauseContainer pauses the given container
|
// pauseContainer pauses the given container
|
||||||
func (r *OCIRuntime) pauseContainer(ctr *Container) error {
|
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
|
// unpauseContainer unpauses the given container
|
||||||
func (r *OCIRuntime) unpauseContainer(ctr *Container) error {
|
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
|
// 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
|
// Stop using SIGTERM by default
|
||||||
// Use SIGSTOP after a timeout
|
// Use SIGSTOP after a timeout
|
||||||
logrus.Debugf("Killing all processes in container %s with SIGTERM", ctr.ID())
|
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())
|
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
|
// Send SIGKILL
|
||||||
logrus.Debugf("Killing all processes in container %s with SIGKILL", ctr.ID())
|
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())
|
return errors.Wrapf(err, "error sending SIGKILL to container %s processes", ctr.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ var (
|
|||||||
CGROUP_MANAGER = "systemd"
|
CGROUP_MANAGER = "systemd"
|
||||||
STORAGE_OPTIONS = "--storage-driver vfs"
|
STORAGE_OPTIONS = "--storage-driver vfs"
|
||||||
ARTIFACT_DIR = "/tmp/.artifacts"
|
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}
|
RESTORE_IMAGES = []string{ALPINE, BB}
|
||||||
ALPINE = "docker.io/library/alpine:latest"
|
ALPINE = "docker.io/library/alpine:latest"
|
||||||
BB = "docker.io/library/busybox:latest"
|
BB = "docker.io/library/busybox:latest"
|
||||||
@ -41,6 +41,7 @@ var (
|
|||||||
redis = "docker.io/library/redis:alpine"
|
redis = "docker.io/library/redis:alpine"
|
||||||
registry = "docker.io/library/registry:2"
|
registry = "docker.io/library/registry:2"
|
||||||
infra = "k8s.gcr.io/pause:3.1"
|
infra = "k8s.gcr.io/pause:3.1"
|
||||||
|
labels = "quay.io/baude/alpine_labels:latest"
|
||||||
defaultWaitTimeout = 90
|
defaultWaitTimeout = 90
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,11 +29,14 @@ func ExecCmd(name string, args ...string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExecCmdWithStdStreams execute a command with the specified standard streams.
|
// 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 := exec.Command(name, args...)
|
||||||
cmd.Stdin = stdin
|
cmd.Stdin = stdin
|
||||||
cmd.Stdout = stdout
|
cmd.Stdout = stdout
|
||||||
cmd.Stderr = stderr
|
cmd.Stderr = stderr
|
||||||
|
if env != nil {
|
||||||
|
cmd.Env = env
|
||||||
|
}
|
||||||
|
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Reference in New Issue
Block a user