From 06fd2630fd4c67a5ae507794d8e16ecec6dc6993 Mon Sep 17 00:00:00 2001
From: lijianguo <lijianguo@zhumengyuan.com>
Date: Mon, 31 Aug 2020 17:01:42 +0800
Subject: [PATCH] feat(wrokflow-cli):drycc run cmd add --mount para

---
 cmd/apps.go         | 24 ++++++++++++++++++++++--
 cmd/cmd.go          |  2 +-
 cmd/volumes.go      | 10 +++++-----
 cmd/volumes_test.go | 10 ++++------
 drycc.go            |  1 +
 parser/apps.go      | 10 +++++++---
 parser/apps_test.go |  2 +-
 7 files changed, 41 insertions(+), 18 deletions(-)

diff --git a/cmd/apps.go b/cmd/apps.go
index 727eea78b..20f051542 100644
--- a/cmd/apps.go
+++ b/cmd/apps.go
@@ -3,6 +3,7 @@ package cmd
 import (
 	"fmt"
 	"os"
+	"regexp"
 	"strings"
 	"time"
 
@@ -190,7 +191,7 @@ func (d *DryccCmd) AppLogs(appID string, lines int) error {
 }
 
 // AppRun runs a one time command in the app.
-func (d *DryccCmd) AppRun(appID, command string) error {
+func (d *DryccCmd) AppRun(appID, command string, volumeVars []string) error {
 	s, appID, err := load(d.ConfigFile, appID)
 
 	if err != nil {
@@ -198,8 +199,12 @@ func (d *DryccCmd) AppRun(appID, command string) error {
 	}
 
 	d.Printf("Running '%s'...\n", command)
+	volumeMap, err := parseMount(volumeVars)
+	//volumeObj := map[string]interface{}{
+	//	"volumes": volumeMap,
+	//}
 
-	out, err := apps.Run(s.Client, appID, command)
+	out, err := apps.Run(s.Client, appID, command, volumeMap)
 	if d.checkAPICompatibility(s.Client, err) != nil {
 		return err
 	}
@@ -214,6 +219,21 @@ func (d *DryccCmd) AppRun(appID, command string) error {
 	return nil
 }
 
+func parseMount(volumeVars []string) (map[string]interface{}, error) {
+	volumeMap := make(map[string]interface{})
+
+	regex := regexp.MustCompile(`^([A-z_]+[A-z0-9_]*):([\s\S]*)$`)
+	for _, volume := range volumeVars {
+		if regex.MatchString(volume) {
+			captures := regex.FindStringSubmatch(volume)
+			volumeMap[captures[1]] = captures[2]
+		} else {
+			return nil, fmt.Errorf("'%s' does not match the pattern 'key:var', ex: MODE:test", volume)
+		}
+	}
+	return volumeMap, nil
+}
+
 // AppDestroy destroys an app.
 func (d *DryccCmd) AppDestroy(appID, confirm string) error {
 	gitSession := false
diff --git a/cmd/cmd.go b/cmd/cmd.go
index cfe581915..a400bee05 100644
--- a/cmd/cmd.go
+++ b/cmd/cmd.go
@@ -15,7 +15,7 @@ type Commander interface {
 	AppInfo(string) error
 	AppOpen(string) error
 	AppLogs(string, int) error
-	AppRun(string, string) error
+	AppRun(string, string, []string) error
 	AppDestroy(string, string) error
 	AppTransfer(string, string) error
 	AutoscaleList(string) error
diff --git a/cmd/volumes.go b/cmd/volumes.go
index 79e3a0b68..cb9d74c34 100644
--- a/cmd/volumes.go
+++ b/cmd/volumes.go
@@ -20,7 +20,7 @@ func (d *DryccCmd) VolumesList(appID string, results int) error {
 	if results == defaultLimit {
 		results = s.Limit
 	}
-	fmt.Println("-----app-----", appID)
+	//fmt.Println("-----app-----", appID)  # debug
 	volumes, count, err := volumes.List(s.Client, appID, results)
 	if d.checkAPICompatibility(s.Client, err) != nil {
 		return err
@@ -38,10 +38,10 @@ func (d *DryccCmd) VolumesList(appID string, results int) error {
 func printVolumes(d *DryccCmd, appID string, volumes api.Volumes, wOut io.Writer) {
 	//volumes := ps.ByType(input)
 
-	fmt.Fprintf(wOut, "=== %s Volumes\n", appID)
+	fmt.Fprintf(wOut, "=== %s volumes\n", appID)
 
 	for _, volume := range volumes {
-		fmt.Fprintf(wOut, "--- %s %s\n", volume.Name, volume.Size)
+		fmt.Fprintf(wOut, "--- %s   %s\n", volume.Name, volume.Size)
 		for k, v := range volume.Path {
 			fmt.Println(k, v)
 		}
@@ -120,7 +120,7 @@ func (d *DryccCmd) VolumesMount(appID string, name string, volumeVars []string)
 		return err
 	}
 
-	d.Print("done\n\n")
+	d.Print("done\n")
 
 	return nil
 }
@@ -153,7 +153,7 @@ func (d *DryccCmd) VolumesUnmount(appID string, name string, volumeVars []string
 		return err
 	}
 
-	d.Print("done\n\n")
+	d.Print("done\n")
 
 	return nil
 }
diff --git a/cmd/volumes_test.go b/cmd/volumes_test.go
index 762e6ea2d..69caa508f 100644
--- a/cmd/volumes_test.go
+++ b/cmd/volumes_test.go
@@ -45,8 +45,8 @@ func TestVolumesList(t *testing.T) {
 	err = cmdr.VolumesList("example-go", -1)
 	assert.NoErr(t, err)
 
-	assert.Equal(t, b.String(), `=== example-go Volumes
---- myvolume 500M
+	assert.Equal(t, b.String(), `=== example-go volumes
+--- myvolume   500M
 `, "output")
 }
 
@@ -131,11 +131,10 @@ func TestVolumesMount(t *testing.T) {
 	assert.NoErr(t, err)
 
 	assert.Equal(t, testutil.StripProgress(b.String()), `Mounting volume... done
-
 `, "output")
 	//
 	//=== example-go Volumes
-	//--- myvolume 500M
+	//--- myvolume   500M
 	//cmd /data/cmd1
 }
 
@@ -175,9 +174,8 @@ func TestVolumesUnmount(t *testing.T) {
 	assert.NoErr(t, err)
 
 	assert.Equal(t, testutil.StripProgress(b.String()), `Unmounting volume... done
-
 `, "output")
 
 	//=== example-go Volumes
-	//--- myvolume 500M
+	//--- myvolume   500M
 }
diff --git a/drycc.go b/drycc.go
index b41f988dc..daec9ffdc 100644
--- a/drycc.go
+++ b/drycc.go
@@ -70,6 +70,7 @@ Subcommands, use 'drycc help [subcommand]' to learn more::
   whitelist     manage whitelisted addresses of an application
   services      manage services for your applications
   timeouts      manage pods termination grace period
+  volumes       manage volumes for your applications
 
 Shortcut commands, use 'drycc shortcuts' to see all::
 
diff --git a/parser/apps.go b/parser/apps.go
index 380340851..56496a64e 100644
--- a/parser/apps.go
+++ b/parser/apps.go
@@ -205,9 +205,13 @@ func appRun(argv []string, cmdr cmd.Commander) error {
 Runs a command inside an ephemeral app container. Default environment is
 /bin/bash.
 
-Usage: drycc apps:run [options] [--] <command>...
+Usage: drycc apps:run [--mount=<volume>:<path>...] [options] [--] <command>...
 
 Arguments:
+  <volume>
+    the volume name
+  <path>
+    the filesystem path.
   <command>
     the shell command to run inside the container.
 
@@ -224,8 +228,8 @@ Options:
 
 	app := safeGetValue(args, "--app")
 	command := strings.Join(args["<command>"].([]string), " ")
-
-	return cmdr.AppRun(app, command)
+	mounts := args["--mount"].([]string)
+	return cmdr.AppRun(app, command, mounts)
 }
 
 func appDestroy(argv []string, cmdr cmd.Commander) error {
diff --git a/parser/apps_test.go b/parser/apps_test.go
index 3aff72bf3..bfe42e695 100644
--- a/parser/apps_test.go
+++ b/parser/apps_test.go
@@ -32,7 +32,7 @@ func (d FakeDryccCmd) AppLogs(string, int) error {
 	return errors.New("apps:logs")
 }
 
-func (d FakeDryccCmd) AppRun(string, string) error {
+func (d FakeDryccCmd) AppRun(string, string, []string) error {
 	return errors.New("apps:run")
 }
 
