Merge pull request #3559 from vieux/insert_job

move insert to a job
This commit is contained in:
Victor Vieux 2014-01-15 15:18:02 -08:00
Родитель 52ec95f363 a33bc3018b
Коммит 44b8d8addf
4 изменённых файлов: 54 добавлений и 27 удалений

20
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

Просмотреть файл

@ -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)

Просмотреть файл

@ -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)
}
}

Просмотреть файл

@ -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 {