summaryrefslogtreecommitdiff
path: root/cmd/podman
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman')
-rw-r--r--cmd/podman/common.go4
-rw-r--r--cmd/podman/runlabel.go80
-rw-r--r--cmd/podman/shared/funcs.go4
-rw-r--r--cmd/podman/stop.go27
-rw-r--r--cmd/podman/utils.go48
5 files changed, 135 insertions, 28 deletions
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 9ab0e57e5..c1e15e2fb 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -249,6 +249,10 @@ var createFlags = []cli.Flag{
Usage: "Keep STDIN open even if not attached",
},
cli.StringFlag{
+ Name: "ip",
+ Usage: "Specify a static IPv4 address for the container",
+ },
+ cli.StringFlag{
Name: "ipc",
Usage: "IPC namespace to use",
},
diff --git a/cmd/podman/runlabel.go b/cmd/podman/runlabel.go
index 34e6b9093..d514a79fc 100644
--- a/cmd/podman/runlabel.go
+++ b/cmd/podman/runlabel.go
@@ -6,9 +6,11 @@ import (
"os"
"strings"
+ "github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/util"
"github.com/containers/libpod/utils"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -23,7 +25,7 @@ var (
},
cli.BoolFlag{
Name: "display",
- Usage: "preview the command that `podman install` would execute",
+ Usage: "preview the command that the label would run",
},
cli.StringFlag{
Name: "cert-dir",
@@ -74,13 +76,14 @@ var (
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,
+ Name: "runlabel",
+ Usage: "Execute the command described by an image label",
+ Description: runlabelDescription,
+ Flags: runlabelFlags,
+ Action: runlabelCmd,
+ ArgsUsage: "",
+ SkipArgReorder: true,
+ OnUsageError: usageErrorHandler,
}
)
@@ -110,12 +113,8 @@ func runlabelCmd(c *cli.Context) error {
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")
+ logrus.Errorf("the runlabel command requires at least 2 arguments: LABEL IMAGE")
return nil
}
if err := validateFlags(c, runlabelFlags); err != nil {
@@ -130,18 +129,17 @@ func runlabelCmd(c *cli.Context) error {
runlabelImage := args[1]
- if c.IsSet("opts1") {
- opts["opts1"] = c.String("opts1")
+ if c.IsSet("opt1") {
+ opts["opt1"] = c.String("opt1")
}
- if c.IsSet("opts2") {
- opts["opts2"] = c.String("opts2")
+ if c.IsSet("opt2") {
+ opts["opt2"] = c.String("opt2")
}
- if c.IsSet("opts3") {
- opts["opts3"] = c.String("opts3")
+ if c.IsSet("opt3") {
+ opts["opt3"] = c.String("opt3")
}
ctx := getContext()
- rtc := runtime.GetConfig()
stdErr = os.Stderr
stdOut = os.Stdout
@@ -154,7 +152,21 @@ func runlabelCmd(c *cli.Context) error {
}
if pull {
- newImage, err = runtime.ImageRuntime().New(ctx, runlabelImage, rtc.SignaturePolicyPath, "", stdOut, nil, image.SigningOptions{}, false, false)
+ var registryCreds *types.DockerAuthConfig
+ if c.IsSet("creds") {
+ creds, err := util.ParseRegistryCreds(c.String("creds"))
+ if err != nil {
+ return err
+ }
+ registryCreds = creds
+ }
+ dockerRegistryOptions := image.DockerRegistryOptions{
+ DockerRegistryCreds: registryCreds,
+ DockerCertPath: c.String("cert-dir"),
+ DockerInsecureSkipTLSVerify: !c.BoolT("tls-verify"),
+ }
+
+ newImage, err = runtime.ImageRuntime().New(ctx, runlabelImage, c.String("signature-policy"), c.String("authfile"), stdOut, &dockerRegistryOptions, image.SigningOptions{}, false, false)
} else {
newImage, err = runtime.ImageRuntime().NewFromLocal(runlabelImage)
}
@@ -187,6 +199,23 @@ func runlabelCmd(c *cli.Context) error {
env := shared.GenerateRunEnvironment(c.String("name"), imageName, opts)
env = append(env, "PODMAN_RUNLABEL_NESTED=1")
+ envmap := envSliceToMap(env)
+
+ envmapper := func(k string) string {
+ switch k {
+ case "OPT1":
+ return envmap["OPT1"]
+ case "OPT2":
+ return envmap["OPT2"]
+ case "OPT3":
+ return envmap["OPT3"]
+ }
+ return ""
+ }
+
+ newS := os.Expand(strings.Join(cmd, " "), envmapper)
+ cmd = strings.Split(newS, " ")
+
if !c.Bool("quiet") {
fmt.Printf("Command: %s\n", strings.Join(cmd, " "))
if c.Bool("display") {
@@ -195,3 +224,12 @@ func runlabelCmd(c *cli.Context) error {
}
return utils.ExecCmdWithStdStreams(stdIn, stdOut, stdErr, env, cmd[0], cmd[1:]...)
}
+
+func envSliceToMap(env []string) map[string]string {
+ m := make(map[string]string)
+ for _, i := range env {
+ split := strings.Split(i, "=")
+ m[split[0]] = strings.Join(split[1:], " ")
+ }
+ return m
+}
diff --git a/cmd/podman/shared/funcs.go b/cmd/podman/shared/funcs.go
index 21e7fe10d..485944f29 100644
--- a/cmd/podman/shared/funcs.go
+++ b/cmd/podman/shared/funcs.go
@@ -24,10 +24,14 @@ func GenerateCommand(command, imageName, name string) []string {
newArg = imageName
case "IMAGE=IMAGE":
newArg = fmt.Sprintf("IMAGE=%s", imageName)
+ case "IMAGE=$IMAGE":
+ newArg = fmt.Sprintf("IMAGE=%s", imageName)
case "NAME":
newArg = name
case "NAME=NAME":
newArg = fmt.Sprintf("NAME=%s", name)
+ case "NAME=$NAME":
+ newArg = fmt.Sprintf("NAME=%s", name)
default:
newArg = arg
}
diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go
index d2fa87730..664d91ea3 100644
--- a/cmd/podman/stop.go
+++ b/cmd/podman/stop.go
@@ -3,6 +3,7 @@ package main
import (
"fmt"
"os"
+ rt "runtime"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
@@ -98,21 +99,33 @@ func stopCmd(c *cli.Context) error {
}
}
+ var stopFuncs []workerInput
for _, ctr := range containers {
+ con := ctr
var stopTimeout uint
if c.IsSet("timeout") {
stopTimeout = c.Uint("timeout")
} else {
stopTimeout = ctr.StopTimeout()
}
- if err := ctr.StopWithTimeout(stopTimeout); err != nil && err != libpod.ErrCtrStopped {
- if lastError != nil {
- fmt.Fprintln(os.Stderr, lastError)
- }
- lastError = errors.Wrapf(err, "failed to stop container %v", ctr.ID())
- } else {
- fmt.Println(ctr.ID())
+ f := func() error {
+ return con.StopWithTimeout(stopTimeout)
+ }
+ stopFuncs = append(stopFuncs, workerInput{
+ containerID: con.ID(),
+ parallelFunc: f,
+ })
+ }
+
+ stopErrors := parallelExecuteWorkerPool(rt.NumCPU()*3, stopFuncs)
+
+ for cid, result := range stopErrors {
+ if result != nil && result != libpod.ErrCtrStopped {
+ fmt.Println(result.Error())
+ lastError = result
+ continue
}
+ fmt.Println(cid)
}
return lastError
}
diff --git a/cmd/podman/utils.go b/cmd/podman/utils.go
index 89ec48dbe..1b767532e 100644
--- a/cmd/podman/utils.go
+++ b/cmd/podman/utils.go
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
gosignal "os/signal"
+ "sync"
"github.com/containers/libpod/libpod"
"github.com/docker/docker/pkg/signal"
@@ -215,3 +216,50 @@ func getPodsFromContext(c *cli.Context, r *libpod.Runtime) ([]*libpod.Pod, error
}
return pods, lastError
}
+
+type pFunc func() error
+
+type workerInput struct {
+ containerID string
+ parallelFunc pFunc
+}
+
+// worker is a "threaded" worker that takes jobs from the channel "queue"
+func worker(wg *sync.WaitGroup, jobs <-chan workerInput, results map[string]error) {
+ for j := range jobs {
+ err := j.parallelFunc()
+ results[j.containerID] = err
+ wg.Done()
+ }
+}
+
+// parallelExecuteWorkerPool takes container jobs and performs them in parallel. The worker
+// int is determines how many workers/threads should be premade.
+func parallelExecuteWorkerPool(workers int, functions []workerInput) map[string]error {
+ var (
+ wg sync.WaitGroup
+ )
+ results := make(map[string]error)
+ paraJobs := make(chan workerInput, len(functions))
+
+ // If we have more workers than functions, match up the number of workers and functions
+ if workers > len(functions) {
+ workers = len(functions)
+ }
+
+ // Create the workers
+ for w := 1; w <= workers; w++ {
+ go worker(&wg, paraJobs, results)
+ }
+
+ // Add jobs to the workers
+ for _, j := range functions {
+ j := j
+ wg.Add(1)
+ paraJobs <- j
+ }
+
+ close(paraJobs)
+ wg.Wait()
+ return results
+}