diff options
Diffstat (limited to 'cmd/podman')
-rw-r--r-- | cmd/podman/common.go | 4 | ||||
-rw-r--r-- | cmd/podman/runlabel.go | 80 | ||||
-rw-r--r-- | cmd/podman/shared/funcs.go | 4 | ||||
-rw-r--r-- | cmd/podman/stop.go | 27 | ||||
-rw-r--r-- | cmd/podman/utils.go | 48 |
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 +} |