summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman/cleanup.go4
-rw-r--r--cmd/podman/container.go1
-rw-r--r--cmd/podman/create.go4
-rw-r--r--cmd/podman/kill.go64
-rw-r--r--cmd/podman/main.go5
-rw-r--r--cmd/podman/pod_stop.go4
-rw-r--r--cmd/podman/ps.go2
-rw-r--r--cmd/podman/run.go2
-rw-r--r--cmd/podman/runlabel.go188
-rw-r--r--cmd/podman/shared/funcs.go57
-rw-r--r--cmd/podman/shared/funcs_test.go89
-rw-r--r--cmd/podman/start.go7
-rw-r--r--cmd/podman/varlink/io.podman.varlink4
13 files changed, 406 insertions, 25 deletions
diff --git a/cmd/podman/cleanup.go b/cmd/podman/cleanup.go
index 6ebb682ed..316704f91 100644
--- a/cmd/podman/cleanup.go
+++ b/cmd/podman/cleanup.go
@@ -46,6 +46,8 @@ func cleanupCmd(c *cli.Context) error {
args := c.Args()
+ ctx := getContext()
+
var lastError error
var cleanupContainers []*libpod.Container
if c.Bool("all") {
@@ -80,7 +82,7 @@ func cleanupCmd(c *cli.Context) error {
}
}
for _, ctr := range cleanupContainers {
- if err = ctr.Cleanup(); err != nil {
+ if err = ctr.Cleanup(ctx); err != nil {
if lastError != nil {
fmt.Fprintln(os.Stderr, lastError)
}
diff --git a/cmd/podman/container.go b/cmd/podman/container.go
index b73fb7a94..82c1c824d 100644
--- a/cmd/podman/container.go
+++ b/cmd/podman/container.go
@@ -25,6 +25,7 @@ var (
restartCommand,
rmCommand,
runCommand,
+ runlabelCommand,
startCommand,
statsCommand,
stopCommand,
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index fc0c71536..574137271 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -784,7 +784,9 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
VolumesFrom: c.StringSlice("volumes-from"),
}
- if !config.Privileged {
+ if config.Privileged {
+ config.LabelOpts = label.DisableSecOpt()
+ } else {
if err := parseSecurityOpt(config, c.StringSlice("security-opt")); err != nil {
return nil, err
}
diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go
index f80d77b8f..db3300984 100644
--- a/cmd/podman/kill.go
+++ b/cmd/podman/kill.go
@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/docker/docker/pkg/signal"
"github.com/pkg/errors"
@@ -14,6 +15,10 @@ import (
var (
killFlags = []cli.Flag{
+ cli.BoolFlag{
+ Name: "all, a",
+ Usage: "Signal all running containers",
+ },
cli.StringFlag{
Name: "signal, s",
Usage: "Signal to send to the container",
@@ -28,7 +33,7 @@ var (
Description: killDescription,
Flags: killFlags,
Action: killCmd,
- ArgsUsage: "[CONTAINER_NAME_OR_ID]",
+ ArgsUsage: "CONTAINER-NAME [CONTAINER-NAME ...]",
UseShortOptionHandling: true,
OnUsageError: usageErrorHandler,
}
@@ -37,11 +42,17 @@ var (
// killCmd kills one or more containers with a signal
func killCmd(c *cli.Context) error {
args := c.Args()
- if len(args) == 0 && !c.Bool("latest") {
- return errors.Errorf("specify one or more containers to kill")
+ if (!c.Bool("all") && !c.Bool("latest")) && len(args) == 0 {
+ return errors.Errorf("you must specify one or more containers to kill")
+ }
+ if (c.Bool("all") || c.Bool("latest")) && len(args) > 0 {
+ return errors.Errorf("you cannot specify any containers to kill with --latest or --all")
+ }
+ if c.Bool("all") && c.Bool("latest") {
+ return errors.Errorf("--all and --latest cannot be used together")
}
- if len(args) > 0 && c.Bool("latest") {
- return errors.Errorf("you cannot specific any containers to kill with --latest")
+ if len(args) < 1 && !c.Bool("all") && !c.Bool("latest") {
+ return errors.Errorf("you must provide at least one container name or id")
}
if err := validateFlags(c, killFlags); err != nil {
return err
@@ -65,30 +76,45 @@ func killCmd(c *cli.Context) error {
killSignal = uint(sysSignal)
}
- if c.Bool("latest") {
- latestCtr, err := runtime.GetLatestContainer()
+ var filterFuncs []libpod.ContainerFilter
+ var containers []*libpod.Container
+ var lastError error
+ if c.Bool("all") {
+ // only get running containers
+ filterFuncs = append(filterFuncs, func(c *libpod.Container) bool {
+ state, _ := c.State()
+ return state == libpod.ContainerStateRunning
+ })
+ containers, err = runtime.GetContainers(filterFuncs...)
if err != nil {
- return errors.Wrapf(err, "unable to get latest container")
+ return errors.Wrapf(err, "unable to get running containers")
}
- args = append(args, latestCtr.ID())
- }
-
- var lastError error
- for _, container := range args {
- ctr, err := runtime.LookupContainer(container)
+ } else if c.Bool("latest") {
+ lastCtr, err := runtime.GetLatestContainer()
if err != nil {
- if lastError != nil {
- fmt.Fprintln(os.Stderr, lastError)
+ return errors.Wrapf(err, "unable to get last created container")
+ }
+ containers = append(containers, lastCtr)
+ } else {
+ for _, i := range args {
+ container, err := runtime.LookupContainer(i)
+ if err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "unable to find container %s", i)
+ continue
}
- lastError = errors.Wrapf(err, "unable to find container %v", container)
- continue
+ containers = append(containers, container)
}
+ }
+ for _, ctr := range containers {
if err := ctr.Kill(killSignal); err != nil {
if lastError != nil {
fmt.Fprintln(os.Stderr, lastError)
}
- lastError = errors.Wrapf(err, "unable to find container %v", container)
+ lastError = errors.Wrapf(err, "unable to find container %v", ctr.ID())
} else {
fmt.Println(ctr.ID())
}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 840650a3f..d4c8454a8 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -7,6 +7,7 @@ import (
"runtime/pprof"
"syscall"
+ "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/hooks"
_ "github.com/containers/libpod/pkg/hooks/0.1.0"
"github.com/containers/libpod/pkg/rootless"
@@ -109,6 +110,10 @@ func main() {
}
app.Before = func(c *cli.Context) error {
+ if err := libpod.SetXdgRuntimeDir(""); err != nil {
+ logrus.Errorf(err.Error())
+ os.Exit(1)
+ }
args := c.Args()
if args.Present() {
if _, notRequireRootless := cmdsNotRequiringRootless[args.First()]; !notRequireRootless {
diff --git a/cmd/podman/pod_stop.go b/cmd/podman/pod_stop.go
index 03d04a3ec..6dc6a2b2d 100644
--- a/cmd/podman/pod_stop.go
+++ b/cmd/podman/pod_stop.go
@@ -50,9 +50,11 @@ func podStopCmd(c *cli.Context) error {
// in which case the following loop will be skipped.
pods, lastError := getPodsFromContext(c, runtime)
+ ctx := getContext()
+
for _, pod := range pods {
// set cleanup to true to clean mounts and namespaces
- ctr_errs, err := pod.Stop(true)
+ ctr_errs, err := pod.Stop(ctx, true)
if ctr_errs != nil {
for ctr, err := range ctr_errs {
if lastError != nil {
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go
index d36c929e8..e53afe1bf 100644
--- a/cmd/podman/ps.go
+++ b/cmd/podman/ps.go
@@ -548,6 +548,8 @@ func getTemplateOutput(psParams []psJSONParams, opts shared.PsOptions) ([]psTemp
labels := formatLabels(psParam.Labels)
switch psParam.Status {
+ case libpod.ContainerStateExited.String():
+ fallthrough
case libpod.ContainerStateStopped.String():
exitedSince := units.HumanDuration(time.Since(psParam.ExitedAt))
status = fmt.Sprintf("Exited (%d) %s ago", psParam.ExitCode, exitedSince)
diff --git a/cmd/podman/run.go b/cmd/podman/run.go
index f9a96e4a6..fbad4237d 100644
--- a/cmd/podman/run.go
+++ b/cmd/podman/run.go
@@ -140,7 +140,7 @@ func runCmd(c *cli.Context) error {
return runtime.RemoveContainer(ctx, ctr, true)
}
- if err := ctr.Cleanup(); err != nil {
+ if err := ctr.Cleanup(ctx); err != nil {
// If the container has been removed already, no need to error on cleanup
// Also, if it was restarted, don't error either
if errors.Cause(err) == libpod.ErrNoSuchCtr ||
diff --git a/cmd/podman/runlabel.go b/cmd/podman/runlabel.go
new file mode 100644
index 000000000..c5dd98ee6
--- /dev/null
+++ b/cmd/podman/runlabel.go
@@ -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:]...)
+}
diff --git a/cmd/podman/shared/funcs.go b/cmd/podman/shared/funcs.go
new file mode 100644
index 000000000..5c401634c
--- /dev/null
+++ b/cmd/podman/shared/funcs.go
@@ -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
+}
diff --git a/cmd/podman/shared/funcs_test.go b/cmd/podman/shared/funcs_test.go
new file mode 100644
index 000000000..3d0ac005f
--- /dev/null
+++ b/cmd/podman/shared/funcs_test.go
@@ -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))
+}
diff --git a/cmd/podman/start.go b/cmd/podman/start.go
index cb65ec6d4..a34f6df5d 100644
--- a/cmd/podman/start.go
+++ b/cmd/podman/start.go
@@ -81,6 +81,9 @@ func startCmd(c *cli.Context) error {
}
args = append(args, lastCtr.ID())
}
+
+ ctx := getContext()
+
var lastError error
for _, container := range args {
ctr, err := runtime.LookupContainer(container)
@@ -121,14 +124,14 @@ func startCmd(c *cli.Context) error {
exitCode = int(ecode)
}
- return ctr.Cleanup()
+ return ctr.Cleanup(ctx)
}
if ctrRunning {
fmt.Println(ctr.ID())
continue
}
// Handle non-attach start
- if err := ctr.Start(getContext()); err != nil {
+ if err := ctr.Start(ctx); err != nil {
if lastError != nil {
fmt.Fprintln(os.Stderr, lastError)
}
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 810f757ca..4a4a1854c 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -820,6 +820,10 @@ error PodNotFound (name: string)
# a container ID of the container that failed.
error PodContainerError (podname: string, errors: []PodContainerErrorData)
+# NoContainersInPod means a pod has no containers on which to perform the operation. It contains
+# the pod ID.
+error NoContainersInPod (name: string)
+
# ErrorOccurred is a generic error for an error that occurs during the execution. The actual error message
# is includes as part of the error's text.
error ErrorOccurred (reason: string)