From 358da6c8c0375ad41c4669aeef71f9626710c83e Mon Sep 17 00:00:00 2001
From: baude <bbaude@redhat.com>
Date: Sun, 10 Feb 2019 16:43:00 -0600
Subject: [PATCH] podman-remote volume create

create a volume using the remote client over varlink

Signed-off-by: baude <bbaude@redhat.com>
---
 cmd/podman/commands_remoteclient.go  |  4 +++-
 cmd/podman/varlink/io.podman.varlink | 12 ++++++++++
 cmd/podman/volume_create.go          | 36 +++++-----------------------
 libpod/adapter/runtime.go            | 30 +++++++++++++++++++++++
 libpod/adapter/runtime_remote.go     | 17 +++++++++++++
 pkg/varlinkapi/volumes.go            | 29 ++++++++++++++++++++++
 6 files changed, 97 insertions(+), 31 deletions(-)
 create mode 100644 pkg/varlinkapi/volumes.go

diff --git a/cmd/podman/commands_remoteclient.go b/cmd/podman/commands_remoteclient.go
index 80083eab9b..993137fde0 100644
--- a/cmd/podman/commands_remoteclient.go
+++ b/cmd/podman/commands_remoteclient.go
@@ -25,7 +25,9 @@ func getPodSubCommands() []*cobra.Command {
 }
 
 func getVolumeSubCommands() []*cobra.Command {
-	return []*cobra.Command{}
+	return []*cobra.Command{
+		_volumeCreateCommand,
+	}
 }
 
 func getGenerateSubCommands() []*cobra.Command {
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 101232b0ce..7263cfea3d 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -27,6 +27,15 @@ type ContainerChanges (
    deleted: []string
 )
 
+type VolumeCreateOpts (
+   volumeName: string,
+   driver: string,
+   labels: [string]string,
+   options: [string]string
+)
+
+
+
 # ImageInList describes the structure that is returned in
 # ListImages.
 type ImageInList (
@@ -1053,6 +1062,9 @@ method ContainerStateData(name: string) -> (config: string)
 method SendFile(type: string, length: int) -> (file_handle: string)
 method ReceiveFile(path: string, delete: bool) -> (len: int)
 
+method VolumeCreate(options: VolumeCreateOpts) -> (volumeName: string)
+
+
 # ImageNotFound means the image could not be found by the provided name or ID in local storage.
 error ImageNotFound (name: string)
 
diff --git a/cmd/podman/volume_create.go b/cmd/podman/volume_create.go
index e0ff4c3418..238579501e 100644
--- a/cmd/podman/volume_create.go
+++ b/cmd/podman/volume_create.go
@@ -4,8 +4,7 @@ import (
 	"fmt"
 
 	"github.com/containers/libpod/cmd/podman/cliconfig"
-	"github.com/containers/libpod/cmd/podman/libpodruntime"
-	"github.com/containers/libpod/libpod"
+	"github.com/containers/libpod/libpod/adapter"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 )
@@ -41,13 +40,7 @@ func init() {
 }
 
 func volumeCreateCmd(c *cliconfig.VolumeCreateValues) error {
-	var (
-		options []libpod.VolumeCreateOption
-		err     error
-		volName string
-	)
-
-	runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+	runtime, err := adapter.GetRuntime(&c.PodmanCommand)
 	if err != nil {
 		return errors.Wrapf(err, "error creating libpod runtime")
 	}
@@ -57,36 +50,19 @@ func volumeCreateCmd(c *cliconfig.VolumeCreateValues) error {
 		return errors.Errorf("too many arguments, create takes at most 1 argument")
 	}
 
-	if len(c.InputArgs) > 0 {
-		volName = c.InputArgs[0]
-		options = append(options, libpod.WithVolumeName(volName))
-	}
-
-	if c.Flag("driver").Changed {
-		options = append(options, libpod.WithVolumeDriver(c.String("driver")))
-	}
-
 	labels, err := getAllLabels([]string{}, c.Label)
 	if err != nil {
 		return errors.Wrapf(err, "unable to process labels")
 	}
-	if len(labels) != 0 {
-		options = append(options, libpod.WithVolumeLabels(labels))
-	}
 
 	opts, err := getAllLabels([]string{}, c.Opt)
 	if err != nil {
 		return errors.Wrapf(err, "unable to process options")
 	}
-	if len(options) != 0 {
-		options = append(options, libpod.WithVolumeOptions(opts))
-	}
 
-	vol, err := runtime.NewVolume(getContext(), options...)
-	if err != nil {
-		return err
+	volumeName, err := runtime.CreateVolume(getContext(), c, labels, opts)
+	if err == nil {
+		fmt.Println(volumeName)
 	}
-	fmt.Printf("%s\n", vol.Name())
-
-	return nil
+	return err
 }
diff --git a/libpod/adapter/runtime.go b/libpod/adapter/runtime.go
index 46771b5b67..050ea6ed4b 100644
--- a/libpod/adapter/runtime.go
+++ b/libpod/adapter/runtime.go
@@ -155,3 +155,33 @@ func (r *LocalRuntime) Export(name string, path string) error {
 func (r *LocalRuntime) Import(ctx context.Context, source, reference string, changes []string, history string, quiet bool) (string, error) {
 	return r.Runtime.Import(ctx, source, reference, changes, history, quiet)
 }
+
+// CreateVolume is a wrapper to create volumes
+func (r *LocalRuntime) CreateVolume(ctx context.Context, c *cliconfig.VolumeCreateValues, labels, opts map[string]string) (string, error) {
+	var (
+		options []libpod.VolumeCreateOption
+		volName string
+	)
+
+	if len(c.InputArgs) > 0 {
+		volName = c.InputArgs[0]
+		options = append(options, libpod.WithVolumeName(volName))
+	}
+
+	if c.Flag("driver").Changed {
+		options = append(options, libpod.WithVolumeDriver(c.Driver))
+	}
+
+	if len(labels) != 0 {
+		options = append(options, libpod.WithVolumeLabels(labels))
+	}
+
+	if len(options) != 0 {
+		options = append(options, libpod.WithVolumeOptions(opts))
+	}
+	newVolume, err := r.NewVolume(ctx, options...)
+	if err != nil {
+		return "", err
+	}
+	return newVolume.Name(), nil
+}
diff --git a/libpod/adapter/runtime_remote.go b/libpod/adapter/runtime_remote.go
index f754aaee60..3df8afc6e7 100644
--- a/libpod/adapter/runtime_remote.go
+++ b/libpod/adapter/runtime_remote.go
@@ -432,3 +432,20 @@ func (r *LocalRuntime) GetContainers(filters ...libpod.ContainerFilter) ([]*libp
 func (r *LocalRuntime) RemoveContainer(ctx context.Context, c *libpod.Container, force bool) error {
 	return libpod.ErrNotImplemented
 }
+
+// CreateVolume creates a volume over a varlink connection for the remote client
+func (r *LocalRuntime) CreateVolume(ctx context.Context, c *cliconfig.VolumeCreateValues, labels, opts map[string]string) (string, error) {
+	cvOpts := iopodman.VolumeCreateOpts{
+		Options: opts,
+		Labels:  labels,
+	}
+	if len(c.InputArgs) > 0 {
+		cvOpts.VolumeName = c.InputArgs[0]
+	}
+
+	if c.Flag("driver").Changed {
+		cvOpts.Driver = c.Driver
+	}
+
+	return iopodman.VolumeCreate().Call(r.Conn, cvOpts)
+}
diff --git a/pkg/varlinkapi/volumes.go b/pkg/varlinkapi/volumes.go
new file mode 100644
index 0000000000..d1e4ae3c60
--- /dev/null
+++ b/pkg/varlinkapi/volumes.go
@@ -0,0 +1,29 @@
+package varlinkapi
+
+import (
+	"github.com/containers/libpod/cmd/podman/varlink"
+	"github.com/containers/libpod/libpod"
+)
+
+// VolumeCreate creates a libpod volume based on input from a varlink connection
+func (i *LibpodAPI) VolumeCreate(call iopodman.VarlinkCall, options iopodman.VolumeCreateOpts) error {
+	var volumeOptions []libpod.VolumeCreateOption
+
+	if len(options.VolumeName) > 0 {
+		volumeOptions = append(volumeOptions, libpod.WithVolumeName(options.VolumeName))
+	}
+	if len(options.Driver) > 0 {
+		volumeOptions = append(volumeOptions, libpod.WithVolumeDriver(options.Driver))
+	}
+	if len(options.Labels) > 0 {
+		volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(options.Labels))
+	}
+	if len(options.Options) > 0 {
+		volumeOptions = append(volumeOptions, libpod.WithVolumeOptions(options.Options))
+	}
+	newVolume, err := i.Runtime.NewVolume(getContext(), volumeOptions...)
+	if err != nil {
+		return call.ReplyErrorOccurred(err.Error())
+	}
+	return call.ReplyVolumeCreate(newVolume.Name())
+}