Parcourir la source

Remove engine.Job references from builder.CmdBuild

Signed-off-by: David Calavera <david.calavera@gmail.com>
David Calavera il y a 10 ans
Parent
commit
9a2c009751
2 fichiers modifiés avec 131 ajouts et 83 suppressions
  1. 42 28
      api/server/server.go
  2. 89 55
      builder/job.go

+ 42 - 28
api/server/server.go

@@ -23,6 +23,7 @@ import (
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/autogen/dockerversion"
+	"github.com/docker/docker/builder"
 	"github.com/docker/docker/daemon"
 	"github.com/docker/docker/daemon/networkdriver/bridge"
 	"github.com/docker/docker/engine"
@@ -236,12 +237,12 @@ func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
 	return json.NewEncoder(w).Encode(v)
 }
 
-func streamJSON(job *engine.Job, w http.ResponseWriter, flush bool) {
+func streamJSON(out *engine.Output, w http.ResponseWriter, flush bool) {
 	w.Header().Set("Content-Type", "application/json")
 	if flush {
-		job.Stdout.Add(utils.NewWriteFlusher(w))
+		out.Add(utils.NewWriteFlusher(w))
 	} else {
-		job.Stdout.Add(w)
+		out.Add(w)
 	}
 }
 
@@ -857,7 +858,7 @@ func (s *Server) postImagesPush(eng *engine.Engine, version version.Version, w h
 	job.Setenv("tag", r.Form.Get("tag"))
 	if version.GreaterThan("1.0") {
 		job.SetenvBool("json", true)
-		streamJSON(job, w, true)
+		streamJSON(job.Stdout, w, true)
 	} else {
 		job.Stdout.Add(utils.NewWriteFlusher(w))
 	}
@@ -1207,7 +1208,7 @@ func (s *Server) getContainersByName(eng *engine.Engine, version version.Version
 	if version.LessThan("1.12") {
 		job.SetenvBool("raw", true)
 	}
-	streamJSON(job, w, false)
+	streamJSON(job.Stdout, w, false)
 	return job.Run()
 }
 
@@ -1232,7 +1233,7 @@ func (s *Server) getImagesByName(eng *engine.Engine, version version.Version, w
 	if version.LessThan("1.12") {
 		job.SetenvBool("raw", true)
 	}
-	streamJSON(job, w, false)
+	streamJSON(job.Stdout, w, false)
 	return job.Run()
 }
 
@@ -1245,9 +1246,11 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R
 		authConfig        = &registry.AuthConfig{}
 		configFileEncoded = r.Header.Get("X-Registry-Config")
 		configFile        = &registry.ConfigFile{}
-		job               = eng.Job("build")
+		job               = builder.NewBuildConfig(eng.Logging, eng.Stderr)
 	)
 
+	b := &builder.BuilderJob{eng, getDaemon(eng)}
+
 	// 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
 	// ConfigFile is present, any value provided as an AuthConfig directly will
@@ -1271,36 +1274,38 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R
 	}
 
 	if version.GreaterThanOrEqualTo("1.8") {
-		job.SetenvBool("json", true)
-		streamJSON(job, w, true)
+		job.JSONFormat = true
+		streamJSON(job.Stdout, w, true)
 	} else {
 		job.Stdout.Add(utils.NewWriteFlusher(w))
 	}
 
 	if toBool(r.FormValue("forcerm")) && version.GreaterThanOrEqualTo("1.12") {
-		job.Setenv("rm", "1")
+		job.Remove = true
 	} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
-		job.Setenv("rm", "1")
+		job.Remove = true
 	} else {
-		job.Setenv("rm", r.FormValue("rm"))
+		job.Remove = toBool(r.FormValue("rm"))
 	}
 	if toBool(r.FormValue("pull")) && version.GreaterThanOrEqualTo("1.16") {
-		job.Setenv("pull", "1")
+		job.Pull = true
 	}
 	job.Stdin.Add(r.Body)
-	job.Setenv("remote", r.FormValue("remote"))
-	job.Setenv("dockerfile", r.FormValue("dockerfile"))
-	job.Setenv("t", r.FormValue("t"))
-	job.Setenv("q", r.FormValue("q"))
-	job.Setenv("nocache", r.FormValue("nocache"))
-	job.Setenv("forcerm", r.FormValue("forcerm"))
-	job.SetenvJson("authConfig", authConfig)
-	job.SetenvJson("configFile", configFile)
-	job.Setenv("memswap", r.FormValue("memswap"))
-	job.Setenv("memory", r.FormValue("memory"))
-	job.Setenv("cpusetcpus", r.FormValue("cpusetcpus"))
-	job.Setenv("cpusetmems", r.FormValue("cpusetmems"))
-	job.Setenv("cpushares", r.FormValue("cpushares"))
+
+	// FIXME(calavera): !!!!! Remote might not be used. Solve the mistery before merging
+	//job.Setenv("remote", r.FormValue("remote"))
+	job.DockerfileName = r.FormValue("dockerfile")
+	job.RepoName = r.FormValue("t")
+	job.SuppressOutput = toBool(r.FormValue("q"))
+	job.NoCache = toBool(r.FormValue("nocache"))
+	job.ForceRemove = toBool(r.FormValue("forcerm"))
+	job.AuthConfig = authConfig
+	job.ConfigFile = configFile
+	job.MemorySwap = toInt64(r.FormValue("memswap"))
+	job.Memory = toInt64(r.FormValue("memory"))
+	job.CpuShares = toInt64(r.FormValue("cpushares"))
+	job.CpuSetCpus = r.FormValue("cpusetcpus")
+	job.CpuSetMems = r.FormValue("cpusetmems")
 
 	// Job cancellation. Note: not all job types support this.
 	if closeNotifier, ok := w.(http.CloseNotifier); ok {
@@ -1310,13 +1315,13 @@ func (s *Server) postBuild(eng *engine.Engine, version version.Version, w http.R
 			select {
 			case <-finished:
 			case <-closeNotifier.CloseNotify():
-				logrus.Infof("Client disconnected, cancelling job: %s", job.Name)
+				logrus.Infof("Client disconnected, cancelling job: build")
 				job.Cancel()
 			}
 		}()
 	}
 
-	if err := job.Run(); err != nil {
+	if err := b.CmdBuild(job); err != nil {
 		if !job.Stdout.Used() {
 			return err
 		}
@@ -1676,3 +1681,12 @@ func toBool(s string) bool {
 	s = strings.ToLower(strings.TrimSpace(s))
 	return !(s == "" || s == "0" || s == "no" || s == "false" || s == "none")
 }
+
+// FIXME(calavera): This is a copy of the Env.GetInt64
+func toInt64(s string) int64 {
+	val, err := strconv.ParseInt(s, 10, 64)
+	if err != nil {
+		return 0
+	}
+	return val
+}

+ 89 - 55
builder/job.go

@@ -9,6 +9,7 @@ import (
 	"os"
 	"os/exec"
 	"strings"
+	"sync"
 
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/builder/parser"
@@ -17,6 +18,7 @@ import (
 	"github.com/docker/docker/graph"
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/httputils"
+	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/streamformatter"
 	"github.com/docker/docker/pkg/urlutil"
@@ -41,41 +43,73 @@ type BuilderJob struct {
 	Daemon *daemon.Daemon
 }
 
+type Config struct {
+	DockerfileName string
+	RemoteURL      string
+	RepoName       string
+	SuppressOutput bool
+	NoCache        bool
+	Remove         bool
+	ForceRemove    bool
+	Pull           bool
+	JSONFormat     bool
+	Memory         int64
+	MemorySwap     int64
+	CpuShares      int64
+	CpuSetCpus     string
+	CpuSetMems     string
+	AuthConfig     *registry.AuthConfig
+	ConfigFile     *registry.ConfigFile
+
+	Stdout *engine.Output
+	Stderr *engine.Output
+	Stdin  *engine.Input
+	// When closed, the job has been cancelled.
+	// Note: not all jobs implement cancellation.
+	// See Job.Cancel() and Job.WaitCancelled()
+	cancelled  chan struct{}
+	cancelOnce sync.Once
+}
+
+// When called, causes the Job.WaitCancelled channel to unblock.
+func (b *Config) Cancel() {
+	b.cancelOnce.Do(func() {
+		close(b.cancelled)
+	})
+}
+
+// Returns a channel which is closed ("never blocks") when the job is cancelled.
+func (b *Config) WaitCancelled() <-chan struct{} {
+	return b.cancelled
+}
+
+func NewBuildConfig(logging bool, err io.Writer) *Config {
+	c := &Config{
+		Stdout:    engine.NewOutput(),
+		Stderr:    engine.NewOutput(),
+		Stdin:     engine.NewInput(),
+		cancelled: make(chan struct{}),
+	}
+	if logging {
+		c.Stderr.Add(ioutils.NopWriteCloser(err))
+	}
+	return c
+}
+
 func (b *BuilderJob) Install() {
-	b.Engine.Register("build", b.CmdBuild)
 	b.Engine.Register("build_config", b.CmdBuildConfig)
 }
 
-func (b *BuilderJob) CmdBuild(job *engine.Job) error {
-	if len(job.Args) != 0 {
-		return fmt.Errorf("Usage: %s\n", job.Name)
-	}
+func (b *BuilderJob) CmdBuild(buildConfig *Config) error {
 	var (
-		dockerfileName = job.Getenv("dockerfile")
-		remoteURL      = job.Getenv("remote")
-		repoName       = job.Getenv("t")
-		suppressOutput = job.GetenvBool("q")
-		noCache        = job.GetenvBool("nocache")
-		rm             = job.GetenvBool("rm")
-		forceRm        = job.GetenvBool("forcerm")
-		pull           = job.GetenvBool("pull")
-		memory         = job.GetenvInt64("memory")
-		memorySwap     = job.GetenvInt64("memswap")
-		cpuShares      = job.GetenvInt64("cpushares")
-		cpuSetCpus     = job.Getenv("cpusetcpus")
-		cpuSetMems     = job.Getenv("cpusetmems")
-		authConfig     = &registry.AuthConfig{}
-		configFile     = &registry.ConfigFile{}
-		tag            string
-		context        io.ReadCloser
+		repoName string
+		tag      string
+		context  io.ReadCloser
 	)
 
-	job.GetenvJson("authConfig", authConfig)
-	job.GetenvJson("configFile", configFile)
-
-	repoName, tag = parsers.ParseRepositoryTag(repoName)
+	repoName, tag = parsers.ParseRepositoryTag(buildConfig.RepoName)
 	if repoName != "" {
-		if err := registry.ValidateRepositoryName(repoName); err != nil {
+		if err := registry.ValidateRepositoryName(buildConfig.RepoName); err != nil {
 			return err
 		}
 		if len(tag) > 0 {
@@ -85,11 +119,11 @@ func (b *BuilderJob) CmdBuild(job *engine.Job) error {
 		}
 	}
 
-	if remoteURL == "" {
-		context = ioutil.NopCloser(job.Stdin)
-	} else if urlutil.IsGitURL(remoteURL) {
-		if !urlutil.IsGitTransport(remoteURL) {
-			remoteURL = "https://" + remoteURL
+	if buildConfig.RemoteURL == "" {
+		context = ioutil.NopCloser(buildConfig.Stdin)
+	} else if urlutil.IsGitURL(buildConfig.RemoteURL) {
+		if !urlutil.IsGitTransport(buildConfig.RemoteURL) {
+			buildConfig.RemoteURL = "https://" + buildConfig.RemoteURL
 		}
 		root, err := ioutil.TempDir("", "docker-build-git")
 		if err != nil {
@@ -97,7 +131,7 @@ func (b *BuilderJob) CmdBuild(job *engine.Job) error {
 		}
 		defer os.RemoveAll(root)
 
-		if output, err := exec.Command("git", "clone", "--recursive", remoteURL, root).CombinedOutput(); err != nil {
+		if output, err := exec.Command("git", "clone", "--recursive", buildConfig.RemoteURL, root).CombinedOutput(); err != nil {
 			return fmt.Errorf("Error trying to use git: %s (%s)", err, output)
 		}
 
@@ -106,8 +140,8 @@ func (b *BuilderJob) CmdBuild(job *engine.Job) error {
 			return err
 		}
 		context = c
-	} else if urlutil.IsURL(remoteURL) {
-		f, err := httputils.Download(remoteURL)
+	} else if urlutil.IsURL(buildConfig.RemoteURL) {
+		f, err := httputils.Download(buildConfig.RemoteURL)
 		if err != nil {
 			return err
 		}
@@ -119,9 +153,9 @@ func (b *BuilderJob) CmdBuild(job *engine.Job) error {
 
 		// When we're downloading just a Dockerfile put it in
 		// the default name - don't allow the client to move/specify it
-		dockerfileName = api.DefaultDockerfileName
+		buildConfig.DockerfileName = api.DefaultDockerfileName
 
-		c, err := archive.Generate(dockerfileName, string(dockerFile))
+		c, err := archive.Generate(buildConfig.DockerfileName, string(dockerFile))
 		if err != nil {
 			return err
 		}
@@ -129,35 +163,35 @@ func (b *BuilderJob) CmdBuild(job *engine.Job) error {
 	}
 	defer context.Close()
 
-	sf := streamformatter.NewStreamFormatter(job.GetenvBool("json"))
+	sf := streamformatter.NewStreamFormatter(buildConfig.JSONFormat)
 
 	builder := &Builder{
 		Daemon: b.Daemon,
 		Engine: b.Engine,
 		OutStream: &streamformatter.StdoutFormater{
-			Writer:          job.Stdout,
+			Writer:          buildConfig.Stdout,
 			StreamFormatter: sf,
 		},
 		ErrStream: &streamformatter.StderrFormater{
-			Writer:          job.Stdout,
+			Writer:          buildConfig.Stdout,
 			StreamFormatter: sf,
 		},
-		Verbose:         !suppressOutput,
-		UtilizeCache:    !noCache,
-		Remove:          rm,
-		ForceRemove:     forceRm,
-		Pull:            pull,
-		OutOld:          job.Stdout,
+		Verbose:         !buildConfig.SuppressOutput,
+		UtilizeCache:    !buildConfig.NoCache,
+		Remove:          buildConfig.Remove,
+		ForceRemove:     buildConfig.ForceRemove,
+		Pull:            buildConfig.Pull,
+		OutOld:          buildConfig.Stdout,
 		StreamFormatter: sf,
-		AuthConfig:      authConfig,
-		ConfigFile:      configFile,
-		dockerfileName:  dockerfileName,
-		cpuShares:       cpuShares,
-		cpuSetCpus:      cpuSetCpus,
-		cpuSetMems:      cpuSetMems,
-		memory:          memory,
-		memorySwap:      memorySwap,
-		cancelled:       job.WaitCancelled(),
+		AuthConfig:      buildConfig.AuthConfig,
+		ConfigFile:      buildConfig.ConfigFile,
+		dockerfileName:  buildConfig.DockerfileName,
+		cpuShares:       buildConfig.CpuShares,
+		cpuSetCpus:      buildConfig.CpuSetCpus,
+		cpuSetMems:      buildConfig.CpuSetMems,
+		memory:          buildConfig.Memory,
+		memorySwap:      buildConfig.MemorySwap,
+		cancelled:       buildConfig.WaitCancelled(),
 	}
 
 	id, err := builder.Run(context)