summaryrefslogtreecommitdiff
path: root/cmd/podman/shared
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/shared')
-rw-r--r--cmd/podman/shared/container.go92
-rw-r--r--cmd/podman/shared/funcs.go36
-rw-r--r--cmd/podman/shared/funcs_test.go9
-rw-r--r--cmd/podman/shared/parallel.go10
-rw-r--r--cmd/podman/shared/pod.go37
-rw-r--r--cmd/podman/shared/prune.go24
6 files changed, 186 insertions, 22 deletions
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index 4404268d4..6236d19b4 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -1,10 +1,10 @@
package shared
import (
+ "context"
"encoding/json"
"fmt"
- "github.com/cri-o/ocicni/pkg/ocicni"
- "github.com/docker/go-units"
+ "io"
"os"
"path/filepath"
"regexp"
@@ -13,9 +13,14 @@ import (
"sync"
"time"
+ "github.com/containers/image/types"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/inspect"
cc "github.com/containers/libpod/pkg/spec"
+ "github.com/containers/libpod/pkg/util"
+ "github.com/cri-o/ocicni/pkg/ocicni"
+ "github.com/docker/go-units"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -40,6 +45,7 @@ type PsOptions struct {
Sort string
Label string
Namespace bool
+ Sync bool
}
// BatchContainerStruct is the return obkect from BatchContainer and contains
@@ -121,6 +127,12 @@ func NewBatchContainer(ctr *libpod.Container, opts PsOptions) (PsContainerOutput
pso PsContainerOutput
)
batchErr := ctr.Batch(func(c *libpod.Container) error {
+ if opts.Sync {
+ if err := c.Sync(); err != nil {
+ return err
+ }
+ }
+
conState, err = c.State()
if err != nil {
return errors.Wrapf(err, "unable to obtain container state")
@@ -589,3 +601,79 @@ func portsToString(ports []ocicni.PortMapping) string {
}
return strings.Join(portDisplay, ", ")
}
+
+// GetRunlabel is a helper function for runlabel; it gets the image if needed and begins the
+// contruction of the runlabel output and environment variables
+func GetRunlabel(label string, runlabelImage string, ctx context.Context, runtime *libpod.Runtime, pull bool, inputCreds string, dockerRegistryOptions image.DockerRegistryOptions, authfile string, signaturePolicyPath string, output io.Writer) (string, string, error) {
+ var (
+ newImage *image.Image
+ err error
+ imageName string
+ )
+ if pull {
+ var registryCreds *types.DockerAuthConfig
+ if inputCreds != "" {
+ creds, err := util.ParseRegistryCreds(inputCreds)
+ if err != nil {
+ return "", "", err
+ }
+ registryCreds = creds
+ }
+ dockerRegistryOptions.DockerRegistryCreds = registryCreds
+ newImage, err = runtime.ImageRuntime().New(ctx, runlabelImage, signaturePolicyPath, authfile, output, &dockerRegistryOptions, image.SigningOptions{}, 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)
+ return runLabel, imageName, err
+}
+
+// GenerateRunlabelCommand generates the command that will eventually be execucted by podman
+func GenerateRunlabelCommand(runLabel, imageName, name string, opts map[string]string, extraArgs []string) ([]string, []string, error) {
+ // The user provided extra arguments that need to be tacked onto the label's command
+ if len(extraArgs) > 0 {
+ runLabel = fmt.Sprintf("%s %s", runLabel, strings.Join(extraArgs, " "))
+ }
+ cmd, err := GenerateCommand(runLabel, imageName, name)
+ if err != nil {
+ return nil, nil, errors.Wrapf(err, "unable to generate command")
+ }
+ env := GenerateRunEnvironment(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, " ")
+ return cmd, env, nil
+}
+
+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 a92e0d547..8770b8ec0 100644
--- a/cmd/podman/shared/funcs.go
+++ b/cmd/podman/shared/funcs.go
@@ -5,13 +5,28 @@ import (
"os"
"path/filepath"
"strings"
+
+ "github.com/google/shlex"
)
func substituteCommand(cmd string) (string, error) {
+ var (
+ newCommand string
+ )
+
+ // Replace cmd with "/proc/self/exe" if "podman" or "docker" is being
+ // used. If "/usr/bin/docker" is provided, we also sub in podman.
+ // Otherwise, leave the command unchanged.
+ if cmd == "podman" || filepath.Base(cmd) == "docker" {
+ newCommand = "/proc/self/exe"
+ } else {
+ newCommand = cmd
+ }
+
// If cmd is an absolute or relative path, check if the file exists.
// Throw an error if it doesn't exist.
- if strings.Contains(cmd, "/") || strings.HasPrefix(cmd, ".") {
- res, err := filepath.Abs(cmd)
+ if strings.Contains(newCommand, "/") || strings.HasPrefix(newCommand, ".") {
+ res, err := filepath.Abs(newCommand)
if err != nil {
return "", err
}
@@ -22,16 +37,7 @@ func substituteCommand(cmd string) (string, error) {
}
}
- // Replace cmd with "/proc/self/exe" if "podman" or "docker" is being
- // used. Otherwise, leave the command unchanged.
- switch cmd {
- case "podman":
- fallthrough
- case "docker":
- return "/proc/self/exe", nil
- default:
- return cmd, nil
- }
+ return newCommand, nil
}
// GenerateCommand takes a label (string) and converts it to an executable command
@@ -42,7 +48,11 @@ func GenerateCommand(command, imageName, name string) ([]string, error) {
if name == "" {
name = imageName
}
- cmd := strings.Split(command, " ")
+
+ cmd, err := shlex.Split(command)
+ if err != nil {
+ return nil, err
+ }
prog, err := substituteCommand(cmd[0])
if err != nil {
diff --git a/cmd/podman/shared/funcs_test.go b/cmd/podman/shared/funcs_test.go
index 596df84e8..7506b9d9c 100644
--- a/cmd/podman/shared/funcs_test.go
+++ b/cmd/podman/shared/funcs_test.go
@@ -18,10 +18,11 @@ var (
)
func TestGenerateCommand(t *testing.T) {
- inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo install"
+ inputCommand := "docker run -it --name NAME -e NAME=NAME -e IMAGE=IMAGE IMAGE echo \"hello world\""
+ correctCommand := "/proc/self/exe run -it --name bar -e NAME=bar -e IMAGE=foo foo echo hello world"
newCommand, err := GenerateCommand(inputCommand, "foo", "bar")
assert.Nil(t, err)
+ assert.Equal(t, "hello world", newCommand[11])
assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
}
@@ -108,8 +109,8 @@ func TestGenerateCommandNoSetName(t *testing.T) {
}
func TestGenerateCommandNoName(t *testing.T) {
- inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install"
- correctCommand := "/proc/self/exe run -it -e IMAGE=foo foo echo install"
+ inputCommand := "docker run -it -e IMAGE=IMAGE IMAGE echo install"
+ correctCommand := "/proc/self/exe run -it -e IMAGE=foo foo echo install"
newCommand, err := GenerateCommand(inputCommand, "foo", "")
assert.Nil(t, err)
assert.Equal(t, correctCommand, strings.Join(newCommand, " "))
diff --git a/cmd/podman/shared/parallel.go b/cmd/podman/shared/parallel.go
index 633781a45..e6ce50f95 100644
--- a/cmd/podman/shared/parallel.go
+++ b/cmd/podman/shared/parallel.go
@@ -30,9 +30,10 @@ func ParallelWorker(wg *sync.WaitGroup, jobs <-chan ParallelWorkerInput, results
// ParallelExecuteWorkerPool takes container jobs and performs them in parallel. The worker
// int determines how many workers/threads should be premade.
-func ParallelExecuteWorkerPool(workers int, functions []ParallelWorkerInput) map[string]error {
+func ParallelExecuteWorkerPool(workers int, functions []ParallelWorkerInput) (map[string]error, int) {
var (
- wg sync.WaitGroup
+ wg sync.WaitGroup
+ errorCount int
)
resultChan := make(chan containerError, len(functions))
@@ -62,9 +63,12 @@ func ParallelExecuteWorkerPool(workers int, functions []ParallelWorkerInput) map
close(resultChan)
for ctrError := range resultChan {
results[ctrError.ContainerID] = ctrError.Err
+ if ctrError.Err != nil {
+ errorCount += 1
+ }
}
- return results
+ return results, errorCount
}
// Parallelize provides the maximum number of parallel workers (int) as calculated by a basic
diff --git a/cmd/podman/shared/pod.go b/cmd/podman/shared/pod.go
index 4e8e58c4d..30dd14845 100644
--- a/cmd/podman/shared/pod.go
+++ b/cmd/podman/shared/pod.go
@@ -1,7 +1,11 @@
package shared
import (
+ "strconv"
+
"github.com/containers/libpod/libpod"
+ "github.com/cri-o/ocicni/pkg/ocicni"
+ "github.com/docker/go-connections/nat"
"github.com/pkg/errors"
)
@@ -95,3 +99,36 @@ func GetNamespaceOptions(ns []string) ([]libpod.PodCreateOption, error) {
}
return options, nil
}
+
+// CreatePortBindings iterates ports mappings and exposed ports into a format CNI understands
+func CreatePortBindings(ports []string) ([]ocicni.PortMapping, error) {
+ var portBindings []ocicni.PortMapping
+ // The conversion from []string to natBindings is temporary while mheon reworks the port
+ // deduplication code. Eventually that step will not be required.
+ _, natBindings, err := nat.ParsePortSpecs(ports)
+ if err != nil {
+ return nil, err
+ }
+ for containerPb, hostPb := range natBindings {
+ var pm ocicni.PortMapping
+ pm.ContainerPort = int32(containerPb.Int())
+ for _, i := range hostPb {
+ var hostPort int
+ var err error
+ pm.HostIP = i.HostIP
+ if i.HostPort == "" {
+ hostPort = containerPb.Int()
+ } else {
+ hostPort, err = strconv.Atoi(i.HostPort)
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to convert host port to integer")
+ }
+ }
+
+ pm.HostPort = int32(hostPort)
+ pm.Protocol = containerPb.Proto()
+ portBindings = append(portBindings, pm)
+ }
+ }
+ return portBindings, nil
+}
diff --git a/cmd/podman/shared/prune.go b/cmd/podman/shared/prune.go
new file mode 100644
index 000000000..90cfe4475
--- /dev/null
+++ b/cmd/podman/shared/prune.go
@@ -0,0 +1,24 @@
+package shared
+
+import (
+ "fmt"
+ "github.com/pkg/errors"
+
+ "github.com/containers/libpod/libpod/image"
+)
+
+// Prune removes all unnamed and unused images from the local store
+func Prune(ir *image.Runtime) error {
+ pruneImages, err := ir.GetPruneImages()
+ if err != nil {
+ return err
+ }
+
+ for _, i := range pruneImages {
+ if err := i.Remove(true); err != nil {
+ return errors.Wrapf(err, "failed to remove %s", i.ID())
+ }
+ fmt.Println(i.ID())
+ }
+ return nil
+}