Переглянути джерело

move build to a job

Docker-DCO-1.1-Signed-off-by: Victor Vieux <victor.vieux@docker.com> (github: vieux)
Victor Vieux 11 роки тому
батько
коміт
415379e45d
2 змінених файлів з 103 додано та 82 видалено
  1. 16 82
      api.go
  2. 87 0
      server.go

+ 16 - 82
api.go

@@ -8,7 +8,6 @@ import (
 	"encoding/json"
 	"expvar"
 	"fmt"
-	"github.com/dotcloud/docker/archive"
 	"github.com/dotcloud/docker/auth"
 	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/pkg/systemd"
@@ -22,7 +21,6 @@ import (
 	"net/http"
 	"net/http/pprof"
 	"os"
-	"os/exec"
 	"regexp"
 	"strconv"
 	"strings"
@@ -892,18 +890,12 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
 		return fmt.Errorf("Multipart upload for build is no longer supported. Please upgrade your docker client.")
 	}
 	var (
-		remoteURL         = r.FormValue("remote")
-		repoName          = r.FormValue("t")
-		rawSuppressOutput = r.FormValue("q")
-		rawNoCache        = r.FormValue("nocache")
-		rawRm             = r.FormValue("rm")
 		authEncoded       = r.Header.Get("X-Registry-Auth")
 		authConfig        = &auth.AuthConfig{}
 		configFileEncoded = r.Header.Get("X-Registry-Config")
 		configFile        = &auth.ConfigFile{}
-		tag               string
+		job               = srv.Eng.Job("build")
 	)
-	repoName, tag = utils.ParseRepositoryTag(repoName)
 
 	// This block can be removed when API versions prior to 1.9 are deprecated.
 	// Both headers will be parsed and sent along to the daemon, but if a non-empty
@@ -927,83 +919,25 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
 		}
 	}
 
-	var context io.Reader
-
-	if remoteURL == "" {
-		context = r.Body
-	} else if utils.IsGIT(remoteURL) {
-		if !strings.HasPrefix(remoteURL, "git://") {
-			remoteURL = "https://" + remoteURL
-		}
-		root, err := ioutil.TempDir("", "docker-build-git")
-		if err != nil {
-			return err
-		}
-		defer os.RemoveAll(root)
-
-		if output, err := exec.Command("git", "clone", remoteURL, root).CombinedOutput(); err != nil {
-			return fmt.Errorf("Error trying to use git: %s (%s)", err, output)
-		}
-
-		c, err := archive.Tar(root, archive.Uncompressed)
-		if err != nil {
-			return err
-		}
-		context = c
-	} else if utils.IsURL(remoteURL) {
-		f, err := utils.Download(remoteURL)
-		if err != nil {
-			return err
-		}
-		defer f.Body.Close()
-		dockerFile, err := ioutil.ReadAll(f.Body)
-		if err != nil {
-			return err
-		}
-		c, err := MkBuildContext(string(dockerFile), nil)
-		if err != nil {
-			return err
-		}
-		context = c
-	}
-
-	suppressOutput, err := getBoolParam(rawSuppressOutput)
-	if err != nil {
-		return err
-	}
-	noCache, err := getBoolParam(rawNoCache)
-	if err != nil {
-		return err
-	}
-	rm, err := getBoolParam(rawRm)
-	if err != nil {
-		return err
-	}
-
 	if version >= 1.8 {
 		w.Header().Set("Content-Type", "application/json")
+		job.SetenvBool("json", true)
 	}
-	sf := utils.NewStreamFormatter(version >= 1.8)
-	b := NewBuildFile(srv,
-		&StdoutFormater{
-			Writer:          utils.NewWriteFlusher(w),
-			StreamFormatter: sf,
-		},
-		&StderrFormater{
-			Writer:          utils.NewWriteFlusher(w),
-			StreamFormatter: sf,
-		},
-		!suppressOutput, !noCache, rm, utils.NewWriteFlusher(w), sf, authConfig, configFile)
-	id, err := b.Build(context)
-	if err != nil {
-		if sf.Used() {
-			w.Write(sf.FormatError(err))
-			return nil
+
+	job.Stdout.Add(utils.NewWriteFlusher(w))
+	job.Stdin.Add(r.Body)
+	job.Setenv("remote", r.FormValue("remote"))
+	job.Setenv("t", r.FormValue("t"))
+	job.Setenv("q", r.FormValue("q"))
+	job.Setenv("nocache", r.FormValue("nocache"))
+	job.Setenv("rm", r.FormValue("rm"))
+
+	if err := job.Run(); err != nil {
+		if !job.Stdout.Used() {
+			return err
 		}
-		return fmt.Errorf("Error build: %s", err)
-	}
-	if repoName != "" {
-		srv.runtime.repositories.Set(repoName, tag, id, false)
+		sf := utils.NewStreamFormatter(version >= 1.8)
+		w.Write(sf.FormatError(err))
 	}
 	return nil
 }

+ 87 - 0
server.go

@@ -96,6 +96,7 @@ func jobInitApi(job *engine.Job) engine.Status {
 		"changes":          srv.ContainerChanges,
 		"top":              srv.ContainerTop,
 		"load":             srv.ImageLoad,
+		"build":            srv.Build,
 	} {
 		if err := job.Eng.Register(name, handler); err != nil {
 			job.Error(err)
@@ -391,6 +392,92 @@ func (srv *Server) exportImage(image *Image, tempdir string) error {
 	return nil
 }
 
+func (srv *Server) Build(job *engine.Job) engine.Status {
+	if len(job.Args) != 0 {
+		job.Errorf("Usage: %s\n", job.Name)
+		return engine.StatusErr
+	}
+	var (
+		remoteURL      = job.Getenv("remote")
+		repoName       = job.Getenv("t")
+		suppressOutput = job.GetenvBool("q")
+		noCache        = job.GetenvBool("nocache")
+		rm             = job.GetenvBool("rm")
+		authConfig     = &auth.AuthConfig{}
+		configFile     = &auth.ConfigFile{}
+		tag            string
+		context        io.Reader
+	)
+	job.GetenvJson("authConfig", authConfig)
+	job.GetenvJson("configFile", configFile)
+	repoName, tag = utils.ParseRepositoryTag(repoName)
+
+	if remoteURL == "" {
+		context = job.Stdin
+	} else if utils.IsGIT(remoteURL) {
+		if !strings.HasPrefix(remoteURL, "git://") {
+			remoteURL = "https://" + remoteURL
+		}
+		root, err := ioutil.TempDir("", "docker-build-git")
+		if err != nil {
+			job.Error(err)
+			return engine.StatusErr
+		}
+		defer os.RemoveAll(root)
+
+		if output, err := exec.Command("git", "clone", remoteURL, root).CombinedOutput(); err != nil {
+			job.Errorf("Error trying to use git: %s (%s)", err, output)
+			return engine.StatusErr
+		}
+
+		c, err := archive.Tar(root, archive.Uncompressed)
+		if err != nil {
+			job.Error(err)
+			return engine.StatusErr
+		}
+		context = c
+	} else if utils.IsURL(remoteURL) {
+		f, err := utils.Download(remoteURL)
+		if err != nil {
+			job.Error(err)
+			return engine.StatusErr
+		}
+		defer f.Body.Close()
+		dockerFile, err := ioutil.ReadAll(f.Body)
+		if err != nil {
+			job.Error(err)
+			return engine.StatusErr
+		}
+		c, err := MkBuildContext(string(dockerFile), nil)
+		if err != nil {
+			job.Error(err)
+			return engine.StatusErr
+		}
+		context = c
+	}
+
+	sf := utils.NewStreamFormatter(job.GetenvBool("json"))
+	b := NewBuildFile(srv,
+		&StdoutFormater{
+			Writer:          job.Stdout,
+			StreamFormatter: sf,
+		},
+		&StderrFormater{
+			Writer:          job.Stdout,
+			StreamFormatter: sf,
+		},
+		!suppressOutput, !noCache, rm, job.Stdout, sf, authConfig, configFile)
+	id, err := b.Build(context)
+	if err != nil {
+		job.Error(err)
+		return engine.StatusErr
+	}
+	if repoName != "" {
+		srv.runtime.repositories.Set(repoName, tag, id, false)
+	}
+	return engine.StatusOK
+}
+
 // Loads a set of images into the repository. This is the complementary of ImageExport.
 // The input stream is an uncompressed tar ball containing images and metadata.
 func (srv *Server) ImageLoad(job *engine.Job) engine.Status {