From 5c02dda869390725a799339b094f548d327c9122 Mon Sep 17 00:00:00 2001
From: baude <bbaude@redhat.com>
Date: Mon, 3 Dec 2018 09:15:29 -0600
Subject: Adding more varlink endpoints

* runlabel
* checkpoint
* restore
* container|image exists
* mount
* unmount

Signed-off-by: baude <bbaude@redhat.com>
---
 cmd/podman/runlabel.go               | 81 +++++-------------------------------
 cmd/podman/shared/container.go       | 81 ++++++++++++++++++++++++++++++++++++
 cmd/podman/varlink/io.podman.varlink | 52 +++++++++++++++++++++++
 3 files changed, 144 insertions(+), 70 deletions(-)

(limited to 'cmd/podman')

diff --git a/cmd/podman/runlabel.go b/cmd/podman/runlabel.go
index e1dee1fb2..b0d87d0d9 100644
--- a/cmd/podman/runlabel.go
+++ b/cmd/podman/runlabel.go
@@ -6,11 +6,9 @@ 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"
@@ -94,7 +92,7 @@ func runlabelCmd(c *cli.Context) error {
 		imageName      string
 		stdErr, stdOut io.Writer
 		stdIn          io.Reader
-		newImage       *image.Image
+		extraArgs      []string
 	)
 
 	// Evil images could trick into recursively executing the runlabel
@@ -124,6 +122,9 @@ func runlabelCmd(c *cli.Context) error {
 		return errors.Errorf("the display and quiet flags cannot be used together.")
 	}
 
+	if len(args) > 2 {
+		extraArgs = args[2:]
+	}
 	pull := c.Bool("pull")
 	label := args[0]
 
@@ -151,75 +152,24 @@ func runlabelCmd(c *cli.Context) error {
 		stdIn = nil
 	}
 
-	if pull {
-		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"),
-		}
-		authfile := getAuthFile(c.String("authfile"))
-
-		newImage, err = runtime.ImageRuntime().New(ctx, runlabelImage, c.String("signature-policy"), authfile, stdOut, &dockerRegistryOptions, 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]
+	dockerRegistryOptions := image.DockerRegistryOptions{
+		DockerCertPath:              c.String("cert-dir"),
+		DockerInsecureSkipTLSVerify: !c.BoolT("tls-verify"),
 	}
 
-	runLabel, err := newImage.GetLabel(ctx, label)
+	authfile := getAuthFile(c.String("authfile"))
+	runLabel, imageName, err := shared.GetRunlabel(label, runlabelImage, ctx, runtime, pull, c.String("creds"), dockerRegistryOptions, authfile, c.String("signature-policy"), stdOut)
 	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, err := shared.GenerateCommand(runLabel, imageName, c.String("name"))
+	cmd, env, err := shared.GenerateRunlabelCommand(runLabel, imageName, c.String("name"), opts, extraArgs)
 	if err != nil {
-		return errors.Wrapf(err, "unable to generate command")
-	}
-	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 ""
+		return err
 	}
-
-	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") {
@@ -228,12 +178,3 @@ 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/container.go b/cmd/podman/shared/container.go
index 4404268d4..d0e892961 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -1,10 +1,15 @@
 package shared
 
 import (
+	"context"
 	"encoding/json"
 	"fmt"
+	"github.com/containers/image/types"
+	"github.com/containers/libpod/libpod/image"
+	"github.com/containers/libpod/pkg/util"
 	"github.com/cri-o/ocicni/pkg/ocicni"
 	"github.com/docker/go-units"
+	"io"
 	"os"
 	"path/filepath"
 	"regexp"
@@ -589,3 +594,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, 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/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 4a4a1854c..b081b60a3 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -371,6 +371,22 @@ type PodContainerErrorData (
     reason: string
 )
 
+# Runlabel describes the required input for container runlabel
+type Runlabel(
+    image: string,
+    authfile: string,
+    certDir: string,
+    creds: string,
+    display: bool,
+    name: string,
+    pull: bool,
+    signaturePolicyPath: string,
+    tlsVerify: bool,
+    label: string,
+    extraArgs: []string,
+    opts: [string]string
+)
+
 # Ping provides a response for developers to ensure their varlink setup is working.
 # #### Example
 # ~~~
@@ -804,6 +820,42 @@ method TopPod() -> (notimplemented: NotImplemented)
 # ~~~
 method GetPodStats(name: string) -> (pod: string, containers: []ContainerStats)
 
+# ImageExists talks a full or partial image ID or name and returns an int as to whether
+# the image exists in local storage. An int result of 0 means the image does exist in
+# local storage; whereas 1 indicates the image does not exists in local storage.
+method ImageExists(name: string) -> (exists: int)
+
+# ContainerExists takes a full or partial container ID or name and returns an int as to
+# whether the container exists in local storage.  A result of 0 means the container does
+# exists; whereas a result of 1 means it could not be found.
+method ContainerExists(name: string) -> (exists: int)
+
+# ContainerCheckPoint performs a checkpopint on a container by its name or full/partial container
+# ID.  On successful checkpoint, the id of the checkpointed container is returned.
+method ContainerCheckpoint(name: string, keep: bool, leaveRunning: bool, tcpEstablished: bool) -> (id: string)
+
+# ContainerRestore restores a container that has been checkpointed.  The container to be restored can
+# be identified by its name or full/partial container ID.  A successful restore will result in the return
+# of the container's ID.
+method ContainerRestore(name: string, keep: bool, tcpEstablished: bool) -> (id: string)
+
+# ContainerRunlabel runs executes a command as described by a given container image label.
+method ContainerRunlabel(runlabel: Runlabel) -> ()
+
+# ListContainerMounts gathers all the mounted container mount points and returns them as an array
+# of strings
+method ListContainerMounts() -> (mounts: []string)
+
+# MountContainer mounts a container by name or full/partial ID.  Upon a successful mount, the destination
+# mount is returned as a string.
+method MountContainer(name: string) -> (path: string)
+
+# UnmountContainer umounts a container by its name or full/partial container ID.
+method  UnmountContainer(name: string, force: bool) -> ()
+
+# This function is not implemented yet.
+method ListContainerPorts(name: string) -> (notimplemented: NotImplemented)
+
 # ImageNotFound means the image could not be found by the provided name or ID in local storage.
 error ImageNotFound (name: string)
 
-- 
cgit v1.2.3-54-g00ecf