move build to a job

Docker-DCO-1.1-Signed-off-by: Victor Vieux <victor.vieux@docker.com> (github: vieux)
This commit is contained in:
Victor Vieux 2014-01-23 12:19:52 -08:00
parent 7687b3cec1
commit 415379e45d
2 changed files with 103 additions and 82 deletions

98
api.go
View File

@ -8,7 +8,6 @@ import (
"encoding/json" "encoding/json"
"expvar" "expvar"
"fmt" "fmt"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/auth" "github.com/dotcloud/docker/auth"
"github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/pkg/systemd" "github.com/dotcloud/docker/pkg/systemd"
@ -22,7 +21,6 @@ import (
"net/http" "net/http"
"net/http/pprof" "net/http/pprof"
"os" "os"
"os/exec"
"regexp" "regexp"
"strconv" "strconv"
"strings" "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.") return fmt.Errorf("Multipart upload for build is no longer supported. Please upgrade your docker client.")
} }
var ( 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") authEncoded = r.Header.Get("X-Registry-Auth")
authConfig = &auth.AuthConfig{} authConfig = &auth.AuthConfig{}
configFileEncoded = r.Header.Get("X-Registry-Config") configFileEncoded = r.Header.Get("X-Registry-Config")
configFile = &auth.ConfigFile{} 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. // 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 // 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 { if version >= 1.8 {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
job.SetenvBool("json", true)
} }
sf := utils.NewStreamFormatter(version >= 1.8)
b := NewBuildFile(srv, job.Stdout.Add(utils.NewWriteFlusher(w))
&StdoutFormater{ job.Stdin.Add(r.Body)
Writer: utils.NewWriteFlusher(w), job.Setenv("remote", r.FormValue("remote"))
StreamFormatter: sf, job.Setenv("t", r.FormValue("t"))
}, job.Setenv("q", r.FormValue("q"))
&StderrFormater{ job.Setenv("nocache", r.FormValue("nocache"))
Writer: utils.NewWriteFlusher(w), job.Setenv("rm", r.FormValue("rm"))
StreamFormatter: sf,
}, if err := job.Run(); err != nil {
!suppressOutput, !noCache, rm, utils.NewWriteFlusher(w), sf, authConfig, configFile) if !job.Stdout.Used() {
id, err := b.Build(context) return err
if err != nil {
if sf.Used() {
w.Write(sf.FormatError(err))
return nil
} }
return fmt.Errorf("Error build: %s", err) sf := utils.NewStreamFormatter(version >= 1.8)
} w.Write(sf.FormatError(err))
if repoName != "" {
srv.runtime.repositories.Set(repoName, tag, id, false)
} }
return nil return nil
} }

View File

@ -96,6 +96,7 @@ func jobInitApi(job *engine.Job) engine.Status {
"changes": srv.ContainerChanges, "changes": srv.ContainerChanges,
"top": srv.ContainerTop, "top": srv.ContainerTop,
"load": srv.ImageLoad, "load": srv.ImageLoad,
"build": srv.Build,
} { } {
if err := job.Eng.Register(name, handler); err != nil { if err := job.Eng.Register(name, handler); err != nil {
job.Error(err) job.Error(err)
@ -391,6 +392,92 @@ func (srv *Server) exportImage(image *Image, tempdir string) error {
return nil 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. // 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. // The input stream is an uncompressed tar ball containing images and metadata.
func (srv *Server) ImageLoad(job *engine.Job) engine.Status { func (srv *Server) ImageLoad(job *engine.Job) engine.Status {