Browse code

move pull and import to a job

Docker-DCO-1.1-Signed-off-by: Victor Vieux <victor.vieux@docker.com> (github: vieux)

Victor Vieux authored on 2014/01/23 06:35:35
Showing 8 changed files
... ...
@@ -413,11 +413,11 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht
413 413
 		return err
414 414
 	}
415 415
 
416
-	src := r.Form.Get("fromSrc")
417
-	image := r.Form.Get("fromImage")
418
-	tag := r.Form.Get("tag")
419
-	repo := r.Form.Get("repo")
420
-
416
+	var (
417
+		image = r.Form.Get("fromImage")
418
+		tag   = r.Form.Get("tag")
419
+		job   *engine.Job
420
+	)
421 421
 	authEncoded := r.Header.Get("X-Registry-Auth")
422 422
 	authConfig := &auth.AuthConfig{}
423 423
 	if authEncoded != "" {
... ...
@@ -431,7 +431,6 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht
431 431
 	if version > 1.0 {
432 432
 		w.Header().Set("Content-Type", "application/json")
433 433
 	}
434
-	sf := utils.NewStreamFormatter(version > 1.0)
435 434
 	if image != "" { //pull
436 435
 		metaHeaders := map[string][]string{}
437 436
 		for k, v := range r.Header {
... ...
@@ -439,22 +438,25 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht
439 439
 				metaHeaders[k] = v
440 440
 			}
441 441
 		}
442
-		if err := srv.ImagePull(image, tag, w, sf, authConfig, metaHeaders, version > 1.3); err != nil {
443
-			if sf.Used() {
444
-				w.Write(sf.FormatError(err))
445
-				return nil
446
-			}
447
-			return err
448
-		}
442
+		job = srv.Eng.Job("pull", r.Form.Get("fromImage"), tag)
443
+		job.SetenvBool("parallel", version > 1.3)
444
+		job.SetenvJson("metaHeaders", metaHeaders)
445
+		job.SetenvJson("authConfig", authConfig)
449 446
 	} else { //import
450
-		if err := srv.ImageImport(src, repo, tag, r.Body, w, sf); err != nil {
451
-			if sf.Used() {
452
-				w.Write(sf.FormatError(err))
453
-				return nil
454
-			}
447
+		job = srv.Eng.Job("import", r.Form.Get("fromSrc"), r.Form.Get("repo"), tag)
448
+		job.Stdin.Add(r.Body)
449
+	}
450
+
451
+	job.SetenvBool("json", version > 1.0)
452
+	job.Stdout.Add(w)
453
+	if err := job.Run(); err != nil {
454
+		if !job.Stdout.Used() {
455 455
 			return err
456 456
 		}
457
+		sf := utils.NewStreamFormatter(version > 1.0)
458
+		w.Write(sf.FormatError(err))
457 459
 	}
460
+
458 461
 	return nil
459 462
 }
460 463
 
... ...
@@ -84,7 +84,12 @@ func (b *buildFile) CmdFrom(name string) error {
84 84
 				resolvedAuth := b.configFile.ResolveAuthConfig(endpoint)
85 85
 				pullRegistryAuth = &resolvedAuth
86 86
 			}
87
-			if err := b.srv.ImagePull(remote, tag, b.outOld, b.sf, pullRegistryAuth, nil, true); err != nil {
87
+			job := b.srv.Eng.Job("pull", remote, tag)
88
+			job.SetenvBool("json", b.sf.Json())
89
+			job.SetenvBool("parallel", true)
90
+			job.SetenvJson("authConfig", pullRegistryAuth)
91
+			job.Stdout.Add(b.outOld)
92
+			if err := job.Run(); err != nil {
88 93
 				return err
89 94
 			}
90 95
 			image, err = b.runtime.repositories.LookupImage(name)
... ...
@@ -137,6 +137,9 @@ func (eng *Engine) Job(name string, args ...string) *Job {
137 137
 }
138 138
 
139 139
 func (eng *Engine) Logf(format string, args ...interface{}) (n int, err error) {
140
-	prefixedFormat := fmt.Sprintf("[%s] %s\n", eng, strings.TrimRight(format, "\n"))
141
-	return fmt.Fprintf(eng.Stderr, prefixedFormat, args...)
140
+	if os.Getenv("TEST") == "" {
141
+		prefixedFormat := fmt.Sprintf("[%s] %s\n", eng, strings.TrimRight(format, "\n"))
142
+		return fmt.Fprintf(eng.Stderr, prefixedFormat, args...)
143
+	}
144
+	return 0, nil
142 145
 }
... ...
@@ -3,6 +3,7 @@ package engine
3 3
 import (
4 4
 	"fmt"
5 5
 	"io"
6
+	"os"
6 7
 	"strings"
7 8
 	"time"
8 9
 )
... ...
@@ -176,8 +177,11 @@ func (job *Job) Environ() map[string]string {
176 176
 }
177 177
 
178 178
 func (job *Job) Logf(format string, args ...interface{}) (n int, err error) {
179
-	prefixedFormat := fmt.Sprintf("[%s] %s\n", job, strings.TrimRight(format, "\n"))
180
-	return fmt.Fprintf(job.Stderr, prefixedFormat, args...)
179
+	if os.Getenv("TEST") == "" {
180
+		prefixedFormat := fmt.Sprintf("[%s] %s\n", job, strings.TrimRight(format, "\n"))
181
+		return fmt.Fprintf(job.Stderr, prefixedFormat, args...)
182
+	}
183
+	return 0, nil
181 184
 }
182 185
 
183 186
 func (job *Job) Printf(format string, args ...interface{}) (n int, err error) {
... ...
@@ -137,7 +137,9 @@ func setupBaseImage() {
137 137
 	// If the unit test is not found, try to download it.
138 138
 	if img, err := srv.ImageInspect(unitTestImageName); err != nil || img.ID != unitTestImageID {
139 139
 		// Retrieve the Image
140
-		if err := srv.ImagePull(unitTestImageName, "", os.Stdout, utils.NewStreamFormatter(false), nil, nil, true); err != nil {
140
+		job = eng.Job("pull", unitTestImageName)
141
+		job.Stdout.Add(utils.NopWriteCloser(os.Stdout))
142
+		if err := job.Run(); err != nil {
141 143
 			log.Fatalf("Unable to pull the test image: %s", err)
142 144
 		}
143 145
 	}
... ...
@@ -2,8 +2,6 @@ package docker
2 2
 
3 3
 import (
4 4
 	"github.com/dotcloud/docker"
5
-	"github.com/dotcloud/docker/utils"
6
-	"io/ioutil"
7 5
 	"testing"
8 6
 	"time"
9 7
 )
... ...
@@ -53,5 +51,8 @@ func generateImage(name string, srv *docker.Server) error {
53 53
 	if err != nil {
54 54
 		return err
55 55
 	}
56
-	return srv.ImageImport("-", "repo", name, archive, ioutil.Discard, utils.NewStreamFormatter(true))
56
+	job := srv.Eng.Job("import", "-", "repo", name)
57
+	job.Stdin.Add(archive)
58
+	job.SetenvBool("json", true)
59
+	return job.Run()
57 60
 }
... ...
@@ -97,6 +97,8 @@ func jobInitApi(job *engine.Job) engine.Status {
97 97
 		"top":              srv.ContainerTop,
98 98
 		"load":             srv.ImageLoad,
99 99
 		"build":            srv.Build,
100
+		"pull":             srv.ImagePull,
101
+		"import":           srv.ImageImport,
100 102
 	} {
101 103
 		if err := job.Eng.Register(name, handler); err != nil {
102 104
 			job.Error(err)
... ...
@@ -1312,8 +1314,25 @@ func (srv *Server) poolRemove(kind, key string) error {
1312 1312
 	return nil
1313 1313
 }
1314 1314
 
1315
-func (srv *Server) ImagePull(localName string, tag string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig, metaHeaders map[string][]string, parallel bool) error {
1316
-	out = utils.NewWriteFlusher(out)
1315
+func (srv *Server) ImagePull(job *engine.Job) engine.Status {
1316
+	if n := len(job.Args); n != 1 && n != 2 {
1317
+		job.Errorf("Usage: %s IMAGE [TAG]", job.Name)
1318
+		return engine.StatusErr
1319
+	}
1320
+	var (
1321
+		localName   = job.Args[0]
1322
+		tag         string
1323
+		sf          = utils.NewStreamFormatter(job.GetenvBool("json"))
1324
+		out         = utils.NewWriteFlusher(job.Stdout)
1325
+		authConfig  *auth.AuthConfig
1326
+		metaHeaders map[string][]string
1327
+	)
1328
+	if len(job.Args) > 1 {
1329
+		tag = job.Args[1]
1330
+	}
1331
+
1332
+	job.GetenvJson("authConfig", authConfig)
1333
+	job.GetenvJson("metaHeaders", metaHeaders)
1317 1334
 
1318 1335
 	c, err := srv.poolAdd("pull", localName+":"+tag)
1319 1336
 	if err != nil {
... ...
@@ -1321,21 +1340,24 @@ func (srv *Server) ImagePull(localName string, tag string, out io.Writer, sf *ut
1321 1321
 			// Another pull of the same repository is already taking place; just wait for it to finish
1322 1322
 			out.Write(sf.FormatStatus("", "Repository %s already being pulled by another client. Waiting.", localName))
1323 1323
 			<-c
1324
-			return nil
1324
+			return engine.StatusOK
1325 1325
 		}
1326
-		return err
1326
+		job.Error(err)
1327
+		return engine.StatusErr
1327 1328
 	}
1328 1329
 	defer srv.poolRemove("pull", localName+":"+tag)
1329 1330
 
1330 1331
 	// Resolve the Repository name from fqn to endpoint + name
1331 1332
 	endpoint, remoteName, err := registry.ResolveRepositoryName(localName)
1332 1333
 	if err != nil {
1333
-		return err
1334
+		job.Error(err)
1335
+		return engine.StatusErr
1334 1336
 	}
1335 1337
 
1336 1338
 	r, err := registry.NewRegistry(authConfig, srv.HTTPRequestFactory(metaHeaders), endpoint)
1337 1339
 	if err != nil {
1338
-		return err
1340
+		job.Error(err)
1341
+		return engine.StatusErr
1339 1342
 	}
1340 1343
 
1341 1344
 	if endpoint == auth.IndexServerAddress() {
... ...
@@ -1343,11 +1365,12 @@ func (srv *Server) ImagePull(localName string, tag string, out io.Writer, sf *ut
1343 1343
 		localName = remoteName
1344 1344
 	}
1345 1345
 
1346
-	if err = srv.pullRepository(r, out, localName, remoteName, tag, sf, parallel); err != nil {
1347
-		return err
1346
+	if err = srv.pullRepository(r, out, localName, remoteName, tag, sf, job.GetenvBool("parallel")); err != nil {
1347
+		job.Error(err)
1348
+		return engine.StatusErr
1348 1349
 	}
1349 1350
 
1350
-	return nil
1351
+	return engine.StatusOK
1351 1352
 }
1352 1353
 
1353 1354
 // Retrieve the all the images to be uploaded in the correct order
... ...
@@ -1551,16 +1574,31 @@ func (srv *Server) ImagePush(localName string, out io.Writer, sf *utils.StreamFo
1551 1551
 	return nil
1552 1552
 }
1553 1553
 
1554
-func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Writer, sf *utils.StreamFormatter) error {
1555
-	var archive io.Reader
1556
-	var resp *http.Response
1554
+func (srv *Server) ImageImport(job *engine.Job) engine.Status {
1555
+	if n := len(job.Args); n != 2 && n != 3 {
1556
+		job.Errorf("Usage: %s SRC REPO [TAG]", job.Name)
1557
+		return engine.StatusErr
1558
+	}
1559
+	var (
1560
+		src     = job.Args[0]
1561
+		repo    = job.Args[1]
1562
+		tag     string
1563
+		sf      = utils.NewStreamFormatter(job.GetenvBool("json"))
1564
+		out     = utils.NewWriteFlusher(job.Stdout)
1565
+		archive io.Reader
1566
+		resp    *http.Response
1567
+	)
1568
+	if len(job.Args) > 2 {
1569
+		tag = job.Args[2]
1570
+	}
1557 1571
 
1558 1572
 	if src == "-" {
1559
-		archive = in
1573
+		archive = job.Stdin
1560 1574
 	} else {
1561 1575
 		u, err := url.Parse(src)
1562 1576
 		if err != nil {
1563
-			return err
1577
+			job.Error(err)
1578
+			return engine.StatusErr
1564 1579
 		}
1565 1580
 		if u.Scheme == "" {
1566 1581
 			u.Scheme = "http"
... ...
@@ -1572,22 +1610,25 @@ func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Write
1572 1572
 		// If curl is not available, fallback to http.Get()
1573 1573
 		resp, err = utils.Download(u.String())
1574 1574
 		if err != nil {
1575
-			return err
1575
+			job.Error(err)
1576
+			return engine.StatusErr
1576 1577
 		}
1577 1578
 		archive = utils.ProgressReader(resp.Body, int(resp.ContentLength), out, sf, true, "", "Importing")
1578 1579
 	}
1579 1580
 	img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "", nil)
1580 1581
 	if err != nil {
1581
-		return err
1582
+		job.Error(err)
1583
+		return engine.StatusErr
1582 1584
 	}
1583 1585
 	// Optionally register the image at REPO/TAG
1584 1586
 	if repo != "" {
1585 1587
 		if err := srv.runtime.repositories.Set(repo, tag, img.ID, true); err != nil {
1586
-			return err
1588
+			job.Error(err)
1589
+			return engine.StatusErr
1587 1590
 		}
1588 1591
 	}
1589 1592
 	out.Write(sf.FormatStatus("", img.ID))
1590
-	return nil
1593
+	return engine.StatusOK
1591 1594
 }
1592 1595
 
1593 1596
 func (srv *Server) ContainerCreate(job *engine.Job) engine.Status {
... ...
@@ -82,3 +82,7 @@ func (sf *StreamFormatter) FormatProgress(id, action string, progress *JSONProgr
82 82
 func (sf *StreamFormatter) Used() bool {
83 83
 	return sf.used
84 84
 }
85
+
86
+func (sf *StreamFormatter) Json() bool {
87
+	return sf.json
88
+}