소스 검색

Merge pull request #3559 from vieux/insert_job

move insert to a job
Victor Vieux 11 년 전
부모
커밋
44b8d8addf
4개의 변경된 파일54개의 추가작업 그리고 27개의 파일을 삭제
  1. 9 11
      api.go
  2. 9 0
      engine/streams.go
  3. 3 6
      integration/server_test.go
  4. 33 10
      server.go

+ 9 - 11
api.go

@@ -510,24 +510,22 @@ func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *ht
 	if err := parseForm(r); err != nil {
 		return err
 	}
-
-	url := r.Form.Get("url")
-	path := r.Form.Get("path")
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 	}
-	name := vars["name"]
 	if version > 1.0 {
 		w.Header().Set("Content-Type", "application/json")
 	}
-	sf := utils.NewStreamFormatter(version > 1.0)
-	err := srv.ImageInsert(name, url, path, w, sf)
-	if err != nil {
-		if sf.Used() {
-			w.Write(sf.FormatError(err))
-			return nil
+
+	job := srv.Eng.Job("insert", vars["name"], r.Form.Get("url"), r.Form.Get("path"))
+	job.SetenvBool("json", version > 1.0)
+	job.Stdout.Add(w)
+	if err := job.Run(); err != nil {
+		if !job.Stdout.Used() {
+			return err
 		}
-		return err
+		sf := utils.NewStreamFormatter(version > 1.0)
+		w.Write(sf.FormatError(err))
 	}
 
 	return nil

+ 9 - 0
engine/streams.go

@@ -12,6 +12,7 @@ type Output struct {
 	sync.Mutex
 	dests []io.Writer
 	tasks sync.WaitGroup
+	used  bool
 }
 
 // NewOutput returns a new Output object with no destinations attached.
@@ -20,6 +21,13 @@ func NewOutput() *Output {
 	return &Output{}
 }
 
+// Return true if something was written on this output
+func (o *Output) Used() bool {
+	o.Mutex.Lock()
+	defer o.Mutex.Unlock()
+	return o.used
+}
+
 // Add attaches a new destination to the Output. Any data subsequently written
 // to the output will be written to the new destination in addition to all the others.
 // This method is thread-safe.
@@ -82,6 +90,7 @@ func (o *Output) AddString(dst *string) error {
 func (o *Output) Write(p []byte) (n int, err error) {
 	o.Mutex.Lock()
 	defer o.Mutex.Unlock()
+	o.used = true
 	var firstErr error
 	for _, dst := range o.dests {
 		_, err := dst.Write(p)

+ 3 - 6
integration/server_test.go

@@ -2,8 +2,6 @@ package docker
 
 import (
 	"github.com/dotcloud/docker"
-	"github.com/dotcloud/docker/utils"
-	"io/ioutil"
 	"strings"
 	"testing"
 )
@@ -365,20 +363,19 @@ func TestImageInsert(t *testing.T) {
 	eng := NewTestEngine(t)
 	defer mkRuntimeFromEngine(eng, t).Nuke()
 	srv := mkServerFromEngine(eng, t)
-	sf := utils.NewStreamFormatter(true)
 
 	// bad image name fails
-	if err := srv.ImageInsert("foo", "https://www.docker.io/static/img/docker-top-logo.png", "/foo", ioutil.Discard, sf); err == nil {
+	if err := srv.Eng.Job("insert", "foo", "https://www.docker.io/static/img/docker-top-logo.png", "/foo").Run(); err == nil {
 		t.Fatal("expected an error and got none")
 	}
 
 	// bad url fails
-	if err := srv.ImageInsert(unitTestImageID, "http://bad_host_name_that_will_totally_fail.com/", "/foo", ioutil.Discard, sf); err == nil {
+	if err := srv.Eng.Job("insert", unitTestImageID, "http://bad_host_name_that_will_totally_fail.com/", "/foo").Run(); err == nil {
 		t.Fatal("expected an error and got none")
 	}
 
 	// success returns nil
-	if err := srv.ImageInsert(unitTestImageID, "https://www.docker.io/static/img/docker-top-logo.png", "/foo", ioutil.Discard, sf); err != nil {
+	if err := srv.Eng.Job("insert", unitTestImageID, "https://www.docker.io/static/img/docker-top-logo.png", "/foo").Run(); err != nil {
 		t.Fatalf("expected no error, but got %v", err)
 	}
 }

+ 33 - 10
server.go

@@ -143,6 +143,10 @@ func jobInitApi(job *engine.Job) engine.Status {
 		job.Error(err)
 		return engine.StatusErr
 	}
+	if err := job.Eng.Register("insert", srv.ImageInsert); err != nil {
+		job.Error(err)
+		return engine.StatusErr
+	}
 	return engine.StatusOK
 }
 
@@ -511,39 +515,58 @@ func (srv *Server) ImagesSearch(term string) ([]registry.SearchResult, error) {
 	return results.Results, nil
 }
 
-func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils.StreamFormatter) error {
-	out = utils.NewWriteFlusher(out)
+func (srv *Server) ImageInsert(job *engine.Job) engine.Status {
+	if len(job.Args) != 3 {
+		job.Errorf("Usage: %s IMAGE URL PATH\n", job.Name)
+		return engine.StatusErr
+	}
+
+	var (
+		name = job.Args[0]
+		url  = job.Args[1]
+		path = job.Args[2]
+	)
+
+	sf := utils.NewStreamFormatter(job.GetenvBool("json"))
+
+	out := utils.NewWriteFlusher(job.Stdout)
 	img, err := srv.runtime.repositories.LookupImage(name)
 	if err != nil {
-		return err
+		job.Error(err)
+		return engine.StatusErr
 	}
 
 	file, err := utils.Download(url)
 	if err != nil {
-		return err
+		job.Error(err)
+		return engine.StatusErr
 	}
 	defer file.Body.Close()
 
 	config, _, _, err := ParseRun([]string{img.ID, "echo", "insert", url, path}, srv.runtime.capabilities)
 	if err != nil {
-		return err
+		job.Error(err)
+		return engine.StatusErr
 	}
 
 	c, _, err := srv.runtime.Create(config, "")
 	if err != nil {
-		return err
+		job.Error(err)
+		return engine.StatusErr
 	}
 
 	if err := c.Inject(utils.ProgressReader(file.Body, int(file.ContentLength), out, sf, false, "", "Downloading"), path); err != nil {
-		return err
+		job.Error(err)
+		return engine.StatusErr
 	}
 	// FIXME: Handle custom repo, tag comment, author
 	img, err = srv.runtime.Commit(c, "", "", img.Comment, img.Author, nil)
 	if err != nil {
-		return err
+		out.Write(sf.FormatError(err))
+		return engine.StatusErr
 	}
-	out.Write(sf.FormatStatus(img.ID, ""))
-	return nil
+	out.Write(sf.FormatStatus("", img.ID))
+	return engine.StatusOK
 }
 
 func (srv *Server) ImagesViz(job *engine.Job) engine.Status {