Ver código fonte

Engine.ParseJob: create a new job from a shell-like text command.

Docker-DCO-1.1-Signed-off-by: Solomon Hykes <solomon@docker.com> (github: shykes)
Solomon Hykes 11 anos atrás
pai
commit
2019a73f03
3 arquivos alterados com 54 adições e 0 exclusões
  1. 43 0
      engine/engine.go
  2. 7 0
      engine/env.go
  3. 4 0
      engine/job.go

+ 43 - 0
engine/engine.go

@@ -1,6 +1,7 @@
 package engine
 package engine
 
 
 import (
 import (
+	"bufio"
 	"fmt"
 	"fmt"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
 	"io"
 	"io"
@@ -136,6 +137,48 @@ func (eng *Engine) Job(name string, args ...string) *Job {
 	return job
 	return job
 }
 }
 
 
+// ParseJob creates a new job from a text description using a shell-like syntax.
+//
+// The following syntax is used to parse `input`:
+//
+// * Words are separated using standard whitespaces as separators.
+// * Quotes and backslashes are not interpreted.
+// * Words of the form 'KEY=[VALUE]' are added to the job environment.
+// * All other words are added to the job arguments.
+//
+// For example:
+//
+// job, _ := eng.ParseJob("VERBOSE=1 echo hello TEST=true world")
+//
+// The resulting job will have:
+//	job.Args={"echo", "hello", "world"}
+//	job.Env={"VERBOSE":"1", "TEST":"true"}
+//
+func (eng *Engine) ParseJob(input string) (*Job, error) {
+	// FIXME: use a full-featured command parser
+	scanner := bufio.NewScanner(strings.NewReader(input))
+	scanner.Split(bufio.ScanWords)
+	var (
+		cmd []string
+		env Env
+	)
+	for scanner.Scan() {
+		word := scanner.Text()
+		kv := strings.SplitN(word, "=", 2)
+		if len(kv) == 2 {
+			env.Set(kv[0], kv[1])
+		} else {
+			cmd = append(cmd, word)
+		}
+	}
+	if len(cmd) == 0 {
+		return nil, fmt.Errorf("empty command: '%s'", input)
+	}
+	job := eng.Job(cmd[0], cmd[1:]...)
+	job.Env().Init(&env)
+	return job, nil
+}
+
 func (eng *Engine) Logf(format string, args ...interface{}) (n int, err error) {
 func (eng *Engine) Logf(format string, args ...interface{}) (n int, err error) {
 	if os.Getenv("TEST") == "" {
 	if os.Getenv("TEST") == "" {
 		prefixedFormat := fmt.Sprintf("[%s] %s\n", eng, strings.TrimRight(format, "\n"))
 		prefixedFormat := fmt.Sprintf("[%s] %s\n", eng, strings.TrimRight(format, "\n"))

+ 7 - 0
engine/env.go

@@ -36,6 +36,13 @@ func (env *Env) Exists(key string) bool {
 	return exists
 	return exists
 }
 }
 
 
+func (env *Env) Init(src *Env) {
+	*env = make([]string, 0, len(*src))
+	for _, val := range *src {
+		(*env) = append((*env), val)
+	}
+}
+
 func (env *Env) GetBool(key string) (value bool) {
 func (env *Env) GetBool(key string) (value bool) {
 	s := strings.ToLower(strings.Trim(env.Get(key), " \t"))
 	s := strings.ToLower(strings.Trim(env.Get(key), " \t"))
 	if s == "" || s == "0" || s == "no" || s == "false" || s == "none" {
 	if s == "" || s == "0" || s == "no" || s == "false" || s == "none" {

+ 4 - 0
engine/job.go

@@ -102,6 +102,10 @@ func (job *Job) String() string {
 	return fmt.Sprintf("%s.%s%s", job.Eng, job.CallString(), job.StatusString())
 	return fmt.Sprintf("%s.%s%s", job.Eng, job.CallString(), job.StatusString())
 }
 }
 
 
+func (job *Job) Env() *Env {
+	return job.env
+}
+
 func (job *Job) EnvExists(key string) (value bool) {
 func (job *Job) EnvExists(key string) (value bool) {
 	return job.env.Exists(key)
 	return job.env.Exists(key)
 }
 }